前言
如果我们的App 程序起始地址在0x08006000 ,并且App 的中断向量表在起始地址,那么BootLoader 程序下载App 后,为了App 程序能正确运行,开始App 程序的运行后第一步,就要把中断向量表重定位到0x08006000 那里。
跳转到新程序运行
我们的BootLoader下载App程序后,App程序就需要做同样的事情。主要有三个步骤,其中BootLoader程序需要做的是:
- 跳转到复位向量
App需要做的是:
- 重定位中断向量表
- 设置栈指针
根据上图分析加入IAP后的起动和运行过程
- STM32复位后,还是从0X08000004地址取出复位中断向量的地址,并跳转到复位中断服务程序,在运行完复位中断服务程序之后跳转到IAP的main函数,如将IAP看作是一个APP的话,那么此部分和正常起动是一样的。(此步=执行复位中断服务程序+跳转main,即将正常运行的①和②合并了)。
- 在执行完IAP以后(固件升级或直接跳转),跳转至APP的复位向量表(APP的复位中断向量起始地址为0X08000004+N+M)。
- 取出APP的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至APP的main函数(此步=执行复位中断服务程序+跳转main)
- 同样main函数为一个超循环,并且注意到此时STM32的FLASH,在不同位置上,共有两个中断向量表。在main函数执行过程中,如果CPU得到一个中断请求,PC指针仍强制跳转到地址0X08000004中断向量表处,而不是APP程序的中断向量表。
- 程序再根据我们设置的中断向量表偏移量,跳转到对应中断源的APP的中断服务程序中,
- 在执行完中断服务程序后,程序返回main函数继续运行。
gd32的启动文件:
升级bootloader调试记录
目前boot的实现方式有两种
- 一直是boot里面只做文件拷贝、版本对比与跳转。这种方法的好处是不需要在boot中添加通讯协议及相关的通讯功能。但是升级需要外部有一个备份区来进行存储升级数据,占用空间较大,但是升级失败后,依然可以运行之前的app,保证机器能一直有app可以使用。
- 另外一种是在boot里面增加通讯功能,让其具备接收数据、并将数据写到指定位置的特性。使用这种方式可以实现不要备份区升级、以此来满足小容量单片机的需求。每次进行升级都会对app区进行擦写。这样就会导致一个问题,当升级失败后,会一直停留在boot等待再一次升级,直到升级成功后,才能去运行app。
升级app调试记录
如果使用了bootloader后需要调试app应用需要做一下操作
1、修改ROM1起始位置及大小
2、修改启动文件(.s)中的NVIC中断向量表的偏移。比如,我的app其中地址的偏移为
#define VECT_TAB_OFFSET (uint32_t)0x1E00 /* vector table base offset */
在SystemInit中会用到
3、修改debug的app堆栈指针的偏移,这里使用外部加载ini文件的方式。
文件内容
SP = _RDWORD(0x08001E00); // Setup Stack Pointer
PC = _RDWORD(0x08001E04); // Setup Program Counter
4、到这里你就可以开心的调试自己的代码了。