Загрузка данных


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