STM32MP157驱动开发指南:4G通信模块驱动详解

STM32MP157驱动开发——4G通信模块驱动

  • 一、简介
  • 二、驱动开发
  • 1.高新兴 ME3630 驱动开发
  • 驱动修改
  • 添加 ECM 支持程序
  • 配置 Linux 内核
  • ppp拨号功能测试
  • ECM 联网测试
  • ME3630 4G 模块 GNSS 定位测试
  • 2.移远EC20 4G驱动开发
  • 驱动修改
  • 配置 Linux 内核
  • EC20 ppp 拨号上网
  • 移远 GobiNET 驱动移植
  • quectel-CM 移植
  • 上网测试

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

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32MP157驱动开发指南:4G通信模块驱动详解

    发表回复