Chinaunix首页 | 论坛 | 博客
  • 博客访问: 45330
  • 博文数量: 11
  • 博客积分: 490
  • 博客等级: 下士
  • 技术积分: 140
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-24 11:23
文章分类
文章存档

2011年(1)

2009年(10)

我的朋友

分类: LINUX

2009-08-12 13:17:56

1 要写某个块时,先要擦除这个块。

2 Nand Flash 一般以512字节为单位进行读写

3 Nand flash上发生位反转,推荐使用EDC/ECC进行错误检测和恢复

4 Nor Flash上常使用jffs2文件系统,在Nand  Flash上常用yaffs文件系统,在更底层,有MTD驱动程序实现对它们的读、写、擦除操作,它也实现了EDC/ECC校验

5 当读、写某页时会先将数据读入\写入页寄存器,大小为528字节

6 NAND Flash K9F1028U0M存储单元组织结构

11=512+16)字节

16字节额外空间的列地址为512---527

21=32=512+16)字节*32=(16K+512)字节

31个器件=4096=4096*16K+512)字节=64M+2M

7地址分析

 1)行地址即页地址:A9---A25

      列地址用来在半页(256字节)中寻址:A0---A7

  (2)读命令00:列地址将在上半部分寻址 A8=0A0---A7

     读命令01:列地址将在下半部分寻址 A8=1A0---A7

     读命令50:寻址列地址为512---52716字节 A0---A3

8 命令介绍

1Read 1

 00h:A区开始读

 01h:B区开始读

 命令字--->4个地址序列--->检测R/nB引脚以确实Flash是否准备好

 具体用法看下面实验

2Read 2

 50h:C区数据

命令字--->4个地址序列--->检测R/nB引脚以确实Flash是否准备好

3Read ID

90h--->4个地址序列(都为0)--->连续读5个数据

4)复位

 FFh

(5)写页

80h--->4个地址序列--->发送数据--->10h--->70h(检测是否成功,是否完成)

(6)写多页

      16M

     528字节寄存器

 

 

 

 

 

 

 

 

第一层:80h--->4个地址序列--->数据(最多528字节)--->11h--->71h( 检测写操作是否完成,是否成功)

第二层:80h--->4个地址序列--->数据(最多528字节)--->11h--->71h( 检测写操作是否完成,是否成功)

第三层:80h--->4个地址序列--->数据(最多528字节)--->11h--->71h( 检测写操作是否完成,是否成功)

第三层:80h--->4个地址序列--->数据(最多528字节)--->11h--->71h( 检测写操作是否完成,是否成功)

第四层:80h--->4个地址序列--->数据(最多528字节)--->11h--->71h( 检测写操作是否完成,是否成功)

(7)将一页复制到同一层的另一页

源地址、目的地址A14A15必须相同

00--->4个源地地址序列--->8A--->4个目的地址序列--->10h(写数据)--->70h(检测此操作是否完成,是否成功)

(8)同时进行多个层的复制操作

00h(读操作)--->源地址--->03h--->源地址--->03h--->源地址--->03h--->8Ah---->目的地址--->11h--->8Ah---->目的地址--->11h--->8Ah---->目的地址--->10h

(9)块擦除

60h--->3个地址序列(234 cycle A9---A13被忽略,A14---A25对应4096个块寻址)--->D0h--->70h(检测此操作是否完成,是否成功)

(10)同时擦除不同层中的块

--->60h--->地址--->60h--->地址--->60h--->地址--->60h--->地址--->D0h--->71h(检查擦除操作是否成功)

(11)读状态(读入状态寄存器)

70h:一层时用

71h:多层时用

9NAND Flash

(1)NFCONF=0x300

0

0

00

0

011

0

000

0000

 

 

[13:12] TACLS=0

 

[10:8] TWRPH0=3

 

[6:4] TWRPH1=0

 

 

 

 

 

 

 

 

 

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

            初始化ECC    禁止控制引脚信号   使能Nand Flash控制器

(3)第一次操作NAND Flash前,通常复位一下NAND flash

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

NFCOM=0xff  复位命令

然后循环查询NFSTAT0,直到它等于1

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

NFCONF|=0x2 禁止NAND Flash

(4) 先使能NAND Flash,然后发出读命令

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

NFCMD=0 读命令 此时A8=0

(5) 发出地止信号

NFADRR=addr&0xff   A0---A7

NFADRR=(addr>>9)&0xff    A9---A16

NFADRR=(addr>>17)&0xff   A17---A24

NFADRR=(addr>>25)&0xff   A25

(6) 循环查询NFSTAT0,直到它等于1,这时就可以读取数据了

(7)连续读NFDATA寄存器512次,得到一页数据(循环执行4567

(8)最后禁止NAND lash片选信号

NFCONT|=(1<<1)

10关键部分代码详解 完整代码:nandflash.tar.gz

这个实验源码文件较多,可用source insight来分析

(1)/* 初始化NAND Flash */

void nand_init(void)

{

#define TACLS   0

#define TWRPH0  3

#define TWRPH1  0

 

    /* 判断是S3C2410还是S3C2440 */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

    {

        nand_chip.nand_reset         = s3c2410_nand_reset;

        nand_chip.wait_idle          = s3c2410_wait_idle;

        nand_chip.nand_select_chip   = s3c2410_nand_select_chip;

        nand_chip.nand_deselect_chip = s3c2410_nand_deselect_chip;

        nand_chip.write_cmd          = s3c2410_write_cmd;

        nand_chip.write_addr         = s3c2410_write_addr;

        nand_chip.read_data          = s3c2410_read_data;

 

        /* 使能NAND Flash控制器, 初始化ECC, 禁止片选, 设置时序 */

        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

    }

    else

    {

        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;

        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();

}

 

(2)/* 读函数 */

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

{

    int i, j;

   

    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {

        return ;    /* 地址或长度不对齐 */

    }

 

    /* 选中芯片 */

    nand_select_chip();

 

    for(i=start_addr; i < (start_addr + size);) {

      /* 发出READ0命令 */

      write_cmd(0);

 

      /* Write Address */

      write_addr(i);

      wait_idle();

 

      for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {

          *buf = read_data();

          buf++;

      }

    }

 

    /* 取消片选信号 */

    nand_deselect_chip();

    

    return ;

}

 

 

阅读(1922) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~