1. 程式人生 > >STM8L IAP升級過程記錄

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中寫入特殊字元來判斷。

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