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


#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;
    }
}