RT-Thread i.MX RT1180 双核 BSP 实战:两核分开跑、分开聊、从核还能被叫醒
RT-Thread i.MX RT1180 双核 BSP 实战两核分开跑、分开聊、从核还能被叫醒【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址: https://gitcode.com/gh_mirrors/rt/rt-threadi.MX RT1180 把两颗 Arm 核心放在同一颗芯片里配套的 RT-Thread BSP 采取双工程、各自编译、各自烧录的做法这对习惯单核 MCU 的开发者来说很容易看晕。本文以 imxrt1180-nxp-evk 为例按任务主线推进第 1 步完成编译烧录并验证启动第 2 步讲透用 menuconfig 按需裁剪外设第 3、4 步拆解主核唤醒从核、核间消息传递两条源码链路。适合用 RT-Thread 做双核项目的入门者。先看懂分工为什么双核就是两个工程一颗芯片、两颗核、一主一从两颗核的定位差别很大Cortex-M7CM7800 MHz 主频带 FPU适合电机控制、信号处理这类算力密集的活Cortex-M33CM33240 MHz 主频自带 TrustZone 安全扩展适合安全启动、系统管理、网络协议栈这类任务。芯片还提供双千兆以太网、EtherCAT 等工业接口并支持宽温工作目标场景是工业控制、电机驱动。这个 BSP 里主从关系是固定的CM33 是主核CM7 是从核remote从核上电后不会自己跑起来必须由主核把它踢起来。同一个 BSP 下的两个独立工程工程结构直接体现了这种分工imxrt1180-nxp-evk目录下并排放着cm33/与cm7/二者各自拥有完整的 rtconfig.h、构建脚本、IDE 模板和链接脚本编译产物互不掺和。两个工程的分工可以直接从各自的 rtconfig.h 确认CM33 侧架构宏为ARCH_ARM_CORTEX_M33ARCH_ARM_CORTEX_SECURE控制台设备是uart1LPUART1RX/TX DMA 通道 0 和 1见 cm33/rtconfig.hCM7 侧架构宏为ARCH_ARM_CORTEX_M7ARCH_ARM_CORTEX_FPU控制台设备是uart12LPUART12DMA 通道 22 和 23见 cm7/rtconfig.h。⚠️串口别接串了两核日志各走各的。想看 CM33 的输出把 USB 转串口接到 UART1看 CM7 则接 UART12两边都按 115200-8-1-N 设置。第 1 步拉包、出工程、验证第一次启动如果还没拿到代码先 clone RT-Thread 仓库https://gitcode.com/gh_mirrors/rt/rt-thread 然后进入bsp/nxp/imx/imxrt/imxrt1180-nxp-evk对应核的目录打开 ENV。编译前唯一的硬前提是拉取软件包。该 BSP 的外设驱动来自 NXP IMXRT 驱动包rtconfig.h 里能看到PKG_USING_NXP_IMXRT_DRIVER开关漏掉这步编译会直接缺库报错pkgs --update scons --targetmdk5 scons -j8三行对应三条路线scons --targetmdk5产出 Keil 工程scons --targetiar产出 IAR 工程scons -j8走 GCC 直接编译8 线程并行。工程文件会落在对应核的目录里比如cm33/。硬件侧数据线把开发板接到 PC板载调试器打开电源开关。工程默认走 CMSIS-DAP 下载确认连接后点一下下载按钮镜像就进板子了。判断成功的标准烧录完系统自动运行串口工具打开对应口、复位一下先看到 RT-Thread 的启动 banner带 logo 和版本号接着是应用输出CM33 工程打印MIMXRT1180_CM33 Hello_World同时板载 LEDcm33/applications/main.c 中的GET_PIN(4, 27)以 500 ms 为周期翻转CM7 工程由 cm7/applications/main.c 打印MIMXRT1180_CM7 Hello_World。✅ 两路串口先后出现各自的 Hello_World说明两核各自拉起来了。第 2 步用 menuconfig 按需裁剪外设默认配置是最小集QSPI Flash、GPIO、DMA 加上各自的控制台串口其余全部关闭。要启用额外资源标准动作是在对应核的 BSP 目录执行menuconfig勾选选项保存退出再pkgs --update最后重新执行 scons 生成工程顺序不能反。哪些外设可用对照 cm33/board/Kconfigcm7 侧同构按支持状态分成三档开箱即用QSPI Flash XIP代码直接驻留外部 NOR flash 执行、flexspi 驱动、CherryUSB设备/主机双角色可选、NETC 网络交换双千兆以太网、EtherCAT、GPIOGET_PIN接口、LPUART1 ~ LPUART12、LPSPI1 ~ LPSPI4、LPI2C每路 100/400 kHz 二选一、LPADC附多通道 DMA 示例、Timer含 DWT 周期计数与微秒忙等、SDIO、RTC、FLEXCAN3需要主从协同开关多核启动kick-off与核间消息RPMsg-Lite第 3、4 步专门讲暂未支持PWM文档标注为后续版本规划。勾选选项时注意两条联动逻辑菜单里不少选项不是孤立的只看表面容易踩空DMA 是被别人带起来的串口、SPI、I2C 没有独立的整板 DMA入口各通道的 RX/TX DMA 开关一勾会自动连带选中BSP_USING_DMA通道号要单独填串口范围 0~32SPI/I2C 范围 0~31默认按序递增。通道配置长这样一个选项带出一串依赖以太网开关会自动带起 lwIP、SAL、netdev还能进一步选 EP0 直连或交换模式NETC_USE_SWT、默认开启 PHY文件系统开关下可以组合SD 卡 FATFS或QSPI Flash LittleFS后者依赖 FAL 分区表见cm33/board/ports/fal_cfg.h。内存布局靠一个选项切换Kconfig 末尾是内存布局三选一对应cm33/board/linker_scripts/下三组.ld/.scf/.icf文件RAM镜像整体放进内部 SRAM 跑FlexSPI NOR默认代码在外部 NOR flash 上 XIP 执行FlexSPI NOR HyperRAMXIP 之外再挂外部 HyperRAM 当附加内存。配合 cm33/rtconfig.py 的机制它扫描 rtconfig.h 里的BSP_LINKER_SCRIPT_*宏挑出匹配的链接脚本生成 Keil 工程时还会把project.uvoptx的当前 Target 同步成对应名称。也就是说 menuconfig 里切一下选项、重新生成工程内存布局就自动跟上不用手改链接文件。⚠️改完布局一定要重新生成工程拿旧工程继续编译链接地址和新布局对不上板子起不来。第 3 步主核唤醒从核MCMGR kickoff 流程CM33 侧的多核逻辑集中在 cm33/applications/multicore_thread.c。系统启动时经INIT_APP_EXPORT自动建一个名为 multicore 的线程栈 2048 字节、优先级 10、时间片 5由它执行唤醒 CM7的全套动作。可以把它类比成先帮搭档装好启动盘再按下开机键每个动作都有对应源码步骤初始化 MCMGRMCMGR_Init()启动多核管理单元它相当于那枚开机键预约就绪回调MCMGR_RegisterEvent()注册远端应用就绪事件CM7 起来后能借此回报取镜像信息BOARD_GetCore1ImageAddrSize()拿到 CM7 镜像的源地址、目的地址、大小和启动地址并逐条打印到控制台供核对搬运镜像BOARD_PrepareCore1()把镜像从源位置拷到目标内存——装启动盘按下开机键MCMGR_StartCore()以同步方式拉起 CM7同时把 RPMsg 共享内存的基址一并传给从核等回执以 10 ms 为周期轮询就绪事件直到 CM7 回报 ready 才往下走。对应 Kconfig 里BSP_USE_MULTICORE之下的两个子开关kick-off 与 RPMsg-Lite均默认打开。kick-off 的 help 文本也明确主核拉起从核时这套启动序列是保证初始化顺序正确所必需的。第 4 步在共享内存留言板上打乒乓RPMsg-Lite 核间通信两核之间不直接共享数据交换而是用 RPMsg-Lite——RPMsg 协议的轻量实现靠一块共享内存完成点对点消息传递。打个比方两个核共用一块留言板谁要说话就在板上留言对方路过时取走。留言板在源码里是 6144 字节的缓冲区rpmsg_lite_base[]这里有个隐蔽的坑缓冲区所在的 section 随编译器变化——IAR 用 pragma location、Keil 用 section 属性、GCC 用.noinit.$rpmsg_sh_mem三者必须与链接脚本里的段定义逐一对上。对不上的话两核指向的内存就不是同一块消息全部石沉大海。主核侧初始化按四步走以 master 身份初始化 RPMsg-Lite 实例 → 建接收队列 → 建本地端点默认地址 40→ 绑定名称服务。最后一步完成后主核进入等待等 CM7 起来后在名称服务上广播服务名回调把远端端点地址写进变量主核立刻转入正式通信。正式通信是一段经典 ping-pong主核发出一个 32 位计数值CM7 收到后回传如此往复约 100 轮计数到顶通信结束随后按顺序销毁端点、队列和名称服务句柄收尾 RPMsg。所有参数都有默认值不改也能跑链路 ID0即RL_PLATFORM_IMXRT1180_M33_M7_LINK_ID本地端点地址CM33 侧40范围 0~65535名称服务广播串rpmsg-openamp-demo-channel共享内存大小6144 字节。Kconfig 里配的值会写进 rtconfig.h源码中用#ifndef兜底所以不显式配置也能按默认参数编译运行。CM7 侧的对称实现在 cm7/applications/multicore_thread.c想追远端逻辑时看它。跑通演示之后走向自己的双核应用到这里开发板已经走完启动—配置—主从拉起—核间通信的完整闭环。做自己的应用时改动其实只有三处把两个工程里演示用的main()换成业务逻辑把 RPMsg 消息的载荷从 32 位计数换成自己的协议结构如果希望一颗芯片从单镜像整体启动还可以借助 MCUXpresso Secure Provisioning Tool 生成可启动的双核镜像做法见 README_zh.md 的说明。这个 BSP 的要点浓缩起来就三句话两核是两个独立工程构建互不干扰主核负责唤醒从核顺序不能颠倒核间消息走那块 6144 字节共享内存section 必须和链接脚本对得上。把这三句记牢后面往 RT1180 上叠电机控制、工业网关之类的业务路就不会走偏。【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址: https://gitcode.com/gh_mirrors/rt/rt-thread创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考