【ARM裸板】Nand Flash编程

本文详细介绍了NAND Flash的编程,包括读芯片ID、读数据、擦除、写数据的过程,以及坏块判断和ECC错误检测。内容涵盖时序、地址序列、数据流程和功能测试,帮助理解NAND Flash的操作机制。
摘要由CSDN通过智能技术生成

1.读芯片ID

1.1 读芯片ID时序

简化为4个步骤:

  • 1.使能片选
  • 2.写命令0x90
  • 3.写地址0x00
  • 4.读ID信息
/* 识别NAND FLASH */
void scan_nand_flash(void)
{
   
   int i;
   //保存读取ID信息的数组
   unsigned char id_info[5] = {
   0};

   nand_enable_cs();//使能CS
   nand_write_cmd(0x90);
   nand_write_addr(0x00);

   for(i = 0;i < 5;i++){
   
   	id_info[i] = nand_read_data();
   }
   nand_disable_cs();//禁止CS
   
   printf("Maker  Code: 0x%x\r\n",id_info[0]);
   printf("Device Code: 0x%x\r\n",id_info[1]);
   printf("3rd   cycle: 0x%x\n\r",id_info[2]);
   printf("Page   size: %d KB\n\r",1  << (id_info[3] & 0x03));//页大小与id_info[3]最低2位有关
   printf("Block  size: %d KB\n\r",64 << ((id_info[3] >> 4) & 0x03));//块大小与id_info[3]第4、5位有关

   printf("5th   cycle: 0x%x\n\r",id_info[4]);

1.2 由ID数据获得芯片参数

  • ID信息的第4字节为0x95
  • 页大小与id_info[3]最低2位有关,可得页大小为:2KB
  • 块大小与id_info[3]第4、5位有关,可得块大小为:128KB

注意:如果此时烧写到Nand Flash,并从Nand Flash启动程序是不会成功的,因为这个bin文件大小已经超过了4K,且现在还没有实现nand flash的读函数。

2.读数据

目标:实现从NAND FLASH中启动,重定位所有数据至SDRAM,并实现读取芯片ID数据

2.1 NAND内部结构分析

  • OOB:out of bank(在bank之外)
    由上图可得:
  • 1Page = 2KB + 64B
  • 1Block = 64 * Pages = 128KB + 4KB
  • 1Device = 2048 * Blocks = 256MB + 8MB

  • OOB区的作用:因为nand的缺点是会发生“位反转”,为了解决这个问题,nand中的OOB区,用于校验数据区的数据是否发生错误,当有错误时,可以恢复数据。(其本身不存储数据)
  • 因为OOB中并不存放数据,只是用于校验数据区是否发生错误,因此当CPU读取Nand Flash第2048个数据,该数据为 Page1中的第0个byte

2.2 地址序列与时序

  • 由地址序列可以看出:发出地址信号共需5个周期,前2个周期发出列地址(Column Address),后3个周期发出行地址(Row Address)
  • 地址线序列有一些位是没有用到的,其目的也是以后兼容更大芯片的nand falsh

Nand Flash内部结构展开大致如下:

2.3 读数据流程

  • 1.发出片选信号
  • 2.发出0x00命令
  • 3.发送5个周期的地址(两个列地址,三个行地址(page))
  • 4.再发送0x30命令
  • 5.等待就绪
  • 6.读数据
  • 7.禁止片选

2.4 转换所读地址的列与页

将输入的地址addr转换为:

  • 列地址(Col Address)
    • page是定位到哪一个页,col变量定位的就是在这个页的偏移量(在这个页上的第几列0~2047)
  • 行地址(页)
    • 因为读取数据的时候是一次性读出一页,因此当给出地址addr之后,每一页的数据大小是2K,因此我们可以根据地址知道我们读取的数据是哪一个页
	int col  = addr % 2048;//列地址  addr &(2048-1); 

	int page = addr / 2048;//行地址(相当于页地址)

2.5 NAND等待就绪

  • 当NFSATA[0] = 0时,表示正忙
  • 当NFSATA[0] = 1时,表示就绪
/* 等待NAND就绪 */
void nand_wait_ready(void)
{
   
	while(!(NFSTAT & 0x01));//当NFSATA[0] = 1时,表示就绪
}

2.6 读取数据函数

/* NAND FLASH读取数据
 * param:读取的地址、存放的地址、读取的长度
 */
void read_nand_data(unsigned int addr,unsigned char *buf,unsigned int len)
{
   
	int i = 0;

	/*page是定位到哪一个页,col变量定位的就是在这个
	 *页的偏移量(在这个页上的第几列0~2047)
	 */
	int col  = addr % 2048;//列地址  addr &(2048-1); 

    /* 因为读取数据的时候是一次性读出一页,因此当给出
	 * 地址addr之后,每一页的数据大小是2K,因此我们可以
	 * 根据地址知道我们读取的数据是哪一个页
	 */
	int page = addr / 2048;//行地址(相当于页地址)

	
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值