#include <common.h>
#include <asm/io.h>
#include <linux/ctype.h>
/* Глобальный адрес DTCM M7 с точки зрения системной шины A55 */
#define M7_TCM_IPC_A55_BASE 0x20400000U
#define CMD_DATA_READY 1U
#define CMD_VERIFY_CRC 2U
#define STAT_IDLE 0U
#define STAT_BUSY 1U
#define STAT_ACK 2U
#define STAT_ERROR 3U
/* Отражение структуры для U-Boot */
struct rproc_update_ipc_a55 {
uint32_t command;
uint32_t status;
uint32_t chunk_size;
uint32_t target_ddr;
uint32_t expected_crc;
uint8_t buffer[204800]; /* 200 КБ буфер */
};
/* Функция отправки прошивки фрагментами */
int imx_rproc_flash_firmware(ulong src_image_addr, ulong image_size) {
volatile struct rproc_update_ipc_a55 *ipc = (struct rproc_update_ipc_a55 *)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;
uint32_t current_target_ddr = 0x80000000U;
printf("RPROC: Starting flash of %lu bytes to M7 via TCM...\n", image_size);
/* 1. Считаем полный CRC32 эталонного образа силами встроенной функции U-Boot */
uint32_t total_expected_crc = crc32(0, src_ptr, image_size);
printf("RPROC: Calculated image CRC32: 0x%08X\n", total_expected_crc);
/* 2. Поцикловая отправка фрагментов */
while (bytes_left > 0) {
if (bytes_left < chunk_len) {
chunk_len = bytes_left; /* Последний «хвост» файла */
}
/* Ждем, пока M7 освободится */
while (ipc->status == STAT_BUSY);
printf("RPROC: Sending chunk of %d bytes...\n", chunk_len);
/* Копируем пачку данных в буфер TCM прошивки M7 */
memcpy((void *)ipc->buffer, src_ptr, chunk_len);
/* Заполняем метаданные для M7 */
ipc->chunk_size = chunk_len;
ipc->target_ddr = current_target_ddr;
ipc->command = CMD_DATA_READY;
/* Пингуем M7 через аппаратный Mailbox (MU) (опционально, если M7 спит) */
// imx_mu_send_signal();
/* Ждем подтверждения (ACK) от M7 */
while (ipc->status == STAT_BUSY || ipc->command == CMD_DATA_READY);
if (ipc->status != STAT_ACK) {
printf("RPROC: Error! M7 rejected chunk at DDR 0x%08X\n", current_ddr);
return -1;
}
/* Сдвигаем указатели */
src_ptr += chunk_len;
current_target_ddr += chunk_len;
bytes_left -= chunk_len;
}
/* 3. Передача финальной команды сверки CRC */
printf("RPROC: All chunks sent. Verifying total CRC...\n");
ipc->expected_crc = total_expected_crc;
ipc->command = CMD_VERIFY_CRC;
while (ipc->status == STAT_BUSY || ipc->command == CMD_VERIFY_CRC);
if (ipc->status == STAT_ACK) {
printf("RPROC: SUCCESS! CRC matches. M7 booted into DDR 0x80000000!\n");
return 0;
} else {
printf("RPROC: CRC VERIFICATION FAILED! Firmware corrupted.\n");
return -1;
}
}