最近需要使用一个通信模组的SDK,其运行在嵌入式linux上,包括了设备树和内核的patch、驱动、用户态库和可执行程序等,文档中说明其适配了i.MX6QSABRESD(ARM32)。我知道市面上有非常多的iMX6的开发板,作为练习IoT正向开发的开始,我希望自己编译uboot、linux运行在板子上,然后探索其中的道理。同时也是为了在使用SDK的过程中,能更好的排错。我先后体验了四家公司的开发板,分别是:百问网、迅为、飞思卡尔、野火。本以为很容易,没想到的是,倘若是怀着探索实现原理心态去看一些的开发板教程,那真是如此的令人费解。所以本篇的选型,说的不是性能,而是在我踩坑的过程中,看到了谁家的开发板能让学习者对计算机看的更透,更清楚。
尝试
百问网
首先尝试是韦东山老师百问网的IMX6ULLMINI:
- 9-12v供电
- micro usb 串口
用这块板子的原因一是不明白,二是手里有:
- 开始尝试这个,大家就能看出来我这个空子纯外行,人家SDK适配的是i.MX6Q,而这块板子是i.MX6ULL
- 这块板子是因为鸿蒙买的:华为鸿蒙系统移植到imx6ull成功
虽然早就听闻过韦东山老师的大名,但还是第一次看他板子的相关资料,总体感觉并不是很好,但可以理解:
文档链接:https://pan.baidu.com/s/1OMX-3tFW2PUsRWdjjgCRzw 密码:oh4z
- 由于主要面向真的是纯新手,所以资料傻瓜化,很多步骤被封成了一个脚本,理解麻烦
- 由于嵌入式不同板子间的知识是有重叠的,所以产生了学习资料复用,看起来非常的乱套
- 由于经过多年的发展和积累,资料的维护和更新也比较乱套,导致资料非常多,但可能用不上
对于这张板子,测试直接编译uboot主线代码并烧录进SD卡是成功的,过程如下:
➜ git clone https://github.com/u-boot/u-boot.git
➜ sudo apt install -y gcc bison flex gcc-arm-linux-gnueabi libssl-dev
➜ cd u-boot/
➜ make mx6ull_14x14_evk_defconfig
➜ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
这里直接使用了ubuntu的apt安装的交叉编译工具,最终编译出的u-boot-dtb.imx即是uboot镜像。编译过程中需要解释的是:为什么要写mx6ull_14x14_evk_defconfig?还有没有别的?写别的行不行?
- 首先可以在文档的204页看到编译他们提供的uboot是此参数
- 此参数是在configs文件夹下的配置文件,如下,不同参数对应不同开发板,所以一般来说不能写别的
➜ ls -al ./configs/ | grep imx6ull
-rw-r--r-- 1 xuanxuan staff 2200 12 30 18:23 colibri-imx6ull-emmc_defconfig
-rw-r--r-- 1 xuanxuan staff 2710 12 30 18:23 colibri-imx6ull_defconfig
-rw-r--r-- 1 xuanxuan staff 1316 12 30 18:23 o4-imx6ull-nano_defconfig
-rw-r--r-- 1 xuanxuan staff 1744 12 30 18:23 seeed_npi_imx6ull_defconfig
➜ ls -al ./configs/ | grep mx6ull
-rw-r--r-- 1 xuanxuan staff 2200 12 30 18:23 colibri-imx6ull-emmc_defconfig
-rw-r--r-- 1 xuanxuan staff 2710 12 30 18:23 colibri-imx6ull_defconfig
-rw-r--r-- 1 xuanxuan staff 1361 12 30 18:23 mx6ull_14x14_evk_defconfig
-rw-r--r-- 1 xuanxuan staff 1333 12 30 18:23 mx6ull_14x14_evk_plugin_defconfig
-rw-r--r-- 1 xuanxuan staff 1316 12 30 18:23 o4-imx6ull-nano_defconfig
-rw-r--r-- 1 xuanxuan staff 1744 12 30 18:23 seeed_npi_imx6ull_defconfig
不用理会那些封装好的图形工具,直接用dd将u-boot-dtb.imx烧录到SD卡中,然后同步一下,确保写入到SD卡中:
➜ sudo dd if=u-boot-dtb.imx of=/dev/sdb seek=2
➜ sync
其中跳过两个扇区(0x400)是imx6的镜像标准:IMX_LINUX_USERS_GUIDE.pdf
最后将拨码开关从1-4分别设置为ON ON ON OFF,重新上电即可从SD卡启动,通过串口可见,成功启动到uboot shell:
U-Boot 2022.01-rc4-00030-gb3f84a939f (Dec 30 2021 - 02:26:02 -0800)
CPU: Freescale i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU: Industrial temperature grade (-40C to 105C) at 43C
Reset cause: POR
Model: Freescale i.MX6 UltraLiteLite 14x14 EVK Board
Board: MX6ULL 14x14 EVK
DRAM: 512 MiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... *** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: Could not get PHY for FEC1: addr 1
Could not get PHY for FEC1: addr 1
Get shared mii bus on ethernet@2188000
Could not get PHY for FEC1: addr 2
Get shared mii bus on ethernet@2188000
Could not get PHY for FEC1: addr 2
No ethernet found.
Hit any key to stop autoboot: 0
=>
=>
=>
之后也尝试了在这张板子上直接编译linux主线内核与buildroot文件系统,虽然有一些要改uboot启动参数的坑,但最后均成功启动。不过后来看到了其SDK适配的i.MX6Q,并且还在设备树上做了修改,我就知道用这张板子是不太可能直接跑通的,因为imx6q和imx6ull根本就是两个不同的SoC:
所以这张板子也就暂时玩到这了,其他参考:
- IMX6的U-boot.imx分析及sd卡烧录详解(dd命令写入)
- 100ASK-IMX6ULL开发板移值NXP官方UBOOT
- i.MX 6ULL研究笔记_硬件篇
- u-boot:移植u-boot-2021.01到正点原子imx6ull mini开发板
迅为
因为之前买过迅为的4412开发板,于是搜到了他们家的确有i.MX6Q开发板:
但这只能看出来是i.MX6Q,是不是i.MX6QSABRESD呢?于是搜到:
其中提到:yocto执行配置是MACHINE=imx6qsabresd。暂时不必去理会yocto是个啥,但看到配置和目标的确一致,那看起来很靠谱了,所以淘宝买了,版本是迅为四核商业级2G+16G:
文档链接:https://pan.baidu.com/s/1JCSz_J05aujdSJOfEKNf3w 密码:wxrd
- 12v供电
- 9针串口,需要转USB
更多的资料就不放了,买完进群会给百度网盘链接,资料类似百问网的,一堆魔改的代码和纯新手教学。同样是看uboot主线代码,本以为跟百问网的一样简单,但编译时却并没看到imx6qsabresd的配置文件:
➜ ls -al ./configs/ | grep imx6qs
➜ ls -al ./configs/ | grep mx6qs
-rw-r--r-- 1 xuanxuan staff 2224 12 30 18:23 mx6qsabrelite_defconfig
后来想到可能是飞思卡尔这张板子的配置并没有进入到uboot主线,于是找到:uboot-imx,可以通过网页上的tree标签来看到代码文件,但直接查看还是没有此配置,但如果查看lf_v2021.04此分支则能看到:
然后就是尝试用这个版本的uboot,git clone需要比较好的网速:
➜ sudo apt install -y gcc bison flex gcc-arm-linux-gnueabi libssl-dev
➜ git clone -b lf_v2021.04 https://source.codeaurora.org/external/imx/uboot-imx
➜ cd uboot-imx
➜ make mx6qsabresd_defconfig
➜ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
➜ sudo dd if=u-boot-dtb.imx of=/dev/sdb seek=2
➜ sync
拨码开关为1和7是ON,其余都是OFF,然后发现无法启动到uboot shell:
U-Boot 2021.04-dirty (Jan 01 2022 - 04:48:21 -0800)
CPU: i.MX6Q rev1.3 996 MHz (running at 792 MHz)
CPU: Extended Commercial temperature grade (-20C to 105C) at 29C
Reset cause: POR
Model: i.MX6 Quad SABRE Smart Device Board
DRAM: 1 GiB
PMIC: PFUZE100! DEV_ID=0xfffffffb REV_ID=0xfffffffb
write error to device: 4df782f0 register: 0x21!
write error to device: 4df782f0 register: 0x24!
write error to device: 4df782f0 register: 0x2f!
write error to device: 4df782f0 register: 0x32!
Not supported, id=11
initcall sequence 4efe3f28 failed at call 17804e89 (err=-22)
### ERROR ### Please RESET the board ###
根据PFUZE100信息排错,然后找到如下文章:
- i.mx6q u-boot2016.03移植笔记
- 基于IMX6Q的u-boot-2017.11的移植(1)->初步移植
- 基于IMX6Q的u-boot-2017.11的移植(2)->MMC移植
- 基于IMX6Q的u-boot-2017.11的移植(3)->Ethernet MAC (ENET)移植
- 迅为iMX6Q开发板:uboot-imx移植与编译
配合迅为给出的可启动的uboot源码,分析启动不了的原因主要是:
- PMIC(电源管理IC)与飞思卡尔官方板子不同
- 内存由官方板的1G升为2G
由此可见底层代码,设备树信息等不仅仅与SoC相关,还与开发板相关。通过这些移植文章也能看出来,底层适配这玩意还是需要点技术含量的,还要看懂板子上的电路是怎么与SoC接上的,反正我目前是看不太懂。
飞思卡尔
最后还是用官方的板子,google搜索imx6qsabresd,结果就是 RD-IMX6Q-SABRE 这张板子。因为没有淘宝京东,正经的渠道就是找中国的代理商购买,这很慢。因为比较着急,所以从咸鱼买了两块回来,每块2000元左右:
相关资料:SABRESDB_IMX6_QSG.pdf、IMX_LINUX_USERS_GUIDE.pdf 更多资料可在产品页面底部下载,需注册NXP账号
- 5v供电,一定注意,国内的圆口电源很多都是12v !!!
- micro usb 串口
- 大号SD卡,不是micro SD(TF)卡
➜ sudo apt install -y gcc bison flex gcc-arm-linux-gnueabi libssl-dev
➜ git clone -b lf_v2021.04 https://source.codeaurora.org/external/imx/uboot-imx
➜ cd uboot-imx
➜ make mx6qsabresd_defconfig
➜ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
➜ sudo dd if=u-boot-dtb.imx of=/dev/sdb seek=2
➜ sync
拨码开关为2和7是ON,其余都是OFF。官方电源是5v5a,国内一般没有这种规格的电源,淘宝可以买到思科的电源是这规格的,不过起uboot用5v2a的电源也启动成功,接电后别忘了打开SW3开关:
U-Boot 2021.04-dirty (Jan 01 2022 - 04:48:21 -0800)
CPU: i.MX6Q rev1.2 996 MHz (running at 792 MHz)
CPU: Automotive temperature grade (-40C to 125C) at 25C
Reset cause: POR
Model: i.MX6 Quad SABRE Smart Device Board
DRAM: 1 GiB
PMIC: PFUZE100! DEV_ID=0x10 REV_ID=0x11
MMC: FSL_SDHC: 1, FSL_SDHC: 2, FSL_SDHC: 3
Loading Environment from MMC... *** Warning - bad CRC, using default environment
No panel detected: default to Hannstar-XGA
Display: Hannstar-XGA (1024x768)
In: serial
Out: serial
Err: serial
SEC0: RNG instantiated
switch to partitions #0, OK
mmc2 is current device
flash target is MMC:2
Net: eth0: ethernet@2188000 [PRIME]
Fastboot: Normal
Normal Boot
Hit any key to stop autoboot: 0
=>
=>
还是官方最顺溜…
野火
其实后来使用飞思卡尔官方开发板已经把SDK成功运行了,但在前几天的SCTF遇到了用野火imx6板子出的题目:
虽然题目本身非常脑洞与无厘头,但这题让我发现野火的教程是非常用心的,正巧回公司岳哥说他那有这板子:
资料链接:i.MX Linux开发实战指南
- 5v供电
- 排针式TTL串口,需转USB,可直接串口供电
开发板上用来选择启动方式的拨码开关一直是一个比较麻烦的问题,一般来说都需要找开发手册才能知道怎么玩,但野火非常贴心的将其选择方式印到了开关附近,着实很贴心。后来发现百问网的也有,就是在板子背面,但迅为和飞思卡尔是真没有。
➜ git clone https://github.com/u-boot/u-boot.git
➜ cd u-boot/
➜ make mx6ull_14x14_evk_defconfig
➜ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
然后按照板子上的开关表格,设置为SD卡启动即可:
U-Boot 2022.01-rc4-00030-gb3f84a939f (Dec 30 2021 - 02:26:02 -0800)
CPU: Freescale i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU: Industrial temperature grade (-40C to 105C) at 45C
Reset cause: POR
Model: Freescale i.MX6 UltraLiteLite 14x14 EVK Board
Board: MX6ULL 14x14 EVK
DRAM: 512 MiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... *** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net:
Error: ethernet@20b4000 address not set.
Error: ethernet@20b4000 address not set.
Error: ethernet@20b4000 address not set.
FEC: can't find phy-handle
Error: ethernet@20b4000 address not set.
Could not get PHY for FEC0: addr 2
Error: ethernet@20b4000 address not set.
FEC: can't find phy-handle
Error: ethernet@20b4000 address not set.
Could not get PHY for FEC0: addr 2
No ethernet found.
Hit any key to stop autoboot: 0
=>
=>
=>
虽然有一些报错,但可见uboot shell还是成功启动,具体怎么适配这张板子,野火也说了:
可见野火的资料是真的告诉你,他都干了啥,你应该怎么干。
总结
对这几家板子的大体感受如下:
- 百问网、迅为:面向纯新手,原理封装狠,较难理解
- 野火:也面向纯新手,但是更讲原理,用心,良心
- 飞思卡尔:权威,官方,缺点是难购买,另外要看英语资料
另外这么折腾一趟下来,也更明白底层咋回事了:
- 上层系统屏蔽硬件差异主要有两套方案:UEFI和DTS(设备树)
- 设备树为嵌入式系统的事实常用方案
- 硬件信息不仅仅是SoC本身,也包括开发板的设计信息
- 没见过直接从SoC上甩几根线出来就当开发板的原因是,SoC的目标是通用,而不是专用,使用其多少接口可以自由裁量
- 所以SoC设计了引脚复用,例如需要几个USB接出来,这个选择的自由度由开发板电路和适配代码(设备树、驱动等)决定
- 这些接口电路,就是板子上除了一个SoC还需要密密麻麻的电阻、电容、电感等零碎的主要原因
- 所以综上,不同板子的切换,不是换个make参数那么简单,要有人来适配这个参数,这个过程一般就叫移植
对国内外技术差异的感受:
- 国内国外硬件常用标准有所不同,如电源、SD卡等
- 国内的许多板子是用国外的SoC,并无核心竞争力,势单力薄,BSP维护难,不会进入到uboot主线
- 中文互联网对于底层相关的资料很少,可能明白这玩意的人都在公司里做板子呢…
另外最近和一些人讨论了IoT固件模拟,经过最近的正向开发,我认为IoT固件的全量模拟是没什么太大意义的:
- 首先现在的IoT技术足够碎片,不过就是一个小计算机,只要制造者能让他跑起来,怎么玩都行
- 其次现在的IoT技术足够复杂,可能是很多个模组,很多处理器共同搭起来的一个系统
- 最后对于安全研究员来说,人家的东西是黑盒的,人家在各种软硬件的地方稍稍来一个花活你就会陷入困惑
但如果只针对一个特定目标,或者一种特定实现,那只要目标价值足够大,还是很有意义的。