OpenWRT系统(二) - LoRa基站开发

文章目录

    • 架构
    • LoRa 芯片驱动调试
      • GPIO 模拟 SPI
      • 硬件SPI片选控制
    • LoRa转发模块移植
    • 有线口回传
    • 4G模块调试
      • 配置编译
      • PPP 拨号
      • QMI拨号
    • 参考
      • 基站端
      • 模组
      • LoRaWAN Server
      • Simulation
      • Semtech Starter Kit

这篇文章主要记录lora原型基站开发的过程,基站支持对接市场上默认的 LoRaWAN Server,支持有线口回传,支持4G回传。

架构

  • 步骤
    • CPU 移植运行 OpenWRT 系统,有线口正常,这块我是基于现成的,此处省略
    • 调试 SX1301 芯片驱动
    • 移植 Semtech 公司开源的 packet_forwarder 到 OpenWRT 平台,对接通用的 LoRaWAN Server
    • 调试移植4G模块驱动
  • 硬件组成:CPU 使用 SOC AR95xx 系列芯片,通过 SPI 接口跟基带芯片通信,LoRa 基带射频使用 Semtech 公司的多路芯片 SX1301 + SX1255,4G 模组使用龙尚 U8300
  • 软件:平台 OpenWRT ,版本 Attitude Adjustment 12.09,内核 3.3.8
  • 报文流程
    • AR95xx 通过 HAL 模块的 SPI 读写操作控制 SX1301 接收终端发送的报文,经过 packet forwarder 模块封装打包后走有线口、WIFI 或 4G 通路,通过UDP方式发送给后台 LoRaWAN Server。
      OpenWRT系统(二) - LoRa基站开发_第1张图片

LoRa 芯片驱动调试

AR9531 可以通过 USB 或 SPI 驱动 SX1301,USB方式需要FTDI转 SPI 芯片方式网上教程较多。由于板子限制,这里采用 SPI 方式,由于板子的 SPI 控制器已经用来驱动 flash,控制 SX1301 有两种方式:

  • GPIO 模拟 SPI 来控制(软 SPI )
  • 实际的硬件 SPI 通过片选控制

为提高调试效率,先修改Makefile的 cmdline 字段波特率,以串口 ttyS0 为例下面命令可以查找包含 ttyS0 对应行,使用 VIM 修改成 115200。

grep ttyS0 ./target/linux/ar71xx/image/Makefile

GPIO 模拟 SPI

参考
https://randomcoderdude.wordpress.com/2013/08/15/spi-over-gpio-in-openwrt/

  • GPIO 管脚使用

先确认 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-gpiospi-bitbang),另外有spi-dev 设备层通用驱动,用来导出到用户空间,编译内核前把这三个模块打开。spi-dev 模块问题是不大方便调试,建议下载移植 spi-gpio-custom 模块用于动态加载软 SPI 模块,根据对应 GPIO 管脚加载。
    OpenWRT系统(二) - LoRa基站开发_第2张图片

    # 参数说明
    * 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 设备是否出现,存在则加载成功
    

硬件SPI片选控制

待完善,主要修订代码 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转发模块移植

  • 编译移植 LoRa 报文转发模块

    下载编译 packet_forwarderlora_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  

4G模块调试

参考
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 里要打开如下模块。

  • 工具
    comgt
  • USB HCI
    kmod-usb2 (aka EHCI)
    kmod-usb-ohci
    kmod-usb-uhci (for example VIA chips)
  • 虚拟串口通信用
    kmod-usb-serial, and kmod-usb-serial-option, and kmod-usb-serial-wwan, or kmod-usb-acm
  • 依赖库
    kmod-usb-core, already in 10.03 RC3 Image
    chat, dependency of comgt
    ppp, dependency of chat, already in 10.03 RC3 Image
    kmod-usb-serial, dependency of kmod-usb-serial-option

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 */

PPP 拨号

速率支持不是最高,当前状态下够用,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 端口

QMI拨号

跟 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

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

Simulation

https://sites.google.com/a/wesdec.be/mweyn/lpwan

Semtech Starter Kit

http://semtechlorakit.blogspot.jp/

你可能感兴趣的:(嵌入式,LoRaWAN,OpenWRT,Tip)