ymodem_update.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /**
  2. * @Author: 李建
  3. * @Date: 2024/9/7 13:06
  4. * Description:
  5. * Copyright: Copyright (©) 2024 永续绿建. All rights reserved.
  6. */
  7. #include "ymodem_update.h"
  8. #include "port.h"
  9. #include "mb.h"
  10. #include "flash.h"
  11. #include <stdio.h>
  12. static enum UPDATE_STATE Update_State = TO_START;
  13. /* 设置升级的步骤 */
  14. static inline void Set_State(enum UPDATE_STATE state)
  15. {
  16. Update_State = state;
  17. }
  18. /* 查询升级的步骤 */
  19. static inline uint8_t Get_State(void)
  20. {
  21. return Update_State;
  22. }
  23. #define POLY 0x1021
  24. /**
  25. * @brief CRC-16 校验
  26. * @param addr 开始地址
  27. * @param num 长度
  28. * @param crc CRC
  29. * @return crc 返回CRC的值
  30. */
  31. static uint16_t CRC16(uint8_t *addr, int num, uint16_t crc)
  32. {
  33. int i;
  34. for (; num > 0; num--) /* Step through bytes in memory */
  35. {
  36. crc = crc ^ (*addr++ << 8); /* Fetch byte from memory, XOR into CRC top byte*/
  37. for (i = 0; i < 8; i++) /* Prepare to rotate 8 bits */
  38. {
  39. if (crc & 0x8000) /* b15 is set... */
  40. crc = (crc << 1) ^ POLY; /* rotate and XOR with polynomic */
  41. else /* b15 is clear... */
  42. crc <<= 1; /* just rotate */
  43. } /* Loop for 8 bits */
  44. crc &= 0xFFFF; /* Ensure CRC remains 16-bit value */
  45. } /* Loop until num=0 */
  46. return(crc); /* Return updated CRC */
  47. }
  48. /**
  49. * @brief 获取数据包的类型, 顺便进行校验
  50. * @param buf 开始地址
  51. * @param len 长度
  52. * @return 1 通过校验 0 没通过校验
  53. */
  54. uint8_t Check_CRC(uint8_t* buf, int len)
  55. {
  56. uint16_t crc = 0;
  57. /* 进行CRC校验 */
  58. crc = CRC16(buf+3, len - 5, crc);
  59. if(crc != (buf[131]<<8|buf[132]))
  60. {
  61. return 0; /* 没通过校验 */
  62. }else{
  63. return 1; /* 通过校验 */
  64. }
  65. }
  66. void Code_Storage_Done(void)
  67. {
  68. uint32_t update_flag = Startup_Update; // 对应bootloader的启动步骤
  69. flash_write((Application_2_Addr + Application_Size - 4), &update_flag,4 ); //在APP2中添加标记 0x801DFFC
  70. }
  71. /**
  72. * 串口写文件回调,内容为ymodem协议报文
  73. * @param header
  74. * @param pucRegBuffer
  75. * @return
  76. */
  77. eMBErrorCode eMBWriteFileCB(UCHAR * header, UCHAR * pucRegBuffer, USHORT * usLen) {
  78. switch (*header) {
  79. case SOH:{
  80. static uint8_t Data_State = 0;
  81. static uint16_t pack_offset = 0;
  82. if(Check_CRC(pucRegBuffer, *usLen - 1)) {
  83. // 如果是起始帧
  84. if(Get_State() == TO_START && pucRegBuffer[1] == 0&&(pucRegBuffer[2] == (uint8_t)(~pucRegBuffer[1]))) {
  85. Set_State(TO_RECEIVE_DATA);
  86. Data_State = 0x01;
  87. pack_offset = 1;
  88. pucRegBuffer[0] = ACK;
  89. flash_erase(Application_2_Addr, (Application_2_Addr + Application_Size) / FLASH_PAGE_SIZE);
  90. DEBUG_PRINTF("flash_erase\r\n");
  91. } else if((Get_State()==TO_RECEIVE_END)&&(pucRegBuffer[1] == 0x00)&&(pucRegBuffer[2] == (uint8_t)(~pucRegBuffer[1])))
  92. {
  93. Code_Storage_Done(); //APP2区代码存放完成
  94. DEBUG_PRINTF("Code_Storage_Done\r\n");
  95. Set_State(TO_START); //标记可以继续接收Ymodem数据
  96. pucRegBuffer[0] = ACK;
  97. pack_offset = 0;
  98. HAL_NVIC_SystemReset(); //重启系统
  99. } else if((Get_State()==TO_RECEIVE_DATA)&&(pucRegBuffer[1] == Data_State)&&(pucRegBuffer[2] == (uint8_t)(~pucRegBuffer[1]))) {
  100. /* 烧录程序 */
  101. flash_write((Application_2_Addr + (pack_offset -1) * 128), pucRegBuffer+3, 128);
  102. pack_offset++;
  103. if(Data_State++ == 0xFF) {
  104. Data_State = 0x01;
  105. }
  106. pucRegBuffer[0] = ACK;
  107. DEBUG_PRINTF("flash_write:%d\r\n", Data_State);
  108. }
  109. } else {
  110. pucRegBuffer[0] = NACK;
  111. DEBUG_PRINTF("crc error:%d\r\n", Data_State);
  112. }
  113. }
  114. break;
  115. case EOT: {
  116. if(Get_State()==TO_RECEIVE_DATA)
  117. {
  118. Set_State(TO_RECEIVE_EOT2);
  119. pucRegBuffer[0] = NACK;
  120. }
  121. else if(Get_State()==TO_RECEIVE_EOT2)
  122. {
  123. Set_State(TO_RECEIVE_END);
  124. pucRegBuffer[0] = ACK;
  125. }
  126. else
  127. {
  128. //Receive EOT, But error...
  129. }
  130. }
  131. break;
  132. }
  133. return MB_ENOERR;
  134. }