#include "OTA.h" #include "gd32c10x_fmc.h" #include "systick.h" #include #include #include #include extern CAN_transmiter CAN0_transmiter; // CAN初始化 extern FlashEEPROM flashEEP; OTAHandler ota; extern "C" { void canfd_rx_irq_handler(void); } #define DEBUG_OTA 1 void OTAHandler::init() {} void OTAHandler::process() { 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); return; } else { delay_1ms(1); ota_time++; } // 检查是否超时(例如:10秒无数据则退出OTA模式) if (ota_time > 10000) { // 10秒超时(10000 x 1ms) ota_time = 0; ota_active = false; } } bool OTAHandler::validateApplication() { u32 *app_vector = (u32 *)APP_START_ADDR; u32 stack_ptr = app_vector[0]; u32 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()) 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(); } void OTAHandler::eraseApplicationArea() { // 擦除APP区域 fmc_unlock(); for (u32 addr = APP_START_ADDR; addr < (APP_START_ADDR + APP_MAX_SIZE); addr += FMC_PAGE_SIZE) { fmc_page_erase(addr); } fmc_lock(); } void OTAHandler::writeApplicationData(u32 offset, u8 *data, u32 size) { fmc_unlock(); u32 write_addr = APP_START_ADDR + offset; // 32位对齐写入 for (u32 i = 0; i < size; i += 4) { u32 word = 0; memcpy(&word, &data[i], 4); fmc_word_program(write_addr + i, word); } fmc_lock(); } void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) { if (id == CANFD_OTA_REQ_ID) { #ifdef DEBUG_OTA printf("req OTA\r\n"); #endif // OTA请求包 u32 new_size = *(u32 *)data; if (new_size <= APP_MAX_SIZE) { expected_size = new_size; received_size = 0; // eraseApplicationArea(); ota_active = true; sendACK(new_size); // 确认开始 #ifdef DEBUG_OTA printf("start OTA%d\r\n", ota_active); #endif } } else if (id == CANFD_OTA_DATA_ID && ota_active) { // 数据包格式:[4字节包序号][实际数据] if (len >= 4) { u32 packet_num = *(u32 *)data; u32 offset = packet_num * (len - 4); if (offset < expected_size) { writeApplicationData(offset, &data[4], len - 4); // 写入数据 received_size += (len - 4); sendACK(packet_num); // 确认ACK ota_time = 0; // 重置计时器 // 检查是否完成 if (received_size >= expected_size) { ota_active = false; // 跳转前延时让ACK发出 for (volatile int i = 0; i < 100000; i++) ; jumpToApplication(); } } } } } void OTAHandler::sendACK(u32 packet_num) { CAN0_transmiter.sendACK(CANFD_OTA_ACK_ID, packet_num); }