- 操作系统
- 嵌入式
- RTOS
- 物联网
【免费下载链接】zephyr
Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
NXP MR-NavQ95B 是面向移动机器人应用的开源开发板,基于 NXP i.MX95 应用处理器,将 Cortex-A55 应用核与 Cortex-M7/M33 实时核集成在同一颗 SoC 中。本文以 boards/nxp/mr_navq95b/doc/index.rst 为主线,结合仓库内板级源码,系统讲解如何在 Zephyr 上为 MR-NavQ95B 的 Cortex-M7 核构建实时固件、从内部 TCM 或外部 Octal SPI NOR Flash 启动运行,以及如何在 M7 上通过 NETC VSI 与 A55 上的 Linux 共享一个物理以太网口。读完本文,你将掌握该板的完整构建、烧录与异构网络配置流程,并理解其板级设备树与启动链路的底层原理。
NXP MR-NavQ95B 开发板:中央为 i.MX95 处理器区域,左侧为千兆以太网接口,右侧带散热模组,底部为各类扩展排针与 USB 接口。
板卡概述与异构多核架构
MR-NavQ95B 是 NXP Robotics 推出的开源移动机器人开发板,面向需要同时承载"高性能应用处理"与"硬实时控制"的机器人场景。其核心价值在于异构多核:i.MX95 把不同实时性、不同算力需求的核放在同一颗芯片上,让开发者可以用一个 SoC 同时跑 Linux(应用/感知/导航)与 Zephyr(电机控制/传感器采集/实时通信)。
处理器与内存资源
- NXP i.MX95 SoC
- 6x Arm Cortex-A55 应用核(典型承载 Linux)
- 1x Arm Cortex-M7 实时核(本文 Zephyr 固件的默认目标)
- 1x Arm Cortex-M33 实时核(在 NavQ95 镜像中充当系统管理器 System Manager)
内存资源方面:
- 片上 SRAM:1376 KiB(带 ECC 校验)
- 外部 LPDDR5:16 GiB(支持 inline ECC 与加密)
- 外部 Flash:64 MiB Octal SPI NOR
在 Zephyr 中,当前支持聚焦于Cortex-M7 核,它通常是实时固件的目标。这一点在 mr_navq95b_mimx9596_m7.dts 与 mr_navq95b_mimx9596_m7.yaml 中有清晰体现:identifier: mr_navq95b/mimx9596/m7、arch: arm、toolchain: zephyr/gnuarmemb,支持的子系统包括 uart、i2c、pwm、spi。
板级配置标识
board.yml定义了该板在 Zephyr 构建系统中的身份:
board: name: mr_navq95b full_name: MR-NavQ95B vendor: nxp socs: - name: mimx9596 variants: - name: ddr cpucluster: m7 - name: flash cpucluster: m7从socs.variants可以看出,该板在 M7 簇下提供ddr与flash两个变体,对应"在外部 LPDDR5 中运行"和"在外部 Flash 中 XIP 运行"两种固件形态,后文会分别展开。
外部扩展与接口复用
MR-NavQ95B 由一块基板(base board)构成,可叠加可选扩展模块以增加接口与功能,其扩展板与可用外设的总览参见 NXP 提供的官方框图(见index.rst的 References 一节)。需要注意,这些接口是复用的(multiplexed),具体哪个外设可用取决于 i.MX95 平台的板级配置与 pinmux 设置。这一点在板级 pinctrl 文件中体现为按外设分别定义引脚组,例如 mr_navq95b-pinctrl.dtsi 中的lpuart2_default、flexspi_default、flexcan2_default等。
串口控制台配置
MR-NavQ95B 的默认串口控制台路由到UART2接口,有两种物理访问途径:
- 通过 I/O 扩展板(I/O expansion board)上 USB-C 连接器(J10)的 USB-to-UART 桥接访问;
- 或通过主板上专用的 JST-GH 板级连接器(J2)直接访问 UART2。
板级设备树中对应节点为lpuart2,mr_navq95b_mimx9596_m7.dts 将其配置如下:
&lpuart2 { status = "okay"; current-speed = <115200>; pinctrl-0 = <&lpuart2_default>; pinctrl-names = "default"; };同时chosen节点把 UART2 同时指定为控制台与 shell 串口:
zephyr,console = &lpuart2; zephyr,shell-uart = &lpuart2;即默认波特率为115200,连接 J10 或 J2 后即可看到 Zephyr 的 shell 与日志输出。设备树中还启用了lpuart5(同样 115200),供其他用途使用。
构建与运行 Hello World
运行形态总览
该板支持两种固件运行形态,构建目标名直接区分:
| 构建目标 | 固件位置 | 说明 |
|---|---|---|
mr_navq95b/mimx9596/m7 | ITCM(片上紧耦合内存) | 最小化起步,直接由调试器加载运行 |
mr_navq95b/mimx9596/m7/flash | MX25UM51345G 外部 Octal SPI NOR | 配合 MCUboot 由外部 Flash XIP 执行 |
在 ITCM 上构建
west build -b mr_navq95b/mimx9596/m7 samples/hello_world/默认(非 flash 变体)的设备树在chosen中把固件放在 TCM 上运行:
chosen { /* TCM */ zephyr,flash = &itcm; zephyr,sram = &dtcm; zephyr,flash-controller = &ext_flash_ctrl; zephyr,console = &lpuart2; zephyr,shell-uart = &lpuart2; zephyr,canbus = &flexcan2; };即代码段放在 ITCM(zephyr,flash),数据段放在 DTCM(zephyr,sram),同时声明了 FlexSPI 外部 Flash 控制器与默认 CAN 总线(flexcan2)。配套的 mr_navq95b_mimx9596_m7_defconfig 启用CONFIG_XIP=y、串口控制台、GPIO,以及通过 SCMI 向 M33 系统管理器请求时钟的CONFIG_ARM_SCMI=y与CONFIG_ARM_SCMI_NXP_VENDOR_EXTENSIONS=y,另外针对 FlexSPI 强制使用 OVRDVAL(CONFIG_FLASH_MCUX_FLEXSPI_FORCE_USING_OVRDVAL=y、CONFIG_FLASH_MCUX_FLEXSPI_OVRDVAL=27)。
从外部 Flash 构建
west build -b mr_navq95b/mimx9596/m7/flash samples/hello_world/Flash 变体在 mr_navq95b_mimx9596_m7_flash.dts 中覆盖chosen节点,把代码分区指向外部 NOR Flash 中的 slot0:
/ { model = "NXP MR-NavQ95B NOR flash variant"; chosen { zephyr,flash = &mx25um51345g; zephyr,itcm = &itcm; zephyr,code-partition = &slot0_partition; }; };同时其 defconfig 启用 MCUboot 支持:CONFIG_BOOTLOADER_MCUBOOT=y、CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE=y,并继续保留CONFIG_XIP=y(从 Flash 直接执行)。
上传固件
固件上传可通过连接 J7 端口的 Segger/J-Link 探针完成:
west flashboard.cmake 根据目标变体为 runner 配置了不同参数:
- flash 变体:pyocd 目标为
--target=mimx95_cm7_mx25um、频率--frequency=20M,并根据zephyr,code-partition与CONFIG_ROM_START_OFFSET计算 VTOR 后以--flash-opt=-O vtor=<addr>传入;J-Link 使用--device=cortex-m7。 - 默认(TCM)变体:pyocd 目标为
--target=mimx95_cm7,J-Link 同样使用--device=cortex-m7。
关于 PyOCD 目标支持的重要说明
注意:要将固件烧写到外部 Flash,需要 PyOCD 支持
mimx95_cm7_mx25um目标。截至文档编写时,该支持尚未合入主线 PyOCD,需按以下步骤手动获取:
安装 pyocd,用于通过板载 JTAG 设备烧写镜像;
将 pyocd 克隆到任意目录,并检出
pr-imx95分支:git clone https://github.com/NXP-Robotics/pyOCD -b pr-imx95构建安装 pyocd:
cd pyocd-private python3 -m pip install .
推荐的整体运行方式:SD 卡镜像 + MCUboot
官方建议在 SD 卡上安装 NavQ95 镜像(构建与烧录说明参见 NXP 的imx-manifest-navq95)。该镜像会在启动时初始化 M33 与 A55 核,并让 M7 在启动时运行 MCUboot,从而从外部 Flash 运行 Zephyr 固件。从外部 Flash 运行时,标准启动流程为:
- 系统管理器(Cortex-M33)初始化系统;
- MCUboot被加载到 TCM;
- MCUboot 校验外部 Flash 中的固件;
- 固件从 Flash直接执行(XIP)。
这一流程与 Flash 变体的设备树/defconfig 一一对应:zephyr,code-partition = &slot0_partition指向 MCUboot 管理的镜像槽位,CONFIG_BOOTLOADER_MCUBOOT=y让构建产物可被 MCUboot 签名/校验,CONFIG_XIP=y保证固件就地执行。
Flash 分区布局
Flash 变体所依赖的 MX25UM51345G 分区定义在 mr_navq95b_mimx9596_m7.dts 中:
| 分区 | 标签 | 地址偏移 | 大小 |
|---|---|---|---|
| boot_partition | mcuboot | 0x00000000 | 128 KiB |
| slot0_partition | image-0 | 0x00020000 | 7 MiB |
| slot1_partition | image-1 | 0x00720000 | 7 MiB |
| storage_partition | storage | 0x00e20000 | 2 MiB - 128 KiB |
分区注释强调:分区大小必须与 Flash 扇区大小(4 KiB)对齐。此外,FlexSPI 控制器节点(nxp,imx-flexspi-mx25um51345g)配置了 120 MHz SPI 时钟、64 MiB 映射范围0x28000000以及 AHB 预取/缓存等优化项(ahb-prefetch、ahb-read-addr-opt、ahb-bufferable、ahb-cacheable),为 XIP 执行提供硬件基础。
DDR 变体
除默认 TCM 与 Flash 两种形态外,mr_navq95b_mimx9596_m7_ddr.dts 还提供了DDR 变体:它删除zephyr,flash属性,并把zephyr,sram指向外部 LPDDR5 中 4 MiB 的映射窗口:
chosen { zephyr,sram = &ddr; /delete-property/ zephyr,flash; }; ddr: memory@80000000 { device_type = "memory"; reg = <0x80000000 DT_SIZE_M(4)>; };对应 defconfig 中CONFIG_XIP=n(固件加载到内存中执行,而非 XIP)。该变体适合需要更大 RAM 内存空间的实验性场景。
Ethernet:在 Linux 旁运行 NETC VSI
共享同一物理网口的架构
i.MX95 的 NETC(ENETC)以太网控制器由 A55 上的Linux与 M7 上的Zephyr 共享:
- Linux通过 Physical Station Interface(PSI)拥有物理端口与 PHY,对应网络接口
end0; - Zephyr(M7)使用 Virtual Station Interface(VSI)——即同一控制器的虚拟功能(VF):
enetc0_vsi1(ENETC0 VF1),通过该共享端口收发数据。
关键约束与分工:
- VF 从属于 PF(Physical Function),因此 Linux 必须先创建 VF 并将其移交给 M7,M7 才能使用它;
- M7 驱动从不触碰 PHY 或 PF,它只启动自己的 station interface,并通过 NETC VSI-to-PSI 消息通道请求 PSI 设置其 MAC 过滤。
这些约束在板级设备树中有明确体现。在 mr_navq95b_mimx9596_m7.dts 中:
/* * The NETC block controller (IERB/NETCMIX/PRB) and the ENETC PSIs are owned by * Linux on the Cortex-A55. The M7 only drives ENETC0 VF1 as a VSI, talking to * the Linux PSI over the VSI-to-PSI message channel. */ &netc_blk_ctrl { status = "disabled"; }; &enetc0_vsi1 { zephyr,random-mac-address; zephyr,mac-address-prefix = [00 04 9f]; status = "okay"; }; &enetc2_vsi1 { zephyr,random-mac-address; zephyr,mac-address-prefix = [00 04 9f]; status = "okay"; };NETC 块控制器(IERB/NETCMIX/PRB)与 ENETC PSI 归 A55 上的 Linux 所有,因此被disabled;M7 仅驱动enetc0_vsi1(以及预留的enetc2_vsi1)作为 VSI,两者都使用00:04:9f前缀的随机 MAC 地址。
Linux 设备树:无需 M7 相关改动
Linux 设备树中不需要任何 M7 相关的修改。默认的 NavQ95 Linux 镜像(见 NXPimx-manifest-navq95)已经启用了 ENETC0 PF 作为带 SR-IOV 支持的end0——这就是全部所需。VF 本身是在运行时动态创建的,而不是在设备树中静态描述。
在 Linux 侧启动 VF
在 A55 上以 root 身份、Linux 启动后执行一次以下步骤(其中end0是移交给 M7 作为 VF1 的 ENETC0 PF):
# 关闭 Linux 的 VF 驱动对 VF 的探测,让 M7 独占 VF,然后创建 VF0+VF1。 echo 0 > /sys/class/net/end0/device/sriov_drivers_autoprobe echo 2 > /sys/class/net/end0/device/sriov_numvfs # 解析 VF1 的 PCI 地址,使其能够 DMA 并触发 MSI-X 中断。 vf=$(basename "$(readlink -f /sys/class/net/end0/device/virtfn1)") setpci -s "$vf" COMMAND=0x0006 # Bus Master Enable setpci -s "$vf" CAP_MSIX+2.w=0x8000:0x8000 # 信任该 VF,使 PSI 响应 M7 驱动发出的 MAC 过滤请求。 ip link set end0 vf 1 trust on各命令的作用:
sriov_drivers_autoprobe=0:先阻止 Linux 自带 VF 驱动自动绑定 VF,避免抢占;sriov_numvfs=2:创建 VF0 与 VF1,其中 VF1 被 M7 使用;setpci ... COMMAND=0x0006:使能 VF 的 Bus Master,允许其发起 DMA;setpci ... CAP_MSIX+2.w=0x8000:0x8000:使能 MSI-X 功能,允许 VF 触发中断;ip link set end0 vf 1 trust on:将 VF1 标记为受信任,PSI 才会接受 M7 驱动设置的 MAC 过滤。
完成上述步骤后,M7 的 VSI 驱动会检测到 VF 已启用,并通过end0接入网络。
提示:NavQ95 BSP(见
imx-manifest-navq95)自带一个enetc-vsi-handoff-mcore服务,会在开机时自动执行这些步骤,因此通常无需手动操作。这里展示手动流程是为了自定义场景(custom setups)的参考。
板级构建系统的支撑细节
Kconfig 结构
Kconfig.mr_navq95b 将三个构建目标统一映射到同一 SoC 型号:
config BOARD_MR_NAVQ95B select SOC_MIMX9596_M7 if BOARD_MR_NAVQ95B_MIMX9596_M7 || \ BOARD_MR_NAVQ95B_MIMX9596_M7_DDR || \ BOARD_MR_NAVQ95B_MIMX9596_M7_FLASH select SOC_PART_NUMBER_MIMX9596AVZXN板级默认外设
板级设备树除串口与网络外,还启用了丰富的机器人常用外设,可作为实际应用的参考起点:
- SPI 传感器:
lpspi1上的 InvenSense ICM-45686 六轴 IMU(加速度计 ±2g、陀螺仪 ±4000dps,ODR 400Hz,FIFO watermark=1);lpspi8上的 Bosch BMI088 加速度计与陀螺仪; - I3C:
i3c1以 400 kHz I2C 模式挂载 Bosch BMP581 气压计与 BMM350 磁力计; - CAN:
flexcan2(默认 CAN 总线)与flexcan3; - PWM:
tpm3/tpm4/tpm5提供多路 PWM(可驱动电机或舵机); - GPIO:
gpio2、gpio5使能并配置中断输出选择; - 定时器:
tstmr2启用。
这些节点与index.rst中"接口复用、取决于板级配置与 pinmux"的描述一致,开发者可以在 mr_navq95b-pinctrl.dtsi 中查看每个外设对应的引脚组定义。
常见问题与排查要点
west flash在 flash 变体上报 PyOCD 目标不支持:说明本地 PyOCD 缺少mimx95_cm7_mx25um目标,需按上文步骤安装 NXP-Roboticspr-imx95分支的 pyocd。- M7 以太网不工作:先确认 A55 侧已完成 VF 创建与移交(
sriov_numvfs、Bus Master、MSI-X、trust on),并确认end0已 up;M7 驱动不会接触 PHY,因此 PHY 状态由 Linux 负责。 - 固件不启动或复位循环:检查是否安装了 NavQ95 SD 卡镜像以初始化 M33 系统管理器与时钟(SCMI),M7 的时钟与系统初始化依赖 M33。
- 分区大小修改:Flash 中的分区必须与 4 KiB 扇区对齐,修改
partitions时注意reg的偏移与大小保持对齐。
参考
- NXP MR-NAVQ95 板卡仓库(硬件原理图、框图等)
- NXP imx-manifest-navq95(SD 卡镜像构建与烧录说明、NavQ95 BSP)
- MR-NavQ95B 扩展板与外设总览框图
相关仓库路径速览:
- 板级文档:boards/nxp/mr_navq95b/doc/index.rst
- 板级设备树:mr_navq95b_mimx9596_m7.dts
- Flash 变体:mr_navq95b_mimx9596_m7_flash.dts 与 mr_navq95b_mimx9596_m7_flash_defconfig
- DDR 变体:mr_navq95b_mimx9596_m7_ddr.dts
- Runner 配置:board.cmake
- 引脚复用:mr_navq95b-pinctrl.dtsi
- 操作系统
- 嵌入式
- RTOS
- 物联网
【免费下载链接】zephyr
Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
相关推荐
Zephyr 在 NXP i.MX95 EVK 上的多核启动与调试实战指南
Zephyr 在 NXP i.MX95 EVK 上的多核启动与调试实战指南 本文以 boards/nxp/imx95_evk/doc/index.rst htt
操作系统嵌入式RTOS物联网Zephyr 在 NXP i.MX 943 EVK 上的多核移植与调试指南:A55 双簇 SMP、M33/M7 协处理与 NETC 以太网实战
Zephyr 在 NXP i.MX 943 EVK 上的多核移植与调试指南:A55 双簇 SMP、M33/M7 协处理与 NETC 以太网实战 导读 本文围绕
操作系统嵌入式RTOS物联网Zephyr 在 NXP i.MX95 EVK 15x15 开发板上的部署指南:硬件特性、A55 启动与编程调试
Zephyr 在 NXP i.MX95 EVK 15x15 开发板上的部署指南:硬件特性、A55 启动与编程调试 本指南以 Zephyr 仓库中 boards/
操作系统嵌入式RTOS物联网
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考