AT32F415的OTA升级

项目简介

在物联网应用开发过程中,不可避免的会需要用到软件升级,一般情况下,以AT32系列芯片为主控制器的设备在出厂时就已经使用J-Link仿真器将应用代码烧录了,如果在设备使用过程中需要进行应用代码的更换、升级等操作的话,则可能需要将设备返回原厂并拆解出来再使用J-Link重新烧录代码,这就增加了很多不必要的麻烦。站在公司的角度来说,就是能远程来更换设备里边的代码程序。IAP却能很好的解决掉这个难题。

IAP实现原理

一片ARM芯片的Code(代码)区内一般只有一个用户程序。而IAP方案则是将代码区划分为两部分,两部分区域各存放一个程序,一个叫bootloader(引导加载程序),另一个较user application(用户应用程序)。bootloader在出厂时就固定下来了,在需要变更user application时只需要通过触发bootloader对userapplication的擦除和重新写入即可完成用户应用的更换。如图所示
bootloader原理图
在程序执行初始进入bootloader,在bootloader里面检测条件是否被触发(串口是否接收到特定的数据),如果有则进行对user application进行擦除和重新写入操作,如果没有则直接跳转到user application执行应用;如果有则进行擦除用户代码并重新写入新的用户代码。

AT32中的内置FLASH分配情况

在这里插入图片描述
AT32程序启动顺序如下图所示
在这里插入图片描述

AT32中的实现过程

BootLoader流程图大致应该如下:

1、初始化时钟。
2、初始化中断向量表地址。
3、初始化串口。
4、检测串口是否收到0xab,是则执行步骤5,否则执行步骤9。
5、擦除用户程序(擦除0x08004000—0x0803ffff地址空间Flash)。
6、从串口读取新的用户代码数据,把代码写入用户程序空间。
7、检测串口数据接收完毕?是则执行步骤9,否则跳回步骤7。
8、用户程序更新完毕,等待重新上电或硬件复位。
9、跳转到用户程序(强制将PC指针跳转到0x08004000+4处)。

跳转到APP的程序代码

void jump_to_app(uint32_t address)
{
	uint32_t stkptr, jumpaddr;
	stkptr = *(uint32_t*)address;
	jumpaddr = *(uint32_t*)(address + sizeof(uint32_t));

	
	//中断失能,串口1为程序下载口,串口2为日志打印口
	nvic_irq_disable(USART1_IRQn);
	nvic_irq_disable(USART2_IRQn);
	__NVIC_ClearPendingIRQ(USART1_IRQn);
	__NVIC_ClearPendingIRQ(USART2_IRQn);

	//关闭串口外设时钟
	crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, FALSE);
	crm_periph_reset(CRM_USART1_PERIPH_RESET, TRUE);
	crm_periph_reset(CRM_USART1_PERIPH_RESET, FALSE);

	crm_periph_clock_enable(CRM_USART2_PERIPH_CLOCK, FALSE);
	crm_periph_reset(CRM_USART2_PERIPH_RESET, TRUE);
	crm_periph_reset(CRM_USART2_PERIPH_RESET, FALSE);
	
	//设置跳转地址
	__set_MSP(stkptr);
	//设置APP程序地址
	pftarget = (void (*)(void))jumpaddr;
	//执行APP程序
	pftarget();
}

删除APP区域的FLASH空间代码

void DelAppCodeArea(void)
{
    int page_index;
    //flash记得解锁,我在调试的时候忘记解锁,导致失败
    flash_unlock();
    for (page_index = 0; page_index <= FLASH_APP_PAGE_COUNT; page_index++)
    {
        flash_sector_erase(FLASH_APP_ADDRESS + page_index * PAGE_SIZE);
        wdt_counter_reload();
    }
    //操作完记得加锁
    flash_lock();
}

写APP的bin数据到FLASH空间代码

void writeToFlash(uint8_t *pdata, uint32_t len)
{
    flash_unlock();
    uint32_t remainLen, i;
    wdt_counter_reload();
    remainLen = PAGE_SIZE - codeCacheIndex; //  codeCache剩余空间

    // codeCache还剩空间
    if (remainLen > len)
    {
        memcpy(codeCache + codeCacheIndex, pdata, len);
        codeCacheIndex += len;
    }
    else
    {
        memcpy(codeCache + codeCacheIndex, pdata, remainLen); // codeCache已经满了,写入flash

        if (programPageSeq <= FLASH_APP_PAGE_COUNT)
        {
            flash_sector_erase(FLASH_APP_ADDRESS + programPageSeq * PAGE_SIZE);

            for (i = 0; i < PAGE_SIZE; i += 2)
            {
                flash_halfword_program(FLASH_APP_ADDRESS + programPageSeq * PAGE_SIZE + i, *(uint16_t *)(codeCache + i));
                wdt_counter_reload();
            }
            programPageSeq++;
        }
        codeCacheIndex = len - remainLen; // 剩余的data放入codeCache
        memset(codeCache, 0xff, PAGE_SIZE);
        if (codeCacheIndex)
            memcpy(codeCache, pdata + remainLen, codeCacheIndex);
    }
    flash_lock();
}

详细工程可以直接联系我获取。

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

q472599451

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值