# 驱动概述 - NAND 作为廉价的存储介质,在大文件的存储场景中占有重要的地位,由此在嵌入式方案中,如何将此驱动做稳定做易用,尤为重要。NAND 控制器驱动具有以下特性: 1. 支持模式 Toggle 介质模式 2. 支持模式时序配置 ,同步模式,异步模式 3. 支持请求之间时间间隔 4. 采用dma 数据方式进行传输 5. 支持时序模式下的高频时钟采样相位调节 6. 支持硬件ECC纠错 当前NAND 驱动控制器主要为用户提供了以下功能接口: 1. NAND 控制器状态初始化函数 2. NAND 介质扫描接口 3. NAND 介质page读/写接口,块擦除接口,spare space 读写接口 4. 中断相关接口 5. 坏块管理接口 ## 驱动功能 驱动组成由以下所示 : . ├── fnand_bbm.c ├── fnand_bbm.h ├── fnand.c ├── fnand_dma.c ├── fnand_dma.h ├── fnand_ecc.c ├── fnand_ecc.h ├── fnand_g.c ├── fnand.h ├── fnand_hw.c ├── fnand_hw.h ├── fnand_intr.c ├── fnand_option.c ├── fnand_sinit.c ├── fnand_timing.c ├── fnand_timing.h ├── fnand_toggle.c └── fnand_toggle.h 其中fnand.h 为用户开发者主要使用接口,提供了以下功能: 1. Nand 控制器初始化接口 2. 根据Nand 介质id 初始化介质页/块的大小 3. Nand 控制器相关状态位的回调函数注册 4. Nand 控制器中断处理函数 5. Nand 坏块管理函数 ## 数据结构 ```c typedef struct _FNand { u32 is_ready; /* Device is ininitialized and ready*/ FNandConfig config; u32 work_mode; /* NAND controler work mode */ /* nand flash info */ FNandInterMode inter_mode[FNAND_CONNECT_MAX_NUM]; /* NAND controler timing work mode */ FNandTimingMode timing_mode[FNAND_CONNECT_MAX_NUM]; u32 nand_flash_interface[FNAND_CONNECT_MAX_NUM] ; /* Nand Flash Interface , followed by FNAND_ONFI_MODE \ FNAND_TOGGLE_MODE*/ struct FNandDmaBuffer dma_data_buffer; /* DMA data buffer */ struct FNandDmaBuffer descriptor_buffer; /* DMA descriptor */ struct FNandDmaDescriptor descriptor[2]; /* DMA descriptor */ struct FNandSdrTimings sdr_timing; /* SDR NAND chip timings */ /* bbm */ FNandBadBlockManager bbt_manager[FNAND_CONNECT_MAX_NUM]; /* bad block manager handler */ /* nand detect */ FNandNandGeometry nand_geometry[FNAND_CONNECT_MAX_NUM]; /* nand flash infomation */ /* dma 页操作 */ FnandIrqEventHandler irq_event_fun_p; /* Interrupt event response function */ void *irq_args; FNandOperationWaitIrqCallback wait_irq_fun_p; /* The NAND controller operates the wait function */ void *wait_args; /* operations */ FNandTransferP write_p ; /* Write page function */ FNandTransferP read_p ; /* Read page function */ FNandTransferP write_oob_p ; /* Write page spare space function */ FNandTransferP read_oob_p ; /* Read page spare space function */ FNandTransferP write_hw_ecc_p ; /* Write page with hardware function */ FNandTransferP read_hw_ecc_p ; /* Read page with hardware function */ FNandEraseP erase_p; /* Erase block function */ } FNand; ``` ## 错误码定义 ``` FNAND_ERR_OPERATION /* NAND 控制器操作NAND flash 失败 */ FNAND_ERR_INVAILD_PARAMETER /* 当NAND 控制器配置信息不存在 */ FNAND_IS_BUSY /* NAND 控制器操作NAND flash ,控制器正忙 */ FNAND_OP_TIMEOUT /* NAND 控制器操作超时*/ FNAND_VALUE_ERROR /* NAND 控制器在进行BBM 搜索过程时,获取坏块管理信息不匹配 */ FNAND_VALUE_FAILURE /* 获取的数据与预期不相符合 */ FNAND_NOT_FET_TOGGLE_MODE /* toggle 模式 */ FNAND_ERR_READ_ECC /* 读取过程中,进行硬件ecc ,错误超过纠错的范围 */ FNAND_ERR_IRQ_OP_FAILED /* 中断进行读/写/擦操作时,回调函数反馈错误 */ FNAND_ERR_IRQ_LACK_OF_CALLBACK /* 中断进行读/写/擦操作时,缺少回调函数 */ FNAND_ERR_IRQ_OP_FAILED /* 等待中断回应失败 */ FNAND_ERR_NOT_MATCH /* 进行flash id 检测时,检测结果与预期不符合 */ ``` ## 应用例程 - baremetal/example/peripheral/nand/nand_test ## API 介绍 ### 1. FNandLookupConfig ``` FNandConfig *FNandLookupConfig(u32 instance_id) ``` #### 介绍 - 获取当前FNand驱动默认配置 #### 参数 - u32 instance_id :当前Nand驱动中对应的ID #### 返回 FGicConfig * :静态默认配置 ### 2. FNandCfgInitialize ``` FError FNandCfgInitialize(FNand *instance_p,FNandConfig *config_p) ``` #### 介绍 - 根据传入配置,初始化NAND驱动实例 #### 参数 - FNand *instance_p FNand 控制器实例的指针 - FNandConfig * 需要应用于示例中的配置项 #### 返回 - FError :FT_SUCCESS 为初始成功 ### 3. FNandScan ``` FError FNandScan(FNand *instance_p) ``` #### 介绍 - Nand flash 扫描,此接口调用之后会自动扫描Nand flash 介质信息 #### 参数 - FNand *instance_p FNand 控制器实例的指针 #### 返回 - FError :FT_SUCCESS 为初始成功 ### 4. FNandWritePage ``` FError FNandWritePage(FNand *instance_p,u32 page_addr,u8 *buffer,u32 page_copy_offset ,u32 length,u8 *oob_buffer,u32 oob_copy_offset,u32 oob_length,u32 chip_addr) ``` #### 介绍 - 每次写一个页面的操作,包括写页面数据和空闲数据 ,默认会进行硬件ecc 编码写入 #### 参数 - FNand *instance_p FNand 控制器实例的指针 - u32 page_addr 页操作地址,单位为页 - u8 *buffer 指向写入内容缓冲区的指针 - u32 page_copy_offset 写入某一页中的具体位置,当此参数非0 时,写入的地址为 ,在page_addr 对应的页面下,0 + page_copy_offset 开始的地址,未覆盖的地方默认填入0xff - u32 length 数据写入页面下的长度 - u8 *oob_buffer 指向写入spare space内容 缓冲区的指针 - u32 oob_copy_offset 写入某一页中spare space 的具体位置,当此参数非0 时,在page_addr 对应的页面下,写入的地址为 页长度 + page_copy_offset 开始的地址,未覆盖的地方默认填入0xff - u32 oob_length spare space数据写入页面下的长度 - u32 chip_addr 芯片地址 #### 返回 - FError :FT_SUCCESS 为写入成功 ### 5. FNandWritePageRaw ``` FError FNandWritePageRaw(FNand *instance_p,u32 page_addr,u8 *buffer,u32 page_copy_offset ,u32 length,u8 *oob_buffer,u32 oob_copy_offset,u32 oob_length,u32 chip_addr) ``` #### 介绍 - 每次写一个页面的操作,包括写页面数据和空闲数据 ,默认不会进行硬件ecc 编码写入 #### 参数 - FNand *instance_p FNand 控制器实例的指针 - u32 page_addr 页操作地址,单位为页 - u8 *buffer 指向写入内容缓冲区的指针 - u32 page_copy_offset 写入某一页中的具体位置,当此参数非0 时,写入的地址为 ,在page_addr 对应的页面下,0 + page_copy_offset 开始的地址,未覆盖的地方默认填入0xff - u32 length 数据写入页面下的长度 - u8 *oob_buffer 指向写入spare space内容 缓冲区的指针 - u32 oob_copy_offset 写入某一页中spare space 的具体位置,当此参数非0 时,在page_addr 对应的页面下,写入的地址为 页长度 + page_copy_offset 开始的地址,未覆盖的地方默认填入0xff - u32 oob_length spare space数据写入页面下的长度 - u32 chip_addr 芯片地址 #### 返回 - FError :FT_SUCCESS 为写入成功 ### 6. FNandReadPage ``` FError FNandReadPage(FNand *instance_p,u32 page_addr,u8 *buffer,u32 page_copy_offset,u32 length,u8 *oob_buffer,u32 oob_copy_offset,u32 oob_length,u32 chip_addr) ``` #### 介绍 - 每次读出一个页面的操作,包括读页面数据和空闲数据 ,默认会进行ecc 纠错 #### 参数 ``` FNand *instance_p FNand 控制器实例的指针 u32 page_addr 页操作地址,单位为页 u8 *buffer 指向读出内容缓冲区的指针 u32 page_copy_offset 读出某一页中的具体位置,当此参数非0 时,读出的地址为 ,在page_addr 对应的页面下 0 + page_copy_offset 开始的地址 u32 length 数据读出页面下的长度 u8 *oob_buffer 指向读出spare space内容 缓冲区的指针 u32 oob_copy_offset 读出某一页中spare space 的具体位置,当此参数非0 时,在page_addr 对应的页面下,读出的地址为 页长度 + page_copy_offset 开始的地址 u32 oob_length spare space数据读出的长度 u32 chip_addr 芯片地址 ``` #### 返回 - FError :FT_SUCCESS 为读出成功 ### 7. FNandReadPageRaw ``` FError FNandReadPageRaw(FNand *instance_p,u32 page_addr,u8 *buffer,u32 page_copy_offset,u32 length,u8 *oob_buffer,u32 oob_copy_offset,u32 oob_length,u32 chip_addr) ``` #### 介绍 - 每次读出一个页面的操作,包括读页面数据和空闲数据 ,不会进行ecc 纠错 #### 参数 ``` FNand *instance_p FNand 控制器实例的指针 u32 page_addr 页操作地址,单位为页 u8 *buffer 指向读出内容缓冲区的指针 u32 page_copy_offset 读出某一页中的具体位置,当此参数非0 时,读出的地址为 ,在page_addr 对应的页面下 0 + page_copy_offset 开始的地址 u32 length 数据读出页面下的长度 u8 *oob_buffer 指向读出spare space内容 缓冲区的指针 u32 oob_copy_offset 读出某一页中spare space 的具体位置,当此参数非0 时,在page_addr 对应的页面下,读出的地址为 页长度 + page_copy_offset 开始的地址 u32 oob_length spare space数据读出的长度 u32 chip_addr 芯片地址 ``` #### 返回 - FError :FT_SUCCESS 为读出成功 ### 8. FNandEraseBlock ``` FError FNandEraseBlock(FNand *instance_p, u32 block, u32 chip_addr) ``` #### 介绍 - 擦除块数据 #### 参数 FNand *instance_p FNand 控制器实例的指针 u32 block 块的位置号 u32 chip_addr 芯片地址 #### 返回 - FError :FT_SUCCESS 为写入成功 ### 9. FNandReadPageOOb ``` FError FNandReadPageOOb(FNand *instance_p,u32 page_addr,u8 *oob_buffer,u32 oob_copy_offset,u32 oob_length,u32 chip_addr) ``` #### 介绍 - 读取每一页中的 spare space 内容 #### 参数 - FNand *instance_p FNand 控制器实例的指针 - u32 page_addr 需要读取空闲空间的Row Address - u8 * oob_buffer 指向读取数据的缓冲区 - u32 oob_copy_offset 读出某一页中spare space 中位置的偏移,当此参数非0 时,读出的地址为 ,在page_addr 对应的页面下 page length + oob_copy_offset 开始的地址 - u32 oob_length 需要读取是页面中spare space 中的长度 - u32 chip_addr 芯片地址 #### 返回 - FError :FT_SUCCESS 为写入成功 ### 10. FNandWritePageOOb ``` FError FNandWritePageOOb(FNand *instance_p,u32 page_addr,u8 *oob_buffer,u32 page_copy_offset,u32 oob_length,u32 chip_addr) ``` #### 介绍 - 读取每一页中的 spare space 内容 #### 参数 - FNand *instance_p FNand 控制器实例的指针 - u32 page_addr 需要写入空闲空间的Row Address - u8 * oob_buffer 指向写入数据的缓冲区 - u32 oob_copy_offset 写入某一页中spare space 中位置的偏移,当此参数非0时,写入的地址为 ,在page_addr 对应的页面下 page length + oob_copy_offset 开始的地址 - u32 oob_length 需要写入是页面中spare space 中的长度 - u32 chip_addr 芯片地址 #### 返回 - FError :FT_SUCCESS 为写入成功 ### 11. FNandSetIsrHandler ``` void FNandSetIsrHandler(FNand *instance_p, FnandIrqEventHandler event_p, void *irq_args) ``` #### 介绍 - 初始化中断事件回调函数 #### 参数 - FNand *instance_p FNand 控制器实例的指针 - FnandIrqEventHandler event_p 中断事件回调函数 - void *irq_args 回调函数传入参数 #### 返回 无 ### 12. FNandIrqHandler ``` void FNandIrqHandler(s32 vector, void *param) ``` #### 介绍 - Nand 控制器中断响应函数 #### 参数 - s32 vector 中断ID - void * param 中断传入参数 #### 返回 - 无 ### 13. FNandInitBbtDesc ``` void FNandInitBbtDesc(FNand *instance_p) ``` #### 介绍 - 坏块表初始化 #### 参数 - FNand *instance_p FNand 控制器实例的指针 #### 返回 - 无 ### 10. FNandScanBbt ``` FError FNandScanBbt(FNand *instance_p, u32 target_addr) ``` #### 介绍 - 在Nand flash中扫描具体目标地址的坏块表 #### 参数 - FNand *instance_p FNand 控制器实例的指针 - u32 chip_addr 芯片地址 #### 返回 - FError :FT_SUCCESS 为扫描成功 ### 11. FNandIsBlockBad ``` FError FNandIsBlockBad(FNand *instance_p, u32 block, u32 target_addr) ``` #### 介绍 - 检查当前块是否为坏块 #### 参数 - FNand *instance_p FNand 控制器实例的指针 - u32 block 需要检查的块ID号 - u32 chip_addr 芯片地址 #### 返回 - FError :FT_SUCCESS 为当前块为坏块 ### 12. FNandOperationWaitIrqRegister ``` void FNandOperationWaitIrqRegister(FNand *instance_p,FNandOperationWaitIrqCallback wait_irq_fun_p ,void *wait_args) ``` #### 参数 - FNand *instance_p FNand 控制器实例的指针 - FNandOperationWaitIrqCallback 用户使用读/写/擦接口过程中,等待中断完成的回调函数接口 ,用户的回调函数,驱动以FT_SUCCESS 作为成功判断,否则为失败 - void *wait_args 用户需要传入至回调函数中的参数 ### 返回 无 ### 13. FNandSetOption - 依据options 选项参数,配置对应参数 ```c FError FNandSetOption(FNand *instance_p,u32 options,u32 value) ``` #### 参数 - FNand *instance_p FNand 控制器实例的指针 - u32 option 具体配置项 - u32 value 配置项中对应的参数