refactor(build): 支持A/B分区逻辑
移除sys/flash.h、sys/flash.cpp、sys/initial.h和sys/OTA相关文件的 引用,清理cproject.yml和cbuild.yml中的未使用组件和文件配置。 BREAKING CHANGE: 移除了FlashEEPROM相关功能和接口。
This commit is contained in:
+211
-41
@@ -7,22 +7,96 @@
|
||||
#include "systick.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <flash.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern CAN_transmiter CAN0_transmiter; // CAN初始化
|
||||
extern FlashEEPROM flashEEP;
|
||||
OTAHandler ota;
|
||||
extern "C" {
|
||||
void canfd_rx_irq_handler(void);
|
||||
}
|
||||
|
||||
inline fmc_state_enum write_ADDRESS(u32 address, u32 data) {
|
||||
fmc_unlock();
|
||||
fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR);
|
||||
|
||||
// 确保使用对齐地址
|
||||
fmc_state_enum fmc_status = fmc_word_program(address, data);
|
||||
|
||||
fmc_lock();
|
||||
return fmc_status;
|
||||
}
|
||||
|
||||
u8 OTA_SET(u32 addr, u32 data) {
|
||||
fmc_state_enum fmc_status;
|
||||
u32 temp_val[OTA_CONFIG_NUM];
|
||||
volatile u32 *flash_ptr = (volatile u32 *)addr;
|
||||
temp_val[0] = *flash_ptr;
|
||||
if (temp_val[0] == data) { // 如果相同
|
||||
return FLASH_EEPROM_OK; // 成功
|
||||
}
|
||||
|
||||
fmc_unlock();
|
||||
// 如果不同,且要写0,直接写
|
||||
if (data == OTA_AVAL) {
|
||||
fmc_status = write_ADDRESS(addr, data);
|
||||
fmc_lock();
|
||||
if (fmc_status == FMC_READY) {
|
||||
return FLASH_EEPROM_OK; // 成功可以直接退出
|
||||
}
|
||||
}
|
||||
|
||||
// 如果不同或写入出错,要写1,需要重置,然后再写
|
||||
flash_ptr = (volatile u32 *)n_APP_LATEST_AVAL_ADDR;
|
||||
temp_val[0] = *flash_ptr;
|
||||
flash_ptr = (volatile u32 *)n_APP_BACKUP_AVAL_ADDR;
|
||||
temp_val[1] = *flash_ptr;
|
||||
flash_ptr = (volatile u32 *)n_APP_LATEST_EN_ADDR;
|
||||
temp_val[2] = *flash_ptr;
|
||||
flash_ptr = (volatile u32 *)n_APP_BACKUP_EN_ADDR;
|
||||
temp_val[3] = *flash_ptr;
|
||||
flash_ptr = (volatile u32 *)n_APP_LATEST_CHECK_ADDR;
|
||||
temp_val[4] = *flash_ptr;
|
||||
flash_ptr = (volatile u32 *)n_APP_BACKUP_CHECK_ADDR;
|
||||
temp_val[5] = *flash_ptr;
|
||||
#if EEP_DEBUG
|
||||
printf("OTA_SET\r\n");
|
||||
printf("0x%x_0x%x_0x%x_0x%x\r\n", temp_val[0], temp_val[1], temp_val[2],
|
||||
temp_val[3]);
|
||||
#endif
|
||||
fmc_status = fmc_page_erase(n_APP_LATEST_AVAL_ADDR); // 擦除页
|
||||
if (fmc_status != FMC_READY) {
|
||||
return FLASH_EEPROM_ERROR; // 擦除错误退出
|
||||
}
|
||||
for (int i = 0; i < OTA_CONFIG_NUM; i++) {
|
||||
if (temp_val[i] == OTA_AVAL and
|
||||
n_APP_LATEST_AVAL_ADDR + 4 * i != addr) {
|
||||
fmc_status = write_ADDRESS(n_APP_LATEST_AVAL_ADDR + 4 * i,
|
||||
OTA_AVAL); // 把需要写入0的写入0
|
||||
if (fmc_status != FMC_READY) {
|
||||
fmc_lock();
|
||||
return FLASH_EEPROM_ERROR; // 写入错误退出
|
||||
}
|
||||
}
|
||||
}
|
||||
fmc_lock();
|
||||
return FLASH_EEPROM_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从4字节数组中提取一个32位无符号整数
|
||||
* @param array: 4字节数组
|
||||
* @retval 32位无符号整数
|
||||
*/
|
||||
static inline uint32_t extract_u32_from_4bytes(const uint8_t *array) {
|
||||
return ((uint32_t)array[3] << 24) | ((uint32_t)array[2] << 16) |
|
||||
((uint32_t)array[1] << 8) | (uint32_t)array[0];
|
||||
}
|
||||
void OTAHandler::init() {}
|
||||
|
||||
/**
|
||||
* @brief OTA处理函数
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void OTAHandler::process() {
|
||||
if (ota_state == OTA_STATE_IDLE) {
|
||||
ota_time = 0; // 重置计时器
|
||||
@@ -43,27 +117,36 @@ void OTAHandler::process() {
|
||||
ota_time = 0;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
ota_error = OTA_ERROR_TIMEOUT;
|
||||
send_error_frame(OTA_ERROR_TIMEOUT); // 验证失败
|
||||
volatile u32 *flash_ptr =
|
||||
(volatile u32 *)n_APP_LATEST_CHECK_ADDR; // 如果是实际可以运行
|
||||
u32 if_checked = *flash_ptr;
|
||||
flash_ptr = (volatile u32 *)n_APP_LATEST_AVAL_ADDR; // 如果是实际已刷入
|
||||
u32 if_aval = *flash_ptr;
|
||||
send_error_frame(OTA_ERROR_TIMEOUT); // OTA超时
|
||||
if (if_checked == OTA_AVAL and if_aval == OTA_AVAL) {
|
||||
OTA_SET(n_APP_LATEST_AVAL_ADDR,
|
||||
OTA_AVAL); // 实际可用,设置APP为启用
|
||||
}
|
||||
jumpToApplication();
|
||||
}
|
||||
}
|
||||
|
||||
bool validateApplication() {
|
||||
u32 *app_vector = (u32 *)APP_START_ADDR;
|
||||
u32 *app_vector = (u32 *)APPLATEST_START_ADDR;
|
||||
u32 stack_ptr = app_vector[0];
|
||||
u32 reset_handler = app_vector[1];
|
||||
|
||||
#if DEBUG_OTA
|
||||
printf("APP_START_ADDR: 0x%08X\r\n", APP_START_ADDR);
|
||||
printf("APPLATEST_START_ADDR: 0x%08X\r\n", APPLATEST_START_ADDR);
|
||||
printf("Stack Pointer: 0x%08X\r\n", stack_ptr);
|
||||
printf("Reset Handler: 0x%08X\r\n", reset_handler);
|
||||
printf("APP Range: 0x%08X - 0x%08X\r\n", APP_START_ADDR,
|
||||
APP_START_ADDR + APP_MAX_SIZE);
|
||||
printf("APP Range: 0x%08X - 0x%08X\r\n", APPLATEST_START_ADDR,
|
||||
APPLATEST_START_ADDR + APP_MAX_SIZE);
|
||||
#endif
|
||||
|
||||
// 简单验证:检查栈指针是否在SRAM范围内
|
||||
bool stack_valid = (stack_ptr >= 0x20000000 && stack_ptr < 0x20008000);
|
||||
bool reset_valid = (reset_handler >= APP_START_ADDR &&
|
||||
reset_handler < (APP_START_ADDR + APP_MAX_SIZE));
|
||||
bool reset_valid = (reset_handler >= APPLATEST_START_ADDR &&
|
||||
reset_handler < (APPLATEST_START_ADDR + APP_MAX_SIZE));
|
||||
|
||||
#if DEBUG_OTA
|
||||
if (!stack_valid) {
|
||||
@@ -77,6 +160,11 @@ bool validateApplication() {
|
||||
return stack_valid && reset_valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 跳转应用处理模块
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void OTAHandler::jumpToApplication() {
|
||||
#if DEBUG_OTA
|
||||
printf("try jump to app\r\n");
|
||||
@@ -90,6 +178,8 @@ void OTAHandler::jumpToApplication() {
|
||||
}
|
||||
printf("jumping1\r\n");
|
||||
#endif
|
||||
OTA_SET(n_APP_LATEST_AVAL_ADDR, OTA_AVAL); // 设置APP为可用
|
||||
OTA_SET(n_APP_LATEST_EN_ADDR, OTA_AVAL); // 设置APP为激活
|
||||
// 1. 关闭所有中断
|
||||
__disable_irq();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
@@ -117,11 +207,11 @@ void OTAHandler::jumpToApplication() {
|
||||
printf("jumping3\r\n");
|
||||
#endif
|
||||
// 5. 设置中断向量表偏移到应用程序起始地址
|
||||
SCB->VTOR = APP_START_ADDR;
|
||||
SCB->VTOR = APPLATEST_START_ADDR;
|
||||
|
||||
// 6. 设置MSP并跳转
|
||||
uint32_t msp_value = *(__IO uint32_t *)APP_START_ADDR;
|
||||
uint32_t reset_handler = *(__IO uint32_t *)(APP_START_ADDR + 4);
|
||||
uint32_t msp_value = *(__IO uint32_t *)APPLATEST_START_ADDR;
|
||||
uint32_t reset_handler = *(__IO uint32_t *)(APPLATEST_START_ADDR + 4);
|
||||
typedef void (*AppEntryFunc)(void);
|
||||
AppEntryFunc app_entry = (AppEntryFunc)reset_handler;
|
||||
#if DEBUG_OTA
|
||||
@@ -151,8 +241,8 @@ void OTAHandler::eraseApplicationArea() {
|
||||
__disable_irq();
|
||||
|
||||
fmc_state_enum fmc_status;
|
||||
for (u32 addr = APP_START_ADDR; addr < (APP_START_ADDR + APP_MAX_SIZE);
|
||||
addr += FMC_PAGE_SIZE) {
|
||||
for (u32 addr = APPLATEST_START_ADDR;
|
||||
addr < (APPLATEST_START_ADDR + APP_MAX_SIZE); addr += FMC_PAGE_SIZE) {
|
||||
fmc_status = fmc_page_erase(addr);
|
||||
if (fmc_status != FMC_READY) {
|
||||
// 如果擦除失败,记录错误并退出
|
||||
@@ -181,7 +271,7 @@ void OTAHandler::eraseApplicationArea() {
|
||||
*/
|
||||
void OTAHandler::writeApplicationData(u32 offset, u8 *data, u32 size) {
|
||||
fmc_unlock();
|
||||
u32 write_addr = APP_START_ADDR + offset;
|
||||
u32 write_addr = APPLATEST_START_ADDR + offset;
|
||||
|
||||
u32 i = 0;
|
||||
u8 *src = data;
|
||||
@@ -207,29 +297,6 @@ void OTAHandler::writeApplicationData(u32 offset, u8 *data, u32 size) {
|
||||
fmc_lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 验证应用程序数据
|
||||
* @param offset: 写入偏移量
|
||||
* @param data: 原始数据指针
|
||||
* @param size: 数据大小
|
||||
* @retval true if verification passes, false otherwise
|
||||
*/
|
||||
bool OTAHandler::verifyApplicationData(u32 offset, u8 *data, u32 size) {
|
||||
u32 verify_addr = APP_START_ADDR + offset;
|
||||
|
||||
for (u32 i = 0; i < size; i++) {
|
||||
if (((u8 *)verify_addr)[i] != data[i]) {
|
||||
#if DEBUG_OTA
|
||||
printf("Data verification failed at offset %d, expected 0x%02X, "
|
||||
"got 0x%02X\r\n",
|
||||
i, data[i], ((u8 *)verify_addr)[i]);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 处理OTA数据包
|
||||
* @param id: CAN帧ID
|
||||
@@ -318,7 +385,7 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
|
||||
ota_state = OTA_STATE_RECEIVING_FIRMWARE;
|
||||
} else if (len == 2 and ota_state == OTA_STATE_FINISHED) {
|
||||
#if DEBUG_OTA
|
||||
printf("stage8:OTA_STATE_FINISHED\r\n");
|
||||
printf("stage--:OTA_STATE_FINISHED\r\n");
|
||||
#endif
|
||||
u8 send_data[2] = {0x0A, 0xAC}; // 确认开始传输
|
||||
// 4. 验证成功 - 发送最终ACK
|
||||
@@ -423,6 +490,12 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 发送错误帧
|
||||
* @param error: 错误码
|
||||
* @retval 无
|
||||
*/
|
||||
|
||||
void send_error_frame(u8 error) {
|
||||
u8 error_frame[1] = {error};
|
||||
CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 1, error_frame);
|
||||
@@ -462,6 +535,103 @@ void getDeviceSerialNumberString(char *str) {
|
||||
str[24] = '\0'; // 确保字符串结束
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将0x08010500地址后0xC000大小区域内的数据搬运到0x08011000地址
|
||||
* @param None
|
||||
* @retval fmc_state_enum: 操作状态
|
||||
*/
|
||||
fmc_state_enum move_app_data() {
|
||||
fmc_state_enum fmc_status = FMC_READY;
|
||||
|
||||
// 关闭全局中断以防止Flash操作期间的中断干扰
|
||||
__disable_irq();
|
||||
fmc_unlock();
|
||||
|
||||
// 首先擦除目标地址的Flash页面
|
||||
uint32_t num_pages =
|
||||
(APP_MAX_SIZE + FMC_PAGE_SIZE - 1) / FMC_PAGE_SIZE; // 向上取整
|
||||
|
||||
for (uint32_t i = 0; i < num_pages; i++) {
|
||||
uint32_t page_addr = APPLATEST_START_ADDR + i * FMC_PAGE_SIZE;
|
||||
|
||||
// 擦除页面
|
||||
fmc_status = fmc_page_erase(page_addr);
|
||||
if (fmc_status != FMC_READY) {
|
||||
fmc_lock();
|
||||
#if OTA_DEBUG
|
||||
printf("move_app_data erase error\r\n");
|
||||
#endif
|
||||
__enable_irq(); // 重新开启中断
|
||||
return fmc_status;
|
||||
}
|
||||
}
|
||||
|
||||
// 复制数据 - 按字(32位)进行复制以提高效率
|
||||
uint32_t offset = 0;
|
||||
uint32_t write_count = 0; // 记录实际写入的字数
|
||||
const uint32_t *src_ptr = (const uint32_t *)APPLATEST_START_ADDR;
|
||||
uint32_t *dst_ptr = (uint32_t *)APPLATEST_START_ADDR;
|
||||
|
||||
// 预计算源数据的CRC,避免重复访问内存
|
||||
crc_deinit();
|
||||
crc_data_register_reset();
|
||||
uint32_t src_crc = crc_block_data_calculate(
|
||||
(uint32_t *)APPBACK_START_ADDR, APP_MAX_SIZE / 4);
|
||||
|
||||
while (offset < APP_MAX_SIZE) {
|
||||
uint32_t src_data = src_ptr[offset / 4];
|
||||
|
||||
// 检查源地址是否为有效的Flash数据(非0xFFFFFFFF表示有数据)
|
||||
if (src_data != 0xFFFFFFFF) {
|
||||
// 清除之前的标志位
|
||||
fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR |
|
||||
FMC_FLAG_PGERR);
|
||||
|
||||
fmc_status =
|
||||
fmc_word_program(APPLATEST_START_ADDR + offset, src_data);
|
||||
|
||||
// 检查写入操作是否成功
|
||||
if (fmc_status != FMC_READY) {
|
||||
#if OTA_DEBUG
|
||||
printf(
|
||||
"Flash write failed at offset 0x%08X with status: %d\r\n",
|
||||
offset, fmc_status);
|
||||
#endif
|
||||
fmc_lock();
|
||||
__enable_irq(); // 重新开启中断
|
||||
return fmc_status;
|
||||
}
|
||||
write_count++;
|
||||
}
|
||||
offset += 4;
|
||||
|
||||
// 每写入一定数量的数据后,喂狗一次
|
||||
if ((offset % 4096) == 0) { // 每4KB喂狗一次
|
||||
fwdgt_counter_reload();
|
||||
}
|
||||
}
|
||||
|
||||
fmc_lock();
|
||||
|
||||
// 重新开启全局中断
|
||||
__enable_irq();
|
||||
crc_data_register_reset(); // 确保CRC计算从初始状态开始
|
||||
|
||||
// 计算目标数据的CRC值
|
||||
uint32_t dst_crc = crc_block_data_calculate(
|
||||
(uint32_t *)APPLATEST_START_ADDR, APP_MAX_SIZE / 4);
|
||||
|
||||
// 比较CRC值,确保数据完整性
|
||||
if (src_crc != dst_crc) {
|
||||
#if OTA_DEBUG
|
||||
printf("CRC mismatch: src_crc=0x%08X, dst_crc=0x%08X\r\n", src_crc,
|
||||
dst_crc);
|
||||
#endif
|
||||
return (fmc_state_enum)0xFF; // CRC校验失败
|
||||
}
|
||||
return fmc_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 带密钥的CRC32校验函数
|
||||
*
|
||||
|
||||
@@ -57,4 +57,6 @@ void calculate_crc32_with_key(const uint8_t *key, const uint8_t *data,
|
||||
u8 *output);
|
||||
void send_error_frame(uint8_t error);
|
||||
bool validateApplication();
|
||||
fmc_state_enum move_app_data();
|
||||
|
||||
#endif
|
||||
+21
-6
@@ -7,17 +7,33 @@
|
||||
#define CAN_DEBUG 0
|
||||
|
||||
// Flash分区配置
|
||||
constexpr u32 BOOTLOADER_SIZE = 0x4000; // 16KB
|
||||
constexpr u32 APP_START_ADDR = 0x08010000; // APP起始地址 0x08004000
|
||||
constexpr u32 APP2_START_ADDR = 0x08010000; // APP2起始地址
|
||||
constexpr u32 APP_MAX_SIZE = 0xC000; // 48KB
|
||||
constexpr u32 FMC_PAGE_SIZE = 0x400; // 1KB
|
||||
constexpr u32 BOOTLOADER_SIZE = 0x4000; // 16KB
|
||||
constexpr u32 BOOTLOADER_START_ADDR = 0x08000000; // BOOT起始地址
|
||||
constexpr u32 APPLATEST_START_ADDR = 0x08011000; // APP起始地址
|
||||
constexpr u32 APPBACK_START_ADDR = 0x08005000; // APPBACK起始地址
|
||||
constexpr u32 APP_MAX_SIZE = 0xC000; // 48KB
|
||||
constexpr u32 FMC_PAGE_SIZE = 0x400; // 1KB
|
||||
|
||||
|
||||
// BOOT 相关
|
||||
constexpr u32 OTA_CONFIG_NUM = 6;
|
||||
constexpr u32 n_APP_LATEST_AVAL_ADDR = 0x0801D000; // 最新APP可用地址
|
||||
constexpr u32 n_APP_BACKUP_AVAL_ADDR = 0x0801D004; // 备份APP可用地址
|
||||
constexpr u32 n_APP_LATEST_EN_ADDR = 0x0801D008; // 最新APP激活
|
||||
constexpr u32 n_APP_BACKUP_EN_ADDR = 0x0801D00C; // 备份APP激活
|
||||
constexpr u32 n_APP_LATEST_CHECK_ADDR = 0x0801D010; // 最新APP校验
|
||||
constexpr u32 n_APP_BACKUP_CHECK_ADDR = 0x0801D014; // 备份APP校验
|
||||
constexpr u32 OTA_NOT_AVAL = 0xFFFFFFFF;
|
||||
constexpr u32 OTA_AVAL = 0x00000000; // 全零表示可用
|
||||
constexpr u32 FLASH_EEPROM_OK = 0;
|
||||
constexpr u32 FLASH_EEPROM_ERROR = 1;
|
||||
|
||||
// CANFD配置
|
||||
constexpr u32 CANFD_OTA_REQ_ID = 0x00000100;
|
||||
constexpr u32 CANFD_OTA_DATA_ID = 0x00000101;
|
||||
constexpr u32 CANFD_OTA_ACK_ID = 0x00000102;
|
||||
constexpr u32 CANFD_OTA_WAIT_ID = 0x00000103;
|
||||
constexpr u32 CANFD_OTA_CANCEL_ID = 0x00000000;
|
||||
|
||||
// 设备唯一ID寄存器地址 (GD32C10x系列)
|
||||
constexpr u32 DEVICE_SERIAL_ADDR_MSB = 0x1FFFF7E8; // 最高32位
|
||||
@@ -33,7 +49,6 @@ typedef union {
|
||||
u8 b[4];
|
||||
} u32_union_t;
|
||||
|
||||
|
||||
// 全局变量(需在安全区域存储)
|
||||
constexpr uint8_t K_master[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB,
|
||||
0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98,
|
||||
|
||||
@@ -52,55 +52,4 @@ FlashEepromStatus FlashEEPROM::format() {
|
||||
}
|
||||
fmc_lock();
|
||||
return FLASH_EEPROM_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 保存CRC数据到Flash
|
||||
* @return FlashEepromStatus: 状态
|
||||
*/
|
||||
FlashEepromStatus FlashEEPROM::writeCRC(u32 CRC_NUM) {
|
||||
static u32 next_address;
|
||||
// 遍历Flash页面寻找下一个可写入crc的位置
|
||||
for (u32 address = EEPROM_DATA_START_ADDRESS - SIZE_U32;
|
||||
address > EEPROM_START_ADDRESS; address -= SIZE_U32) {
|
||||
// 安全读取Flash数据
|
||||
volatile u32 *flash_ptr = (volatile u32 *)address;
|
||||
u32 data_word = *flash_ptr;
|
||||
// 找到空位置
|
||||
if (data_word == 0xFFFFFFFF) {
|
||||
next_address = address;
|
||||
break;
|
||||
}
|
||||
// 更新下一个可能的写入位置(如果需要格式化)
|
||||
next_address = address - SIZE_U32;
|
||||
}
|
||||
|
||||
// 如果当前CRC与现在的crc值不同,则写入
|
||||
if (*((u32 *)next_address) != CRC_NUM) {
|
||||
// 如果有足够空间,直接写入crc值
|
||||
if (next_address > EEPROM_START_ADDRESS) {
|
||||
fmc_unlock();
|
||||
fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR);
|
||||
fmc_state_enum fmc_status = fmc_word_program(next_address, CRC_NUM);
|
||||
fmc_lock();
|
||||
#if EEPDEBUG
|
||||
printf("CRC cmp1,0x%X_0x%x \r\n", CRC_NUM, *((u32 *)next_address));
|
||||
#endif
|
||||
|
||||
// 检查写入是否成功
|
||||
if (fmc_status != FMC_READY) {
|
||||
EEPROMStatus = fmc_status;
|
||||
return FLASH_EEPROM_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 重新读取CRC校验
|
||||
if (CRC_NUM == *((u32 *)next_address)) {
|
||||
EEPROMStatus = FLASH_EEPROM_OK; // 设置EEPROM状态
|
||||
return FLASH_EEPROM_OK;
|
||||
} else {
|
||||
EEPROMStatus = FLASH_EEPROM_CRC_ERROR; // 设置EEPROM错误状态
|
||||
return FLASH_EEPROM_CRC_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <cstdio>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
|
||||
/* retarget the C library printf function to the USART */
|
||||
u8 USART0_init() {
|
||||
@@ -36,6 +37,102 @@ void unused_pin_init() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 扫描APP地址范围内的Flash内容
|
||||
* @param print_content 是否打印Flash内容,默认为true
|
||||
* @param page_count 扫描的页数,默认为0表示扫描整个APP区域
|
||||
* @retval 无
|
||||
*/
|
||||
void scanAppFlashContent(bool print_content = true, u32 page_count = 0) {
|
||||
u32 start_addr = APPLATEST_START_ADDR;
|
||||
u32 total_size = 0xC000;
|
||||
|
||||
// 如果指定了页数,则按页数计算大小
|
||||
if (page_count > 0) {
|
||||
total_size = page_count * FMC_PAGE_SIZE;
|
||||
}
|
||||
|
||||
u32 end_addr = start_addr + total_size;
|
||||
|
||||
#if DEBUG_OTA
|
||||
printf("Scanning Flash from 0x%08X to 0x%08X (%d bytes)\r\n", start_addr,
|
||||
end_addr, total_size);
|
||||
#endif
|
||||
|
||||
u32 page_count_scanned = 0;
|
||||
u32 empty_pages = 0;
|
||||
u32 data_pages = 0;
|
||||
|
||||
for (u32 addr = start_addr; addr < end_addr; addr += FMC_PAGE_SIZE) {
|
||||
bool page_empty = true;
|
||||
|
||||
// 检查当前页是否全为0xFF(空页)
|
||||
for (u32 offset = 0; offset < FMC_PAGE_SIZE; offset += 4) {
|
||||
u32 data = *(u32 *)(addr + offset);
|
||||
|
||||
if (data != 0xFFFFFFFF) {
|
||||
page_empty = false;
|
||||
break; // 找到非空数据,立即退出检查
|
||||
}
|
||||
}
|
||||
|
||||
if (page_empty) {
|
||||
empty_pages++;
|
||||
} else {
|
||||
data_pages++;
|
||||
|
||||
// 只有在非空页面且需要打印时才输出内容
|
||||
if (print_content) {
|
||||
printf("Page 0x%08X: \r\n", addr);
|
||||
|
||||
// 打印所有内容
|
||||
for (u32 offset = 0; offset < FMC_PAGE_SIZE;
|
||||
offset += 16) { // 每行打印16字节
|
||||
// 打印地址偏移
|
||||
printf(" +%03X: ", offset);
|
||||
|
||||
// 打印十六进制数据
|
||||
for (u32 byte_idx = 0; byte_idx < 16; byte_idx++) {
|
||||
if ((offset + byte_idx) < FMC_PAGE_SIZE) {
|
||||
u8 data = *(__IO u8 *)(addr + offset + byte_idx);
|
||||
printf("%02X ", data);
|
||||
} else {
|
||||
printf(" "); // 空白填充
|
||||
}
|
||||
|
||||
// 每8字节加个小空格,便于阅读
|
||||
if (byte_idx == 7) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
// 打印可打印字符
|
||||
printf("|");
|
||||
for (u32 byte_idx = 0; byte_idx < 16; byte_idx++) {
|
||||
if ((offset + byte_idx) < FMC_PAGE_SIZE) {
|
||||
u8 data = *(__IO u8 *)(addr + offset + byte_idx);
|
||||
if (data >= 32 && data <= 126) { // 可打印字符范围
|
||||
printf("%c", data);
|
||||
} else {
|
||||
printf(".");
|
||||
}
|
||||
} else {
|
||||
printf(" "); // 空白填充
|
||||
}
|
||||
}
|
||||
printf("|\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
page_count_scanned++;
|
||||
}
|
||||
|
||||
#if DEBUG_OTA
|
||||
printf("Scan complete: %d pages scanned, %d empty pages, %d data pages\r\n",
|
||||
page_count_scanned, empty_pages, data_pages);
|
||||
#endif
|
||||
}
|
||||
|
||||
// // 发送单个字节到串口 (用于调试)
|
||||
// void uart_send_byte(uint8_t data) {
|
||||
|
||||
@@ -34,12 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "systick.h"
|
||||
#include "Can.h"
|
||||
#include "flash.h"
|
||||
#include "gd32c10x.h"
|
||||
|
||||
volatile static uint32_t delay;
|
||||
extern CAN_transmiter CAN0_transmiter;
|
||||
extern FlashEEPROM flashEEP;
|
||||
|
||||
/*!
|
||||
\brief configure systick
|
||||
|
||||
Reference in New Issue
Block a user