stm8L IAP之自定义bootloader
2019-07-26 本文已影响0人
田文健
IAP可以实现更新stm单片机内的程序。
![](https://img.haomeiwen.com/i7098445/cc4916ca79d8e101.png)
有些芯片内置了BootLoader,在0x6000的地方。具体使用可查文档。内置的BootLoader有一些限制,所以自己实现一个。
那么现在stm里面相当于有两个程序,一个是BootLoader,一个是应用程序。BootLoader从地址0x8000开始到自己设定的地址(根据BootLoader程序大小设置)比如0x8FFF,然后应用程序就从0x9000开始。
启动单片机进入bootloader,BootLoader从串口接收到程序数据写到flash里面,然后跳转到应用程序。
这么设置程序的地址呢,在IAR中可以设置ICF文件
![](https://img.haomeiwen.com/i7098445/eac8cfc868a2e471.png)
这里需要注意的一个问题是中断向量表,中断向量默认是在0x8000-0x8080这段地址中,它里面跳转到一个中断服务地址。在有BootLoader的情况下,中断不会跳转到应用程序中,所以需要中断向量表重定向。
//重定向中断向量表到主程序
__root const long reintvec[]@".intvec"=
{
0x82008080,0x82009004,0x82009008,0x8200900c,
0x82009010,0x82009014,0x82009018,0x8200901c,
0x82009020,0x82009024,0x82009028,0x8200902c,
0x82009030,0x82009034,0x82009038,0x8200903c,
0x82009040,0x82009044,0x82009048,0x8200904c,
0x82009050,0x82009054,0x82009058,0x8200905c,
0x82009060,0x82009064,0x82009068,0x8200906c,
0x82009070,0x82009074,0x82009078,0x8200907c,
};
除了第一个,其他的需要根据应用程序的开始地址设置,即应用程序的中断向量表位置。
在程序写到flash之后,跳转(加入应用程序开始地址是0x90000),stm8汇编不太懂,照着写就是了
void goToMain()
{
asm("LDW X, SP");
asm("LD A, $FF");
asm("LD XL, A");
asm("LDW SP, X");
asm("JPF $9000");
}
过程中还有个麻烦的点是操作flash,flash的块操作需要在内存中执行,而且我尝试循环擦除也失败了,只能在外部函数中循环。(注意要先解锁flash,uint32_t 在库stdint里)
//擦除块
__ramfunc void eraseBlock(uint16_t blockAddr)
{
uint32_t *pwFlash = (uint32_t *)blockAddr;
FLASH_CR2_bit.ERASE = 1;
*pwFlash = (uint32_t)0x00;
while (FLASH_IAPSR_bit.EOP == 0); //等待擦除完成
}
另外如果串口连续发数据,flash可能来不及写。这时候需要设计一个合理的串口烧写协议。
参考文章:
IAP升级记录
Intel Hex概述
stm8s IAP实践