Franike 4 ماه پیش
والد
کامیت
4b45c337c2

+ 60 - 0
App/BootLoader/Inc/boot.h

@@ -0,0 +1,60 @@
+
+#ifndef __BOOT_H
+#define __BOOT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __BOOT_H_GLOBAL
+#define __BOOT_H_EXTERN
+#else
+#define __BOOT_H_EXTERN extern
+#endif
+
+/************************************************************************************************
+ *                                          Version                                             *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          How to use                                          *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Enable config                                        *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Includes                                            *
+ ************************************************************************************************/
+
+#include <stdint.h>
+
+/************************************************************************************************
+ *                                          Defines                                              *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Typedefs                                            *
+ ************************************************************************************************/
+
+typedef enum
+{
+    INVALID = 0,
+    VALID   = !INVALID
+} validity_status;
+
+typedef void (*pFunction)(void);
+
+/************************************************************************************************
+ *                                          Interfaces                                          *
+ ************************************************************************************************/
+
+void    run_app(void);
+uint8_t check_addr_sp(uint32_t addr);
+uint8_t check_addr_pc(uint32_t addr);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __BOOT_H

+ 62 - 0
App/BootLoader/Inc/flash.h

@@ -0,0 +1,62 @@
+#ifndef __DRV_FLASH_H
+#define __DRV_FLASH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __DRV_FLASH_H_GLOBAL
+#define __DRV_FLASH_H_EXTERN
+#else
+#define __DRV_FLASH_H_EXTERN extern
+#endif
+
+/************************************************************************************************
+ *                                          Version                                              *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          How to use                                           *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Enable config                                         *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Includes                                             *
+ ************************************************************************************************/
+
+#include <stdint.h>
+
+/************************************************************************************************
+ *                                          Defines                                              *
+ ************************************************************************************************/
+
+#define FMC_PAGE_SIZE     ((uint16_t)0x800)
+#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)
+
+/************************************************************************************************
+ *                                          Defines *
+ ************************************************************************************************/
+
+void     fmc_clear_flag_star(void);
+void     fmc_clear_flag_end(void);
+uint8_t  fmc_read_byte(uint32_t read_addr);
+uint16_t fmc_read_half_word(uint32_t read_addr);
+uint8_t  fmc_read_n_half_word(uint32_t read_addr, uint16_t *buff, uint16_t count);
+uint8_t  fmc_read_one_page(uint32_t read_addr, uint16_t *buff);
+uint8_t  fmc_erase_pages(uint32_t erase_addr, uint16_t len);
+uint8_t  fmc_write_n_half_word(uint32_t write_addr, uint16_t *buff, uint16_t len);
+uint16_t firmware_crc16_ccitt_false(uint16_t init_value, uint8_t *pbuff, uint32_t len);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __DRV_FLASH_H

+ 120 - 0
App/BootLoader/Inc/iap.h

@@ -0,0 +1,120 @@
+#ifndef __DEV_IAP_H
+#define __DEV_IAP_H
+
+#include "can_interface.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __DEV_IAP_H_GLOBAL
+#define __DEV_IAP_H_EXTERN
+#else
+#define __DEV_IAP_H_EXTERN extern
+#endif
+
+/************************************************************************************************
+ *                                          Version                                              *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          How to use                                           *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Enable config                                         *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Includes                                             *
+ ************************************************************************************************/
+
+#include "can_interface.h"
+#include <stdint.h>
+
+/************************************************************************************************
+ *                                          Defines *
+ ************************************************************************************************/
+
+#define UPGRADE_FLAG_DATA_SIZE 4 // 升级参数数组元素个数
+#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)0x08004000)
+#define APP_END_ADDR   ((uint32_t)0x0801D000)
+
+#define UPGRADE_FLAG_START_ADDR ((uint32_t)0x0801D000)
+#define UPGRADE_FLAG_END_ADDR   ((uint32_t)0x08027000)
+
+#define DOWNLOAD_START_ADDR  ((uint32_t)0x08027000)
+#define DOWNLOAD_END_ADDR    ((uint32_t)0x08040000)
+#define DOWNLOAD_MIDDLE_ADDR ((uint32_t)0x08033800)
+
+// 升级命令
+#define IAP_CMD_VERSION    0x71   // 查询版本号
+#define IAP_CMD_INFO       0x72   // 包信息
+#define IAP_CMD_ERASE      0x73   // 擦除命令
+#define IAP_CMD_DATA       0x80   // 数据帧 IAP_CMD_DATA |帧号
+#define IAP_CMD_CRC        0x74   // 传输结果校验
+#define IAP_CMD_JUMP       0x75   // 执行跳转
+#define IAP_CMD_JUMP_OVER  0x0175 // 执行跳转
+#define IAP_CMD_MODEL_TYPE 0x76   // 执行跳转
+
+#define UPGRADE_SIGN 0x5AA5
+#define DEVICE_ID    0x5AA5
+
+typedef union
+{
+    uint16_t u8_buf[8];
+    uint16_t u16_buf[4];
+} u16_u8;
+
+typedef union
+{
+    uint16_t u8_save[200];
+    uint16_t u16_save[100];
+} u16save_u8save;
+
+typedef struct
+{
+    uint16_t       total_packages;
+    uint16_t       current_packages;
+    uint16_t       count_packages;
+    uint16_t       recv_len;
+    uint16_t       crc16;
+    uint16_t       firmware_crc16;
+    uint16_t       firmware_ver;
+    uint16_t       total_bytes;
+    uint16_t       count_bytes;
+    u16_u8         flash_data;
+    u16_u8         recheck_data;
+    u16save_u8save save_data;
+} iap_type;
+
+typedef union
+{
+    struct
+    {
+        uint16_t sign;        // 首地址 buf[0]
+        uint16_t crc16;       // 中地址 buf[1]
+        uint32_t moving_size; // 高地址 buf[2] buf[3]
+    } param;
+    uint16_t infor_buf[UPGRADE_FLAG_DATA_SIZE];
+} upgrade_param; // 升级参数使用
+
+extern upgrade_param upgrade;
+
+void    set_firmver(void);
+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);
+
+/************************************************************************************************
+ *                                          Defines                                              *
+ ************************************************************************************************/
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __DEV_IAP_H

+ 49 - 0
App/BootLoader/Src/boot.c

@@ -0,0 +1,49 @@
+#include "boot.h"
+#include "iap.h"
+#include <stdint.h>
+
+void run_app(void)
+{
+    pFunction     Jump_To_Application;
+    __IO uint32_t JumpAddress;
+
+    // CAN_DeInit(CAN1);
+
+    if (((*(__IO uint32_t *)APP_START_ADDR) & 0x2FFE0000) == 0x20000000)
+    {
+        JumpAddress         = *(__IO uint32_t *)(APP_START_ADDR + 4);
+        Jump_To_Application = (pFunction)JumpAddress;
+        __set_MSP(*(__IO uint32_t *)APP_START_ADDR);
+        Jump_To_Application();
+    }
+}
+
+uint8_t check_addr_sp(uint32_t addr)
+{
+    int ret;
+
+    if (((*(uint32_t *)addr) & 0x2FFE0000) == 0x20000000) // 检查栈顶地址是否合法
+    {
+        ret = VALID;
+    }
+    else
+    {
+        ret = INVALID;
+    }
+    return ret;
+}
+
+uint8_t check_addr_pc(uint32_t addr)
+{
+    int ret;
+
+    if (((*(uint32_t *)(addr + 4)) & 0xFF000000) == 0x08000000) // 检查中断向量表地址是否合法
+    {
+        ret = VALID;
+    }
+    else
+    {
+        ret = INVALID;
+    }
+    return ret;
+}

+ 158 - 0
App/BootLoader/Src/flash.c

@@ -0,0 +1,158 @@
+/************************************************************************************************
+ *                                          Include                                              *
+ ************************************************************************************************/
+
+#include "flash.h"
+#include "stm32f1xx_hal.h"
+#include <stdint.h>
+
+/************************************************************************************************
+ *                                          Config                                                *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Data structs                                         *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          implements                                           *
+ ************************************************************************************************/
+FLASH_ProcessTypeDef p_flash;
+
+// 解除写保护,清除fmc特定寄存器
+void fmc_clear_flag_star(void)
+{
+    HAL_FLASH_Unlock();    // 解锁
+    HAL_FLASH_OB_Unlock(); // FLASH擦除期间,必须禁止数据缓存
+    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
+}
+
+// 设置写保护,清除fmc特定寄存器
+void fmc_clear_flag_end(void)
+{
+    HAL_FLASH_OB_Lock(); // FLASH擦除结束,开启数据缓存
+    HAL_FLASH_Lock();    // 上锁
+}
+
+// 读取一字节, 读取无需考虑字节对齐
+uint8_t fmc_read_byte(uint32_t read_addr)
+{
+    return *(__IO uint8_t *)read_addr;
+}
+
+// 读取两字节, 读取需考虑字节对齐
+uint16_t fmc_read_half_word(uint32_t read_addr)
+{
+    return *(__IO uint16_t *)read_addr;
+}
+
+// 读取N字节, 读取必须需考虑字节对齐
+uint8_t fmc_read_n_half_word(uint32_t read_addr, uint16_t *buff, uint16_t count)
+{
+    uint16_t i = 0;
+
+    __IO uint16_t *addr = (__IO uint16_t *)read_addr;
+
+    if (read_addr % 2 != 0)
+        return 1; // 错误返回
+
+    for (i = 0; i < count; i++)
+    {
+        *buff++ = *addr++;
+    }
+    return 0;
+}
+
+// 读取1页, 地址必须对齐页首
+uint8_t fmc_read_one_page(uint32_t read_addr, uint16_t *buff)
+{
+    uint16_t i = 0;
+
+    __IO uint16_t *addr = (__IO uint16_t *)read_addr;
+
+    if (read_addr % FMC_PAGE_SIZE != 0)
+        return 1; // 错误返回
+
+    for (i = 0; i < 1024; i++)
+    {
+        *buff++ = *addr++;
+    }
+    return 0;
+}
+
+// 擦出N页, 地址必须对齐页首
+uint8_t fmc_erase_pages(uint32_t erase_addr, uint16_t len)
+{
+    uint16_t               i = 0, j = 0;
+    FLASH_EraseInitTypeDef p_erase_init;
+    uint32_t               page_error = 0;
+
+    p_erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
+    p_erase_init.Banks     = FLASH_BANK_1;
+    p_erase_init.NbPages   = 1;
+
+    uint32_t *addr = (uint32_t *)erase_addr;
+
+    if (erase_addr % FMC_PAGE_SIZE != 0)
+        return 1; // 错误返回
+
+    for (i = 0; i < len; i++)
+    {
+        p_erase_init.PageAddress = erase_addr + FMC_PAGE_SIZE * i;
+
+        if (HAL_FLASHEx_Erase(&p_erase_init, &page_error) != HAL_OK)
+            return 1;
+
+        for (j = 0; j < 512; j++)
+        {
+            if (*addr != 0xFFFFFFFF)
+                return 1;
+            else
+                addr++;
+        }
+    }
+    return 0;
+}
+
+// 只写入,写入前需擦除,地址必须两字节对齐
+uint8_t fmc_write_n_half_word(uint32_t write_addr, uint16_t *buff, uint16_t len)
+{
+
+    uint32_t end_addr = write_addr + len * 2;
+
+    if (write_addr % 2 != 0)
+        return 1;
+
+    while (write_addr < end_addr)
+    {
+
+        HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, write_addr, *buff); // 写入数据
+        if (*(__IO uint16_t *)write_addr != *buff)
+        {
+            return 1;
+        }
+        write_addr += 2;
+        buff++;
+    }
+    return 0;
+}
+
+uint16_t firmware_crc16_ccitt_false(uint16_t init_value, uint8_t *pbuff, uint32_t len)
+{
+    uint16_t temp = 0;
+    uint16_t crc  = init_value;
+
+    for (uint32_t i = 0; i < len; i++)
+    {
+        for (uint32_t j = 0; j < 8; j++)
+        {
+            temp = ((pbuff[i] << j) & 0x80) ^ ((crc & 0x8000) >> 8);
+            crc <<= 1;
+            if (temp != 0)
+            {
+                crc ^= 0x1021;
+            }
+        }
+    }
+    return crc;
+}

+ 286 - 0
App/BootLoader/Src/iap.c

@@ -0,0 +1,286 @@
+/************************************************************************************************
+ *                                          Include                                              *
+ ************************************************************************************************/
+
+#include "iap.h"
+#include "can_task.h"
+#include "flash.h"
+#include <stdint.h>
+#include <string.h>
+
+/************************************************************************************************
+ *                                          Config                                                *
+ ************************************************************************************************/
+extern uint8_t jump_flag;
+uint8_t        can_rx_flag;
+// extern can_receive_message receive_iap_message;
+static uint16_t jump_boot_time = 0;
+uint8_t         send_buff[8]   = {0, 0, 0, 0, 0, 0, 0, 0};
+unsigned char   recv_crc[2];
+unsigned char   recvdata_ema[204];
+unsigned char   recvdata_buffer[210];
+
+uint16_t firm_ver[UPGRADE_APP_DATA_SIZE]       = {IAP_CMD_JUMP_OVER};
+uint16_t firm_ver_buff[UPGRADE_BUFF_DATA_SIZE] = {0};
+uint8_t  iap_disconnect_count                  = 0;
+/************************************************************************************************
+ *                                          Data structs                                         *
+ ************************************************************************************************/
+iap_type      g_iap;
+upgrade_param upgrade;
+/************************************************************************************************
+ *                                          implements                                           *
+ ************************************************************************************************/
+void invert_uint8()
+{
+}
+
+void iap_connect_clear(void)
+{
+    iap_disconnect_count = 0;
+    send_buff[0]         = 0x00;
+    send_buff[1]         = 0x00;
+    send_buff[2]         = 0x00;
+    send_buff[3]         = 0x00;
+    send_buff[4]         = 0x00;
+    send_buff[5]         = 0x00;
+    send_buff[6]         = 0x00;
+    send_buff[7]         = 0x00;
+}
+
+void iap_disconnect_check(void)
+{
+    if (++iap_disconnect_count >= 5)
+    {
+        iap_disconnect_count = 5;
+    }
+}
+
+// iap相关参数初始化
+void iap_param_init(void)
+{
+    g_iap.recv_len         = 0;
+    g_iap.total_packages   = 0;
+    g_iap.current_packages = 0;
+    g_iap.crc16            = 0xFFFF;
+    g_iap.total_bytes      = 0;
+    g_iap.count_bytes      = 0;
+    g_iap.count_packages   = 0;
+    g_iap.firmware_crc16   = 0;
+    g_iap.firmware_ver     = 0;
+}
+
+// 清除升级信息标志位
+void set_firmver(void)
+{
+    fmc_clear_flag_star();
+    fmc_read_n_half_word(UPGRADE_FLAG_START_ADDR, firm_ver_buff, UPGRADE_BUFF_DATA_SIZE);
+    fmc_erase_pages(UPGRADE_FLAG_START_ADDR, 1);
+
+    fmc_write_n_half_word(UPGRADE_FLAG_START_ADDR, firm_ver_buff, UPGRADE_BUFF_DATA_SIZE);
+    fmc_clear_flag_end();
+}
+
+void iap_flag_release(void)
+{
+    fmc_read_n_half_word(UPGRADE_FLAG_START_ADDR, upgrade.infor_buf, UPGRADE_FLAG_DATA_SIZE);
+
+    if (upgrade.param.sign == UPGRADE_SIGN)
+    {
+        fmc_clear_flag_star();
+        fmc_erase_pages(UPGRADE_FLAG_START_ADDR, 1);
+        fmc_write_n_half_word(UPGRADE_FLAG_START_ADDR + (UPGRADE_FLAG_DATA_SIZE * 2), firm_ver,
+                              UPGRADE_APP_DATA_SIZE);
+        fmc_clear_flag_end();
+        for (uint8_t i = 0; i < (UPGRADE_APP_DATA_SIZE * 2); i++)
+        {
+            send_buff[i] =
+                fmc_read_byte(UPGRADE_FLAG_START_ADDR + (UPGRADE_FLAG_DATA_SIZE * 2) + i);
+        }
+        CAN_IT_TME_ENABLE();
+    }
+}
+
+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);
+    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;
+
+    w_start_addr = pack_num * 6 + APP_START_ADDR;
+    fmc_write_n_half_word(w_start_addr, buf, pack_len);
+}
+
+void read_app_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num)
+{
+    static uint32_t w_start_addr = 0;
+
+    w_start_addr = pack_num * 6 + APP_START_ADDR;
+    fmc_read_n_half_word(w_start_addr, buf, pack_len);
+}
+
+uint8_t write_download_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num)
+{
+    uint8_t         status       = 0;
+    static uint32_t w_start_addr = 0;
+
+    w_start_addr = pack_num * 6 + DOWNLOAD_START_ADDR;
+    status       = fmc_write_n_half_word(w_start_addr, buf, pack_len);
+    return status;
+}
+
+void read_download_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num)
+{
+    static uint32_t w_start_addr = 0;
+
+    w_start_addr = pack_num * 6 + DOWNLOAD_START_ADDR;
+    fmc_read_n_half_word(w_start_addr, buf, pack_len);
+}
+
+void iap_rec_handler(pdu_tag rec_msg)
+{
+    uint8_t erase_flag = 0x01;
+
+    // ota_can_id = rec_msg.id.r;
+    if (rec_msg.data.u8_buf[0] != IAP_CMD_VERSION)
+        iap_connect_clear();
+
+    if (rec_msg.data.u8_buf[0] >> 7)
+    {
+        if (rec_msg.id.b.sa == 0xE1)
+        {
+            g_iap.recv_len = rec_msg.reg.dlc - 2;
+            g_iap.current_packages =
+                ((uint16_t)(rec_msg.data.u8_buf[0] & 0x7F) << 8) | rec_msg.data.u8_buf[1];
+            memcpy(g_iap.flash_data.u8_buf, &rec_msg.data.u8_buf[2], g_iap.recv_len);
+
+            if ((g_iap.count_packages == g_iap.current_packages) &&
+                (g_iap.current_packages < g_iap.total_packages))
+            {
+                g_iap.count_bytes += g_iap.recv_len;
+
+                if ((g_iap.recv_len % 2) != 0)
+                {
+                    g_iap.flash_data.u8_buf[g_iap.recv_len] = 0xFF;
+                    g_iap.recv_len++;
+                }
+
+                fmc_clear_flag_star();
+                erase_flag = write_download_flash(g_iap.flash_data.u16_buf, g_iap.recv_len / 2,
+                                                  g_iap.count_packages);
+                fmc_clear_flag_end();
+
+                g_iap.crc16 = firmware_crc16_ccitt_false(g_iap.crc16, g_iap.flash_data.u8_buf,
+                                                         g_iap.recv_len);
+
+                send_buff[0] = IAP_CMD_DATA;
+                send_buff[1] = !erase_flag;
+                g_iap.count_packages++;
+            }
+            else
+            {
+                send_buff[0] = IAP_CMD_DATA;
+                send_buff[1] = 0x06;
+            }
+
+            send_buff[2] = rec_msg.data.u8_buf[0] & 0x7F;
+            send_buff[3] = rec_msg.data.u8_buf[1];
+
+            send_buff[4] = g_iap.count_packages >> 8;
+            send_buff[5] = g_iap.count_packages & 0xFF;
+        }
+    }
+    else
+    {
+        switch (rec_msg.data.u8_buf[0])
+        {
+        case IAP_CMD_VERSION:
+            iap_param_init();
+            for (uint8_t i = 0; i < (UPGRADE_APP_DATA_SIZE * 2); i++)
+            {
+                send_buff[i] =
+                    fmc_read_byte(UPGRADE_FLAG_START_ADDR + (UPGRADE_FLAG_DATA_SIZE * 2) + i);
+            }
+
+            send_buff[0] = IAP_CMD_VERSION;
+            send_buff[1] = 0x01;
+            break;
+        case IAP_CMD_INFO:
+            g_iap.total_bytes = (uint16_t)rec_msg.data.u8_buf[1] << 8 | rec_msg.data.u8_buf[2];
+            g_iap.total_bytes <<= 16;
+            g_iap.total_bytes |= (uint16_t)rec_msg.data.u8_buf[3] << 8 | rec_msg.data.u8_buf[4];
+            g_iap.total_packages = (uint16_t)rec_msg.data.u8_buf[5] << 8 | rec_msg.data.u8_buf[6];
+            send_buff[0]         = IAP_CMD_INFO;
+            send_buff[1]         = 0x01;
+            break;
+        case IAP_CMD_ERASE:
+            g_iap.firmware_crc16 = (uint16_t)rec_msg.data.u8_buf[2] << 8 | rec_msg.data.u8_buf[3];
+            if (rec_msg.data.u8_buf[1])
+            {
+                // 喂狗
+                fmc_clear_flag_star();
+                erase_flag = erase_app_flash(DOWNLOAD_START_ADDR, DOWNLOAD_END_ADDR);
+                fmc_clear_flag_end();
+                // 喂狗
+                g_iap.count_bytes    = 0;
+                g_iap.count_packages = 0;
+            }
+            send_buff[0] = IAP_CMD_ERASE;
+            send_buff[1] = !erase_flag;
+            break;
+        case IAP_CMD_CRC:
+            send_buff[0] = IAP_CMD_CRC;
+            send_buff[1] = (g_iap.crc16 == g_iap.firmware_crc16 ? 1 : 0);
+            break;
+        case IAP_CMD_JUMP:
+            if (g_iap.crc16 != g_iap.firmware_crc16)
+            {
+                send_buff[1] = 0x00;
+            }
+            else
+            {
+                fmc_clear_flag_star();
+                fmc_erase_pages(UPGRADE_FLAG_START_ADDR, 1);
+                upgrade.param.sign        = UPGRADE_SIGN;
+                upgrade.param.crc16       = g_iap.crc16;
+                upgrade.param.moving_size = g_iap.total_bytes;
+                fmc_write_n_half_word(UPGRADE_FLAG_START_ADDR, upgrade.infor_buf,
+                                      UPGRADE_FLAG_DATA_SIZE);
+                fmc_clear_flag_end();
+                jump_boot_time = 10;
+                send_buff[1]   = 0x01;
+            }
+            send_buff[0] = IAP_CMD_JUMP;
+            break;
+        case IAP_CMD_MODEL_TYPE:
+            send_buff[0] = IAP_CMD_MODEL_TYPE;
+            send_buff[1] = 0x01;
+
+            send_buff[2] = DEVICE_ID >> 8;
+            send_buff[3] = DEVICE_ID & 0xFF;
+        }
+    }
+
+    push_can_message_to_queue(0x18DFE1F4, 8, send_buff);
+}

+ 2 - 1
App/Can/Src/can_task.c

@@ -1,6 +1,7 @@
 #include "can_task.h"
 #include "can_interface.h"
 #include "hal_math.h"
+#include "iap.h"
 #include "queue.h"
 #include "utils.h"
 #include <stdint.h>
@@ -157,7 +158,7 @@ void can_rx_update(pdu_tag rec_msg)
     }
 }
 
-can_rx_tab can_tab[] = {{0x18011801, can_rx_update}};
+can_rx_tab can_tab[] = {{0x18DFF4E1, iap_rec_handler}};
 
 void can_start_send(void)
 {

+ 19 - 0
CMakeLists.txt

@@ -48,6 +48,9 @@ target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE
 # Add sources to executable
 target_sources(${CMAKE_PROJECT_NAME} PRIVATE
     # Add user sources here
+    App/BootLoader/Src/boot.c
+    App/BootLoader/Src/flash.c
+    App/BootLoader/Src/iap.c
     App/Can/Src/can_task.c
     App/Can/Src/can_interface.c
     App/Common/Src/hal_math.c
@@ -61,6 +64,7 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE
 # Add include paths
 target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
     # Add user defined include paths
+    App/BootLoader/Inc
     App/Common/Inc
     App/Can/Inc
     App/Task/Inc
@@ -78,3 +82,18 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
 
     # Add user defined libraries
 )
+
+# post-build
+add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
+        COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
+        )
+
+# 生成 hex 文件
+add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
+        COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${CMAKE_PROJECT_NAME}.hex
+        )
+
+# 生成 bin 文件
+add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
+        COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${CMAKE_PROJECT_NAME}.bin
+        )

+ 20 - 2
Core/Src/main.c

@@ -23,11 +23,12 @@
 #include "usart.h"
 #include "usb_device.h"
 
-
 /* Private includes ----------------------------------------------------------*/
 /* USER CODE BEGIN Includes */
 #include "can_task.h"
+#include "iap.h"
 #include "schedule.h"
+
 /* USER CODE END Includes */
 
 /* Private typedef -----------------------------------------------------------*/
@@ -59,7 +60,18 @@ void SystemClock_Config(void);
 
 /* Private user code ---------------------------------------------------------*/
 /* USER CODE BEGIN 0 */
+#define NVIC_VectTab_FLASH (uint32_t)0x8000000 // stm32的flash起始地址
+#define APP_FLASH_OFFSET   0x4000
+#define BOOT_EN            1
+
+// 重设中断向量表
+void NVIC_SetVectorTable(uint32_t NVIC_VecTab, uint32_t OffSet)
+{
+    assert_param(IS_NVIC_VECTAB(NVIC_VecTab));
+    assert_param(IS_NVIC_OFFSET(OffSet));
 
+    SCB->VTOR = NVIC_VecTab | (OffSet & (uint32_t)0x1FFFFF80);
+}
 /* USER CODE END 0 */
 
 /**
@@ -70,7 +82,10 @@ int main(void)
 {
 
     /* USER CODE BEGIN 1 */
-
+#if (BOOT_EN == 1)
+    NVIC_SetVectorTable(NVIC_VectTab_FLASH, APP_FLASH_OFFSET);
+    __set_PRIMASK(0);
+#endif
     /* USER CODE END 1 */
 
     /* MCU Configuration--------------------------------------------------------*/
@@ -99,6 +114,9 @@ int main(void)
     /* USER CODE BEGIN 2 */
     can_network_init();
     LL_USART_EnableIT_RXNE(USART1);
+    set_firmver();
+    iap_flag_release();
+    iap_param_init();
     schedule_init(TASK_PERIOD);
     /* USER CODE END 2 */
 

+ 1 - 1
STM32F103RCTx_FLASH.ld

@@ -62,7 +62,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */
 MEMORY
 {
 RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 48K
-FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 256K
+FLASH (rx)      : ORIGIN = 0x8004000, LENGTH = 240K
 }
 
 /* Define output sections */