Загрузка данных
#define MAGIC_M7_READY 0x4D37424CU /* "M7BL" - Set by M7 to signal it has booted and cleared RAM */
#define MAGIC_UB_START 0x55424D37U /* "UBM7" - Set by U-Boot to open a legitimate transfer session */
/* Function of sending firmware to M7 in fragments */
int imx_rproc_flash_firmware(struct udevice *dev, ulong src_image_addr, ulong image_size)
{
struct imx_rproc *priv = dev_get_priv(dev);
const struct imx_rproc_dcfg *dcfg = priv->dcfg;
/* CRITICAL: Ensure IMX95_M7_TCM_IPC_A55_BASE matches 0x20402000U (8 KB offset inside DTCM) */
volatile struct rproc_update_ipc_a55 *ipc = (struct rproc_update_ipc_a55 *)IMX95_M7_TCM_IPC_A55_BASE;
uint8_t *src_ptr = (uint8_t *)src_image_addr;
uint32_t bytes_left = image_size;
uint32_t chunk_len = 204800; /* 200 KB chunk size */
uint32_t current_target_ddr = 0x80000000U;
uint32_t timeout;
printf("RPROC: Starting flash of %lu bytes to M7 via TCM...\n", image_size);
/* ===================================================================== */
/* TWO-WAY SAFE HANDSHAKE PHASE */
/* ===================================================================== */
/* 1. Wait for M7 core to complete Cold Boot, wipe RAM, and set its ready token */
printf("RPROC: Waiting for M7 Bootloader handshake (Looking for 0x%08X)...\n", MAGIC_M7_READY);
timeout = 1000000; /* Timeout to protect U-Boot from locking up if M7 fails */
while (ipc->magic_word != MAGIC_M7_READY)
{
udelay(1);
if (--timeout == 0) {
printf("RPROC: Error! Handshake timed out. M7 is not responding.\n");
return -1;
}
}
printf("RPROC: Handshake Phase 1 Success! M7 Bootloader is alive and ready.\n");
/* 2. Overwrite the exact same field with U-Boot token to establish the session */
ipc->magic_word = MAGIC_UB_START;
printf("RPROC: Handshake Phase 2 Success! Session opened with token 0x%08X.\n", MAGIC_UB_START);
/* ===================================================================== */
/* DATA TRANSMISSION PHASE */
/* ===================================================================== */
/* 3. Calculate full reference CRC32 of the source file using built-in U-Boot function */
uint32_t total_expected_crc = crc32(0, src_ptr, image_size);
printf("RPROC: Calculated reference image CRC32: 0x%08X\n", total_expected_crc);
/* 4. Sequential chunk transmission loop */
while (bytes_left > 0)
{
if (bytes_left < chunk_len) {
chunk_len = bytes_left;
}
/* Runtime Protection: Verify M7 has not cleared the token due to internal faults */
if (ipc->magic_word != MAGIC_UB_START) {
printf("RPROC: Error! M7 broken session safety check during transmission.\n");
return -1;
}
printf("RPROC: Sending chunk of %d bytes to DDR 0x%08X...\n", chunk_len, current_target_ddr);
/* Copy data block directly into the now-isolated DTCM buffer area */
memcpy((void *)ipc->buffer, src_ptr, chunk_len);
/* Fill control and routing structures */
ipc->chunk_size = chunk_len;
ipc->target_ddr = current_target_ddr;
/* Set busy state BEFORE command flag to prevent potential race conditions */
ipc->status = STAT_BUSY;
ipc->command = CMD_DATA_READY;
/* Hardware Data Synchronization Barrier for ARMv8 (Cortex-A55) cache coherency */
asm volatile("dsb sy" : : : "memory");
/* Wait for chunk processing confirmation (ACK) from M7 with a 2-second timeout */
timeout = 2000000;
while (ipc->command == CMD_DATA_READY)
{
udelay(1);
if (--timeout == 0) {
printf("RPROC: Error! M7 processing timeout at DDR 0x%08X\n", current_target_ddr);
return -1;
}
}
/* Evaluate processing response status */
if (ipc->status != STAT_ACK) {
printf("RPROC: Error! M7 rejected or failed chunk at DDR 0x%08X. Status: %d\n",
current_target_ddr, ipc->status);
return -1;
}
/* Shift memory and stream pointers */
src_ptr += chunk_len;
current_target_ddr += chunk_len;
bytes_left -= chunk_len;
}
/* ===================================================================== */
/* VERIFICATION AND FINALIZATION PHASE */
/* ===================================================================== */
printf("RPROC: All chunks sent successfully. Verifying total CRC...\n");
ipc->expected_crc = total_expected_crc;
ipc->status = STAT_BUSY;
ipc->command = CMD_VERIFY_CRC;
asm volatile("dsb sy" : : : "memory");
/* Wait for M7 to finish cumulative 4 MB CRC32 mathematical validation (5s max) */
timeout = 5000000;
while (ipc->command == CMD_VERIFY_CRC)
{
udelay(1);
if (--timeout == 0) {
printf("RPROC: Error! CRC Verification timed out.\n");
return -1;
}
}
if (ipc->status == STAT_ACK) {
printf("RPROC: SUCCESS! CRC matches. File is valid.\n");
/* NOTE: Triggering the final Logical Machine clean reboot via SCMI/M33
should be executed right here to branch M7 execution into 0x80000000 cleanly */
return 0;
} else {
printf("RPROC: CRC VERIFICATION FAILED! Firmware corrupted on M7 side.\n");
return -1;
}
}