Explorar el Código

bootloader升级

樊春春 hace 3 meses
padre
commit
ecffaa9a42

+ 1 - 4
app/stm32f4xx_it.c

@@ -143,10 +143,7 @@ void PendSV_Handler(void)
 void SysTick_Handler(void)
 {
     schedule_clock();
-    // if (jump_boot_time == 10)
-    // {
-    //     NVIC_SystemReset();
-    // }
+    jump_boot_time_ctrl();
 }
 
 /******************************************************************************/

+ 34 - 16
dev/can/dev_can.c

@@ -5,6 +5,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+queue_entry(pdu_tag, 30) can_tx_queue;
+queue_entry(pdu_tag, 30) can_rx_queue;
+
 double pow_branch(double x, long long N)
 {
     double ans = 1.0;
@@ -57,7 +60,8 @@ void product_array(uint8_t send_array[8])
 
 uint8_t push_can_message_to_queue(uint32_t id, uint8_t len, uint8_t *p_data)
 {
-    pdu_tag response_msg;
+    pdu_tag      response_msg;
+    QUEUE_STATUS result_status;
     response_msg.id.r    = id;
     response_msg.reg.dlc = len;
     memcpy(&response_msg.data.u8_buf[0], p_data, len);
@@ -71,7 +75,10 @@ uint8_t push_can_message_to_queue(uint32_t id, uint8_t len, uint8_t *p_data)
         response_msg.reg.ide = CAN_Id_Standard;
     }
 
-    if (en_queue(&can_tx_queue, response_msg) != Q_OK)
+    __disable_irq();
+    en_queue(&can_tx_queue, response_msg, result_status);
+    __enable_irq();
+    if (result_status != Q_OK)
     {
         return 0;
     }
@@ -88,9 +95,12 @@ static uint8_t can_tx_frame(pdu_tag can_message)
 
 void can_tx_callback(void)
 {
-    pdu_tag tx_data;
+    pdu_tag      tx_data;
+    QUEUE_STATUS result_status;
+
+    de_queue(&can_tx_queue, tx_data, result_status);
 
-    if (de_queue(&can_tx_queue, &tx_data) == Q_OK) // 返回值为1代表读取成功
+    if (result_status == Q_OK) // 返回值为1代表读取成功
     {
         can_tx_frame(tx_data);
         CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);
@@ -103,16 +113,15 @@ void can_tx_callback(void)
 
 void can_rx_callback(CanRxMsg rx_message)
 {
-    pdu_tag data;
-    uint8_t ps;
-    uint8_t pf;
+    pdu_tag      data;
+    QUEUE_STATUS result;
     switch (rx_message.ExtId)
     {
     case 0x18DFF4E1:
         data.id.r    = 0x18DFF4E1;
         data.reg.dlc = rx_message.DLC;
         memcpy(&data.data.u8_buf[0], rx_message.Data, rx_message.DLC);
-        en_queue(&can_rx_queue, data);
+        en_queue(&can_rx_queue, data, result);
         break;
     default:
         return;
@@ -127,11 +136,13 @@ can_rx_tab can_tab[] = {
 
 void can_start_send(void)
 {
-    pdu_tag tx_msg;
-    if (RESET == CAN_GetITStatus(CAN1, CAN_IT_TME))
-    {
+    pdu_tag      tx_msg;
+    QUEUE_STATUS result_status;
 
-        if (de_queue(&can_tx_queue, &tx_msg) == Q_OK) // 返回值为1代表读取成功
+    if (0 == ((CAN1->IER) & 0x1))
+    {
+        de_queue(&can_tx_queue, tx_msg, result_status);
+        if (result_status == Q_OK) // 返回值为1代表读取成功
         {
             can_tx_frame(tx_msg);
             CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);
@@ -141,13 +152,18 @@ void can_start_send(void)
 
 static uint8_t can_rx_process(void)
 {
-    uint8_t i;
-    uint8_t flg = 0;
-    pdu_tag rec_msg;
+    uint8_t      i;
+    uint8_t      flg = 0;
+    pdu_tag      rec_msg;
+    QUEUE_STATUS result;
 
     for (uint8_t j = 0; j < 15; j++)
     {
-        if (Q_OK == de_queue(&can_rx_queue, &rec_msg))
+        __disable_irq();
+        de_queue(&can_rx_queue, rec_msg, result);
+        __enable_irq();
+
+        if (Q_OK == result)
         {
             for (i = 0; i < ARR_SIZE(can_tab); i++)
             {
@@ -164,6 +180,8 @@ static uint8_t can_rx_process(void)
 void dev_can_network_init(void)
 {
     drv_can_init();
+    queue_init(&can_rx_queue);
+    queue_init(&can_tx_queue);
     drv_can_rx_back_init(can_rx_callback);
     drv_can_tx_back_init(can_tx_callback);
 }

+ 30 - 2
dev/iap/dev_iap.c

@@ -103,10 +103,38 @@ uint8_t erase_app_flash(uint32_t start_address, uint32_t end_addr)
     uint8_t  status   = 0;
     uint16_t page_len = 0;
     // page_len          = (end_addr - start_address) / FMC_PAGE_SIZE;
-    status = fmc_erase_pages(start_address, page_len);
+    // status = fmc_erase_pages(start_address, page_len);
+
+    if ((start_address == ADDR_FLASH_SECTOR_2))
+    {
+        status = fmc_erase_pages(start_address, 5);
+    }
+    else if ((start_address == ADDR_FLASH_SECTOR_8))
+    {
+        status = fmc_erase_pages(start_address, 3);
+    }
+    else
+    {
+        status = 1;
+    }
+
     return status;
 }
 
+void jump_boot_time_ctrl(void)
+{
+    if (jump_boot_time > 0)
+    {
+        jump_boot_time--;
+        if (jump_boot_time == 0)
+        {
+            // jump_flag = 1;
+            __set_FAULTMASK(1); //  关闭所有中断
+            NVIC_SystemReset(); //  复位
+        }
+    }
+}
+
 void write_app_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num)
 {
     static uint32_t w_start_addr = 0;
@@ -218,7 +246,7 @@ void iap_rec_handler(pdu_tag rec_msg)
             {
                 // 喂狗
                 fmc_clear_flag_star();
-                erase_flag = erase_app_flash(DOWNLOAD_START_ADDR, DOWNLOAD_MIDDLE_ADDR);
+                erase_flag = erase_app_flash(DOWNLOAD_START_ADDR, DOWNLOAD_END_ADDR);
                 fmc_clear_flag_end();
                 // 喂狗
                 g_iap.count_bytes    = 0;

+ 5 - 4
dev/iap/dev_iap.h

@@ -36,14 +36,14 @@ extern 'C'
 #define UPGRADE_APP_DATA_SIZE  4                                                // 升级参数数组元素个数
 #define UPGRADE_BUFF_DATA_SIZE (UPGRADE_FLAG_DATA_SIZE + UPGRADE_APP_DATA_SIZE) // 升级参数数组元素个数
 
-#define APP_START_ADDR ((uint32_t)0x08010000)
-#define APP_END_ADDR   ((uint32_t)0x08060000)
+#define APP_START_ADDR ((uint32_t)0x08008000)
+#define APP_END_ADDR   ((uint32_t)0x0805FFFF)
 
 #define UPGRADE_FLAG_START_ADDR ((uint32_t)0x08060000)
-#define UPGRADE_FLAG_END_ADDR   ((uint32_t)0x08061000)
+#define UPGRADE_FLAG_END_ADDR   ((uint32_t)0x0807FFFF)
 
 #define DOWNLOAD_START_ADDR  ((uint32_t)0x08080000)
-#define DOWNLOAD_END_ADDR    ((uint32_t)0x080C0000)
+#define DOWNLOAD_END_ADDR    ((uint32_t)0x080DFFFF)
 #define DOWNLOAD_MIDDLE_ADDR ((uint32_t)0x080A0000)
 
 // 升级命令
@@ -103,6 +103,7 @@ extern 'C'
     void    iap_param_init(void);
     void    iap_flag_release(void);
     uint8_t erase_app_flash(uint32_t start_address, uint32_t end_addr);
+    void    jump_boot_time_ctrl(void);
     void    iap_rec_handler(pdu_tag rec_msg);
 
 /************************************************************************************************

+ 0 - 104
dev/queue/queue.c

@@ -1,104 +0,0 @@
-#include "queue.h"
-
-///   front   ...         rear      数据方向 ->
-/* 队列的顺序存储结构(循环队列) */
-
-can_queue_tag can_tx_queue;
-can_queue_tag can_rx_queue;
-
-/****************************************************
- *  函 数 名:init_queue
- *  函数功能:初始化队列
- *  入口参数:无
- *  说    明:
- ****************************************************/
-void queue_init(p_can_queue_tag p_queue)
-{                                      /* 构造一个空队列Q */
-    p_queue->head = p_queue->tail = 0; /*空队列*/
-    p_queue->count                = 0;
-}
-
-/****************************************************
- *  函 数 名:is_queue_empty
- *  函数功能:查询队列是否为空
- *  入口参数:Q 队列
- *  说    明:空队列,返回SUCCESS;否则返回ERROR
- ****************************************************/
-uint8_t queue_empty(p_can_queue_tag p_queue)
-{ /* 若*/
-    return p_queue->count == 0;
-}
-
-uint8_t queue_full(p_can_queue_tag p_queue)
-{ /* 若*/
-    return p_queue->count == MAX_QSIZE;
-}
-
-/****************************************************
- *  函 数 名:queue_length
- *  函数功能:初始化长度
- *  入口参数:Q 队列
- *  说    明:
- ****************************************************/
-uint16_t queue_length(can_queue_tag p_queue)
-{ /* 返回Q的元素个数,即队列的长度 */
-    return (p_queue.tail - p_queue.head + MAX_QSIZE) % MAX_QSIZE;
-}
-
-/****************************************************
- *  函 数 名:get_head
- *  函数功能:获取对头数据
- *  入口参数:Q 队列
- *  说    明:
- ****************************************************/
-uint8_t get_head(
-    can_queue_tag *p_queue,
-    pdu_tag       *e)
-{                                       /* 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR*/
-    if (p_queue->head == p_queue->tail) /* 队列空 */
-        return Q_ERR;
-    *e = p_queue->can_message[p_queue->head];
-
-    p_queue->head = (p_queue->head + 1) % MAX_QSIZE;
-    return Q_OK;
-}
-
-/****************************************************
- *  函 数 名:insert_queue
- *  函数功能:队列插入数据
- *  入口参数:Q 待插入队列    e 待插入数据
- *  说    明:
- ****************************************************/
-QUEUE_STATUS en_queue(p_can_queue_tag p_queue,
-                      pdu_tag         data)
-{
-    if (queue_full(p_queue))
-        return Q_FULL;
-    p_queue->count++;
-    p_queue->can_message[p_queue->head] = data;
-    p_queue->head                       = (p_queue->head + 1) % MAX_QSIZE;
-    return Q_OK;
-    /* 插入元素e为Q的新的队尾元素 */
-    // if ((p_queue->tail + 1) % MAX_QSIZE == p_queue->head) /* 队列满 */
-    //     return ERROR;
-    // p_queue->can_message[p_queue->tail] = e;
-    // p_queue->tail                       = (p_queue->tail + 1) % MAX_QSIZE;
-    // return SUCCESS;
-}
-
-QUEUE_STATUS de_queue(p_can_queue_tag p_queue,
-                      p_pdu_tag       p_data)
-{ /* 插入元素e为Q的新的队尾元素 */
-    // if ((p_queue->tail + 1) % MAX_QSIZE == p_queue->head) /* 队列满 */
-    //     return ERROR;
-    // p_queue->can_message[p_queue->tail] = e;
-    // p_queue->tail                       = (p_queue->tail + 1) % MAX_QSIZE;
-    // return SUCCESS;
-    if (queue_empty(p_queue))
-        return Q_EMPTY;
-    *p_data       = p_queue->can_message[p_queue->tail];
-    p_queue->tail = (p_queue->tail + 1) % MAX_QSIZE;
-    p_queue->count--;
-
-    return Q_OK;
-}

+ 51 - 27
dev/queue/queue.h

@@ -2,10 +2,6 @@
 #define __QUEUE_H
 #include "stdio.h"
 
-#define MAX_QSIZE (60u) /* 最大队列长度 */
-
-typedef unsigned long long u64;
-
 typedef struct
 {
     struct
@@ -32,24 +28,10 @@ typedef struct
         uint8_t  u8_buf[8];
         uint16_t u16_buf[4];
         uint32_t u32_buf[2];
-        u64      u64_buf;
+        uint64_t u64_buf;
     } data;
 } pdu_tag, *p_pdu_tag;
 
-typedef struct
-{
-    uint8_t  buf[8];
-    uint32_t can_id;
-} CanData_TypeDef;
-
-typedef struct
-{
-    uint16_t head;
-    uint16_t tail;
-    uint16_t count;
-    pdu_tag  can_message[MAX_QSIZE];
-} can_queue_tag, *p_can_queue_tag;
-
 typedef enum
 {
     Q_OK,
@@ -58,13 +40,55 @@ typedef enum
     Q_EMPTY,
 } QUEUE_STATUS;
 
-extern can_queue_tag can_tx_queue;
-extern can_queue_tag can_rx_queue;
+#define queue_entry(type, size) \
+    struct                      \
+    {                           \
+        uint8_t head;           \
+        uint8_t tail;           \
+        uint8_t count;          \
+        type    message[size];  \
+    }
+
+#define queue_init(name)                 \
+    {                                    \
+        (name)->head = (name)->tail = 0; \
+        (name)->count               = 0; \
+    }
+
+/* List functions. */
+#define queue_empty(name) ((name)->count == 0)
+#define queue_max(name)   ((sizeof((name)->message)) / (sizeof((name)->message[0])))
+#define queue_full(name)  ((name)->count == ((sizeof((name)->message)) / (sizeof((name)->message[0]))))
+#define en_queue(name, field, ret)                                                \
+    do                                                                            \
+    {                                                                             \
+        if (queue_full(name))                                                     \
+        {                                                                         \
+            ret = Q_FULL;                                                         \
+        }                                                                         \
+        else                                                                      \
+        {                                                                         \
+            (name)->count++;                                                      \
+            (name)->message[(name)->head] = field;                                \
+            (name)->head                  = ((name)->head + 1) % queue_max(name); \
+            ret                           = Q_OK;                                 \
+        }                                                                         \
+    } while (0)
+
+#define de_queue(name, field, ret)                               \
+    do                                                           \
+    {                                                            \
+        if (queue_empty(name))                                   \
+        {                                                        \
+            ret = Q_EMPTY;                                       \
+        }                                                        \
+        else                                                     \
+        {                                                        \
+            field        = (name)->message[(name)->tail];        \
+            (name)->tail = ((name)->tail + 1) % queue_max(name); \
+            (name)->count--;                                     \
+            ret = Q_OK;                                          \
+        }                                                        \
+    } while (0)
 
-void         queue_init(p_can_queue_tag);  // 初始化队列
-uint8_t      queue_empty(p_can_queue_tag); // 查询队列是否为空
-uint8_t      queue_full(p_can_queue_tag);
-uint8_t      get_head(can_queue_tag *p_queue, pdu_tag *data); // 获取对头数据
-QUEUE_STATUS en_queue(p_can_queue_tag, pdu_tag);              // 队列插入数据
-QUEUE_STATUS de_queue(p_can_queue_tag, p_pdu_tag);
 #endif

BIN
doc/BOOT升级协议/CAN升级协议.xlsx


+ 1 - 1
driver/board.c

@@ -5,5 +5,5 @@ void drv_board_init()
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
     drv_systick_init();
     drv_gpio_init();
-    dwt_init();
+    // dwt_init();
 }

+ 1 - 2
driver/can/drv_can.c

@@ -42,7 +42,7 @@ u8 drv_can1_mode_init(uint8_t tsjw, uint8_t tbs2, uint8_t tbs1, uint16_t brp, ui
 
     // CAN单元设置
     CAN_InitStructure.CAN_TTCM      = DISABLE; // 非时间触发通信模式
-    CAN_InitStructure.CAN_ABOM      = DISABLE; // 软件自动离线管理
+    CAN_InitStructure.CAN_ABOM      = ENABLE;  // 软件自动离线管理
     CAN_InitStructure.CAN_AWUM      = DISABLE; // 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
     CAN_InitStructure.CAN_NART      = DISABLE; // 禁止报文自动传送
     CAN_InitStructure.CAN_RFLM      = DISABLE; // 报文不锁定,新的覆盖旧的
@@ -78,7 +78,6 @@ u8 drv_can1_mode_init(uint8_t tsjw, uint8_t tbs2, uint8_t tbs1, uint16_t brp, ui
     NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
 
-    CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); // FIFO0消息挂号中断允许.
     NVIC_InitStructure.NVIC_IRQChannel                   = CAN1_TX_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0; // 次优先级为0

+ 32 - 3
driver/flash/drv_flash.c

@@ -108,13 +108,42 @@ uint8_t fmc_read_one_page(uint32_t read_addr, uint16_t *buff)
 // 擦出N页, 地址必须对齐页首
 uint8_t fmc_erase_pages(uint32_t erase_addr, uint16_t len)
 {
+
     uint8_t status = 0;
-    status         = FLASH_EraseSector(fmc_get_flash_sector(erase_addr), VoltageRange_3);
-    if (status != FLASH_COMPLETE)
+    uint8_t i = 0, j = 0;
+    for (i = 0; i < len; i++)
     {
-        return 1;
+        status = FLASH_EraseSector(fmc_get_flash_sector(erase_addr), VoltageRange_3);
+        if (status != FLASH_COMPLETE)
+        {
+            return 1;
+        }
+        if ((erase_addr >= ADDR_FLASH_SECTOR_0) && (erase_addr < ADDR_FLASH_SECTOR_4))
+        {
+            erase_addr += (i * FMC_PAGE_SIZE_16K);
+        }
+        else if ((erase_addr >= ADDR_FLASH_SECTOR_4) && (erase_addr < ADDR_FLASH_SECTOR_5))
+        {
+            erase_addr += (i * FMC_PAGE_SIZE_64K);
+        }
+        else if ((erase_addr >= ADDR_FLASH_SECTOR_4) && (erase_addr < ADDR_FLASH_SECTOR_END))
+        {
+            erase_addr += (i * FMC_PAGE_SIZE_128K);
+        }
+        else
+        {
+            return 0;
+        }
     }
     return 0;
+
+    // uint8_t status = 0;
+    // status         = FLASH_EraseSector(fmc_get_flash_sector(erase_addr), VoltageRange_3);
+    // if (status != FLASH_COMPLETE)
+    // {
+    //     return 1;
+    // }
+    // return 0;
     // uint16_t i = 0, j = 0;
 
     // uint32_t *addr = (uint32_t *)erase_addr;

+ 5 - 0
driver/flash/drv_flash.h

@@ -34,6 +34,11 @@ extern 'C'
 #define FMC_PAGE_SIZE_U16 ((uint16_t)0x400)
 #define FMC_FLASH_BASE    ((uint32_t)0x08000000)
 
+#define FMC_PAGE_SIZE_16K  ((uint32_t)0x4000)
+#define FMC_PAGE_SIZE_32K  ((uint32_t)0x8000)
+#define FMC_PAGE_SIZE_64K  ((uint32_t)0x10000)
+#define FMC_PAGE_SIZE_128K ((uint32_t)0x20000)
+
 // FLASH 扇区的起始地址
 #define ADDR_FLASH_SECTOR_0   ((u32)0x08000000) // 扇区0起始地址, 16 Kbytes
 #define ADDR_FLASH_SECTOR_1   ((u32)0x08004000) // 扇区1起始地址, 16 Kbytes