Blog:
NXP iMX8MM 修改 UART4至 Cortex-A53 核心

Thursday, September 7, 2023

1). 简介

NXP iMX8MM SoC UART-4 接口在默认的 ATF(ARM Trusted Firmware) 中被 RDC 分配给了 Cortex-M4 核心,用作 M4 核心的 Debug UART。如果这时候在 Cortex-A53 核心 Linux Devcie-tree 配置中使能 UART-4,就会出现 Kernel Oops 错误,本文就简单示例如何通过修改 ATF 固件来将 UART-4 重新分配给 Cortex-A53 核心使用。


本文测试使用的是 Toradex 基于 iMX8MM SoC Verdin iMX8MM 计算机模块。


2). 准备

a). Verdin iMX8MM Quad 2GB WB IT ARM核心版配合 Dahlia 载板,连接调试串口UART3(载板X18)到开发主机方便调试。

b). 本文测试 iMX8MM Linux基于 Toradex Ycoto Linux BSP 6.x,更多信息可以参考这里


3). ATF 固件修改编译

a). ATF 固件是 iMX8MM Boot Container Image的一部分,其中多核心资源管理分配就在这部分固件实现,因此这里先对其进行修改编译,来将 uart4 由默认的 Cortex-M4 重新分配给 Cortex-A53 核心使用。

b). 获取ATF源代码

$ cd ~/workdir
$ git clone https://github.com/nxp-imx/imx-atf.git -b lf_v2.6


c). 应用保证 Verdin iMX8MM 正常工作的 patches

./ 这里下载如下两个 patches,或者也可以从 Ycoto 编译环境下 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


./ 将补丁应用到 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). 参考这里说明配置编译toolchain,因为ATF运行于Cortex-A核心,因此需要使用GCC ARM针对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 编译环境变量
$ 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

### 测试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 再后续组装Boot Container Image中会需要
$ ls build/imx8mm/release/bl31.bin 
build/imx8mm/release/bl31.bin


4). Boot Container Image编译组装

a). 本文以下编译流程都是基于当前Toradex 最新Linux BSP V6.3版本操作,其他版本以及后续更新版本和不同硬件平台 (比如 Verdin iMX8MP) 差异可以参考这里说明修改适配。

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编译

./ 参考这里说明进行U-boot源代码下载以及编译,这个就是比较常规的bootloader修改编译过程了,针对iMX8MM/iMX8MP平台,如果只是需要修改U-bootATF不做修改)的话也需要参考本文流程重新组装Boot Container Image文件后再进行部署。

./ 下载对应BSP版本U-boot源代码

$ cd ~/workdir
$ git clone -b toradex_imx_lf_v2022.04 git://git.toradex.cn/u-boot-toradex.git


./ 编译toolchain和上一章节编译ATF是同样toolchain配置,这里不再赘述。

./ 编译,生成 u-boot-nodtb.bin/u-boot-spl.bin/imx8mm-verdin.dtb用于后续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


./ 将上述章节准备好的DDR Training FirmwareATFU-boot binary等文件复制到imx-mkimage对应目录

$ 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 内核设备树 (Device-Tree) 修改

a). 除了上面 ATF 固件的修改,由于uart4 接口默认 Linux Device Tree 配置是关闭的,这里需要修改打开后重新编译生成新的 Device Tree 文件。

b). 参考这里说明下载 Verdin iMX8MM Ycoto Linux BSP 6.3对应的Linux Kernel branch (toradex_5.15-2.1.x-imx),并配置相应的编译环境,参考如下 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). 部署测试

a). 这里下载Toradex Ycoto Linux BSP Multimedia Image Quarterly 6.3.0+build.7版本,默认image通过Toradex Easy Installer安装后,将 /boot 目录下的默认 imx8mm-verdin-wifi-dev.dtb device-tree 文件替换为章节6 生成的文件后启动测试,由于没有修改 ATF (默认版本是v2.6(release):lf_v2.6-g3c1583ba0a),会报出 kernel Oops 错误。

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). 用上述章节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重新通过Toradex Easy Installer更新到Verdin iMX8MM模块后,查看 ATF 版本变化(v2.6(release):lf-6.1.1-1.0.0-2-gc9c586a62-dirty),然后可以成功进入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). 可以参考这里说明进行 UART4 串口的测试,UART4 通过 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). 总结

本文基于NXP iMX8M Mini嵌入式平台简单介绍了修改 ATF 固件来将 UART4 Cortex-M4 核心连接到 Cortex-A53以及组装 Boot Container Image 的流程。





Author: 秦海,Toradex 销售工程师
Share this on:

Leave a comment

Please login to leave a comment!
Have a Question?