1. NandFlash 读CACHE简介


    由于磁盘属于低速设备,磁盘的读写速度远远低于CPU,所以为了解决这种速度不匹配的问题,SylixOS提供了对应块设备的缓冲器。与此对应的,为了提高NandFlash的读速度,SylixOS也为NandFlash提供了一种读CACHE机制。为了不影响写平衡软件对坏块的管理,该缓冲机制在NandFlash写一个扇区时,将相关的扇区CACHE全部设为读不命中;当NandFlash擦除一个块时,将块内所有的扇区CACHE设为读不命中。


  2. 技术实现

    SylixOS中关于NandFlash读CACHE的内容主要在"libsylixos/SylixOS/fs/nandRCache"目录下,主要实现了读CACHE的创建、删除操作,以及节点的申请、释放操作。其中,读CACHE的创建函数接口如程序清单 2-1所示。

    程序清单 2-1CACHE创建函数

    #include 
    LW_API ULONG  API_NandRCacheCreate(PVOID              pvNandRCacheMem, 
                                       size_t             stMemSize,
                                       ULONG              ulPageSize,
                                       ULONG              ulSpareSize,
                                       ULONG              ulPagePerBlock,
                                       PLW_NRCACHE_CB    *ppnrcache);

    函数API_NandRCacheCreate原型分析:

  • 此函数成功返回ERROR_NONE,失败返回错误码;

  • 参数pvNandRCacheMem是缓存内存地址;

  • 参数stMemSize是缓存内存大小;

  • 参数ulPageSize是每个页面数据区大小;

  • 参数ulSpareSize是每个页面扩展区大小;

  • 参数ulPagePerBlock是每一块页面的个数;

  • 参数ppnrcache是需要返回的创建成功的控制块。

使用API_NandRCacheCreate函数创建CACHE成功时,最后一个入参将返回NandFlash的读CACHE控制块,该控制块的详细信息如程序清单 2-2所示。

程序清单 2-2CACHE管理控制块

   typedef struct {

    PLW_NRCACHE_NODE         NRCACHE_pnrcachenBuffer;                   /*  nand flash 所有的缓冲       */
    ULONG                    NRCACHE_ulPagePerBlock;                    /*  每一个块的页面个数          */
    ULONG                    NRCACHE_ulnCacheNode;                      /*  CACHE 中包含的节点个数      */
    INT                      NRCACHE_iHashSize;                         /*  hash 表大小                 */
    PLW_LIST_LINE           *NRCACHE_pplineHash;                        /*  搜索 hash 表                */
    PLW_LIST_RING            NRCACHE_pringLRU;                          /*  有效点中最近最少使用表      */
    PLW_LIST_LINE            NRCACHE_plineFree;                         /*  空闲表头                    */
} LW_NRCACHE_CB;
typedef LW_NRCACHE_CB       *PLW_NRCACHE_CB;                            /*  nand read cache 控制块      */


NandFlash的读CACHE创建过程主要包括开辟Hash表内存、开辟初始化控制块内存以及初始化每个节点内存使用情况。和块设备的DiskCACHE类似,NandFlash读CACHE以NODE节点管理CACHE缓存,每一个NODE节点都对应着一页缓存,NODE节点则以LRU(Least Recently Used)的方式组成循环链表,方便刷新脏节点。对于已经缓存的扇区,则通过HASH表与链表结合的方式进行快速索引。空闲的节点单独构成一个链表,方便节点的快速申请。


      管理CACHE缓存的NODE节点详细信息如程序清单 2-3所示。

程序清单 2-3 NODE节点控制块

typedef struct {
    LW_LIST_LINE             NRCACHEN_lineManage;                       /*  空闲链表 或 hash            */
    LW_LIST_RING             NRCACHEN_ringLRU;                          /*  LRU 链                      */
    ULONG                    NRCACHEN_ulChunkNo;                        /*  扇区号                      */
    caddr_t                  NRCACHEN_pcChunk;                          /*  数据区缓冲                  */
    caddr_t                  NRCACHEN_pcSpare;                          /*  扩展区缓冲                  */
} LW_NRCACHE_NODE;
typedef LW_NRCACHE_NODE     *PLW_NRCACHE_NODE;                          /*  缓冲节点                    */


对于NODE节点的操作主要包括申请、查找、释放等操作,其中节点申请函数接口如程序清单 2-4所示。

程序清单 2-4 CACHE节点申请函数

#include 
LW_API PLW_NRCACHE_NODE      API_NandRCacheNodeAlloc(PLW_NRCACHE_CB  pnrcache, ULONG  ulChunkNo);

      函数API_NandRCacheCreate原型分析:

  • 此函数成功返回NODE节点,失败返回LW_NULL

  • 参数pnrcache是CACHE控制块;

  • 参数ulChunkNo是需要缓存的扇区号。

函数API_NandRCacheCreate从空闲NODE池中获取节点时,若不存在空闲节点,则将从LRU表中淘汰一个最久未使用的节点。


获得指定扇区节点的函数接口如程序清单 2-5所示。

程序清单 2-5 CACHE节点查找函数

#include 
LW_API PLW_NRCACHE_NODE      API_NandRCacheNodeGet(PLW_NRCACHE_CB  pnrcache, ULONG  ulChunkNo);

  函数API_NandRCacheNodeGet原型分析:

  • 此函数成功返回节点控制块,失败返回LW_NULL

  • 参数pnrcache是CACHE控制块;

  • 参数ulChunkNo是需要缓存的扇区号。

当API_NandRCacheNodeGet函数在CACHE中命中时,会将此节点挂入LRU表的头部,这样最近使用的数据始终保持在链表头部。


将一个有效节点释放的函数接口如程序清单 2-6所示。

程序清单 2-6 CACHE节点释放函数

#include 
LW_API VOID    API_NandRCacheNodeFree(PLW_NRCACHE_CB  pnrcache, ULONG   ulChunkNo);

函数API_NandRCacheNodeFree原型分析:

  • 此函数成功返回;

  • 参数pnrcache是CACHE控制块;

  • 参数ulChunkNo是需要缓存的扇区号;


NandFlash的读CACHE删除操作的函数接口如程序清单 2-7所示。

程序清单 2-7CACHE删除函数

#include 
LW_API ULONG   API_NandRCacheDelete(PLW_NRCACHE_CB    pnrcache);

函数API_NandRCacheDelete原型分析:

  • 此函数成功ERROR_NONE,失败返回PX_ERROR

  • 参数pnrcache是CACHE控制块。

  1. 参考资料