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 = 652

RESERVED : ORIGIN = 0x00000400, LENGTH = 0x0C

OPTBYTES : ORIGIN = 0x0000040C, LENGTH = 0x48

FLASH : ORIGIN = 0x00000500, LENGTH = 0xF000

RAMCODE_FLASH : ORIGIN = 0x0000F500, LENGTH = 0x8B00

SIMFS_REGION : ORIGIN = 0x00018000, LENGTH = 0x2000

TPCFG : ORIGIN = 0x0001A000, LENGTH = 0x5000

OTPREGION : ORIGIN = 0x0001F000, LENGTH = 0x1000

APPL_VECT : ORIGIN = 0x00020000, LENGTH = 0x08

flash_bld_app : ORIGIN = 0x00020100, LENGTH = 0x100

flash_bld_dev : ORIGIN = 0x00020200, LENGTH = 0x100

RAM : ORIGIN = 0x1FFF8000, LENGTH = 0xE700

HEAP : ORIGIN = 0x20006700, LENGTH = 0x100

STACK : ORIGIN = 0x20006800, LENGTH = 0x800

magicflag : ORIGIN = 0x20005DF0, LENGTH = 0x10

flashcode : ORIGIN = 0x20005E00, LENGTH = 0x900

BSS : 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_code

IO_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.c

SBL驱动接口与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)