0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

应用笔记|米尔NXP iMX 93开发板OTA功能搭建

米尔电子 2024-05-23 08:01 次阅读

1.概述

空中下载技术(Over-the-Air Technology, OTA)是通过移动通信的空中接口实现对移动终端设备及SIM卡数据进行远程管理的技术。本文采用了swupdate的方式进行ota升级,swupdate是一个基于嵌入式Linux平台的升级服务框架程序,它提供了分区升级,文件升级,差分升级(补丁应用)功能,并提供了开放接口,方便用户添加自定义升级处理函数。本应用笔记主要讲述如何使用搭建在米尔基于NXP iMX 93核心板系统中的OTA功能,实现对米尔基于NXP iMX 93核心板文件系统的远程升级。

2.环境准备

2.1.软件资源

OTA升级文件制作工具:ota-generate_swu.tar.gz(路径:03_Tools/ota-tools)。

MYC-LMX9X-Core文件系统:myir-image-core-myd-lmx9x.ext4(路径:02_Images/ 或者通过Yocto编译得到,编译相关情况查看软件开发指南内容)。

Ubuntu操作系统主机环境,虚拟机或者安装的Ubuntu PC主机皆可,没有版本要求。


2.2.硬件资源

米尔基于NXP iMX 93开发板(或者MYC-LMX9X核心板+自研底板,自研底板要求至少有一个网口或者存在Wifi芯片)。

网线或者Wifi天线

开发板电源、串口线及其他能够确保开发板能够正常运行启动所需求的配件。


2.3.主机环境配置

进行OTA升级,必须要要在Ubuntu主机环境搭建Http服务器,以下将以Ubuntu18.04的Http服务器搭建过程举例,用户名将以myir举例,为了后续OTA升级使用,将Http服务器直接配置为后续可直接使用的配置。该过程仅供参考使用,如果使用其他版本的Ubuntu系统在搭建过程中出现任何以下说明中未出现的错误情况,请咨询互联网寻找解决办法。

安装apache2

sudo apt install -y apache2

配置环境

默认是80端口,防止其他情况使用导致冲突,修改为自定义端口:8001,修改 /etc/apache2/ports.conf文件监听端口:

$:vi/etc/apache2/ports.confListen8001##其它行不变

修改/etc/apache2/sites-enabled/000-default.conf文件端口与访问目录,方便后续使用。

$:vi/etc/apache2/sites-enabled/000-default.conf8001> ## 其他行不变#DocumentRoot /var/www/html ## 默认浏览器访问目录,注释掉DocumentRoot/home/myir/swupdate##修改为此目录,用户名请根据修改做修改

修改apache2的配置文件/etc/apache2/apache2.conf:

$: vi /etc/apache2/apache2.conf##找到如下行,并修改为如下内容# ##配置文件默认目录,注释掉 Options Indexes FollowSymLinks AllowOverride None Require all granted

重启服务

$: sudo /etc/init.d/apache2 restart

测试

如果是虚拟机请修改Ubuntu网络配置为桥接网卡让虚拟机和Windows主机为同一IP下,如果是其他环境则可以直接打开浏览器,并在浏览器中输入http://{hostIP}:8001,此处hostIP为配置了http服务器的Ubuntu的ip地址,例如Ubuntu 的ip地址为192.168.1.20,则在浏览器中输入//192.168.1.20:8001,成功则如下图所示:

9e04595e-1897-11ef-bebc-92fbcf53809c.png图2-1. http搭建成功

3.升级原理

OTA简单理解就是在线升级固件,将固件从服务器下载之后,相应的写入对应的分区,在这个过程中可能会存在烧录中断电或者其他原因导致分区损坏了问题,所以MYD-LMX9X选择了AB对称分区的方式来保存文件系统。

3.1.AB分区介绍

对于MYD-LMX9X的AB对称文件系统,首先做了以下逻辑处理:

首先在Uboot的env变量中添加了boot_limit,mmcbootpart,mmcbootpart_back三个变量,并且对它们添加了一定的逻辑判断,可以通过uboot命令行看到:

u-boot=>printenvboot_limitboot_limit=3u-boot=> printenv mmcbootpartmmcbootpart=2u-boot=> printenv mmcbootpart_backmmcbootpart_back=3bsp_bootcmd=echoRunningBSPbootcmd...;mmcdev${mmcdev};ifmmcrescan;thenifrunloadbootscript;thenrunbootscript;elseiftest${sec_boot}=yes;thenifrunloadcntr;thenrunmmcboot;elserunnetboot;fi;elseifrunloadimage;theniftest${boot_limit}-gt0;thensetexprboot_limit ${boot_limit}-1;setenvboot_limit${boot_limit};saveenv;setenvmmcroot/dev/mmcblk${mmcdev}p${mmcbootpart}rootwaitrw;elsesetenvmmcroot/dev/mmcblk${mmcdev}p${mmcbootpart_back}rootwaitrw;fi;runmmcboot;elserunnetboot;fi;fi;fi;fi;

boot_limit的值每当开发板上电进入uboot后会将其减一,可以通过上述高亮的地方可以查看到,但是当文件系统启动成功后会被设置为3,所以假如出现了文件系统损坏的问题导致无法启动,boot_limit无法被设置为3,并且文件系统启动失败后会自动运行看门狗重启,看门狗默认时间为60s,当发现启动失败后手动重启系统也是一样的,重启后再次进入uboot,此时由于boot_limit没有被设置为3,所以此时boot_limit值为2,并且则会被再次减一。

mmcbootpart变量是当前启动的分区号,比如上述中值为2,则稍后会从mmcblk0p2启动;mmcbootpart_back是备份启动的分区号,如上述中值为3,则文件系统mmcblk0p2无法启动或者启动错误后,在boot_limit值在重启多次后为0时,将会启动mmcblk0p3备份分区。

具体的运行逻辑流程图如下:

9e1a8f80-1897-11ef-bebc-92fbcf53809c.png图3-1. AB分区流程图

可以在文件系统中执行以下命令查看到eMMC中分区的情况:

root@myd-lmx9x:~#cat/proc/partitionsmajor minor #blocks name179 0 7634944 mmcblk0179 1 102400 mmcblk0p1 #Image+dtb内核和设备树文件存放分区179 2 3686400 mmcblk0p2 #A文件系统分区179 3 3686400 mmcblk0p3 #B文件系统分区179 32 32640 mmcblk0boot01796432640mmcblk0boot1

3.2.Swupdate介绍

本节将介绍在上章节中,在进入文件系统后会进行swupdate的更新,该更新由systemd的服务启动,是自动更新,只需要修改对应的ip地址路径的配置即可。

首先介绍swupdate更新会需要到的swu文件,该文件由脚本制作生产,该制作工具压缩包已存放在03_Tools中,名称为ota-generate_swu.tar.gz,具体制作过程后续4.1章节会介绍,在这里先介绍其中swu文件的配置文件sw-description,该文件如下所示:

software ={ version = "1.1"; description = "Firmware update for myd-lmx9x" myd-lmx9x = { hardware-compatibility: [ "1.0", "1.1" ]; stable: { main: { images:( { filename = "myir-image-core-myd-lmx9x.ext4"; device = "/dev/mmcblk0p3"; filesystem = "ext4" ; } ); bootenv:( { name="mmcbootpart"; value="3"; }, { name="mmcbootpart_back"; value="2"; } ); scripts: ( { filename = "update.sh"; type = "shellscript"; } ); };

其中包含了version,设备名称myd-lmx9x,硬件版本hardware-compatibility,stable和之中的main分支,以及images、bootenv、scripts参数

系统内已经安装了自启动服务,在系统开机后将会自行执行,输入以下命令查看服务具体内容:

[Unit]Description=SWUpdate daemonAfter=swupdate.service
[Service]ExecStart=/etc/myir-swupdate.shKillMode=mixed
[Install]WantedBy=multi-user.target

该服务将会自动执行/etc/myir-swupdate.sh脚本,查看该脚本内容:

#!/bin/sh. /etc/board_part_info.confecho EMMC_DEV ${EMMC_DEV}echo SD_DEV ${SD_DEV}echo ROOTFS_A_PART=${ROOTFS_A_PART}echo ROOTFS_B_PART=${ROOTFS_B_PART}current_rootfs=""check_root_part_cmdline(){ cmdline=`cat /proc/cmdline` for i in $cmdline do if [[ `echo $i | grep "root="` != "" ]];then current_rootfs=${i##*/} fi done}check_need_repalce_env(){ echo ${current_rootfs} result=$(echo ${current_rootfs} | grep "mmcblk") if [[ ${result} != "" ]];then bootdev=${current_rootfs%p*} #echo bootdev ${bootdev} if [[ `grep ${bootdev} /etc/fw_env.config` == "" ]];then sed -i "s/mmcblk[0-9]*/${bootdev}/g" /etc/fw_env.config fi fi}function_on_different_part(){ case ${current_rootfs:0-1} in ${ROOTFS_A_PART}) echo "rootfs A part" fw_setenv swu_mode 0 fw_setenv boot_limit 3 fw_setenv mmcbootpart ${ROOTFS_A_PART} fw_setenv mmcbootpart_back ${ROOTFS_B_PART} echo "SWUPDATE_ARGS="-v -d -uhttp://192.168.1.20/MYD-LMX9X-IMAGE/myd-lmx9x.swu -e stable,main"" > /etc/myir-swupdate.cfg ;; ${ROOTFS_B_PART}) echo "rootfs B part" fw_setenv swu_mode 0 fw_setenv boot_limit 3 fw_setenv mmcbootpart ${ROOTFS_B_PART} fw_setenv mmcbootpart_back ${ROOTFS_A_PART} echo "SWUPDATE_ARGS="-v -d -uhttp://192.168.1.20/MYD-LMX9X-IMAGE/myd-lmx9x.swu -e stable,alt"" > /etc/myir-swupdate.cfg ;; *) echo "con not distinguish part" exit 1 esac}check_root_part_cmdlinecheck_need_repalce_envfunction_on_different_part

该脚本中,就会执行上一章节提到的env变量默认设置,以及会将修改/etc/fw_env.config文件,配置正确的fw_env工具可以使用的配置文件,fw_env其中包含了fw_printenv和fw_setenv可以再文件系统中修改uboot的env环境变量。

该脚本最后一部分将会把swupdate需要的配置信息添加到/etc/myir-swupdate.cfg中:

root@myd-lmx9x:~# cat /etc/myir-swupdate.cfgSWUPDATE_ARGS="-v -d -uhttp://192.168.1.20/MYD-LMX9X-IMAGE/myd-lmx9x.swu -e stable,main"

其中包含了http服务器的具体ip,和swu文件的路径,已经sw-description中的分支选择。

4.操作步骤

4.1.远程升级

要实现OTA功能,至少需要两块设备,分别是服务器与客户端。服务器只有一个,就是MYD-LMX9X(本文以下皆用MYD-LMX9X开发板做为示例)。开发板通过串口与PC机连接,或者也可以通过ssh的方式远程访问开发板的串口,这个步骤可以阅读快速入门指南和评估指南了解具体信息。然后将需要OTA需要的swu文件存放于PC主机,然后开发板执行对应命令即可完成OTA升级,接下来详细介绍操作步骤和注意事项。

4.1.1.制作swu文件

首先通过MYD-LMX9X的米尔电子下载中心链接或者百度网盘共享链接获取OTA升级文件制作工具:ota-generate_swu.tar.gz。

1)解压工具

在Ubuntu主机下创建工作目录并解压该工具,解压完成后进入目录:

$: mkdir ~/swupdate$: cp /ota-generate_swu.tar.gz ~/swupdate/ota-generate_swu.tar.gz# 此处的请根据实际情况填写文件所在路径$: cd ~/swupdate$: tar xvf ota-generate_swu.tar.gz$: ls -latotal 24drwxrwxr-x 3 beste beste 4096 4月 9 17:52 .drwxrwx--- 55 beste beste 4096 4月 9 17:52 ..-rw-rw-r-- 1 beste beste 10240 4月 9 17:52 ota-generate_swu.tar.gzdrwxrwxr-x 2 beste beste 4096 4月 9 17:51 swupdate-ota$: cd swupdate-ota$: lsgenerate_swu.sh readme.txt sw-description update.sh

2)sw-description说明

swupdate 采用cpio的方式进行归档,该文件是描述文件,默认名称为sw-description。该文件描述了升级包归档文件中的文件信息和升级信息。sw-description内容如下:

software ={ version = "1.1"; description = "Firmware update for myd-lmx9x" myd-lmx9x = { hardware-compatibility: [ "1.0", "1.1" ]; stable: { main: { images:( { filename = "myir-image-core-myd-lmx9x.ext4"; device = "/dev/mmcblk0p3"; filesystem = "ext4" ; } ); bootenv:( { name="mmcbootpart"; value="3"; }, { name="mmcbootpart_back"; value="2"; } ); scripts: ( { filename = "update.sh"; type = "shellscript"; } ); }; alt: { images:( { filename = "myir-image-full-mys-8mmx.ext4.gz"; compressed = "zlib"; device = "/dev/mmcblk0p2"; } ); bootenv:( { name="mmcbootpart"; value="2"; }, { name="mmcbootpart_back"; value="3"; } ); scripts: ( { filename = "update.sh"; type = "shellscript"; } ); }; }; };}

该文件中的内容中,部分关键字将会在后续的开发板中进行update时使用到,这里可以先打开MYD-LMX9X开发板的串口查看下稍后会使用到的脚本,开发板eMMC启动上电并打开串口:

root@myd-lmx9x:~# ls /etc/myir-swupdate*/etc/myir-swupdate.cfg /etc/myir-swupdate.sh

可以看到swupdate使用到的脚本和cfg配置文件,打开配置文件:

root@myd-lmx9x:~# cat /etc/myir-swupdate.cfgSWUPDATE_ARGS="-v -d -uhttp://192.168.1.20/MYD-LMX9X-IMAGE/myd-lmx9x.swu -e stable,main"

如果没有此配置文件,请先执行如下脚本,关于该脚本的具体描述,会在后续的3.1.2章节讲述:

root@myd-lmx9x:~# /etc/myir-swupdate.shEMMC_DEV 2SD_DEV 1ROOTFS_A_PART=2ROOTFS_B_PART=3mmcblk0p2rootfs B part

可以看到配置的swu文件路径为http://192.168.1.20/MYD-LMX9X-IMAGE/myd-lmx9x.swu,其中选择sw-description说明文件中stable的main分支,可以对比参考刚才sw-description中的内容阅读理解。

其中选择main分支下的内容则将把myir-image-core-myd-lmx9x.ext4文件系统烧录到/dev/mmcblk0p3也就是开发板eMMC下的第三个分区,其中mmcblk0p1第一个分区为内核文件和设备树文件存放分区,mmcblk0p2和mmcblk0p3是文件系统分区A和文件系统分区B。

3)构建swu文件

从02_Image或者Yocto构建编译获取到myir-image-core-myd-lmx9x.ext4,并将其放到swupdate-ota目录下

$: cp /myir-image-core-myd-lmx9x.ext4 ~/swupdate/swupdate-ota# 此处的请根据实际情况填写文件所在路径$: lsgenerate_swu.sh myir-image-core-myd-lmx9x.ext4 readme.txt sw-description update.sh

然后将新添加的文件加入generate_swu.sh脚本:

#!/bin/bash
CONTAINER_VER="1.1"PRODUCT_NAME="myd-lmx9x"FILES="sw-description myir-image-core-myd-lmx9x.ext4 update.sh"
#openssl dgst -sha256 -sign swupdate-priv.pem sw-description > sw-description.sig
for i in $FILES;do echo $i;done | cpio -ov -H crc > ${PRODUCT_NAME}_${CONTAINER_VER}.swu

最后执行generate_swu.sh脚本文件:

$: ./generate_swu.shsw-descriptionmyir-image-core-myd-lmx9x.ext4update.sh2362324 blocks

可以看到需要的swu文件myd-lmx9x_1.1.swu构建完成。

$: lsgenerate_swu.sh myd-lmx9x_1.1.swu myir-image-core-myd-lmx9x.ext4 readme.txt sw-description update.sh

在执行接下来的步骤之前,要确保http服务器上可以正常访问到myd-lmx9x_1.1.swu文件,如下图所示:

9e39006e-1897-11ef-bebc-92fbcf53809c.png图4-1. http服务器

保证开发板和搭建了http服务器ubuntu主机系统处于同一个网段下,如本文示例,开发板的ip为192.168.1.56,ubuntu主机ip为192.168.1.20,并且确保互相能够ping通。

# 查看ubuntu主机 ip$ ifconfigenp0s3: flags=4163 mtu 1500 inet 192.168.1.20 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80:d51c270c prefixlen 64 scopeid 0x20 ether 08276a:48 txqueuelen 1000 (Ethernet) RX packets 1132717 bytes 1333243911 (1.3 GB) RX errors 0 dropped 6181 overruns 0 frame 0 TX packets 64347 bytes 19130410 (19.1 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0# 查看MYD-LMX9X开发板 iproot@myd-lmx9x:~# ifconfig eth0eth0: flags=4163 mtu 1500 inet 192.168.1.56 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80:54ff88fb prefixlen 64 scopeid 0x20 ether 465488:fb txqueuelen 1000 (Ethernet) RX packets 10516 bytes 989859 (966.6 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 589 bytes 46288 (45.2 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0# 尝试Ping ubuntu主机root@myd-lmx9x:~# ping 192.168.1.20PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.64 bytes from 192.168.1.20: icmp_seq=1 ttl=63 time=60.2 ms64 bytes from 192.168.1.20: icmp_seq=2 ttl=63 time=5.73 ms64 bytes from 192.168.1.20: icmp_seq=3 ttl=63 time=4.94 ms64 bytes from 192.168.1.20: icmp_seq=4 ttl=63 time=2.95 ms^C--- 192.168.1.20 ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 3004msrtt min/avg/max/mdev = 2.948/18.442/60.151/24.101 ms

4.1.2.更新系统

完成上面的步骤后,开机进入文件系统,修改/etc/swupdate.sh,将网络地址修改为实际情况下的ip以及对应的文件路径:

echo "SWUPDATE_ARGS="-v -d -uhttp://192.168.1.20/swupdate-ota/myd-lmx9x_1.1.swu -e stable,main"" > /etc/myir-swupdate.cfg

修改完成后保存,重启开发板后将会自动更新该swu文件。

9e3ccb0e-1897-11ef-bebc-92fbcf53809c.png

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • NXP
    NXP
    +关注

    关注

    60

    文章

    1229

    浏览量

    178659
  • 开发板
    +关注

    关注

    25

    文章

    4574

    浏览量

    94975
  • 米尔电子
    +关注

    关注

    0

    文章

    73

    浏览量

    375
收藏 人收藏

    评论

    相关推荐

    米尔NXP i.MX 93开发板的Qt开发指南

    1.概述Qt是一个跨平台的图形应用开发框架,被应用在不同尺寸设备和平台上,同时提供不同版权版本供用户选择。米尔NXPi.MX93开发板(MYD-LMX9X
    的头像 发表于 06-07 08:01 1038次阅读
    <b class='flag-5'>米尔</b><b class='flag-5'>NXP</b> i.MX <b class='flag-5'>93</b><b class='flag-5'>开发板</b>的Qt<b class='flag-5'>开发</b>指南

    米尔NXP i.MX 93开发板的Qt开发指南

    1. 概述Qt 是一个跨平台的图形应用开发框架,被应用在不同尺寸设备和平台上,同时提供不同版权版本供用户选择。米尔 NXP i.MX 93 开发板
    发表于 06-07 20:45

    【技术分享】NXP iMX8M Mini芯片应用处理器开发板专题

    【技术分享】NXP iMX8M Mini芯片应用处理器开发板专题 应用案例1. 迅为iMX8M Mini开发板硬件接口原理分析 迅为I.MX
    发表于 12-28 11:27

    用笔记-iMX8MP开发板在UUU烧写时卡在99%

    用笔记-iMX8MP开发板在UUU烧写时卡在99%近期查看飞凌嵌入式技术支持部门问题反馈列表时,发现部分客户反馈iMX8MP产品用UUU烧写时卡在99%处,并且问题反馈用的都是同一个
    发表于 03-30 10:48

    米尔科技NXP LPC1857 LPC1850 Cortex-M3开发板概述

    MYD-LPC185X系列开发板是深圳市米尔科技有限公司推出的基于NXP(恩智浦)LPC185X系列处理器(Cortex-M3内核)开发板
    的头像 发表于 11-04 14:46 3858次阅读
     <b class='flag-5'>米尔</b>科技<b class='flag-5'>NXP</b> LPC1857 LPC1850 Cortex-M3<b class='flag-5'>开发板</b>概述

    NXP iMX6ULL开发板的WIFI接口功能测试

    一、 iMX6 ULL开发板 WIFI 功能测试 WiFi支持: 模块 支持 RTL8188EUS WiFi RTL8723BU WiFi RTL8723DU WiFi 1、 USB WIFI
    的头像 发表于 05-05 17:02 1989次阅读

    NXP iMX8MP开发板的试用体验

    NXP iMX8MP开发板试用体验
    的头像 发表于 06-06 10:42 1885次阅读

    金秋回馈100%中奖,买米尔NXP系列开发板

    各位筒子们!金秋好时节,米尔NXP系列开发板搞活动啦~~超多福利优惠都给你们妥妥地安排上给你的秋天加点猛料!一直以来,米尔NXP都保持深度
    的头像 发表于 09-15 08:01 346次阅读
    金秋回馈100%中奖,买<b class='flag-5'>米尔</b><b class='flag-5'>NXP</b>系列<b class='flag-5'>开发板</b>

    米尔NXP系列开发板优惠大放送

    一直以来,米尔NXP都保持深度合作。米尔推出基于NXP系列的低、中、高端核心板开发板,为客户提供不同功耗、可扩展性、计算性能、安全性的产品
    的头像 发表于 09-16 14:40 381次阅读
    <b class='flag-5'>米尔</b><b class='flag-5'>NXP</b>系列<b class='flag-5'>开发板</b>优惠大放送

    芯旺微KF8F3132开发板用笔记之Flash读写

    芯旺微KF8F系列单片机KF8F3132开发板用笔记之Flash读写
    发表于 10-19 16:21 1次下载

    芯旺微KF8F3132开发板用笔记之AMP模块

    芯旺微KF8F系列单片机KF8F3132开发板用笔记之AMP模块
    发表于 10-19 16:21 0次下载

    芯旺微KF8F3132开发板用笔记之PWM5

    芯旺微KF8F系列单片机KF8F3132开发板用笔记之PWM5
    发表于 10-19 16:21 0次下载

    免费!NXP i.MX 93开发板有奖试用

    米尔NXP合作发布的新品基于NXPi.MX93应用处理器的MYD-LMX9X开发板免费试用活动来啦~~米尔提供了2块价值678
    的头像 发表于 05-23 08:01 161次阅读
    免费!<b class='flag-5'>NXP</b> i.MX <b class='flag-5'>93</b><b class='flag-5'>开发板</b>有奖试用

    端午好礼丨米尔喊你抽奖啦!NXP i.MX开发板、吸尘器、定制背包等你带回家

    喜迎端午节好礼相送!米尔联合NXP福利送~免费赠送i.MX开发板、吸尘器、定制背包、京东购物卡快来参与,你就是锦鲤~一等奖(3名)米尔基于NXPi.MX
    的头像 发表于 06-07 08:01 126次阅读
    端午好礼丨<b class='flag-5'>米尔</b>喊你抽奖啦!<b class='flag-5'>NXP</b> i.MX<b class='flag-5'>开发板</b>、吸尘器、定制背包等你带回家

    点击参与米尔NXP i.MX 93开发板有奖试用

    米尔NXP合作发布的新品基于NXPi.MX93应用处理器的MYD-LMX9X开发板免费试用活动来啦~~米尔提供了3块价值678元的MYD-
    的头像 发表于 06-13 08:02 67次阅读
    点击参与<b class='flag-5'>米尔</b><b class='flag-5'>NXP</b> i.MX <b class='flag-5'>93</b><b class='flag-5'>开发板</b>有奖试用