MYD-YA157C系列定制板RM500Q-GL驱动移植笔记 2021.8.12
一、准备工作
(1)YA157C开发板一块
(2) Ipex1代转SMA母,转接线若干
(3) Ipex4代转SMA母,转接线若干
(4) 跳线帽若干,并安装到如下图所示的指定位置
(5G模块硬件拉高开机,默认状态)
(蓝色带包5G模块软件拉高开机)
(5) 准备一个linux环境用来交叉编译,这里我使用了deepin系统,并将其安装在VMware虚拟机环境下
(6) 参考《MYD-YA157C_Linux软件开发指南V2.0.pdf》准备交叉编译环境
我们在使用 Yocto 构建完系统镜像之后,还可以使用 Yocto 构建一套可扩展的 SDK。在米尔提供的光盘镜像中包含一个编译好的 SDK 包,位于:03-Tools/Complie Toolchain/QT-SDK/sdk-qt.tar.xz,这个 SDK 中除了包含一个独立的交叉开发工具链还提供 qmake, 目标平台的 sysroot, Qt 应用开发所依赖的库和头文件等。用户可以直接使用这个 SDK 来建立一个独立的开发环境,单独编译 Bootloader,Kernel 或者编译自己的应用程序。
将 SDK 压缩包拷贝到deepin 下的用户工作目录,如$HOME/work 下,解压文件,得
到安装脚本文件,如下:
PC$ cd $HOME/work PC$ tar -Jxvf sdk-qt.tar.xz sdk
进入 SDK 目录,可以看到下面安装脚本文件:
meta-toolchain-qt5-openstlinux-eglfs-myir-x86_64-toolchain-3.1-snapshot.host.manifest meta-toolchain-qt5-openstlinux-eglfs-myir-x86_64-toolchain-3.1-snapshot.sh meta-toolchain-qt5-openstlinux-eglfs-myir-x86_64-toolchain-3.1-snapshot.target. manifest meta-toolchain-qt5-openstlinux-eglfs-myir-x86_64-toolchain-3.1-snapshot.testdata.json
PC$ ./meta-toolchain-qt5-openstlinux-eglfs-myir-x86_64-toolchain-2.6-snapshot.sh
SDK 默认被安装到/opt/st/myir/3.1-snapshot 目录下,用户也可以根据提示自己选择合适的目录,具体根据提示进行操作:
ST OpenSTLinux - EGLfs - (A Yocto Project Based Distro) SDK installer version 3.1- snapshot =============================================== Enter target directory for SDK (default: /opt/st/myir/3.1-snapshot): You are about to install the SDK to "/opt/st/myir/3.1-snapshot". Proceed [Y/n]? y [sudo] password for licy: Extracting SDK ........................................................................................................................................... done Setting it up...done SDK has been successfully set up and is ready to be used. Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g. $ . /opt/st/myir/3.1-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
安装完成后,使用以下命令设置环境变量,测试 SDK 是否完成:
PC$ source /opt/st/myir/3.1-snapshot/environment-setup-cortexa7t2hf-neon-vfp v4-ostl-linux-gnueabi PC$ $CC --version arm-ostl-linux-gnueabi-gcc (GCC) 8.2.0 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
米尔提供的 SDK 中除了包含交叉工具链,还包含 Qt 库,qmake 等开发 Qt 应用程序所需的资源,这些是后续使用 QT Creator 进行应用程序开发和调试的基础。
二、上电开机,通过网络连接开发板,登陆后,执行lsusb命令,正常情况下可以识别移远RM500Q-GL的VID与PID如图所示(我已经移植了驱动,所以可以正常识别型号,如果未做驱动移植,这里可能只会显示2c7c:0800)。
三、参考官方文档《Quectel_LTE&5G_Linux_USB_Driver_User_Guide_V2.0.pdf》移植驱动
(1)为了识别模块,需要将下图最后一行RM500Q的VID和PID信息添加到[KERNEL]/drivers/usb/serial/option.c文件的指定位置中(米尔提供的内核中已添加RM500Q的VID和PID,可省略此步骤)
(2) 添加Zero Packet Mechanism
根据USB协议的要求,需要在bulk-out传输过程中增加处理零包的机制,添加如下语句(米尔提供的内核中已定义,可省略此步骤)。
[KERNEL]/drivers/usb/serial/usb_wwan.c. static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, int dir, void *ctx, char *buf, int len,void (*callback) (struct urb *)) { …… usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx); #if 1 //Added by Quectel for zero packet if (dir == USB_DIR_OUT) { struct usb_device_descriptor *desc = &serial->dev->descriptor; if (desc->idVendor == cpu_to_le16(0x2C7C)) urb->transfer_flags |= URB_ZERO_PACKET ; } #endif return urb; }
[KERNEL]/drivers/usb/serial/option.c. /* Helper functions used by option_setup_urbs */ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint, int dir, void *ctx, char *buf, int len, void (*callback)(struct urb *)) { …… usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx); #if 1 //Added by Quectel for zero packet if (dir == USB_DIR_OUT) { struct usb_device_descriptor *desc = &serial->dev->descriptor; if (desc->idVendor == cpu_to_le16(0x2C7C)) urb->transfer_flags |= URB_ZERO_PACKET ; #endif return urb; }
(3) 配置重置机制
当MCU进入Suspend/Sleep模式时,部分USB主机控制器/USB hub会断电或复位,当MCU退出Suspend/Sleep模式后,部分USB主机控制器/USB hub将无法用于USB恢复。需要通过添加以下语句启用reset-resume机制。
[KERNEL]/drivers/usb/serial/option.c. static struct usb_serial_driver option_1port_device = { …… #ifdef CONFIG_PM .suspend = usb_wwan_suspend, .resume = usb_wwan_resume, #if 1 //Added by Quectel .reset_resume = usb_wwan_resume, #endif #endif };
[KERNEL]/drivers/usb/serial/usb-serial.c. /* Driver structure we register with the USB core */ static struct usb_driver usb_serial_driver = { .name = "usbserial", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .suspend = usb_serial_suspend, .resume = usb_serial_resume, #if 1 //Added by Quectel .reset_resume = usb_serial_resume, #endif .no_dynamic_id = 1, .supports_autosuspend = 1, };
(4) 添加对MBIM, GobiNet和QMI_WWWAN驱动的支持
当需要使用MBIM、GobiNet或QMI_WWAN驱动时,需要添加如下语句,防止模块接口4作为USB串口设备使用。
[KERNEL]/drivers/usb/serial/option.c. static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { struct usb_wwan_intf_private *data; …… #if 1 //Added by Quectel //Quectel modules’s interface 4 can be used as USB network device if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) { //some interfaces can be used as USB Network device (ecm, rndis, mbim) if (serial->interface->cur_altsetting->desc.bInterfaceClass != 0xFF) { return -ENODEV; } //interface 4 can be used as USB Network device (qmi) else if (serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) { return -ENODEV; } } #endif /* Store device id so we can use it during attach. */ usb_set_serial_data(serial, (void *)id); return 0; }
[KERNEL]/drivers/usb/serial/option.c. static int option_startup(struct usb_serial *serial) { …… dbg("%s", __func__); #if 1 //Added by Quectel if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) { //some interfaces can be used as USB Network device (ecm, rndis, mbim) if (serial->interface->cur_altsetting->desc.bInterfaceClass != 0xFF) { return -ENODEV; } //interface 4 can be used as USB Network device (qmi) else if (serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) { return -ENODEV; } } #endif …… }
(5) 配置内核
解压米尔提供的iso文件,进入04_Sources,找到MYiR-STM32-kernel.tar.bz2,放入即将进行交叉编译的linux环境中(在这里指安装了deepin的虚拟机),并解压
cd myir-st-linux
mkdir -p ../build
make -j16 ARCH=arm O="$PWD/../build" myc-ya157c_defconfig #注意:此处的-j16是指使用16个处理器进行多线程同时编译,如果你只给虚拟机分配了两个处理器,这里就改为-j2依次类推。
进入刚创建的build目录
cd ../build
使用下面的命令编译内核
Make menuconfig
使用以下选项启用CONFIG_USB_SERIAL_OPTION。
make menuconfig [*] Device Drivers → [*] USB Support → [*] USB Serial Converter support → [*] USB driver for GSM and CDMA modems
使用TAB键,移动光标至Save,然后按照提示保存,保存后执行多次ESC键以退出界面。
(6) 配置GobiNet驱动
在build目录下再次执行make menuconfig,进入
[*] Device Drivers → -*- Network device support → USB Network Adapters → {*} Multi-purpose USB Networking Framework
确保Multi-purpose USB Networking Framework为打开状态(按Y即可打开)
保存并退出,系统生成.config文件。
obj-y += GobiNet.o GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o
请注意:对于米尔的这个开发板子,需要使用obj-m的方式,obj-m表示把文件test.o作为"模块"进行编译,不会编译到内核,但是会生成一个独立的 "test.ko" 文件;obj-y表示把test.o文件编译进内核;本人在这里卡顿了许久,编译成功后一直打不上驱动,最后在这个地方得到了解决,即在上述文件夹中,添加以下内容:
obj-m += GobiNet.o GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o
保存并退出。
(7) 编译内核
Source /opt/st/myir/3.1-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
make ARCH=arm O="$PWD/../build" myc-ya157c_defconfig
make -j16 ARCH=arm uImage vmlinux dtbs LOADADDR=0xC2000040 O="$PWD/../build" make -j16 ARCH=arm modules O="$PWD/../build"
以16线程同时编译,大约编译两分钟。以单线程运行时,编译过程大约需要15-20分钟,请合理分配虚拟机CPU,保证最大化的利用系统资源,节省编译时间。
make -j16 ARCH=arm INSTALL_MOD_PATH="$PWD/../build/install_artifact" modules_install O="$PWD/../build" mkdir -p $PWD/../build/install_artifact/boot/ cp $PWD/../build/arch/arm/boot/uImage $PWD/../build/install_artifact/boot/ cp $PWD/../build/arch/arm/boot/dts/st*.dtb $PWD/../build/install_artifact/boot/
l 将编译完成的文件传输到开发板并更新kernel
进入build/install_artifact/目录,执行以下命令
scp -r boot/* root@192.168.2.66:/boot #更新 uImage 与设备树,此处假设开发板的ip为192.168.2.66,如果有密码,还需输入密码
rm lib/modules/5.4.31/source lib/modules/5.4.31/build #删除编译生成文件 build/install_artifact/lib 下的软连接文件
scp -r lib/modules/* root@192.168.2.66:/lib/modules/ #更新内核 modules
使用finalshell等软件,连接到开发板
执行以下命令完成同步&重启
sync & reboot
四、测试驱动是否正常安装
(1) 使用lsusb命令,查看能否正常显示RM500Q-GL的型号
(2) 使用ifconfig命令,查看是否新增“eth1”网卡
一、交叉编译拨号软件
(1) 解压Quectel_QConnectManager_Linux_V1.6.0.6
(2) 进入Quectel_QConnectManager_Linux_V1.6.0.6,在此处打开终端,加载环境变量
source /opt/st/myir/3.1-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
(3) 执行编译
make CROSS_COMPILE=arm-hisiv300-linux-
编译完成后,将该文件夹拷贝至开发板/home/root目录下
(4) 给该目录下的.sh文件添加可执行权限
chmod a+x *.sh
(5) 运行拨号软件
./quectel-CM &
(出现以上信息代表驱动已经成功移植,5G模块已能够被系统识别,此处我没有插入SIM卡,所以是sim_absent状态)