Files
GD32_BOOT/Robot_V2/sys/OTA.cpp
T
2025-12-25 12:07:06 +08:00

120 lines
2.9 KiB
C++

#include "OTA.h"
#include "gd32c10x_fmc.h"
#include <cstring>
extern CAN_transmiter CAN0_transmiter; // CAN初始化
extern "C" {
void canfd_rx_irq_handler(void);
}
OTAHandler::OTAHandler() : ota_active(false), received_size(0) {}
void OTAHandler::init() {
// 初始化CANFD接收中断
nvic_irq_enable(CAN0_RX0_IRQn, 1, 1);
}
void OTAHandler::process() {
if (!ota_active)
return;
// 这里可以添加超时处理逻辑
// 例如:10秒无数据则退出OTA模式
}
bool OTAHandler::validateApplication() {
uint32_t *app_vector = (uint32_t *)APP_START_ADDR;
uint32_t stack_ptr = app_vector[0];
uint32_t reset_handler = app_vector[1];
// 简单验证:检查栈指针是否在SRAM范围内
return (stack_ptr >= 0x20000000 && stack_ptr < 0x20008000) &&
(reset_handler >= APP_START_ADDR &&
reset_handler < (APP_START_ADDR + APP_MAX_SIZE));
}
void OTAHandler::jumpToApplication() {
if (!validateApplication()) {
// 无效APP,停留在bootloader
return;
}
// 关闭所有中断
__disable_irq();
// 设置主栈指针
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;
// 跳转
app_entry();
}
void OTAHandler::eraseApplicationArea() {
// 擦除APP区域
fmc_unlock();
for (uint32_t addr = APP_START_ADDR; addr < (APP_START_ADDR + APP_MAX_SIZE);
addr += FMC_PAGE_SIZE) {
fmc_page_erase(addr);
}
fmc_lock();
}
void OTAHandler::writeApplicationData(uint32_t offset, uint8_t *data,
uint32_t size) {
fmc_unlock();
uint32_t write_addr = APP_START_ADDR + offset;
// 32位对齐写入
for (uint32_t i = 0; i < size; i += 4) {
uint32_t word = 0;
memcpy(&word, &data[i], 4);
fmc_word_program(write_addr + i, word);
}
fmc_lock();
}
void OTAHandler::handleOTAMessage(uint32_t id, uint8_t *data, uint8_t len) {
if (id == CANFD_OTA_REQ_ID) {
// OTA请求包
uint32_t new_size = *(uint32_t *)data;
if (new_size <= APP_MAX_SIZE) {
expected_size = new_size;
received_size = 0;
eraseApplicationArea();
ota_active = true;
sendACK(0xFFFFFFFF); // 确认开始
}
} else if (id == CANFD_OTA_DATA_ID && ota_active) {
// 数据包格式:[4字节包序号][实际数据]
if (len >= 4) {
uint32_t packet_num = *(uint32_t *)data;
uint32_t offset = packet_num * (len - 4);
if (offset < expected_size) {
writeApplicationData(offset, &data[4], len - 4);
received_size += (len - 4);
sendACK(packet_num);
// 检查是否完成
if (received_size >= expected_size) {
ota_active = false;
// 跳转前延时让ACK发出
for (volatile int i = 0; i < 100000; i++)
;
jumpToApplication();
}
}
}
}
}
void OTAHandler::sendACK(uint32_t packet_num) {
CAN0_transmiter.sendACK(CANFD_OTA_ACK_ID, packet_num);
}