uboot下读写nand flash以及nand_read()函数的实现

1、uboot下NAND操作指令 

      指令              Flash内地址        擦除长度

 nand erase     0x100000            0x200000 
       指令              内存中地址         Flash内地址 写入长度

 nand write     0x20000000        0x100000     0x200000 

nand read      0x20000000        0x100000     0x200000 

关于nand flash的时序分析,http://blog.chinaunix.net/uid-20178794-id-4111272.html这篇文章写得不错

2、分析读nand flash操作的时序图
(1)时序图

(2)相关分析

(3)步骤归纳

  • 发出片选信号,选中nand flash芯片
  • 发出00h命令
  • 发出5个地址序列,前两个对应的是列地址(对应一页中的某一列),后三个是行地址(对应的是某一页)
  • 发出30h命令
  • 等待nand flash准备好数据
  • nand flash准备好数据后,从nand flash 中读取数据
  • 取消片选信号,以确保进行其他与nand flash无关的操作影响到nand flash。

nand_read()函数的实

从nand flash的地址start_addr开始,读取数据大小为size的数据到buf指定的地址里。

void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;


#ifdef LARGER_NAND_PAGE(由于此宏在源程序中有定义,因而走下面第一路径)

//因为nand flash每次读操作是以page为单位的,而一个page 是2048字节(不同nand flash的page大小不一定相同)

//一个数如果是2048的倍数,低11位必须是0.这里&是按位与的意思,也就是size和start_addr是16进制数,而NAND_BLOCK_MASK_LP是十进制,它们都会转换成二进制,进行按位与操作。这里定义NAND_BLOCK_MASK_LP为2047,也就是首位为0,后11位为1,与2048的二进制首位为1,后11位为0按位相与后为0.
    if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) {
        return ;    /* 地址或长度不对齐 */
    }
#else
    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return ;    /* 地址或长度不对齐 */
    }
#endif


    /* 选中芯片 */
    nand_select_chip();

   
  
 for(i=start_addr; i < (start_addr + size);) {
 /*发出00h命令*/
      write_cmd(0);

 /* 发出5个周期的地址序列 */
      write_addr(i);
#ifdef LARGER_NAND_PAGE(程序中有定义,因为要区分nand flash 的大小页构造)

 /*发出30h命令*/

 write_cmd(0x30);
#endif

 /*发出空闲等待信号*/

   wait_idle();


#ifdef LARGER_NAND_PAGE

/*开始读取数据*/
      for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {     //这里的NAND_SECTOR_SIZE_LP定义为2048
#else
 for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
#endif

         *buf = read_data();
          buf++;
      }
    }


 /*取消片选信号*/

    nand_deselect_chip();
    
    return ;
}



版权声明:本文为qingkongyeyue原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。