#include "OTA.h" #include "gd32c10x_fmc.h" #include 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); }