STM8L IAP升級過程記錄

STM8L IAP升級
芯片:STM8LXXX
通訊方式:SPI
IDE: IAR for STM8

工作需求,需要實現基於SPI通信的IAP升級,百度了一些資料,爬過了一些坑,現在測試升級ok,因此寫篇筆記記錄一下整個過程,以下便是整個過程,純屬個人記錄,難免有不到的地方,如有錯誤,麻煩指出。

一、介紹
1) IAP簡介
所謂的IAP即應用程序中編程(In-application programming),即可以在產品出廠後,更新程序。既然可以更新程序,那麼就要有程序負責這部分功能,這個程序就叫做BootLoader,而被更新的程序就叫做Application.

2)官方BooLoader
如果只是想使用這個功能,而不用自己編寫BootLoader,ST官方已經內置了Bootloader,參考文檔《AN2659.pdf》中:點擊下載
這裏寫圖片描述

根據上面的文檔,可以瞭解,ST官方已經在STM8中內置了Bootloader,然後參考文檔《UM0560.pdf》,點擊下載,可以查看自己要使用的MCU是否支持內置的Bootloader,還有支持什麼通信方式。
我使用的這顆MCU官方的Bootloader只支持USART方式通信,而我們的項目需求是使用SPI方式通信,因此需要自己開發Bootloader。
如果使用官方的Bootloader,則《UM0560.pdf》文檔裏面有詳細的升級協議,可以根據協議進行對接。

3)自己編寫BootLoader注意點
如果自己編寫Bootloader,則需要注意幾個方面:
1.中斷向量表的重定向
參考文檔《STM8L IAP 應用程序中編程指導.pdf》中的說明,點擊下載,如下圖
這裏寫圖片描述

可以看到,當Application中發生中斷的時候,會跳轉到0x8000地址處,因此在Bootloader中需要將中斷進行重定向,使之能夠跳轉到Application中的中斷向量表中去。
2.Bootloader與Application的大小以及數據的寫入
這個要根據自己的項目實際情況來確定大小以及區塊位置,下面將會詳細說明。

3.程序跳轉
程序跳轉可以分爲Bootloader跳轉到Application, Application跳轉到Bootloader.下面將會詳細說明。

二、功能實現
根據上面的說明,自己編寫BootLoader需要實現以下幾個方面:中斷向量表、分區大小、數據寫入、程序跳轉
1)中斷向量表
中斷向量表的重定向,需要根據自己的Bootloader大小進行設置,例如,大小爲4KB,則Bootloader地址範圍爲0x8000 ~ 0x8FFF,則可以中斷向量表可以重定向如下:

/* interrupt vetor redirected app addres is 0x9000
*  bld size is 4kb
*/
__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,
};

如果大小爲5KB,則Bootloader地址範圍爲0x8000 ~ 0x93FF,則可以中斷向量表可以重定向如下:

/* interrupt vetor redirected app addres is 0x9400
*  bld size is 5kb
*/
__root const long reintvec[]@".intvec"=
{
0x82008080,0x82009404,0x82009408,0x8200940c,
0x82009410,0x82009414,0x82009418,0x8200941c,
0x82009420,0x82009424,0x82009428,0x8200942c,
0x82009430,0x82009434,0x82009438,0x8200943c,
0x82009440,0x82009444,0x82009448,0x8200944c,
0x82009450,0x82009454,0x82009458,0x8200945c,
0x82009460,0x82009464,0x82009468,0x8200946c,
0x82009470,0x82009474,0x82009478,0x8200947c,
};

2)分區設置
如果確定自己的BooLoader大小,然後就可以設置對應的icf文件已經flash的大小。
例如,現在使用的MCU flash地址空間爲 0x8000 ~ 0xBFFF, 並且確定Bootloader的大小爲5KB,則Bootloader地址爲 0x8000 ~ 0x93FFF, Application地址爲0x94000 ~ 0xBFFF.
首先需要找到對應MCU的icf文件,具體路徑爲C:\Program Files\IAR Systems\Embedded Workbench 8.0_2\stm8\config 這個要根據你自己的IAR軟件安裝位置來確定。
找到對應的MCU icf文件後,創建Bootloader和Application兩份工程,然後將每一份工程的icf中,根據自己的分區的大小進行修改:
Bootloader修改如下:
這裏寫圖片描述

Application中修改如下:

這裏寫圖片描述
修改完畢後,還需要將此文件載入工程,直接在IAR中點擊創建的過程,右鍵options —> Linker —> Configuration, 選擇自己修改好的icf文件然後載入,如下:
這裏寫圖片描述

3)數據寫入
數據的寫入,根據MCU的datasheeet有幾種寫入方式,因爲是大數據寫入,所以採用了塊寫入的方式,即每次直接寫入一個塊,每個塊128Bytes則需要計算寫入塊的位置。
(0xbfff - 0x8000) / 128 = 128block 可知一共有128個塊
而Application的地址範圍爲 0x9400 ~ 0xbfff, 則Application的起始位置是(0x9400 - 0x8000) / 128 = 40 block
也就是,Bootloader的位置爲block0 ~ block 39, Application的位置爲block40 ~ block127
數據的寫入和擦除使用的是IN_RAM方式,代碼如下:


/*
Block programming, also called standard block programming: The block is automatically erased before being programmed.
Fast block programming: No previous erase operation is performed.
Block erase
*/
IN_RAM(void bld_flash_write_block(uint16_t BlockNum,FLASH_MemType_TypeDef FLASH_MemType,uint8_t *Buffer))
//void Write_Flash_Block(uint16_t BlockNum,FLASH_MemType_TypeDef FLASH_MemType,uint8_t *Buffer)
{
    FLASH_Unlock(FLASH_MemType);

    //FLASH_EraseBlock(BlockNum,FLASH_MemType);
    FLASH_ProgramBlock(BlockNum, FLASH_MemType,FLASH_ProgramMode_Fast,Buffer);
    FLASH_WaitForLastOperation(FLASH_MemType);

    FLASH_Lock(FLASH_MemType);
}


IN_RAM(void bld_flash_erase_block(FLASH_MemType_TypeDef FLASH_MemType))
{
    uint8_t i = 0;

    FLASH_Unlock(FLASH_MemType);
    for (i = FLASH_START_BLOCK; i <= FLASH_END_BLOCK; i++)
    {
        FLASH_EraseBlock(i, FLASH_MemType);
        FLASH_WaitForLastOperation(FLASH_MemType);
    }

    FLASH_Lock(FLASH_MemType);
}

代碼中寫入的時候採用的是FLASH_ProgramMode_Fast方式,即直接寫入,FLASH_ProgramMode_Standard模式則是寫入前先自動擦除,速度較慢。可以根據自己的需求進行選擇。

4)程序跳轉
Bootloadre — > Application
跳轉直接採用彙編的方式,這裏不再說明

void bld_goto_app()
{
    asm("LDW X, SP");
    asm("LD  A, $FF");   
    asm("LD  XL, A");
    asm("LDW SP, X");
    asm("JPF $9400");
}

Application —> Bootloader
當需要升級的時候,需要進入到Bootloader狀態,此時可以通過一些方法,例如外部電源reset、看門狗超時復位、或者直接採用彙編的方式跳轉,如下:

void app_goto_bld()
{
    asm("LDW X, SP");
    asm("LD  A, $FF");   
    asm("LD  XL, A");
    asm("LDW SP, X");
    asm("JPF $8000");
}

不過,在使用這種方式之前,最好要 enableInterrupts();,否則會有一些有趣的事情發生。。。

5)BootLoader如何確定要升級?
這個各有各的方法,目前簡單採用向EEPROM中寫入特殊字符來判斷。

以上是全部的過程,如有錯誤的地方,麻煩指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章