Загрузка данных
uint32_t calculate_crc32(uint32_t crc, const uint8_t *buf, uint32_t len)
{
while (len--) {
crc = (crc >> 8) ^ crc32_table[(crc ^ *buf++) & 0xFF];
}
return crc;
}
void tcm_bootloader_main(void)
{
/* Mapping IPC structure onto DTCM memory region */
struct rproc_update_ipc *ipc = (struct rproc_update_ipc *)IPC_BASE_ADDR;
uint32_t current_ddr_ptr = 0x80000000U; /* Target execution DDR memory address for M7 */
uint32_t calculated_total_crc = 0xFFFFFFFFU; /* Standard CRC32 initializtion vector */
memset((void *)ipc, 0, offsetof(struct rproc_update_ipc, buffer));
/* 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) {
#if 0
__WFI();
#endif
}
PRINTF("U-BOOT magic_word 0x%X become success\r\n",IPC_MAGIC_UB_READY);
while(1) {
/* Force volatile read of the command flag to prevent compiler optimization loops */
uint32_t cmd = *(volatile uint32_t *)&(ipc->command);
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 */
calculated_total_crc = calculate_crc32(calculated_total_crc, (const uint8_t *)ipc->buffer, ipc->chunk_size);
/* 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) {
/* 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 {
/* 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%. */
#if 0
__WFI();
#endif
}
}
}
u-boot=> rproc load_firmware 0 ${loadaddr} ${filesize}
imx_rproc_load_firmware(210)
imx_rproc_load_firmware(214)
RPROC: Starting flash of 12872 bytes to M7 via TCM...
RPROC: Waiting for M7 Bootloader handshake (Looking for 0x4D37424C)...
RPROC: Handshake Phase 1 Success! M7 Bootloader is alive and ready.
RPROC: Handshake Phase 2 Success! Session opened with token 0x55424D37.
RPROC: Calculated image CRC32: 0xB536E007
RPROC: Sending chunk of 12872 bytes...
RPROC: All chunks sent. Verifying total CRC...
RPROC: CRC VERIFICATION FAILED! Firmware corrupted.
imx_rproc imx95-cm7: Failed load firmware to remote core!
imx_rproc_load_firmware(219) ret=1
Load firmware to Remote Processor 0 with data@addr=0x90400000 12872 bytes: Failed!
Wait U-BOOT magic_word 0x55424D37
U-BOOT magic_word 0x55424D37 become success
Have CMD_DATA_READY from U-BOOT
Have CMD_VERIFY_CRC from U-BOOT
CRC Mismatch Error 0x953C3EF7 != 0xB536E007