×
嵌入式 > 技术百科 > 详情

STM8的IAP在线升级

发布时间:2021-01-19 发布时间:
|

IAP(In Application Program)在线应用编程


官方资料(STVD开发环境):例程AN2659,


《 AN2659 Application Note.pdf 》


要实现在线升级,MCU代码须分为 : bootloader和 用户代码App 两个部分。

图1.STM8下IAP程序的存储方式


用户启动区域(UBC): (可理解为用户自定义的bootloader的存放区域)


包含有复位和中断向量表,它可用于存储IAP及通讯程序。UBC有一个两级保护结构可保护用户代码及数据在IAP编程中免于无意的擦除或修改。这意味着该区域总是写保护的,而且写保护不能通过使用MASS密钥来解锁。它的大小可通过配置option bytes 设置。


一、中断向量表:


STM8的中断向量表的地址是固定的,位于0x8000~0x8080,即发生中断时,程序将会跳转至0x8000~0x8080的中断向量表中寻找中断入口地址,继而跳转至对应的中断服务函数中执行中断程序。


若是要实现IAP,而0x8000~0x8080的中断向量表将会位于UBC区域,被bootloader所占用。如此一来,UBC区域中的bootloader程序与MAIN PROGRAM区域中的App发生中断时,程序同样都是跳转至UBC区域中的中断向量表中寻找中断入口地址。所以,若App要执行App自己的中断服务函数,则须在App中建立自己的中断向量表,并对bootloader中的中断向量表进行重定向,将程序跳转至App的中断向量表。如图2、图3所示。

          

图2.中断跳转示意图

图3.中断跳转流程图


中断向量表的重定向:(以STVD环境下的官方例程AN2659为例)


以下重定向即可使App程序能够找到自己对应的中断服务函数,但是bootloader的中断将不可使用


原中断向量表为:


struct interrupt_vector const _vectab[] = {

{0x82, (interrupt_handler_t)_stext}, /* reset */

{0x82, NonHandledInterrupt}, /* trap  */

{0x82, NonHandledInterrupt}, /* irq0  */

{0x82, NonHandledInterrupt}, /* irq1  */

{0x82, NonHandledInterrupt}, /* irq2  */

{0x82, NonHandledInterrupt}, /* irq3  */

{0x82, NonHandledInterrupt}, /* irq4  */

{0x82, NonHandledInterrupt}, /* irq5  */

{0x82, NonHandledInterrupt}, /* irq6  */

{0x82, NonHandledInterrupt}, /* irq7  */

{0x82, NonHandledInterrupt}, /* irq8  */

{0x82, NonHandledInterrupt}, /* irq9  */

{0x82, NonHandledInterrupt}, /* irq10 */

{0x82, NonHandledInterrupt}, /* irq11 */

{0x82, NonHandledInterrupt}, /* irq12 */

{0x82, NonHandledInterrupt}, /* irq13 */

{0x82, NonHandledInterrupt}, /* irq14 */

{0x82, NonHandledInterrupt}, /* irq15 */

{0x82, NonHandledInterrupt}, /* irq16 */

{0x82, NonHandledInterrupt}, /* irq17 */

{0x82, NonHandledInterrupt}, /* irq18 */

{0x82, NonHandledInterrupt}, /* irq19 */

{0x82, NonHandledInterrupt}, /* irq20 */

{0x82, NonHandledInterrupt}, /* irq21 */

{0x82, NonHandledInterrupt}, /* irq22 */

{0x82, NonHandledInterrupt}, /* irq23 */

{0x82, NonHandledInterrupt}, /* irq24 */

{0x82, NonHandledInterrupt}, /* irq25 */

{0x82, NonHandledInterrupt}, /* irq26 */

{0x82, NonHandledInterrupt}, /* irq27 */

{0x82, NonHandledInterrupt}, /* irq28 */

{0x82, NonHandledInterrupt}, /* irq29 */

};


改为


struct interrupt_vector const UserISR_IRQ[32] @ MAIN_USER_RESET_ADDR;    //MAIN_USER_RESET_ADDR为主程序区的首地址 的宏定义

 

//redirected interrupt table

struct interrupt_vector const _vectab[] = {

    {0x82, (interrupt_handler_t)_stext}, /* reset */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+ 1)}, /* trap  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+ 2)}, /* irq0  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+ 3)}, /* irq1  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+ 4)}, /* irq2  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+ 5)}, /* irq3  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+ 6)}, /* irq4  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+ 7)}, /* irq5  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+ 8)}, /* irq6  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+ 9)}, /* irq7  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+10)}, /* irq8  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+11)}, /* irq9  */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+12)}, /* irq10 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+13)}, /* irq11 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+14)}, /* irq12 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+15)}, /* irq13 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+16)}, /* irq14 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+17)}, /* irq15 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+18)}, /* irq16 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+19)}, /* irq17 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+20)}, /* irq18 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+21)}, /* irq19 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+22)}, /* irq20 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+23)}, /* irq21 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+24)}, /* irq22 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+25)}, /* irq23 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+26)}, /* irq24 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+27)}, /* irq25 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+28)}, /* irq26 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+29)}, /* irq27 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+30)}, /* irq28 */

    {0x82, (interrupt_handler_t)(UserISR_IRQ+31)}, /* irq29 */

}; 


其中,

typedef void @far (*interrupt_handler_t)(void);  //定义中断函数地址类型


struct interrupt_vector {


  unsigned char            interrupt_instruction;    //指令,其中0x82为跳转指令


  interrupt_handler_t    interrupt_handler;    //函数地址


};


二、FLASH块编程程序的存放:

对于stm8的块编程,代码必须在Ram中运行,因为在块编程时Flash程序将会停止运行。因此,存储在Flash中的代码(与Flash编程相关的代码)必须拷贝至Ram中进行编译、链接、运行。这样,程序将在Ram中执行块编程,块编程时Flash的状态也不会影响到Ram中的程序继续运行。


方法如下:


1、代码的编写:


将Flash编程相关的代码存放至FLASH_CODE段:


#pragma section (FLASH_CODE)    //将代码存放至RAM

void Write_Flash(void)

{

    //....

}

void Erase_Flash(void)

{

    //....

}

#pragma section ()    //代码放置至默认段

 

注意,在调用这些函数之前,必须把这些代码拷贝至RAM中,

STVD的cosmic编译器可以使用内置函数 int  _fctcpy(char name)实现此功能。


int  _fctcpy(char name)    //name为定义的段名首字母


如本例中Flash块编程所在的段名为FLASH_CODE,其首字母为 ‘F’ 故在调用这些函数之前须执行


_fctcpy('F');


2、STVD的设置:在STVD--Settings--Linker选项卡下,选择目录Category下的Input,


在Ram下新建Section,Option填-ic,表示可移至RAM。

三、程序的跳转


若bootloader程序要跳转到app,须将程序跳转至主程序区的首地址。


可使用汇编指令完成:


    //reset stack pointer (lower byte - because compiler decreases SP with some bytes) 

    _asm("LDW X, SP "); 

    _asm("LD A, $FF"); 

    _asm("LD XL, A "); 

    _asm("LDW SP, X "); 

 

    //跳转至App程序 :     

    _asm("JPF $A000");//这里假设app首地址为0x00A000。

    /***或者可以***/

    _asm("JPF [_MainUserApplication]");//跳转至app程序首地址,其中_MainUserApplication的定义在下面有所解释

 

/*****其中:*****/

//typedef @far void (*)(void) TFunction;

typedef @far void (*TFunction)(void);

 

//main application code (user reset) - init user code start - to interrupt table reset jump

const TFunction MainUserApplication = (TFunction)MAIN_USER_RESET_ADDR;



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
相聚2021年慕尼黑电子展