Initial commit: CCU621_M firmware project with BLE debug link support.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* @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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user