/** * @file flash_upgrade.c * @brief 外置 Flash 固件升级区读写(与 CCU601E_D / CCU621_IAP 布局一致) */ #include "flash_upgrade.h" #include "app_init/app_init.h" #include "wdt_task/wdt_task.h" #include "exflash_spi4_gd25qxx.h" #include #include extern U8_T s32_flash_dataflash_write(U32_T addr, U8_T *buf, U32_T len); extern U8_T s32_flash_dataflash_read(U32_T addr, U8_T *buf, U32_T len); extern U8_T s32_flash_dataflash_erase_sector(U32_T addr); /* 0: 按包擦扇区;1: upgrade_erase_program_area 已整体擦除 */ static int g_upgrade_program_pre_erased = 0; static uint8_t s_upgrade_header_buf[sizeof(upgrade_header_t)] __attribute__((aligned(32))); __attribute__((weak)) void upgrade_erase_yield(void) { } int upgrade_init(void) { upgrade_header_t header; if (upgrade_read_header(&header) == 0) { if (header.upgrade_flag == UPGRADE_FLAG_NEED_UP) { return 1; } if (header.upgrade_flag == UPGRADE_FLAG_DONE) { return 2; } } g_upgrade_program_pre_erased = 0; return 0; } int upgrade_write_header(const upgrade_header_t *header) { if (header == NULL) { return -1; } spi_flash_wait_for_write_end(); v_wdt_dog_toggle(); s32_flash_dataflash_erase_sector(HEADER_SECTOR_ADDR); v_wdt_dog_toggle(); memcpy(s_upgrade_header_buf, header, sizeof(upgrade_header_t)); if (s32_flash_dataflash_write(HEADER_SECTOR_ADDR, s_upgrade_header_buf, sizeof(upgrade_header_t)) != 0U) { printf("[FW_UPGRADE] header write failed\r\n"); return -1; } spi_flash_wait_for_write_end(); v_wdt_dog_toggle(); return 0; } int upgrade_read_header(upgrade_header_t *header) { if (header == NULL) { return -1; } if (s32_flash_dataflash_read(HEADER_SECTOR_ADDR, (U8_T *)header, sizeof(upgrade_header_t)) != 0U) { return -1; } return 0; } int upgrade_success_update_header(upgrade_header_t *header) { return upgrade_write_header(header); } int upgrade_write_packet(uint32_t packet_index, const uint8_t *data, uint32_t data_len) { uint32_t packet_addr; uint32_t sector_start; if ((data == NULL) || (data_len == 0U) || (data_len > PACKET_SIZE)) { return -1; } packet_addr = PROGRAM_START_ADDR + (packet_index * PACKET_SIZE); if (packet_addr + data_len > UPGRADE_END_ADDR) { return -1; } if (!g_upgrade_program_pre_erased) { sector_start = (packet_addr / SECTOR_SIZE) * SECTOR_SIZE; if ((packet_index * PACKET_SIZE) % SECTOR_SIZE == 0U) { s32_flash_dataflash_erase_sector(sector_start); v_wdt_dog_toggle(); mSleep(1); } } if (s32_flash_dataflash_write(packet_addr, (U8_T *)data, data_len) != 0U) { return -1; } return 0; } int upgrade_read_packet(uint32_t packet_index, uint8_t *data, uint32_t *data_len) { uint32_t packet_addr; uint32_t max_read_size; if ((data == NULL) || (data_len == NULL)) { return -1; } packet_addr = PROGRAM_START_ADDR + (packet_index * PACKET_SIZE); if (packet_addr > UPGRADE_END_ADDR) { return -1; } if (s32_flash_dataflash_read(packet_addr, data, PACKET_SIZE) != 0U) { return -1; } max_read_size = UPGRADE_END_ADDR - packet_addr + 1U; if (max_read_size < PACKET_SIZE) { *data_len = max_read_size; } else { *data_len = PACKET_SIZE; } return 0; } int upgrade_erase_program_area(void) { return upgrade_erase_program_area_for_size(PROGRAM_MAX_SIZE); } int upgrade_erase_program_area_for_size(uint32_t firmware_bytes) { uint32_t sector_addr; uint32_t last_byte; uint32_t last_sector; if (firmware_bytes == 0U) { return -1; } if (firmware_bytes > PROGRAM_MAX_SIZE) { return -1; } last_byte = PROGRAM_START_ADDR + firmware_bytes - 1U; if (last_byte > UPGRADE_END_ADDR) { return -1; } last_sector = (last_byte / SECTOR_SIZE) * SECTOR_SIZE; printf("[FW_UPGRADE] erase start size=%lu sectors=0x%08lX..0x%08lX\r\n", (unsigned long)firmware_bytes, (unsigned long)PROGRAM_START_ADDR, (unsigned long)last_sector); for (sector_addr = PROGRAM_START_ADDR; sector_addr <= last_sector; sector_addr += SECTOR_SIZE) { s32_flash_dataflash_erase_sector(sector_addr); v_wdt_dog_toggle(); mSleep(1); upgrade_erase_yield(); if (((sector_addr - PROGRAM_START_ADDR) / SECTOR_SIZE) % 10U == 9U) { printf("[FW_UPGRADE] erase progress at 0x%08lX\r\n", (unsigned long)sector_addr); } } printf("[FW_UPGRADE] erase done\r\n"); g_upgrade_program_pre_erased = 1; return 0; }