Flash

Flash作为一种非易失性存储器,与RAM不同。RAM可以直接读写,直接执行代码或存储数据。而flash的写入操作只能在空的或已擦除的单元内进行。因此,在执行flash写访问之前常常需要先执行擦除访问。

备注

Flash具有最高100,000次的编程次数限制,如果频繁对某个区块擦写,将容易产生坏块。当用户需要利用flash存储数据时,Flash驱动程序的接口并不首推给APP使用,更建议使用 FTL 接口。

Flash布局

RTL87x2G集成flexible memory controller(FMC),支持外挂SPI Flash。FMC支持最大的地址映射空间为64M bytes,对应地址空间0x04000000 ~ 0x07FFFFFF。

Flash布局分两级来设置,包括High Level Flash map和OTA Bank map,具体见: 调整Flash布局

High Level Flash Map

RTL87x2G SDK中,High Level Flash Map由11部分组成,包括Reserved,OEM Header(即config file的存储空间),Bank0 Boot Patch,Bank1 Boot Patch,OTA Bank 0,OTA Bank 1,Bank0 Secure APP(optional),Bank1 Secure APP(optional),OTA Tmp,FTL和APP Defined Section。Flash布局 说明如下。

../../../../_images/High_Level_Flash_Map.png

High Level Flash Map

Flash段说明

内存段

起始地址

大小

作用

Reserved

0x00400000

0x1000

系统保留区域

OEM Header

0x00401000

0x1000

config信息存储区域,包括蓝牙地址,AES Key,和用户可修改的Flash布局等

Bank0 Boot Patch

可变

(由eFuse决定)

可变

(由eFuse决定)

Flash boot loader,Bank0 Boot Patch和Bank1 Boot Patch作用相同,互为备份区

Bank1 Boot Patch

可变

(由eFuse决定)

可变

(由eFuse决定)

Flash boot loader

OTA Bank0

可变

(由eFuse决定)

可变

(由eFuse决定)

存储数据和代码运行,进一步细分为OTA Header,System Patch,BT Stack Patch,BT Host,APP,APP Data1,APP Data2,APP Data3,APP Data4,APP Data5,APP Data6。如果选择不切换bank的OTA方案,OTA_TMP区用作OTA备份区;相反,如果选择切换bank的OTA方案,OTA bank0和OTA bank1作用相同,互为备份区

OTA Bank1

可变

(由eFuse决定)

可变

(由eFuse决定)

选择切换bank的OTA方案时才存在,假设OTA Bank0为运行区,则OTA Bank1为备份区

相反,如果OTA Bank1为运行区,则OTA Bank0为备份区,其大小必须和OTA Bank0一致

Bank0 Secure APP

可变

(由eFuse决定)

可变

(由eFuse决定)

TrustZone enable下才需要,Secure APP中开启TrustZone,Bank0 Secure APP 和Bank1 Secure APP作用相同,互为备份区

Bank1 Secure APP

可变

(由eFuse决定)

可变

(由eFuse决定)

TrustZone enable下才需要

OTA TMP

可变

(由eFuse决定)

可变

(由eFuse决定)

不切换bank方式下,作为OTA备份区使用,大小必须不小于OTA bank0最大的image大小

FTL

可变

(由eFuse决定)

可变

(由eFuse决定)

该区域空间支持以逻辑地址访问flash,用户可以以最小4bytes为单位读写flash

APP Defined Section

可变

(由eFuse决定)

可变

(由eFuse决定)

Flash剩余未划分区域,用户可以自由使用,但不可以进行OTA升级

OTA Bank Map

RTL87x2G SDK中,OTA Bank中包括12种类型的image,分别是OTA Header,System Patch,BT Stack Patch,BT Host,APP,APP Config File, APP Data1,APP Data2,APP Data3,APP Data4,APP Data5,APP Data6。OTA Bank这一级的布局是由其中的OTA header决定,通过Flashmap Generate Tool可以生成不同OTA Bank布局的OTA header。

../../../../_images/OTA_Bank_layout.png

OTA Bank布局

OTA Bank各image说明

内存段

起始地址

大小

作用

OTAHeader

由OEM header决定

4KB

存储OTA header的版本信息、Bank中各image的起始地址和大小

System Patch

由OTA header决定

可变

对non-secure rom中系统的优化和扩展代码

BT Stack Patch

由OTA header决定

可变

蓝牙controller协议栈优化和扩展代码

BT Host

由OTA header决定

可变

实现HCI及以上蓝牙协议栈部分代码

APP

由OTA header决定

可变

开发方案的运行代码

App Config File

由OTA header决定

可变

App配置信息

App Data1

由OTA header决定

可变

开发方案中需要升级的数据区

App Data2

由OTA header决定

可变

开发方案中需要升级的数据区

App Data3

由OTA header决定

可变

开发方案中需要升级的数据区

App Data4

由OTA header决定

可变

开发方案中需要升级的数据区

App Data5

由OTA header决定

可变

开发方案中需要升级的数据区

App Data6

由OTA header决定

可变

开发方案中需要升级的数据区

调整Flash布局

Flash布局设置分为两级,其中High Level Flash map是由config文件决定,而OTA Bank map是由OTA Header文件决定。用户可通过MPTool中 Config Set 选项加载自定义的flash布局文件并生成config文件。

../../../../_images/MPTool_config.png

通过MPTool生成config文件

为方便用户使用,Realtek提供Flashmap Generate Tool用于生成flash布局文件(flash map.iniflash_map.h )。flash map.ini 文件可以导入到MP Tool,用于生成config file和OTA header。而 flash_map.h 文件则需要拷贝到APP的工程目录下,编译出正确可运行的APP image。

../../../../_images/FlashMapGenerateTool.png

FlashMapGenerateTool配置Flash Map

但与此同时,必须遵从以下的原则来调整flash布局。

  1. 如果选择支持bank切换的OTA方案,保证OTA bank0的大小等于OTA bank1的大小,并且将OTA TMP区域的大小设置为0。

  2. 如果选择支持bank切换的OTA方案,可以使用不同的OTA bank布局来生成Bank0 OTA Header file和Bank1 OTA Header file,但是OTA bank0和bank1大小不可变,并且不小于OTA bank内各个image大小的总和。

  3. 如果选择不支持bank切换的OTA方案,将OTA bank1的大小设置为0,OTA tmp区域的大小不小于OTA bank0中最大的image的大小。

  4. 原始的APP Data bin文件需要经过RTL87x2G SDK中提供的App Data tool处理之后才可以通过MPTool烧录和MPPackTool打包。该工具路径在sdk/tools/AppData,处理之后会添加一个满足特定格式的1280Byte的image header。注意,OTA bank内的APP Data1、APP Data2、APP Data3、APP Data4、APP Data5或APP Data6区域是存储需要进行OTA的App Data。如果数据无需升级,应当放在“APP Defined Section”区域。

  5. 为了将所有的code区域都上锁,以防止非预期的flash写入和擦除操作,尽可能地将OTA bank1结束地址相对于flash起始地址的偏移对齐到实际所选用的flash所支持的某个保护级别对应的范围,如64KB、128KB、256KB、512KB等。

  6. 因为存放在OTA bank内的APP Data1、APP Data2、APP Data3、APP Data4、APP Data5或APP Data6区域的数据是有可能落在flash上锁范围内的,所以该区域内一般是存储只读的数据。如需存储要改写的数据应该放在“APP Defined Section”区域。

Flash布局示例

基于上文所述的调整flash布局的规则,本节提供不切bank方案切bank方案下的Flash布局示例。

不切bank方案Flash布局示例

不切bank方案flash总大小为1MB的示例布局

flash总大小为1MB的示例布局

大小(字节)

起始地址

Reserved

4K

0x04000000

OEM Header

4K

0x04001000

Bank0 Boot Patch

32K

0x04002000

Bank1 Boot Patch

32K

0x0400A000

OTA Bank0

612K

0x04012000

  • OTA Header

4K

0x04012000

  • System Patch code

32K

0x04013000

  • BT Stack Patch code

60K

0x0401B000

  • BT Host code

212K

0x0402A000

  • APP code

304K

0x0405F000

  • APP Config File

4K

0x040AC000

  • APP data1

0K

0x040AD000

  • APP data2

0K

0x040AD000

  • APP data3

0K

0x040AD000

  • APP data4

0K

0x040AD000

  • APP data5

0K

0x040AD000

  • APP data6

0K

0x040AD000

OTA Bank1(等于0)

0K

0x040AD000

Bank0 Secure APP code

0K

0x040AD000

Bank0 Secure APP Data

0K

0x040AD000

Bank1 Secure APP code

0K

0x040AD000

Bank1 Secure APP Data

0K

0x040AD000

OTA Temp

312K

0x040AD000

FTL

16K

0x040FB000

APP Defined Section

4K

0x040FF000

切bank方案Flash布局示例

切bank方案flash总大小为2MB的示例布局

flash总大小为2MB的示例布局

大小(字节)

起始地址

Reserved

4K

0x04000000

OEM Header

4K

0x04001000

Bank0 Boot Patch

32K

0x04002000

Bank1 Boot Patch

32K

0x0400A000

OTA Bank0

596K

0x04012000

  • OTA Header

4K

0x04012000

  • System Patch code

32K

0x04013000

  • BT Stack Patch code

60K

0x0401B000

  • BT Host code

212K

0x0402A000

  • APP code

284K

0x0405F000

  • APP Config File

4K

0x040A6000

  • APP data1

0K

0x040A7000

  • APP data2

0K

0x040A7000

  • APP data3

0K

0x040A7000

  • APP data4

0K

0x040A7000

  • APP data5

0K

0x040A7000

  • APP data6

0K

0x040A7000

OTA Bank1

596K

0x040A7000

  • OTA Header

4K

0x040A7000

  • System Patch code

32K

0x040A8000

  • BT Stack Patch code

60K

0x040B0000

  • BT Host code

212K

0x040BF000

  • APP code

284K

0x040F4000

  • APP Config File

4K

0x0413B000

  • APP data1

0K

0x0413C000

  • APP data2

0K

0x0413C000

  • APP data3

0K

0x0413C000

  • APP data4

0K

0x0413C000

  • APP data5

0K

0x0413C000

  • APP data6

0K

0x0413C000

Bank0 Secure APP code

0K

0x0413C000

Bank0 Secure APP Data

0K

0x0413C000

Bank1 Secure APP code

0K

0x0413C000

Bank1 Secure APP Data

0K

0x0413C000

OTA Temp

32K

0x0413C000

FTL

16K

0x04148000

APP Defined Section

736K

0x040FF000

FTL

FTL(Flash Translation Layer)是基于flash driver实现的软件抽象层,用于用户读写flash数据。FTL物理空间的位置可以查看 flash 布局。FTL的目的是简化对flash中数据的修改过程。

如果不使用FTL,在用户需要修改flash上的数据时,需要先擦除flash。频繁修改flash时,会在擦除上浪费大量时间。而FTL用逻辑地址代替物理地址来访问flash,在用户进行数据修改时,原先的数据不会被直接修改,而是将新的数据会写入新的物理地址,并且逻辑地址会指向该物理地址。在这种方式下,可以避免频繁擦除flash,节约修改数据所需时间。

当FTL检测到没有足够的空间写入新记录时,会触发垃圾回收(GC,Garbage Collection)机制,对过期或不再被使用的记录进行擦除和回收。FTL由于循环使用flash空间、均匀分布擦写操作,可以避免某些块过早失效,达到磨损均衡的效果。

目前,FTL支持v1和v2版本。v1版本包含上述功能的完整实现。在v1的基础上,v2版本在最大存储空间和flash利用率方面进行了改进,并且支持创建“module”划分逻辑空间。

备注

  • FTL适用于需要频繁改写的数据,一方面API接口更为简单,另一方面有助于延长flash使用寿命(磨损均衡)。

  • 如果数据量较大、只读(或偶尔改写)、不需要支持OTA升级,推荐使用flash API将数据存储在“APP Defined Section”区域。

  • 如果数据量较大、只读(或偶尔改写)、需要支持OTA升级,推荐将数据存储在OTA bank内的App Data1、App Data2、App Data3、App Data4、App Data5、App Data6和secure app data区域。

FTL v1

SDK v1.2.0及以前版本默认支持FTL v1,在后续SDK版本如需使用FTL v1,请参考以下步骤:

  1. 打开SDK根目录。

  2. 拷贝 ftl_v1\ftl.hbsp\sdk_lib\inc\,替换目标路径下已有 ftl.h 文件。

  3. 如果使用 GCC 编译,将 ftl_v1\librtl87x2g_sdk.a 拷贝到 bsp\sdk_lib\lib\rtl87x2g\gcc\,替换目标路径下已有 librtl87x2g_sdk.a 文件。

  4. 如果使用 MDK 编译,将 ftl_v1\rtl87x2g_sdk.lib 拷贝到 bsp\sdk_lib\lib\rtl87x2g\mdk\,替换目标路径下已有 rtl87x2g_sdk.lib 文件。

  5. 重新编译APP工程。

FTL空间的功能划分

FTL空间按照其功能划分为以下两块存储空间,以默认设置的FTL物理空间大小为16K为例。

  1. BT存储空间

    1. 逻辑地址范围 [0x0000, 0x0D00),但是这部分空间的大小可通过otp_config.h参数调整。(当前SDK暂时未支持)

    2. 用于存储BT信息,例如设备地址,link key等。

    3. 详细请参考 LE Host

  2. APP存储空间

    1. 逻辑地址范围 [0x0D00, 0x17F0)。

    2. 用于存储APP的信息。

    3. 可用以下API读/写APP存储的数据

    uint32_t ftl_save(void *pdata, uint16_t offset, uint16_t size);
    uint32_t ftl_load(void *pdata, uint16_t offset, uint16_t size);
    

    备注

    ftl_save API和ftl_load API在实现上已对传入的offset参数加上APP存储空间的偏移0x0D00,因此,APP使用这两个API时offset参数从0开始规划即可。

调整FTL空间的大小

FTL的物理空间大小是可配置的,通过修改config文件的配置参数来调整(更多Flash布局调整相关内容,请参考 调整Flash布局)。操作步骤如下:

  1. 首先利用Flashmap Generate Tool(随MPTool一起发布)来生成 flash map.iniflash_map.h 文件。

  2. flash_map.h 文件拷贝到APP工程目录下,例如: sdk\samples\bluetooth\ble_peripheral,这样APP编译的时候可以获取正确的加载地址。

  3. 将第一步生成的 flash map.ini 加载到MPTool中生成config文件用于烧录,如下图示例,调整FTL的物理空间到32K。

../../../../_images/Modify_flash_map.png

修改 flash map 配置文件

备注

  1. 当调整FTL物理空间大小时,APP可使用的最大逻辑空间也会对应改变。假设实际FTL的物理空间大小设置的mK(m是4的整数倍),对应APP可使用的最大逻辑空间等于((511*(m-4) - 4) - 3328) bytes。

  2. 为了提升FTL读取的效率,底层做了一套物理地址和逻辑地址的映射机制,这个映射表会占用一定的RAM空间。在默认设置FTL物理空间大小为16K情况下,这个映射表占用2298byte的RAM HEAP空间。假设实际FTL的物理空间大小设置的mK(m是4的整数倍),其映射表占用的RAM空间等于((511 * (m-4) - 4) * 0.375) bytes。

  3. 用户在调整FTL空间大小需要依据具体的应用场景来合理调整,如果调至过大将会浪费一部分RAM资源。另一方面,如果对于选用的比较小的flash并且想压缩FTL的占用的空间,必须保证FTL的物理空间不比12K小。由于映射表中每个逻辑地址对应的物理地址默认使用12个bit来表示,FTL的物理空间最大可以调整到32K。

FTL v2

SDK v1.3.0及以后版本默认使用FTL v2。FTL v2延续了v1的基本功能,并且在以下方面进行优化升级:

  1. 扩大映射表单元,每个逻辑地址对应的物理地址使用16个bit来表示(v1使用12个bit),可以支持更大的存储空间。

  2. 新增通过“module”划分逻辑空间的功能。

    1. 每个FTL module在创建时都可以独立设置block_len。合理选择“module”的block_len参数,能够减少辅助信息的空间占用而获得更高的Flash利用率。

    2. “module”之间逻辑空间相互独立,每个“module”的逻辑地址都从0地址开始,有助于上层应用组织和管理数据。

FTL空间的功能划分

FTL初始化时自动创建“系统module”,用于保证FTL基础功能和存储BT信息,用户可创建新的module以存储用户数据。

  1. 系统module

    1. 逻辑地址范围 [0x0000, 0x0C00),占用物理空间6144 bytes,但这部分空间的大小可通过otp_config.h参数调整。(当前SDK暂时未支持)

    2. [0x0000, 0x0A20) 用于存储BT信息,例如设备地址,link key等,详细请参考 LE Host

    3. [0xA20, 0x0C00) 用于存储FTL module info等。

  2. 用户module

    1. 支持用户创建最多6个module,在创建新的module前,需要确保FTL物理空间充足,请参考 调整FTL空间的大小

    2. 用于存储APP的信息。

FTL APIs

int32_t ftl_init_module(char *module_name, uint16_t malloc_size, uint8_t block_len);
int32_t ftl_save_to_module(char *module_name, void *pdata, uint16_t offset, uint16_t size);
int32_t ftl_load_from_module(char *module_name, void *pdata, uint16_t offset, uint16_t size);

备注

  • ftl_init_module的block_len参数决定module的最小可访问逻辑空间,需要对齐4bytes。根据实际存储数据单元的大小,尽可能选用较大的block_len能够减少RAM空间占用并获得更高的flash利用率(减少了辅助信息占用的空间)。

  • ftl_save_to_module/ftl_load_from_module的offset参数为存储/读取数据的逻辑地址,需要与block_len对齐。

ftl_init_module API用于创建FTL module,ftl_save_to_module/ftl_load_from_module API用于向module写入数据/从module读取数据。在创建新的FTL module之前,请确保FTL物理空间充足,详见 调整FTL空间的大小

基础示例如下:

#define EXT_FTL_NAME "TEST_FTL"
#define EXT_FTL_LOGIC_SIZE     (0x1000)
#define EXT_FTL_BLOCK_SIZE     (64)
void ftl_ext_module_demo(void)
{
    // Init an ext FTL module
    ftl_init_module(EXT_FTL_NAME, EXT_FTL_LOGIC_SIZE, EXT_FTL_BLOCK_SIZE);
    // Save data
    uint8_t data_buf[EXT_FTL_BLOCK_SIZE];
    memset(data_buf, 0x5A, EXT_FTL_BLOCK_SIZE);
    uint16_t test_offset = 0x800;
    uint32_t ret = ftl_save_to_module(EXT_FTL_NAME, data_buf, test_offset, EXT_FTL_BLOCK_SIZE);
    if (ret != ESUCCESS)
    {
        //save data error
        return;
    }
    //Load data
    uint8_t read_buf[EXT_FTL_BLOCK_SIZE];
    ret = ftl_load_from_module(EXT_FTL_NAME, read_buf, test_offset, EXT_FTL_BLOCK_SIZE);
    if (ret != ESUCCESS)
    {
        //load data error
        return;
    }
}

调整FTL空间的大小

调整FTL物理空间方法与FTL v1一致,请参考 调整FTL空间的大小

进行调整时,需要保证FTL module可用物理空间满足需求,否则module将创建失败,计算方法如下:

../../../../_images/FTLv2_flash_calculation_cn.png

FTLv2物理空间计算

此外,为提升FTL读取效率,在创建module时会为其建立映射表,用于实现逻辑地址和物理地址的转换。FTL module的映射表占用RAM空间: (malloc_size / block_len * 2Bytes) 。

备注

由于FTL需要预留空间用于“系统module”和GC机制,并且FTL物理空间大小与4KB对齐,所以如果选用较小的flash并且需要压缩FTL占用的空间,必须保证FTL物理空间不小于16KB。(FTL预留空间可通过otp_config.h参数调整,当前SDK暂时未支持)

Flash API

如果FTL无法满足需求而必须使用flash driver,请调用下文中介绍的flash 操作。

读操作

函数名

flash_nor_read_locked

函数原型

FLASH_NOR_RET_TYPE flash_nor_read_locked(uint32_t addr, uint8_t *data, uint32_t len)

功能描述

读取flash数据

输入参数

addr:flash读取地址

data:读出数据的存储buffer,注意buffer的地址不能在flash上

len: 读取的数据长度

返回值

若读取成功

通过十进制查看返回值为24(对应FLASH_NOR_RET_SUCCESS)

先决条件

写操作

函数名

flash_nor_write_locked

函数原型

FLASH_NOR_RET_TYPE flash_nor_write_locked(uint32_t addr, uint8_t *data, uint32_t len)

功能描述

写数据到flash

输入参数

addr:flash写入地址

data:写入数据的存储buffer,注意buffer的地址不能在flash上

len: 写入的数据长度

返回值

若写入成功

通过十进制查看返回值为24(对应FLASH_NOR_RET_SUCCESS)

先决条件

擦除操作

函数名

flash_nor_erase_locked

函数原型

FLASH_NOR_RET_TYPE flash_nor_erase_locked(uint32_t addr, FLASH_NOR_ERASE_MODE mode)

功能描述

擦除flash

输入参数

addr:flash擦除地址

FLASH_NOR_ERASE_MODE:flash擦除类型

返回值

若擦除成功

通过十进制查看返回值为24(对应FLASH_NOR_RET_SUCCESS)

先决条件

flash_nor_erase_locked() 支持三种擦除类型(FLASH_NOR_ERASE_MODE)

  1. 擦除Sector(4K-Byte) (FLASH_NOR_ERASE_SECTOR)

  2. 擦除Block(64K-byte) (FLASH_NOR_ERASE_BLOCK)

  3. 擦除chip(flash整片擦除) (FLASH_NOR_ERASE_CHIP)

备注

需要注意的是FLASH_NOR_ERASE_CHIP在一般应用中没有使用场景,因此整片擦除功能很少使用。

位模式

除了标准串行外围接口(SPI)之外,大多数flash模型还支持高性能的双位/四位模式I/O SPI,由以下六个引脚控制。

  1. 串行时钟 (CLK)

  2. 片选 (CS#)

  3. 串行数据IO0 (DI)

  4. 串行数据IO1 (DO)

  5. 串行数据IO2 (WP#)

  6. 串行数据IO3 (HOLD#)

三种位模式

单位模式

标准的SPI模式,也称为1位模式,只使用CLK,CS#,DI和DO。WP#作为写保护的输入,而HOLD#作为保持功能的输入。

双位模式

使用CLK,CS#,并将DI、DO分别用作IO0、IO1。WP#和HOLD#的功能和和单位模式中一致。

四位模式

使用CLK,CS#,并将DI、DO、WP#、HOLD#分别用作IO0、IO1、IO2、IO3。由于6根管脚全部被使用,所以四位模式下写保护和保持功能不可用。

备注

目前RTL87x2G支持SDR和DTR两种四位读取模式,用户如果需要使用相应的四位读取模式,应预先确认flash型号与特性。

位模式切换

RTL87x2G为支持更多flash型号,在启动时默认flash都是在1位模式。如果用户需要切换至高速位模式(2或4位模式),可调用SDK中提供的接口:flash_nor_try_high_speed_mode() 切换至高速位模式,并由参数“mode”配置flash尝试切换至的高位模式,如果切换失败将会切回1位模式。

SDK中提供的进行位模式切换的接口函数原型如下。

函数名

flash_nor_try_high_speed_mode

函数原型

FLASH_NOR_RET_TYPE flash_nor_try_high_speed_mode(FLASH_NOR_IDX_TYPE idx, FLASH_NOR_BIT_MODE mode)

功能描述

切换flash到不同的位模式

输入参数

idx:默认设置为FLASH_NOR_IDX_SPIC0

mode:切换的位模式(FLASH_NOR_1_BIT_MODE, FLASH_NOR_2_BIT_MODE, FLASH_NOR_4_BIT_MODE, FLASH_NOR_DTR_4_BIT_MODE)

返回值

若切换成功

通过十进制查看返回值为24(对应FLASH_NOR_RET_SUCCESS)

先决条件

软件块保护

Flash支持通过硬件保护管脚(#WP)来锁定整个flash以防止写入和擦除操作,但有以下两个缺点。

  1. 如果使用管脚#WP用作保护功能,就无法使用flash的四位模式。

  2. 硬件保护只能选择保护整颗flash或者全部不保护,不能保护部分flash空间。

RTL87x2G通过一个更为灵活的机制——软件块保护(Software Block Protect,BP)来防止意外的flash的擦写操作。其原理是利用flash状态寄存器中的一些BP位来选择要保护的范围。Flash使用状态寄存器中的BP(X)位来识别要锁定的块的数量,以及TB位来决定锁定的方向。RTL87x2G只支持从flash的低地址端开始上锁。

../../../../_images/Flash_Block_Protect.png

软件块保护

RTL87x2G默认是利用BP功能来保护一些重要的数据(如配置的参数)和代码段,而不是整个flash空间。

备注

需要注意的是,由于不同的Flash供应商和模型有不同的规则和限制,而且Flash状态寄存器默认使用NVRAM类型来保持数据,BP函数需要改变BP位来切换不同的保护级别,但是NVRAM有100K次编程限制。虽然大多数厂商支持使用0x50命令将Flash状态寄存器切换至SRAM类型,但也不是所有的flash厂商都支持,例如MXIC。那么,频繁访问状态寄存器将会损坏flash。

RTL87x2G所使用的flash不一定支持上图所示有比例的上锁方式(即0~1/2~1/4~…)。例如 GD25WD80C软件块保护,最小的上锁范围为768KB,不到二分之一,此时driver中只会支持将其设定为全部上锁或全部解锁。

../../../../_images/Flash_Block_Protect_For_GD25WD80C.png

GD25WD80C软件块保护

提供的进行BP设定的接口函数如下。

函数名

flash_nor_set_bp_lv_locked

函数原型

FLASH_NOR_RET_TYPE flash_nor_set_bp_lv_locked(FLASH_NOR_IDX_TYPE idx, uint8_t bp_lv)

功能描述

设置flash bp等级

输入参数

idx:默认设置为FLASH_NOR_IDX_SPIC0

bp_lv:设定的bp等级

返回值

若设定成功

通过十进制查看返回值为24(对应FLASH_NOR_RET_SUCCESS)

先决条件

函数名

flash_nor_get_bp_lv_locked

函数原型

FLASH_NOR_RET_TYPE flash_nor_get_bp_lv_locked(FLASH_NOR_IDX_TYPE idx, uint8_t *bp_lv)

功能描述

获取flash当前的bp等级

输入参数

idx:默认设置为FLASH_NOR_IDX_SPIC0

bp_lv:读出数据的存储buffer

返回值

若获取成功

通过十进制查看返回值为24(对应FLASH_NOR_RET_SUCCESS)

先决条件

省电

Flash的功耗模式主要分以下三种场景。

  • 工作模式:耗电一般在10 mA数量级

  • 待机模式:耗电一般在几十uA左右

  • Power Down模式:耗电更低,甚至低于1 uA

Flash在没有访问时会自动进入待机模式,当需要再访问时会自动进入工作状态。而要进入Power Down模式,需要使用特定的命令:大多数Flash使用命令0xB9控制其进入Power Down模式,使用命令0xAB退出Power Down模式,而MXIC是通过切换#CS引脚退出Power Down模式。

需要注意的是,Flash在进入Power Down模式之后,除了退出Power Down命令(0xAB)之外,接收其他的命令都是危险的。因为Flash在进入Power Down模式之后只接受唤醒命令退出Power Down模式,其他命令都将被忽略,但Flash控制器可能会进入无限循环等待Flash的响应。

为了防止滥用Flash Power Down模式带来的风险,系统的DLPS机制中已经加入Flash Power Down模式的控制:进入DLPS时自动下指令使Flash进入Power Down模式,在退出DLPS时唤醒Flash。

XIP

当所剩的RAM空间不够时,需要将部分或者全部APP代码放在flash上执行。RTL87x2G上执行XIP的相关配置总结如下。

  1. 宏FEATURE_RAM_CODE(mem_config.h中配置)
    a. 配置为1时,默认不加任何section修饰的代码都将在RAM上执行。
    b. 配置为0时,默认不加任何section修饰的代码都将在flash上执行。
  2. Section修饰(参考app_section.h)
    a. APP_FLASH_TEXT_SECTION:指定代码在flash上执行。
    b. APP_RAM_TEXT_SECTION:指定代码在RAM上执行。

    备注

    如果RAM空间不足,要优先将时间敏感的代码放在RAM上执行以保证效率。

  3. 提高XIP执行代码的效率的方式
    将flash切换至双位或者四位模式:调用 flash_nor_try_high_speed_mode()

RTL87x2G通过SPIC的支持可以使用自动模式去读取flash并且直接在SPI Flash上执行代码。但是用户有可能通过调用提供的接口在用户模式下对flash执行读写擦操作,而用户模式访问flash的操作不是原子性的,如果被另一个自动模式访问操作打断,就会造成flash访问异常。为保证用户模式访问flash操作的原子性,XIP时需要遵循以下的使用限制和注意事项。

备注

  • RTL87x2G中提供的用户模式访问flash的接口都带“_locked”后缀,默认加临界区保护,会关闭0和1优先级以下的中断,也就是中断优先级数值设置为2到7的中断(中断优先级数值越大,中断优先级越低)。如果flash操作的时间过久,比如一次写大量的数据,建议将一次写的动作拆分成多次少量数据写的动作,以避免关闭中断时间过长而丢中断。

  • 如果有时间非常关键的中断(中断优先级0和1的中断)需要处理,需要保证中断服务例程本身不能XIP,中断服务例程中也禁止访问flash。