stm32实现iap远程固件更新

简介: stm32实现iap远程固件更新

前提

想来做iap升级了,应该不是什么新手。

下面的程序需要用到一些简单的功能

串口收发数据

开关总中断

虽然本文标题是实现远程固件更新,但是具体远程方案本文不做详细说明,重点在于介绍mcu接收到新的固件后怎么保存更新,以及更新失败回滚等。下面简单说明一下远程的事情。

stm32的通信方式有串口,spi,iic,以及sdio等。也就是说我们的固件可以通过这些方式传输到mcu,不过普遍常用的是串口或者用sdio(外接sd卡)这两种方式。个人觉得用sd卡来回copy也不怎么方便。简单点还是再加一个串口网络模块,然后把固件存到服务器,经由串口网络模块透传到mcu。比如用http协议把固件发送下来。远程下载就这么简单一说。接下来重点分析更新的事情。

固件生成

远程更新使用的固件和我们平时烧录程序用的固件格式有点区别,我们需要用二进制格式(.bin)文件。生成方式以mdk为例介绍一下,只需要添加一条命令行。


在mdk工程配置选项选择User,这个页面是让我们添加自定义命令行的,我们要添加的命令添加到第三个选项,即在编译完成后执行。下面是命令内容,需要注意的是 bin前面两个-,app1.bin就是生成的固件,名字可以自定义,**.axf是你工程实际的.axf文件,路径要正确。不知道你的axf在那在output页面查看。

fromelf.exe --bin -o ../app1.bin ./**.axf

现在我们就可以生成bin文件了,但是还差一点步骤。

一般使用下mcu启动后会自动把0x0800 0000映射到地址0x0000 0000,然后取指令执行。但是现在我们程序可以理解成分成了两部分。


app就是我们实际实现各种功能的固件,BootLoader为控制更新的固件。可以看到加入iap升级功能后我们app的起始地址变了,所以对应工程也要做这部分修改



如图,我这里把地址偏移了0x20000,同时在Linker中把“Use Memory Layout from Target Dialog”勾选,让我们的修改生效。

如此设置以后就一些ok了


图中上半部分是起始地址为0x800 0000 下半部分为起始地址0x802 0000,可以看到复位中断地址,以及下面一系列入口地址都相应变化了。

关于固件有一点需要注意,因为起始地址修改了,所以导致我们的中断向量表也整体偏移了,所以需要在app程序起始添加一行代码,本文是偏移0x20000,根据实际使用做相应改动

NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x2000);

固件保存

下载到板子的方式自选,下到板子后,我们需要把固件保存到内置flash对应的地址,

int writeToFlash(unsigned char *data, unsigned int len,unsigned int baseAddress )

{

unsigned char i = 0;

unsigned char pageNum = 0;

FLASH_Status FLASHStatus;

pageNum = len/FLASH_PAGE_SIZE+1;//求出总页数

FLASH_Unlock();

FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);

for (i=0; i < pageNum; i++)

{

FLASHStatus = FLASH_ErasePage(baseAddress + FLASH_PAGE_SIZE*i);

if (FLASHStatus != FLASH_COMPLETE)

{

FLASH_Lock();

return -1;

}

}

pageNum = (len+1)>> 1;

for (i=0; i < pageNum; i++)

{

FLASHStatus = FLASH_ProgramHalfWord(baseAddress+i*2, *((unsigned short*)data+i));

if (FLASHStatus != FLASH_COMPLETE)

{

FLASH_Lock();

return -1;

}

}

FLASH_Lock();

return 0;

}


本文上面设置的偏移是0x2 0000,所以此处写入flash的地址也必须是0x802 0000(0x800 0000 + 0x2 0000)

除了写入外,还应该加一些必要的文件完整性检查,比如使用校验等方式,这部分自行处理。然后在flash特定区域立一个flag,通知BootLoader程序更新固件。

固件更新

现在万事具备了,接下来就是更新的事情了,先简单说一下更新的思路。上电启动后运行BootLoader程序,在bootloader中检查是否是否需要更新,不需要的话就引导之前的app程序运行,需要更新就引导新的app程序。引导步骤大体就是重置栈顶指针,强制跳转app的reset复位中断。

#define APPLICATION_ADDRESS 0x08020000

typedef void (*pFunction)(void);

int main(void)

{

SystemInit();

BootLoad_Jump();

}

__asm void MSR_MSP(u32 addr) //设置堆栈指针

{

MSR MSP, r0

BX r14

}

void BootLoad_Jump(void)

{

u32 JumpAddress;

pFunction Jump_To_Application;

/* Check Vector Table: Test if user code is programmed starting from address

"APPLICATION_ADDRESS" */

//d_printfhex32((*(__IO uint32_t*)APPLICATION_ADDRESS));d_printf("\n");

if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)

{

__disable_irq();

JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS +4);

//d_printfhex32(JumpAddress);d_printf("\n");

Delay(100);

Jump_To_Application = (pFunction) JumpAddress;

/* Initialize user application's Stack Pointer */

MSR_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);

Jump_To_Application();

}

}

相关文章
|
3月前
|
芯片 存储 C语言
STM32F103标准外设库——固件库 (三)
STM32F103标准外设库——固件库 (三)
69 0
STM32F103标准外设库——固件库 (三)
No.0 个人与固件库工程文件分析 结构(STM32F429/F767/H743)
No.0 个人与固件库工程文件分析 结构(STM32F429/F767/H743)
|
7月前
|
存储 物联网 芯片
STM32速成笔记(十四)—串口IAP
本文介绍了什么是IAP,IAP有什么作用,如何实现IAP。最后,给出了IAP的实现程序。
115 0
STM32速成笔记(十四)—串口IAP
|
8月前
|
存储 Linux C语言
stm32cubeMX学习、USB DFU(Download Firmware Update)固件更新
stm32cubeMX学习、USB DFU(Download Firmware Update)固件更新
366 1
|
9月前
|
芯片
No.2 STM32F429IGT6 固件库 CMSIS标准及库和STM32官方文档资料总结 (STM32F429/F767/H743)
No.2 STM32F429IGT6 固件库 CMSIS标准及库和STM32官方文档资料总结 (STM32F429/F767/H743)
|
11月前
|
芯片 内存技术
STM32串口IAP实验笔记
STM32串口IAP实验笔记
149 0
|
12月前
STM32的串口固件库编程归纳
STM32的串口固件库编程归纳
56 0
|
12月前
|
存储 芯片 UED
【STM32】单片机模式配置&FlyMcu串口下载固件&STLINK Utility
【STM32】单片机模式配置&FlyMcu串口下载固件&STLINK Utility
330 0
stm32f407探索者开发板(二)——新建工程(基于固件库)(下)
stm32f407探索者开发板(二)——新建工程(基于固件库)(下)
114 0
stm32f407探索者开发板(二)——新建工程(基于固件库)(下)
stm32f407探索者开发板(二)——新建工程(基于固件库)(上)
stm32f407探索者开发板(二)——新建工程(基于固件库)(上)
252 0
stm32f407探索者开发板(二)——新建工程(基于固件库)(上)