packet_forwarder
到 OpenWRT 平台,对接通用的 LoRaWAN ServerAR9531 可以通过 USB 或 SPI 驱动 SX1301,USB方式需要FTDI转 SPI 芯片方式网上教程较多。由于板子限制,这里采用 SPI 方式,由于板子的 SPI 控制器已经用来驱动 flash,控制 SX1301 有两种方式:
为提高调试效率,先修改Makefile的 cmdline
字段波特率,以串口 ttyS0 为例下面命令可以查找包含 ttyS0 对应行,使用 VIM 修改成 115200。
grep ttyS0 ./target/linux/ar71xx/image/Makefile
参考
https://randomcoderdude.wordpress.com/2013/08/15/spi-over-gpio-in-openwrt/
先确认 GPIO 管脚是否可用,是否能拉高拉低
cat /sys/kernel/debug/gpio # 查看 GPIO 调试信息
cd /sys/class/gpio
echo 2 > export # 把 GPIO 管脚 2 导出到用户空间
cd gpio2
echo out > direction # 配置成输出
echo 0 > value # 输入值 0
cat value # 查看值是否改变
echo 1 > value # 输入值 1
cat value
如果CPU用到对应 GPIO 口存在 JTAG 复用的话,芯片初始化 GPIO 时把 JTAG 关掉
//文件:linux-3.3.8/arch/mips/ath79/gpio.c
//函数:ath79_gpio_init
if (soc_is_qca953x())
ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE);
移植编译内核模块
OpenWRT 内核默认就已经有 GPIO 模拟 SPI 的驱动模块(spi-gpio
、spi-bitbang
),另外有spi-dev
设备层通用驱动,用来导出到用户空间,编译内核前把这三个模块打开。spi-dev
模块问题是不大方便调试,建议下载移植 spi-gpio-custom
模块用于动态加载软 SPI 模块,根据对应 GPIO 管脚加载。
# 参数说明
* bus0 These four arguments can be arrays of
* bus1 1-8 unsigned integers as follows:
* bus2
* bus3 <id>,<sck>,<mosi>,<miso>,<mode1>,<maxfreq1>,<cs1>,...
* where:
*
* <id> ID to used as device_id for the corresponding bus (required)
* <sck> GPIO pin ID to be used for bus SCK (required)
* <mosi> GPIO pin ID to be used for bus MOSI (required*)
* <miso> GPIO pin ID to be used for bus MISO (required*)
* <modeX> Mode configuration for slave X in the bus (required)
* (see /include/linux/spi/spi.h)
* <maxfreqX> Maximum clock frequency in Hz for slave X in the bus (required)
* <csX> GPIO pin ID to be used for slave X CS (required**)
insmod spi-gpio-custom bus0=1,14,15,16,0,1000000,4 # 加载模块
ls /dev/ | grep spidev1.0 # 确认 spidev 设备是否出现,存在则加载成功
待完善,主要修订代码 dev-m25p80.c,
+static struct ath79_spi_controller_data ath79_spi_cdata0 =
+{
+ .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
+ .cs_line = 0,
+};
+
+static struct ath79_spi_controller_data ath79_spi_cdata1 =
+{
+ .cs_type = ATH79_SPI_CS_TYPE_GPIO,
+ .cs_line = 2,
+ .is_flash = false
+};
+
+static struct spi_board_info ath79_spi_info_multi[] = {
+ {
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 25000000,
+ .modalias = "m25p80",
+ .controller_data = &ath79_spi_cdata0,
+ },
+ {
+ .bus_num = 0,
+ .chip_select = 1,
+ .max_speed_hz = 25000000,
+ .modalias = "spidev",
+ .controller_data = &ath79_spi_cdata1,
+ }
+};
+
+void __init ath79_register_m25p80_multidev(struct flash_platform_data *pdata)
+{
+ multi_pdata = pdata;
+ add_mtd_concat_notifier();
+ ath79_spi_data.bus_num = 0;
+ ath79_spi_data.num_chipselect = 2;
+ ath79_spi_cdata0.is_flash = false;
+ ath79_spi_info_multi[0].platform_data = pdata;
+ ath79_register_spi(&ath79_spi_data, ath79_spi_info_multi, 2);
+}
编译移植 LoRa 报文转发模块
下载编译 packet_forwarder
、lora_gateway
模块,lora_gateway
编译时生成 .a 库文件,供 packet_forwarder
模块调用运行报文转发程序,根据自己系统修改下 Makefile
,编译完生成 lora_pkt_fwd
可执行文件以及其他测试程序。
https://github.com/Lora-net/packet_forwarder
https://github.com/Lora-net/lora_gateway
Note:模块 v3.0.0 版本对接 LoRaWAN Server 使用了自定义的 GWMP 协议版本 2,不兼容版本 1,对接时要注意两边版本一致
编写 packet_forwarder
起机脚本,包含了加载软 SPI 模块,复位 SX1301(手册要求),更新 local_conf
网关 MAC,启动 LoRa 转发模块,参考如下
#!/bin/sh /etc/rc.common
START=101
STOP=102
insmod_gpio_custom=true
reset_lora_chip=true
reset_cmd="reset_lgw.sh"
upgw_cmd="update_gwid.sh"
cmd="lora_pkt_fwd"
mod="spi-gpio-custom"
configFile="local_conf.json"
gpio_spi_dev="/dev/spidev1.0" # gpio simulated driver
hard_spi_dev="/dev/spidev0.1" # alternative: controlled by hardware spi controller
pid_file="/var/run/$cmd.pid"
stdout_log="/tmp/$cmd.log"
#stderr_log="/tmp/$cmd.err"
sck_pin=14
mosi_pin=15
miso_pin=16
mode=0
max_freq=10000000
cs_pin=4
get_pid() {
ps | grep -v grep | grep "$cmd" | awk '{print $1}'
}
is_running() {
ps | grep -v grep | grep "$cmd" > /dev/null
[ $? = 0 ]
}
start() {
if is_running; then
echo "Already started"
else
if [ \( ! -e "$gpio_spi_dev" \) -a \( ! -e "$hard_spi_dev" \) ]; then
echo "insmod custom gpio based spi"
insmod $mod bus0=1,$sck_pin,$mosi_pin,$miso_pin,$mode,$max_freq,$cs_pin # 可以在代码里加载好
fi
if [ "$reset_lora_chip" = true ]; then
echo "Reset SX1301"
chmod +x /etc/lora/"$reset_cmd"
/etc/lora/"$reset_cmd" start
fi
echo "update gateway id"
chmod +x /etc/lora/"$upgw_cmd"
/etc/lora/"$upgw_cmd" /etc/lora/"$configFile"
echo "Starting $cmd"
/usr/sbin/"$cmd" # >> "$stdout_log" 2>> "$stdout_log" &
echo "$!" > "$pid_file"
if ! is_running; then
echo "Unable to start, see $stdout_log"
exit 1
else
echo "Successfully started, see $stdout_log"
fi
fi
}
stop() {
if is_running; then
echo -n "Stopping $cmd.."
kill `get_pid`
for i in {1..60}
do
if ! is_running; then
break
fi
echo -n "."
sleep 1
done
echo
sleep 1
if [ "$reset_lora_chip" = true ]; then
/etc/lora/$reset_cmd stop
fi
if [ -e "$gpio_spi_dev" ]; then
echo "rmmod custom gpio based spi"
rmmod $mod
fi
if is_running; then
echo "Not stopped; may still be shutting down or shutdown may have failed"
exit 1
else
echo "Stopped"
if [ -f "$pid_file" ]; then
rm "$pid_file"
fi
fi
else
echo "Not running"
fi
}
restart() {
stop "$@"
start "$@"
}
status() {
if is_running; then
echo "Running"
else
echo "Stopped"
exit 1
fi
}
EXTRA_COMMANDS="status"
EXTRA_HELP=" status Print the status of lora packet-forward"
/etc/init.d/packet_forwarder start # 启动
Note: 运行测试程序前需先加载
spi-gpio-custom
模块,可以启动一下 /etc/init.d/packet_forwarder start 关掉,或者手动加载模块
# 发送功率测试,参数根据要求配置
util_tx_continuous -f 433.3 -r 1255 --mod LORA --sf 7 --bw 125
# 接收灵敏度测试
util_rx_test -c /etc/lora/freq_conf_433.json
对接 LoRaWAN Server
只是原型的话推荐接入 Loriot.io 社区进行调试期间试用, https://cn1dashboard.loriot.io/login,也可以自己到 github 上查找开源相关自己搭建一个。
参考 https://wiki.openwrt.org/doc/uci/network
注意与 4G 回传二选一来配置,ping 不通时,注意查看路由表默认路由是否是4G端口 route -e
,DNS 要配,LoRa 报文转发模块默认会解析 server 域名。
uci set network.lan.proto=static # 静态IP
uci set network.lan.ipaddr=xxx.xxx.xxx.xxx
uci set network.lan.gateway=xxx.xxx.xxx.xxx
uci set network.lan.dns=xxx.xxx.xxx.xxx
uci set network.lan.netmask=255.255.255.0
uci commit
或者通过改配置文件 /etc/config/network
config interface 'lan'
option ifname 'eth0 eth1 ath0'
option type 'bridge' # 桥模式
option force_link '1'
option proto 'static'
option ipaddr 'xxx.xxx.xxx.xxx'
option netmask '255.255.255.0'
option gateway 'xxx.xxx.xxx.xxx'
option dns 'xxx.xxx.xxx.xxx'
重启网络生效
/etc/init.d/network restart
参考
https://wiki.openwrt.org/doc/recipes/3gdongle
http://blog.csdn.net/qianguozheng/article/details/50543704
4G网卡的拨号方式有三种: PPP (PPP over EV-DO, CDMA, UMTS or GPRS),QMI (USB modems using QMI protocol),NCM (USB modems using NCM rotocol)
使用驱动程序及工具,通过 make menuconfig
里要打开如下模块。
option 驱动加载后,出现 5 个 ttyUSB,PPP 拨号使用 ttyUSB1,AT 命令查询 ttyUSB2,数据通路走 PPP 或 QMI 拨号,两者都要修订代码 option_ids 增加 id,芯片初始化要注册USB控制器。
//文件:linux-3.3.8/arch/mips/ath79/mach-ap120-h.c
//函数:static void __init xxx_setup(void)
ath79_register_usb();
//文件:linux-3.3.8/drivers/usb/serial/option.c
{ USB_DEVICE(LONGSUNG_VENDOR_ID, LONGSUNG_U8300_PRODUCT_ID)}, /* add for longsung U8300 LTE modem */
速率支持不是最高,当前状态下够用,3.3.8 内核配置完就可支持,通过 UCI 命令配置
uci set wan.ifname=ppp0
uci set wan.device=/dev/ttyUSB1
uci set wan.apn=3gnet
uci set wan.service=umts
uci set wan.dialnumber=*99#
uci set wan.proto=3g
uci set wan.defaultroute=1
或者修改 /etc/config/network
增加 ppp0 的 wan 口
config interface 'wan'
option ifname 'ppp0'
option device '/dev/ttyUSB1'
option apn '3gnet' # 根据运营商变化注:联通apn:3gnet 电信apn:ctnet 移动apn:cmnet/cmwap
option service 'umts'
option dialnumber '*99#' # 联通dialnumber:3G为*99# 电信:3G为#777 移动为:*99***1# LTE为:*99#
option proto '3g'
option defaultroute '1'
/etc/init.d/network restart
重启网络
ifconfig
查看是否出现 3G 端口
跟 PPP 拨号二选一, 修改代码跳过第四接口不让其被 option 驱动检测到,加载 GobiNet 模块驱动该口,支持 4G,更高速率,使用时 PPP 拨号要关掉
//文件:drivers/usb/serial/option.c
//函数: static int option_probe(struct usb_serial *serial, const struct usb_device_id *id)
if (cpu_to_le16(serial->dev->descriptor.idVendor) == LONGSUNG_VENDOR_ID &&
cpu_to_le16(serial->dev->descriptor.idProduct) == LONGSUNG_U8300_PRODUCT_ID &&
serial->interface->cur_altsetting->desc.bInterfaceNumber == 4) {
printk(KERN_INFO"Discover the 4th interface for U8300 NDIS\n");
return -ENODEV;
}
Gobi 芯片是高通开发的移动宽带 modem,3.3.8 内核需自己移植 GobiNet
驱动,3.4 内核以上系统自身有带 qmi_wwan
驱动,用户空间工具 ofono, uqmi and libqmi
,感兴趣的可以看下 https://sigquit.wordpress.com/2014/06/11/qmiwwan-or-gobinet/
#加载模块
insmod /lib/modules/3.3.8/GobiNet.ko
#读返回结果
cat /dev/ttyUSB2 &
#拨号
echo -e 'at$qcrmcall=1,1\r\n' > /dev/ttyUSB2
#查看出现4g用接口
ifconfig
#查询网络服务类型
echo -en "at+psrat\r" > /dev/ttyUSB2
#查询手机功能
echo -e "at+cfun?\r" > /dev/ttyUSB2
#查询pin是否正常识别或是否有pin码
echo -e "at+cpin?\r" > /dev/ttyUSB2
#查询运营商
echo -e "at+cops?\r" > /dev/ttyUSB2
#返回IMSI号
echo -en "at+cimi\r" > /dev/ttyUSB2
#查询IMEI号
echo -e "at+cgsn\r" > /dev/ttyUSB2
#查询集成电路卡识别码
echo -e "at+iccid\r" > /dev/ttyUSB2
#查询信号质量,返回rssi,rxlevel
echo -e "at+csq\r" > /dev/ttyUSB2
#断开连接
echo -e 'at$qcrmcall=0,1\r\n' > /dev/ttyUSB2
除了前面提到了,下面罗列一些关于 LoRaWAN 系统搭建可能会用到的代码链接。
Low-cost LoRa gateway with SX1272 and Raspberry
https://github.com/CongducPham/LowCostLoRaGw
This is a fork with the needed modifications to be able to use lora_gateway with a Multitech MTAC-LORA (MultiConnect mCard) board instead of a IoT Starter Kit platform.
https://github.com/mirakonta/lora_gateway
Semtech 开源的节点实现代码,MCU基于STM32L151CB,射频SX1272
https://github.com/Lora-net/LoRaMac-node
IBM 开源的节点实现代码,BSD License,支持ClassA、B
https://www.research.ibm.com/labs/zurich/ics/lrsc/lmic.html
lorawan server开源实现,MIT授权,可以参考实现
go语言 the things network社区,15年10月就开始做了,比较完整
https://github.com/TheThingsNetwork/ttn
V1版本源码:https://github.com/TheThingsNetwork/ttn/tree/v1-staging
TTN官网:https://www.thethingsnetwork.org
TTN架构:https://www.thethingsnetwork.org/wiki/Backend/Overview
ttnctl CLI:https://www.thethingsnetwork.org/docs/current/cli/
后台:https://account.thethingsnetwork.org
go语言,16年2月开始做的,跟TTN很像
https://github.com/brocaar/loraserver/
erlang语言,适合小型网络使用,只有1个人在开发
https://github.com/gotthardp/lorawan-server
https://sites.google.com/a/wesdec.be/mweyn/lpwan
http://semtechlorakit.blogspot.jp/