nand.c
上传用户:jankzhpno
上传日期:2022-08-03
资源大小:4763k
文件大小:5k
源码类别:

Windows CE

开发平台:

Visual C++

  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include "def.h"
  4. #include "option.h"
  5. #include "2440addr.h"
  6. #include "2440lib.h"
  7. #include "nand.h"
  8. #define NF_MECC_UnLock()    {rNFCONT&=~(1<<5);}
  9. #define NF_MECC_Lock()      {rNFCONT|=(1<<5);}
  10. #define NF_CMD(cmd) {rNFCMD=cmd;}
  11. #define NF_ADDR(addr) {rNFADDR=addr;}
  12. #define NF_nFCE_L() {rNFCONT&=~(1<<1);}
  13. #define NF_nFCE_H() {rNFCONT|=(1<<1);}
  14. #define NF_RSTECC() {rNFCONT|=(1<<4);}
  15. #define NF_RDDATA()  (rNFDATA)
  16. #define NF_RDDATA8()  ((*(volatile unsigned char*)0x4E000010) )
  17. #define NF_WRDATA(data)  {rNFDATA=data;}
  18. #define NF_WAITRB()     {while(!(rNFSTAT&(1<<1)));} 
  19.      //wait tWB and check F_RNB pin.
  20. // RnB Signal
  21. #define NF_CLEAR_RB()     {rNFSTAT |= (1<<2);} // Have write '1' to clear this bit.
  22. #define NF_DETECT_RB()     {while(!(rNFSTAT&(1<<2)));}
  23. #define TACLS 0 // 1-clk(0ns) 
  24. #define TWRPH0 6 // 3-clk(25ns)
  25. #define TWRPH1 0 // 1-clk(10ns)  //TACLS+TWRPH0+TWRPH1>=50ns
  26. #define STATIC
  27. STATIC void __RdPage512(U8 *buf)
  28. {
  29. unsigned i;
  30. for (i = 0; i < 512; i++) {
  31. buf[i] =  NF_RDDATA8();
  32. }
  33. }
  34. STATIC void Nand_Reset(void)
  35. {
  36.     volatile int i;
  37.    
  38. NF_nFCE_L();
  39. NF_CLEAR_RB();
  40. for (i=0; i<10; i++);
  41. NF_CMD(0xFF); //reset command
  42. NF_DETECT_RB();
  43. NF_nFCE_H();
  44. }
  45. STATIC U32 NF8_CheckId(void)
  46. {
  47. int i;
  48. U8 Mid, Did, DontCare, id4th;  
  49. NF_nFCE_L();
  50.   NF_CMD(0x90);
  51. NF_ADDR(0x0);
  52. for (i=0; i<100; i++);
  53. Mid  = NF_RDDATA8();
  54. Did    = NF_RDDATA8();
  55. DontCare  = NF_RDDATA8();
  56. id4th  = NF_RDDATA8();
  57. NF_nFCE_H();
  58. switch(Did) {
  59. case 0x76:
  60. return 0;
  61. case 0xF1:
  62. case 0xD3:
  63. return 1;
  64. default:
  65. Uart_SendString("Unknown NAND typern");
  66. for(;;);
  67. }
  68. }
  69. STATIC int Nand_Init(void)
  70. {
  71. rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
  72. rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0);
  73. rNFSTAT = 0;
  74. Nand_Reset();
  75. return NF8_CheckId();
  76. }
  77. STATIC int Nand_IsBadBlockPage512(U32 block)
  78. {
  79.     U32  Page;
  80. U8  BAD;
  81.     Page = (block<<8);
  82.     Nand_Reset();
  83.      
  84.     NF_nFCE_L();
  85. NF_CLEAR_RB();
  86. NF_CMD(0x50);       
  87.    NF_ADDR(5);     
  88.     NF_ADDR(Page&0xff);  
  89.     NF_ADDR((Page>>8)&0xff);
  90.     NF_ADDR((Page>>16)&0xff);   
  91.     NF_DETECT_RB();  
  92.     BAD = NF_RDDATA8();
  93.              
  94.     NF_nFCE_H();
  95.     return BAD != 0xff;
  96.     
  97. }
  98. STATIC int Nand_IsBadBlockPage2048(U32 block)
  99. {
  100.     U32  Page;
  101. U8  BAD;
  102.     Page = block << 6;
  103.     NF_nFCE_L();
  104.     NF_CLEAR_RB();
  105.     NF_CMD(0x00);
  106. NF_ADDR(0);
  107. NF_ADDR((2048>>8)&0xff);
  108.     NF_ADDR(Page&0xff);
  109.     NF_ADDR((Page>>8)&0xff);
  110.     NF_ADDR((Page>>16)&0xff);
  111.     NF_CMD(0x30);        
  112.     NF_DETECT_RB();
  113.     BAD = NF_RDDATA8();
  114.              
  115.     NF_nFCE_H();    
  116.     return BAD != 0xff;
  117. }
  118. STATIC int Nand_IsBadBlock(U32 block,int bLargeBlock)
  119. {
  120. switch(bLargeBlock) {
  121. case 0:
  122. return Nand_IsBadBlockPage512(block);
  123. case 1:
  124. return Nand_IsBadBlockPage2048(block);
  125. }
  126. return 0;
  127. }
  128. STATIC int Nand_ReadSectorPage512(U32 sector, U8 *buffer)
  129. {
  130.     Nand_Reset();
  131.     
  132. NF_nFCE_L();    
  133. NF_CLEAR_RB();
  134. NF_CMD(0x00);
  135.     NF_ADDR(0x00);
  136. NF_ADDR(sector&0xff);
  137. NF_ADDR((sector>>8)&0xff);
  138. NF_ADDR((sector>>16)&0xff);
  139.  
  140. NF_DETECT_RB();
  141.     __RdPage512(buffer);
  142. NF_nFCE_H();    
  143.     return 1;
  144. }
  145. STATIC int Nand_ReadSectorPage2048(U32 sector, U8 *buffer)
  146. {
  147. U32 page, data_addr;
  148.     Nand_Reset();
  149.  
  150. NF_nFCE_L();    
  151. NF_CLEAR_RB();
  152. NF_CMD(0x00); // Read command
  153. page = sector/4;
  154. data_addr = 512 *(sector%4);
  155. NF_ADDR(data_addr&0xff);
  156. NF_ADDR((data_addr>>8)&0xff);
  157. NF_ADDR(page&0xff);
  158. NF_ADDR((page>>8)&0xff);
  159. NF_ADDR((page>>16)&0xff);
  160. NF_CMD(0x30);
  161.  
  162. NF_DETECT_RB();
  163.     __RdPage512(buffer);
  164. NF_nFCE_H();    
  165.     return OK;
  166. }
  167. STATIC int Nand_ReadSector(U32 sector, U8 *buffer, int bLargeBlock)
  168. {
  169. switch(bLargeBlock) {
  170. case 0:
  171. return Nand_ReadSectorPage512(sector, buffer);
  172. case 1:
  173. return Nand_ReadSectorPage2048(sector, buffer);
  174. }
  175. return 0;
  176. }
  177. void CopyProgramFromNand(void)
  178. {
  179. const int bLargeBlock = Nand_Init();
  180. const unsigned StartSector = 0, StopSector = 5120;
  181. const unsigned byte_sector_shift = 9;
  182. const unsigned sector_block_shift = bLargeBlock ? 8 : 5;
  183. unsigned char *RAM = (unsigned char *)0x30000000;
  184. unsigned Sector, GoodSector;
  185. for (Sector = StartSector, GoodSector = Sector; Sector < StopSector; Sector ++, GoodSector++) {
  186. // begin of a block
  187. if (GoodSector & ( (1 << sector_block_shift) - 1 ) == 0) {
  188. // found a good block
  189. for (;;) {
  190. if (!Nand_IsBadBlock(GoodSector >> sector_block_shift, bLargeBlock)) {
  191. // Is good Block
  192. break;
  193. }
  194. // try next block
  195. GoodSector += (1 << sector_block_shift);
  196. }
  197. }
  198. Nand_ReadSector(GoodSector, RAM + (Sector << byte_sector_shift ), bLargeBlock);
  199. }
  200. }