Files
GD32_BOOT/Robot_V2/sys/OTA.cpp
T

156 lines
3.9 KiB
C++
Raw Normal View History

2025-12-25 12:07:06 +08:00
#include "OTA.h"
#include "gd32c10x_fmc.h"
2025-12-27 19:20:23 +08:00
#include "systick.h"
#include <cstdio>
2025-12-25 12:07:06 +08:00
#include <cstring>
2025-12-27 19:20:23 +08:00
#include <flash.h>
#include <stdint.h>
2025-12-25 12:07:06 +08:00
extern CAN_transmiter CAN0_transmiter; // CAN初始化
2025-12-27 19:20:23 +08:00
extern FlashEEPROM flashEEP;
OTAHandler ota;
2025-12-25 12:07:06 +08:00
extern "C" {
void canfd_rx_irq_handler(void);
}
2025-12-27 19:20:23 +08:00
#define DEBUG_OTA 1
2025-12-25 12:07:06 +08:00
2025-12-27 19:20:23 +08:00
void OTAHandler::init() {}
2025-12-25 12:07:06 +08:00
void OTAHandler::process() {
2025-12-27 19:20:23 +08:00
if (!ota_active) {
ota_time = 0; // 重置计时器
static u8 zero[1] = {ota_active};
CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_WAIT_ID, 0, zero);
#ifdef DEBUG_OTA
printf("wait OTA%d\r\n", ota_active);
#endif
delay_1ms(10);
2025-12-25 12:07:06 +08:00
return;
2025-12-27 19:20:23 +08:00
} else {
delay_1ms(1);
ota_time++;
}
2025-12-25 12:07:06 +08:00
2025-12-27 19:20:23 +08:00
// 检查是否超时(例如:10秒无数据则退出OTA模式)
if (ota_time > 10000) { // 10秒超时(10000 x 1ms)
ota_time = 0;
ota_active = false;
}
2025-12-25 12:07:06 +08:00
}
bool OTAHandler::validateApplication() {
2025-12-27 19:20:23 +08:00
u32 *app_vector = (u32 *)APP_START_ADDR;
u32 stack_ptr = app_vector[0];
u32 reset_handler = app_vector[1];
2025-12-25 12:07:06 +08:00
// 简单验证:检查栈指针是否在SRAM范围内
return (stack_ptr >= 0x20000000 && stack_ptr < 0x20008000) &&
(reset_handler >= APP_START_ADDR &&
reset_handler < (APP_START_ADDR + APP_MAX_SIZE));
}
void OTAHandler::jumpToApplication() {
2025-12-27 19:20:23 +08:00
if (!validateApplication()) return;
// 1. 关闭所有中断
__disable_irq();
for (int i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
}
// 2. 重置外设(特别是CAN,防止冲突)
can_deinit(CAN0);
// 3. 重置系统时钟到默认状态
rcu_system_clock_source_config(RCU_CKSYSSRC_IRC8M);
// 4. 关闭一些关键外设时钟
rcu_periph_clock_disable(RCU_GPIOA);
rcu_periph_clock_disable(RCU_GPIOB);
rcu_periph_clock_disable(RCU_GPIOC);
rcu_periph_clock_disable(RCU_USART0);
rcu_periph_clock_disable(RCU_CAN0);
rcu_periph_clock_disable(RCU_TIMER0);
rcu_periph_clock_disable(RCU_DMA0);
// 5. 设置MSP并跳转
uint32_t msp_value = *(__IO uint32_t*)APP_START_ADDR;
__set_MSP(msp_value);
uint32_t reset_handler = *(__IO uint32_t*)(APP_START_ADDR + 4);
typedef void (*AppEntryFunc)(void);
AppEntryFunc app_entry = (AppEntryFunc)reset_handler;
// 6. 跳转
app_entry();
2025-12-25 12:07:06 +08:00
}
void OTAHandler::eraseApplicationArea() {
// 擦除APP区域
fmc_unlock();
2025-12-27 19:20:23 +08:00
for (u32 addr = APP_START_ADDR; addr < (APP_START_ADDR + APP_MAX_SIZE);
2025-12-25 12:07:06 +08:00
addr += FMC_PAGE_SIZE) {
fmc_page_erase(addr);
}
fmc_lock();
}
2025-12-27 19:20:23 +08:00
void OTAHandler::writeApplicationData(u32 offset, u8 *data, u32 size) {
2025-12-25 12:07:06 +08:00
fmc_unlock();
2025-12-27 19:20:23 +08:00
u32 write_addr = APP_START_ADDR + offset;
2025-12-25 12:07:06 +08:00
// 32位对齐写入
2025-12-27 19:20:23 +08:00
for (u32 i = 0; i < size; i += 4) {
u32 word = 0;
2025-12-25 12:07:06 +08:00
memcpy(&word, &data[i], 4);
fmc_word_program(write_addr + i, word);
}
fmc_lock();
}
2025-12-27 19:20:23 +08:00
void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
2025-12-25 12:07:06 +08:00
if (id == CANFD_OTA_REQ_ID) {
2025-12-27 19:20:23 +08:00
#ifdef DEBUG_OTA
printf("req OTA\r\n");
#endif
2025-12-25 12:07:06 +08:00
// OTA请求包
2025-12-27 19:20:23 +08:00
u32 new_size = *(u32 *)data;
2025-12-25 12:07:06 +08:00
if (new_size <= APP_MAX_SIZE) {
expected_size = new_size;
received_size = 0;
2025-12-27 19:20:23 +08:00
// eraseApplicationArea();
2025-12-25 12:07:06 +08:00
ota_active = true;
2025-12-27 19:20:23 +08:00
sendACK(new_size); // 确认开始
#ifdef DEBUG_OTA
printf("start OTA%d\r\n", ota_active);
#endif
2025-12-25 12:07:06 +08:00
}
} else if (id == CANFD_OTA_DATA_ID && ota_active) {
// 数据包格式:[4字节包序号][实际数据]
if (len >= 4) {
2025-12-27 19:20:23 +08:00
u32 packet_num = *(u32 *)data;
u32 offset = packet_num * (len - 4);
2025-12-25 12:07:06 +08:00
if (offset < expected_size) {
2025-12-27 19:20:23 +08:00
writeApplicationData(offset, &data[4], len - 4); // 写入数据
2025-12-25 12:07:06 +08:00
received_size += (len - 4);
2025-12-27 19:20:23 +08:00
sendACK(packet_num); // 确认ACK
ota_time = 0; // 重置计时器
2025-12-25 12:07:06 +08:00
// 检查是否完成
if (received_size >= expected_size) {
ota_active = false;
// 跳转前延时让ACK发出
for (volatile int i = 0; i < 100000; i++)
;
jumpToApplication();
}
}
}
}
}
2025-12-27 19:20:23 +08:00
void OTAHandler::sendACK(u32 packet_num) {
2025-12-25 12:07:06 +08:00
CAN0_transmiter.sendACK(CANFD_OTA_ACK_ID, packet_num);
}