NXP iMX8MM 修改 UART4至 Cortex-A53 核心
1). 簡(jiǎn)介
NXP iMX8MM SoC UART-4 接口在默認(rèn)的 ATF(ARM Trusted Firmware) 中被 RDC 分配給了 Cortex-M4 核心,用作 M4 核心的 Debug UART。如果這時(shí)候在 Cortex-A53 核心 Linux Devcie-tree 配置中使能 UART-4,就會(huì)出現(xiàn) Kernel Oops 錯(cuò)誤,本文就簡(jiǎn)單示例如何通過(guò)修改 ATF 固件來(lái)將 UART-4 重新分配給 Cortex-A53 核心使用。
本文測(cè)試使用的是 Toradex 基于 iMX8MM SoC 的 Verdin iMX8MM 計(jì)算機(jī)模塊。
2). 準(zhǔn)備
a). Verdin iMX8MM Quad 2GB WB IT ARM核心版配合 Dahlia 載板,連接調(diào)試串口UART3(載板X18)到開(kāi)發(fā)主機(jī)方便調(diào)試。
b). 本文測(cè)試 iMX8MM Linux基于 Toradex Ycoto Linux BSP 6.x,更多信息可以參考這里。
3). ATF 固件修改編譯
a). ATF 固件是 iMX8MM Boot Container Image的一部分,其中多核心資源管理分配就在這部分固件實(shí)現(xiàn),因此這里先對(duì)其進(jìn)行修改編譯,來(lái)將 uart4 由默認(rèn)的 Cortex-M4 重新分配給 Cortex-A53 核心使用。
b). 獲取ATF源代碼
-------------------------------
$ cd ~/workdir
$ git clone https://github.com/nxp-imx/imx-atf.git -b lf_v2.6
-------------------------------
c). 應(yīng)用保證 Verdin iMX8MM 正常工作的 patches
./ 從這里下載如下兩個(gè) patches,或者也可以從 Ycoto 編譯環(huán)境下 eta-toradex-nxp/recipes-bsp/imx-atf/files/ 位置獲取。
0001-Revert-Add-NXP-s-SoCs-partition-reboot-support.patch 0002-imx8m-hab.c-work-around-gcc-12.1-false-positives.patch
./ 將補(bǔ)丁應(yīng)用到 ATF 源碼
-------------------------------
$ cd ~/workdir/imx-atf
$ git am 0001-Revert-Add-NXP-s-SoCs-partition-reboot-support.patch \
0002-imx8m-hab.c-work-around-gcc-12.1-false-positives.patch
-------------------------------
d). 參考這里說(shuō)明配置編譯toolchain,因?yàn)?span style="font-family: Calibri;">ATF運(yùn)行于Cortex-A核心,因此需要使用GCC ARM針對(duì)Coretx-A核心的GNU-A toolchain,這里使用了9.2 aarch64 64bit版本。
-------------------------------
$ cd ~/workdir/toolchain/
### 解壓下載的toolchain壓縮包
$ tar xvf gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz
$ ls gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu
9.2-2019.12-x86_64-aarch64-none-linux-gnu-manifest.txt bin lib libexec
aarch64-none-linux-gnu include lib64 share
### export 編譯環(huán)境變量
$ export ARCH=arm
$ export CROSS_COMPILE=aarch64-none-linux-gnu-
$ export PATH=$PATH:~/workdir/toolchain/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin
### 測(cè)試toolchain
$ aarch64-none-linux-gnu-gcc --version
aarch64-none-linux-gnu-gcc (GNU Toolchain for the A-profile Architecture 9.2-2019.12 (arm-9.10)) 9.2.1 20191025
Copyright ? 2019 Free Software Foundation, Inc.
......
-------------------------------
e). 參考如下Patch文件修改 ATF 源碼
-------------------------------
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
index 8702d5160..c5bb66040 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -61,7 +61,7 @@ static const struct imx_rdc_cfg rdc[] = {
RDC_MDAn(RDC_MDA_M4, DID1),
/* peripherals domain permission */
- RDC_PDAPn(RDC_PDAP_UART4, D1R | D1W),
+ RDC_PDAPn(RDC_PDAP_UART4, D0R | D0W),
RDC_PDAPn(RDC_PDAP_UART2, D0R | D0W),
RDC_PDAPn(RDC_PDAP_UART1, D0R | D0W),
@@ -108,7 +108,7 @@ static const struct imx_rdc_cfg rdc[] = {
RDC_MDAn(RDC_MDA_M4, DID1),
/* peripherals domain permission */
- RDC_PDAPn(RDC_PDAP_UART4, D1R | D1W),
+ RDC_PDAPn(RDC_PDAP_UART4, D0R | D0W),
RDC_PDAPn(RDC_PDAP_UART2, D0R | D0W),
RDC_PDAPn(RDC_PDAP_UART1, D0R | D0W),
-------------------------------
f). 編譯ATF
-------------------------------
$ cd ~/workdir/imx-atf
$ make PLAT=imx8mm IMX_BOOT_UART_BASE=0x30860000 bl31
### 編譯出 bl31.bin 再后續(xù)組裝Boot Container Image中會(huì)需要
$ ls build/imx8mm/release/bl31.bin
build/imx8mm/release/bl31.bin
-------------------------------
4). Boot Container Image編譯組裝
a). 本文以下編譯流程都是基于當(dāng)前Toradex 最新Linux BSP V6.3版本操作,其他版本以及后續(xù)更新版本和不同硬件平臺(tái) (比如 Verdin iMX8MP) 差異可以參考這里說(shuō)明修改適配。
b). 首先獲取 DDR Training firmware
----------------------------------
$ cd ~/workdir
$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.17.bin
$ chmod u+x firmware-imx-8.17.bin
$ ./firmware-imx-8.17.bin
$ ls firmware-imx-8.17/firmware/ddr/synopsys/
----------------------------------
Verdin iMX8MM 需要的是如下 DDR Training firmware 文件
----------------------------------
lpddr4_pmu_train_1d_dmem.bin
lpddr4_pmu_train_2d_dmem.bin
lpddr4_pmu_train_1d_imem.bin
lpddr4_pmu_train_2d_imem.bin
----------------------------------
c). U-boot編譯
./ 參考這里說(shuō)明進(jìn)行U-boot源代碼下載以及編譯,這個(gè)就是比較常規(guī)的bootloader修改編譯過(guò)程了,針對(duì)iMX8MM/iMX8MP平臺(tái),如果只是需要修改U-boot(ATF不做修改)的話也需要參考本文流程重新組裝Boot Container Image文件后再進(jìn)行部署。
./ 下載對(duì)應(yīng)BSP版本U-boot源代碼
-------------------------------
$ cd ~/workdir
$ git clone -b toradex_imx_lf_v2022.04 git://git.toradex.cn/u-boot-toradex.git
-------------------------------
./ 編譯toolchain和上一章節(jié)編譯ATF是同樣toolchain配置,這里不再贅述。
./ 編譯,生成 u-boot-nodtb.bin/u-boot-spl.bin/imx8mm-verdin.dtb用于后續(xù)Boot Container Image組裝
-------------------------------
$ cd ~/workdir/u-boot-toradex
$ make verdin-imx8mm_defconfig
$ make -j$(nproc) 2>&1 | tee build.log
$ ls u-boot-nodtb.bin
u-boot-nodtb.bin
$ ls spl/u-boot-spl.bin
spl/u-boot-spl.bin
$ ls arch/arm/dts/imx8mm-verdin.dtb
arch/arm/dts/imx8mm-verdin.dtb
-------------------------------
d). Boot Container Image組裝
./ 首先下載 imx-mkimage 工具
-------------------------------
$ cd ~/workdir/
$ git clone -b lf-5.15.32_2.0.0 https://github.com/nxp-imx/imx-mkimage.git
-------------------------------
./ 將上述章節(jié)準(zhǔn)備好的DDR Training Firmware、ATF、U-boot binary等文件復(fù)制到imx-mkimage對(duì)應(yīng)目錄
-------------------------------
$ cd ~/workdir/imx-mkimage/
$ cp ~/workdir/firmware-imx-*/firmware/ddr/synopsys/lpddr4_pmu_train_1d_dmem.bin iMX8M
$ cp ~/workdir/firmware-imx-*/firmware/ddr/synopsys/lpddr4_pmu_train_2d_dmem.bin iMX8M
$ cp ~/workdir/firmware-imx-*/firmware/ddr/synopsys/lpddr4_pmu_train_1d_imem.bin iMX8M
$ cp ~/workdir/firmware-imx-*/firmware/ddr/synopsys/lpddr4_pmu_train_2d_imem.bin iMX8M
$ cp ~/workdir/imx-atf/build/imx8mm/release/bl31.bin iMX8M
$ cp ~/workdir/u-boot-toradex/spl/u-boot-spl.bin iMX8M
$ cp ~/workdir/u-boot-toradex/u-boot-nodtb.bin iMX8M
$ cp ~/workdir/u-boot-toradex/arch/arm/dts/imx8mm-verdin.dtb iMX8M/fsl-imx8mm-evk.dtb
$ cp ~/workdir/u-boot-toradex/tools/mkimage iMX8M/mkimage_uboot
-------------------------------
./ 組裝Boot Container Image,最終生成 flash.bin 文件
-------------------------------
$ make clean; make SOC=iMX8MM flash_evk_emmc_fastboot
$ ls iMX8M/flash.bin
-------------------------------
5). Linux 內(nèi)核設(shè)備樹(shù) (Device-Tree) 修改
a). 除了上面 ATF 固件的修改,由于uart4 接口默認(rèn) Linux Device Tree 配置是關(guān)閉的,這里需要修改打開(kāi)后重新編譯生成新的 Device Tree 文件。
b). 參考這里說(shuō)明下載 Verdin iMX8MM Ycoto Linux BSP 6.3對(duì)應(yīng)的Linux Kernel branch (toradex_5.15-2.1.x-imx),并配置相應(yīng)的編譯環(huán)境,參考如下 patch 修改 device tree源文件后,重新編譯生成新的device tree binary 文件 imx8mm-verdin-wifi-dev.dtb
-------------------------------
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi
index a8a906e18d1e..59977b8a3698 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi
@@ -141,6 +141,11 @@
status = "okay";
};
+/* Verdin UART_4, used by M4 by default need corresponding ATF firmware modification to active */
+&uart4 {
+ status = "okay";
+};
+
/* Verdin USB_1 */
&usbotg1 {
disable-over-current;
-------------------------------
6). 部署測(cè)試
a). 從這里下載Toradex Ycoto Linux BSP Multimedia Image Quarterly 6.3.0+build.7版本,默認(rèn)image通過(guò)Toradex Easy Installer安裝后,將 /boot 目錄下的默認(rèn) imx8mm-verdin-wifi-dev.dtb device-tree 文件替換為章節(jié)6 生成的文件后啟動(dòng)測(cè)試,由于沒(méi)有修改 ATF (默認(rèn)版本是v2.6(release):lf_v2.6-g3c1583ba0a),會(huì)報(bào)出 kernel Oops 錯(cuò)誤。
-------------------------------
U-Boot SPL 2022.04-6.3.0+git.c71ae7141f30 (May 15 2023 - 16:20:01 +0000)
DDRINFO: start DRAM init
DDRINFO: DRAM rate 3000MTS
DDRINFO:ddrphy calibration done
DDRINFO: ddrmix config done
Normal Boot
WDT: Started watchdog@30280000 with servicing (60s timeout)
Trying to boot from MMC1
NOTICE: BL31: v2.6(release):lf_v2.6-g3c1583ba0a
NOTICE: BL31: Built : 11:00:38, Nov 21 2022
......
......
0.795948] Internal error: synchronous external abort: 96000210 [#1] PREEMPT SMP
[ 0.803445] Modules linked in:
[ 0.806510] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.15.77-6.3.0+git.ddc6ca4d76ea #1
[ 0.814525] Hardware name: Toradex Verdin iMX8M Mini WB on Verdin Development Board (DT)
[ 0.822624] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 0.829593] pc : imx_uart_probe+0x31c/0x7d0
[ 0.833791] lr : imx_uart_probe+0x30c/0x7d0
[ 0.837984] sp : ffff800009c1bb60
[ 0.841300] x29: ffff800009c1bb60 x28: 0000000000000000 x27: ffff8000096904c0
[ 0.848452] x26: ffff000000a9de00 x25: 00000000fffffffa x24: 00000000fffffffa
[ 0.855603] x23: ffff000000394810 x22: 0000000000000032 x21: ffff000000394800
[ 0.862754] x20: 0000000000000000 x19: ffff000000889880 x18: ffffffffffffffff
[ 0.869904] x17: 647561625f657361 x16: 62202c3534203d20 x15: ffff000000a9da8a
[ 0.877051] x14: ffffffffffffffff x13: 0000000000000018 x12: 0101010101010101
[ 0.884202] x11: 0000000000000030 x10: 0101010101010101 x9 : 0000000000000000
[ 0.891356] x8 : ffff000000a9df00 x7 : 0000000000000000 x6 : ffff000000088000
[ 0.898504] x5 : 00000000000000c0 x4 : 0000000000000000 x3 : 0000000000000000
[ 0.905652] x2 : 0000000000000000 x1 : ffff80000a320080 x0 : 0000000000000000
[ 0.912805] Call trace:
[ 0.915256] imx_uart_probe+0x31c/0x7d0
[ 0.919103] platform_probe+0x68/0xe0
[ 0.922771] really_probe+0xbc/0x46c
[ 0.926356] __driver_probe_device+0x114/0x190
[ 0.930813] driver_probe_device+0x40/0x100
[ 0.935005] __driver_attach+0xac/0x210
[ 0.938850] bus_for_each_dev+0x70/0xd0
[ 0.942694] driver_attach+0x24/0x30
[ 0.946275] bus_add_driver+0x144/0x244
[ 0.950119] driver_register+0x78/0x130
[ 0.953964] __platform_driver_register+0x28/0x34
[ 0.958673] imx_uart_init+0x3c/0x64
[ 0.962259] do_one_initcall+0x50/0x1b0
[ 0.966102] kernel_init_freeable+0x20c/0x290
[ 0.970468] kernel_init+0x24/0x12c
[ 0.973968] ret_from_fork+0x10/0x20
[ 0.977556] Code: 2a0003f4 35001820 f9400a61 91020021 (b9400021)
[ 0.983674] ---[ end trace 600c5e6ad38c2c3e ]---
[ 0.988366] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[ 0.996030] SMP: stopping secondary CPUs
[ 0.999963] Kernel Offset: disabled
[ 1.003454] CPU features: 0x00002001,20000846
[ 1.007817] Memory Limit: none
[ 1.010875] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000
00b ]---
-------------------------------
b). 用上述章節(jié)4生成的 flash.bin文件替換掉剛才下載的BSP 6.3.0 image壓縮包里面的imx-boot文件
-------------------------------
$ cd ~/workdir/
$ tar xvf Verdin-iMX8MM_Reference-Multimedia-Image-Tezi_6.3.0+build.7.tar
$ cd Verdin-iMX8MM_Reference-Multimedia-Image-Tezi_6.3.0+build.7/
$ rm imx-boot
$ cp imx-mkimage/iMX8QM/flash.bin imx-boot
-------------------------------
c). 將上述修改后的image重新通過(guò)Toradex Easy Installer更新到Verdin iMX8MM模塊后,查看 ATF 版本變化(v2.6(release):lf-6.1.1-1.0.0-2-gc9c586a62-dirty),然后可以成功進(jìn)入Linux并查看到 UART4 端口 (/dev/ttymxc3)。
-------------------------------
U-Boot SPL 2022.04-21601-g7bd2074193 (Sep 04 2023 - 15:51:26 +0800)
DDRINFO: start DRAM init
DDRINFO: DRAM rate 3000MTS
DDRINFO:ddrphy calibration done
DDRINFO: ddrmix config done
Normal Boot
WDT: Started watchdog@30280000 with servicing (60s timeout)
Trying to boot from MMC1
NOTICE: BL31: v2.6(release):lf-6.1.1-1.0.0-2-gc9c586a62-dirty
NOTICE: BL31: Built : 14:49:42, Sep 6 2023
...
...
TDX Wayland with XWayland 6.3.0+build.7 (kirkstone) verdin-imx8mm-07276322 ttymxc0
Verdin-iMX8MM_Reference-Multimedia-Image
root@verdin-imx8mm-07276322:~# ls /dev/ttymxc*
/dev/ttymxc0 /dev/ttymxc1 /dev/ttymxc2 /dev/ttymxc3
-------------------------------
d). 可以參考這里說(shuō)明進(jìn)行 UART4 串口的測(cè)試,UART4 通過(guò) Dahlia載板 X18 USBC 引出。
-------------------------------
root@verdin-imx8mm-07276322:~# echo Test_From_Verdin_iMX8MM > /dev/ttymxc3
root@verdin-imx8mm-07276322:~# cat < /dev/ttymxc3
Test_From_Host_PC
-------------------------------
7). 總結(jié)
本文基于NXP iMX8M Mini嵌入式平臺(tái)簡(jiǎn)單介紹了修改 ATF 固件來(lái)將 UART4 從 Cortex-M4 核心連接到 Cortex-A53以及組裝 Boot Container Image 的流程。
提交
Verdin AM62 LVGL 移植
基于 NXP iMX8MM 測(cè)試 Secure Boot 功能
隆重推出 Aquila - 新一代 Toradex 計(jì)算機(jī)模塊
Verdin iMX8MP 調(diào)試串口更改
NXP iMX8MM Cortex-M4 核心 GPT Capture 測(cè)試