了解BootLoader——基於MPC5744P Bootloader例程


一、BootLoader的作用:BootLoader是固化在PFlash中的一個程序,其作用可以分為兩部分:boot和load。

  (1)boot:MCU上電時首先會運行BootLoader程序(因為它一般位於PFlash最前面的啟動區,接下來會談到啟動區Boot location的概念),BootLoader程序會初始化系統時鍾、看門狗等以保證系統的正常運行,此外還會初始化CAN(也可以是串口、SPI等)以實現和上位機的通信。

  (2)load:系統初始化完成后,程序會進入等待狀態,如果在預定時間內沒有接收到上位機的程序下載請求信號(CAN幀),則跳轉並執行MCU內部原有的用戶應用程序(位於PFlash的其他啟動區)。如果在預定時間內接收到來自上位機的程序下載請求信號,則BootLoader程序進入新程序下載狀態。下載過程中,上位機與BootLoader程序之間采用一問一答的方式逐行的下載S19文件(用戶應用程序的可執行文件)並進行解析,得到程序地址和程序數據,從而將每一行程序數據按照程序地址寫入到PFlash中。程序下載完成后,清除RAM,關閉CAN等BootLoader用到的外設,跳轉到新的用戶應用程序並開始執行。

二、Boot location的概念:Boot location就是每次MCU復位后運行BAM(Boot Assist Module)時尋找合法復位配置半字RCHW(Reset Configuration Harf-Word)和應用程序開始地址(Application Start Address,也可以叫做應用程序復位向量地址(Reset Vector)的區域。復位后CPU將從Boot location0~7依次查找由正確Boot_ID--0x5A組成的合法復位配置半字和應用程序開始地址,從而執行用戶應用程序。MPC5744P有8個Boot location,在Flash Memory Map中標明了哪些block可以作為Boot location,如下圖:

 

 Boot location的組成如下圖所示:

Boot location的起始位置是復位配置半字(RCHW),其結構如下所示。

只有設置了真確的BootID,該Boot location才被識別為可啟動的,如BootLoader程序和用戶應用程序生成的S19文件:

  

 

 

 

在BootLoader程序的S19文件第二行中,0x00F98000為Boot location_0的起始地址,也就是RCHW的地址,其中存放的數據為0x01_5A,RCHW的VLE位置1,BOOT_ID為0x5A,即配置該Boot location為可啟動的。reserve的16-31位默認為0x00

從用戶應用程序的S19文件第三行可以看到,0x00FA0004為用戶應用程序開始地址(應用程序復位向量地址),其中記錄的數據0x0100000為應用程序的復位函數地址,也就是應用程序真正開始執行的地址。因此,一般用如下方法實現到用戶應用程序的跳轉:

#define APP_StartAddr (*(uint32_t*)0x00FA0004)
(*(void (*)(void))(APP_StartAddr))();

 

三、BootLoader程序和用戶應用程序App在PFlash中的位置關系(Flash分配)

對BootLoader程序和用戶應用程序的 link_file做如下設置:

MEMORY  //BootLoader
{

    /*16 KB low flash memory block 2 (boot location 0) from 0x00F98000 to 0x00F9BFFF*/  
    /*16 KB low flash memory block 3 (boot location 1) from 0x00F9C000 to 0x00F9FFFF*/
    /* use the low flash memory block 2 and 3(32KB in total) as bootloader area */
    
    flash_rchw : org = 0x00F98000,   len = 0x4
    cpu0_reset_vec : org = 0x00F98004,   len = 0x4
    
    m_text :    org = 0x00F99000, len = 28K    /*code flash for bootloader interrupt vector table, startup and boot codes*/
    
    m_data :    org = 0x40000000,   len = 384K  /*system SRAM*/
    
    local_dmem  : org = 0x50800000,   len = 64K /*CPU core data tightly coupled memory*/         
}
MEMORY  //User App
{

    flash_rchw : org = 0x00FA0000,   len = 0x4
    cpu0_reset_vec : org = 0x00FA0004,   len = 0x4
        
    m_text :    org = 0x1000000, len = 2048K  
    m_data :    org = 0x40000000,   len = 384K
    
    local_dmem  : org = 0x50800000,   len = 64K    
}

則BootLoader和App的在PFlash中的關系如下:

 

 

四、S19文件結構:

五、數據對齊問題:

例程中的對齊函數主體及注釋如下:

    stafno = (srcd_t->addr&0x7)>>1;   /* number of uint16_t need to be pre-staffed  */  //if addr is not a multiple of 8-Bytes, get the surplus bytes then >>1
    srcd_t->addr &= 0xFFFFFFF8;           /* align data base address at 4W   */            //about why >>1(divided by 2 regardless odd num addr): maybe there isn't odd address
    
    if(stafno) 
    {
        for(i=srcd_t->dtlen; i>0; i--) 
            srcd_t->data[i+stafno-1] = srcd_t->data[i-1];  // move forward data in number of stafno
        
        srcd_t->dtlen += stafno;    // update dtlen
        
        while(stafno--)    
            srcd_t->data[stafno] = 0xFFFF;           // pre-staff 0xFFFF
    }

    while((srcd_t->dtlen&0x000003)!=0)   // need to append post-staffing uint16_t  //if data num is a multiple of 4(each data is uint_16, so it's a judge of 64bits - 8bytes)
        srcd_t->data[srcd_t->dtlen++] = 0xFFFF; //if not enough 4*uint_16 - 8bytes, padding with 0xFFFF behind data's tail
}
// conclusion: address is aligned with 8bytes by &0xFFFFFFF8, but data field will not move accordingly,
// it just padding with 0xFF in the front of array, so as to accord with origin address(0x0004) correctly
//
//    address     data(uint16)                address     data(uint16)
//    |0x0000|                                |0x0000|<-- 0xFF
//    |0x0002|                     after      |0x0002|    0xFF
//    |0x0004|<-- 0x55(data[0])    =======>>  |0x0004|    0x55
//    |0x0006|    0x66             address    |0x0006|    0x66
//    |0x0008|    0x77             align      |0x0008|    0x77
//    |0x000A|    0x88                        |0x000A|    0x88
//    |0x000C|                                |0x000C|
//
//     note: (1) i guess that 0xFF will not be recognized as a instruction by CPU, so CPU fetch instruction from 0x0000
//                but execute from 0x0004 in fact.
//           (2) and note that the graph above is base on the struct SRecord_t,
//                so that data[0] is always correspond with base address(SRecord->addr)

其中srcd_t的結構如下:

typedef struct {
    uint32_t addr;
    uint32_t  dtlen;  // num of valid data
    uint16_t  data[20];
} SRecord_t;

另外,關於數據對齊問題,可以參考博文:https://blog.csdn.net/maxlovezyy/article/details/70231804

 

六、其他:下圖為建立多核工程時的Flash和RAM資源的分配,可以用來參考以加深對程序在內存中的存儲的理解

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM