微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > S3C6410学习——Nand flash陷阱

S3C6410学习——Nand flash陷阱

时间:11-28 来源:互联网 点击:
当系统以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函数:

  1. intnand_read(unsignedintnand_start,unsignedintddr_start,unsignedintlen)
  2. {
  3. unsignedlongrest=len;
  4. unsignedlongaddr=nand_start;
  5. unsignedlongpage;
  6. unsignedchar*dest=(unsignedchar*)ddr_start;
  7. inti;
  8. nand_select();
  9. while(rest>0){
  10. nand_cmd(0x00);
  11. nand_addr(addr);
  12. nand_cmd(0x30);
  13. nand_ready();
  14. page=rest>PAGE_SIZE?PAGE_SIZE:rest;
  15. for(i=0;i!=page;++i){
  16. *dest++=NFDATA;
  17. }
  18. rest-=page;
  19. addr+=page;
  20. }
  21. nand_deselect();
  22. return0;
  23. }


如上,我们可以完成必要的硬件初始化后用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函数应该这样写:

  1. voidcopy2ddr(unsignedlonglength){
  2. unsignedlongrest=length;
  3. unsignedlongsize;
  4. unsignedlongi;
  5. for(i=0;i!=4;++i){
  6. size=rest>2048?2048:rest;
  7. nand_read(PAGE_SIZE*i,0x50000000+i*2048,size);
  8. rest-=size;
  9. if(rest==0)
  10. return;
  11. }
  12. nand_read(PAGE_SIZE*4,0x50000000+PAGE_SIZE,rest);
  13. }


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

  1. voidnand_write(unsignedintnand_start,unsignedchar*buf,unsignedintlen)
  2. {
  3. unsignedlongcount=0;
  4. unsignedlongaddr=nand_start;
  5. inti=nand_start%PAGE_SIZE;
  6. nand_select();
  7. while(count
  8. {
  9. nand_cmd(0x80);
  10. nand_addr(addr);
  11. for(;i
  12. {
  13. NFDATA=buf[count++];
  14. addr++;
  15. }
  16. nand_cmd(0x10);
  17. nand_ready();
  18. i=0;
  19. }
  20. nand_deselect();
  21. }


store2nand函数应该这样写:

  1. voidstore2nand(unsignedlongddr_start,unsignedlonglength){
  2. unsignedchar*src=(unsignedchar*)ddr_start;
  3. unsignedlongrest=length;
  4. unsignedlongsize;
  5. unsignedlongi;
  6. for(i=0;i!=4;++i){
  7. size=rest>2048?2048:rest;
  8. nand_write(PAGE_SIZE*i,src+2048*i,size);
  9. rest-=size;
  10. if(rest==0)
  11. return;
  12. }
  13. nand_write(PAGE_SIZE*4,src+2048*4,rest);
  14. }


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

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

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

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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top