Zephyr 在 NXP i.MX8MQ EVK 上运行 Cortex-M4 核的完整指南:异构架构、内存映射与 U-Boot 加载调试
【免费下载链接】zephyrPrimary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.项目地址: https://gitcode.com/GitHub_Trending/ze/zephyr
NXP i.MX8MQ EVK 是一块以 quad Cortex-A53 为主处理器、单 Cortex-M4 为协处理器的异构开发板,Zephyr RTOS 被移植到其中的 Cortex-M4 核心上运行,与运行 Linux 的 A53 构成典型的主从(heterogeneous)系统。本文以 Zephyr 仓库中的 boards/nxp/imx8mq_evk/doc/index.rst 为骨架,结合板级设备树、SoC 设备树、defconfig、board.cmake 等源码文件,系统讲解该板卡的硬件资源、M4 侧 Zephyr 的编译配置、A53 与 M4 的双核内存映射,以及如何通过 U-Boot 从 SD 卡或串口将 Zephyr 固件加载到 M4 上运行,并完成 J-Link 调试。读完本文,你将掌握 imx8mq_evk/mimx8mq6/m4 这个板卡目标从构建到运行调试的完整闭环。
板卡概述与硬件资源
i.MX8MQ EVK 基于 NXP i.MX8MQ 应用处理器,由四核 Cortex-A53 集群与单个 Cortex-M4 核心构成。Zephyr OS 被移植到 Cortex-M4 核心上运行——这决定了整个开发流程的特殊性:M4 不是独立启动的主核,而是由 A53 一侧(U-Boot 或 Linux)负责加载与引导。
板卡的主要硬件特性如下:
- RAM:3GB LPDDR4
- 存储:16GB eMMC5.0、32MB QSPI NOR、microSD 卡座
- 无线:WiFi 2.4/5GHz IEEE 802.11 a/b/g/n/ac,Bluetooth v4.1
- USB:1x Type-C OTG、1x Type-A HOST
- 接口:Ethernet、PCI-E M.2
- LED:1x 电源状态 LED、1x UART LED
- 调试:10-pin JTAG 连接器;MicroUSB 提供 UART 调试,暴露 A53 与 M4 两个 COM 口
从 Zephyr 板级描述文件可以印证这一板卡的官方标识:boards/nxp/imx8mq_evk/board.yml声明板卡名为imx8mq_evk、全称MIMX8MQ EVK、厂商nxp,SoC 为mimx8mq6;而boards/nxp/imx8mq_evk/imx8mq_evk_mimx8mq6_m4.yaml则定义了 Zephyr 中的具体目标标识imx8mq_evk/mimx8mq6/m4,类型为mcu,架构arm(Cortex-M4),并声明 128KB RAM 与 128KB flash(对应 TCM 区域,详见下文内存映射一节)。
支持的硬件特性
.. zephyr:board-supported-hw::指令会从板级设备树与 Kconfig 中自动汇总当前板卡在 Zephyr 中启用的硬件支持能力。结合源码可以确认,imx8mq_evk/mimx8mq6/m4 目标当前实际启用的能力集中在最小运行集上:
- 串口(UART2,用作 console 与 shell)
- 时钟控制(clock control)
- XIP(片上执行,代码直接从内存执行)
这些能力由 imx8mq_evk_mimx8mq6_m4_defconfig 中的配置项支撑:
CONFIG_CLOCK_CONTROL=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_CONSOLE=y CONFIG_XIP=y其中CONFIG_XIP=y与下文的 TCM/OCRAM 代码区选择直接相关:当 XIP 使能时,Zephyr 固件直接从所选的内存区域取指执行,而不是先拷贝到 SRAM。其余外设(GPIO、ECSPI、UART1/3/4、Mailbox 等)在 SoC 设备树中均已定义但默认为disabled,需要时可通过 overlay 使能。
引脚连接与 IO 配置
MIMX8MQ EVK 板在 Zephyr 中经过验证的 pinmux 配置如下:
| Board Name | SoC Name | Usage |
|---|---|---|
| UART2 RXD | UART2_TXD | UART Console |
| UART2 TXD | UART2_RXD | UART Console |
(表中 Board Name 与 SoC Name 的交叉对应是原文档的既有表述,实际含义为:板级上 UART2 的 RXD/TXD 引脚复用为 UART2 的接收/发送功能,用于串口控制台。)
引脚复用配置在 imx8mq_evk-pinctrl.dtsi 中实现。该文件由gen_board_pinctrl.py从 NXP 官方引脚配置工具文件生成,定义了uart2_default状态:
&pinctrl { uart2_default: uart2_default { group0 { pinmux = <&iomuxc_uart2_rxd_uart_rx_uart2_rx>, <&iomuxc_uart2_txd_uart_tx_uart2_tx>; slew-rate = "fast"; drive-strength = "45-ohm"; }; }; };注意这里出现了两组看似矛盾的uart2_rxd_uart_rx_uart2_rx/uart2_txd_uart_tx_uart2_tx——这正是异构系统中"从 M4 视角看 UART2"的复用关系,引脚所属 pad 由 A53 侧主导,M4 通过 IOMUXC 将这些 pad 配置为 UART2 的 RX/TX 功能。
系统时钟
M4 核被配置为以266 MHz时钟运行。时钟框架由 SoC 设备树中的ccm(Clock Controller Module)节点提供,地址0x30380000,#clock-cells = <3>(见 dts/arm/nxp/imx/nxp_imx8m_m4.dtsi),UART2 等外设的时钟源即通过clocks = <&ccm IMX_CCM_UART2_CLK 0x68 28>这样的三元组引用。CONFIG_CLOCK_CONTROL=y使能时钟控制驱动,保证 UART 波特率等外设时序正确。
串口
i.MX8MQ SoC 共有四个 UART,Zephyr 将UART_2 配置为控制台,其余 UART 未使用/未测试。板级设备树 imx8mq_evk_mimx8mq6_m4.dts 中:
aliases { uart-2 = &uart2; }; chosen { zephyr,flash = &tcml_code; zephyr,sram = &tcmu_sys; zephyr,console = &uart2; zephyr,shell-uart = &uart2; }; &uart2 { status = "okay"; current-speed = <115200>; pinctrl-0 = <&uart2_default>; pinctrl-names = "default"; };UART2 在 SoC 设备树中位于0x30890000,兼容nxp,imx-iuart(见 nxp_imx8m_m4.dtsi)。板级文件将其status置为okay、波特率设为 115200,并把zephyr,console与zephyr,shell-uart都指向 UART2,因此串口终端需以 115200 波特率连接。
内存映射:A53 与 M4 的双视图
i.MX8MQ EVK 板没有可供 M4 独立启动的 QSPI flash,M4 固件必须由 A53 核心加载:A53 负责把 M4 应用程序二进制载入 RAM、将 M4 置于复位、设置 M4 的程序计数器(PC)与栈指针(SP)、再解除 M4 复位。这些步骤既可以在 bootloader(U-Boot)阶段完成,也可以在 Linux 系统启动后完成。
M4 最多可使用 3 种不同的 RAM。下表是 A53 与 M4 视角下的内存映射(两个核通过不同总线地址访问同一物理存储):
| Region | Cortex-A53 | Cortex-M4 (System Bus) | Cortex-M4 (Code Bus) | Size |
|---|---|---|---|---|
| OCRAM | 0x00900000-0x0091FFFF | 0x20200000-0x2021FFFF | 0x00900000-0x0091FFFF | 128KB |
| TCMU | 0x00800000-0x0081FFFF | 0x20000000-0x2001FFFF | — | 128KB |
| TCML | 0x007E0000-0x007FFFFF | — | 0x1FFE0000-0x1FFFFFFF | 128KB |
| OCRAM_S | 0x00180000-0x00187FFF | 0x20180000-0x20187FFF | 0x00180000-0x00187FFF | 32KB |
这些区域在 SoC 设备树 nxp_imx8m_m4.dtsi 中有完整的节点定义:
tcml_code: code@1ffe0000 { compatible = "nxp,imx-itcm"; reg = <0x1ffe0000 DT_SIZE_K(128)>; }; tcmu_sys: memory@20000000 { compatible = "nxp,imx-dtcm"; reg = <0x20000000 DT_SIZE_K(128)>; }; ocram_code: code@900000 { compatible = "nxp,imx-code-bus"; reg = <0x00900000 DT_SIZE_K(256)>; }; ocram_sys: memory@20200000 { compatible = "nxp,imx-sys-bus"; reg = <0x20200000 DT_SIZE_K(256)>; }; ocram_s_code: code@180000 { compatible = "nxp,imx-code-bus"; reg = <0x00180000 DT_SIZE_K(32)>; }; ocram_s_sys: memory@20180000 { compatible = "nxp,imx-sys-bus"; reg = <0x20180000 DT_SIZE_K(32)>; };而 nxp_imx8mq_m4.dtsi 进一步将 OCRAM 收敛为与文档一致的 128KB:ocram_code的reg覆盖为0x00900000起始 128KB,ocram_sys覆盖为0x20200000起始 128KB(M4 System Bus 视角的 OCRAM 别名)。
在编译时需要选择固件放在哪块 RAM。该配置在板级设备树 imx8mq_evk_mimx8mq6_m4.dts 中通过zephyr,flash(当CONFIG_XIP=y时生效)与zephyr,sram属性完成。可选组合如下:
"zephyr,flash" - &tcml_code (TCML,Code Bus 0x1FFE0000,128KB) - &ocram_code (OCRAM,Code Bus 0x00900000,128KB) - &ocram_s_code (OCRAM_S,Code Bus 0x00180000,32KB) "zephyr,sram" - &tcmu_sys (TCMU,System Bus 0x20000000,128KB) - &ocram_sys (OCRAM,System Bus 0x20200000,128KB) - &ocram_s_sys (OCRAM_S,System Bus 0x20180000,32KB)板级默认选择为zephyr,flash = &tcml_code;与zephyr,sram = &tcmu_sys;,即代码放在 TCML、数据放在 TCMU——这也是 defconfig 中CONFIG_XIP=y的落点:固件直接在 TCM 中取指执行。修改内存布局时,只需在设备树 overlay 中改这两个chosen属性,并确保与 U-Boot 侧的加载地址(见下一节)一致。
从 A53 加载并运行 Zephyr(U-Boot 方式)
编译目标为imx8mq_evk/mimx8mq6/m4。以 hello_world 为例,标准构建命令为:
west build -b imx8mq_evk/mimx8mq6/m4 samples/hello_world产物为build/zephyr/zephyr.bin。注意板卡默认的内存选择(TCML 代码 + TCMU 数据)意味着 128KB 的代码容量上限,若固件超出可改用 OCRAM 布局。
方式一:从 SD 卡加载
- 将编译好的
zephyr.bin复制到 SD 卡第一个 FAT 分区,插入板卡。 - 上电并在 U-Boot 提示符处停下执行。
- 将 M4 二进制加载到目标内存并启动:
fatload mmc 0:1 0x40480000 zephyr.bin cp.b 0x40480000 0x7e0000 0x8000 bootaux 0x7e0000逐条说明:
fatload mmc 0:1 0x40480000 zephyr.bin:从 SD 卡第 0 个控制器、第 1 个分区读取zephyr.bin到 DDR 临时地址0x40480000。cp.b 0x40480000 0x7e0000 0x8000:将固件从 DDR 拷贝到0x7e0000。0x7e0000正是 A53 视角下 TCML 的起始地址(见内存映射表0x007E0000-0x007FFFFF),0x8000(32KB)为拷贝长度——即把 128KB 的 TCML 分四段拷入,或按实际固件大小调整。bootaux 0x7e0000:U-Boot 的bootaux命令将 M4 置于复位、设置 PC 为0x7e0000、设置 SP,然后解除复位,使 M4 开始执行。
方式二:从串口加载
此方式需要宿主机安装screen与lrzsz。
- 启动
screen,上电板卡并在 U-Boot 提示符处停下:
screen <tty-device> 115200- 在 U-Boot 中启动
loadx,偏移量7e0000(同样是 TCML 的 A53 地址),波特率 115200:
loadx 7e0000 115200- 回到 screen 会话,按下 :kbd:
Ctrl-a后跟:进入命令模式,输入以下命令用sx发送编译好的zephyr.bin:
exec !! sx </full/path/to/zephyr.bin>sx会通过 XMODEM 协议把文件经串口发送给 U-Boot 的loadx,并写入0x7e0000。
- 启动执行:
bootaux 0x7e0000关键点回顾
无论哪种方式,核心三要素是:加载地址必须是 A53 视角下与所选代码区一致的内存地址(TCML 为 0x7e0000);拷贝/传输长度要覆盖整个固件;通过bootaux让 A53 完成对 M4 的复位释放与 PC/SP 设置。如果你在设备树中把代码区改到 OCRAM(A53 地址0x00900000),则上述命令中的目标地址应相应替换。
调试:J-Link 外部调试器
MIMX8MQ EVK 可以通过外接 J-Link JTAG 调试器调试:将 J-Link 连接到板上的J401 调试连接器并接到 PC,之后即可按常规方式调试应用。
以hello_world为例,调试命令为:
west build -b imx8mq_evk/mimx8mq6/m4 samples/hello_world west debug板级支持文件 board.cmake 说明了调试器的接线方式:
board_set_debugger_ifnset(jlink) board_set_flasher_ifnset(jlink) board_runner_args(jlink "--device=MIMX8MQ6_M4") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)即默认调试器与烧录器均为 J-Link,且以MIMX8MQ6_M4作为 J-Link 目标器件。
打开串口终端,在调试器中单步执行应用,应能在终端看到如下输出:
***** Booting Zephyr OS build zephyr-v2.6.99-30942-g6ee70bd22058 ***** Hello World! imx8mq_evk(上方 boot banner 中的具体 commit 哈希随仓库版本变化,属于示例输出。)Hello World!之后的板名由 samples/hello_world/src/main.c 中的printf("Hello World! %s\n", CONFIG_BOARD_TARGET)打印,CONFIG_BOARD_TARGET在该板目标上即imx8mq_evk。
常见问题与注意事项
- M4 无法独立启动:板卡没有 M4 可用的 QSPI flash,脱离 A53 的 M4 固件无法自行引导,必须走 U-Boot
bootaux或 Linux 侧的远程处理器框架流程。 - 内存容量:TCML/TCMU 各 128KB,OCRAM_S 仅 32KB。代码放不下时可改用
zephyr,flash = &ocram_code(128KB)或将数据区移到&ocram_sys。 - 地址一致性:设备树中的代码区地址(M4 Code Bus 视角)与 U-Boot 加载地址(A53 视角)必须对应同一物理存储:TCML 的 A53 地址是
0x7e0000,而设备树中 TCML 的 M4 地址是0x1ffe0000,二者指向同一块物理内存。 - 测试范围:板卡 yaml 中声明测试忽略
net与bluetooth标签,即网络与蓝牙相关测试默认不在此板目标上运行。
延伸阅读
- 板卡文档原文:boards/nxp/imx8mq_evk/doc/index.rst
- 板级设备树:boards/nxp/imx8mq_evk/imx8mq_evk_mimx8mq6_m4.dts
- SoC 设备树(M4 视角内存与外设定义):dts/arm/nxp/imx/nxp_imx8m_m4.dtsi、dts/arm/nxp/imx/nxp_imx8mq_m4.dtsi
- 板级默认配置:boards/nxp/imx8mq_evk/imx8mq_evk_mimx8mq6_m4_defconfig
- J-Link 调试接线与参数:boards/nxp/imx8mq_evk/board.cmake
- hello_world 示例:samples/hello_world/README.rst
【免费下载链接】zephyrPrimary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.项目地址: https://gitcode.com/GitHub_Trending/ze/zephyr
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考