[转载]S3C2410对Nand flash读操作的分析----仔细读下会有新理解的

原文地址http://blog.csdn.net/ling1874/archive/2009/12/16/5


      前几天大致分析了u-boot针对smdk2410的源码,了解了启动的流程,但是对板上许多硬件的驱动过程还不太清楚。smdk2410源码中有针对Nor Flash的初始化和读取,但源码中没有对Nand Flash的操作,虽然针对其他型号的板子应该有Nand的源码,但方便起见,我查阅了vivi的源码,它支持从Nand Flash启动,自然有我需要的东西。下面我就自己的分析和总结列出来,中间当然也从google上得到不少前人留下的宝贵资料:)。

我先摘录一段对NorNand flash区别的几条总结:
    NOR flash采用位读写,因为它具有sram的接口,有足够的引脚来寻址,可以很容易的存取其内部的每一个字节
    NAND flash使用复杂的I/O口来串行地存取数据。8个引脚用来传送控制、地址和数据信息(复用)。NAND读和写单位为512Byte的页,擦写单位为32页的块
    ● NOR的读速度比NAND稍快一些。
    ● NAND的写入速度比NOR快很多。 
    ● NAND4ms擦除速度远比NOR5s快。
    ● 大多数写入操作需要先进行擦除操作。
    ● NAND的擦除单元更小,相应的擦除电路更少。
    NOR器件上运行代码不需要任何的软件支持,在NAND器件上进行同样操作时,通常需要驱动程序,也就是内存技术驱动程序(MTD)NANDNOR器件在进行写入和擦除操作时都需要MTD

再来看看Nand flash自身的特点(部分摘自August0703的文章):
     Nand Flash
的数据是以bit的方式保存在memory cell中,一般来说,一个cell 中只能存储一个bit。这些cell 8个或者16个为单位,连成bit line,形成所谓的byte(x8)/word(x16)这就是NAND Device的位宽
    
多个line(多个位宽大小的数据)会再组成Page。我使用的Nand flash是三星的K9F1208U0M,从datesheet上得知,此flash每页528Bytes512byteMain Area + 16byteSpare Area),每32page形成一个Block(32*528B)。具体一片flash上有多少个Block视需要所定。我所使用的k9f1208U0M具有4096block,故总容量为4096*32*528B=66MB,但是其中的2MBSpaer Area)是用来保存ECC校验码等额外数据的,故实际中可使用的为64MB
    Nand flash
以页(512Byte)为单位读写数据,而以块(16KB)为单位擦除数据。按照这样的组织方式可以形成所谓的三类地址: 
    ● Column Address
:列地址,地址的低8
    ● Page Address 
:页地址
    ● Block Address 
:块地址
    
对于NAND Flash来讲,地址命令只能在I/O[7:0]上传递,数据宽度也是8,这导致在读写指定地址的数据时,地址是分4次传递的(3次右移),见后文。
    s3c2410
这个处理器之所以可以直接从Nand flash启动,是因为CPU内置了4KB的片内SRAM,手册上称作“Steppingstone”。板子上电复位之后,CPU会自动将Nand flash的前4KB代码拷贝到片内SRAM中去执行(此过程是靠硬件实现的,见datasheetFigure 6-1. NAND Flash Controller Block Diagram),这也是导致从NorNand启动后的内存映射不同的原因。所以,vivistage1代码head.S必须要小于4KB,其中实现基本的CPU初始化等工作,并且要实现把自身拷贝到SDRAM中,之后的stage2就实现复杂功能。
    
关于SDRAM的初始化,之前分析u-boot时虽然涉及,但那篇没有仔细分析,我将另外归纳一篇。

下面具体看一下如何读写这块Nand flash
    
s3c2410datasheet上得知,Nand flash的操作通过NFCONFNFCMDNFADDRNFDATANFSTATNFECC这六个寄存器来完成,并且列出操作Nand flash4个步骤:

NAND FLASH MODE CONFIGURATION
1. Set NAND flash configuration by NFCONF register.
2. Write NAND flash command onto NFCMD register.
3. Write NAND flash address onto NFADDR register.
4. Read/Write data while checking NAND flash status by NFSTAT register. R/nBsignal should be checked before read operation or after program operation.

    下面结合vivi源码来详细的分析具体如何操作这6个寄存器来完成以上4个步骤来完成读过程:
先要初始化Nand flash,紧接着复位一下:

void reset_nand()
{
    int i=0;
    NFCONF &= ~0x800;    /* 现在真正使用Nand flash,bit[11]要置0,与初始化时相反 */
        for(; i<10; i++);
    NFCMD = 0xff;    //reset command

/* 复位命令。NFCMD寄存器只用到低8位(bit[7:0])。
K9F1208U0M手册中列出了针对此块flash的各种命令,见Table 1. Command Sets。vivi/include/mtd/nand.h更直观的列出了各种命令 */

    wait_idle();
}

/* 初始化NAND Flash */
/* NFCONF设定为0xf830,作用是使能Nand flash控制器、初始化ECC、Nand flash片选信号nFCE=1(inactive,真正使用时再让它等于0)、设置TACLS、TWRPH0、TWRPH1。
TACLS、 TWRPH0、TWRPH1这三个参数是控制Nand flash信号线CLE/ALE和写控制信号nWE的时序关系的,要参照具体的flash芯片手册来设置。我这个是K9F1208U0M ,在表“AC Timing Characteristics for Command / Address / Data Input”中可以看到: 
CLE setup Time = 0 ns,CLE Hold Time = 10 ns, 
ALE setup Time = 0 ns,ALE Hold Time = 10 ns, 
WE Pulse Width = 25 ns 
可 以计算,即使在HCLK=100MHz的情况下,TACLS+TWRPH0+TWRPH1=6/100 uS=60 ns,也是可以满足NAND Flash K9F1208U0M的时序要求的。(此句摘自thisway.diy@163.com的文章。关于如何配置时序,以后我得好好学习一下,还自诩电子出 身,丢人啊。。。)*/
 
void init_nand()
{
    NFCONF = 0xf830;
    reset_nand();
}

    初始化Nand flash之后,就可以把stage2main函数代码拷贝到SDRAM中去执行,当然之前已经配置好了SDRAM。以上工作都是在stage1阶段(片内SRAM中)完成的,之后就可以读写Nand flash了。
    
下面分析读操作的实现,贴上vivi/s3c2410/nand_read.c源码:

#include <config.h>

#define __REGb(x)    (*(volatile unsigned char *)(x))
#define __REGi(x)    (*(volatile unsigned int *)(x))
#define NF_BASE        0x4e000000
#define NFCONF        __REGi(NF_BASE + 0x0)
#define NFCMD        __REGb(NF_BASE + 0x4)
#define NFADDR        __REGb(NF_BASE + 0x8)
#define NFDATA        __REGb(NF_BASE + 0xc)
#define NFSTAT        __REGb(NF_BASE + 0x10)

#define BUSY 1
inline void wait_idle(void) {
    int i;

/* NFSTAT:只用到位0,0-busy,1-ready */
    while(!(NFSTAT & BUSY))
      for(i=0; i<10; i++);
}

#define NAND_SECTOR_SIZE    512            /* Nand flash是以512Byte为单位来读写的 */
#define NAND_BLOCK_MASK        (NAND_SECTOR_SIZE - 1)

/* low level nand read function */
/* 下面的读过程严格按照2410手册上的顺序 */
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;

    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return -1;    /* invalid alignment */
    }

/* chip Enable */
/* 对应第一条:1. Set NAND flash configuration by NFCONF register. */
    NFCONF &= ~0x800;
    for(i=0; i<10; i++);

    for(i=start_addr; i < (start_addr + size);) {
      /* READ0 */
/* 对应第二条:2. Write NAND flash command onto NFCMD register. */
      NFCMD = 0;

      /* Write Address */
/* 对应第三条:3. Write NAND flash address onto NFADDR register. 
*NFADDR寄存器也只用到低八位来传输,所以需要分4次来写入一个完整的32位地址,需要注意后3次的移位操作
*/

      NFADDR = i & 0xff;
      NFADDR = (>> 9) & 0xff;
      NFADDR = (>> 17) & 0xff;
      NFADDR = (>> 25) & 0xff;

/* 对应第四条:4. Read/Write data while checking NAND flash status by NFSTAT register. 
一个地址对应512个字节数据。所以,由于8bit位宽的限制,每次读取8位(1个字节),共读512次得到1页512Byte数据
*/

      wait_idle();
      for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
        *buf = (NFDATA & 0xff);
        buf++;
      }
    }

/* chip Disable */
/* 读写完毕需要禁止Nand flash ,与开始相对应*/
    NFCONF |= 0x800;    /* chip disable */

    return 0;
}


    以上是对
Nand flash读操作的分析。总体来看,关键在于根据CPUFlashdatasheet配置各寄存器和按照规定顺序进行操作。具体的配置过程是比较繁杂的,可参照u-bootvivi中对各种硬件支持的源码来配置,可省不少事。以后若自己尝试写bootloader,再实践一下作为练习吧。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NAND flash memory is widely used in electronic devices such as smartphones, tablets, and solid-state drives (SSDs). During the reading process, errors can occur due to various factors such as noise and interference. To improve the reliability of data reading, NAND flash memory controllers implement two techniques: re-read and read retry. Re-read is a technique where the memory controller reads the same data multiple times and compares the results to detect errors. If the results are inconsistent, the controller will perform another read operation until it gets a consistent result. Re-read is a simple and effective technique to detect and correct errors. Read retry is a more advanced technique that involves adjusting the read parameters of the memory controller based on the characteristics of the NAND flash memory. Read parameters such as read voltage and read latency can be adjusted to improve the reliability of data reading. Read retry requires more complex algorithms and can improve the performance of the NAND flash memory in high-noise environments. In summary, re-read and read retry are two techniques used by NAND flash memory controllers to improve the reliability of data reading. Re-read is a simple and effective technique that reads the same data multiple times and compares the results to detect errors. Read retry is a more advanced technique that adjusts the read parameters of the memory controller based on the characteristics of the NAND flash memory to improve the reliability of data reading.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值