JZ2440:nandflash

本篇文章链接:http://blog.csdn.net/qqliyunpeng/article/details/51180276

芯片的型号:K9F2G08U0C

1. 硬件部分:

1.1 简介:

  • 芯片大小:256M Byte
  • 记忆单元阵列:(256M + 8,192K)bit x 8bit
  • 擦写次数比较少:10 万次
  • 数据保留时间:10
  • 8个IO
    口进行数据和地址的复用,因此,读写的时候要用到多个周期

几个特殊的引脚:


引脚名字


引脚功能


RE#


读使能,低电平有效


WE#


写使能,上升沿有效


WP#


写保护,低电平有效


R/B#


READY/BUSY 输出,这个引脚表征设备操作的状态,低电平表示忙,高电平表示完成(状态包括:读、写、擦除)


PRE


POWER-ON READ 使能,高电平时上电时执行芯片的读操作

1.2 内部存储单元的组织结构:

对 nandflash 的结构的几点说明:

  1. 一页中 1k 表示的是main 区(用于存储用户数据)容量,32 表示的是 spare 区(用于在读写操作的时候存放校验码)容量
  2. 块的大小一般是 128kb、256kb、512kb,貌似这里更小,是64kb
  3. 每个块里边包含很多页,老的 nandflash ,页大小是 256 Bytes、512Bytes,这类被称作 small block,地址周期只有 4 个。常见的nandflash,页大小多数是 2k Bytes,被称作 big block,地址周期 5 个,更新的 nandflash 页大小是
    4k Bytes,这里的这个芯片,页大小是 2k Bytes,属于 big block。
  4. 这个芯片的写操作是以页为单位的,擦除是以块为单位的。
  5. 在一个块中,对每一页的编程必须是顺序的,比如,一个块中有128个页,那么你只能先对 Page0 编程,再对 Page1 编程 ...
  6. 为了能让 nandflash 作为启动介质,s3c2440 内部集成了4k 的 sram ,当从 nand 启动的时候,nandflash 代码的前 4k 空间会被赋值到 s3c2440 内部,然后从内部的 sram 开始启动。
  7. s3c2440 硬件产生 ECC 校验码。

2. 软件部分:

由于 s3c2440 内部有nand 的控制器,去查看芯片的原理图,自己编写时序操作程序不是明智的选择,正确的方式是配置好 s3c2440 的 nandflash 控制器:

2.1 初始化部分:

设置好时序中的几个间隔时间:

从 s3c2440 芯片手册上可以知道:

图1:

对于 CLE/ALE 上的时序,我们需要设置 TACLS,TWRPH0,TWRPH1,这几个都在 NFCONF 寄存器里。

寄存器


地址


R/W


描述


复位值


NFCONF


0x4E000000


R/W


Nandflash 的配置寄存器


0x0000100X


NFCONF


Bit


描述


初始值


Reserved


[15:14]


保留


-


TACLS


[13:12]


CLE & ALE duration setting value (0~3)

Duration =  HCLK x TACLS


01


...


...


...


...


TWRPH0


[10:8]


TWRPH0 duration setting value (0~7)

Duration =  HCLK x ( TWRPH0 + 1 )


000


...


...


...


...


TWRPH1


[6:4]


TWRPH1 duration setting value (0~7)

Duration =  HCLK x ( TWRPH1 + 1 )


000


从这里之后的几个都是由硬件决定(就是上下拉)的不需要软件管。

原理图中的这个地方设置的是上表中 TWRPH1 之后的位:

CCON = 1; // 支持 1k 字节或 2k 字字节每页的NAND flash存储器

GPG13 = 1; // 每页 2k 字节

GPG14 = 1; // 5个地址周期

GPG15 = 0; // 8位总线

要 求上边的 TACLS、TWRPH0、TWRPH1 的值:

  1. 我们假设 HCLK 为 是 100MHz 则 HCLK 的周期是 1/100MHz = 10ns
  2. 查看 nandflash 的数据手册,找到跟时间相关的时序图和时间:

时间表:

时序:

找一个跟上边 红字 图1 中都有的一张时序图:

我们把图一也拿过来

图1:

TACLS 时间是 tcls -twp,查 时间表 得到 15ns -15ns = 0ns

根据寄存器中描述的计算公式:Duration =  HCLK x TACLS =>  0ns = 10ns x TACLS  => TACLS = 0

TWRPH0 的时间是 twp ,查 时间表 得到 15ns

根据寄存器中描述的计算公式:Duration =  HCLK x ( TWRPH0 + 1 )  =>  15ns = 10ns x (TWRPH0 + 1)  => TWRPH0 = 0.5 ,由于他的取值范围是 (0~7) ,并且,时间表中的时间是最小能识别的时间,那我们取TWRPH0 =
1

TWRPH1 的时间是 tclh = 5ns

根据寄存器中描述的计算公式:Duration =  HCLK x ( TWRPH1 + 1 ) => 5ns = 10ns x (TWRPH1 + 1) => TWRPH1 = 0 即能满足

#define NFCONF  (*((volatile unsigned long *)0x4E000000))

void nand_init(void )
{
    #define TACLS   0
    #define TWRPH0  1
    #define TWRPH1  0

    /* 设置时序 */
    NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
    /* 使能 nandflash 控制器,初始化ECC,关片选 */
    NFCONT = (1<<4)|(1<<1)|(1<<0);
}

2.2 芯片的选择和禁止(让芯片操作 CE 引脚):

#define NFCONT  (*((volatile unsigned long *)0x4E000004))

void nand_select(void )
{
    NFCONT &= ~(1<<1);
}

void nand_deselect(void )
{
    NFCONT |= (1<<1);
}

2.3 写命令和写地址:

// 写命令 注意是八位的命令
#define NFCMMD (*((volatile unsigned char *)0x4E000008))

void nand_cmd(unsigned char cmd)
{
 volatile int i;
 NFCMMD = cmd;
 for (i = 0; i<10; i++); // 延时一段时间
}

// 写地址
#define NFADDR (*((volatile unsigned char *)0x4E00000C))
#define NAND_SECTOR_SIZE    2048
#define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE_LP - 1)

void nand_addr(unsigned int addr)
{
// unsigned int col = addr % 2048;
// unsigned int page = addr / 2048;
 col = addr & NAND_BLOCK_MASK;
 page = addr / NAND_SECTOR_SIZE;
 volatile int i;
 NFADDR = col & 0xff;                /* Column Address A0~A7 */
 for (i = 0; i<10; i++);
 NFADDR = (col>>8) & 0x0f;       /* Column Address A8~A11 */
 for (i = 0; i<10; i++);
 NFADDR = page & 0xff;            /* Row Address A12~A19 */
 for (i = 0; i<10; i++);
 NFADDR = (page>>8) & 0xff;   /* Row Address A20~A27 */
 for (i = 0; i<10; i++);
 NFADDR = (page>>16) & 0x03;  /* Row Address A28~A29 */
 for (i = 0; i<10; i++);
}

对程序的解释:

flash芯片的手册上有对于大页 flash 的访问 各个周期传递的位:

因此上边的命令 NFADDR = ... 就不难理解了。

至于,各个周期间的延时:

从flash芯片的数据手册上知道:

对于 I/O 引脚上的数据进行采集是在 WE 的上升沿进行的,因此, 每两个周期的间隔至少应该大于一个 tDS = 15ns,而对 flash 他的时钟来自 HCLK = 100MHz(这里如果不懂,可以查看我之前的文章(JZ2440:时钟设置)),即使是单周期指令,也要
10ns,因此,要延时一段时间。

2.4 读数据:

flash 芯片上:

flash 芯片上:

#define NFSTAT (*((volatile unsigned char *)0x4E000020))
#define NFDATA (*((volatile unsigned char *)0x4E000010))
void nand_wait_teady(void)
{
    while(!(NFSTAT & 1))
         for(i = 0; i < 10; i++);
}

unsigned char nand_data(void)
{
    return NFDATA;
}
/*
* 参数的含义: addr 要读的地址,buf 读出来的数据存放的缓存,len 要读的长度
*/
void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
{
    int col = addr % 2048;
    int i = 0 ;

    nand_select(); // 选中芯片
    while(i < len)
    {
        nand_cmd(0x00); // 发出读命令 00h
        nand_addr(addr); // 发送读的地址
        nand_cmd(0x30); // 发出读命令 30h
        nand_wait_ready(); // 等待不忙

        for(;(col < 2048) && (i < len);col++)
        {
            buf[i] = nand_data(); // 读数据
            i++;
            addr++;
        }
        col = 0;
    }
    nand_deselect(); // 取消片选
}

2.5 复位 flash 芯片:

知道了上边的命令的表格,那 复位的实现也就简单了:

void nand_reset(void)
{
    nand_select(); // 选中芯片
    nand_cmd(0xff);
    nand_read_ready();
    nand_deselect();
}
时间: 2024-10-04 19:53:09

JZ2440:nandflash的相关文章

u-boot分析1:Nandflash、Norflash启动

了解u-boot之前首先了解下Bootloader,简单说Bootloader就是一段小程序,它在系统上电时开始运行,初始化硬件设备,准备好软件环境,最后调用操作系统内核. u-boot全称:Universal Boot Loader,即通用Bootloader,遵循GPL条款,开放源码. 支持多种嵌入式操作系统内核:Linux.NetBSD.VxWorks等 支持多个处理器系列:如PowerPC.ARM.x86.MIPS等 u-boot的核心最终目的就是从Flash上读出内核,然后启动内核.如

JZ2440:norflash

采用的器件是:29lv160dbt1-70g 1. 简介: norflash 的特点是: NOR Flash 的特点是芯片内执行(XIP ,eXecute In Place),这样应用程序可以直接在Flash闪存内运行,不必再把代码读到系统RAM中. NOR 的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响到它的性能. 由于擦除NOR器件时是以64-128KB的块进行的,执行一个写入/擦除操作的时间为5s NOR Flash 能够像内存一样读操作,不能像

JZ2440:时钟设置

这一节的目标是对板子上的时钟有一个初步的了解.而且能通过初步设置.为我们接下来的程序做准备. 1. 板子上的基本资源: 板载晶振12M 主时钟源和 USB 时钟源都是晶振 2. 手冊中的相关项(按时钟进入的方向): 2.1 时钟的总体结构: 2.2 OM[ 3:2 ]: 从图中我们能够看到OM[] 起到可选择的作用(效果同三八译码器): 模式 OM[3:2] MPLL状态 UPLL 状态 主时钟源 USB 时钟源 00 开启 开启 晶振 晶振 01 开启 开启 晶振 外部时钟 10 开启 开启

9.NandFlash的驱动_读操作2440

9.NandFlash的驱动_读操作 在Makefile里添加nand.o,然后新建一个nand.c来实现NandFlash的读操作. 对NandFlash的读方式有两种: 按页读(需要提供页地址,也就是行地址). 随机读(就是读取页里的某一列,需要提供页地址,也就是行地址和列地址). 实现页读需要两个操作,一个是页地址,另一个是存放读出的数据的变量.所以定义的函数的原型: void NF_PageRead(unsigned long addr,unsigned char* buff) 该函数根

nandflash裸机程序分析

原文: nandflash裸机程序分析 它包含7个文件: head.S init.c main.c Makefile nand.c nand.lds 我们之前的程序都是在nandflash的前4k放代码,上电后自动拷贝到SRAM中,之后将SRAM中的代码拷贝到SDRAM中.可是当我们的程序太大超过4k的时候就不行了,因为无法将nandflash的代码完全拷贝到SRAM中去,这时就需要从nandflash中拷贝代码了. 本程序里面我们要实现的就是:将一部分代码放在nandflash的4096之后,

【转】深度分析NandFlash—物理结构及地址传送(以TQ2440开发板上的K9F2G08U0A为例)

K9F2G08U0A是三星公司生产的总容量为256M的NandFlash,常用于手持设备等消费电子产品.还是那句话,搞底层就得会看datasheet,我们就从它的datasheet看起. 这就是 K9F2G08U0A的内部结构,具体的各个部件的介绍,就不详细介绍了,想了解的话可以参考伟东山的<嵌入式linux应用开发完全手册>. 现在就看一下重点的,NandFlash的存储单元的组织结构,K9F2G08U0A的存储单元的组织结构如下: 结合上面的图,我们现在来分析一下: NandFlash的存

arm:判断是从nand启动还是从norflash启动

//int bBootFrmNORFlash(void) :判断是否从norflash启动. //ret==1 :norflash启动 //ret==0 :nandflash启动.(或者是jlink调试的情况.) //该函数应用范围有限,只针对于bootloader最初的stage1. int bBootFrmNORFlash(void) { volatile unsigned int *pdw = (volatile unsigned int *)0; unsigned int dwVal;

嵌入式Linux裸机开发(十一)——Nandflash

嵌入式Linux裸机开发(十一)--Nandflash 一.Nand Flash简介 NandFlash是Flash的一种,具有容量较大,改写速度快等优点,适用于大量数据的存储.NandFlash没有专门的地址线,发送指令.地址和数据都通过8/16位宽的总线(I/O接口)到内部的寄存器. NandFlash分为SLC和MLC两类.SLC全称为Single-Level Cell,单层单元闪存,MLC全称为Multi-Level Cell,多层单元闪存.SLC每一个单元储存一位数据,而MLC通过使用

ok6410 uboot nandflash移植

1.4  Nandflash移植 先解决上面的错误,修改arch/arm/cpu/arm1176/s3c64xx/timer.c static ulong timer_load_val;修改为 DECLARE_GLOBAL_DATA_PTR; 删除下面的两个定义: /* Internal tick units */ /* Last decremneter snapshot */ static unsigned long lastdec; /* Monotonic incrementing tim