IAP即In Application Programming(在应用中编程).
面对场景:
- 嵌入式板位于不便手动烧录新程序的地方时,比如在机器内部没有引出线缆,或者在异地
- 数量较多的嵌入板 需要统一升级新固件
- 构建完善的机器人的嵌入式系统
以下是正文
首先了解
STM32的启动步骤:
- 上电复位后,从
0x0000 0000
地址取出栈顶地址赋给MSP寄存器(主堆栈寄存器),即MSP = __initial_sp
。这一步是由硬件自动完成的 - 从
0x0000 0004
地址取出复位程序的地址给PC寄存器(程序计数器),即PC = Reset_Handler
。这一步也是由硬件自动完成 - 调用
SystemInit
函数初始化系统时钟 - 跳到C库的
__main
函数初始化堆栈(初始化时是根据前面的分配的堆空间和栈空间来初始化的)和代码重定位(初始RW 和ZI段),然后跳到main
函数执行应用程序
bootloader启动过程:
- 设置
application
的MSP
的值; 从0x0800 C000
地址取出栈顶地址的值赋给MSP
。(0x0800 C000
是application
的起始地址 ) - 从
0x0800 C004
地址取出application
第一个执行的函数地址赋值给函数指针fun_point
- 使用
fun_point
函数针跳到application
执行 - 跳到
application
后需要设置中断向量表的偏移;也就是设置VTOR
寄存器的值(VTOR
寄存器可以到《Cortex-M3权威指南》查看)。发生中断后,cpu要到application
的空间找到中断服务程序的;如果不设置偏移,默认是从bootloader
空间找到中断服务程序的。
准备工作
新固件编译时需设置新的起始地址.
设置使Keil生成bin文件
C:MDKARMARMCCbinfromelf.exe --bin -o .ProjectProject.bin .ProjectProject.axf
可以通过串口或者其他方式传输新固件,然后烧录并运行.
跳转程序设计
1.加载栈地址
__asm void MSR_MSP(uint32_t addr)
{
MSR MSP, r0
BX r14;
}
__asm void MSR_MSP(uint32_t addr) 是MDK嵌入式汇编形式。
MSR MSP, r0 意思是将r0寄存器中的值加载到MSP(主栈寄存器,复位时默认使用)寄存器中,r0中保存的是参数值,即addr的值
BX r14 跳转到连接寄存器保存的地址中,即退出函数,跳转到函数调用地址
2.程序跳转
#define APP_ADDR 0x08002000 //应用程序首地址定义
typedef void (*APP_FUNC)(); //函数指针类型定义
APP_FUNC jump2app; //定义一个函数指针
jump2app = ( APP_FUNC )(APP_ADDR + 4); //给函数指针赋值
jump2app(); //调用函数指针,实现程序跳转
3.中断向量表重映射
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
注意事项:
- 跳到新的application时, bootloader中的中断须关闭或者新的application有对应的中断处理函数.否则程序会无限进入中断,然后跑飞.
- 需对新的application进行校检
加深理解可以看下面文章:
BIN文件详解blog.csdn.net