当前位置:   article > 正文

STM32F4 Boot升级例程_stm32刷boot

stm32刷boot

本文重点介绍代码实现,不介绍工程配置。

1.串口需要开启DMA接收数据,normal模式

 2.修改串口中断

  1. /* USER CODE BEGIN 0 */
  2. __weak void uart_user_handle(void)
  3. {
  4. }
  5. /* USER CODE END 0 */
  6. void USART3_IRQHandler(void)
  7. {
  8. /* USER CODE BEGIN USART3_IRQn 0 */
  9. /* USER CODE END USART3_IRQn 0 */
  10. HAL_UART_IRQHandler(&huart3);
  11. /* USER CODE BEGIN USART3_IRQn 1 */
  12. if(0 != __HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE))
  13. {
  14. __HAL_UART_CLEAR_IDLEFLAG(&huart3);
  15. uart_user_handle();
  16. }
  17. /* USER CODE END USART3_IRQn 1 */
  18. }

3.创建串口操作源文件 uart.c

  1. /**
  2. * @brief 串口应用层接口
  3. * @author lj
  4. * @date 2022/09/16
  5. *
  6. * ---------------------------------
  7. */
  8. #include "uart.h"
  9. #include "usart.h"
  10. #include "stm32f4xx.h"
  11. #include "common/ringbuffer.h"
  12. /* 串口接收最大 */
  13. #define RS485_RECV_MAX_SIZE 1024
  14. #define UART_ASSERT(x) { \
  15. if (!(x)) \
  16. return 0; \
  17. }
  18. #pragma pack(1)
  19. typedef struct {
  20. uint16_t size; // 缓冲区大小
  21. uint8_t buf[0]; // 动态缓冲区
  22. }uart_fifo_t;
  23. #pragma pack()
  24. /**
  25. * @brief 串口设备信息
  26. */
  27. typedef struct {
  28. UART_HandleTypeDef *huart; // 串口设备句柄
  29. uart_fifo_t *fifo; // 串口缓冲接收缓冲区
  30. T_RingBuffer ring; // 环形队列,用于数据存取
  31. uint16_t recv_cnt; // 接收次数
  32. }Uart_info_t;
  33. // 串口缓冲区
  34. static uint8_t uart3_buf[sizeof(uart_fifo_t) + RS485_RECV_MAX_SIZE] = {0};
  35. // 串口DMA缓冲区
  36. static uint8_t uart3_dma_buf[RS485_RECV_MAX_SIZE] = {0};
  37. // 串口DMA句柄
  38. extern DMA_HandleTypeDef hdma_usart3_rx;
  39. // 串口设备
  40. static Uart_info_t g_uart_device = {0};
  41. //static uint8_t *uart3_p = uart3_buf;
  42. /**
  43. * @brief RS485串口初始化
  44. * @param None
  45. * @retval None
  46. */
  47. void uart_init(void)
  48. {
  49. // 串口3初始化
  50. g_uart_device.huart = &huart3;
  51. g_uart_device.fifo = (uart_fifo_t *)uart3_buf;
  52. g_uart_device.fifo->size = RS485_RECV_MAX_SIZE;
  53. g_uart_device.recv_cnt = 0;
  54. // 初始化环形队列
  55. ringbuf_init(&g_uart_device.ring, g_uart_device.fifo->buf, g_uart_device.fifo->size);
  56. //使能IDLE中断
  57. __HAL_UART_ENABLE_IT(g_uart_device.huart, UART_IT_IDLE);
  58. // 开启dma接收
  59. HAL_UART_Receive_DMA(g_uart_device.huart, uart3_dma_buf, RS485_RECV_MAX_SIZE);
  60. }
  61. /**
  62. * @brief 串口写
  63. * @param buf:待发送数据
  64. * @param len:待发送数据长度
  65. * @retval 发送数据长度
  66. */
  67. uint16_t uart_write(uint8_t *buf, uint16_t len)
  68. {
  69. UART_ASSERT(buf != NULL);
  70. UART_ASSERT(len != 0);
  71. UART_ASSERT(g_uart_device.huart != NULL);
  72. HAL_GPIO_WritePin(GPIOG,GPIO_PIN_2,GPIO_PIN_SET);
  73. HAL_UART_Transmit(g_uart_device.huart, buf, len, 0xff);
  74. HAL_GPIO_WritePin(GPIOG,GPIO_PIN_2,GPIO_PIN_RESET);
  75. return len;
  76. }
  77. /**
  78. * @brief 串口读
  79. * @param buf:读取数据buf
  80. * @param len:读取数据buf长度
  81. * @retval 读取数据长度
  82. */
  83. uint16_t uart_read(uint8_t *buf, uint16_t len)
  84. {
  85. uint16_t length = 0;
  86. UART_ASSERT(buf != NULL);
  87. UART_ASSERT(len != 0);
  88. UART_ASSERT(g_uart_device.huart != NULL);
  89. __disable_irq(); // 防止数据读取时进入中断导致fifo数据被更改
  90. length = ringbuf_get(&g_uart_device.ring, buf, len);
  91. __enable_irq();
  92. return length;
  93. }
  94. /**
  95. * @brief 读取串口接收次数
  96. * @param None
  97. * @retval 串口接收次数
  98. */
  99. uint16_t get_uart_recv_cnt(void)
  100. {
  101. return g_uart_device.recv_cnt;
  102. }
  103. /**
  104. * @brief 串口中断DMA保存数据
  105. * @param None
  106. * @retval None
  107. */
  108. void uart_user_handle(void)
  109. {
  110. uint16_t rec_len = 0;
  111. // 停止DMA
  112. HAL_UART_DMAStop(g_uart_device.huart);
  113. // 获取数据长度
  114. rec_len = (RS485_RECV_MAX_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx));
  115. if (0 == rec_len)
  116. return;
  117. // 将数据放到fifo中
  118. __disable_irq();
  119. ringbuf_put(&g_uart_device.ring, uart3_dma_buf, rec_len);
  120. g_uart_device.recv_cnt++;
  121. __enable_irq();
  122. // 重新开启dma
  123. HAL_UART_Receive_DMA(g_uart_device.huart, uart3_dma_buf, RS485_RECV_MAX_SIZE); //重新打开DMA接收
  124. }
  125. /**
  126. * @brief 串口中断异常处理,清除ORE标志并重启中断
  127. */
  128. void HAL_UART_ErrorCallback (UART_HandleTypeDef *huart)
  129. {
  130. __attribute((unused)) uint32_t data = 0;
  131. __HAL_UNLOCK(huart);
  132. if(__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET)
  133. {
  134. __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_ORE); //清除溢出中断
  135. data = huart->Instance->SR;
  136. data = huart->Instance->DR;
  137. __HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
  138. }
  139. }

4.创建升级主文件 boot.c

  1. * boot.c
  2. *
  3. * Created on: 2022年10月22日
  4. * Author: lj
  5. */
  6. #include "boot.h"
  7. #include "uart.h"
  8. #include "flash.h"
  9. #include "common/crc.h"
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #ifdef STM32F407xx
  13. #include "stm32f4xx_hal.h"
  14. #endif
  15. typedef void (*jump_func)(void);
  16. // 每一包数据大小
  17. #define SEND_SIZE_PER_SEND 256
  18. // 最大数据长度 = 每一包数据大小+1字节类型+2字节长度+除帧数据外的字节数
  19. #define BUF_MAX_LENGTH (SEND_SIZE_PER_SEND+3+7)
  20. // 最大读取长度
  21. #define BUF_MAX_READ_LEN 1024
  22. // 接收最小字节数 (3字节头+2字节数据长度+1字节命令字+1字节校验和)
  23. #define RECV_BYTES_MIN 7
  24. // 软件版本
  25. #define VERSION_INFO(main,sub,modify) (((main) << 24) | ((sub) << 16) | ((modify) << 8))
  26. #define BOOT_VERSION VERSION_INFO(1, 0, 0)
  27. //------------------flash操作状态---------------
  28. #define UPDATE_ACK_STATE_CHECK_ERROR 0x01 // 校验错误
  29. #define UPDATE_ACK_STATE_WRITE_RIGHT 0x02 // FLASH写入正确
  30. #define UPDATE_ACK_STATE_WRITE_ERROR 0x03 // FLASH写入错误
  31. #define UPDATE_ACK_STATE_ERASEING 0x04 // FLASH擦除中
  32. #define UPDATE_ACK_STATE_ERASE_DONE 0x05 // FLASH擦除完毕
  33. // 返回升级boot命令字
  34. #define CMD_ACK_BOOTLOADER 0xE0
  35. // 返回升级app命令字
  36. #define CMD_ACK_APP 0xE1
  37. // 返回升级错误命令字
  38. #define CMD_ACK_ERR 0xE2
  39. // 升级过程中升级内容为boot
  40. #define CMD_UPDATE_BOOT 0xBC
  41. // 升级过程中升级内容为app
  42. #define CMD_UPDATE_APP 0xBD
  43. /**
  44. * @brief 接收一帧完成
  45. */
  46. typedef enum
  47. {
  48. BOOT_NO,
  49. BOOT_YES
  50. }boot_recv_e;
  51. /**
  52. * @brief 升级过程中状态
  53. */
  54. typedef enum
  55. {
  56. CMD_UPDATE_READY = 0xE0,
  57. CMD_UPDATE_FILE = 0xF0,
  58. CMD_UPDATE_FINISH = 0xFF
  59. }boot_update_e;
  60. /**
  61. * @brief 升级类型
  62. */
  63. typedef enum
  64. {
  65. BOOT_TYPE_NONE,
  66. BOOT_TYPE_BOOTLOADER,
  67. BOOT_TYPE_APP
  68. }boot_type_e;
  69. /**
  70. * @brief 升级状态机
  71. */
  72. typedef enum
  73. {
  74. BOOT_STATE_HEAD0, // 接收帧头第一个字节
  75. BOOT_STATE_HEAD1, // 接收帧头第二个字节
  76. BOOT_STATE_HEAD2, // 接收帧头第三个字节
  77. BOOT_STATE_LEN, // 接收帧长
  78. BOOT_STATE_PRO // 接收至数据完成
  79. }boot_state_e;
  80. #pragma pack(1)
  81. /**
  82. * @brief 数据缓存buf
  83. */
  84. typedef union
  85. {
  86. uint8_t buffer[BUF_MAX_LENGTH];
  87. struct
  88. {
  89. uint8_t head0; // 头字节1
  90. uint8_t head1; // 头字节2
  91. uint8_t head2; // 头字节3
  92. uint16_t len; // 数据长度
  93. uint8_t cmd; // 指令
  94. uint8_t data[BUF_MAX_LENGTH - 6]; // 数据
  95. }data_t;
  96. }recv_buf_t;
  97. /**
  98. * @brief boot主结构体
  99. */
  100. typedef struct
  101. {
  102. uint8_t state; // 状态机标志
  103. uint16_t count; // 接收数量
  104. uint8_t check_sum; // 校验和
  105. uint8_t recv_flag; // 接收标志
  106. recv_buf_t recv_buf; // 接收缓冲区
  107. }boot_t;
  108. /**
  109. * @brief 升级参数
  110. */
  111. typedef struct
  112. {
  113. uint32_t fw_flag; // 升级标志位
  114. uint32_t page_num; // 页数量
  115. uint32_t chksum; // 校验和
  116. uint32_t size; // 总大小
  117. uint16_t addsum; // 累加和
  118. }boot_param_t;
  119. /**
  120. * @brief 升级过程中的参数
  121. */
  122. typedef struct
  123. {
  124. uint8_t is_finish;// 升级类型 1:bootloader 2:app
  125. uint8_t boot_type;
  126. uint32_t addr;
  127. uint32_t flash_addr;
  128. }boot_pro_t;
  129. #pragma pack()
  130. // 头字节
  131. const uint8_t boot_head_bytes[] = {0xAA, 0x55, 0xAA};
  132. // 升级所需参数
  133. static boot_pro_t g_state = {0};
  134. // 升级参数
  135. static boot_param_t g_param_data = {0};
  136. // boot
  137. static boot_t g_boot_data = {0};
  138. // 解析出来的完整的数据
  139. static boot_t g_boot_data_entire = {0};
  140. // 软件版本信息
  141. static char soft_version[] = \
  142. "\r\n==============================================\r\n \
  143. ** CPU(stm32f4xx) BootLoader\r\n \
  144. **Author lj\r\n \
  145. **Date 20221022\r\n \
  146. **Version V1.0.0\r\n \
  147. ===================================================\r\n\0";
  148. /**
  149. * @brief 计算校验和
  150. * @param buff:待校验数据
  151. * @param len:数据长度
  152. * @retval 校验和
  153. */
  154. static uint8_t calc_chksum(uint8_t* buff, uint16_t len)
  155. {
  156. uint8_t checkSum = 0;
  157. uint16_t i = 0;
  158. if(buff == NULL || len == 0)
  159. return 0;
  160. for(i=0; i<len; i++)
  161. {
  162. checkSum += buff[i];
  163. }
  164. return checkSum;
  165. }
  166. /**
  167. * @brief boot发送数据
  168. * @param cmd:命令子
  169. * @param data:待发送数据
  170. * @param len:发送数据长度
  171. * @retval None
  172. */
  173. static void boot_send_data(uint8_t cmd, uint8_t* data, uint16_t len)
  174. {
  175. recv_buf_t send_buf = {0};
  176. memcpy(send_buf.buffer, boot_head_bytes, sizeof(boot_head_bytes));
  177. send_buf.data_t.cmd = cmd;
  178. if((data == NULL) || (len == 0))
  179. {
  180. send_buf.data_t.len = RECV_BYTES_MIN;
  181. }
  182. else
  183. {
  184. memcpy(&send_buf.data_t.data[0], data, len);
  185. send_buf.data_t.len = len + RECV_BYTES_MIN;
  186. }
  187. send_buf.data_t.data[len] = calc_chksum(&send_buf.buffer[3], 3+len);
  188. // 发送数据
  189. uart_write(&send_buf.buffer[0], send_buf.data_t.len);
  190. }
  191. /**
  192. * @brief 保存升级参数
  193. * @param None
  194. * @retval None
  195. */
  196. static void boot_save_param(void)
  197. {
  198. uint16_t i = 0;
  199. // boot_param_t read ={0};
  200. if(g_state.boot_type != BOOT_TYPE_APP)
  201. return;
  202. // 擦除参数
  203. flash_erase_param();
  204. g_param_data.fw_flag = PARAM_FLAG;
  205. g_param_data.addsum = 0;
  206. for(i=0; i<(sizeof(boot_param_t)-1); i++)
  207. {
  208. g_param_data.addsum += ((uint8_t*)&g_param_data)[i];
  209. }
  210. flash_write(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&g_param_data);
  211. // memset(g_param_data, 0, sizeof(boot_param_t));
  212. // flash_read(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&read);
  213. // i++;
  214. }
  215. /**
  216. * @brief 读取参数
  217. * @param None
  218. * @retval None
  219. */
  220. __attribute((unused)) static void boot_read_param(void)
  221. {
  222. uint8_t sum = 0;
  223. uint16_t i = 0;
  224. memset((uint8_t*)&g_param_data, 0, sizeof(boot_param_t));
  225. flash_read(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&g_param_data);
  226. for(i=0; i<(sizeof(boot_param_t)-1); i++)
  227. {
  228. sum += ((uint8_t*)&g_param_data)[i];
  229. }
  230. if(sum != g_param_data.addsum)
  231. {
  232. memset((uint8_t*)&g_param_data, 0, sizeof(boot_param_t));
  233. }
  234. }
  235. /**
  236. * @brief 开始升级,初始化参数
  237. * @param data:指令类型
  238. * @retval None
  239. */
  240. static void boot_init(uint8_t* data)
  241. {
  242. uint8_t cmd = 0;
  243. if(data == NULL)
  244. return;
  245. if(data[0] == 0x01) // 升级BOOT
  246. {
  247. g_state.addr = BOOT_START_ADDR;
  248. g_state.boot_type = BOOT_TYPE_BOOTLOADER;
  249. g_state.is_finish = BOOT_NO;
  250. g_state.flash_addr = 0;
  251. // EraseAddr = BOOT_ADDR;
  252. // Flash_Erase_Num = BOOT_BLUK_NUM;
  253. cmd = CMD_ACK_BOOTLOADER;
  254. }
  255. else if(data[0] == 0x02) // 升级APP
  256. {
  257. g_state.addr = APP_START_ADDR;
  258. g_state.boot_type = BOOT_TYPE_APP;
  259. g_state.is_finish = BOOT_NO;
  260. g_state.flash_addr = 0;
  261. //Bin_Flash_Adr = 0;
  262. // EraseAddr = APP_ADDR;
  263. // Flash_Erase_Num = APP_ERASE_NUM;
  264. cmd = CMD_ACK_APP;
  265. }
  266. else
  267. {
  268. g_state.addr = APP_START_ADDR;
  269. g_state.boot_type = BOOT_TYPE_NONE;
  270. g_state.is_finish = BOOT_NO;
  271. g_state.flash_addr = 0;
  272. cmd = CMD_ACK_ERR;
  273. }
  274. boot_send_data(cmd, NULL, 0);
  275. }
  276. #pragma pack(1)
  277. typedef struct
  278. {
  279. uint8_t type; // 类型
  280. uint16_t num; // 程序页数量
  281. uint8_t content[SEND_SIZE_PER_SEND];// 程序内容
  282. }file_data_t;
  283. #pragma pack()
  284. /**
  285. * @brief 开始升级,初始化参数
  286. * @param data:升级数据,为
  287. * @retval None
  288. */
  289. static void boot_update(uint8_t* data)
  290. {
  291. uint8_t ack_state = 0;
  292. uint8_t read_tmp[256] = {0};
  293. uint16_t i = 0;
  294. uint32_t check_sum = 0;
  295. uint32_t bin_write_addr = 0;
  296. file_data_t* file_data = NULL;
  297. if(g_state.boot_type == BOOT_TYPE_NONE || data == NULL)
  298. return;
  299. file_data = (file_data_t *)data;
  300. if((file_data->type == CMD_UPDATE_BOOT && g_state.addr == BOOT_START_ADDR) ||
  301. (file_data->type == CMD_UPDATE_APP && g_state.addr == APP_START_ADDR))
  302. {
  303. bin_write_addr = g_state.addr + g_state.flash_addr;
  304. }
  305. else
  306. {
  307. ack_state = UPDATE_ACK_STATE_WRITE_ERROR;
  308. boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
  309. }
  310. if(g_state.flash_addr == file_data->num * SEND_SIZE_PER_SEND)
  311. {
  312. if(g_state.flash_addr == 0)
  313. {
  314. ack_state = UPDATE_ACK_STATE_ERASEING; // FLASH 擦除中
  315. boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
  316. flash_erase_app();
  317. ack_state = UPDATE_ACK_STATE_ERASE_DONE; // FLASH 擦除完毕
  318. boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
  319. // flash_erase_param(); // 参数擦除
  320. }
  321. flash_write(bin_write_addr, SEND_SIZE_PER_SEND, &file_data->content[0]);
  322. flash_read(bin_write_addr, SEND_SIZE_PER_SEND, &read_tmp[0]);
  323. for(i=0; i<SEND_SIZE_PER_SEND; i++)
  324. {
  325. check_sum += read_tmp[i];
  326. if(read_tmp[i] != file_data->content[i]) // 如果校验错误,需要重发
  327. {
  328. ack_state = UPDATE_ACK_STATE_CHECK_ERROR;
  329. boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
  330. return;
  331. }
  332. }
  333. g_state.flash_addr += SEND_SIZE_PER_SEND;
  334. g_param_data.page_num = file_data->num + 1;
  335. g_param_data.chksum += check_sum;
  336. ack_state = UPDATE_ACK_STATE_WRITE_RIGHT;
  337. boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
  338. }
  339. else
  340. {
  341. ack_state = UPDATE_ACK_STATE_WRITE_RIGHT;
  342. boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
  343. }
  344. }
  345. /**
  346. * @brief 获取当前时间
  347. * @param None
  348. * @retval 当前时间
  349. */
  350. static uint32_t get_current_time(void)
  351. {
  352. #ifdef STM32F407xx
  353. return HAL_GetTick();
  354. #else
  355. return 0;
  356. #endif
  357. }
  358. /**
  359. * @brief 处理升级数据
  360. * @param data:接收到的完整数据
  361. * @retval None
  362. */
  363. static void boot_handle_cmd(recv_buf_t *data )
  364. {
  365. uint8_t ack_state = 0;
  366. uint32_t sys_time = 0;
  367. static uint32_t pre_time = 0;
  368. if(data == NULL)
  369. return;
  370. switch(data->data_t.cmd)
  371. {
  372. // 固件升级使能
  373. case CMD_UPDATE_READY:
  374. {
  375. sys_time = get_current_time();
  376. // 500 ms内只响应一次
  377. if((pre_time != 0) && (sys_time-pre_time) < 500)
  378. return;
  379. pre_time = sys_time;
  380. boot_init(&data->data_t.data[0]);
  381. }
  382. break;
  383. // 固件文件传输
  384. case CMD_UPDATE_FILE:
  385. {
  386. boot_update(&data->data_t.data[0]);
  387. }
  388. break;
  389. // 固件升级完成
  390. case CMD_UPDATE_FINISH:
  391. {
  392. boot_save_param();
  393. g_state.flash_addr = 0;
  394. g_state.boot_type = BOOT_TYPE_NONE;
  395. g_state.is_finish = BOOT_YES;
  396. }
  397. break;
  398. default:
  399. {
  400. ack_state = UPDATE_ACK_STATE_CHECK_ERROR;
  401. boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
  402. }
  403. break;
  404. }
  405. }
  406. /**
  407. * @brief 返回升级成功标志
  408. * @param None
  409. * @retval 升级成功标志位
  410. */
  411. uint8_t is_boot_finish(void)
  412. {
  413. return g_state.is_finish;
  414. }
  415. /**
  416. * @brief 返回升级状态
  417. * @param None
  418. * @retval 升级状态 !0=升级中 0=没升级
  419. */
  420. uint8_t get_boot_status(void)
  421. {
  422. return g_state.boot_type;
  423. }
  424. /**
  425. * @brief 发送软件版本信息
  426. * @param None
  427. * @retval None
  428. */
  429. void send_boot_version(void)
  430. {
  431. uart_write((uint8_t *)soft_version, strlen(soft_version));
  432. }
  433. /**
  434. * @brief 接收解析串口数据
  435. * @param None
  436. * @retval None
  437. */
  438. static void boot_recv_data(void)
  439. {
  440. uint8_t ch = 0;
  441. uint16_t i = 0;
  442. uint16_t date_len = 0;
  443. uint8_t buff[BUF_MAX_READ_LEN] = {0};
  444. // 读取串口数据
  445. date_len = uart_read(buff, BUF_MAX_READ_LEN);
  446. if(date_len == 0)
  447. return;
  448. for(i=0; i<date_len; i++)
  449. {
  450. ch = buff[i];
  451. switch(g_boot_data.state)
  452. {
  453. // 找帧头
  454. case BOOT_STATE_HEAD0:
  455. {
  456. if(ch == boot_head_bytes[0])
  457. {
  458. g_boot_data.count = 0;
  459. g_boot_data.check_sum = 0;
  460. g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
  461. g_boot_data.state = BOOT_STATE_HEAD1;
  462. }
  463. }
  464. break;
  465. case BOOT_STATE_HEAD1:
  466. {
  467. if(ch == boot_head_bytes[1]) // 如果第二个字节为0x55,就找第三个字节
  468. {
  469. g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
  470. g_boot_data.state = BOOT_STATE_HEAD2;
  471. }
  472. else if(ch == boot_head_bytes[0]) // 如果第二个字节为0xAA,则继续找第二个字节
  473. {
  474. g_boot_data.count = 0;
  475. g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
  476. g_boot_data.state = BOOT_STATE_HEAD1;
  477. }
  478. else // 否则丢掉当前字节,继续找第一个字节
  479. {
  480. g_boot_data.state = BOOT_STATE_HEAD0;
  481. }
  482. }
  483. break;
  484. case BOOT_STATE_HEAD2:
  485. {
  486. if(ch == boot_head_bytes[2]) // 帧头正确,接收帧长度
  487. {
  488. g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
  489. g_boot_data.state = BOOT_STATE_LEN;
  490. }
  491. else // 否则重新接收
  492. {
  493. g_boot_data.state = BOOT_STATE_HEAD0;
  494. }
  495. }
  496. break;
  497. case BOOT_STATE_LEN: // 接收帧长
  498. {
  499. g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
  500. g_boot_data.check_sum += ch; // 此时开始计算校验和
  501. if(g_boot_data.count >= (sizeof(boot_head_bytes)+sizeof(uint16_t))) // 确保已经接收到了帧长
  502. {
  503. if((g_boot_data.recv_buf.data_t.len >= RECV_BYTES_MIN) // 判断帧长是否合法
  504. && (g_boot_data.recv_buf.data_t.len <= BUF_MAX_LENGTH))
  505. {
  506. g_boot_data.state = BOOT_STATE_PRO;
  507. }
  508. else
  509. {
  510. g_boot_data.state = BOOT_STATE_HEAD0;
  511. }
  512. }
  513. }
  514. break;
  515. case BOOT_STATE_PRO:
  516. {
  517. g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
  518. if(g_boot_data.count >= g_boot_data.recv_buf.data_t.len) // 接收完毕
  519. {
  520. // 校验和正确
  521. if(g_boot_data.check_sum == g_boot_data.recv_buf.buffer[g_boot_data.count-1])
  522. {
  523. // 数据解析完成
  524. memcpy(&g_boot_data_entire, &g_boot_data, sizeof(g_boot_data));
  525. g_boot_data_entire.recv_flag = BOOT_YES;
  526. }
  527. g_boot_data.state = BOOT_STATE_HEAD0;
  528. // return;
  529. }
  530. else
  531. {
  532. g_boot_data.check_sum += ch;
  533. }
  534. }
  535. break;
  536. default:
  537. g_boot_data.state = BOOT_STATE_HEAD0;
  538. break;
  539. }
  540. }
  541. }
  542. /**
  543. * @brief 开始跳转
  544. * @param None
  545. * @param None
  546. */
  547. void app_entry(void)
  548. {
  549. uint32_t *ptop;
  550. uint32_t stacktop;
  551. jump_func app;
  552. HAL_DeInit();
  553. __disable_irq();
  554. ptop = (uint32_t *)APP_START_ADDR;
  555. stacktop = *ptop++;
  556. app = (jump_func)*ptop;
  557. SCB->VTOR = FLASH_ADDR_BASE | (BOOTLOADER_LEN + PARAM_LEN);
  558. __set_MSP(stacktop);
  559. app();
  560. while(1);
  561. }
  562. /**
  563. * @brief 程序校验和跳转到app执行
  564. * @param None
  565. * @retval None
  566. */
  567. void boot_start_app(void)
  568. {
  569. uint32_t i = 0;
  570. uint8_t sum = 0;
  571. boot_param_t app_param = {0};
  572. flash_read(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&app_param);
  573. for(i=0; i<(sizeof(boot_param_t)-1); i++)
  574. {
  575. sum += ((uint8_t*)&app_param)[i];
  576. }
  577. if(sum != app_param.addsum)
  578. return;
  579. if(app_param.fw_flag != PARAM_FLAG)
  580. return;
  581. // 启动APP
  582. app_entry();
  583. }
  584. /**
  585. * @brief 是否需要升级
  586. * @param None
  587. * @retval 1:需要升级 0:不需要
  588. */
  589. uint8_t is_need_update(void)
  590. {
  591. boot_param_t app_param = {0};
  592. flash_read(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&app_param);
  593. if(app_param.fw_flag != PARAM_FLAG)
  594. return 1;
  595. return 0;
  596. }
  597. /**
  598. * @brief 使用帧协议接收处理串口数据
  599. * @param None
  600. * @retval None
  601. */
  602. void boot_event(void)
  603. {
  604. boot_recv_data();
  605. if(g_boot_data_entire.recv_flag == BOOT_YES)
  606. {
  607. g_boot_data_entire.recv_flag = BOOT_NO;
  608. boot_handle_cmd(&g_boot_data_entire.recv_buf);
  609. }
  610. }

5.主任务调用如下,

  1. // 需要处理串口数据次数
  2. volatile uint16_t g_uart_deal_cnt = 0;
  3. void system_reset(void)
  4. {
  5. __set_FAULTMASK(1);
  6. HAL_NVIC_SystemReset();
  7. }
  8. /**
  9. * @brief 主任务程序入口,由main调用
  10. * @param None
  11. * @retval 0
  12. */
  13. int main_loop(void)
  14. {
  15. uint32_t i;
  16. // 如果不需要升级则直接跳转
  17. if (!is_need_update())
  18. {
  19. app_entry();
  20. }
  21. while(1)
  22. {
  23. // 如果串口接收完成数据则g_uart_deal_cnt+1
  24. // 如果不等就需要处理串口数据,等则意味这串口无数据来,同时记录串口数据接收次数
  25. if (get_uart_recv_cnt() != g_uart_deal_cnt)
  26. {
  27. g_uart_deal_cnt++;
  28. boot_event();
  29. }
  30. // 如果升级完成
  31. if (is_boot_finish())
  32. {
  33. system_reset();
  34. }
  35. }
  36. return 0;
  37. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/477326?site=
推荐阅读
相关标签
  

闽ICP备14008679号