feat(ota): 修复备份APP区域恢复功能和OTA流程优化、启用BRS、减小延时
- 添加sendBackup方法用于在备份APP激活时发送确认消息 - 优化OTA跳转逻辑,在jumpToApplication中清除复位标志 - 修复move_app_data函数中数据源地址错误,从备份区域正确读取数据 - 在OTA流程中正确设置APP状态标志,确保应用验证状态管理 refactor(can): 清理调试代码和函数签名优化 - 移除调试用的printf语句和未使用的cstdio头文件 - 统一函数参数类型为u8和u32,提高代码一致性 - 优化CAN通信检查逻辑,移除冗余的调试输出 perf(ota): 优化OTA处理中的延时函数 - 将delay_1ms(1)改为delay_1us(100),提高延时精度 - 添加微秒级延时函数delay_1us实现 - 增加OTA超时时间从10秒到100秒 fix(ota): 修复OTA状态管理和错误处理 - 在各种错误情况下正确设置ota_state为OTA_STATE_IDLE - 在eraseApplicationArea中正确初始化APP状态标志 - 添加CRC校验失败时的调试输出选项 - 修复数据包大小验证逻辑
This commit is contained in:
+25
-15
@@ -108,7 +108,7 @@ void OTAHandler::process() {
|
||||
delay_1ms(10);
|
||||
return;
|
||||
} else {
|
||||
delay_1ms(1);
|
||||
delay_1us(100);
|
||||
ota_time++;
|
||||
}
|
||||
|
||||
@@ -126,8 +126,8 @@ void OTAHandler::process() {
|
||||
if (if_checked == OTA_AVAL and if_aval == OTA_AVAL) {
|
||||
OTA_SET(n_APP_LATEST_AVAL_ADDR,
|
||||
OTA_AVAL); // 实际可用,设置APP为启用
|
||||
jumpToApplication();
|
||||
}
|
||||
jumpToApplication();
|
||||
}
|
||||
}
|
||||
bool validateApplication() {
|
||||
@@ -218,7 +218,11 @@ void OTAHandler::jumpToApplication() {
|
||||
printf("jumping5, MSP:0x%08X, Reset Handler:0x%08X\r\n", msp_value,
|
||||
reset_handler);
|
||||
#endif
|
||||
|
||||
__set_MSP(msp_value);
|
||||
|
||||
// 在跳转前清除复位标志
|
||||
rcu_all_reset_flag_clear();
|
||||
// 7. 跳转
|
||||
app_entry();
|
||||
|
||||
@@ -234,6 +238,9 @@ void OTAHandler::jumpToApplication() {
|
||||
* @retval 无
|
||||
*/
|
||||
void OTAHandler::eraseApplicationArea() {
|
||||
OTA_SET(n_APP_LATEST_CHECK_ADDR, OTA_NOT_AVAL); // 设置APP为未确认
|
||||
OTA_SET(n_APP_LATEST_EN_ADDR, OTA_NOT_AVAL); // 设置APP为未激活
|
||||
OTA_SET(n_APP_LATEST_AVAL_ADDR, OTA_NOT_AVAL); // 设置APP为不可用
|
||||
// 擦除APP区域
|
||||
fmc_unlock();
|
||||
|
||||
@@ -338,6 +345,10 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
|
||||
0) {
|
||||
ota_error = OTA_ERROR_INVALID_CRC;
|
||||
send_error_frame(OTA_ERROR_INVALID_CRC);
|
||||
#if DEBUG_OTA
|
||||
std::printf("CRC32 :%x,%x!\r\n", receive_dataCRC32[0],
|
||||
calculated_dataCRC32[0]);
|
||||
#endif
|
||||
receive_packet_num -= 1;
|
||||
} else {
|
||||
// 写入Flash前验证数据
|
||||
@@ -347,6 +358,7 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
|
||||
OTA_PACKET_SIZE);
|
||||
} else {
|
||||
ota_error = OTA_ERROR_INVALID_SIZE;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(OTA_ERROR_INVALID_SIZE);
|
||||
}
|
||||
}
|
||||
@@ -374,11 +386,13 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
|
||||
received_size = 0;
|
||||
} else {
|
||||
ota_error = OTA_ERROR_INVALID_SIZE;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(OTA_ERROR_INVALID_SIZE);
|
||||
return;
|
||||
}
|
||||
u8 send_data[6] = {0xBA, 0xC0, 0x00,
|
||||
0x00, 0x00, 0x00}; // 确认开始传输
|
||||
|
||||
eraseApplicationArea();
|
||||
// 发送接收包0请求
|
||||
CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 6, send_data);
|
||||
@@ -393,6 +407,7 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
|
||||
|
||||
} else {
|
||||
ota_error = OTA_ERROR_INVALID_PACKET;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(OTA_ERROR_INVALID_PACKET);
|
||||
}
|
||||
} else if (id == CANFD_OTA_REQ_ID) {
|
||||
@@ -471,7 +486,7 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
|
||||
// 验证失败 - 可能密钥错误或攻击
|
||||
ota_error = OTA_ERROR_INVALID_KEY;
|
||||
send_error_frame(OTA_ERROR_INVALID_KEY); // 验证失败
|
||||
// reset_ota_state();
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -484,6 +499,7 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
|
||||
} else {
|
||||
// 其他握手异常
|
||||
ota_error = OTA_ERROR_INVALID_HANDSHAKE;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(OTA_ERROR_INVALID_HANDSHAKE);
|
||||
return;
|
||||
}
|
||||
@@ -569,17 +585,16 @@ fmc_state_enum move_app_data() {
|
||||
// 复制数据 - 按字(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;
|
||||
const uint32_t *src_ptr = (const uint32_t *)APPBACK_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);
|
||||
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];
|
||||
uint32_t src_data = src_ptr[offset / 4]; // 从备份区域读取数据
|
||||
|
||||
// 检查源地址是否为有效的Flash数据(非0xFFFFFFFF表示有数据)
|
||||
if (src_data != 0xFFFFFFFF) {
|
||||
@@ -588,7 +603,7 @@ fmc_state_enum move_app_data() {
|
||||
FMC_FLAG_PGERR);
|
||||
|
||||
fmc_status =
|
||||
fmc_word_program(APPLATEST_START_ADDR + offset, src_data);
|
||||
fmc_word_program(APPLATEST_START_ADDR + offset, src_data); // 写入到最新APP区域
|
||||
|
||||
// 检查写入操作是否成功
|
||||
if (fmc_status != FMC_READY) {
|
||||
@@ -604,11 +619,6 @@ fmc_state_enum move_app_data() {
|
||||
write_count++;
|
||||
}
|
||||
offset += 4;
|
||||
|
||||
// 每写入一定数量的数据后,喂狗一次
|
||||
if ((offset % 4096) == 0) { // 每4KB喂狗一次
|
||||
fwdgt_counter_reload();
|
||||
}
|
||||
}
|
||||
|
||||
fmc_lock();
|
||||
@@ -710,4 +720,4 @@ void calculate_crc32_with_key(const uint8_t *key, const uint8_t *data,
|
||||
output[1] = (uint8_t)(crc >> 8);
|
||||
output[2] = (uint8_t)(crc >> 16);
|
||||
output[3] = (uint8_t)(crc >> 24);
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -10,20 +10,20 @@
|
||||
class OTAHandler {
|
||||
public:
|
||||
u32 ota_stateota_time;
|
||||
uint32_t received_size;
|
||||
uint32_t expected_size;
|
||||
u32 received_size;
|
||||
u32 expected_size;
|
||||
|
||||
void init();
|
||||
void process();
|
||||
bool isActive() const { return ota_state; }
|
||||
|
||||
void handleOTAMessage(uint32_t id, uint8_t *data, uint8_t len);
|
||||
void handleOTAMessage(u32 id, u8 *data, u8 len);
|
||||
void jumpToApplication();
|
||||
|
||||
private:
|
||||
u16 ota_time;
|
||||
u32 ota_time;
|
||||
void eraseApplicationArea();
|
||||
void writeApplicationData(uint32_t offset, uint8_t *data, uint32_t size);
|
||||
void writeApplicationData(u32 offset, u8 *data, u32 size);
|
||||
bool verifyApplicationData(u32 offset, u8 *data, u32 size);
|
||||
typedef enum {
|
||||
OTA_STATE_IDLE = 0,
|
||||
@@ -44,18 +44,18 @@ class OTAHandler {
|
||||
OTA_ERROR_INVALID_SIZE
|
||||
} ota_error_t;
|
||||
|
||||
uint8_t device_uid[12]; // 从GD32 UID寄存器读取
|
||||
uint8_t current_K_session[16];
|
||||
uint8_t nonce_server[16];
|
||||
u8 device_uid[12]; // 从GD32 UID寄存器读取
|
||||
u8 current_K_session[16];
|
||||
u8 nonce_server[16];
|
||||
|
||||
aes128_context aes_ctx; // AES上下文
|
||||
ota_state_t ota_state = OTA_STATE_IDLE;
|
||||
ota_error_t ota_error = OTA_ERROR_NONE;
|
||||
};
|
||||
void getDeviceSerialNumber(uint8_t *buffer);
|
||||
void calculate_crc32_with_key(const uint8_t *key, const uint8_t *data,
|
||||
void getDeviceSerialNumber(u8 *buffer);
|
||||
void calculate_crc32_with_key(const u8 *key, const u8 *data,
|
||||
u8 *output);
|
||||
void send_error_frame(uint8_t error);
|
||||
void send_error_frame(u8 error);
|
||||
bool validateApplication();
|
||||
fmc_state_enum move_app_data();
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ constexpr uint8_t K_master[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB,
|
||||
0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98,
|
||||
0x76, 0x54, 0x32, 0x10}; // 预置主密钥
|
||||
// 其他
|
||||
constexpr u32 OTA_TIMEOUT = 10000;
|
||||
constexpr u32 OTA_TIMEOUT = 100000;
|
||||
constexpr u8 SIZE_U32 = sizeof(uint32_t);
|
||||
constexpr u8 SIZE_FLOAT = sizeof(float);
|
||||
#endif
|
||||
@@ -56,6 +56,24 @@ void systick_config(void) {
|
||||
NVIC_SetPriority(SysTick_IRQn, 0x00U);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief delay a time in microseconds
|
||||
\param[in] count: count in microseconds
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void delay_1us(uint32_t count) {
|
||||
/* 计算循环次数以实现微秒延时
|
||||
假设CPU每执行一条nop指令需要1个时钟周期
|
||||
根据系统时钟频率计算需要的循环次数 */
|
||||
uint32_t cycles = (SystemCoreClock / 4000000UL) * count; // 每微秒的时钟周期数
|
||||
|
||||
/* 循环减去执行指令所需的周期数 */
|
||||
for(uint32_t i = 0; i < cycles; i++) {
|
||||
__NOP(); // 空操作指令
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief delay a time in milliseconds
|
||||
\param[in] count: count in milliseconds
|
||||
|
||||
@@ -44,6 +44,8 @@ extern "C" {
|
||||
void systick_config(void);
|
||||
/* delay a time in milliseconds */
|
||||
void delay_1ms(uint32_t count);
|
||||
/* delay a time in microseconds */
|
||||
void delay_1us(uint32_t count);
|
||||
/* delay a time in seconds */
|
||||
void delay_1s(uint32_t count);
|
||||
/* delay decrement */
|
||||
|
||||
Reference in New Issue
Block a user