RT thread 之 Nand flash 读写过程分析

文章目录


前言:什么是Nand Flash?

NAND Flash 是一种常见的闪存存储器类型,广泛应用于各种电子设备中,如手机、平板电脑、嵌入式系统等。它是一种非易失性存储器,可以持久地保存数据即使在断电情况下。

NAND Flash 与传统的 NOR Flash 相比具有较高的存储密度和较低的成本,但其随机访问速度较慢。它使用了一种称为 NAND 门的逻辑结构,使得数据存储和读取操作更加高效。

NAND Flash 存储器被组织为多个块(Block),每个块又由多个页(Page)组成。每个页通常包含一个数据区域和一个擦除区域,数据区域用于存储实际的用户数据,擦除区域用于擦除整个块。

NAND Flash 的基本操作包括读取、写入和擦除。读取操作通过指定页地址和偏移量来获取存储在特定位置的数据。写入操作将数据写入指定的页地址和偏移量。擦除操作会将整个块的数据擦除,使其变为可写状态。

在嵌入式系统中,使用 NAND Flash 存储器通常需要通过驱动程序与操作系统进行交互。驱动程序负责管理 NAND Flash 的读取、写入和擦除操作,并提供文件系统层面的接口供应用程序使用。

总的来说,NAND Flash 是一种常见的闪存存储器,具有高存储密度和低成本的优势。它在各种电子设备中广泛应用,并通过驱动程序与操作系统进行交互,提供数据存储和读取功能。

1、Nand Flash 读取步骤

NAND Flash 的读取步骤通常包括以下几个关键步骤:

  1. 选择芯片(Chip Select):如果系统中同时连接了多个 NAND Flash 芯片,首先需要选择要读取的芯片。这通常通过将芯片的片选引脚(CE)置为逻辑低电平来实现。

  2. 发送读取命令:向 NAND Flash 发送读取命令,以指示要读取的页地址和偏移量。读取命令通常是通过将命令字节序列发送到 NAND Flash 的命令/地址总线上实现的。

  3. 等待就绪状态:发送读取命令后,需要等待 NAND Flash 进入就绪状态,表示它已准备好进行读取操作。可以通过检查状态寄存器或等待足够的时间来实现等待。

  4. 读取数据:一旦 NAND Flash 进入就绪状态,就可以开始读取数据。读取的数据通常通过数据总线传输,并存储到指定的缓冲区中。

  5. 解码和处理数据:读取的数据可能需要进行解码和处理,以还原原始的用户数据。这通常涉及到 ECC(错误检测和纠正)算法,用于检测和纠正可能存在的位错误。

  6. 取消芯片选择:读取操作完成后,需要取消对芯片的选择,以释放总线资源。通常通过将芯片的片选引脚(CE)置为逻辑高电平来实现。

需要注意的是,具体的 NAND Flash 读取步骤可能会因芯片厂商和控制器的不同而有所差异。因此,在实际应用中,需要参考 NAND Flash 芯片的规格手册和相关的驱动程序文档,以了解具体的读取流程和命令序列。

  1. 从主存中读到Cache
  2. 从Cache读取数据

2、从主存读到Cache

2.1 在标准spi接口下读取过程

发送Page Read to Cache command(13H)

发送page地址 24位

检查寄存器位OIP,读取flash状态,等待主存读cache操作完成

读取hwecc位,判断是否超过ecc纠错的最大限度

c 复制代码
rt_err_t spinand_read_dataload(struct rt_spi_device *spi,  uint8_t u8Addr2, uint8_t u8Addr1, uint8_t u8Addr0)
{
    rt_err_t result = RT_EOK;
    uint8_t au8Cmd[4] = {CMD_PAGE_READ_TO_CACHE, u8Addr2, u8Addr1, u8Addr0};
    uint8_t u8SR;


    if ((result = rt_spi_send(spi, &au8Cmd[0], sizeof(au8Cmd))) == 0)
        goto exit_spinand_read_dataload;

    if (spinand_isbusy(spi))
    {
        result = -RT_EIO;
        goto exit_spinand_read_dataload;
    }

    u8SR = spinand_hwecc_status_get(spi);
    if ((u8SR != 0x00) && (u8SR != 0x01))
    {
        result = -RT_MTD_EECC;
        LOG_E("Error ECC status error[0x%x].", u8SR);
    }

exit_spinand_read_dataload:

    return result > 0 ? RT_EOK : -RT_ERROR;
}

2.2 测试时序(SPI频率30MHz)

  1. 发送读取指令和地址:
  2. 检查寄存器位OIP,读取flash状态,等待主存读cache操作完成
  3. OIP位至0,主存读cache操作完成
  4. 整个过程消耗时间

3.从Cache读取数据

3.1在标准spi接口读取过程

复制代码
发送Read From Cache command(03H)
发送page地址 24位
发送数据
c 复制代码
	rt_err_t spinand_normal_read(struct rt_spi_device *spi, uint8_t u8AddrH, uint8_t u8AddrL, uint8_t *pu8Buff, uint32_t u32Count)
	{
	    uint8_t au8Cmd[4] = {CMD_READ_FROM_CACHE, u8AddrH, u8AddrL, DUMMY_BYTE};
	
	    return rt_spi_send_then_recv(spi, &au8Cmd[0], sizeof(au8Cmd), pu8Buff, u32Count);
}

测试时序

发送读取指令和地址:

相关推荐
NaZiMeKiY8 分钟前
HTML5前端第二章节
前端·html·html5
天若有情67311 分钟前
深入浅出:HTML 中 <a> 标签嵌入链接教程
前端·html
烂蜻蜓12 分钟前
HTML 样式之 CSS 全面解析
前端·css·html
冬冬小圆帽13 分钟前
Webpack 优化深度解析:从构建性能到输出优化的全面指南
前端·webpack·node.js
Tiger Z38 分钟前
R 语言科研绘图 --- 密度图-汇总
开发语言·程序人生·r语言·贴图
叶雅茗1 小时前
PHP语言的区块链扩展性
开发语言·后端·golang
双叶8362 小时前
(C语言)写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和(递归函数)
c语言·开发语言·数据结构·算法·游戏
大龄大专大前端2 小时前
JavaScript闭包的认识/应用/原理
前端·javascript·ecmascript 6
字节源流2 小时前
【SpringMVC】常用注解:@SessionAttributes
java·服务器·前端
肥肠可耐的西西公主2 小时前
前端(vue)学习笔记(CLASS 4):组件组成部分与通信
前端·vue.js·学习