gcc编译hal库方式实现M0系列芯片IAP升级

gcc编译hal库方式实现M0系列芯片IAP
IAP:调用iap_load_app函数即可,输入参数为app起始地址

void iap_load_app(uint32_t appxaddr)
{
    uint32_t sram_addr = 0;
    sram_addr = (*(__IO uint32_t *)appxaddr) & 0x2FFE0000;
    printf("sram_addr : %08lx\n", sram_addr);
    //APPLICATION_ADDRESS是在FLASH中存放APP的起始地址
    //此判断是为了保证APP的栈地址是在SRAM中。其实结果并不一定是0x20000000。有些APP可能定义的全局变量较多,那么栈的起始地址会偏移
    if (((*(__IO uint32_t *)appxaddr) & 0x2FFE0000) == 0x20000000)
    {
        /* Jump to user application */
        JumpAddress = *(__IO uint32_t *)(appxaddr + 4);
        printf("jump addr : %08lx\n", JumpAddress);
        Jump_To_Application = (pFunction)JumpAddress;
        /* Initialize user application's Stack Pointer */
        MSR_MSP(*(__IO uint32_t *)appxaddr);
        printf("appxaddr : %08lx\n", appxaddr);
        /*关闭或反初始化前面用到的外设和中断*/
        HAL_DeInit();
        Jump_To_Application();
    }
}

其中MSR_MSP()函数

void MSR_MSP(u32 addr)
{
    __ASM volatile("MSR MSP, r0");
    __ASM volatile("BX r14");
}

其中JumpAddress定义

typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;

APP:

void NVIC_SetVectorTable(void)
{
    uint8_t i;

    uint32_t *pVecTab = (uint32_t *)(0x20000000);
    //复制中断向量表到SRAM首地址
    for (i = 0; i < 48; i++)
    {
        *(pVecTab++) = *(__IO uint32_t *)(APPLICATION_ADDRESS + (i << 2));
    }
    //开启 SYSCFG 时钟
    __HAL_RCC_SYSCFG_CLK_ENABLE();
    //重映射 SRAM 地址到 0x00000000
    __HAL_SYSCFG_REMAPMEMORY_SRAM();
}

在mian()函数一开始调用NVIC_SetVectorTable()函数

int main(void)
{
    /* USER CODE BEGIN 1 */
    NVIC_SetVectorTable();

修改.ld文件,例如STM32F070RBTx_FLASH.ld
RAM修改为0x200000C0,flash修改为自己的起始地址

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x200000C0, LENGTH = 16K
FLASH (rx)      : ORIGIN = 0x8005000, LENGTH = 100K
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值