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模块,所以仅粘贴原子哥教程的相关操作部分,具体的实验需要根据自己的设备进行验证。

猜你喜欢

转载自blog.csdn.net/weixin_45682654/article/details/128550384