STM32MP157驱动开发——4G通信模块驱动
参考文章:【正点原子】I.MX6U嵌入式Linux驱动开发——Linux 4G通信
一、简介
使用有线网络和无线 wifi 都会存在一些限制,因为都需要周围环境中存在路由器等设备才能连接,所以就需要一种直接使用蜂窝网络联网的方案。
目前市面上很多4G 模块都是 MiniPCIE 接口的,很适合用于Linux 平台或者 Android 平台。不过虽然使用的接口是 MiniPCIE,内部的通信协议却大多是 USB,所以驱动的开发就转化成了 USB 驱动开发。
二、驱动开发
原理图:
图中的 U22 就是 MiniPCIE 接口,该接口连接到 FE2.1 这个 USB HUB 芯片的 DP7 和 DM7 引脚。U26 为 Nano SIM 接口,这样就可以通过手机卡进行联网测试。
实物图:
4G模块:
左边为高新兴物联的 ME3630,右边为上海移远公司的 EC20。将模块连接到开发板上,再插入 SIM 卡,就可以进行后续的驱动开发了。(模块需要连接配套的天线)
1.高新兴 ME3630 驱动开发
ME3630 是一款 LTE Cat.4 七模全网通 4G 模块,在 LTE 模式下可以提供 50Mbps 上行速率以及 150Mbps 的下行速率,并支持回退到 3G 或 2G 网络。其特性如下:
① 一路 USB2.0 接口。
② 一路 UART 接口。
③ SIM 卡接口支持 1.8/3.0V。
④ 内置 TCP、 UDP、 FTP 和 HTTP 等协议。
⑤ 支持 RAS/ECM/NDIS。
⑥ 支持 AT 指令。
ME3630 4G 模块有多种配置,比如纯数据版本、集成 GNSS 版本、全网通版本等。本节主要使用数据通信功能,所以可以使用全网通版本,如果需要定位功能,就要使用全网通+GNSS版本。
驱动修改
首先需要在 Linux 内核中添加 ME3630 的 USB 设备信息,打开 Linux 源码的 drivers/usb/serial/option.c 文件,在 option_ids 数组中,添加 ME3630 的 PID 和 VID:
{ USB_DEVICE(0x19d2, 0x0117) }, /* ME3630*/
{ USB_DEVICE(0x19d2, 0x0199) },
{ USB_DEVICE(0x19d2, 0x1476) },
添加 ECM 支持程序
ME3630 支持 ECM 接口,可以通过 ECM 接口轻松联网,修改 drivers/usb/serial/option.c 文件中的 option_probe 函数,添加如下内容:
/* GOSUNCN 4G modems */
printk("idVendor=%x, idProduct=%x, bInterfaceNumber =%d\r\n",
serial->dev->descriptor.idVendor,
serial->dev->descriptor.idProduct,
serial->interface->cur_altsetting->desc. bInterfaceNumber);
if (serial->dev->descriptor.idVendor == 0x19d2 &&
serial->dev->descriptor.idProduct == 0x1476 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber == 3)
return -ENODEV;
if (serial->dev->descriptor.idVendor == 0x19d2 &&
serial->dev->descriptor.idProduct == 0x1476 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber == 4)
return -ENODEV;
if (serial->dev->descriptor.idVendor == 0x19d2 &&
serial->dev->descriptor.idProduct == 0x1509 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber == 4)
return -ENODEV;
if (serial->dev->descriptor.idVendor == 0x19d2 &&
serial->dev->descriptor.idProduct == 0x1509 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber == 5)
return -ENODEV;
配置 Linux 内核
首先使能 USBNET 功能,在 Device Drivers 路径下,选中以下选项:
然后使能 USB 串口 GSM、CDMA 驱动:
使能 USB 的 CDC ACM 模式:
ppp拨号功能测试
ME3630 除了支持使用 ECM 接口上网,也支持通过 ppp 拨号上网。使能 Linux 内核的 ppp 功能:
接着移植 pppd 软件,这个在buildroot
中进行使能:
接着编译出新的内核镜像uImage和根文件系统,就可以启动开发板进行测试。
使用pppd -v
就可以查看pppd的版本号:
在使用 pppd 进行拨号上网之前,需要先创建 4 个文件,在开发板根文件系统下创建 /etc/ppp/gosuncn 目录,然后新建一个名为“ppp-on”的 shell 脚本文件:
#!/bin/sh
clear
OPTION_FILE="gosuncn_options"
DIALER_SCRIPT=$(pwd)/gosuncn_ppp_dialer
exec pppd file $OPTION_FILE connect "chat -v -f ${DIALER_SCRIPT}"
再新建一个名为“gosuncn_options”的文件:
/dev/ttyUSB2
115200
crtscts
modem
persist
lock
noauth
noipdefault
debug
nodetach
user Anyname
password Anypassword
ipcp-accept-local
ipcp-accept-remote
defaultroute
usepeerdns
noccp
nobsdcomp
novj
dump
如果是联通或移动的卡就是用 ttyUSB2。
接着新建一个名为“gosuncn_ppp_dialer”的文件:
ABORT "NO CARRIER"
ABORT "ERROR"
TIMEOUT 120
"" ATE
SAY "ATE"
ECHO ON
OK ATH
OK ATP
OK AT+CGDCONT=1,\"IP\",\"3GNET\"
OK ATD*99#
CONNECT
倒数第2、3行是网络 APN 码,如果是联通卡,修改为以下内容:
OK AT+CGDCONT=1,\"IP\",\"3GNET\"
OK ATD*99#
电信卡:
OK AT+CGDCONT=1,\"IP\",\"CTNET\"
OK ATD*99#
移动卡:
OK AT+CGDCONT=1,\"IP\",\"CMNET\"
OK ATD*99#
最后,新建一个名为“disconnect”的 shell 脚本:
#!/bin/sh
killall pppd
编写完成以后要给予 ppp-on 和 disconnect 这两个文件可执行权限:
chmod 777 ppp-on disconnect
在使用以下命令连接4G网络:
/ppp-on &
如果连接成功,就会自动申请IP地址,并在终端打印。
注:4G 网络测试需要关闭其他网卡,否则的话网络测试可能有问题。使用网络文件系统不好操作,可以将 uboot、Linux kernel、.dtb 设备树和根文件系统都烧写到板子的EMMC 里面,然后直接启动 EMMC 上的系统。
ECM 联网测试
如果不使用 ppp 拨号上网,可以直接输入ifconfig -a
命令,找到一个名为“usb0”的网卡,这个就是ME3630的设备网卡。
在开发板根文件系统的/etc/ppp/gosuncn目录下创建一个名为“ecm_on”的 shell 脚本:
#!/bin/sh
clear
OPTION_FILE="gosuncn_options"
DIALER_SCRIPT=$(pwd)/gosuncn_ecm_dialer
exec pppd file $OPTION_FILE connect "chat -v -f ${DIALER_SCRIPT}"
最后再创建一个名为“gosuncn_ecm_dialer” 的文件:
ABORT "NO CARRIER"
ABORT "ERROR"
TIMEOUT 120
"" ATE
SAY "ATE"
ECHO ON
OK ATH
OK ATP
OK AT+ZSWITCH=L
OK AT+ZECMCALL=1
OK AT+CGDCONT=1,"IP","3GNET"
OK ATD*99#
CONNECT
倒数第2、3行依旧是网络 APN 码,不同运营商的设置与上文相同。
再给予 ecm-on 这个文件可执行权限:
chmod 777 ecm-on
并使用以下命令连接网络:
/ecm-on &
打开网卡并自动获取IP地址:
ifconfig usb0 up
udhcpc -i usb0
ME3630 4G 模块 GNSS 定位测试
注意:ME3630-C3C 的 GNSS 要用无源天线,不能使用有源天线,否则无法定位。
有些型号的 ME3630 带有 GNSS 功能,移植完后会出现 3 个 ttyUSB 设备,分别为 ttyUSB0~ttyUSB2,其中 ttyUSB1 为 GNSS 接口。GPS 模块通常都是使用串口进行通信,ME3630 也一样,只不过是 USB 转串口。所以可以直接使用 minicom 来查看 ttyUSB1 输出的 GNSS 信息,ME3630 的 GNSS 定位使用 ttyUSB1 接口,波特率为 115200,相关设置可以参考之前的串口通信的内容,这里不再赘述。
这里主要了解一下使用 AT 指令配置 ME3630 的步骤,ME3630 默认关闭了 GNSS 定位输出功能的,所以必须先使用 AT 指令配置:
ATI //查看固件信息
Manufacturer: GOSUNCNWELINK
Model: ME3630-W
Revision: ME3630C3CV1.0B03
IMEI: 864863045876287
OK
AT+ZGINIT //初始化 GPS
OK
AT+ZGPSEVENT=1 //使能 GPS 事件上报
OK
AT+ZGMODE=3 //设置定位模式
OK
AT+ZGPORT=0 //定位信息从 AT、 MODEM、 UART 三个口同时上报
OK
AT+ZGNMEA=31 //设置 GPS 数据为 NMEA 格式
OK
AT+ZGPSR=1 //使能 ZGPSR 数据
OK
AT+ZGRUN=2 //连续定位模式
OK
其中每句指令的下半部分为模块的返回值。AT 指令配置完成以后 ME3630 就会开始搜星。注:GPS 天线一定要放到室外。
等 ME3630搜星结束以后就会输出 NEMA 格式的定位信息。
2.移远EC20 4G驱动开发
移远的 EC20 4G 模块采用 LTE 3GPP Rel.11 技术,支持最大下行速率 150Mbps,最大上行速率 50Mbps。相关的版本分类及选用与ME3630相同。其相关特性如下:
① 一路 USB2.0 高速接口,最高可达 480Mbps。
② 一组模拟语音接口(可选)
③ 1.8V/3.0V SIM 接口
④ 1 个 UART 接口
⑤ W_DISABLE#(飞行模式控制)
⑥ LED_WWAN#(网络状态指示)
驱动修改
需要先在 Linux 内核中添加 EC20 的 USB 设备信息,在 drivers/usb/serial/option.c 文件的 option_ids 数组中添加移远的模块 ID:
{ USB_DEVICE(0x2C7C, 0x0125) }, /* EC20 */
然后在 drivers/usb/serial/option.c 文件中的 option_probe 函数添加以下内容:
/* EC20 */
if (serial->dev->descriptor.idVendor == 0x05c6 &&
serial->dev->descriptor.idProduct == 0x9003 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber >= 4)
return -ENODEV;
if (serial->dev->descriptor.idVendor == 0x05c6 &&
serial->dev->descriptor.idProduct == 0x9215 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber >= 4)
return -ENODEV;
if (serial->dev->descriptor.idVendor == 0x2c7c &&
serial->interface->cur_altsetting->desc. bInterfaceNumber >= 4)
return -ENODEV;
除此之外,还要在 drivers/usb/serial/option.c 文件里的 option_1port_device 结构体变量中,加入休眠后唤醒接口:
打开 drivers/usb/serial/usb_wwan.c 文件,在usb_wwan_setup_urb函数中添加零包处理代码:
static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, int endpoint, int dir, void *ctx, char *buf, int len, void (*callback) (struct urb *))
{
struct usb_serial *serial = port->serial;
struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
struct urb *urb;
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (!urb)
return NULL;
usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx);
if (intfdata->use_zlp && dir == USB_DIR_OUT)
urb->transfer_flags |= URB_ZERO_PACKET;
/* EC20 */
if (dir == USB_DIR_OUT) {
struct usb_device_descriptor *desc = &serial->dev->descriptor;
if (desc->idVendor == cpu_to_le16(0x05c6) && desc->iProduct == cpu_to_le16(0x9090))
urb->transfer_flags |= URB_ZERO_PACKET;
if (desc->idVendor == cpu_to_le16(0x05c6) && desc->iProduct == cpu_to_le16(0x9003))
urb->transfer_flags |= URB_ZERO_PACKET;
if (desc->idVendor == cpu_to_le16(0x05c6) && desc->iProduct == cpu_to_le16(0x9215))
urb->transfer_flags |= URB_ZERO_PACKET;
if (desc->idVendor == cpu_to_le16(0x2c7c))
urb->transfer_flags |= URB_ZERO_PACKET;
}
return urb;
}
配置 Linux 内核
需要使能 USB NET、GSM、CDMA 驱动等,与上文的设置相同。
然后编译出内核镜像即可使用。开机后会出现 4 个tty接口 ttyUSB0~ttyUSB,其功能如下:
ttyUSB | 描述 |
---|---|
ttyUSB0 | DM |
ttyUSB1 | GPS 的 NMEA 信息输出接口 |
ttyUSB2 | AT 指令接口 |
ttyUSB3 | PPP 连接或 AT 指令接口 |
EC20 ppp 拨号上网
同样需要创建 4 个文件,在开发板根文件系统下创建/etc/ppp/quectel目录,然后新建一个名为“ppp-on”的 shell 脚本文件:
#!/bin/sh
clear
OPTION_FILE="quectel_options"
DIALER_SCRIPT=$(pwd)/quectel_ppp_dialer
exec pppd file $OPTION_FILE connect "chat -v -f ${DIALER_SCRIPT}"
再新建一个名为“quectel_options”的文件:
/dev/ttyUSB2
115200
crtscts
modem
persist
lock
noauth
noipdefault
debug
nodetach
user Anyname
password Anypassword
ipcp-accept-local
ipcp-accept-remote
defaultroute
usepeerdns
noccp
nobsdcomp
novj
dump
其中ppp 拨号接口使用 ttyUSB2。
再新建一个名为“quectel_ppp_dialer”的文件:
ABORT "NO CARRIER"
ABORT "ERROR"
TIMEOUT 120
"" ATE
SAY "ATE"
ECHO ON
OK ATH
OK ATP
OK AT+CGDCONT=1,\"IP\",\"3GNET\"
OK ATD*99#
CONNECT
倒数第2、3行的运营商 APN 码参考上文设置。
最后新建一个名为“disconnect”的 shell 脚本:
#!/bin/sh
killall pppd
赋予文件可执行权限并启动网络连接:
chmod 777 ppp-on disconnect
/ppp-on &
移远 GobiNET 驱动移植
EC20 除了可以使用 ppp 拨号上网,也可以使用移远提供的 GobiNnet 驱动。将原子哥提供的相关文件拷贝到 Linux 内核的 /driver/net/usb 目录下:
然后打开 Linux 内核的 drivers/net/usb/Makefile 文件,在末尾添加以下内容:
obj-$(CONFIG_USB_GOBI_NET) += GobiNet.o
GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o
最后在 drivers/net/usb/Kconfig 文件中加入下所示内容,配置可视化界面:
config USB_GOBI_NET
tristate"Gobi USB Net driver for Quectel module"
help
Support Quectelmodule.
A modemmanager with support for GobiNet is recommended.
Tocompile this driver as a module, choose M here: the module will be calledGobiNet.1
然后在 Linux 内核的 menuconfig 中,使能添加的 Gobi 驱动:
然后编译出新的 uImage 启动开发板,启动后会出现一个 “/dev/qcqmi1” 设备文件。
quectel-CM 移植
GobiNET 移植成功以后如果要想上网,还需要用到移远提供的 quectel-CM 这个软件,这个软件是移远提供的网络管理工具。将原子哥提供的相关工具的源码拷贝到 Ubuntu 下并解压。
使用make CROSS_COMPILE=arm-none-linux-gnueabihf-
命令进行交叉编译,得到一个名为“quectel-CM”软件。将编译出来的 quectel-CM 软件拷贝到开发板根文件系统的/usr/bin 目录下。
sudo cp quectel-CM ~/linux/nfs/rootfs/usr/bin/ -f
上网测试
quectel-CM -s 3gnet &
-s 指定 APN 类型,移动卡的 APN 为 cmnet,联通卡的 APN 为 3gnet,电信卡的 APN 为 cenet。 网卡会使用到 udhcpc 自动获取 IP 地址。
结束语:这里笔者没有相关的4G模块,所以仅粘贴原子哥教程的相关操作部分,具体的实验需要根据自己的设备进行验证。