当前位置:   article > 正文

【Linux教程】基于NVIDIA®Jetson AGX Xavier™的Quectel EC200A 4G USB Dongle模块Linux驱动的移植_imx6 ec200a-cn

imx6 ec200a-cn

目录

1. 项目背景:

(1)硬件平台介绍

(2)编译平台和工具

2. 准备材料和知识:

(1)AGX内核源码

(2)4G模块EC200A驱动

3. 移植USB驱动代码

(1)查询4G模块的VID和PID信息

(2)添加USB驱动代码

A. 修改 [KERNEL_SRC] /kernel/kernel-5.10/drivers/usb/serial/option.c 文件

(i) 添加VID和PID

(ii) 添加掉电恢复机制

B. 修改 [KERNEL_SRC] /kernel/kernel-5.10/drivers/usb/serial/usb_wwan.c 文件

(·) 添加零包机制

C. 配置并编译内核

D. 移植驱动文件(.ko文件)

4. 驱动测试

(1)驱动查看

(2)串口测试

(3)实物测试

参考文献


1. 项目背景:

使用Quectel移远EC200A型号的4G模块给NVIDIA® Jetson AGX Xavier™平台添加移动网络。

(1)硬件平台介绍

· NVIDIA® Jetson AGX Xavier™嵌入式平台,如图1左;

· Quectel EC200A 4G USB Dongle通信模块,如图1右。

          

图1 AGX平台(左)和4G模块(右)

(2)编译平台和工具

· 系统版本:Ubuntu 20.04.5 LTS

· 编译工具:aarch64-linux-gnu-gcc 9.4.0

本文是在目标设备AGX(arm64/aarch64)上配置并编译Linux驱动,也可以在x64架构的电脑主机上采用交叉编译方式进行配置。如果采用交叉编译的方式则推荐使用的交叉编译工具链为aarch64-linux-gnu-gcc 7.3.1 (Linaro GCC 7.3-2018.05),下载地址:Linaro Releases

2. 准备材料和知识:

(1)AGX内核源码

NVIDIA Jetson AGX系列是专为嵌入式人工智能应用而设计的开发板,它具有自己特定的硬件架构和外设。为了适配硬件平台,我们不能使用普通的kernel内核源码。

根据AGX的Linux内核版本,在NVIDIA官网下载对应的Linux内核源码。

  1. mv@ubuntu:~$ uname -a
  2. Linux ubuntu 5.10.104-tegra #1 SMP PREEMPT Sun Mar 19 07:55:28 PDT 2023 aarch64 aarch64 aarch64 GNU/Linux
  3. mv@ubuntu:~$ head -n 1 /etc/nv_tegra_release
  4. # R35 (release), REVISION: 3.1, GCID: 32827747, BOARD: t186ref, EABI: aarch64, DATE: Sun Mar 19 15:19:21 UTC 2023

 这里使用的AGX版本是R35,内核版本是Linux 5.10.104。于是在NVIDIA DEVELOPER下载中心(需要注意的是NVIDIA开发者的.cn网站不提供下载页面,访问后提示找不到页面,这里给出的是NVIDIA开发者.com的网站:Jetson Download Center | NVIDIA Developer)搜索kernel,并选择对应的版本(R35.1),如图2所示。点击下载跳转到对应的下载页面,如图3所示。

图2 Jetson Download Center页面

图3 Jetson Linux 35.1页面

现在NVIDIA产品套件的源码是打包在一起的,也就是图3中对应的红框部分Driver Package (BSP) Sources。这里我们也可以使用NVIDIA提供的交叉编译工具链aarch64-buildroot-linux-gnu-gcc 9.3(如图3中橙色线框,Bootlin Toolchain gcc 9.3)进行交叉编译。

下载图3中对应的红框部分Driver Package (BSP) Sources后得到public_sources.tbz2。在[DECOMPRESS_OUT] /Linux_for_Tegra/source/public/ 文件夹内找到kernel_src.tbz2,这就是AGX所使用kernel内核源码文件。将内核源码解压到普通用户目录下的某个文件夹内,便于后续添加USB驱动代码,内核源码解压后的文件如图4所示。 

图4 kernel内核源码解压文件目录

图4中显示的内核源码解压文件,后续我们主要会使用其中的 [KERNEL_SRC] /kernel/kernel-5.10/ 这个文件夹及其内的源文件。

(2)4G模块EC200A驱动

Quectel EC200A_CN型号的4G模块只需用到USB接口,没有使用RJ45(8P8C)网络接口。于是仅需配置EC200A在Linux系统下的USB驱动即可,无需配置GobiNet驱动和QMI驱动。因为GobiNet驱动和QMI驱动是与网卡相关的驱动。因此,这里我们主要移植4G模块在Linux系统下的USB驱动。

3. 移植USB驱动代码

参考Quectel官方提供的Quectel LTE&5G Linux USB Driver User Guide V2.0.pdf》文件配置USB驱动。

(1)查询4G模块的VID和PID信息

将4G模块的USB口连接到AGX上,在AGX平台使用命令行 lsusb 查询当前设备中所有的USB信息,如下图5所示。从图5中,我们可以看到EC200A模块的 [VID:PID] 为 [2C7C:6005] 。

图5 查询4G模块USB信息

(2)添加USB驱动代码

A. 修改 [KERNEL_SRC] /kernel/kernel-5.10/drivers/usb/serial/option.c 文件

(i) 添加VID和PID

在option.c文件中的static const struct usb_device_id option_ids[] 中添加设备的VID和PID,如图所示6。

  1. static const struct usb_device_id option_ids[] = {
  2. /****************** Added by Helmholtz_optic *************************/
  3. { USB_DEVICE(0x2C7C, 0x6005) },/* Quectel EC200A: add VID and PID */
  4. /******************************************************************************/
  5. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
  6. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
  7. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
  8. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
  9. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) },
  10. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS) },
  11. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_LIGHT) },
  12. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD) },
  13. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT) },
  14. { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
  15. ......
  16. }

图6 添加VID和PID 

(ii) 添加掉电恢复机制

在option.c文件中的static struct usb_serial_driver option_1port_device 中添加掉电恢复机制,如图7所示。

  1. static struct usb_serial_driver option_1port_device = {
  2. .driver = {
  3. .owner = THIS_MODULE,
  4. .name = "option1",
  5. },
  6. .description = "GSM modem (1-port)",
  7. .id_table = option_ids,
  8. .num_ports = 1,
  9. .probe = option_probe,
  10. .open = usb_wwan_open,
  11. .close = usb_wwan_close,
  12. .dtr_rts = usb_wwan_dtr_rts,
  13. .write = usb_wwan_write,
  14. .write_room = usb_wwan_write_room,
  15. .chars_in_buffer = usb_wwan_chars_in_buffer,
  16. .tiocmget = usb_wwan_tiocmget,
  17. .tiocmset = usb_wwan_tiocmset,
  18. .get_serial = usb_wwan_get_serial_info,
  19. .set_serial = usb_wwan_set_serial_info,
  20. .attach = option_attach,
  21. .release = option_release,
  22. .port_probe = usb_wwan_port_probe,
  23. .port_remove = usb_wwan_port_remove,
  24. .read_int_callback = option_instat_callback,
  25. #ifdef CONFIG_PM
  26. .suspend = usb_wwan_suspend,
  27. .resume = usb_wwan_resume,
  28. /****************** Added by Helmholtz_optic *************************/
  29. .reset_resume = usb_wwan_resume, /*Quectel EC200A: add reset resume*/
  30. /******************************************************************************/
  31. #endif
  32. };

图7 添加掉电恢复机制

B. 修改 [KERNEL_SRC] /kernel/kernel-5.10/drivers/usb/serial/usb_wwan.c 文件

(·) 添加零包机制

在usb_wwan.c文件中的static struct urb *usb_wwan_setup_urb() 中添加休眠唤醒机制,如图8所示。

  1. static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
  2. int endpoint,
  3. int dir, void *ctx, char *buf, int len,
  4. void (*callback) (struct urb *))
  5. {
  6. struct usb_serial *serial = port->serial;
  7. struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
  8. struct urb *urb;
  9. urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
  10. if (!urb)
  11. return NULL;
  12. usb_fill_bulk_urb(urb, serial->dev,
  13. usb_sndbulkpipe(serial->dev, endpoint) | dir,
  14. buf, len, callback, ctx);
  15. if (intfdata->use_zlp && dir == USB_DIR_OUT)
  16. urb->transfer_flags |= URB_ZERO_PACKET;
  17. /****************** Added by Helmholtz_optic *************************/
  18. /*Quectel 2C7C modules: add the zero packet mechanism*/
  19. if(dir == USB_DIR_OUT){
  20. struct usb_device_descriptor *desc = &serial->dev->descriptor;
  21. if(desc->idVendor == cpu_to_le16(0x2c7c))
  22. urb->transfer_flags |= URB_ZERO_PACKET;
  23. }
  24. /******************************************************************************/
  25. return urb;
  26. }

图8 添加零包机制

C. 配置并编译内核

进入并在 [KERNEL_SRC] /kernel/kernel-5.10/ 目录下进行内核编译。

  1. $mkdir ../../kernel_out
  2. $TEGRA_KERNEL_OUT=../../kernel_out
  3. $export CROSS_COMPILE=aarch64-linux-gnu-

在 [KERNEL_SRC] / 目录下建立了名为 kernel_out 的编译输出文件夹,并导入编译工具链。

接着配置编译选项,如下:

$sudo make ARCH=arm64 O=$TEGRA_KERNEL_OUT menuconfig

在弹出的menuconfig中配置编译输出选项,这里推荐将USB驱动编译成模块(m),便于移植和加载。

  1. [ ] Device Drivers →
  2. [*] USB Support →
  3. [M] USB Serial Converter support →
  4. [M] USB driver for GSM and CDMA modems

需要注意的是,按照Quectel官方提供的Quectel LTE&5G Linux USB Driver User Guide V2.0.pdf》中的menuconfig设置后,无法生成独立的.ko文件。它的做法是将驱动模块文件编译进Linux内核中(y),而不是模块化(m)编译生成独立的驱动模块文件(.ko文件)。

最后就可以编译内核了,这里使用的AGX的CPU核心数为8。

$sudo make ARCH=arm64 O=$TEGRA_KERNEL_OUT -j8

成功编译完成后,有如下输出显示,如图9所示。

图9 成功编译输出

D. 移植驱动文件(.ko文件)

在编译输出的kernel_out文件夹中,[kernel_out] /drivers/usb/serial/ 文件夹中找到生成的option.ko,usb_wwan.ko 和 qcserial.ko 文件,并将这些文件复制到AGX的驱动文件夹中。

  1. $sudo cp option.ko /usr/lib/modules/5.10.104-tegra/kernel/drivers/usb/serial
  2. $sudo cp usb_wwan.ko /usr/lib/modules/5.10.104-tegra/kernel/drivers/usb/serial
  3. $sudo cp qcserial.ko /usr/lib/modules/5.10.104-tegra/kernel/drivers/usb/serial

完成后,加载.ko驱动模块并重启。

  1. $sudo depmod -a
  2. $sudo reboot

4. 驱动测试

(1)驱动查看

重启后,接入4G模块并查看查看驱动加载情况。

  1. $sudo modprobe usbmon    // 加载usbmon驱动模块
  2. $sudo dmesg
  3. $lsmod

图10 dmesg查看USB驱动情况 

图11 lsmod查看驱动情况

如果编译无误,则会出现如图10和11所示的情况。如果没有,则需要考虑重新编译。

(2)串口测试

接着我们使用串口调试工具minicom连接ttyUSB1,尝试对4G模块发送AT指令,测试结果如图12所示。

$sudo minicom -c on

图12 串口测试结果

图12中,可以看到AGX检测到4G模块并且成功识别了中国移动SIM卡。

(3)实物测试

将AGX连接显示屏后,发现在连接4G模块后会多出一个移动网络的标识符,如图13左所示。使用ping命令发现也可以连通,驱动移植成功。

   

图13 移动网络标识符(左)和ping命令结果(右)

参考文献

[1] 移植EC20F 4G模块驱动基于Jetson-xavier-CSDN博客.

[2] 基于Xavier 移植移远EG25G 4G模块-CSDN博客.

[3] 移远EC20 4G模块Linux驱动移植和测试_ec25 4g模块驱动-CSDN博客.

[4] 4G模块 EC20 R2.0 USB Serial/GobiNet/QMI WWAN 驱动移植过程_qmi_wwan-CSDN博客.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/468650
推荐阅读
相关标签
  

闽ICP备14008679号