第 5 章 - Azure RTOS LevelX NOR 支持

NOR 闪存由块组成,这些块通常被平均分隔为 512 字节。 NOR 闪存中没有闪存页的概念。 另外,NOR 闪存中也没有备用字节,因此 Azure RTOS LevelX 必须对所有管理信息使用 NOR 闪存本身。 在 NOR 闪存中可以直接进行读取访问。 写入访问通常需要一系列特殊操作。 只要清除位,就可以多次写入 NOR 闪存。 通过擦除块操作,NOR 闪存中的位只能设置一次。

LevelX 将每个或 NOR 闪存块分割为 512 字节的逻辑扇区。 此外,LevelX 使用每个 NOR 闪存块的前“n”个扇区来存储管理信息。 LevelX NOR 闪存管理信息的格式如下所示:

LevelX NOR 块格式

字节偏移量 目录
0 [块擦除计数]
4 [最小映射扇区]
8 [最大映射扇区]
12 [可用扇区位图]
m [扇区 0 映射条目]
m+4*(n-1) [扇区“n”映射条目]
s [扇区 0 内容]
s+512*(n-1) [扇区“n”内容]

32 位块擦除计数包含块的擦除次数。 LevelX 的主要目标是使所有块的擦除计数相对接近,以帮助防止任何一个块过早耗尽。 仅当块中的所有逻辑扇区都已被映射并写入时,才会写入 32 位的最小映射扇区和最大映射扇区字段 。 这些字段有助于优化扇区读取操作。 “可用扇区位图”条目是一个位图,其中每个设置的位对应于块中未映射的扇区。 此字段用于提高可用扇区搜索的效率。 这是一个可变长度字段,该字段需要块中每 32 个扇区有一个字。 “扇区映射条目”数组包含块中每个扇区的映射信息。 每个条目均具有以下格式:

扇区映射条目

含义
31 有效标志。 如果逻辑扇区并非设置为全部扇区,表示映射有效
30 过时标志。 如果清除此项,表示该映射可能已过时或即将过时。
29 如果此位为 0,表示映射条目写入完成
0-28 映射到此物理扇区的逻辑扇区(并非全部扇区)。

32 位字段的高位(位 31)用于指示逻辑扇区映射有效。 如果此位为 0,则此条目中的信息(以及相应的扇区内容)将不再有效。 下一位(位 30)用于指示此扇区即将过时,将写入新的扇区。 位 29 用于指示映射条目写入完成的时间。 如果位 29 为 0,表示映射条目写入完成。 如果设置了位 29,表示映射条目正在写入过程中。 位 30 和 29 用于在更新新的扇区映射时从潜在断电中恢复。 最后,低 29 位 (28-0) 包含扇区的逻辑扇区号。 如果未映射扇区,则会设置所有位,也就是说,其值将为 0xFFFFFFFF。

NOR 驱动程序要求

LevelX 需要基础的 NOR 闪存驱动程序,该驱动程序特定于基础闪存部分和硬件实现。 在初始化期间,通过 API lx_nor_flash_open 将驱动程序指定给 LevelX。 LevelX 驱动程序的原型如下:

INT nor_driver_initialize(LX_NOR_FLASH *instance);

“instance”参数指定 LevelX NOR 控制块。 驱动程序初始化函数负责为关联的 LevelX 实例设置所有其他的驱动程序级服务。 每个 LevelX NOR 实例所需的服务如下:

  • 读取扇区
  • 写入扇区
  • 块擦除
  • 验证擦除的块
  • 系统错误处理程序

驱动程序初始化

这些服务是通过在驱动程序初始化函数内的 LX_NOR_FLASH 实例中设置函数指针来设置的。 驱动程序初始化函数还负责:

  1. 指定闪存的基址。
  2. 指定块总数和每个块的字词数。
  3. RAM 缓冲区,用于读取闪存的某一扇区(512 字节)并保持一致以获取 ULONG 访问。

在返回 LX_SUCCESS 之前,驱动程序初始化函数可能还执行其他特定于设备和/或实现的初始化任务。

驱动程序读取扇区

LevelX NOR 驱动程序“读取扇区”服务负责读取 NOR 闪存的特定块中的特定扇区。 所有错误检查和纠正逻辑都由驱动程序服务负责。 如果成功,LevelX NOR 驱动程序将返回 LX_SUCCESS。 如果失败,LevelX NOR 驱动程序将返回 LX_ERROR。 LevelX NOR 驱动程序“读取扇区”服务的原型如下:

INT nor_driver_read_sector(
    ULONG *flash_address,
    ULONG *destination, 
    ULONG words);

其中“flash_address”指定内存的 NOR 闪存块内某个逻辑扇区的地址,“destination”和“words”指定扇区内容的放置位置以及要读取的 32 位字的数量 。

驱动程序写入扇区

LevelX NOR 驱动程序“写入扇区”服务负责写入 NOR 闪存的块中的特定扇区。 所有错误检查都由驱动程序服务负责。 如果成功,LevelX NOR 驱动程序将返回 LX_SUCCESS。 如果失败,LevelX NOR 驱动程序将返回 LX_ERROR。 LevelX NOR 驱动程序“写入扇区”服务的原型如下:

INT nor_driver_write_sector(
    ULONG *flash_address,
    ULONG *source, 
    ULONG words);

其中“flash_address”指定内存的 NOR 闪存块内某个逻辑扇区的地址,“source”和“words”指定写入的源以及要写入的 32 位字的数量 。

注意

LevelX 依赖驱动程序来验证写入扇区是否已成功。 这通常通过读取回编程值来实现,以确保它与要写入的请求的值相匹配。

驱动程序块擦除

LevelX NOR 驱动程序“块擦除”服务负责擦除 NOR 闪存的指定块。 如果成功,LevelX NOR 驱动程序将返回 LX_SUCCESS。 如果失败,LevelX NOR 驱动程序将返回 LX_ERROR。 LevelX NOR 驱动程序“块擦除”服务的原型如下:

INT nor_driver_block_erase(ULONG block,  
    ULONG erase_count);

其中“block”标识要清除的 NOR 块。 出于诊断目的提供了参数“erase_count”。 例如,当擦除计数超过特定阈值时,驱动程序可能需要警告应用程序软件的另一部分。

注意

LevelX 依赖驱动程序检查块的所有字节,以确保将其擦除(包含所有字节)。

验证擦除的驱动程序块

LevelX NOR 驱动程序“验证擦除的块”服务负责验证 NOR 闪存的指定块是否被擦除。 如果已被擦除,LevelX NOR 驱动程序将返回 LX_SUCCESS。 如果未擦除该块,LevelX NOR 驱动程序将返回 LX_ERROR。 LevelX NOR 驱动程序“验证块擦除”服务的原型如下:

INT nor_driver_block_erased_verify(ULONG block);

其中“block”指定要验证是否被擦除的块。

注意

LevelX 依赖驱动程序检查指定块的所有字节,以确保将其擦除(包含所有字节)。

驱动程序系统错误

LevelX NOR 驱动程序“系统错误处理程序”服务负责设置 LevelX 检测到的处理系统错误。 此例程中的处理依赖于应用程序。 如果成功,LevelX NOR 驱动程序将返回 LX_SUCCESS。 如果失败,LevelX NOR 驱动程序将返回 LX_ERROR。 LevelX NOR 驱动程序“系统错误”服务的原型如下:

INT nor_driver_system_error(UINT error_code);

其中“error_code”表示发生的错误。

NOR 模拟驱动程序

LevelX 提供模拟的 NOR 闪存驱动程序,该驱动程序只使用 RAM 来模拟 NOR 闪存部件的操作。 默认情况下,NOR 模拟驱动程序提供 8 个 NOR 闪存块,每个块 16 个扇区,每扇区 512 字节。

模拟的 NOR 闪存驱动程序初始化函数为 lx_nor_flash_simulator_initialize,在 x_nor_flash_simulator.c 中定义。 此驱动程序还为编写特定的 NOR 闪存驱动程序提供了一个很好的模板。

NOR FileX 集成

如前文所述,LevelX 不依赖于 FileX 进行操作。 应用程序软件可以直接调用所有 LevelX API,以将原始数据存储/检索到 LevelX 提供的逻辑扇区。 但是,LevelX 也支持 FileX。

文件 fx_nor_flash_simulated_driver.c 包含用于 NOR 闪存模拟的示例 FileX 驱动程序。 LevelX 的 NOR 闪存 FileX 驱动程序为编写自定义 FileX 驱动程序提供了一个很好的起点。

注意

FileX NOR 闪存格式应该是小于 NOR 闪存提供的扇区的一个完整块大小。 这将有助于确保在损耗均衡处理期间获得最佳性能。 在 LevelX 损耗均衡算法中提高写入性能的其他技巧包含:

  1. 确保所有写入大小都恰好是一个或多个群集,并且在确切的群集边界上启动。
  2. 通过 API 的 FileX fx_file_allocate 类执行大文件写入操作之前,请先预分配群集
  3. 定期使用 lx_nor_flash_defragment 释放尽可能多的 NOR 块,从而提高写入性能
  4. 确保已启用 FileX 驱动程序以接收释放扇区信息,并通过调用 lx_nor_flash_sector_release 在驱动程序中处理对驱动程序发出的释放扇区的请求