nand.c
上传用户:zbk8730
上传日期:2017-08-10
资源大小:12168k
文件大小:7k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2.  support 512/page NAND Flash only
  3. */
  4. #include <string.h>
  5. #include "2440addr.h"
  6. #include "2440lib.h"
  7. #include "2440slib.h"
  8. #include "Nand.h"
  9. //suppport boot params
  10. #define EnNandFlash() (rNFCONT |= 1)
  11. #define DsNandFlash() (rNFCONT &= ~1)
  12. #define NFChipEn() (rNFCONT &= ~(1<<1))
  13. #define NFChipDs() (rNFCONT |= (1<<1))
  14. #define InitEcc() (rNFCONT |= (1<<4))
  15. #define MEccUnlock() (rNFCONT &= ~(1<<5))
  16. #define MEccLock() (rNFCONT |= (1<<5))
  17. #define SEccUnlock() (rNFCONT &= ~(1<<6))
  18. #define SEccLock() (rNFCONT |= (1<<6))
  19. #define WrNFDat8(dat) (rNFDATA8 = (dat))
  20. #define WrNFDat32(dat) (rNFDATA = (dat))
  21. #define RdNFDat8() (rNFDATA8) //byte access
  22. #define RdNFDat32() (rNFDATA) //word access
  23. #define WrNFCmd(cmd) (rNFCMD = (cmd))
  24. #define WrNFAddr(addr) (rNFADDR = (addr))
  25. #define WrNFDat(dat) WrNFDat8(dat)
  26. #define RdNFDat() RdNFDat8() //for 8 bit nand flash, use byte access
  27. #define RdNFMEcc() (rNFMECC0) //for 8 bit nand flash, only use NFMECC0
  28. #define RdNFSEcc() (rNFSECC) //for 8 bit nand flash, only use low 16 bits
  29. #define RdNFStat() (rNFSTAT)
  30. #define NFIsBusy() (!(rNFSTAT&1))
  31. #define NFIsReady() (rNFSTAT&1)
  32. //#define WIAT_BUSY_HARD 1
  33. //#define ER_BAD_BLK_TEST
  34. //#define WR_BAD_BLK_TEST
  35. #define READCMD0 0
  36. #define READCMD1 1
  37. #define READCMD2 0x50
  38. #define ERASECMD0 0x60
  39. #define ERASECMD1 0xd0
  40. #define PROGCMD0 0x80
  41. #define PROGCMD1 0x10
  42. #define QUERYCMD 0x70
  43. #define RdIDCMD 0x90
  44. static U16 NandAddr;
  45. // HCLK=100Mhz
  46. #define TACLS 1//7 // 1-clk(0ns) 
  47. #define TWRPH0 4//7 // 3-clk(25ns)
  48. #define TWRPH1 0//7 // 1-clk(10ns)  //TACLS+TWRPH0+TWRPH1>=50ns
  49. static void InitNandCfg(void)
  50. {
  51. // for S3C2440
  52. rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
  53. // TACLS [14:12] CLE&ALE duration = HCLK*TACLS.
  54. // TWRPH0 [10:8] TWRPH0 duration = HCLK*(TWRPH0+1)
  55. // TWRPH1 [6:4] TWRPH1 duration = HCLK*(TWRPH1+1)
  56. // AdvFlash(R) [3] Advanced NAND, 0:256/512, 1:1024/2048
  57. // PageSize(R) [2] NAND memory page size
  58. // when [3]==0, 0:256, 1:512 bytes/page.
  59. // when [3]==1, 0:1024, 1:2048 bytes/page.
  60. // AddrCycle(R) [1] NAND flash addr size
  61. // when [3]==0, 0:3-addr, 1:4-addr.
  62. // when [3]==1, 0:4-addr, 1:5-addr.
  63. // BusWidth(R/W) [0] NAND bus width. 0:8-bit, 1:16-bit.
  64. rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
  65. // Lock-tight [13] 0:Disable lock, 1:Enable lock.
  66. // Soft Lock [12] 0:Disable lock, 1:Enable lock.
  67. // EnablillegalAcINT[10] Illegal access interupt control. 0:Disable, 1:Enable
  68. // EnbRnBINT [9] RnB interrupt. 0:Disable, 1:Enable
  69. // RnB_TrandMode[8] RnB transition detection config. 0:Low to High, 1:High to Low
  70. // SpareECCLock [6] 0:Unlock, 1:Lock
  71. // MainECCLock [5] 0:Unlock, 1:Lock
  72. // InitECC(W) [4] 1:Init ECC decoder/encoder.
  73. // Reg_nCE [1] 0:nFCE=0, 1:nFCE=1.
  74. // NANDC Enable [0] operating mode. 0:Disable, 1:Enable.
  75. // rNFSTAT = 0;
  76.     
  77. //    Nand_Reset();
  78. }
  79. #ifdef WIAT_BUSY_HARD
  80. #define WaitNFBusy() while(NFIsBusy())
  81. #else
  82. static U32 WaitNFBusy(void) // R/B 未接好?
  83. {
  84. U8 stat;
  85. WrNFCmd(QUERYCMD);
  86. do {
  87. stat = RdNFDat();
  88. //Uart_Printf("%xn", stat);
  89. }while(!(stat&0x40));
  90. WrNFCmd(READCMD0);
  91. return stat&1;
  92. }
  93. #endif
  94. U32 ReadChipId(void)
  95. {
  96. U32 id;
  97. NFChipEn();
  98. WrNFCmd(RdIDCMD);
  99. WrNFAddr(0);
  100. while(NFIsBusy());
  101. id  = RdNFDat()<<8;
  102. id |= RdNFDat();
  103. NFChipDs();
  104. return id;
  105. }
  106. U16 ReadStatus(void)
  107. {
  108. U16 stat;
  109. NFChipEn();
  110. WrNFCmd(QUERYCMD);
  111. stat = RdNFDat();
  112. NFChipDs();
  113. return stat;
  114. }
  115. static U32 EraseBlock(U32 addr)
  116. {
  117. U8 stat;
  118. addr &= ~0x1f;
  119. NFChipEn();
  120. WrNFCmd(ERASECMD0);
  121. WrNFAddr(addr);
  122. WrNFAddr(addr>>8);
  123. if(NandAddr)
  124. WrNFAddr(addr>>16);
  125. WrNFCmd(ERASECMD1);
  126. stat = WaitNFBusy();
  127. NFChipDs();
  128. #ifdef ER_BAD_BLK_TEST
  129. if(!((addr+0xe0)&0xff)) stat = 1; //just for test bad block
  130. #endif
  131. Uart_Printf("Erase block 0x%x %sn", addr, stat?"fail":"ok");
  132. return stat;
  133. }
  134. //addr = page address
  135. void ReadPage(U32 addr, U8 *buf)
  136. {
  137. U16 i;
  138. NFChipEn();
  139. WrNFCmd(READCMD0);
  140. WrNFAddr(0);
  141. WrNFAddr(addr);
  142. WrNFAddr(addr>>8);
  143. if(NandAddr)
  144. WrNFAddr(addr>>16);
  145. InitEcc();
  146. WaitNFBusy();
  147. for(i=0; i<512; i++)
  148. buf[i] = RdNFDat();
  149. NFChipDs();
  150. }
  151. static U32 WritePage(U32 addr, U8 *buf)
  152. {
  153. U32 i, mecc;
  154. U8 stat, tmp[7];
  155. NFChipEn();
  156. WrNFCmd(PROGCMD0);
  157. WrNFAddr(0);
  158. WrNFAddr(addr);
  159. WrNFAddr(addr>>8);
  160. if(NandAddr)
  161. WrNFAddr(addr>>16);
  162. InitEcc(); //reset mecc and secc
  163. MEccUnlock();
  164. for(i=0; i<512; i++)
  165. WrNFDat(buf[i]);
  166. MEccLock();
  167. mecc = RdNFMEcc();
  168. tmp[0] = mecc&0xff;
  169.     tmp[1] = (mecc>>8)&0xff;
  170.     tmp[2] = (mecc>>16)&0xff;
  171.     tmp[3] = (mecc>>24)&0xff;
  172.     tmp[5] = 0xff; //mark good block
  173.     
  174.     SEccUnlock();
  175. WrNFDat(tmp[0]);
  176. WrNFDat(tmp[1]);
  177. WrNFDat(tmp[2]);
  178. WrNFDat(tmp[3]);
  179. SEccLock();
  180. WrNFDat(tmp[4]);
  181. WrNFDat(tmp[5]);
  182.     
  183. WrNFCmd(PROGCMD1);
  184. stat = WaitNFBusy();
  185. NFChipDs();
  186. #ifdef WR_BAD_BLK_TEST
  187. if((addr&0xff)==0x17) stat = 1; //just for test bad block
  188. #endif
  189. if(stat)
  190. Uart_Printf("Write nand flash 0x%x failn", addr);
  191. else {
  192. U8 RdDat[512];
  193. ReadPage(addr, RdDat);
  194. for(i=0; i<512; i++)
  195. if(RdDat[i]!=buf[i]) {
  196. Uart_Printf("Check data at page 0x%x, offset 0x%x failn", addr, i);
  197. stat = 1;
  198. break;
  199. }
  200. }
  201. return stat;
  202. }
  203. static void MarkBadBlk(U32 addr)
  204. {
  205. addr &= ~0x1f;
  206. NFChipEn();
  207. WrNFCmd(READCMD2); //point to area c
  208. WrNFCmd(PROGCMD0);
  209. WrNFAddr(4); //mark offset 4,5,6,7
  210. WrNFAddr(addr);
  211. WrNFAddr(addr>>8);
  212. if(NandAddr)
  213. WrNFAddr(addr>>16);
  214. WrNFDat(0); //mark with 0
  215. WrNFDat(0);
  216. WrNFDat(0); //mark with 0
  217. WrNFDat(0);
  218. WrNFCmd(PROGCMD1);
  219. WaitNFBusy(); //needn't check return status
  220. WrNFCmd(READCMD0); //point to area a
  221. NFChipDs();
  222. }
  223. int CheckBadBlk(U32 addr)
  224. {
  225. U8 dat;
  226. addr &= ~0x1f;
  227. NFChipEn();
  228. WrNFCmd(READCMD2); //point to area c
  229. WrNFAddr(5); //mark offset 4,5,6,7
  230. WrNFAddr(addr);
  231. WrNFAddr(addr>>8);
  232. if(NandAddr)
  233. WrNFAddr(addr>>16);
  234. WaitNFBusy();
  235. dat = RdNFDat();
  236. WrNFCmd(READCMD0); //point to area a
  237. NFChipDs();
  238. return (dat!=0xff);
  239. }
  240. /************************************************************/
  241. void InitNandFlash(int info)
  242. {
  243. U32 i;
  244. InitNandCfg();
  245. i = ReadChipId();
  246. if(info)
  247. Uart_Printf("Read chip id = %xn", i);
  248. if((i==0x9873)||(i==0xec75))
  249. NandAddr = 0;
  250. else if(i==0xec76)
  251. NandAddr = 1;
  252. else {
  253. //Uart_Printf("Chip id error!!!n");
  254. return;
  255. }
  256. }