电子大神的日记本,供应链专家的功夫茶盘,在这里记录、分享与共鸣。

登录以开始

C8051F340 BOOTLOADER 固件升级的的实现过程

实现过程:

一:内部flash 的空间划分

0XFFFF

 

保留区

 

应用程序区

 

 

BOOTLOADER可操作区域

 

 

0XF000

 

0X1000

0X1000

 

0X0000

 

二:中断向量软件映射

MCU中断向量分布在复位(0x0000)以后,按规则排布,若改变编译器设置,如51,可改变程序在FLASH中的位置,可改变中断向量起始点,如改到这样0X1000,即:就是将0X0000地址内容映射到0X1000,把0X1000作为一个虚拟的复位地址,编译后,中断向量安装在0X1000后。但是,硬件跳转是不能改变的。就是说中断发生后,仍然进入以0X0000为复位地址的向量表。但是,这个向量表中,不再是直接跳转到中断服务程序,而是需要手动跳转到虚拟中断向量表,再由虚拟中断向量表跳转到中断服务程序。但是其原始向量表可能为空,所以需要加入程序判进行手动跳转到新向量表。
       所以编译的时候,将APP程序中断向量表虚拟,BOOT程序使用原始的向量表。所以任何时候中断发生后,将执行BOOT中断服务程序。在BOOT中断服务程序中判断当前程序是执行BOOT区还是APP区,如果是执行APP区,就跳转到APP中断服务程序即可(入口向量已经规则地排布在0X1000以后)。

51的中断向量排布规则是:  LJMP   3+8*INTERRUPT_VECTOR_NUMBER

图解:

原始地址(向量表)
作用
描述

0000H
RESET
POWER UP ENTRY

0003H
INTERRUPT 0入口
 

000BH
INTERRUPT 1入口
 

0013H
INTERRUPT 2入口
 



虚拟后地址(向量表)
作用
描述

1000H
虚拟复位地址
 

1003H
INTERRUPT 0虚拟入口
进入中断

100BH
INTERRUPT 1虚拟入口
进入中断



注意:中断向量虚拟后,并不是说发生中断程序就转入虚拟后的向量表。而是:中断向量表的实质是一条跳转指令,跳转到相关ISR,虚拟后,这个跳转指令被放在了新的地址,而不是原始默认地址。所以,需要在原始地址处再放一辅助向量表(中断发生后,硬件挑到此处),用于跳转到新的向量表。这个辅助向量表有BOOT区完成。

1:STARTUP.A51文件设置:

;vector_base           EQU     01000h

;vector

                            CSEG    AT      03h

                            LJMP    vect + 03h            ;// 0 外部中断0 (/INT0)

;user_address     EQU     01000h

user_process:

                            LJMP    vect;user_address

                            CSEG    AT      0bh

                            LJMP    vect + 0bh            ;// 1 定时器0溢出

                            CSEG    AT      13h

                            LJMP    vect + 013h          ;// 2 外部中断1 (/INT1)

                            CSEG    AT      1bh

                            LJMP    vect + 01bh          ;// 3 定时器1溢出

                            CSEG    AT      23h

                            LJMP    vect + 023h          ;// 4 UART0

                            CSEG    AT      2bh

                            LJMP    vect + 02bh          ;// 5 定时器2溢出

                            CSEG    AT      33h

                            LJMP    vect + 033h          ;// 6 SPI0

                            CSEG    AT      3bh

                            LJMP    vect + 03bh          ;// 7 SMB0

                            CSEG    AT      43h

                            LJMP    vect + 043h          ;// 8 USB0

                            CSEG    AT      4bh

                            LJMP    vect + 04bh          ;// 9 ADC0窗口比较

                            CSEG    AT      53h

                            LJMP    vect + 053h          ;// 10 ADC0转换结束

                            CSEG    AT      5bh

                            LJMP    vect + 05bh          ;// 11 可编程计数器阵列

                            CSEG    AT      63h

                            LJMP    vect + 063h          ;// 12 比较器0 

                            CSEG    AT      6bh

                            LJMP    vect + 06bh          ;// 13 比较器1

                            CSEG    AT      73h

                            LJMP    vect + 073h          ;// 14 定时器3溢出

                            CSEG    AT      7bh

                            LJMP    vect + 07bh          ;// 15 VBUS电平

                            CSEG    AT      83h

                            LJMP    vect + 083h          ;// 16 UART1

                CSEG    AT      000h

?C_STARTUP:     LJMP    STARTUP1

 

2:应用程序区工程设置:

 

 

 

 

 

 

3:bootloader程序和 APP 应用程序的初始化时钟必须是一致的, 否则容易造成死机的现象

三:BOOTLOADER 程序

1:主程序的编写

main(void)

{

       uint8 uartRX;

        uint16 timeout;

        void (*boot)( void);

        Sys_Clk_Init();  // 初始化设备                 

        PORT_Init();                       

        UART0_Init();

        FLSCL = 0x86;

        if (1) {

             Uart_Print("\n");

             Uart_Print("**************BootLoader v1.0***************\n");

             Uart_Print(">Please press 's' to start programming.\n");

         while (1)

         {

           for(timeout=0;timeout<4000;timeout++)

             {

                    if(RI0)

                     {

                        uartRX=SBUF0;

                      RI0=0;

                            break;

                     }

                     delay_ms(10);

              }

          if (uartRX=='s')

          {RTload();    

              uartRX = 0; 

            }

              else if(vect == 0x02)

                     {

                            goto USE_CODE;

                     }

          }

  }

USE_CODE:

       user_process();

       while(1)

       {

       }

2:片内FLASH的 操作

unsigned char FLASH_ByteRead (FLADDR addr)

{

   bit EA_SAVE = EA;               

   char code * data pread;           

   unsigned char byte;

   EA = 0;                           

   pread = (char code *) addr;

   byte = *pread;                     

   EA = EA_SAVE;                      

   return byte;

}

 

void FLASH_ByteWrite (FLADDR addr, char byte)

{

   bit EA_SAVE = EA;               

   char xdata * data pwrite;       

   EA = 0;                           

   pwrite = (char xdata *) addr;

   PFE0CN = PFE0CN & 0xFE;            

   PSCTL  = 0x01;                  

   FLKEY  = 0xA5;                  

   FLKEY  = 0xF1;                 

   *pwrite = byte;                  

   PSCTL = 0;                   

   EA = EA_SAVE;                      

}

void FLASH_PageErase (FLADDR addr)

{

   bit EA_SAVE = EA;                

   char xdata * data pwrite;         

   EA = 0;                         

   pwrite = (char xdata *) addr;

   FLKEY  = 0xA5;                    

   FLKEY  = 0xF1;                    

   PSCTL  = 0x03;                 

   *pwrite = 0;                      

   PSCTL = 0;                  

   EA = EA_SAVE;                 

}

 

可以正常使用串口更新程序, 有需要的, 可以给我留言,一起起步!

 

博主
081010
081010's Blog
081010
点击跳转