Загрузка данных
u-boot=> setenv image bootloader_cm7.bin
u-boot=> setenv serverip 192.168.0.193
u-boot=> setenv ipaddr 192.168.0.200
u-boot=> tftpboot ${loadaddr} ${image}
u-boot=> mw.l 0x203c0000 0 0x10000
u-boot=> cp.b ${loadaddr} 0x203c0000 ${filesize}
M33:
>$ reboot_m7
[MONITOR] No boot_vector specified. Using default boot_vector.
MONITOR_Dispatch(608) reboot M7 (vector: 0x0)
LMM_SystemLmReset status=0
>$ cpu.r
000: m33p => run-mode = RUN, slp-mode = RUN, vector = 0x00000000_00000000
001: m7p => run-mode = RUN, slp-mode = RUN, vector = 0x00000000_00000000
002: a55c0 => run-mode = RUN, slp-mode = WAIT, vector = 0x00000000_20480000
003: a55c1 => run-mode = STOP, slp-mode = RUN, vector = 0x00000000_00001000
004: a55c2 => run-mode = STOP, slp-mode = RUN, vector = 0x00000000_00001000
005: a55c3 => run-mode = STOP, slp-mode = RUN, vector = 0x00000000_00001000
006: a55c4 => run-mode = STOP, slp-mode = RUN, vector = 0x00000000_00001000
007: a55c5 => run-mode = STOP, slp-mode = RUN, vector = 0x00000000_00001000
008: a55p => run-mode = RUN, slp-mode = WAIT, vector = 0x00000000_00000000
M7 исходник(PRINTF не печатаются):
void tcm_bootloader_main(void)
{
/* Mapping IPC structure onto DTCM memory region */
struct rproc_update_ipc *ipc = (struct rproc_update_ipc *)(IPC_BASE_ADDR + IPC_DTCM_OFFSET);
uint32_t current_ddr_ptr = 0x80000000U; /* Target execution DDR memory address for M7 */
uint32_t calculated_total_crc; /* Standard CRC32 initializtion vector */
char ch;
memset((void *)ipc, 0, sizeof(struct rproc_update_ipc));
/* Clean initial state */
ipc->magic_word = IPC_MAGIC_M7_READY;
ipc->command = 0;
ipc->status = STAT_IDLE;
PRINTF("Wait U-BOOT magic_word 0x%X\r\n",IPC_MAGIC_UB_READY);
while(ipc->magic_word != IPC_MAGIC_UB_READY) {
__NOP();
__NOP();
}
while (1)
{
ch = GETCHAR();
PUTCHAR(ch);
}
PRINTF("U-BOOT magic_word 0x%X become success\r\n",IPC_MAGIC_UB_READY);
calculated_total_crc = 0xFFFFFFFFU;
while(1) {
/* Force volatile read of the command flag to prevent compiler optimization loops */
uint32_t cmd = *(volatile uint32_t *)&(ipc->command);
#if 0
if(ipc->magic_word != IPC_MAGIC_UB_READY) {
ipc->status = STAT_ERROR;
break;
}
if (cmd == CMD_DATA_READY) {
PRINTF("Have CMD_DATA_READY from U-BOOT\r\n");
ipc->status = STAT_BUSY;
__DSB(); /* Ensure status write completes before processing data */
/* Safe memory block copy from TCM communication buffer to target DDR location */
memcpy((void *)current_ddr_ptr, (const void *)ipc->buffer, ipc->chunk_size);
/* Feed the chunk into the continuous stream CRC32 accumulator */
#if 0
calculated_total_crc = calculate_crc32(calculated_total_crc, (const uint8_t *)ipc->buffer, ipc->chunk_size);
#endif
/* Advance the DDR pointer forward by the size of the written chunk */
current_ddr_ptr += ipc->chunk_size;
/* Data Synchronization Barrier: Ensure all bus transaction write cycles to DDR are complete */
__DSB(); __ISB();
/* Signal U-Boot that the data chunk has been acknowledged and saved */
ipc->command = 0;
ipc->status = STAT_ACK;
__DSB();
}
else if (cmd == CMD_VERIFY_CRC) {
PRINTF("Have CMD_VERIFY_CRC from U-BOOT\r\n");
ipc->status = STAT_BUSY;
__DSB();
calculated_total_crc = calculated_total_crc ^ 0xFFFFFFFFU;
if (calculated_total_crc == ipc->expected_crc) {
PRINTF("CRC is ok\r\n");
#if 0
/* Flush and clean Data Cache for the loaded firmware region in DDR */
SCB_CleanDCache_by_Addr((void *)0x80000000U, (current_ddr_ptr - 0x80000000U));
/* Invalidate Instruction Cache to force CPU reload instructions from modified DDR memory */
SCB_InvalidateICache();
__DSB();
__ISB();
/* Fetch the entry point address (Reset Handler) from the Application Vector Table */
uint32_t jump_address = *(volatile uint32_t *)(0x80000004U);
/* CRITICAL FOR CORTEX-M: Force the least significant bit (LSB) to 1.
This signals the ARM core to enter Thumb-2 state execution mode, preventing HardFaults. */
jump_address |= 1U;
void (*entry_point)(void) = (void (*)(void))jump_address;
/* Respond to the host with final ACK status before relinquishing control */
ipc->command = 0;
ipc->status = STAT_ACK;
__DSB(); __ISB();
/* Relocate Vector Table Offset Register (VTOR) to point to the base of DDR application */
SCB->VTOR = 0x80000000U;
/* Load Main Stack Pointer (MSP) from the very first word of the firmware binary */
__set_MSP(*(volatile uint32_t *)(0x80000000U));
/* Branch execution context directly to the application entry point */
entry_point();
#else
/* Respond to the host with final ACK status before relinquishing control */
ipc->command = 0;
ipc->status = STAT_ACK;
__DSB(); __ISB();
PRINTF("Try start M7 from DDR\r\n");
while(1) {
__NOP();
__NOP();
};
#endif
} else {
/* CRC Mismatch Error state handling */
PRINTF("CRC Mismatch Error 0x%X != 0x%X\r\n",calculated_total_crc,ipc->expected_crc);
ipc->command = 0;
ipc->status = STAT_ERROR;
__DSB();
/* Reset internal tracking states to allow recovery or retry firmware transmission */
calculated_total_crc = 0xFFFFFFFFU;
current_ddr_ptr = 0x80000000U;
}
}
else {
/* Low-Power Optimization for Bare-metal:
Puts the Cortex-M7 core into sleep state until any hardware interrupt occurs
(e.g., Systick, MU Mailbox, or Timer interrupt). Prevents pinning the CPU to 100%. */
__NOP();
__NOP();
}
#endif
}
return;
}
/*!
* @brief Main function
*/
int main(void)
{
/* Init board hardware. */
BOARD_InitHardware();
PRINTF("MCUX SDK version: %s\r\n", MCUXSDK_VERSION_FULL_STR);
PRINTF("Bootloader.\r\n");
tcm_bootloader_main();
}