SBL(Falsh驱动程序)在bootloader中的应用
目錄
?
SBL 常見方式
SBL(Second Boot Loader)由PBL下載到RAM種進行代碼執行,理論上PBL與SBL的代碼功能應幾乎是完全一模一樣的,差異體現在如下倆部分:
1 PBL有的功能SB卻L沒有的功能: PBL下載并激活SBL
2 SBL有的功能PBL卻沒有的功能: flash驅動
本文檔總結的情況,SBL僅僅只有flash驅動功能,基于vector的SIP包進行功能開發。
?Flash驅動程序,主要提供Flash內存的擦除及刷寫。在線升級中,首先擦除特定flash內存中的數據,然后把APP的可執行文件刷寫進去。
flash驅動?常見方式
?項目開發種,需要首先把刷寫/擦除程序下載到RAM,然后再進行應用程序的下載。SBL有下面三種方式:
第一種是把驅動程序固化在falsh中,定義一個const數組,使用時拷貝到RAM中。
第二種是驅動程序是放在PC端,通過總線下載到RAM中去。
第三種是芯片供應商已經固化flash刷寫/擦除程序在Flash的空間里,這時候只需根據提供的函數指針調用函數進行內存操作。
著重介紹第二種方式:
SBL flash驅動代碼在PC端,當需要升級時,首先把SBL通過總線下載到RAM中,然后根據指針調用相關驅動函數。
在bootloader代碼中定義一個全局變量的數組,其數組長度為SBL可執行代碼的長度。同時設定這個數組存放的內存位置。
/*fbl_flio.c*/#define FLASH_SIZE (2304) __attribute__ ((section ("FLASHCODE"))) uint8 flashCode[FLASH_SIZE];/*定義一個長度2048字節的數組,并把這個數組放在FLASHCODE段中*/FLASHCODE段在內存中的具體定義,見如下鏈接文件:
鏈接文件定義了flashcode這段的開始地址為0x20005E00,長度為2034(這段內存是上一步驟定義的flashcode數組的存儲內存)
MEMORY {VECTORS : ORIGIN = 0x00000000, LENGTH = 652RESERVED : ORIGIN = 0x00000400, LENGTH = 0x0COPTBYTES : ORIGIN = 0x0000040C, LENGTH = 0x48FLASH : ORIGIN = 0x00000500, LENGTH = 0xF000RAMCODE_FLASH : ORIGIN = 0x0000F500, LENGTH = 0x8B00SIMFS_REGION : ORIGIN = 0x00018000, LENGTH = 0x2000TPCFG : ORIGIN = 0x0001A000, LENGTH = 0x5000OTPREGION : ORIGIN = 0x0001F000, LENGTH = 0x1000APPL_VECT : ORIGIN = 0x00020000, LENGTH = 0x08flash_bld_app : ORIGIN = 0x00020100, LENGTH = 0x100flash_bld_dev : ORIGIN = 0x00020200, LENGTH = 0x100RAM : ORIGIN = 0x1FFF8000, LENGTH = 0xE700HEAP : ORIGIN = 0x20006700, LENGTH = 0x100STACK : ORIGIN = 0x20006800, LENGTH = 0x800magicflag : ORIGIN = 0x20005DF0, LENGTH = 0x10flashcode : ORIGIN = 0x20005E00, LENGTH = 0x900BSS : ORIGIN = 0x1FFFF000, LENGTH = 0x6DF0}.flash_drv (NOLOAD) : {*(FLASHCODE)} >flashcode打開SBL的可執行文件:可看到該文件對應的開始地址為0x20005E00,長度為0x900。
當通過總線接收到SBL的文件后,會直接根據文件定義的start address 以及 data length直接把數據寫進RAM中(寫入RAM不需要驅動程序,可直接通過地址操作)。
這時候flash_code指向的這段RAM內存中。
/*fbl_ramio.c*/#RAM_DRV_BUFFER flash_codeIO_ErrorType V_API_NEAR RamDriver_RWriteSync( IO_MemPtrType writeBuffer, IO_SizeType writeLength, IO_PositionType writeAddress ) /* PRQA S 3673 */ /* MD_FblRamio_3673 */ {IO_ErrorType result;IO_SizeType offset;IO_SizeType i;result = RamDriver_GetOffset(writeLength, writeAddress, &offset);if (IO_E_OK == result){for (i = 0u; i < writeLength; i++){if (0u == (i & (RAM_DRV_POLLING_INTERVAL - 1u))){RAM_DRV_POLLING_FUNCTION();} #endif /* RAM_DRV_POLLING_INTERVAL */RAM_DRV_BUFFER[offset] = writeBuffer[i];offset++;}}return result; }/******************************************************************* *注:在auotsar中,對內存的操作都認為是操作文件,都為專門的接口函數 */如操作RAM的接口模塊fbl_ramio.c如操作falsh的接口fbl_flio.cSBL驅動接口與Bootloader
? ? ? ? ?前面介紹SBL如何在運行bootloader程序過程中,下載到RAM空間中,當程序下載到空間后,我們如何調用并訪問需要的接口呢?
? ? ? ? ?autosar的做法是,定義如下結構體變量,并把這個結構體放在特定的內存中
typedef struct {/** Version Information */tFlashUint8 version; /**< Version of downloaded flash driver */tFlashUint8 reserved; /**< Reserved for future use */tFlashUint8 maskType; /**< Flash cell mask type */tFlashUint8 CPUType; /**< Microcontroller type *//** Function pointer to routines */tFlashFct flashInitFct; /**< Function pointer to init function */tFlashFct flashDeinitFct; /**< Function pointer to de-init function */tFlashFct flashEraseFct; /**< Function pointer to erase function */tFlashFct flashWriteFct; /**< Function pointer to write function */ } tFlashHeader; /* PRQA S 3448 */ /* MD_FblDrvFlash_3448 */# define FLASH_START_SEC_FLASH_DRIVER_HEADER # include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_19.1 */ const tFlashHeader flashHeader= /* PRQA S 3408 */ /* MD_FblDrvFlash_3408 */ {FLASH_DRIVER_VERSION_INTERFACE,0x00,FLASH_DRIVER_VERSION_MASKTYPE,FLASH_DRIVER_VERSION_MCUTYPE,&ExpFlashInit,&ExpFlashDeinit,&ExpFlashErase,&ExpFlashWrite }; # define FLASH_STOP_SEC_FLASH_DRIVER_HEADER # include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_19.1 */這個結構體包含了當前驅動的版本信息以及flash驅動的函數指針。這個flash_header指向的是0x20005E00的位置。
打開SBL的可執行文件如下:(內存范圍 0x20005E00~0x20005E16)
同時打開打開map文件,查看接口函數的地址:
可以發現:
0x20005E004~0x20005E007 存放的是ExpFlashDeinit的函數的地址: 20 00 5f 25
0x20005E008~0x20005E00b?存放的是ExpFlashInit的函數的地址:? 20 00 5e b9
0x20005E00c~0x20005E00f?存放的是ExpFlashErase的函數的地址:20 00 5f 6d
0x20005E010~0x20005E014?存放的是ExpFlashWrite的函數的地址:20 00 5f c9
在bootloader程序中:
通過以flash_code的地址為基地址加上偏移量,就可以找到存儲函數地址的地址。
/*可以看到MAP文件里的函數的地址的數值與hex文件里的數據對比,hex里函數的地址是在MAP文件對應函數地址的值的基礎上加1,而不是相等?*/
這是因為本芯片采用Thumb-2指令,如果指令讀取20 00 5e b9的內容,實際上讀取20 00 5e b8 的內容。
typedef void (* tFlashFct)( tFlashParam *fp );/************************************************************************************************************************ MACROS**********************************************************************************************************************/ /* macros to call flash driver functions in flashCode buffer ----------------*/ #define FLASH_DRIVER_WRITE(flashCode, fp) \((tFlashFct)(*(tFlashUint32 *)&(flashCode)[16]))(fp) /* PRQA S 3453 */ /* MD_MSR_19.7 *//* Flash erase function --------------------------------------------*/ #define FLASH_DRIVER_ERASE(flashCode, fp) \((tFlashFct)(*(tFlashUint32 *)&(flashCode)[12]))(fp) /* PRQA S 3453 */ /* MD_MSR_19.7 *//* Flash init function ---------------------------------------------*/ #define FLASH_DRIVER_INIT(flashCode, fp) \((tFlashFct)(*(tFlashUint32 *)&(flashCode)[4]))(fp) /* PRQA S 3453 */ /* MD_MSR_19.7 *//* Flash deinitialization function ---------------------------------*/ #define FLASH_DRIVER_DEINIT(flashCode, fp) \((tFlashFct)(*(tFlashUint32 *)&(flashCode)[8]))(fp) /* PRQA S 3453 */ /* MD_MSR_19.7 */根據不同的flash使用手冊,有如下需要根據flash手冊進行確認:
1? 底層單次寫入flash的數據長度,S32k144單次只能寫入8字節。
/* Minimum number of bytes that have to be programmed at a time */
#define FLASH_SEGMENT_SIZE ? ? ? ? ? ? ? ? ? ? ?0x08ul
flash接口函數ExpFlashWrite傳遞的刷寫數據的大小必須是8的整數倍。
2? flash單次擦除falsh的數據長度是0x1000
# ?define FLASH_SECTOR_SIZE ? ? ? ? ? ? ? ? ? ? 0x1000u
flash接口ExpFlashErase傳遞擦除的數據大小是必須是0x1000的整數倍。
常用FLASH擦寫規則
- 最小擦除單位:扇區
- 可選擇擦除單位:扇區、塊、全片
- 最小編程(寫入)單位:頁( 256 Byte),大于256 Byte則需要循環寫入。
- 未寫入時FLASH里面的數據為全1,即0xFF。
(reference:FLASH知識及讀寫擦除規則 - CodeAntenna)
總結
以上是生活随笔為你收集整理的SBL(Falsh驱动程序)在bootloader中的应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 元气森林“被薅羊毛”,损失200多万?我
- 下一篇: 论坛开张了,欢迎大家来搞