赞
踩
本文重点介绍代码实现,不介绍工程配置。
1.串口需要开启DMA接收数据,normal模式
2.修改串口中断,
- /* USER CODE BEGIN 0 */
- __weak void uart_user_handle(void)
- {
-
- }
- /* USER CODE END 0 */
-
- void USART3_IRQHandler(void)
- {
- /* USER CODE BEGIN USART3_IRQn 0 */
-
- /* USER CODE END USART3_IRQn 0 */
- HAL_UART_IRQHandler(&huart3);
- /* USER CODE BEGIN USART3_IRQn 1 */
- if(0 != __HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE))
- {
- __HAL_UART_CLEAR_IDLEFLAG(&huart3);
- uart_user_handle();
- }
- /* USER CODE END USART3_IRQn 1 */
- }
3.创建串口操作源文件 uart.c
- /**
- * @brief 串口应用层接口
- * @author lj
- * @date 2022/09/16
- *
- * ---------------------------------
- */
- #include "uart.h"
- #include "usart.h"
- #include "stm32f4xx.h"
- #include "common/ringbuffer.h"
-
- /* 串口接收最大 */
- #define RS485_RECV_MAX_SIZE 1024
-
- #define UART_ASSERT(x) { \
- if (!(x)) \
- return 0; \
- }
-
- #pragma pack(1)
-
- typedef struct {
- uint16_t size; // 缓冲区大小
- uint8_t buf[0]; // 动态缓冲区
- }uart_fifo_t;
-
- #pragma pack()
-
- /**
- * @brief 串口设备信息
- */
- typedef struct {
- UART_HandleTypeDef *huart; // 串口设备句柄
- uart_fifo_t *fifo; // 串口缓冲接收缓冲区
- T_RingBuffer ring; // 环形队列,用于数据存取
- uint16_t recv_cnt; // 接收次数
- }Uart_info_t;
-
-
- // 串口缓冲区
- static uint8_t uart3_buf[sizeof(uart_fifo_t) + RS485_RECV_MAX_SIZE] = {0};
- // 串口DMA缓冲区
- static uint8_t uart3_dma_buf[RS485_RECV_MAX_SIZE] = {0};
- // 串口DMA句柄
- extern DMA_HandleTypeDef hdma_usart3_rx;
- // 串口设备
- static Uart_info_t g_uart_device = {0};
- //static uint8_t *uart3_p = uart3_buf;
-
- /**
- * @brief RS485串口初始化
- * @param None
- * @retval None
- */
- void uart_init(void)
- {
- // 串口3初始化
- g_uart_device.huart = &huart3;
- g_uart_device.fifo = (uart_fifo_t *)uart3_buf;
- g_uart_device.fifo->size = RS485_RECV_MAX_SIZE;
- g_uart_device.recv_cnt = 0;
-
- // 初始化环形队列
- ringbuf_init(&g_uart_device.ring, g_uart_device.fifo->buf, g_uart_device.fifo->size);
- //使能IDLE中断
- __HAL_UART_ENABLE_IT(g_uart_device.huart, UART_IT_IDLE);
- // 开启dma接收
- HAL_UART_Receive_DMA(g_uart_device.huart, uart3_dma_buf, RS485_RECV_MAX_SIZE);
- }
-
- /**
- * @brief 串口写
- * @param buf:待发送数据
- * @param len:待发送数据长度
- * @retval 发送数据长度
- */
- uint16_t uart_write(uint8_t *buf, uint16_t len)
- {
- UART_ASSERT(buf != NULL);
- UART_ASSERT(len != 0);
- UART_ASSERT(g_uart_device.huart != NULL);
-
- HAL_GPIO_WritePin(GPIOG,GPIO_PIN_2,GPIO_PIN_SET);
- HAL_UART_Transmit(g_uart_device.huart, buf, len, 0xff);
- HAL_GPIO_WritePin(GPIOG,GPIO_PIN_2,GPIO_PIN_RESET);
-
- return len;
- }
-
- /**
- * @brief 串口读
- * @param buf:读取数据buf
- * @param len:读取数据buf长度
- * @retval 读取数据长度
- */
- uint16_t uart_read(uint8_t *buf, uint16_t len)
- {
- uint16_t length = 0;
-
- UART_ASSERT(buf != NULL);
- UART_ASSERT(len != 0);
- UART_ASSERT(g_uart_device.huart != NULL);
-
- __disable_irq(); // 防止数据读取时进入中断导致fifo数据被更改
- length = ringbuf_get(&g_uart_device.ring, buf, len);
- __enable_irq();
-
- return length;
- }
-
- /**
- * @brief 读取串口接收次数
- * @param None
- * @retval 串口接收次数
- */
- uint16_t get_uart_recv_cnt(void)
- {
- return g_uart_device.recv_cnt;
- }
-
- /**
- * @brief 串口中断DMA保存数据
- * @param None
- * @retval None
- */
- void uart_user_handle(void)
- {
- uint16_t rec_len = 0;
-
- // 停止DMA
- HAL_UART_DMAStop(g_uart_device.huart);
- // 获取数据长度
- rec_len = (RS485_RECV_MAX_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx));
- if (0 == rec_len)
- return;
-
- // 将数据放到fifo中
- __disable_irq();
- ringbuf_put(&g_uart_device.ring, uart3_dma_buf, rec_len);
- g_uart_device.recv_cnt++;
- __enable_irq();
- // 重新开启dma
- HAL_UART_Receive_DMA(g_uart_device.huart, uart3_dma_buf, RS485_RECV_MAX_SIZE); //重新打开DMA接收
- }
-
-
- /**
- * @brief 串口中断异常处理,清除ORE标志并重启中断
- */
- void HAL_UART_ErrorCallback (UART_HandleTypeDef *huart)
- {
- __attribute((unused)) uint32_t data = 0;
- __HAL_UNLOCK(huart);
-
- if(__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET)
- {
- __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_ORE); //清除溢出中断
- data = huart->Instance->SR;
- data = huart->Instance->DR;
- __HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
- }
- }
-
4.创建升级主文件 boot.c
-
- * boot.c
- *
- * Created on: 2022年10月22日
- * Author: lj
- */
- #include "boot.h"
- #include "uart.h"
- #include "flash.h"
- #include "common/crc.h"
-
- #include <stdlib.h>
- #include <string.h>
-
- #ifdef STM32F407xx
- #include "stm32f4xx_hal.h"
- #endif
-
- typedef void (*jump_func)(void);
-
- // 每一包数据大小
- #define SEND_SIZE_PER_SEND 256
- // 最大数据长度 = 每一包数据大小+1字节类型+2字节长度+除帧数据外的字节数
- #define BUF_MAX_LENGTH (SEND_SIZE_PER_SEND+3+7)
- // 最大读取长度
- #define BUF_MAX_READ_LEN 1024
- // 接收最小字节数 (3字节头+2字节数据长度+1字节命令字+1字节校验和)
- #define RECV_BYTES_MIN 7
- // 软件版本
- #define VERSION_INFO(main,sub,modify) (((main) << 24) | ((sub) << 16) | ((modify) << 8))
- #define BOOT_VERSION VERSION_INFO(1, 0, 0)
-
-
- //------------------flash操作状态---------------
- #define UPDATE_ACK_STATE_CHECK_ERROR 0x01 // 校验错误
- #define UPDATE_ACK_STATE_WRITE_RIGHT 0x02 // FLASH写入正确
- #define UPDATE_ACK_STATE_WRITE_ERROR 0x03 // FLASH写入错误
- #define UPDATE_ACK_STATE_ERASEING 0x04 // FLASH擦除中
- #define UPDATE_ACK_STATE_ERASE_DONE 0x05 // FLASH擦除完毕
-
- // 返回升级boot命令字
- #define CMD_ACK_BOOTLOADER 0xE0
- // 返回升级app命令字
- #define CMD_ACK_APP 0xE1
- // 返回升级错误命令字
- #define CMD_ACK_ERR 0xE2
- // 升级过程中升级内容为boot
- #define CMD_UPDATE_BOOT 0xBC
- // 升级过程中升级内容为app
- #define CMD_UPDATE_APP 0xBD
-
- /**
- * @brief 接收一帧完成
- */
- typedef enum
- {
- BOOT_NO,
- BOOT_YES
- }boot_recv_e;
-
- /**
- * @brief 升级过程中状态
- */
- typedef enum
- {
- CMD_UPDATE_READY = 0xE0,
- CMD_UPDATE_FILE = 0xF0,
- CMD_UPDATE_FINISH = 0xFF
- }boot_update_e;
-
- /**
- * @brief 升级类型
- */
- typedef enum
- {
- BOOT_TYPE_NONE,
- BOOT_TYPE_BOOTLOADER,
- BOOT_TYPE_APP
- }boot_type_e;
-
- /**
- * @brief 升级状态机
- */
- typedef enum
- {
- BOOT_STATE_HEAD0, // 接收帧头第一个字节
- BOOT_STATE_HEAD1, // 接收帧头第二个字节
- BOOT_STATE_HEAD2, // 接收帧头第三个字节
- BOOT_STATE_LEN, // 接收帧长
- BOOT_STATE_PRO // 接收至数据完成
- }boot_state_e;
-
- #pragma pack(1)
- /**
- * @brief 数据缓存buf
- */
- typedef union
- {
- uint8_t buffer[BUF_MAX_LENGTH];
- struct
- {
- uint8_t head0; // 头字节1
- uint8_t head1; // 头字节2
- uint8_t head2; // 头字节3
- uint16_t len; // 数据长度
- uint8_t cmd; // 指令
- uint8_t data[BUF_MAX_LENGTH - 6]; // 数据
- }data_t;
- }recv_buf_t;
-
- /**
- * @brief boot主结构体
- */
- typedef struct
- {
- uint8_t state; // 状态机标志
- uint16_t count; // 接收数量
- uint8_t check_sum; // 校验和
- uint8_t recv_flag; // 接收标志
- recv_buf_t recv_buf; // 接收缓冲区
- }boot_t;
-
- /**
- * @brief 升级参数
- */
- typedef struct
- {
- uint32_t fw_flag; // 升级标志位
- uint32_t page_num; // 页数量
- uint32_t chksum; // 校验和
- uint32_t size; // 总大小
- uint16_t addsum; // 累加和
- }boot_param_t;
-
- /**
- * @brief 升级过程中的参数
- */
- typedef struct
- {
- uint8_t is_finish;// 升级类型 1:bootloader 2:app
- uint8_t boot_type;
- uint32_t addr;
- uint32_t flash_addr;
- }boot_pro_t;
- #pragma pack()
-
-
- // 头字节
- const uint8_t boot_head_bytes[] = {0xAA, 0x55, 0xAA};
- // 升级所需参数
- static boot_pro_t g_state = {0};
- // 升级参数
- static boot_param_t g_param_data = {0};
- // boot
- static boot_t g_boot_data = {0};
- // 解析出来的完整的数据
- static boot_t g_boot_data_entire = {0};
- // 软件版本信息
- static char soft_version[] = \
- "\r\n==============================================\r\n \
- ** CPU(stm32f4xx) BootLoader\r\n \
- **Author lj\r\n \
- **Date 20221022\r\n \
- **Version V1.0.0\r\n \
- ===================================================\r\n\0";
-
- /**
- * @brief 计算校验和
- * @param buff:待校验数据
- * @param len:数据长度
- * @retval 校验和
- */
- static uint8_t calc_chksum(uint8_t* buff, uint16_t len)
- {
- uint8_t checkSum = 0;
- uint16_t i = 0;
-
- if(buff == NULL || len == 0)
- return 0;
-
- for(i=0; i<len; i++)
- {
- checkSum += buff[i];
- }
-
- return checkSum;
- }
-
- /**
- * @brief boot发送数据
- * @param cmd:命令子
- * @param data:待发送数据
- * @param len:发送数据长度
- * @retval None
- */
- static void boot_send_data(uint8_t cmd, uint8_t* data, uint16_t len)
- {
- recv_buf_t send_buf = {0};
- memcpy(send_buf.buffer, boot_head_bytes, sizeof(boot_head_bytes));
-
- send_buf.data_t.cmd = cmd;
-
- if((data == NULL) || (len == 0))
- {
- send_buf.data_t.len = RECV_BYTES_MIN;
- }
- else
- {
- memcpy(&send_buf.data_t.data[0], data, len);
- send_buf.data_t.len = len + RECV_BYTES_MIN;
- }
-
- send_buf.data_t.data[len] = calc_chksum(&send_buf.buffer[3], 3+len);
-
- // 发送数据
- uart_write(&send_buf.buffer[0], send_buf.data_t.len);
- }
-
- /**
- * @brief 保存升级参数
- * @param None
- * @retval None
- */
- static void boot_save_param(void)
- {
- uint16_t i = 0;
- // boot_param_t read ={0};
-
- if(g_state.boot_type != BOOT_TYPE_APP)
- return;
-
- // 擦除参数
- flash_erase_param();
-
- g_param_data.fw_flag = PARAM_FLAG;
- g_param_data.addsum = 0;
- for(i=0; i<(sizeof(boot_param_t)-1); i++)
- {
- g_param_data.addsum += ((uint8_t*)&g_param_data)[i];
- }
-
- flash_write(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&g_param_data);
- // memset(g_param_data, 0, sizeof(boot_param_t));
- // flash_read(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&read);
- // i++;
- }
-
- /**
- * @brief 读取参数
- * @param None
- * @retval None
- */
- __attribute((unused)) static void boot_read_param(void)
- {
- uint8_t sum = 0;
- uint16_t i = 0;
-
- memset((uint8_t*)&g_param_data, 0, sizeof(boot_param_t));
- flash_read(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&g_param_data);
-
- for(i=0; i<(sizeof(boot_param_t)-1); i++)
- {
- sum += ((uint8_t*)&g_param_data)[i];
- }
-
- if(sum != g_param_data.addsum)
- {
- memset((uint8_t*)&g_param_data, 0, sizeof(boot_param_t));
- }
- }
-
- /**
- * @brief 开始升级,初始化参数
- * @param data:指令类型
- * @retval None
- */
- static void boot_init(uint8_t* data)
- {
- uint8_t cmd = 0;
-
- if(data == NULL)
- return;
-
- if(data[0] == 0x01) // 升级BOOT
- {
- g_state.addr = BOOT_START_ADDR;
- g_state.boot_type = BOOT_TYPE_BOOTLOADER;
- g_state.is_finish = BOOT_NO;
- g_state.flash_addr = 0;
- // EraseAddr = BOOT_ADDR;
- // Flash_Erase_Num = BOOT_BLUK_NUM;
- cmd = CMD_ACK_BOOTLOADER;
- }
- else if(data[0] == 0x02) // 升级APP
- {
- g_state.addr = APP_START_ADDR;
- g_state.boot_type = BOOT_TYPE_APP;
- g_state.is_finish = BOOT_NO;
- g_state.flash_addr = 0;
- //Bin_Flash_Adr = 0;
- // EraseAddr = APP_ADDR;
- // Flash_Erase_Num = APP_ERASE_NUM;
- cmd = CMD_ACK_APP;
- }
- else
- {
- g_state.addr = APP_START_ADDR;
- g_state.boot_type = BOOT_TYPE_NONE;
- g_state.is_finish = BOOT_NO;
- g_state.flash_addr = 0;
-
- cmd = CMD_ACK_ERR;
- }
-
- boot_send_data(cmd, NULL, 0);
- }
-
- #pragma pack(1)
-
- typedef struct
- {
- uint8_t type; // 类型
- uint16_t num; // 程序页数量
- uint8_t content[SEND_SIZE_PER_SEND];// 程序内容
- }file_data_t;
- #pragma pack()
-
- /**
- * @brief 开始升级,初始化参数
- * @param data:升级数据,为
- * @retval None
- */
- static void boot_update(uint8_t* data)
- {
- uint8_t ack_state = 0;
- uint8_t read_tmp[256] = {0};
- uint16_t i = 0;
- uint32_t check_sum = 0;
- uint32_t bin_write_addr = 0;
- file_data_t* file_data = NULL;
-
- if(g_state.boot_type == BOOT_TYPE_NONE || data == NULL)
- return;
-
- file_data = (file_data_t *)data;
-
- if((file_data->type == CMD_UPDATE_BOOT && g_state.addr == BOOT_START_ADDR) ||
- (file_data->type == CMD_UPDATE_APP && g_state.addr == APP_START_ADDR))
- {
- bin_write_addr = g_state.addr + g_state.flash_addr;
- }
- else
- {
- ack_state = UPDATE_ACK_STATE_WRITE_ERROR;
- boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
- }
-
-
- if(g_state.flash_addr == file_data->num * SEND_SIZE_PER_SEND)
- {
- if(g_state.flash_addr == 0)
- {
- ack_state = UPDATE_ACK_STATE_ERASEING; // FLASH 擦除中
- boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
-
- flash_erase_app();
-
- ack_state = UPDATE_ACK_STATE_ERASE_DONE; // FLASH 擦除完毕
- boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
-
- // flash_erase_param(); // 参数擦除
- }
-
- flash_write(bin_write_addr, SEND_SIZE_PER_SEND, &file_data->content[0]);
- flash_read(bin_write_addr, SEND_SIZE_PER_SEND, &read_tmp[0]);
-
- for(i=0; i<SEND_SIZE_PER_SEND; i++)
- {
- check_sum += read_tmp[i];
- if(read_tmp[i] != file_data->content[i]) // 如果校验错误,需要重发
- {
- ack_state = UPDATE_ACK_STATE_CHECK_ERROR;
- boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
- return;
- }
- }
-
- g_state.flash_addr += SEND_SIZE_PER_SEND;
- g_param_data.page_num = file_data->num + 1;
- g_param_data.chksum += check_sum;
-
-
- ack_state = UPDATE_ACK_STATE_WRITE_RIGHT;
- boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
- }
- else
- {
- ack_state = UPDATE_ACK_STATE_WRITE_RIGHT;
- boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
- }
-
- }
-
- /**
- * @brief 获取当前时间
- * @param None
- * @retval 当前时间
- */
- static uint32_t get_current_time(void)
- {
- #ifdef STM32F407xx
- return HAL_GetTick();
- #else
- return 0;
- #endif
- }
-
- /**
- * @brief 处理升级数据
- * @param data:接收到的完整数据
- * @retval None
- */
- static void boot_handle_cmd(recv_buf_t *data )
- {
- uint8_t ack_state = 0;
- uint32_t sys_time = 0;
- static uint32_t pre_time = 0;
-
- if(data == NULL)
- return;
-
- switch(data->data_t.cmd)
- {
- // 固件升级使能
- case CMD_UPDATE_READY:
- {
- sys_time = get_current_time();
- // 500 ms内只响应一次
- if((pre_time != 0) && (sys_time-pre_time) < 500)
- return;
-
- pre_time = sys_time;
-
- boot_init(&data->data_t.data[0]);
- }
- break;
-
- // 固件文件传输
- case CMD_UPDATE_FILE:
- {
- boot_update(&data->data_t.data[0]);
- }
- break;
-
- // 固件升级完成
- case CMD_UPDATE_FINISH:
- {
- boot_save_param();
-
- g_state.flash_addr = 0;
- g_state.boot_type = BOOT_TYPE_NONE;
- g_state.is_finish = BOOT_YES;
- }
- break;
-
- default:
- {
- ack_state = UPDATE_ACK_STATE_CHECK_ERROR;
- boot_send_data(CMD_UPDATE_FILE, &ack_state, 1);
- }
- break;
- }
- }
-
- /**
- * @brief 返回升级成功标志
- * @param None
- * @retval 升级成功标志位
- */
- uint8_t is_boot_finish(void)
- {
- return g_state.is_finish;
- }
-
- /**
- * @brief 返回升级状态
- * @param None
- * @retval 升级状态 !0=升级中 0=没升级
- */
- uint8_t get_boot_status(void)
- {
- return g_state.boot_type;
- }
-
- /**
- * @brief 发送软件版本信息
- * @param None
- * @retval None
- */
- void send_boot_version(void)
- {
- uart_write((uint8_t *)soft_version, strlen(soft_version));
- }
-
- /**
- * @brief 接收解析串口数据
- * @param None
- * @retval None
- */
- static void boot_recv_data(void)
- {
- uint8_t ch = 0;
- uint16_t i = 0;
- uint16_t date_len = 0;
- uint8_t buff[BUF_MAX_READ_LEN] = {0};
-
- // 读取串口数据
- date_len = uart_read(buff, BUF_MAX_READ_LEN);
- if(date_len == 0)
- return;
-
- for(i=0; i<date_len; i++)
- {
- ch = buff[i];
-
- switch(g_boot_data.state)
- {
- // 找帧头
- case BOOT_STATE_HEAD0:
- {
- if(ch == boot_head_bytes[0])
- {
- g_boot_data.count = 0;
- g_boot_data.check_sum = 0;
- g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
- g_boot_data.state = BOOT_STATE_HEAD1;
- }
- }
- break;
-
- case BOOT_STATE_HEAD1:
- {
- if(ch == boot_head_bytes[1]) // 如果第二个字节为0x55,就找第三个字节
- {
- g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
- g_boot_data.state = BOOT_STATE_HEAD2;
- }
- else if(ch == boot_head_bytes[0]) // 如果第二个字节为0xAA,则继续找第二个字节
- {
- g_boot_data.count = 0;
- g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
- g_boot_data.state = BOOT_STATE_HEAD1;
- }
- else // 否则丢掉当前字节,继续找第一个字节
- {
- g_boot_data.state = BOOT_STATE_HEAD0;
- }
- }
- break;
-
- case BOOT_STATE_HEAD2:
- {
- if(ch == boot_head_bytes[2]) // 帧头正确,接收帧长度
- {
- g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
- g_boot_data.state = BOOT_STATE_LEN;
- }
- else // 否则重新接收
- {
- g_boot_data.state = BOOT_STATE_HEAD0;
- }
- }
- break;
-
- case BOOT_STATE_LEN: // 接收帧长
- {
- g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
- g_boot_data.check_sum += ch; // 此时开始计算校验和
- if(g_boot_data.count >= (sizeof(boot_head_bytes)+sizeof(uint16_t))) // 确保已经接收到了帧长
- {
- if((g_boot_data.recv_buf.data_t.len >= RECV_BYTES_MIN) // 判断帧长是否合法
- && (g_boot_data.recv_buf.data_t.len <= BUF_MAX_LENGTH))
- {
- g_boot_data.state = BOOT_STATE_PRO;
- }
- else
- {
- g_boot_data.state = BOOT_STATE_HEAD0;
- }
- }
- }
- break;
-
- case BOOT_STATE_PRO:
- {
- g_boot_data.recv_buf.buffer[g_boot_data.count++] = ch;
- if(g_boot_data.count >= g_boot_data.recv_buf.data_t.len) // 接收完毕
- {
- // 校验和正确
- if(g_boot_data.check_sum == g_boot_data.recv_buf.buffer[g_boot_data.count-1])
- {
- // 数据解析完成
- memcpy(&g_boot_data_entire, &g_boot_data, sizeof(g_boot_data));
- g_boot_data_entire.recv_flag = BOOT_YES;
- }
- g_boot_data.state = BOOT_STATE_HEAD0;
- // return;
- }
- else
- {
- g_boot_data.check_sum += ch;
- }
- }
- break;
-
- default:
- g_boot_data.state = BOOT_STATE_HEAD0;
- break;
- }
- }
- }
-
-
- /**
- * @brief 开始跳转
- * @param None
- * @param None
- */
- void app_entry(void)
- {
- uint32_t *ptop;
- uint32_t stacktop;
- jump_func app;
-
- HAL_DeInit();
- __disable_irq();
-
- ptop = (uint32_t *)APP_START_ADDR;
-
- stacktop = *ptop++;
- app = (jump_func)*ptop;
-
- SCB->VTOR = FLASH_ADDR_BASE | (BOOTLOADER_LEN + PARAM_LEN);
- __set_MSP(stacktop);
-
- app();
-
- while(1);
- }
-
- /**
- * @brief 程序校验和跳转到app执行
- * @param None
- * @retval None
- */
- void boot_start_app(void)
- {
- uint32_t i = 0;
- uint8_t sum = 0;
-
- boot_param_t app_param = {0};
-
- flash_read(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&app_param);
-
- for(i=0; i<(sizeof(boot_param_t)-1); i++)
- {
- sum += ((uint8_t*)&app_param)[i];
- }
-
- if(sum != app_param.addsum)
- return;
-
- if(app_param.fw_flag != PARAM_FLAG)
- return;
-
- // 启动APP
- app_entry();
- }
-
- /**
- * @brief 是否需要升级
- * @param None
- * @retval 1:需要升级 0:不需要
- */
- uint8_t is_need_update(void)
- {
- boot_param_t app_param = {0};
-
- flash_read(PARAM_START_ADDR, sizeof(boot_param_t), (uint8_t*)&app_param);
-
- if(app_param.fw_flag != PARAM_FLAG)
- return 1;
- return 0;
- }
-
- /**
- * @brief 使用帧协议接收处理串口数据
- * @param None
- * @retval None
- */
- void boot_event(void)
- {
- boot_recv_data();
-
- if(g_boot_data_entire.recv_flag == BOOT_YES)
- {
- g_boot_data_entire.recv_flag = BOOT_NO;
- boot_handle_cmd(&g_boot_data_entire.recv_buf);
- }
- }
5.主任务调用如下,
- // 需要处理串口数据次数
- volatile uint16_t g_uart_deal_cnt = 0;
-
- void system_reset(void)
- {
- __set_FAULTMASK(1);
- HAL_NVIC_SystemReset();
- }
-
- /**
- * @brief 主任务程序入口,由main调用
- * @param None
- * @retval 0
- */
- int main_loop(void)
- {
- uint32_t i;
-
- // 如果不需要升级则直接跳转
- if (!is_need_update())
- {
- app_entry();
- }
-
- while(1)
- {
- // 如果串口接收完成数据则g_uart_deal_cnt+1
- // 如果不等就需要处理串口数据,等则意味这串口无数据来,同时记录串口数据接收次数
- if (get_uart_recv_cnt() != g_uart_deal_cnt)
- {
- g_uart_deal_cnt++;
-
- boot_event();
-
- }
-
- // 如果升级完成
- if (is_boot_finish())
- {
- system_reset();
- }
- }
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。