尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

i.MX8M Mini/Nano实战:从BSP到设备树的嵌入式Linux量产级开发指南

i.MX8M Mini/Nano实战:从BSP到设备树的嵌入式Linux量产级开发指南 1. 为什么i.MX8M系列成了嵌入式Linux开发的“标准答案”之一做嵌入式Linux开发这些年我评估过不少MPU平台从早期的i.MX6系列到后来的全志、瑞芯微、TI各有各的脾气。但如果你问我在“Linux友好度”和“量产成熟度”之间平衡得最好的方案是什么我大概率会推荐i.MX8M系列。尤其是Mini和Nano这两个型号几乎成了这两年工控、边缘计算、HMI和IoT网关项目的首选。先说个背景。i.MX8M系列是NXP在2018年前后陆续推出的主打多媒体和边缘计算场景。整个家族从高到低分为QuadMax、QuadXPlus、Quad、Dual、Mini和Nano。今天要聊的Mini和Nano定位是“性价比最高的Linux量产级SoMSystem on Module系统级模块”。它们不像Quad那样堆四颗Cortex-A53但该有的接口和多媒体能力一个不少而且功耗控制比大哥们好太多。那“Linux-Friendly”到底体现在哪我觉得可以从三个方面来理解第一BSPBoard Support Package板级支持包成熟度极高。NXP官方维护的Linux内核分支基于kernel 5.15或6.1视Yocto版本而定对这两款芯片支持得非常完善从电源管理到GPU驱动再到VPU编解码基本开箱即用。第二生态系统完善。Yocto、Buildroot、Debian、Ubuntu甚至Android都有官方或社区维护的适配方案。第三文档和社区资源丰富。NXP的应用笔记、参考手册、官方Wiki加上这几年国内做核心板的厂商也不少遇到问题基本能搜到答案——这一点对项目排期来说比芯片本身的性能更重要。用一句话总结我的感受i.MX8M Mini和Nano是那种“你不需要成为内核专家也能把Linux系统跑起来并量产”的平台。这不代表它没有坑但至少坑都是“已知的坑”而不是那种需要自己拿头撞墙才能发现的坑。我手上这块板子是某国产核心板厂商做的i.MX8M Mini方案主频1.8GHz这是官方标称的最高主频配了2GB LPDDR4和16GB eMMC跑的是Yocto构建的Linux 5.15系统。接下来我会围绕这个平台把从硬件选型到系统适配再到驱动调试的完整链路拆开讲讲。2. 深入拆解i.MX8M Mini与Nano的硬件底子2.1 两者在芯片规格上的核心区别Mini和Nano虽然名字上像“大小号”关系但它们在硬件规格上其实有不小的差异。搞清楚这些差异才能做对选型。我列个表方便直接对照。特性i.MX8M Minii.MX8M NanoCPU核心4x Cortex-A53 1x Cortex-M44x Cortex-A53 1x Cortex-M4CPU主频最高1.8GHz最高1.5GHzGPUGC NanoUltra 3D GC400 2DGC7000UL 3D GC400 2DVPU编解码支持1080p H.265/H.264编解不支持VPUMIPI-DSI1路最高1080p1路最高1080pMIPI-CSI1路1路部分型号支持2路PCIe1路PCIe 2.0不支持PCIe以太网1路10/100/1000M1路10/100/1000MCAN-FD2路2路典型功耗约2.5W整机约1.5W整机Mini最大的优势是带VPU硬件编解码单元在需要视频处理的场景里非常吃香。Nano砍掉了VPU但保留了GPU和大部分接口功耗更低成本也更友好适合不需要视频编解码的纯HMI、工业控制或网关类应用。2.2 核心板设计的几个关键点电源、DDR、启动方式如果是自己画核心板我强烈建议不要从零开始直接买第三方的SoM模块或者参考NXP官方的评估板原理图。原因很简单DDR布线的等长控制、电源时序、阻抗匹配这些不是看一眼Datasheet就能搞定的需要高速信号仿真和多次打板实测的积累。说说电源。i.MX8M系列的电源域划分很细VDD_SOC、VDD_ARM、VDD_GPU、VDD_DRAM、NVCC_*等等。上电时序有严格的要求比如NVCC_SD要先于VDD_SOC稳定否则可能导致IO口闩锁效应轻则系统不稳定重则烧毁芯片。如果你用的是第三方核心板这些都已经调好了你只需要关注载板上的电源设计。DDR方面Mini和Nano都支持LPDDR4和DDR4。Nano还支持DDR3L部分型号。实际项目里LPDDR4用得最多因为它体积小、功耗低适合核心板这种紧凑布局。容量从512MB到4GB都有但我的经验是跑完整的Linux系统带GPU和AI框架最少2GB起步否则内存不够时OOM Killer会给你带来非常痛苦的排障经历。启动方式默认是eMMC通过Boot ROM读取Boot Configuration Pins也就是BOOT_MODE[3:0]引脚的电平状态来决定。调试阶段建议把BOOT_MODE拨到USB下载模式即串行下载模式这样可以通过UUU工具NXP官方烧录工具把镜像直接烧进eMMC不用反复插拔SD卡。2.3 为什么选择Yocto而不是Buildroot系统构建工具链的选择直接决定后期维护的幸福感。嵌入式Linux的镜像构建主流就两个Yocto和Buildroot。Buildroot简单、快、适合个人开发者或小团队快速出活Yocto学习曲线陡峭、构建时间长但胜在可定制性和生态规范性。我的建议是如果是做量产产品老老实实学Yocto。原因有三点第一Yocto的层Layer机制非常好用NXP官方维护的meta-freescale、meta-fsl-bsp-release等层会跟随内核版本长期更新安全补丁也能及时同步。第二Yocto的Recipe机制能让你精确控制rootfs里有哪些包最终产出的镜像体积小、攻击面也小这对工控和医疗设备尤为重要。第三Yocto的构建是可复现的——同样的配置在不同机器上构建出来的镜像hash一致只要把所有源码和依赖都锁住这在过认证时非常有用。当然Yocto也不是没有缺点。首次构建要拉取大量源码耗时几个小时磁盘占用轻松突破100GB。我的经验是CI服务器上挂一台高性能机器专门做构建本地只改配置不重复全量构建。3. 系统跑起来之后的三个“拦路虎”GPU、显示和WiFi/BT适配3.1 GPU驱动别小看内核配置里的几个Kconfig很多人拿到板子第一件事就是跑glmark2测GPU性能结果发现渲染不出来或者跑出来的分数惨不忍睹。这时候十有八九是内核配置里GPU相关的选项没开全。i.MX8M Mini和Nano的GPU是VivanteVeriSilicon的IP核内核驱动走的是DRMDirect Rendering Manager框架。你需要确保内核配置里打开以下选项CONFIG_DRM_IMXCONFIG_DRM_IMX_CDN_DP仅部分板型需要CONFIG_DRM_IMX_LCDIF_MUXCONFIG_DRM_VIVANTENXP分支上是这个名字主线内核里可能不同CONFIG_DRM_FSL_IMX还要在Device Tree里正确声明GPU节点并把对应的firmware文件放到/lib/firmware里。Nano的GPU是GC7000ULMini的GPU是GC NanoUltra。两者的firmware文件不同千万别混用否则驱动加载时会报“Firmware: Failed to load”错误GPU节点直接挂不起来。如果你用的是Yocto可以在local.conf里加上IMAGE_INSTALL_append libgpu这是NXP提供的用户态GPU库包包含了OpenGL ES、OpenVG、G2D等运行时库。装完之后记得确认一下/dev/dri/下面有没有card0和设备节点。提示如果你跑的是NXP官方BSPGPU的用户态库必须和内核版本严格配套。跨大版本混用比如把5.10的libgpu放到5.15的内核上轻则运行报错重则整个X/Wayland起不来。升级内核时一定同步升级用户态库。3.2 显示链路HMI开发中的分辨率与图层配置Mini和Nano都只有一个MIPI-DSI接口最高支持1080p60fps。如果做双屏异显就得走外部HDMI转接芯片比如LT8912扩展。这里有个常见误区很多开发者以为DRM框架下接上屏幕就能自动识别分辨率但实际上MIPI-DSI的时序参数全靠Device Tree里配置的panel节点。一个典型的panel节点配置包括compatible属性对应具体的面板驱动backlight背光PWM的GPIO和PWM通道分辨率、时序hactive/vactive/hbackPorch等参数设备树里DSI设备的时钟频率如果时序参数填错屏幕会闪、花屏或者完全没显示。有时候从厂商那拿到的屏幕规格书里只给了“典型值”但实际调试还要根据面板的blanking参数微调。我的经验是先用简单的测试图片输出确认屏幕有信号了再调颜色格式和图层合成。别一开始就上复杂的GUI应用要不然你看不出问题是出在LCD时序还是GPU合成。图层方面i.MX8M Mini和Nano的Display Controller支持多图层叠加但并不是无限图层。通常是一层作为主界面带alpha一层用作视频或相机预览。如果做带透明效果的界面要注意图层合成的带宽和内存占用。实测下来在1080p分辨率下跑WestonWayland compositorCPU占用率能控制在5%以下GPU占用也就30%左右流畅度完全够用。3.3 WiFi/BT模组适配从Device Tree到固件加载的完整路径用核心板做产品无线模组基本是标配。但WiFi/BT这块恰恰是很多自学的开发者最容易卡住的地方。原因很简单WiFi/BT芯片厂商的Linux驱动和固件质量参差不齐。我用的核心板默认焊了一颗Realtek的WiFi/BT芯片具体型号是RTL8822CS。它在Linux内核里的驱动是rtl8822cs属于staging目录下的驱动质量嘛……能用但偶尔会有断连或蓝牙音频卡顿的问题。驱动加载需要三样东西驱动模块、固件文件、Device Tree节点。Device Tree节点大致长这样sdio { status okay; bus-width 4; non-removable; cap-power-off-card; mmc-pwrseq pwrseq_sdio; vmmc-supply reg_3v3; vqmmc-supply reg_1v8; pinctrl-names default; pinctrl-0 pinctrl_sdio; };固件文件放在/lib/firmware/rtl_bt/和/lib/firmware/rtlwifi/目录下分别对应BT和WiFi。如果固件路径不对dmesg里会明确报错。另外WiFi芯片的时隙、功耗策略也需要在驱动里配置否则会出现待机后无法唤醒WiFi的现象。如果你既要保证无线稳定又不想和驱动纠缠我的建议是选型时优先考虑主流厂商的模组比如Murata的模块搭配Cypress/Infineon芯片或者QCA高通系列的模组。它们在主线内核里的驱动成熟度远高于杂牌芯片遇到问题也更容易在社区里搜到答案。4. 实战从SDK到第一个GUI应用跑通的全部流程4.1 获取代码和工具链在整个开发链路里最耗时但不难的一步是配置Yocto环境并首次构建。先放结论如果你是用第三方核心板很多厂商会直接提供构建好的BSP、Yocto Layer或者预编译镜像。优先用厂商提供的BSP在此基础上做定制而不是自己从官方拉一份从头开始配置。不为别的就因为厂商已经把电源配置、存储初始化、显示时序、无线模组适配等板级改动都做好了你自己从头搞光调设备树就要一两周。下面是我个人比较推荐的“实用派”流程从厂商官网下载BSP发布包通常是一个压缩包解压后包含预编译的u-boot镜像内核源码和内核配置文件rootfs镜像可能是Yocto构建的也可能是Ubuntu Base把u-boot烧到eMMC或SD卡里通过串口终端进入u-boot命令行确认板子能正常启动。用厂商的Linux内核源码按自己的需求修改设备树比如改网口、GPIO、背光引脚编译生成新的dtb。制作SD卡启动盘把dtb、zImage、rootfs拷贝到对应分区从SD卡启动系统。如果你非得从零构建Yocto那我给你一个最小可玩步骤$ git clone -b gatesgarth git://git.yoctoproject.org/poky.git $ cd poky $ git clone -b gatesgarth git://git.yoctoproject.org/meta-freescale.git $ git clone -b gatesgarth git://git.yoctoproject.org/meta-freescale-distro.git $ source oe-init-build-env build $ bitbake-layers add-layer ../meta-freescale $ bitbake-layers add-layer ../meta-freescale-distro $ echo MACHINE imx8mmevk conf/local.conf $ bitbake core-image-base这个流程跑完大概需要2~3小时取决于网速和CPU性能构建产物在tmp/deploy/images/imx8mmevk/目录下。4.2 用Device Tree点亮板载LED和按键很多人对Device Tree有恐惧心理觉得它复杂。其实Device Tree就是描述硬件拓扑的“说明书”让内核知道某个GPIO对应哪颗LED、哪个按键接在哪个中断上。很多调试工作靠的就是一遍遍改Device Tree。我们以点亮板载LED为例找到核心板说明书里LED接的GPIO引脚比如GPIO1_IO13。在设备树里新增一个gpio-leds节点leds { compatible gpio-leds; pinctrl-names default; pinctrl-0 pinctrl_led; status-led { label status; gpios gpio1 13 GPIO_ACTIVE_LOW; default-state on; linux,default-trigger heartbeat; }; };对应配置pinctrl_led节点把GPIO1_IO13复用为GPIO功能pinctrl_led: ledsgrp { fsl,pins MX8MM_IOMUXC_GPIO1_IO13_GPIO1_IO13 0x19 ; };重新编译dtb并烧录重启后在/sys/class/leds/目录下就能看到status这个LED设备通过echo命令即可控制亮灭echo 0 /sys/class/leds/status/brightness echo 255 /sys/class/leds/status/brightness这里有个小坑不同核心板的GPIO号对应关系可能不同。同样是GPIO1_IO13在i.MX8M Mini的iomuxc宏定义里和Nano可能不一样实际上Nano用的还是different iomuxc base。所以改Device Tree之前建议用/sys/kernel/debug/gpio接口先看看Linux给每个GPIO分配的编号免得盲改。4.3 部署Qt应用显示、输入、性能调优GUI应用部署是嵌入式Linux开发的收尾环节却也是问题高发区。最典型的三个问题界面不显示、触摸没响应、运行卡顿。界面不显示的问题多半出在环境变量没设置好。如果跑X11应用需要设置DISPLAY:0如果跑Wayland需要设置WAYLAND_DISPLAYwayland-0和XDG_RUNTIME_DIR/run/user/0。如果连weston都没启动那应用怎么着都显示不出来。调试顺序是先确认weston(X)进程在跑再用weston-terminal这类自带终端验证合成器正常最后才启动你的Qt应用。触摸没响应一般是input event设备没正确加载或者Qt的QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS没指定到正确的设备节点。可以用cat /proc/bus/input/devices确认触摸控制器注册为/dev/input/eventX。然后在Qt的环境变量里指过去比如export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS/dev/input/event2如果你的触摸屏是电容屏通常还需要校准电阻屏则要用tslib做校准。Qt5和Qt6对tslib的支持程度有所不同Qt6上更推荐直接用evdev不用tslib。性能调优方面我强烈建议监控两个指标CPU占用率和GPU内存带宽。可以用top看CPU用gpu-top有些BSP带看GPU占用。如果GPU功耗高、功耗下不来检查一下Weston的渲染模式是不是跑了软件渲染llvmpipe那会吃CPU吃到怀疑人生。确保weston.ini里配置了GBM后端并启用了use-gpu-renderertrue。5. 从“能跑”到“能量产”稳定性测试与功耗优化的真实心得5.1 长时间运行测试这5个项必测很多开发者跑通demo就以为自己完成了其实真正的痛苦从量产后才刚开始。我在过往项目里吃过不少亏总结下来稳定性测试至少要做五个方向第一长时间重启测试。写一个脚本循环执行reboot连续跑24小时观察是否有偶发的启动失败、eMMC挂载失败或者WiFi初始化失败。i.MX8M系列的启动速度本身很快从u-boot到登录shell大概15秒左右所以做300次循环也不用太久。如果出现启动失败优先看电源时序——很多“偶尔启动失败”的本质是某路电源晚了几毫秒芯片没来得及正确复位。第二CPU超负荷测试。跑stress-ng或sysbench让CPU满载运行至少8小时同时监控核心温度。i.MX8M Mini没有主动散热的话满载温度很容易飙到80℃以上。虽然不是立即坏但长期高温会导致热漂移和eMMC寿命缩短。我见过一个客户的产品外壳设计完全密闭CPU满载时核心温度90度跑了一个月后eMMC读写就开始报错。这事必须有散热设计兜底。第三内存压力测试。用memtester或stress-ng --vm压满内存持续4小时以上。如果出现OOM或者进程被kill要么是内存不够要么是LPDDR4的时序配置有问题这在自制板卡上特别常见。跑DDR测试时最好在dmesg里同时观察是否有ECC错误如果有ECC颗粒。第四网络稳定性测试。如果你是做IoT网关用iperf3打流量持续测12小时以上关注是否有断流、重传率过高、延迟抖动。i.MX8M系列的网卡控制器本身没太大问题但驱动和PHY芯片的匹配需要调某些PHY芯片如果不加tx-fifo-depth等参数极限流量下会丢包。第五断掉电源测试。这个最容易忽略。模拟产品在用户家里被直接拔电反复多次观察系统文件系统是否有损坏eMMC上的数据是否完整回读是否有异常。eMMC掉电容易丢数据但很多情况可以通过在Yocto里配置ubifs或ext4的auto_da_alloc选项来降低风险。另外建议把重要的配置数据存到独立分区使用mount -o sync挂载避免因为突发断电把配置弄丢。5.2 功耗优化不只是改设备树功耗是嵌入式产品的核心竞争力之一尤其是电池供电的便携设备。i.MX8M Nano能成为便携设备的宠儿核心就是它的功耗控制。但“能”和“实际做到”是两回事你必须主动做功耗优化。i.MX8M系列的功耗管理主要靠cpuidle和cpufreq。Linux内核默认的cpuidle驱动已经适配了C1/C2低功耗状态但默认的cpufreq governor是schedutil频点切换不够激进。在电池场景下可以切到powersave模式把CPU锁在最低频点减少不必要的性能浪费。在交互式场景下又要兼顾响应速度建议还是用schedutil但把energy_aware调度打开CONFIG_SCHED_ENERGY_AWAREy。实际功耗测试数据i.MX8M Nano在静态待机屏幕熄灭、WiFi关、CPU空闲下整板电流可以做到约150mA5V输入也就是0.75W左右。如果只是跑一个简单的HMI界面功耗在1.2W上下。作为对比i.MX8M Mini跑同样的界面大约1.8W。如果设备对重量和电池容量敏感Nano省下的这0.6W可以多撑不少时间。另外别忘了关闭用不到的外设电源域。在设备树里把不用的usdhc1另一张SD卡槽、uart4、sai3等节点设为status disabled。不关的后果就是外设时钟一直开启白白多耗几十毫瓦。如果对实时性要求不高还可以考虑加rtc-helper让系统定时进入suspend状态定期唤醒上报数据。5.3 安全启动和镜像签名量产产品绕不开的课题最后聊聊OTPOne-Time Programmable一次性可编程存储器和安全启动。很多人觉得这东西是大厂或者军品才需要其实现在信息安全的门槛越来越高民用产品过认证也经常被问到安全启动能力。i.MX8M系列支持HABHigh Assurance Boot安全启动。原理是芯片内置的Boot ROM加载u-boot之前先用RSA公钥验证u-boot的签名。签名有效才继续执行否则就进入恢复模式。这样能防止rootfs或内核被篡改后依然能启动。实际烧录流程大致是生成RSA密钥对私钥保存在安全环境里公钥烧进芯片eFuse中。对u-boot二进制做签名生成带签名的镜像.signed文件。通过UUU工具把签名后的u-boot烧录到eMMC的启动分区。首次启动时Boot ROM读取eFuse里的公钥校验u-boot签名校验通过后更新eFuse状态为“Closed”。HAB配置最麻烦的地方在于一旦eFuse烧进去了就不能改回Open状态。如果u-boot源码有改动密钥不匹配板子就变砖了只能通过串行下载模式或JTAG强制刷有些型号在Closed状态下直接锁死。所以建议在开发阶段用软件签名验证模式也就是不烧eFuse只做相关配置确认能验证通过的情况到了批量阶段严格走一遍Closed流程并且把密钥备份放在保险柜。我在实际项目里HAB相关的坑踩了不止一次。最惨的一次是客户临时改了u-boot配置把启动参数从SD卡改到eMMC但签名用的是旧的密钥文件并且已经烧进eFuse——结果一整批测试板全部变砖只能返厂重新烧写固件。所以我的经验是烧eFuse之前务必确认u-boot的配置变更尤其是启动顺序、显示参数等100%不会再有变动然后才执行Close操作。6. 选题之外的扩展思考Nano在AI和边缘场景下的新玩法写完上面的实战链路再补充一点我最近在折腾的方向也算给后来者指条路。i.MX8M Nano虽然没有内置NPU但它的GPUGC7000UL支持OpenCL 1.2。这意味着你可以用GPU跑一些轻量级AI推理比如用NCNN的OpenCL后端做物体检测或者用TensorFlow Lite的GPU delegate。实测下来在Nano上跑一个MobileNetV2分类模型每帧推理时间大约80~120ms取决于输入分辨率。这个性能对低功耗的电池设备来说已经足以做一些简单的智能交互了。如果你需要更强的AI算力i.MX8M Plus才是带NPU2.3 TOPS的选择但功耗也上去了。取舍逻辑很简单要极致功耗就上Nano加GPU推理要性能就上Plus。Mini夹在中间定位更偏向多媒体处理而非AI。还有一点很多老工程师在选型时容易忽略M4协处理器Cortex-M4是一个完全独立的核可以跑裸机程序或FreeRTOS。在Mini和Nano上M4可以用来做实时控制任务比如电机控制、数据采集、电源管理。这样A53核专注跑Linux应用实时性要求高的循环交给M4整个系统的确定性和可靠性都会好很多。NXP的官方包里有rpmsg框架示例可以快速搭起A53和M4之间的通信。我现在的板子就在实验这样一个架构A53跑Qt界面和网络服务M4跑一个2kHz的采集循环通过rpmsg把数据传给A53显示。目前跑了三天没出过问题。如果你有类似的场景强烈建议试试这套玩法。最后分享一个我在调这个板子时最深刻的体会嵌入式Linux不是“会跑Linux就行”而是要理解硬件和内核之间的那层关系——Device Tree、Boot ROM、电源管理、驱动模型每一层都有它存在的理由。i.MX8M Mini和Nano给了我一个很难得的平台它足够开放可以让你钻研到很底层它又足够成熟不至于让你在一堆硬件Bug里迷失方向。对想深入嵌入式Linux的开发者来说这个系列是目前性价比最高的“教材”之一。
返回列表