精华内容
下载资源
问答
  • NandFlash控制器

    2012-10-31 21:42:11
    这是一个VHDL描述的NandFlash控制器
  • nandflash控制器

    2011-06-21 19:44:15
    nandflash控制器,里面包括3个大模块:nandflash读模块、nandflash写模块、nandflash擦除模块。
  • NAND Flash 控制器

    2019-07-15 08:15:00
    掌握通过 NAND Flash 控制器访问 NAND Flash 的方法 NAND Flash 介绍和 NAND Flash 控制器使用 NAND Flash 在嵌入式系统中的地位与 PC 上的硬盘类似,用于保存: 系统运行所必须的操作系统 应用程序 用户...

    目标:

    • 了解 NAND Flash 芯片的接口
    • 掌握通过 NAND Flash 控制器访问 NAND Flash 的方法

    NAND Flash 介绍和 NAND Flash 控制器使用

    NAND Flash 在嵌入式系统中的地位与 PC 上的硬盘类似,用于保存:

    • 系统运行所必须的操作系统
    • 应用程序
    • 用户数据
    • 运行过程中产生的各类数据

    Flash 介绍

    常用的 Flash 类型有 NOR Flash 和 NAND Flash 两种。

    两者的差别如下:

    NOR Flash 支持 XIP,即代码可以直接在 NOR Flash 上执行,无需复制到内存中。

    这是由于 NOR Flash 的接口与 RAM 完全相同,可以随机访问任意地址的数据。

    在 NOR Flash 上进行读操作的效率非常高,但是曹处和写操作的效率很低;另外,NOR Flash 的容量一般比较小。

    NAND Flash 进行擦除和写操作的效率更高,并且容量更大。

    一般而言,NOR Flash 用于存储程序,NAND Flash 用于存储数据。

    基于 NAND Flash 的设备通常也要搭配 NOR Flash 以存储程序。

     

    Flash 存储器件由 擦除单元(也成为块)组成,当要写入某个块时,需要确保这个块已经被擦除。

    NOR Flash 的块大小范围为 64KB~128KB;NAND Flash 的块大小范围为 8KB~64KB,擦/写一个 NOR Flash 块需要 4s,而擦写一个 NAND Flash 块仅需 2ms。

    NOR Flash 的块太大,不仅增加了擦写时间,而且对于给定的写操作,NOR Flash 也需要更多的擦除操作——特别是小文件,比如一个文件只有 1KB,但是为了保存它却需要擦除大小为 64KB~128KB 的 NOR Flash 块。

    NOR Flash 的接口与 RAM 完全相同,可以随意访问任意地址的数据。

    而 NAND Flash 的接口仅仅包含几个 I/O 引脚,需要串行地访问。NAND Flash 一般以 512 字节为单位进行读写。

    这使得 NOR Flash 适合于运行程序,而 NAND Flash 更适合于存储数据。

    容量相同的情况下,NAND Flash 的体积更小,对于空间有严格要求的系统,NAND Flash 可以节省更多的空间。

    市场上 NOR Flash 的容量通常为 1MB~4MB(也有 32MB 的 NOR Flash),NAND Flash 的容量为 8MB~512MB。

    容量差别也使得 NOR Flash 多用于存储程序,NAND Flash 多用于存储数据。

     

    对于 Flash 存储器件的可靠性需要考虑 3 点:位反转、坏块和可擦除次数。

    所有 Flash 器件都遭遇位反转的问题:由于 Flash 固有的电器特性,在读写数据的过程中,偶然会产生一位或几位数据错误(这种概率很低),而 NAND Flash 出的概率远大于 NOR Flash。

    当位反转发生在关键的代码、数据上时,有可能导致系统崩溃。

    当仅仅是报告位反转,重新读取即可;如果确实发生了位反转,则必须有相应的错误检测/恢复措施。

    在 NAND Flash 上发生位反转的概率更高,推荐使用 EDC/ECC 进行错误检测和恢复。NAND Flash 上面会有坏块随机分布,在使用前需要将坏块扫描出来,确保不再使用它们,否则会使产品含有严重的故障。NAND Flash 每块的可擦除次数通常在 100000 次左右,是 NOR Flash 的 10 倍。

    另外,因为 NAND Flash 的块大小通常是 NOR Flash 的 1/8,所以 NAND Flash 的寿命远远超过 NOR Flash。

     

    嵌入式 Linux 对 NOR、NAND Flash 的软件支持都很成熟。

    在 NOR Flash 上常使用 jffs2 文件系统,而在 NAND Flash 上常用 yaffs 文件系统。

    在更底层,有 MTD 驱动程序实现对它们的读、写、擦除操作,它也实现了 EDC/ECC 校验。

     

    我擦,概念讲了一堆啊!!!

    NAND Flash 的物理结构

    以 NAND Flash K9F1208U0M 为例,K9F1208U0M 是三星公司生产的容量为 64MB 的  NAND Flash,常用于手持设备等消费电子产品。

    它的封装及外部引脚如上图。

    K9F1208U0M 的功能结构图如下图所示:

    K9F1208U0M 的内部结构分为 10 个功能部件。

    • X-Buffers Latche & Decoders:用于行地址
    • Y-Buffers Latche & Decoders:用于列地址
    • Command Register:用于命令字
    • Control Logic & High Voltage Generator:控制逻辑及产生 Flash 所需高压。
    • NAND Flash Array:存储部件。
    • Page Register & S/A:页寄存器,当读、写某页时,会将数据先读入/写入此寄存器,大小为 528 字节。
    • Y-Gating
    • I/O Buffers & Latches
    • Global Buffers
    • Output Driver

     

    NAND Flash 存储单元组织结构如下图:

    K9F1208U0M 容量为 528 Mbit,分 131072 行(页)

     

    待续。。。

     

    转载于:https://www.cnblogs.com/tuhooo/p/11186819.html

    展开全文
  • NAND FLASH控制器

    千次阅读 2015-08-29 17:40:37
    一、NAND Flash介绍和NAND Flash控制器的使用 NAND Flash在嵌入式系统中的作用,相当于PC上的硬盘 常见的Flash有NOR Flash和NAND Flash,NOR Flash上进行读取的效率非常高,但是擦除和写操作的效率很低,容量...

    摘自:《嵌入式Linux应用开发完全手册》——韦东山

    一、NAND Flash介绍和NAND Flash控制器的使用

    NAND Flash在嵌入式系统中的作用,相当于PC上的硬盘

    常见的Flash有NOR Flash和NAND Flash,NOR Flash上进行读取的效率非常高,但是擦除和写操作的效率很低,容量一般比较小;NAND Flash进行擦除和写操作的效率更高,并且容量更大。一般NOR Flash用于存储程序,NAND Flash用于存储数据。

    1)NAND Flash的物理结构

    笔者用的开发板上NAND Flash型号是K9F1G08,大小为128M,下图为它的封装和外部引脚

    * NandFlash接口信号较少

    * 数据宽度只有8Bit,没有地址总线。地址和数据总线复用,串行读取


    信号名称

    信号描述

    IO[7..0]

    数据总线

    CE#

    片选信号(Chip Select),低电平有效

    WE#

    写有效(Write Enable),低电平表示当前总线操作是写操作

    RE#

    读有效(Read Enable),低电平表示当前总线操作是读操作

    CLE

    命令锁存(Command Latch Enable)信号,写操作时给出此信号表示写命令

    ALE

    地址/数据锁存(Address Latch Enable)信号,写操作时给出此信号表示写地址或数据

    WP#

    写保护(Write Protect)信号

    R/B

    (Read/Busy)信号

     

    2)K9F1G08功能结构图如下

     

    K9F1G08内部结构有下面一些功能部件

    ①X-Buffers Latches & Decoders:用于行地址

    ②X-Buffers Latches & Decoders:用于列地址

    ③Command Register:用于命令字

    ④Control Logic & High Voltage Generator:控制逻辑及产生Flash所需高压

    ⑤Nand Flash Array:存储部件

    ⑥Data Register & S/A:数据寄存器,读、写页时,数据存放此寄存器

    ⑦Y-Gating

    ⑧I/O Buffers & Latches

    ⑨Global Buffers

    ⑩Output Driver

    3)NAND Flash 存储单元组织结构图如下:

     

    K9F1G08容量为1056Mbit,分为65536行(页)、2112列,每一页大小为2kb,外加64字节的额外空间,这64字节的额外空间的列地址为2048-2111

    命令、地址、数据都通过IO0-IO7输入/输出,写入命令、地址或数据时,需要将WE、CE信号同时拉低,数据在WE信号的上升沿被NAND FLash锁存;命令锁存信号CLE、地址锁存信号ALE用来分辨、锁存命令或地址。

    K9F1G08有128MB的存储空间,需要27位地址,以字节为单位访问Flash时,需要4个地址序列

    NandFlash地址结构

    * NandFlash设备的存储容量是以页(Page)和块(Block)为单位的。

    * Page=528Byte (512Byte用于存放数据,其余16Byte用于存放其他信息,如块好坏的标记、块的逻辑地址、页内数据的ECC校验和等)

    * Block=32Page

    * 容量为64MBNandFlash存储结构为:512Byte×32Page×4096Block

    * NandFlash以页为单位进行读和编程(写)操作,一页为512Byte;以块为单位进行擦除操作,一块为512Byte*32page=16KB

    * 对于64MBNAND设备,需要26根地址线,由于NAND设备数据总线宽度是8位的,因此必须经过4个时钟周期才能把全部地址信息接收下来


     

    I/O7

    I/O6

    I/O5

    I/O4

    I/O3

    I/O2

    I/O1

    I/O0

    第一个周期

    A7

    A6

    A5

    A4

    A3

    A2

    A1

    A0

    第二个周期

    A15

    A14

    A13

    A12

    A11

    A10

    A9

    A8

    第三个周期

    A23

    A22

    A21

    A20

    A19

    A18

    A17

    A16

    第四个周期

     

     

     

     

     

     

    A25

    A24

     

    * 可以这么说,第一个时钟周期给出的是目标地址在一个page内的偏移量,而后三个时钟周期给出的是页地址

    * 由于一个页内有512Byte,需要9bit的地址寻址,而第一个时钟周期只给出了低8bit,最高位A8由不同的读命令(Read Mode2)来区分的。

    4). NandFlash的命令 

    [ARM笔记]存储器扩展连接理解(S3C2410为例)—NandFlash - Fantity Wei - Footprint

    NAND Flash访问方法

    NAND Flash硬件连接如下图:

     

    NAND Flash和S3C2440的连线包括,8个IO引脚,5个使能信号(nWE、ALE、CLE、nCE、nRE)、1个状态引脚(R/B)、1个写保护引脚(nWP)。地址、数据和命令都是在这些使能信号的配合下,通过8个IO引脚传输。写地址、数据、命令时,nCE、nWE信号必须为低电平,它们在 nWE信号的上升沿被锁存。命令锁存使能信号CLE和地址锁存使能信号ALE用来区别IO引脚上传输的是命令还是地址。

     

    命令字及操作方法

            操作NAND Flash时,先传输命令,然后传输地址,最后读写数据,这个期间要检查Flash的状态。K9F1G08容量为128MB,需要一个27位的地址,发出命令后,后面要紧跟着4个地址序列。

    下图为K9F1G08的命令字

    下图为K9F1G08的地址序列

    K9F1G08有2112列,所以必须使用A0-A11共12位来寻址,有65535行,所以必须使用A12-A27共16位来寻址。

     

    3)S3C2440 NAND Flash控制器介绍

    NAND Flash的读写操作次序如下:

    ①设置NFCONF配置NAND Flash

    ②向NFCMD寄存器写入命令

    ③向NFADDR寄存器写入地址

    ④读写数据:通过寄存器NFSTAT检测NAND Flash的状态,在启动某个操作后,应该检测R/nB信号以确定该操作是否完成、是否成功。

     

    下面介绍这些寄存器:

    ①NFCONF:配置寄存器

            用来设置NAND Flash的时序参数,设置数据位宽,设置是否支持其他大小的页等。

    ②NFCONT:控制寄存器

            用来使能NAND Flash控制器、使能控制引脚信号nFCE、初始化ECC,锁定NAND Flash等功能

    ③NFCMD:命令寄存器

            用来发送Flash操作命令

    ④NFADDR:地址寄存器

            用来向Flash发送地址信号

    ⑤NFDATA:数据寄存器

            读写此寄存器启动对NAND Flash的读写数据操作

    ⑥NFSTAT:状态寄存器

            0:busy,1:ready

     

    二、NAND Flash控制器操作实例:读Flash

    1)读NAND Flash的步骤

    ①设置NFCONF

            在HCLK=100Mhz的情况下,TACLS=0,TWRPH0=3,TWRPH1=0,则

            NFCONF = 0x300

            使能NAND Flash控制器、禁止控制引脚信号nFCE,初始化ECC

            NFCONT = (1<<4) | (1<<1) | (1<<0)

    ②操作NAND Flash前,复位

            NFCONT &= ~(1<<1)        发出片选信号

            NFCMD = 0xff        reset命令

            然后循环查询NFSTAT位0,直到等于1,处于就绪态

            最后禁止片选信号,在实际使用时再使能

            NFCONT |= 0x2        禁止NAND Flash

    ③发出读命令

            NFCONT &= ~(1<<1)        发出片选信号

            NFCMD = 0        读命令

    ④发出地址信号

    ⑤循环查询NFSTAT,直到等于1

    ⑥连续读NFDATA寄存器,得到一页数据

    ⑦最后禁止NAND Flash片选信号

            NFCONT |= (1<<1)

     

     2)代码详解

    本实例的目的是把一部分代码存放在NAND Flash地址4096之后,当程序启动后通过NAND Flash控制器读出代码,执行。

    连接脚本 nand.lds

     

    SECTIONS { 

      firtst   0x00000000 : { head.o init.o nand.o}

      second  0x30000000 : AT(4096) { main.o }

    head.o init.o nand.o三个文件运行地址为0,生成的镜像文件偏移地址也为0

    main.0的运行地址为0x30000000,生成的镜像文件偏移地址为4096

     

     

    @******************************************************************************

    @ File:head.s

    @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行

    @******************************************************************************       

      

    .text

    .global _start

    _start:

                                                @函数disable_watch_dog, memsetup, init_nand, nand_read_ll在init.c中定义

                ldr     sp, =4096               @设置堆栈 

                bl      disable_watch_dog       @关WATCH DOG

                bl      memsetup                @初始化SDRAM

                bl      nand_init               @初始化NAND Flash


                                                @将NAND Flash中地址4096开始的1024字节代码(main.c编译得到)复制到SDRAM中

                                                @nand_read_ll函数需要3个参数:

                ldr     r0,     =0x30000000     @1. 目标地址=0x30000000,这是SDRAM的起始地址

                mov     r1,     #4096           @2.  源地址   = 4096,连接的时候,main.c中的代码都存在NAND Flash地址4096开始处

                mov     r2,     #2048           @3.  复制长度= 2048(bytes),对于本实验的main.c,这是足够了

                bl      nand_read               @调用C函数nand_read


                ldr     sp, =0x34000000         @设置栈

                ldr     lr, =halt_loop          @设置返回地址

                ldr     pc, =main               @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转

    halt_loop:

                b       halt_loop

     

    init.c 用于初始化操作
    /* WOTCH DOG register */
    #define  WTCON (*(volatile unsigned long *)0x53000000)
     
    /* SDRAM regisers */
    #define  MEM_CTL_BASE 0x48000000
     
    void disable_watch_dog();
    void memsetup();
     
    /*上电后,WATCH DOG默认是开着的,要把它关掉 */
    void disable_watch_dog()
    {
    WTCON = 0;
    }
     
    /* 设置控制SDRAM的13个寄存器 */
    void memsetup()
    {
    int  i = 0;
    unsigned long *p = (unsigned long *)MEM_CTL_BASE;
     
        /* SDRAM 13个寄存器的值 */
        unsigned long  const    mem_cfg_val[]={ 0x22011110,     //BWSCON
                                                0x00000700,     //BANKCON0
                                                0x00000700,     //BANKCON1
                                                0x00000700,     //BANKCON2
                                                0x00000700,     //BANKCON3  
                                                0x00000700,     //BANKCON4
                                                0x00000700,     //BANKCON5
                                                0x00018005,     //BANKCON6
                                                0x00018005,     //BANKCON7
                                                0x008C07A3,     //REFRESH
                                                0x000000B1,     //BANKSIZE
                                                0x00000030,     //MRSRB6
                                                0x00000030,     //MRSRB7
                                        };
     
    for(; i < 13; i++)
    p[i] = mem_cfg_val[i];
    }
     
    nand.c 用于操作nand flash
     
    #define BUSY            1
     
    #define NAND_SECTOR_SIZE_LP    2048        //K9F1G08使用2048+64列
    #define NAND_BLOCK_MASK_LP     (NAND_SECTOR_SIZE_LP - 1)
     
    typedef unsigned int S3C24X0_REG32;
     
    typedef struct {
        S3C24X0_REG32   NFCONF;
        S3C24X0_REG32   NFCONT;
        S3C24X0_REG32   NFCMD;
        S3C24X0_REG32   NFADDR;
        S3C24X0_REG32   NFDATA;
        S3C24X0_REG32   NFMECCD0;
        S3C24X0_REG32   NFMECCD1;
        S3C24X0_REG32   NFSECCD;
        S3C24X0_REG32   NFSTAT;
        S3C24X0_REG32   NFESTAT0;
        S3C24X0_REG32   NFESTAT1;
        S3C24X0_REG32   NFMECC0;
        S3C24X0_REG32   NFMECC1;
        S3C24X0_REG32   NFSECC;
        S3C24X0_REG32   NFSBLK;
        S3C24X0_REG32   NFEBLK;
    } S3C2440_NAND;        //此结构体存储操作NAND Flash相关寄存器
     
     
    typedef struct {
        void (*nand_reset)(void);
        void (*wait_idle)(void);
        void (*nand_select_chip)(void);
        void (*nand_deselect_chip)(void);
        void (*write_cmd)(int cmd);
        void (*write_addr)(unsigned int addr);
        unsigned char (*read_data)(void);
    }t_nand_chip;        //存储nand相关操作的函数地址
     
    static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;        //s2c2440nand控制器地址
     
    static t_nand_chip nand_chip;
     
    /* 供外部调用的函数 */
    void nand_init(void);
    void nand_read(unsigned char *buf, unsigned long start_addr, int size);
     
    /* NAND Flash操作的总入口, 它们将调用S3C2440的相应函数 */
    static void nand_reset(void);
    static void wait_idle(void);
    static void nand_select_chip(void);
    static void nand_deselect_chip(void);
    static void write_cmd(int cmd);
    static void write_addr(unsigned int addr);
    static unsigned char read_data(void);
     
    /* S3C2440的NAND Flash处理函数 */
    static void s3c2440_nand_reset(void);
    static void s3c2440_wait_idle(void);
    static void s3c2440_nand_select_chip(void);
    static void s3c2440_nand_deselect_chip(void);
    static void s3c2440_write_cmd(int cmd);
    static void s3c2440_write_addr(unsigned int addr);
    static unsigned char s3c2440_read_data(void);
     
    /* S3C2440的NAND Flash操作函数 */
     
    /* 复位 */
    static void s3c2440_nand_reset(void)
    {
        s3c2440_nand_select_chip();
        s3c2440_write_cmd(0xff);  // 复位命令
        s3c2440_wait_idle();
        s3c2440_nand_deselect_chip();
    }
     
    /* 等待NAND Flash就绪 */
    static void s3c2440_wait_idle(void)
    {
        int i;
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
        while(!(*p & BUSY))        //*p=1表示就绪,跳出循环
            for(i=0; i<10; i++);
    }
     
    /* 发出片选信号 */
    static void s3c2440_nand_select_chip(void)
    {
        int i;
        s3c2440nand->NFCONT &= ~(1<<1);
        for(i=0; i<10; i++);    
    }
     
    /* 取消片选信号 */
    static void s3c2440_nand_deselect_chip(void)
    {
        s3c2440nand->NFCONT |= (1<<1);
    }
     
    /* 发出命令 */
    static void s3c2440_write_cmd(int cmd)
    {
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
        *p = cmd;
    }
     
    /* 发出地址 */
    static void s3c2440_write_addr_lp(unsigned int addr)
    {
    int i;
    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
    int col, page;
     
    col = addr & NAND_BLOCK_MASK_LP;        //取得列地址
    page = addr / NAND_SECTOR_SIZE_LP;        //取得行地址
    *p = col & 0xff; /* 列地址 A0~A7 */
    for(i=0; i<10; i++);
    *p = (col >> 8) & 0x0f;  /* 列地址 A8~A11 */
    for(i=0; i<10; i++);
    *p = page & 0xff; /* 行地址 A12~A19 */
    for(i=0; i<10; i++);
    *p = (page >> 8) & 0xff; /* 行地址 A20~A27 */
    for(i=0; i<10; i++);
    *p = (page >> 16) & 0x03; /* 行地址 A28~A29 */
    for(i=0; i<10; i++);
    }
     
     
    /* 读取数据 */
    static unsigned char s3c2440_read_data(void)
    {
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
        return *p;
    }
     
     
    /* 在第一次使用NAND Flash前,复位一下NAND Flash */
    static void nand_reset(void)
    {
        nand_chip.nand_reset();
    }
     
    static void wait_idle(void)
    {
        nand_chip.wait_idle();
    }
     
    static void nand_select_chip(void)
    {
        int i;
        nand_chip.nand_select_chip();
        for(i=0; i<10; i++);
    }
     
    static void nand_deselect_chip(void)
    {
        nand_chip.nand_deselect_chip();
    }
     
    static void write_cmd(int cmd)
    {
        nand_chip.write_cmd(cmd);
    }
    static void write_addr(unsigned int addr)
    {
        nand_chip.write_addr(addr);
    }
     
    static unsigned char read_data(void)
    {
        return nand_chip.read_data();
    }
     
     
    /* 初始化NAND Flash */
    void nand_init(void)
    {
    #define TACLS   0
    #define TWRPH0  3
    #define TWRPH1  0
            nand_chip.nand_reset         = s3c2440_nand_reset;
            nand_chip.wait_idle          = s3c2440_wait_idle;
            nand_chip.nand_select_chip   = s3c2440_nand_select_chip;
            nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;
            nand_chip.write_cmd          = s3c2440_write_cmd;
            nand_chip.write_addr         = s3c2440_write_addr_lp;
            nand_chip.read_data          = s3c2440_read_data;
     
    /* 设置时序 */
            s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
            /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
            s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
        
        /* 复位NAND Flash */
        nand_reset();
    }
     
     
    /* 读函数 用于把nand flash中代码复制到sdram中*/
    void nand_read(unsigned char *buf, unsigned long start_addr, int size)
    {
        int i, j;
     
        if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) {
            return ;     /* 地址或长度不对齐 */
        }
     
     
        /* 选中芯片 */
        nand_select_chip();
     
        for(i=start_addr; i < (start_addr + size);) {
          /* 发出READ命令 */
          write_cmd(0);
     
          /* 写地址 */
          write_addr(i);
          write_cmd(0x30);
          wait_idle();
     
     
          for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {
              *buf = read_data();
              buf++;
          }
        }
     
        /* 取消片选信号 */
        nand_deselect_chip();
        
        return ;
    }
     
    main.c 很简单,点灯
     
    #define GPBCON (*(volatile unsigned long *)0x56000010)
    #define GPBDAT (*(volatile unsigned long *)0x56000014)

    #define GPB5_out (1<<(5*2))
    #define GPB6_out (1<<(6*2))
    #define GPB7_out (1<<(7*2))
    #define GPB8_out (1<<(8*2))

    void  wait(unsigned long dly)
    {
    for(; dly > 0; dly--);
    }

    int main(void)
    {
    unsigned long i = 0;
    GPBCON = GPB5_out|GPB6_out|GPB7_out|GPB8_out; // 将LED1-4对应的GPB5/6/7/8四个引脚设为输出

    GPBDAT = ~(1<<5) | ~(1<<7) | ~(1<<8);
    while(1){
    wait(30000);
    GPBDAT = (~(i<<5)); // 根据i的值,点亮LED1-4
    if(++i == 16)
    i = 0;
    }

    return 0;
    }
     
    最后是Makefile
    objs := head.o init.o nand.o main.o

    nand.bin : $(objs)
    arm-linux-ld -Tnand.lds -o nand_elf $^
    arm-linux-objcopy -O binary -S nand_elf $@
    arm-linux-objdump -D -m arm  nand_elf > nand.dis

    %.o:%.c
    arm-linux-gcc -Wall -c -O2 -o $@ $<

    %.o:%.S
    arm-linux-gcc -Wall -c -O2 -o $@ $<

    clean:
    rm -f  nand.dis nand.bin nand_elf *.o
    展开全文
  • NAND Flash控制器

    千次阅读 2013-04-26 09:20:52
    一、NAND Flash介绍和NAND Flash控制器的使用 NAND Flash在嵌入式系统中的作用,相当于PC上的硬盘 常见的Flash有NOR Flash和NAND Flash,NOR Flash上进行读取的效率非常高,但是擦除和写操作的效率很低,容量一般...

    一、NAND Flash介绍和NAND Flash控制器的使用
    NAND Flash在嵌入式系统中的作用,相当于PC上的硬盘
    常见的Flash有NOR Flash和NAND Flash,NOR Flash上进行读取的效率非常高,但是擦除和写操作的效率很低,容量一般比较小;NAND Flash进行擦除和写操作的效率更高,并且容量更大。一般NOR Flash用于存储程序,NAND Flash用于存储数据。
    1)NAND Flash的物理结构
    笔者用的开发板上NAND Flash型号是K9F1G08,大小为128M,下图为它的封装和外部引脚

    ARM学习笔记(五)-NAND <wbr>Flash控制器

    I/O0-I/O7        数据输入/输出
    CLE        命令锁存使能
    ALE        地址锁存使能
    CE        芯片使能
    RE        读使能
    WE        写使能
    WP        写保护
    R/B        就绪/忙输出信号
    Vcc        电源
    Vss        地
    N.C        不接
     
    K9F1G08功能结构图如下
     ARM学习笔记(五)-NAND <wbr>Flash控制器

    K9F1G08内部结构有下面一些功能部件
    ①X-Buffers Latches & Decoders:用于行地址
    ②X-Buffers Latches & Decoders:用于列地址
    ③Command Register:用于命令字
    ④Control Logic & High Voltage Generator:控制逻辑及产生Flash所需高压
    ⑤Nand Flash Array:存储部件
    ⑥Data Register & S/A:数据寄存器,读、写页时,数据存放此寄存器
    ⑦Y-Gating
    ⑧I/O Buffers & Latches
    ⑨Global Buffers
    ⑩Output Driver
    NAND Flash 存储单元组织结构图如下:
    ARM学习笔记(五)-NAND <wbr>Flash控制器

    K9F1G08容量为1056Mbit,分为65536行(页)、2112列,每一页大小为2kb,外加64字节的额外空间,这64字节的额外空间的列地址为2048-2111
    命令、地址、数据都通过IO0-IO7输入/输出,写入命令、地址或数据时,需要将WE、CE信号同时拉低,数据在WE信号的上升沿被NAND FLash锁存;命令锁存信号CLE、地址锁存信号ALE用来分辨、锁存命令或地址。
    K9F1G08有128MB的存储空间,需要27位地址,以字节为单位访问Flash时,需要4个地址序列
     
    2)NAND Flash访问方法
    NAND Flash硬件连接如下图:
    ARM学习笔记(五)-NAND <wbr>Flash控制器

    NAND Flash和S3C2440的连线包括,8个IO引脚,5个使能信号(nWE、ALE、CLE、nCE、nRE)、1个状态引脚(R/B)、1个写保护引脚(nWP)。地址、数据和命令都是在这些使能信号的配合下,通过8个IO引脚传输。写地址、数据、命令时,nCE、nWE信号必须为低电平,它们在nWE信号的上升沿被锁存。命令锁存使能信号CLE和地址锁存使能信号ALE用来区别IO引脚上传输的是命令还是地址。
     
    命令字及操作方法
            操作NAND Flash时,先传输命令,然后传输地址,最后读写数据,这个期间要检查Flash的状态。K9F1G08容量为128MB,需要一个27位的地址,发出命令后,后面要紧跟着4个地址序列。
    下图为K9F1G08的命令字

    ARM学习笔记(五)-NAND <wbr>Flash控制器

    下图为K9F1G08的地址序列

    ARM学习笔记(五)-NAND <wbr>Flash控制器

    K9F1G08有2112列,所以必须使用A0-A11共12位来寻址,有65535行,所以必须使用A12-A27共16位来寻址。
     
    3)S3C2440 NAND Flash控制器介绍
    NAND Flash的读写操作次序如下:
    ①设置NFCONF配置NAND Flash
    ②向NFCMD寄存器写入命令
    ③向NFADDR寄存器写入地址
    ④读写数据:通过寄存器NFSTAT检测NAND Flash的状态,在启动某个操作后,应该检测R/nB信号以确定该操作是否完成、是否成功。
     
    下面介绍这些寄存器:
    ①NFCONF:配置寄存器
            用来设置NAND Flash的时序参数,设置数据位宽,设置是否支持其他大小的页等。
    ②NFCONT:控制寄存器
            用来使能NAND Flash控制器、使能控制引脚信号nFCE、初始化ECC,锁定NAND Flash等功能
    ③NFCMD:命令寄存器
            用来发送Flash操作命令
    ④NFADDR:地址寄存器
            用来向Flash发送地址信号
    ⑤NFDATA:数据寄存器
            读写此寄存器启动对NAND Flash的读写数据操作
    ⑥NFSTAT:状态寄存器
            0:busy,1:ready
     
    二、NAND Flash控制器操作实例:读Flash
    1)读NAND Flash的步骤
    ①设置NFCONF
            在HCLK=100Mhz的情况下,TACLS=0,TWRPH0=3,TWRPH1=0,则
            NFCONF = 0x300
            使能NAND Flash控制器、禁止控制引脚信号nFCE,初始化ECC
            NFCONT = (1<<4) | (1<<1) | (1<<0)
    ②操作NAND Flash前,复位
            NFCONT &= ~(1<<1)        发出片选信号
            NFCMD = 0xff        reset命令
            然后循环查询NFSTAT位0,直到等于1,处于就绪态
            最后禁止片选信号,在实际使用时再使能
            NFCONT |= 0x2        禁止NAND Flash
    ③发出读命令
            NFCONT &= ~(1<<1)        发出片选信号
            NFCMD = 0        读命令
    ④发出地址信号
    ⑤循环查询NFSTAT,直到等于1
    ⑥连续读NFDATA寄存器,得到一页数据
    ⑦最后禁止NAND Flash片选信号
            NFCONT |= (1<<1)
     
     2)代码详解
    本实例的目的是把一部分代码存放在NAND Flash地址4096之后,当程序启动后通过NAND Flash控制器读出代码,执行。
    连接脚本 nand.lds
     
    SECTIONS {
      firtst   0x00000000 : { head.o init.o nand.o}
      second  0x30000000 : AT(4096) { main.o }
    }

    head.o init.o nand.o三个文件运行地址为0,生成的镜像文件偏移地址也为0
    main.0的运行地址为0x30000000,生成的镜像文件偏移地址为4096
     
     
    @******************************************************************************
    @ File:head.s
    @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
    @******************************************************************************      
     
    .text
    .global _start
    _start:
                      @函数disable_watch_dog, memsetup, init_nand, nand_read_ll在init.c中定义
                ldr     sp, =4096               @设置堆栈
                bl      disable_watch_dog       @关WATCH DOG
                bl      memsetup                @初始化SDRAM
                bl      nand_init              
     @初始化NAND Flash


                    @将NAND Flash中地址4096开始的1024字节代码(main.c编译得到)复制到SDRAM中
                                                @nand_read_ll函数需要3个参数:
                ldr     r0,     =0x30000000     @1. 目标地址=0x30000000,这是SDRAM的起始地址
                mov     r1,     #4096           @2.  源地址   = 4096,连接的时候,main.c中的代码都存在NAND Flash地址4096开始处
                mov     r2,     #2048           @3.  复制长度= 2048(bytes),对于本实验的main.c,这是足够了
                bl      nand_read              
     @调用C函数nand_read


                ldr     sp, =0x34000000         @设置栈
                ldr     lr, =halt_loop          @设置返回地址
                ldr     pc, =main               @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转
    halt_loop:
                b       halt_loop
     
    init.c 用于初始化操作

    #define  WTCON    (*(volatile unsigned long *)0x53000000)
     

    #define  MEM_CTL_BASE  0x48000000
     
    void disable_watch_dog();
    void memsetup();
     

    void disable_watch_dog()
    {
     WTCON = 0;
    }
     

    void memsetup()
    {
     int  i = 0;
     unsigned long *p = (unsigned long *)MEM_CTL_BASE;
     
       
        unsigned long  const    mem_cfg_val[]={ 0x22011110,     //BWSCON
                                                0x00000700,     //BANKCON0
                                                0x00000700,     //BANKCON1
                                                0x00000700,     //BANKCON2
                                                0x00000700,     //BANKCON3 
                                                0x00000700,     //BANKCON4
                                                0x00000700,     //BANKCON5
                                                0x00018005,     //BANKCON6
                                                0x00018005,     //BANKCON7
                                                0x008C07A3,     //REFRESH
                                                0x000000B1,     //BANKSIZE
                                                0x00000030,     //MRSRB6
                                                0x00000030,     //MRSRB7
                                        };
     
     for(; i < 13; i++)
      p[i] = mem_cfg_val[i];
    }
     
    nand.c 用于操作nand flash
     
    #define BUSY            1
     
    #define NAND_SECTOR_SIZE_LP    2048        //K9F1G08使用2048+64列
    #define NAND_BLOCK_MASK_LP     (NAND_SECTOR_SIZE_LP - 1)
     
    typedef unsigned int S3C24X0_REG32;
     
    typedef struct {
        S3C24X0_REG32   NFCONF;
        S3C24X0_REG32   NFCONT;
        S3C24X0_REG32   NFCMD;
        S3C24X0_REG32   NFADDR;
        S3C24X0_REG32   NFDATA;
        S3C24X0_REG32   NFMECCD0;
        S3C24X0_REG32   NFMECCD1;
        S3C24X0_REG32   NFSECCD;
        S3C24X0_REG32   NFSTAT;
        S3C24X0_REG32   NFESTAT0;
        S3C24X0_REG32   NFESTAT1;
        S3C24X0_REG32   NFMECC0;
        S3C24X0_REG32   NFMECC1;
        S3C24X0_REG32   NFSECC;
        S3C24X0_REG32   NFSBLK;
        S3C24X0_REG32   NFEBLK;
    } S3C2440_NAND;        //此结构体存储操作NAND Flash相关寄存器
     
     
    typedef struct {
        void (*nand_reset)(void);
        void (*wait_idle)(void);
        void (*nand_select_chip)(void);
        void (*nand_deselect_chip)(void);
        void (*write_cmd)(int cmd);
        void (*write_addr)(unsigned int addr);
        unsigned char (*read_data)(void);
    }t_nand_chip;        //存储nand相关操作的函数地址
     
    static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;        //s2c2440nand控制器地址
     
    static t_nand_chip nand_chip;
     

    void nand_init(void);
    void nand_read(unsigned char *buf, unsigned long start_addr, int size);
     

    static void nand_reset(void);
    static void wait_idle(void);
    static void nand_select_chip(void);
    static void nand_deselect_chip(void);
    static void write_cmd(int cmd);
    static void write_addr(unsigned int addr);
    static unsigned char read_data(void);
     

    static void s3c2440_nand_reset(void);
    static void s3c2440_wait_idle(void);
    static void s3c2440_nand_select_chip(void);
    static void s3c2440_nand_deselect_chip(void);
    static void s3c2440_write_cmd(int cmd);
    static void s3c2440_write_addr(unsigned int addr);
    static unsigned char s3c2440_read_data(void);
     

     

    static void s3c2440_nand_reset(void)
    {
        s3c2440_nand_select_chip();
        s3c2440_write_cmd(0xff);  // 复位命令
        s3c2440_wait_idle();
        s3c2440_nand_deselect_chip();
    }
     

    static void s3c2440_wait_idle(void)
    {
        int i;
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
        while(!(*p & BUSY))        /
    static void s3c2440_nand_select_chip(void)
    {
        int i;
        s3c2440nand->NFCONT &= ~(1<<1);
        for(i=0; i<10; i++);   
    }
     

    static void s3c2440_nand_deselect_chip(void)
    {
        s3c2440nand->NFCONT |= (1<<1);
    }
     

    static void s3c2440_write_cmd(int cmd)
    {
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
        *p = cmd;
    }
     

    static void s3c2440_write_addr_lp(unsigned int addr)
    {
     int i;
     volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
     int col, page;
     
     col = addr & NAND_BLOCK_MASK_LP;        //取得列地址
     page = addr / NAND_SECTOR_SIZE_LP;        //取得行地址
     
     *p = col & 0xff;   
     for(i=0; i<10; i++);  
     *p = (col >> 8) & 0x0f;  
     for(i=0; i<10; i++);
     *p = page & 0xff;   
     for(i=0; i<10; i++);
     *p = (page >> 8) & 0xff; 
     for(i=0; i<10; i++);
     *p = (page >> 16) & 0x03; 
     for(i=0; i<10; i++);
    }
     
     

    static unsigned char s3c2440_read_data(void)
    {
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
        return *p;
    }
     
     

    static void nand_reset(void)
    {
        nand_chip.nand_reset();
    }
     
    static void wait_idle(void)
    {
        nand_chip.wait_idle();
    }
     
    static void nand_select_chip(void)
    {
        int i;
        nand_chip.nand_select_chip();
        for(i=0; i<10; i++);
    }
     
    static void nand_deselect_chip(void)
    {
        nand_chip.nand_deselect_chip();
    }
     
    static void write_cmd(int cmd)
    {
        nand_chip.write_cmd(cmd);
    }
    static void write_addr(unsigned int addr)
    {
        nand_chip.write_addr(addr);
    }
     
    static unsigned char read_data(void)
    {
        return nand_chip.read_data();
    }
     
     

    void nand_init(void)
    {
    #define TACLS   0
    #define TWRPH0  3
    #define TWRPH1  0
            nand_chip.nand_reset         = s3c2440_nand_reset;
            nand_chip.wait_idle          = s3c2440_wait_idle;
            nand_chip.nand_select_chip   = s3c2440_nand_select_chip;
            nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;
            nand_chip.write_cmd          = s3c2440_write_cmd;
            nand_chip.write_addr         = s3c2440_write_addr_lp;
            nand_chip.read_data          = s3c2440_read_data;
     
      
            s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
            
            s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
        }
       
       
        nand_reset();
    }
     
     

    void nand_read(unsigned char *buf, unsigned long start_addr, int size)
    {
        int i, j;
     
        if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) {
            return ;    
        }
     
     
       
        nand_select_chip();
     
        for(i=start_addr; i < (start_addr + size);) {
         
          write_cmd(0);
     
         
          write_addr(i);
          write_cmd(0x30);  
          wait_idle();
     
     
          for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {
              *buf = read_data();
              buf++;
          }
        }
     
       
        nand_deselect_chip();
       
        return ;
    }
     
    main.c 很简单,点灯
     
    #define GPBCON  (*(volatile unsigned long *)0x56000010)
    #define GPBDAT  (*(volatile unsigned long *)0x56000014)


    #define GPB5_out (1<<(5*2))
    #define GPB6_out (1<<(6*2))
    #define GPB7_out (1<<(7*2))
    #define GPB8_out (1<<(8*2))


    void  wait(unsigned long dly)
    {
     for(; dly > 0; dly--);
    }


    int main(void)
    {
     unsigned long i = 0;
     
     GPBCON = GPB5_out|GPB6_out|GPB7_out|GPB8_out;  // 将LED1-4对应的GPB5/6/7/8四个引脚设为输出


     GPBDAT = ~(1<<5) | ~(1<<7) | ~(1<<8);
     
     while(1){
      wait(30000);
      GPBDAT = (~(i<<5));  // 根据i的值,点亮LED1-4
      if(++i == 16)
       i = 0;
     }


     return 0;
    }
     
    最后是Makefile
    objs := head.o init.o nand.o main.o


    nand.bin : $(objs)
     arm-linux-ld -Tnand.lds -o nand_elf $^
     arm-linux-objcopy -O binary -S nand_elf $@
     arm-linux-objdump -D -m arm  nand_elf > nand.dis


    %.o:%.c
     arm-linux-gcc -Wall -c -O2 -o $@ $<


    %.o:%.S
     arm-linux-gcc -Wall -c -O2 -o $@ $<


    clean:
     rm -f  nand.dis nand.bin nand_elf *.o


    展开全文
  • nand flash控制器

    2015-06-11 17:23:39
    PIN CONFIGURATION OM[1:0] = 00: Enable NAND flash memory boot NCON: NAND flash memory selection(Normal / Advance) 0: Normal NAND flash(256Words/512Bytes page size, 3/4 address cycle) 1: Advance NA
    PIN CONFIGURATION
    OM[1:0] = 00: Enable NAND flash memory boot
    NCON: NAND flash memory selection(Normal / Advance)
    0: Normal NAND flash(256Words/512Bytes page size, 3/4 address cycle)
    1: Advance NAND flash(1KWords/2KBytes page size, 4/5 address cycle)
    GPG13: NAND flash memory page capacitance selection
    0: Page=256Words(NCON = 0) or Page=1KWords(NCON = 1)
    1: Page=512Bytes(NCON = 0) or Page=2KBytes(NCON = 1)
    GPG14: NAND flash memory address cycle selection
    0: 3 address cycle(NCON = 0) or 4 address cycle(NCON = 1)
    1: 4 address cycle(NCON = 0) or 5 address cycle(NCON = 1)
    GPG15: NAND flash memory bus width selection
    0: 8-bit bus width
    1: 16-bit bus width


    OM[1:0]:使能nand flash存储器 
    NCON :nand flash 存储器选择位  
    0:正常模式:256字/512字节页,3/4 地址周期
    1:先进模式:1K字/2K字节页,4/5 地址周期


    GPG13:nand flash 存储器页面容量选择位
    0:页 = 256字(NCON = 0)或者页 = 1K字(NCON = 1)
    1:页 = 512字节(NCON = 0)或者页 = 2K字节(NCON = 1)


    GPG14:nand flash 存储器地址周期选择位
    0:3地址周期(NCON = 0)或者 4地址周期(NCON = 1)
    1:4地址周期(NCON = 0)或者 4地址周期(NCON = 1)


    GPG15:nand flash 存储器总线宽度选择位
    0:8bit 总线宽度
    1:16bit 总线宽度


    NOTE
    The configuration pin – NCON, GPG[15:13] – will be fetched during reset.
    In normal status, these pins must be set as input so that the pin status is not to be changed, when enters
    Sleep mode by software or unexpected cause.


    这些配置引脚 —— NCON ,GPG[15:13]  在重启时将被获取
    在正常状态中,这些引脚必须被设置成输入以便当在由软件设置进入睡眠模式或意外的原因发生时,这些引脚不被改变


    Nand flash启动 


    在s3c2410的datasheet的述(OVERVIEW)中,讲到需要注意的几点:
    一、nandflash是没有办法直接映射到cpu内存空间的。nandflash要通到控制方式(在这里是nandflash controller)与cpu交换数
    据。
    二、既然没有办法映射到内存空间,就没有办法从nandflash直接启动。(原因:系统启动或复位时cpu中没有任何代码,系统会从
    内存空间0x00000000开始取指令到cpu运行,而nandflash没有办法通过0x00000000这个地址访问,至少在启动时不能)。
    三、办法是人想出来的。s3c2440a,包括s3c2410,采用stepping stone方式实现了从nandflash启动。stepping stone(垫脚时),
    就是s3c2440a中内置的一段4KB的SRAM.当系统启动时,nandflash controller通过硬件方式把nandflash中前4KB中的内容拷贝到
    stepping stone中。
    我当看到这里就想,既然可以通过硬件方式拷贝。做到同样方式拷贝到SDRAM中不就行了?为什么还要有nandflash的驱动呢?
    其实是这样的:硬件拷贝只是单纯的拷贝。没有办法做ECC校验。这样肯定是不行的,大家也知道。nandflash的正常工作是要
    ecc校验来保证的。
    那么这里就不需要ECC校验了吗?
    不需要,因为在后面了解到。nandflash它的第一个块是采用特殊工艺制作的。它的工艺保证了它的第一个块是不会出现位反转的。
    (当然也不是绝对,但是在很大程度上)。所以回到主题上来,我们是可以直接把前4KB拷贝到SRAM中的,但没有办法通过这种方式
    做后面的工作。
    前4KB的代码己经进入sram,我们的板子都有一个跳线开关,那个开关就是为了控制启动方式选择的。一边是选择norflash.另一面是
    选择nandflash.如果我们是选择nandflash,系统会通过自带的硬件方式把sram映射到内存空间的0x00000000处。然后cpu会自动从
    0x00000000处的指令,开始运行。
    注意:所有的上述过程都是硬件自动完成的。当中除了在硬件设计上需要注意的一些情况外,复位时无需人工干预。
    四、这段4KB的代码是用来做什么的呢?
    书中暗表,这4KB是有他们特殊的使命的。它们要把bootloader的后面部分全部通过软件方式拷贝到SDRAM中去,也就是内存中去。
    能起到这个作用的代码在很常见的u-boot开源代码中是没有的。最起码到1.3.4的版本还没有。大家要用的话需要做移植。
    而移植时要考虑的方方面面则留待下回分解。
    说到最后,再讲一个数据手册里的最后的features段的内容:


    FEATURES
    1. Auto boot: The boot code is transferred into 4-kbytes Steppingstone during reset. After the transfer, the boot
    code will be executed on the Steppingstone.
    2. NAND Flash memory I/F: Support 256Words, 512Bytes, 1KWords and 2KBytes Page.
    3. Software mode: User can directly access NAND flash memory, for example this feature can be used in
    read/erase/program NAND flash memory.
    4. Interface: 8 / 16-bit NAND flash memory interface bus.
    5. Hardware ECC generation, detection and indication (Software correction).
    6. SFR I/F: Support Little Endian Mode, Byte/half word/word access to Data and ECC Data register, and Word
    access to other registers
    7. SteppingStone I/F: Support Little/Big Endian, Byte/half word/word access.
    8. The Steppingstone 4-KB internal SRAM buffer can be used for another purpose after NAND flash booting.


    特点:
    一、自动引导
    引导时,引导代码会被传送给4KB的垫脚石(stepping stone)中。传送后引导代码会自动在stepping stone中运行。
    需要注意的就是这个传送过程是通过nandflash controller来做到的。这是一个硬件完成的过程,无需你的任何操作。而且
    stepping stone是一个段sram.通过nandflash启动时它会被自动(这里自动与上面是一个意思,无需你任何操作,或代码)映射到
    0x00000000并执行。上面都讲了。这里只是重申一下罢了。
    二、nandflash存储器接口
    支持256words,512bytes,1Kwords,2Kbytes 每页。
    一般来说,我们板子上多数是512bytes的那种。
    三、软件模式
    用户可以直接访问nandflash存储内容。比如说我们可以比它进行读、写、擦除的操作。
    注意,这里说的是软件方式,不是硬件自动的了哦。想读写什么的还有点麻烦呢。稍后章节介绍。
    四、接口:8/16位nandflash接口总线。
    五、硬件ecc产生,检测和指正(后者指软件改正)不懂的看稍后章节。
    六、特殊功能寄存器(SFR)接口
    支持小端模式字节/半字/字访问数据和ECC数据寄存器。支持字访问其它寄存器。
    这里的意思是说:对数据寄存器和ECC数据寄存器可以每次访问一个字节/一个半字/一个字,即8/16/32位都可以。但其它寄存器
    一次只可以访问一个字。即32位方式访问。
    七、stepping stone 接口
    支持小端/大端,字节/半字/字访问。
    八、垫脚石(stepping stone)
    啊!上面忘记讲了。这个sram再引导过程结束后是可以用作其它用途的。
    嘿嘿,回头又看数据手册,原来它也要讲这条。我上面只是想插一条,下面再讲本条数据手册的内容呢。巧合!无巧不成书啊!
    这些都是有了一知半解后再回头看数据手册,根据自己理解做了些解释,自以为很详细了。但是我也知道,如果初次接触的话,

    还是看不懂。我会继续讲解其它内容,然后来这里做链接,希望对大家有所帮助。


    ECC PROGRAMMING GUIDE
    1. In software mode, ECC module generates ECC parity code for all read / write data. So you have to reset ECC
    value by writing the InitECC(NFCONT[4]) bit as ‘1’ and have to clear theMainECCLock(NFCONT[5]) bit to
    ‘0’(Unlock) before read or write data.
    MainECCLock(NFCONT[5]) and SpareECCLock(NFCONT[6]) control whether ECC Parity code is generated
    or not.
    2. Whenever data is read or written, the ECC module generates ECC parity code on register NFMECC0/1.
    3. After you completely read or write one page (not include spare area data), Set the MainECCLock bit to
    ‘1’(Lock). ECC Parity code is locked and the value of the ECC status register will not be changed.
    4. To generate spare area ECC parity code, Clear as ‘0’(Unlock) SpareECCLock(NFCONT[6]) bit.
    5. Whenever data is read or written, the spare area ECC module generates ECC parity code on register
    NFSECC.
    6. After you completely read or write spare area, Set the SpareECCLock bit to ‘1’(Lock). ECC Parity code is
    locked and the value of the ECC status register will not be changed.
    7. Once completed you can use these values to record to the spare area or check the bit error.


    ECC编程指南
    1.在软件模式,ECC模块为所有的读数据或写数据产生ECC校验代码。所以必须在读数据或写数据之前通过往InitECC(NFCONT[4])位
    写‘1’和清除theMainECClock(NFCONT[5])位为‘0’重设ECC值。
    MainECCLock(NFCONT[5])和SpareECCLock(NFCONT[6])控制ECC检验代码是否产生。
    2.无论数据是写还是读时,ECC模块在寄存器 NFMECC0/1 产生ECC校验代码。
    3.在你完成读或写页后(不包括备用区数据),需设置MainECCLock(NFCONT[5])位为‘1’(锁状态)。ECC校验代码是被锁住的,同时
    ECC状态寄存器的值不会改变。
    4.为了产生备用区校验代码,清除SpareECCLock(NFCONT[6])位为‘0’(解锁状态)。
    5.无论数据是写还是读时,ECC模块在寄存器 NFSECC 产生ECC校验代码。
    6.在你完成读或写备用区后,需设置SpareECCLock(NFCONT[6])位为‘1’(锁状态)。ECC校验代码是被锁住的,同时ECC状态寄存器的
    值不会改变。
    7.一旦完成你可以使用这些值来记录备用区域或检查错误。

    展开全文
  • Nand Flash控制器

    千次阅读 2016-11-20 11:17:07
    回忆一下,一上电以后,Nand Flash的前面4K就会被拷贝到2440的片内存里面。 在前面几个程序,编译出来的程序都小于4K;如果我们编译出来的程序大于了4K,这时候Nand Flash的前面4K拷贝到2440的片内存里面,拷贝到...
  • 1 引言 在便携式电子产品如U盘、MP3播放器、数码相机中...使系统用户能够方便地使用NAND FLASH,为此提出了一种基于FPGA的NAND FLASH控制器的设计方法,并用VHDL给予实现,Modelsim得出仿真结果,并在ALTERA公司的EP2C
  • 这是NAND FLASH 控制器的verilog源码,很有参考价值! 这是NAND FLASH 控制器的verilog源码,很有参考价值!
  • 介绍了基于AMBA APB总线NandFlash控制器的设计,首先简单介绍了NandFlash的一些特点,然后详细介绍了NandFlash控制器的整体框架、具体功能及其内部的数据通路。该控制器通过ModelSim进行了仿真及FPGA板级验证,验证...
  • 随着大数据、云计算、移动互联网等信息技术新领域在近些年来的爆发式发展,整个社会对数据存储的需求正在快速增长。...在包括 SOPC 在内的各型片上系统中,集成 NAND Flash 控制器正成为一种常态。
  • 为了实现在轨卫星的数据的高效存储,本文设计了一种基于FPGA的NAND FLASH控制器。该控制器适配常用的异步NAND FLASH,支持对多片NAND FLASH阵列控制;支持NAND FLASH操作超时异常检测;支持对FLASH的复位、读数据、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,244
精华内容 5,697
关键字:

nandflash控制器