Customers adopting multi-i.MXRT master-slave architectures (one master, multiple slaves) aim to meet functional requirements while simultaneously reducing costs and improving system efficiency through optimized hardware design.
In multi-i.MXRT systems, a typical design adopts a master-slave architecture where one i.MXRT acts as the master and others as slaves. Since the i.MXRT chip lacks on-chip non-volatile memory, each i.MXRT requires an independent boot device (e.g., NOR Flash connected via FlexSPI) to load programs and initiate startup.
Traditional Architecture:
- Each i.MXRT has its own dedicated Flash memory, ensuring operational independence.
Advantages:
- Full System Independence:
- Simplified Firmware Management:
Disadvantages:
- Complex programming workflow (multiple Flash devices need individual firmware updates).
- Higher hardware complexity, larger PCB footprint, and increased cost due to multiple Flash chips.
A single Flash device is connected to multiple i.MXRTs. The master i.MXRT controls the POR_B (Power-On Reset) signal of all slave i.MXRTs, enabling shared access to the same Flash.
Boot Process:
1. The master i.MXRT boots first in Non-XIP mode.
2. The master sequentially releases the POR_B signals of slave i.MXRTs, allowing them to occupy the Flash and boot in Non-XIP mode one at a time.
Advantages:
- Reduced cost and simplified hardware design.
- Smaller PCB footprint with only one Flash required.
- Streamlined firmware programming (single Flash update) for mass production.
Disadvantages:
- If slave i.MXRTs require different firmware, the Flash must be partitioned into regions, leading to:
- Complex OTA version management challenges.
- Reduced system independence among slave devices.
Rework:
Due to both master and slave i.MXRTs sharing a single application (differentiated via conditional branches), the app must be Non-XIP. Therefore, we designed a boot_loader project that copies and jumps to the boot_app, instead of using SPT or MCUBootUtility.
Key modules:
.
├── boards
│ └── evkmimxrt1010
│ ├── demo_apps
│ │ ├── boot_app
│ │ ├── boot_loader
│ │ ├── hello_world
│ │ └── led_blinky
│ └── xip
│ ├── evkmimxrt1010_flexspi_nor_config.c
│ └── evkmimxrt1010_flexspi_nor_config.h
├── CMSIS
│ ├── Core
│ ├── Driver
│ ├── DSP
│ ├── LICENSE.txt
│ ├── NN
│ └── RTOS2
├── components
│ ├── lists
│ ├── serial_manager
│ └── uart
├── devices
│ └── MIMXRT1011
├── LICENSE
└── README.md
Note: Please see the whole reference project from attchement.
The boot_loader
is a XiP project directly booted by the chip's BootROM. It can be based on the SDK's hello_world
example (flexspi_nor
target). The FCB boot header should be modified as follows (1-bit SPI, 30MHz, Normal Read Mode):
// boot_loader
// xip/evkmimxrt1010_flexspi_nor_config.c
const flexspi_nor_config_t qspiflash_config = {
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClksrc=kFlexSPIReadSampleClkLoopbackInternally,
.csHoldTime = 3u,
.csSetupTime = 3u,
.deviceType = kFlexSpiDeviceTypeSerialNOR,
.sflashPadType = kSerialFlash_1Pad,
.serialClkFreq = kFlexSpiSerialClk_30Hz,
.sflashA1Size = 16u * 1024u * 1024u,
.lookupTable = {
// Read LUTs
FLEXSPI_LUT_SEQ(CHIP_SELECT, FLEXSPI_1PAD, 0x03, RADDR_SDR, FLEXSPI_1PAD, 0x18),
FLEXSPI_LUT_SEQ(READ_SDR, FLEXSPI_1PAD, 0x04, STOP, FLEXSPI_1PAD, 0x0),
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.blockSize = 64u * 1024u,
.isUniformBlockSize = false,
};
The boot_app
is a Non-XIP project (based on SDK’s debug
target). Its binary is imported into the boot_loader
project. With proper linking address and memory layout, the copy & jump logic can be implemented with standard code. The finalized boot_loader
can then be downloaded to Flash using an IDE.
The boot_app
is also derived from the SDK's hello_world
. It supports receiving simple UART commands (A
, B
, etc.) for various tests. Currently, six test commands are supported:
Commands | Target Device i.MX RT | Description |
'A' | Master | Drive master i.MXRT's GPIO_11 high to pull POR_B high and release slave i.MXRT from reset. |
'B' | Master | Drive master i.MXRT's GPIO_11 low to pull POR_B low and hold slave i.MXRT in reset. |
Commands | Target Device | Description |
'F' | Salve | Toggle GPIO_11 periodically with a timer to blink the D25 LED. |
Commands | Target Device | Description |
'C' | Master or Slave | Initialize Flash-related pins for FlexSPI functionality. |
'D' | Master or Slave | Restore Flash-related pins to default GPIO state. |
'E' | Master or Slave | Erase, program, and read U13 Flash. |
Notes:
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);
}
boot_loader
(containing embedded boot_app
) to Flash.Quick Test:
Note: Please see readme.md from attchement for more details.
The i.MXRT master-slave architectures (Independent Flash vs. Shared Flash) offer distinct trade-offs:
- Independent Flash: Prioritizes system reliability and independent firmware management at the cost of higher hardware complexity and cost.
- Shared Flash: Reduces costs and PCB footprint but introduces firmware dependency and OTA management challenges.
The prototype successfully validated the Shared Flash approach, demonstrating its feasibility for cost-sensitive, mass-production scenarios. Customers can choose between these designs based on their specific priorities: high reliability with independence (Independent Flash) or cost-efficiency with streamlined workflows (Shared Flash).