大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是多个i.MXRT共享一颗Flash启动的方法。
在 《多个i.MXRT共享一颗Flash启动的方法与实践(上)》 一文里痞子衡给大家从理论上介绍一种多 i.MXRT 共享 Flash 启动的方法,但是理论虽好,如果没有经过实践验证切实可行,不过是纸上谈兵,所以今天痞子衡就找了两个 i.MXRT 开发板来具体实操这种方法:
一、搭建硬件平台
理论上任意两块 i.MXRT 开发板均可以用作硬件测试平台(这里仅考虑一主一从,至于一主多从原理差不多),但是痞子衡手头 MIMXRT1010-EVK_Rev.C 开发板较多,就选用它来做测试吧,痞子衡对硬件做了如下改动:
- 去除从板上 U13 - Flash
- 保留主板上 U13 - Flash,并且飞线连接到从板 U13(低速启动仅需 CS, SCLK, IO0, IO1)
- 主板主芯片 GPIO_11 信号(R1870 靠主芯片端,非 D25 LED 端)连到从板主芯片 POR_B(SW3 的 Pin3/4)

二、软件代码设计
有了硬件平台,现在开始设计代码。为了简单起见,主从 i.MXRT 共用一份 App(可以在条件分支里做区分)。因为 Flash 是共享的,所以 App 必须是 Non-XIP 性质。要让芯片 BootROM 去支持 Non-XIP 启动,得使用专用上位机工具(比如痞子衡的 MCUBootUtility 或者恩智浦官方 SPT )来下载程序镜像文件,这样稍微麻烦一点。为了避免下载程序的麻烦,我们可以简单设计一个 boot_loader 工程来拷贝和跳转 boot_app 程序。
text
代码仓库:
https://github.com/JayHeng/func-imxrt-flexspi-share-flash-boot-multiple-mcu
两个工程路径:
/boards/evkmimxrt1010/demo_apps/boot_loader
/boards/evkmimxrt1010/demo_apps/boot_app
2.1 boot_loader 工程设计
boot_loader 工程是一个 XiP 工程,由芯片 BootROM 直接启动。我们可以直接基于 SDK 里的 hello_world 来修改(flexspi_nor target),先对它的启动头 FCB 做如下修改(1-bit SPI 30MHz Normal Read Mode):

boot_app 工程是一个 Non-XiP 工程,也可以基于 SDK 里的 hello_world 来修改(debug target),它生成的 binary 直接导入到 boot_loader 工程里,具体方法可参见 《i.MXRT双核工程调试的三种方法(IAR篇)》 一文里的 2.3 通用方法:双核工程有关联,主核加载从核 小节,这里不再赘述。
boot_loader 工程里有了 boot_app 数据以及链接地址,拷贝和跳转函数设计就比较简单了,都是通用代码。最终调稳定的 boot_loader 工程可以直接在 IDE 里下载到 Flash 里运行(需调试器连接到主板 SWD 口)。
2.2 boot_app 工程设计
现在来到最核心的 boot_app 工程设计,工程还是基于 hello_world,可以从串口接收简单的字符指令(A,B...)来做不同测试,目前设计了六个测试指令:
text
字符指令 A(仅适用主 i.MXRT)- 将 GPIO_11 输出电平由低变高控制 POR_B 信号以释放从 i.MXRT
字符指令 B(仅适用主 i.MXRT)- 将 GPIO_11 输出电平由高变低控制 POR_B 信号以复位保持从 i.MXRT
字符指令 C(适用主/从i.MXRT)- 初始化 Flash 相关引脚为 FlexSPI 功能
字符指令 D(适用主/从i.MXRT)- 恢复 Flash 相关引脚为默认 GPIO 状态
字符指令 E(适用主/从i.MXRT)- 以一线模式擦写读 U13 Flash
字符指令 F(仅适用从 i.MXRT)- 用定时器不断翻转 GPIO_11 来驱动 D25 LED 闪烁
这里需要特别说一下指令 A 和 E,这里面涉及到主/从 i.MXRT 芯片 FlexSPI 引脚共同驱动一个 Flash 的冲突问题。当主 i.MXRT 执行 A 指令来释放从 i.MXRT 时,需要先执行 D 指令(即调用如下函数)将 FlexSPI 引脚恢复到上电默认 GPIO 状态(BootROM 启动时已将这些引脚配置成了 FlexSPI 功能),否则从 i.MXRT 可能无法正常从 Flash 启动。
C
void bsp_deinit_flexspi_pins(void)
{
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_06_GPIO2_IO06, 0U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_07_GPIO2_IO07, 0U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_09_GPIO2_IO09, 0U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_10_GPIO2_IO10, 0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_06_GPIO2_IO06, 0x10A0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_07_GPIO2_IO07, 0x10A0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_09_GPIO2_IO09, 0x10A0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_10_GPIO2_IO10, 0x10A0U);
}
C 指令和 E 指令显然是结伴而行的,当从 i.MXRT 执行过 C,E 指令且仍处于激活状态时,如果主 i.MXRT 想正常执行 C,E 指令,要么先执行 B 指令直接将从 i.MXRT 复位保持住(FlexSPI 相关引脚配置也自动复位了),要么让从 i.MXRT 先执行下 D 指令。
三、在板卡上测试
现在给板卡供电,将包含 boot_app 的 boot_loader 程序下载进 Flash,主板串口是 COM43,从板串口是 COM50,我们做一个快速测试,给主板直接发送 A 指令发现从板没有启动,但是执行过 D 指令后再发送 A 指令,这时候从板就正常启动了。此外主/从板也都能对 Flash 进行正常擦写,这证明我们的创新连接方法是切实可行的。

至此,多个i.MXRT共享一颗Flash启动的方法痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园、CSDN、微信公众号、知乎、与非网、电子技术应用AET、电子星球、51CTO 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。
