iap_upgrade.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include "iap_upgrade.h"
  2. static uint32_t upgrade_offset = 0;
  3. static uint32_t expected_file_size = 0; // 升级文件大小值
  4. static uint8_t expected_md5[16]; // 接收的MD5码头4字节
  5. static uint32_t current_packet_index = 0;
  6. static bool upgrade_in_progress = false;
  7. static uint32_t upgrade_target_addr = 0;
  8. // 发送应答帧(状态码:0=成功,其他为错误)
  9. void send_upgrade_response(uint8_t func_code, uint16_t reg_addr, uint8_t status_code, uint16_t sliceCount)
  10. {
  11. uint8_t tx_buf[32];
  12. uint16_t len = 0;
  13. tx_buf[len++] = g_deviceParams.SlaveDevice_addr;
  14. tx_buf[len++] = func_code;
  15. tx_buf[len++] = reg_addr >> 8;
  16. tx_buf[len++] = reg_addr & 0xFF;
  17. tx_buf[len++] = 0x41; // 自定义应答命令
  18. tx_buf[len++] = 0x00;
  19. tx_buf[len++] = status_code; // 状态码
  20. tx_buf[len++] = 0x00;
  21. tx_buf[len++] = sliceCount >> 8;
  22. tx_buf[len++] = sliceCount & 0xFF;
  23. uint16_t crc = modbus_crc16(tx_buf, len);
  24. tx_buf[len++] = crc & 0xFF;
  25. tx_buf[len++] = (crc >> 8) & 0xFF;
  26. HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET);
  27. HAL_UART_Transmit_DMA(&huart1, tx_buf, len);
  28. }
  29. // 默认写入到 APP2 区,如果当前运行的是 APP2,则写 APP1 区
  30. uint32_t get_backup_app_addr(void)
  31. {
  32. return (APP1_ADDR == BOOTLOADER_ADDR) ? APP2_ADDR : APP1_ADDR;
  33. }
  34. // 清除升级状态(在失败或完成后调用)
  35. void reset_upgrade_state(void)
  36. {
  37. upgrade_offset = 0;
  38. expected_file_size = 0;
  39. memset(expected_md5, 0, sizeof(expected_md5));
  40. current_packet_index = 0;
  41. upgrade_in_progress = false;
  42. }
  43. /*
  44. 状态码值:
  45. 00:正常
  46. 01:busy
  47. 02:升级文件大小超限
  48. 03:单帧切片大小超限
  49. 04:切片索引错误
  50. 05:crc校验错误
  51. 06:参数错误
  52. 07:命令码错误
  53. 08:执行错误(如无起始帧却先收到了数据帧)
  54. */
  55. // 处理起始帧 (0x4000)
  56. void handle_upgrade_start_frame(uint8_t *data)
  57. {
  58. uint16_t subcode = (data[6] << 8 | data[7]);
  59. if (subcode == 0x0100) {
  60. expected_file_size = (data[23] << 24) | (data[24] << 16) | (data[25] << 8) | data[26];
  61. if (expected_file_size > MAX_UPGRADE_SIZE) {
  62. send_upgrade_response(0x42, 0xAABB, 0x02,0x0000); // 文件过大
  63. return;
  64. }
  65. upgrade_target_addr = get_backup_app_addr();
  66. Flash_ErasePages(upgrade_target_addr, expected_file_size / PAGE_SIZE + 1);
  67. upgrade_offset = 0;
  68. current_packet_index = 0;
  69. upgrade_in_progress = true;
  70. send_upgrade_response(0x42, 0xAABB, 0x00,0x0000);
  71. } else if (subcode == 0x0200) {
  72. expected_file_size = (data[8] << 24) | (data[9] << 16) | (data[10] << 8) | data[11];
  73. memcpy(expected_md5, &data[12], 4); // 支持MD5的头4字节
  74. send_upgrade_response(0x42, 0x4000, 0x00, 0x0000);
  75. }else{
  76. send_upgrade_response(0x42, 0xAABB, 0x06, 0x0000); // 参数错误
  77. }
  78. }
  79. // 处理数据帧 (0x4001)
  80. void handle_upgrade_data_frame(uint8_t *data)
  81. {
  82. if (!upgrade_in_progress) {
  83. send_upgrade_response(0x42, 0x4001, 0x08, 0x0000); // 执行错误08(无起始帧却先收到数据帧)
  84. return;
  85. }
  86. if ((data[2] << 8 | data[3]) != 0x4001) return;
  87. uint16_t index = data[6] << 8 | data[7];
  88. if (index != current_packet_index) {
  89. send_upgrade_response(0x42, 0x4001, 0x04, 0x0000);
  90. reset_upgrade_state();
  91. return;
  92. }
  93. Flash_Write64(upgrade_target_addr + upgrade_offset, (uint64_t*)&data[8], PACKET_SIZE / 8);
  94. upgrade_offset += PACKET_SIZE;
  95. current_packet_index++;
  96. send_upgrade_response(0x42, 0x4001, 0x00, 0x0000);
  97. }
  98. // 处理结束帧 (0x4002)
  99. void handle_upgrade_end_frame(void)
  100. {
  101. uint32_t addr = get_backup_app_addr();
  102. uint8_t result_md5[16];
  103. MD5_CTX context;
  104. MD5Init(&context);
  105. MD5Update(&context, (uint8_t*)addr, expected_file_size);
  106. MD5Final(result_md5, &context);
  107. if (memcmp(result_md5, expected_md5, 4) == 0) {
  108. BootParams new_params;
  109. SaveBootloaderParams();
  110. memcpy(&new_params, &params, sizeof(BootParams));
  111. if (addr == APP1_ADDR) {
  112. memcpy(new_params.app1_md5, result_md5, 16);
  113. new_params.app1_valid = 0xA5;
  114. new_params.app1_version += 1;
  115. } else {
  116. memcpy(new_params.app2_md5, result_md5, 16);
  117. new_params.app2_valid = 0xA5;
  118. new_params.app2_version += 1;
  119. }
  120. new_params.upgrade_flag = 0xAABBCCDD;
  121. memcpy(&params, &new_params, sizeof(BootParams));
  122. SaveBootloaderParams();
  123. NVIC_SystemReset();
  124. } else {
  125. Flash_ErasePages(addr, expected_file_size / PAGE_SIZE + 1);
  126. }
  127. reset_upgrade_state();
  128. }