stm8L IAP之自定義bootloader

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


存儲.png

有些芯片內(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文件


設(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實踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容