新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > S3C6410學(xué)習(xí)——Nand flash陷阱

S3C6410學(xué)習(xí)——Nand flash陷阱

作者: 時(shí)間:2016-11-28 來(lái)源:網(wǎng)絡(luò) 收藏
當(dāng)系統(tǒng)以Nand方式啟動(dòng)時(shí),硬件將Nand Flash的前8KB拷貝到Steppingstone,然后從0地址開始運(yùn)行程序,在這8KB以內(nèi)代碼中,我們需要完成必要的硬件初始化,如果代碼超過(guò)8K,我們還需要將剩余代碼的搬移到鏈接地址處,一般在SDRAM/DDR中。其中,硬件部分需要初始化系統(tǒng)時(shí)鐘、DDR和NAND Flash三部分。這就是S3C6410以Nand方式啟動(dòng)時(shí)的大致流程,看上去跟ARM9(S3C2440)沒(méi)有差別,但是如果您親自動(dòng)手寫一下這個(gè)啟動(dòng)過(guò)程,你會(huì)發(fā)現(xiàn)ARM9跟ARM11還是存在若干差別的,這里我要說(shuō)的是Nand裸機(jī)驅(qū)動(dòng)的問(wèn)題。述了S3C6410的Nand方式啟動(dòng)流程,看上去跟ARM9(S3C2440)沒(méi)有太大差別,但是如果您親自動(dòng)手寫一下這個(gè)啟動(dòng)過(guò)程,你會(huì)發(fā)現(xiàn)ARM9跟ARM11還是存在若干差別的,這里我要說(shuō)的是Nand裸機(jī)驅(qū)動(dòng)的問(wèn)題。

我的開發(fā)板式Tiny6410,配置的Nand flash是K9GAG08U0E,塊空間1M,頁(yè)空間8K。于是可以實(shí)現(xiàn)nand_read函數(shù):

本文引用地址:http://butianyuan.cn/article/201611/322802.htm
  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)來(lái)將完整的代碼從Nand搬移到DDR中,開始我也是這樣想的,但是發(fā)現(xiàn)代碼根本無(wú)法運(yùn)行,后來(lái)調(diào)試了一下發(fā)現(xiàn),這樣只將代碼的前2K拷貝到DDR中,接下來(lái)的6K代碼丟失了,而再接下來(lái)的代碼是正確的!這很奇怪啊,手冊(cè)中明卻指出,該Nand的頁(yè)大小為8KB,但為何我實(shí)際讀取時(shí)卻只能讀取到2KB呢?原來(lái)S3C6410啟動(dòng)時(shí)拷貝的8K代碼不是存儲(chǔ)在Nand flash的第一頁(yè)上,而是存儲(chǔ)在Nand flash的前4頁(yè)上,每頁(yè)2K,總共8K,這是S3C6410芯片的硬件結(jié)構(gòu)決定的!也就是說(shuō),雖然我們的Nand flash的頁(yè)大小是8K,但是S3C6410為了適應(yīng)各種型號(hào)的Nand flash并保證硬件能正確的拷貝Nand flash中的前8K到SRAM中,硬性的加上這一規(guī)定。因此,nand2ddr函數(shù)應(yīng)該這樣寫:

  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. }

對(duì)應(yīng)還有寫操作,原理一樣,逆著寫回去,這里就不分析原理了,nand_write函數(shù):

  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函數(shù)應(yīng)該這樣寫:

  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函數(shù)可以用來(lái)下載程序時(shí)寫nand用,如果不按照這種方式將程序?qū)懭雗and,硬件就無(wú)法正確加載Nand flash的前8K代碼,程序也就無(wú)法正常運(yùn)行。

下面是我自己寫的Tiny6410裸機(jī)程序,arm-linux-gcc環(huán)境,如果需要可以下載了看看,代碼實(shí)現(xiàn)了系統(tǒng)時(shí)鐘、DDR、Nand flash還有串口的初始化,下面是鏈接地址,以后還會(huì)繼續(xù)完善:

下載地址:(前段時(shí)間忘了改了)

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



關(guān)鍵詞: S3C641Nandflash陷

評(píng)論


技術(shù)專區(qū)

關(guān)閉