欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

stm32之Bootloader

程序员文章站 2024-02-23 22:57:06
...

利用bootloader代码能够实现远程代码更新。

要清楚的认识bootloader,我们就要先了解stm32正常程序运行流程。

stm32之Bootloader

 

 

在stm32中将所有的中断做成了一张中断向量表(其实就像是一张表格),由上图可知由栈顶地址向下,我们可以大致分为三个部分。

1、中断向量表

2、各个中断程序入口。

3、main函数入口。

整个单片机上电运行的流程为:

上电------复位(从中断向量表中找到复位中断向量)-----执行复位中断服务程序-----执行main函数程序-----main函数中发生中断内请求----PC指针强制跳转到中断向量表处找到相应的中断向量-------执行对应的中断服务程序------返回mian函数

以上就是整个stm32上电运行main函数的流程。

当我们加入bootloader程序之后,在我们单片机的flush里面实际有两个或者多个程序(程序个数取决于flush大小),每个程序有着自己的mian函数,我们的多个程序分别放在flush的不同位置,我们的bootloader放在0X08000000(即是首地址处),其余的程序(app)紧随bootloader之后。

加入bootloader之后的启动流程如下图:

stm32之Bootloader

由图我们可以看出每个程序都有着自己的中断向量表等等。。。多个程序的驱动流程和单个的大致相似。。只是在app中发生中断时PC指针指向的是0X08000004这个位置的中断向量表,而非app本身的中断向量表处,,这里的注意,,在执行相应的中断程序时是跳转到app自己的中断程序表位置,,,这里的注意。。。

由此,我们利用bootloader实现代码的更新无非就是在bootloader里面将接受到的代码下载到指定的flush区域替换掉原先的代码,然后将PC指针强制指向app栈顶地址处即可实现代码的跟新。。。。。

同理我也尝试过在app中强制的将pc指针指向另外的app也能实现两个应用程序之间的切换。。。。

bootloader中主要代码为跳转程序:

//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
{
	if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法.  
	{ 
		jump2app=(iapfun)*(vu32*)(appxaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)		
		MSR_MSP(*(vu32*)appxaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		jump2app();									//跳转到APP.
	}
}		

注意:

if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)   :判断栈顶值是否合法,若没有这一句的话,即使没有下载程序也会进入而导致跑飞。

其中appxaddr表示栈顶地址中的值是栈顶地址中的值而非地址。 栈顶合法值为0x20000000--0x20020000

如何查看一个程序的栈顶值,可以在工程中查看map文件至于怎么查看map文件自行百度。。。。

stm32之Bootloader

这是我们app项目生成的map文件可以看到我们的栈顶值为0x2000b360,是一个合法的栈顶值。

    jump2app=(iapfun)*(vu32*)(appxaddr+4);        //用户代码区第二个字为程序开始地址(复位地址)        

appxaddr:栈顶地址+4表示的是指向中断向量表位置(也是复位地址)处。

其中iapfun,jump2app都是一个函数指针

typedef  void (*iapfun)(void);                //定义一个函数类型的参数.

汇编 初始化堆栈指针  MSR_MSP(*(vu32*)appxaddr);                    //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)

楼主实力有限。。。不懂汇编所以这里也不做解释了。。。。照搬

 

 

jump2app():把用户代码的复位地址付给PC指针,我看到jump2app()这句代码debug的时候对应的汇编代码是

LDR r0,[pc,#12] ;相对PC的数据加载到函数指针的地址
LDR r0,[r0,#00] ;R0做索引,无偏移,数据装载到R0,这个内容就是函数指针指向的内容,也就是函数的地址了,用户程序的起始地址;
BLX r0              ;这个不解释,说了是跳转
 

到此整个bootloader的开发流程大致清楚,就可以利用bootloader实现app更新等一系列项目开发。。。

除了使用按键跟新程序,,我们也可以通过标志位等其他方式更新app。。。