加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Nand flash陷阱

发布时间:2020-12-15 17:29:20 所属栏目:百科 来源:网络整理
导读:转载:http://blog.csdn.net/girlkoo/article/details/8115849 当系统以Nand方式启动时,硬件将Nand Flash的前8KB拷贝到Steppingstone,然后从0地址开始运行程序,在这8KB以内代码中,我们需要完成必要的硬件初始化,如果代码超过8K,我们还需要将剩余代码的

转载:http://blog.csdn.net/girlkoo/article/details/8115849

当系统以Nand方式启动时,硬件将Nand Flash的前8KB拷贝到Steppingstone,然后从0地址开始运行程序,在这8KB以内代码中,我们需要完成必要的硬件初始化,如果代码超过8K,我们还需要将剩余代码的搬移到链接地址处,一般在SDRAM/DDR中。其中,硬件部分需要初始化系统时钟、DDR和NAND Flash三部分。这就是S3C6410以Nand方式启动时的大致流程,看上去跟ARM9(S3C2440)没有差别,但是如果您亲自动手写一下这个启动过程,你会发现ARM9跟ARM11还是存在若干差别的,这里我要说的是Nand裸机驱动的问题。述了S3C6410的Nand方式启动流程,看上去跟ARM9(S3C2440)没有太大差别,但是如果您亲自动手写一下这个启动过程,你会发现ARM9跟ARM11还是存在若干差别的,这里我要说的是Nand裸机驱动的问题。

我的开发板式Tiny6410,配置的Nand flash是K9GAG08U0E,块空间1M,页空间8K。于是可以实现nand_read函数:

[cpp]? view plain copy

在CODE上查看代码片

派生到我的代码片

  1. int?nand_read(unsigned?int?nand_start,?unsigned?int?ddr_start,87); font-weight:bold; background-color:inherit">int?len)??
  2. {??
  3. ????unsigned?long?rest?=?len;??
  4. ????unsigned?long?addr?=?nand_start;??
  5. long?page;??
  6. char?*dest?=?(unsigned?char?*)ddr_start;??
  7. ????int?i;??
  8. ??
  9. ????nand_select();??
  10. ????while(rest?>?0){??
  11. ????????nand_cmd(0x00);??
  12. ????????nand_addr(addr);??
  13. ????????nand_cmd(0x30);??
  14. ????????nand_ready();??
  15. ??
  16. ????????page?=?rest>PAGE_SIZE?PAGE_SIZE:rest;??
  17. ????????for(i?=?0;?i?!=?page;?++i){??
  18. ????????????*dest++?=?NFDATA;??
  19. ????????}??
  20. ????????rest?-=?page;??
  21. ????????addr?+=?page;??
  22. ????}??
  23. ????nand_deselect();??
  24. ????return?0;??
  25. }??

如上,我们可以完成必要的硬件初始化后用nand_read(0,0x50000000,__bss_start-_start)来将完整的代码从Nand搬移到DDR中,开始我也是这样想的,但是发现代码根本无法运行,后来调试了一下发现,这样只将代码的前2K拷贝到DDR中,接下来的6K代码丢失了,而再接下来的代码是正确的!这很奇怪啊,手册中明却指出,该Nand的页大小为8KB,但为何我实际读取时却只能读取到2KB呢?原来S3C6410启动时拷贝的8K代码不是存储在Nand flash的第一页上,而是存储在Nand flash的前4页上,每页2K,总共8K,这是S3C6410芯片的硬件结构决定的!也就是说,虽然我们的Nand flash的页大小是8K,但是S3C6410为了适应各种型号的Nand flash并保证硬件能正确的拷贝Nand flash中的前8K到SRAM中,硬性的加上这一规定。因此,nand2ddr函数应该这样写:

派生到我的代码片

    void?copy2ddr(unsigned?long?length){??
  1. long?rest?=?length;??
  2. long?size;??
  3. long?i;??
  4. for(i?=?0;?i?!=?4;?++i){??
  5. ????????size?=?rest>2048?2048:rest;??
  6. ????????nand_read(PAGE_SIZE*i,?0x50000000+i*2048,?size);??
  7. ????????rest?-=?size;??
  8. ????????if(rest?==?0)??
  9. ????????????return;??
  10. ????nand_read(PAGE_SIZE*4,?0x50000000+PAGE_SIZE,?rest);??
  11. }??

对应还有写操作,原理一样,逆着写回去,这里就不分析原理了,nand_write函数:

派生到我的代码片

    void?nand_write(unsigned?char?*?buf,87); font-weight:bold; background-color:inherit">long?count?=?0;??
  1. long?addr??=?nand_start;??
  2. int?i?=?nand_start?%?PAGE_SIZE;??
  3. while?(count?<?len)??
  4. ????{??
  5. ????????nand_cmd(0x80);??
  6. ????????nand_addr(addr);??
  7. for?(;?i?<?PAGE_SIZE?&&?count?<?len;?i++)??
  8. ????????{??
  9. ????????????NFDATA?=?buf[count++];??
  10. ????????????addr++;??
  11. ????????}??
  12. ????????nand_cmd(0x10);??
  13. ????????i?=?0;??
  14. }??

store2nand函数应该这样写:

派生到我的代码片

    void?store2nand(unsigned?long?ddr_start,87); font-weight:bold; background-color:inherit">char*?src?=?(unsigned?char*)ddr_start;??
  1. long?rest?=?length;??
  2. long?size;??
  3. long?i;??
  4. for(i?=?0;?i?!=?4;?++i){??
  5. ????????size?=?rest>2048?2048:rest;??
  6. ????????nand_write(PAGE_SIZE*i,?src+2048*i,?size);??
  7. ????????rest?-=?size;??
  8. if(rest?==?0)??
  9. ????????????return;??
  10. ????}??
  11. ????nand_write(PAGE_SIZE*4,?src+2048*4,?rest);??
  12. }??

store2nand函数可以用来下载程序时写nand用,如果不按照这种方式将程序写入nand,硬件就无法正确加载Nand flash的前8K代码,程序也就无法正常运行。

下面是我自己写的Tiny6410裸机程序,arm-linux-gcc环境,如果需要可以下载了看看,代码实现了系统时钟、DDR、Nand flash还有串口的初始化,下面是链接地址,以后还会继续完善:

下载地址:(前段时间忘了改了)

http://download.csdn.net/detail/girlkoo/4690705

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读