IAP可以實現(xiàn)更新stm單片機內(nèi)的程序。

有些芯片內(nèi)置了BootLoader,在0x6000的地方。具體使用可查文檔。內(nèi)置的BootLoader有一些限制,所以自己實現(xiàn)一個。
那么現(xiàn)在stm里面相當(dāng)于有兩個程序,一個是BootLoader,一個是應(yīng)用程序。BootLoader從地址0x8000開始到自己設(shè)定的地址(根據(jù)BootLoader程序大小設(shè)置)比如0x8FFF,然后應(yīng)用程序就從0x9000開始。
啟動單片機進(jìn)入bootloader,BootLoader從串口接收到程序數(shù)據(jù)寫到flash里面,然后跳轉(zhuǎn)到應(yīng)用程序。
這么設(shè)置程序的地址呢,在IAR中可以設(shè)置ICF文件

這里需要注意的一個問題是中斷向量表,中斷向量默認(rèn)是在0x8000-0x8080這段地址中,它里面跳轉(zhuǎn)到一個中斷服務(wù)地址。在有BootLoader的情況下,中斷不會跳轉(zhuǎn)到應(yīng)用程序中,所以需要中斷向量表重定向。
//重定向中斷向量表到主程序
__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,
};
除了第一個,其他的需要根據(jù)應(yīng)用程序的開始地址設(shè)置,即應(yīng)用程序的中斷向量表位置。
在程序?qū)懙絝lash之后,跳轉(zhuǎn)(加入應(yīng)用程序開始地址是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的塊操作需要在內(nèi)存中執(zhí)行,而且我嘗試循環(huán)擦除也失敗了,只能在外部函數(shù)中循環(huán)。(注意要先解鎖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); //等待擦除完成
}
另外如果串口連續(xù)發(fā)數(shù)據(jù),flash可能來不及寫。這時候需要設(shè)計一個合理的串口燒寫協(xié)議。
參考文章:
IAP升級記錄
Intel Hex概述
stm8s IAP實踐