Flash存储映射
GR5525封装了一个采用XQSPI总线接口的可擦除外部Flash存储器。该Flash物理上由若干个4 KB大小的Flash扇区(Sector)组成;逻辑上可根据不同的应用场景,划分为不同用途的存储区域。
图 5为GR5525典型应用场景的Flash存储布局。
- System Configuration Area(SCA):系统配置区,主要用于存储系统启动参数等配置信息。
- User App:Application Firmware存储区域,主要用于存储应用固件。
- Unused Space:空闲区域,开发者可以自行使用该区域。例如,在DFU升级过程中,使用Unused Space临时存储新的Application Firmware。
- Non-volatile Data Storage(NVDS):非易失性数据存储区域。
NVDS缺省占用Flash的最后两个Sector。开发者也可以根据产品的Flash存储布局,合理配置NVDS的起始地址与所占用的Flash Sector数,具体配置方法参考配置custom_config.h。
NVDS起始地址需与Flash Sector的起始地址对齐。
SCA
系统配置区(SCA)占用Flash的前两个Sector(共8 KB,0x0020_0000 ~ 0x0020_2000),其主要存储系统启动过程使用的标志以及其他系统配置参数。
下载固件时,下载算法或GProgrammer会根据Application Firmware中的BUILD_IN_APP_INFO结构体生成SCA Image,并将其与应用固件一并烧写至Flash中(Image_Info被存放在SCA中)。系统启动时Bootloader根据SCA区域中的启动信息进行校验,校验通过后再跳转至固件的入口地址。
BUILD_IN_APP_INFO的定义和配置如下:
该结构体位于SDK_Folder\platform\soc\common\gr_platform.c,其中SDK_Folder为SDK的根目录。
const APP_INFO_t BUILD_IN_APP_INFO __attribute__((section(".app_info"))) =
#endif
{
.app_pattern = APP_INFO_PATTERN_VALUE,
.app_info_version = APP_INFO_VERSION,
.chip_ver = CHIP_VER,
.load_addr = APP_CODE_LOAD_ADDR,
.run_addr = APP_CODE_RUN_ADDR,
.app_info_sum = CHECK_SUM,
.check_img = BOOT_CHECK_IMAGE,
.boot_delay = BOOT_LONG_TIME,
.sec_cfg = SECURITY_CFG_VAL,
#ifdef APP_INFO_COMMENTS
.comments = APP_INFO_COMMENTS,
#endif
};
- app_pattern:固定值0x47525858。
- app_info_version:固件信息版本,与APP_INFO_VERSION对应。
- chip_ver:固件对应的芯片版本,与custom_config.h中的CHIP_VER对应。
- load_addr:固件存储地址,与custom_config.h中的APP_CODE_LOAD_ADDR对应。
- run_addr:固件运行地址,与custom_config.h中的APP_CODE_RUN_ADDR对应。
- app_info_sum:固件信息的校验和,由CHECK_SUM宏自动计算。
- check_img:系统启动配置参数,与custom_config.h中的BOOT_CHECK_IMAGE对应。当此参数配置为“1”时,启动时Bootloader会对固件进行校验。
- boot_delay:启动配置参数,与custom_config.h中的BOOT_LONG_TIME对应。当此参数配置为“1”时,系统冷启动时将增加1 秒延时。
- sec_cfg:安全配置参数,保留值。
- comments:固件描述信息,最大长度为12 字节。
System Configuration Area布局如下图所示。
- Boot_Info与Boot_Info Backup存储相同信息,Boot_Info Backup为Boot_Info的备份。
- 在非安全模式下,Bootloader会默认从Boot_Info中获取启动信息。
- 在安全模式下,Bootloader会先校验Boot_Info,如果Boot_Info校验不过,则会校验Boot_Info Backup,并从Boot_Info Backup中获取启动信息。
- Boot_Info(32B)区域中存储固件启动信息。系统启动时,Bootloader会根据启动信息进行校验,校验通过后跳转至固件的入口地址。
- Boot Config:系统启动配置信息。
- SPI Access Mode:SPI访问方式配置。为系统固定配置,用户无法修改。
- Run Addr:固件运行地址,与BUILD_IN_APP_INFO中的run_addr对应。
- Load Addr:固件存储地址,与BUILD_IN_APP_INFO中的load_addr对应。
- CheckSum:固件校验和,生成固件后,由下载算法自动计算。
- APP Size:固件的Size信息,生成固件后,由下载算法自动计算。
- Img_Info区域可存储至多10个固件信息。当使用GProgrammer下载固件或使用DFU升级固件时,固件信息会被存储至Img_Info区域。
- Comments:固件描述信息,最大长度为12个字符。生成固件后,下载算法使用固件文件名作为Comments信息。
- Boot Info(24B):固件启动信息,与Boot_Info(32B)的低24 Bytes数据相同。
- Version:固件版本信息,与custom_config.h中VERSION对应。
- Pattern:固定值0x4744。
- DFU Config Info区域存储ROM中DFU模块的配置信息。
- UART Info:DFU模块的UART串口相关配置,包括状态位、波特率、GPIO配置等。
- ADV Name Info:DFU模块的广播相关配置,包括状态位、广播名、广播长度。
- NVDS Init Info:DFU模块的NVDS系统的初始化配置,包括状态位、NVDS区域大小、起始地址。
- DFU Disable Cmd Info:DFU模块的DFU禁用命令配置,包括状态位和Disable DFU Cmd(2B,设置格式为Bitmask),可通过设置Disable DFU Cmd值来禁用某些DFU命令。
- HMAC区域存储HMAC校验值。该区域仅在安全模式下有效。
NVDS
NVDS是一个轻量级逻辑数据存储系统,它依赖于Flash硬件抽象层(Flash HAL)。其存储于Flash中,掉电时数据不会丢失。NVDS默认占用Flash最后两个Sector,也可由开发者自行设定占用的Flash Sector数。在NVDS区域中,最后一个扇区用于碎片整理,其余扇区用于数据存储。
NVDS系统适合存储小块数据,例如应用程序的配置参数、校准数据、状态和用户信息等。Bluetooth LE协议栈也会使用NVDS存储设备绑定等参数。
NVDS系统具有以下特性:
- 每个存储项(TAG)具有唯一的标识TAG ID。用户程序可以根据TAG ID对数据内容进行读取和更改操作,而无需关心数据存储的物理地址。
- 针对Flash存储介质的特性进行了优化,支持数据校验、Word对齐、碎片整理和擦写平衡。
- 存储区域的大小和起始地址可配置,Flash存储区以Sector为单位,一个Sector的大小为4 KB,NVDS存储区域可配置为若干个Sector;配置的起始地址需按4 KB对齐。
- 开发者可在custom_config.h文件中添加宏NVDS_START_ADDR和更改宏NVDS_NUM_SECTOR,配置NVDS区域的起始地址和占用大小。
-
Bluetooth LE 协议栈与Application共享相同的NVDS存储区域,但TAG ID命名空间被划分为不同类别,开发者只能使用分配给Application的TAG ID命名类别。
- Application必须使用NV_TAG_APP(idx)获取应用程序数据的TAG ID。该TAG ID被用作NVDS API的参数。
- Application不能将idx直接作为NVDS API的参数。idx取值范围是0x4000 ~ 0x7FFF。
-
在Application第一次运行前,开发者可使用工具GProgrammar将 Bluetooth LE 协议栈和Application所使用的TAG ID初始值写入到NVDS。
-
若开发者不使用GR5525 SDK缺省的NVDS区域,而需自行指定NVDS区域,则必须确保GProgrammar中配置的NVDS起始地址配置按4 KB对齐。
NVDS存储数据的格式如图 7所示:
数据头(Data Header)格式如表 2所示:
Byte | Name | Description |
---|---|---|
0-1 | tag | 数据的tag标识 |
2-3 | len | 数据的长度 |
4-4 | checksum | 数据头的校验和 |
5-5 | value_cs | 数据的校验和 |
6-7 | reserved | 保留字段 |
GR5525 SDK提供了下列NVDS API,可方便开发者操作Flash中的非易失性数据。
函数原型 | 描述 |
---|---|
uint8_t nvds_init(uint32_t start_addr, uint8_t sectors) |
初始化NVDS使用的Flash Sector。 |
uint8_t nvds_get(NvdsTag_t tag, uint16_t *p_len, uint8_t *p_buf) |
从NVDS中读取tag标识对应的数据。 |
uint8_t nvds_put(NvdsTag_t tag, uint16_t len, const uint8_t *p_buf) |
将数据写入到NVDS并使用tag标识。若为首次写数据,则需创建一个tag标识。 |
uint8_t nvds_del(NvdsTag_t tag) |
删除NVDS中tag标识对应的数据。 |
uint16_t nvds_tag_length(NvdsTag_t tag) |
获取指定Tag标识的数据长度。 |
uint8_t nvds_drv_func_replace(nvds_drv_func_t *p_nvds_drv_func) | 替代直接操作Flash的相关API。 |
uint8_t nvds_func_replace(nvds_func_t *p_nvds_func) | 替代NVDS操作相关API。 |
void nvds_retention_size(uint8_t bond_dev_num) | 为设备绑定信息预留空间,且空间大小由设备绑定数决定。 |
关于NVDS API的详细说明,可参考NVDS头文件SDK_Folder\components\sdk\gr55xx_nvds.h。