发新帖我要提问
12
返回列表
打印
[其他]

STM32/GD32 IAP/Bootloader升级APP

[复制链接]
手机看帖
扫描二维码
随时随地手机跟帖
21
铁血丹心LLLL|  楼主 | 2022-11-23 15:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
跳转前关闭中断,防止 1)已经跳转到APP了但来了一个中断并落在了Bootloader, 2)中断向量表已偏移但来了中断,就会落在错误的地方

使用特权

评论回复
22
铁血丹心LLLL|  楼主 | 2022-11-23 15:37 | 只看该作者
需要特别注意的是,如果使能了Systick等内核级别的中断,用__disable_irq(); 之类的屏蔽中断的语句是无法关闭的,需要去停止Systick的运行。最优的是在bootloader跳转前关闭所有用到的资源以及中断,在APP中重新配置所需要的,以免在Bootloader中用到的中断在APP中没有用到,而缺少对应的中断处理导致中断死循环或HardFault。APP跳转Bootloader亦应如此。

使用特权

评论回复
23
铁血丹心LLLL|  楼主 | 2022-11-23 15:38 | 只看该作者
Bootloader升级APP

从串口接收到hex文件的一行,校验后调用以下函数写入FLASH。以下是简单的一个写入流程
@ CSDN Tyrion.Mon
void UpgradeAPP(xxx)
{
        uint16_t i = 0;
    uint16_t line_data_len = xxx;        //数据域长度
    static uint32_t base_addr = 0;       
    uint32_t offset_addr = 0x0000ffff & xxx;        //偏移地址
    uint32_t write_addr = 0;
    static uint32_t has_erase_page = 0;
    uint32_t need_erase_page = 0;
    static bool APP_StartAddr_OK = false;
        uint8_t line_type = xxx;
       
    switch (line_type)        //行数据类型
    {
    case 4: //指定基地址
        base_addr = xxx;
        base_addr = (base_addr << 16) & 0xffff0000;
        【解锁FLASH】
        break;
    case 0: //写入Flash的数据
        write_addr = base_addr | offset_addr;

        if (APP_StartAddr_OK == false && ((APP_LOADED_ADDR + 0x08000000) == write_addr))
        {
            APP_StartAddr_OK = true;    //APP Flash首地址正确
        }
        if (APP_StartAddr_OK == true)
        {
            for (i = 0; i < line_data_len; i += 4)
            {
                need_erase_page = ((write_addr + i) - 0x08000000) / 2048;        //算出当前地址所在页,2K每页

                if (need_erase_page != has_erase_page)
                {
                    has_erase_page = need_erase_page;
                    【擦除该页】
                }
               
                【向指定地址以整字方式写入FLASH,或者接收到一页的量后采用页编程方式写入】
                【读出对比】
                printf("%x, ", *((volatile uint32_t *)(write_addr + i)));
            }
            printf("\r\n");
        }
        break;
        case 1: //文件结束
            【FLASH上锁】
        break;
    default:
        break;
    }
}

使用特权

评论回复
24
铁血丹心LLLL|  楼主 | 2022-11-23 15:38 | 只看该作者
跳转APP后的处理
/* 基地址 */
#define NVIC_VECTTAB_RAM            ((uint32_t)0x20000000) /*!< RAM */
#define NVIC_VECTTAB_FLASH          ((uint32_t)0x08000000) /*!< Flash */

/* NVIC中断向量表偏移掩码 */
#define NVIC_VECTTAB_OFFSET_MASK    ((uint32_t)0x1FFFFF80)

#define USER_BOOT_EXIST                                                1                        //是否有bootloader
#define VECT_TAB_OFFSET                                                0x5000                //

#if (USER_BOOT_EXIST == 1)
        /* APP中断向量表地址偏移 需要在Linker选项卡勾选“USE Memory Layout from Target Dialog”,并修改Target选项卡中的ROM的Start地址 */
        nvic_vector_table_set(NVIC_VECTTAB_FLASH, VECT_TAB_OFFSET);
        __enable_irq();        //解除中断屏蔽
#endif
@ CSDN Tyrion.Mon
void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset)
{
    SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK);
}

使用特权

评论回复
25
铁血丹心LLLL|  楼主 | 2022-11-23 15:39 | 只看该作者
如果在Bootloader跳转APP前就设置了中断向量偏移,则略过。

使用特权

评论回复
26
铁血丹心LLLL|  楼主 | 2022-11-23 15:39 | 只看该作者
NVIC_VECTTAB_OFFSET_MASK掩码为0x1FFFFF80是因为VTOR寄存器的格式

使用特权

评论回复
27
铁血丹心LLLL|  楼主 | 2022-11-23 15:40 | 只看该作者
APP地址偏移不能随意,CortexM3 M4权威指南中有如下描述。且还要关注该型号单片机的Flash每页大小,因为写Flash时需要整页擦除,须避免APP和Bootloader代码在同一页。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则