123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- #include "iap_upgrade.h"
- static uint32_t upgrade_offset = 0;
- static uint32_t expected_file_size = 0; // 升级文件大小值
- static uint8_t expected_md5[16]; // 接收的MD5码头4字节
- static uint32_t current_packet_index = 0;
- static bool upgrade_in_progress = false;
- static uint32_t upgrade_target_addr = 0;
- // 发送应答帧(状态码:0=成功,其他为错误)
- void send_upgrade_response(uint8_t func_code, uint16_t reg_addr, uint8_t status_code, uint16_t sliceCount)
- {
- uint8_t tx_buf[32];
- uint16_t len = 0;
-
- tx_buf[len++] = g_deviceParams.SlaveDevice_addr;
- tx_buf[len++] = func_code;
- tx_buf[len++] = reg_addr >> 8;
- tx_buf[len++] = reg_addr & 0xFF;
- tx_buf[len++] = 0x41; // 自定义应答命令
- tx_buf[len++] = 0x00;
- tx_buf[len++] = status_code; // 状态码
- tx_buf[len++] = 0x00;
- tx_buf[len++] = sliceCount >> 8;
- tx_buf[len++] = sliceCount & 0xFF;
- uint16_t crc = modbus_crc16(tx_buf, len);
- tx_buf[len++] = crc & 0xFF;
- tx_buf[len++] = (crc >> 8) & 0xFF;
- HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET);
- HAL_UART_Transmit_DMA(&huart1, tx_buf, len);
- }
- // 默认写入到 APP2 区,如果当前运行的是 APP2,则写 APP1 区
- uint32_t get_backup_app_addr(void)
- {
- return (APP1_ADDR == BOOTLOADER_ADDR) ? APP2_ADDR : APP1_ADDR;
- }
- // 清除升级状态(在失败或完成后调用)
- void reset_upgrade_state(void)
- {
- upgrade_offset = 0;
- expected_file_size = 0;
- memset(expected_md5, 0, sizeof(expected_md5));
- current_packet_index = 0;
- upgrade_in_progress = false;
- }
- /*
- 状态码值:
- 00:正常
- 01:busy
- 02:升级文件大小超限
- 03:单帧切片大小超限
- 04:切片索引错误
- 05:crc校验错误
- 06:参数错误
- 07:命令码错误
- 08:执行错误(如无起始帧却先收到了数据帧)
- */
- // 处理起始帧 (0x4000)
- void handle_upgrade_start_frame(uint8_t *data)
- {
- uint16_t subcode = (data[6] << 8 | data[7]);
- if (subcode == 0x0100) {
- expected_file_size = (data[23] << 24) | (data[24] << 16) | (data[25] << 8) | data[26];
- if (expected_file_size > MAX_UPGRADE_SIZE) {
- send_upgrade_response(0x42, 0xAABB, 0x02,0x0000); // 文件过大
- return;
- }
- upgrade_target_addr = get_backup_app_addr();
- Flash_ErasePages(upgrade_target_addr, expected_file_size / PAGE_SIZE + 1);
- upgrade_offset = 0;
- current_packet_index = 0;
- upgrade_in_progress = true;
- send_upgrade_response(0x42, 0xAABB, 0x00,0x0000);
-
- } else if (subcode == 0x0200) {
- expected_file_size = (data[8] << 24) | (data[9] << 16) | (data[10] << 8) | data[11];
- memcpy(expected_md5, &data[12], 4); // 支持MD5的头4字节
- send_upgrade_response(0x42, 0x4000, 0x00, 0x0000);
-
- }else{
- send_upgrade_response(0x42, 0xAABB, 0x06, 0x0000); // 参数错误
- }
- }
- // 处理数据帧 (0x4001)
- void handle_upgrade_data_frame(uint8_t *data)
- {
- if (!upgrade_in_progress) {
- send_upgrade_response(0x42, 0x4001, 0x08, 0x0000); // 执行错误08(无起始帧却先收到数据帧)
- return;
- }
- if ((data[2] << 8 | data[3]) != 0x4001) return;
-
- uint16_t index = data[6] << 8 | data[7];
- if (index != current_packet_index) {
- send_upgrade_response(0x42, 0x4001, 0x04, 0x0000);
- reset_upgrade_state();
- return;
- }
- Flash_Write64(upgrade_target_addr + upgrade_offset, (uint64_t*)&data[8], PACKET_SIZE / 8);
- upgrade_offset += PACKET_SIZE;
- current_packet_index++;
- send_upgrade_response(0x42, 0x4001, 0x00, 0x0000);
- }
- // 处理结束帧 (0x4002)
- void handle_upgrade_end_frame(void)
- {
- uint32_t addr = get_backup_app_addr();
- uint8_t result_md5[16];
- MD5_CTX context;
- MD5Init(&context);
- MD5Update(&context, (uint8_t*)addr, expected_file_size);
- MD5Final(result_md5, &context);
- if (memcmp(result_md5, expected_md5, 4) == 0) {
- BootParams new_params;
- SaveBootloaderParams();
- memcpy(&new_params, ¶ms, sizeof(BootParams));
- if (addr == APP1_ADDR) {
- memcpy(new_params.app1_md5, result_md5, 16);
- new_params.app1_valid = 0xA5;
- new_params.app1_version += 1;
- } else {
- memcpy(new_params.app2_md5, result_md5, 16);
- new_params.app2_valid = 0xA5;
- new_params.app2_version += 1;
- }
- new_params.upgrade_flag = 0xAABBCCDD;
- memcpy(¶ms, &new_params, sizeof(BootParams));
- SaveBootloaderParams();
- NVIC_SystemReset();
- } else {
- Flash_ErasePages(addr, expected_file_size / PAGE_SIZE + 1);
- }
- reset_upgrade_state();
- }
|