NANDFlashd的读写(基于s3c2440)

发布者:omicron25最新更新时间:2016-05-03 来源: eefocus关键字:NANDFlashd  读写  s3c2440 手机看文章 扫描二维码
随时随地手机看文章

 

  1. #ifndef __TEST_H__  
  2. #define __TEST_H__  
  3. #include"def.h"  
  4. #define MAX_NAND_BLOCK 2048  //一共2048块  
  5. #define NAND_PAGE_SIZE 2048  //每块main区2k字节=2048  
  6. typedef struct nand_id_info //芯片的ID信息  
  7. {  
  8.  U8 IDm; //厂商ID  
  9.  U8 IDd; //设备ID  
  10.  U8 ID3rd;  
  11.  U8 ID4th;  
  12.  U8 ID5th;  
  13. } nand_id_info;  
  14. typedef struct bad_block_info //登记坏块  
  15. {  
  16.   U8 area[MAX_NAND_BLOCK];  //0表示非坏块,1表示坏块  
  17.   U32 sum;    //坏块的总数  
  18. } bad_block_info;  
  19. //NAND 操作指令  
  20. #define NAND_CMD_READ_1st             0x00  
  21. #define NAND_CMD_READ_2st             0x30  
  22. #define NAND_CMD_RANDOM_WRITE         0x85  //随机写  
  23. #define NAND_CMD_RANDOM_READ_1st      0x05  
  24. #define NAND_CMD_RANDOM_READ_2st      0xe0  
  25. #define NAND_CMD_READ_CB_1st          0x00   //将NAND里一块内容写进另一块  
  26. #define NAND_CMD_READ_CB_2st          0x35  
  27. #define NAND_CMD_READ_ID              0x90    
  28. #define NAND_CMD_RES                  0xff  //复位命令  
  29. #define NAND_CMD_WRITE_PAGE_1st       0x80    
  30. #define NAND_CMD_WRITE_PAGE_2st       0x10    
  31. #define NAND_CMD_BLOCK_ERASE_1st      0x60  //擦除命令  
  32. #define NAND_CMD_BLOCK_ERASE_2st      0xd0    
  33. #define NAND_CMD_READ_STATUS          0x70  
  34. //NAND 中断向量  
  35. #define INT_NFCON 24  
  36. //NFCONF HCLK=100MHZ  
  37. #define S3C2440_NFCONF_TACLS_init (1<<12)  
  38. #define S3C2440_NFCONF_TWRPH0_init (4<<8)  
  39. #define S3C2440_NFCONF_TWRPH1_init (0<<4)  
  40. #define S3C2440_NFCONF_BusWidth_init (0)  
  41. #define S3C2440_NFCONF_init() ( rNFCONF = S3C2440_NFCONF_TACLS_init  | /  
  42.                                         S3C2440_NFCONF_TWRPH0_init | /  
  43.                                         S3C2440_NFCONF_TWRPH1_init | /  
  44.                                         S3C2440_NFCONF_BusWidth_init )  
  45.                               
  46. //NFCONT  
  47. #define S3C2440_NFCONT_LockTight_init (0<<13)  
  48. #define S3C2440_NFCONT_SoftLock_init (0<<12)  
  49. #define S3C2440_NFCONT_EnbIllegalAccINT_init (1<<10)  
  50. #define S3C2440_NFCONT_EnbRnBINT_init (0<<9)  
  51. #define S3C2440_NFCONT_RnB_TransMode_init (0<<8)  
  52. #define S3C2440_NFCONT_SpareECCLock_init (1<<6)  
  53. #define S3C2440_NFCONT_MainECCLock_init (1<<5)  
  54. #define S3C2440_NFCONT_InitECC_init (1<<4)  
  55. #define S3C2440_NFCONT_Reg_nCE_init (1<<1)  //初始配置片选无效  
  56. #define S3C2440_NFCONT_MODE_init (0)  
  57. #define S3C2440_NFCONT_init() ( rNFCONT = S3C2440_NFCONT_LockTight_init | /  
  58.                                         S3C2440_NFCONT_SoftLock_init | /  
  59.                                         S3C2440_NFCONT_EnbIllegalAccINT_init | /  
  60.                                         S3C2440_NFCONT_EnbRnBINT_init | /  
  61.                                         S3C2440_NFCONT_RnB_TransMode_init | /  
  62.                                         S3C2440_NFCONT_SpareECCLock_init | /  
  63.                                         S3C2440_NFCONT_MainECCLock_init | /  
  64.                                         S3C2440_NFCONT_InitECC_init | /  
  65.                                         S3C2440_NFCONT_Reg_nCE_init | /  
  66.                                         S3C2440_NFCONT_MODE_init )  
  67. //NFSTAT  
  68. #define S3C2440_NFSTAT_init() ( rNFSTAT &= 0x3 )  
  69. //NFESTAT0  
  70. #define S3C2440_NFESTAT0_init() ( rNFESTAT0 = 0 )  
  71. //NFESTAT1  
  72. #define S3C2440_NFESTAT1_init() ( rNFESTAT1 = 0 )  
  73. //  
  74. #define select_nand() ( rNFCONT &= ~(1<<1) )  
  75. #define dis_select_nand() ( rNFCONT |= 1<<1 )  
  76. #define controller_enable() ( rNFCONT |= 1 )  
  77. #define controller_disable() ( rNFCONT &= ~1 )  
  78. //  
  79. void nand_flash_init(void);   //初始化  
  80. void nand_read_id(void);  
  81. extern int nand_block_erase(U32 num);   //num要删除的块号  
  82. extern int nand_page_write(U32 addr,U8 *buffer,U32 size);  //addr要写的起始页地址,buffer要写的缓存,size要写的字节大小最大为4G  
  83. extern int nand_page_read(U32 addr,U8 *buffer,U32 size);   //addr开始页地址,从每页00地址开始读  
  84. extern int nand_random_read(U32 paddr,U32 offset,U8 *data);   //随机读数据 paddr页地址,offset页内偏移地址  
  85. extern int nand_random_write(U32 paddr,U32 offset,U8 data);   //随机写,paddr页地址,offset页内区最后一个地偏移地址  
  86. extern void nand_test_bad_block(void);    //测试坏块函数,并标记在nand_bbi变量里和spare里(如果非0xff则为坏块)  
  87. #endif  
  88. #include "2440addr.h"  
  89. #include "test.h"  
  90. #include"def.h"  
  91. #define NAND_DEBUG 1  //打印一些串口调试信息  
  92. #define USE_ECC 1   //使用ECC验证  
  93. nand_id_info  nand_id;   //定义登记芯片ID的全局变量  
  94. bad_block_info  nand_bbi;   //定义来登记坏的全局变量  
  95. void init_nand_bbi(void)  //初始化变量  
  96. {  
  97.     U32 i;  
  98.     nand_bbi.sum=0;  
  99.     for (i=0;i
  100.     nand_bbi.area[i]=0;   //全部初始化为0  
  101. }  
  102. void nand_mask_bad_block(U32 n)  //标志坏块,n是坏块的块号  
  103. {  
  104.     #ifdef NAND_DEBUG  
  105.     Uart_Printf("NAND found and mask a bad block= %d .",n);  
  106.     #endif  
  107.     if (nand_bbi.area[n]!=1)  
  108.     {  
  109.         nand_bbi.area[n]=1;  
  110.         nand_bbi.sum++;  
  111.         nand_random_write(n*64,2048+64-1,0);//每块的第一个spare的最后一个字节,标志本块是否为坏块,非0xff为坏块  
  112.     }  
  113. }  
  114. int detect_nand_busy(void)  //检测是否忙  
  115. {  
  116.     U32 a;  
  117.     a=0;  
  118.     while(!(rNFSTAT&(1<<2)))  
  119.     {  
  120.         a++;  
  121.         if (a==5000000)   //等待超时  
  122.         {  
  123.             Uart_Printf("/r/n Error: Detect Nand Busy time out!!! /r/n");  
  124.             rNFSTAT |= (1<<2);    //清忙标志  
  125.             return -1;   //错误返回-1  
  126.         }  
  127.     }  
  128.     rNFSTAT |= (1<<2);  //清忙标志  
  129.     return 1;  
  130. }  
  131. void nand_reset(void)   //NAND复位  
  132. {  
  133.     rNFCMD = NAND_CMD_RES;    
  134.     detect_nand_busy(); //检测忙  
  135. }  
  136. void control_start(void) //芯片开启  
  137. {   
  138.     select_nand();  
  139.     controller_enable();  
  140.     rNFSTAT |= (1<<2);  //清忙标志  
  141.     nand_reset();  
  142. }  
  143. void control_end(void) //芯片关闭  
  144. {  
  145.     dis_select_nand();  
  146.     controller_disable();  
  147. }  
  148.     
  149. void ecc_main_init(void)    //初始化ECC值  
  150. {  
  151.     rNFCONT |= 1<<4;  //initEcc  
  152. }  
  153.                                                                
  154. void ecc_main_start(void)   //开锁main ECC  
  155. {  
  156.     rNFCONT &= ~(1<<5);   //unlock  
  157. }  
  158. void ecc_main_end(void) //锁定main ECC  
  159. {  
  160.     rNFCONT |= 1<<5;  //lock  
  161. }  
  162. void ecc_spare_start(void) //开锁spare ECC  
  163. {  
  164.     rNFCONT &= ~(1<<6); //unlock  
  165. }  
  166. void ecc_spare_end(void) //锁定spare ECC  
  167. {  
  168.     rNFCONT |= 1<<6; //lock  
  169. }  
  170. void __irq nandINT(void)    //NAND中断函数  
  171. {  
  172.      //此处写处理代码  
  173.      #ifdef NAND_DEBUG  
  174.     Uart_Printf("/r/n Nand Error... In interrupt now!!!");//只有错误才会进入中断  
  175.     #endif  
  176.     rSRCPND |= 0x1<
  177.     rINTPND |= 0x1<
  178. }  
  179. void nand_read_id(void)//读取芯片ID信息  
  180. {  
  181.     control_start();//开控制  
  182.     rNFCMD  = NAND_CMD_READ_ID;  
  183.     rNFADDR = 0;  
  184.     //读芯片ID  
  185.     nand_id.IDm=(U8)rNFDATA8;  
  186.     nand_id.IDd=(U8)rNFDATA8;  
  187.     nand_id.ID3rd=(U8)rNFDATA8;  
  188.     nand_id.ID4th=(U8)rNFDATA8;  
  189.     nand_id.ID5th=(U8)rNFDATA8;  
  190.     //打印ID信息  
  191.     #ifdef NAND_DEBUG  
  192.     Uart_Printf("/r/n Read NAND Flash ID:");  
  193.     Uart_Printf("/r/n NAND Mark code:   0x%x ",nand_id.IDm);  
  194.     Uart_Printf("/r/n NAND Device code: 0x%x ",nand_id.IDd);  
  195.     Uart_Printf("/r/n NAND 3rdID code:  0x%x ",nand_id.ID3rd);  
  196.     Uart_Printf("/r/n NAND 4thID code:  0x%x ",nand_id.ID4th);  
  197.     Uart_Printf("/r/n NAND 5thID code:  0x%x ",nand_id.ID5th);  
  198.     #endif  
  199.    
  200.     control_end();  //关控制  
  201. }  
  202. //擦出时只要给定块所在页的地址,就能擦除整个块  
  203. int nand_block_erase(U32 num)   //num要删除的块号  
  204. {    
  205.     num=num*64; //每块的第一页  
  206.     control_start();    //开控制  
  207.     nand_reset();   //复位  
  208.     rNFCMD  = NAND_CMD_BLOCK_ERASE_1st;  
  209.     rNFADDR = num&0xff;  
  210.     rNFADDR = (num>>8)&0xff;  
  211.     rNFADDR = (num>>16)&0xff;  
  212.     rNFCMD  = NAND_CMD_BLOCK_ERASE_2st;  
  213.     detect_nand_busy();  
  214.      
  215.     rNFCMD =NAND_CMD_READ_STATUS; //读状态  
  216.     if(rNFDATA8 & 1)  //最低位可以判断擦除和写是否成功  
  217.     {  
  218.         #ifdef NAND_DEBUG  
  219.         Uart_Printf("/r/n Error:nand erase error... block=0x%x",num/64);  
  220.         #endif  
  221.         control_end();//关控制  
  222.         nand_mask_bad_block(num/64);//登记为坏块  
  223.         return -1;//删除错误返回0  
  224.     }  
  225.      
  226.     control_end();//关控制  
  227.     #ifdef NAND_DEBUG  
  228.     Uart_Printf("/r/n NAND block %d erase completed.",num/64);    
  229.     #endif  
  230.     return 1;  //擦除成功  
  231. }  
  232. int nand_page_write(U32 addr,U8 *buffer,U32 size) //addr要写的起始页地址,buffer要写的缓存,size要写的字节大小最大为4G  
  233. {  
  234.     U32 i,n,p,temp,ecc;  
  235.     U8 *bu;  
  236.     bu=buffer;  
  237.     temp=0;  
  238.     n=size/2048+(((size%2048)==0)?0:1); //计算出要写的页数,小于一页的部分当作一页  
  239.    
  240.     for(i=0;i
  241.     {   
  242.         control_start();  //开控制  
  243.         nand_reset();  //复位  
  244.     
  245.     #ifdef USE_ECC  
  246.         ecc_main_init();  
  247.         ecc_main_start(); //可以产生main区ECC  
  248.     #endif  
  249.         rNFCMD  = NAND_CMD_WRITE_PAGE_1st;  
  250.         rNFADDR = 0;     //从每页的0地址开始  
  251.         rNFADDR = 0;     //从每页的0地址开始  
  252.         rNFADDR = (addr)&0xff;  
  253.         rNFADDR = (addr>>8)&0xff;  
  254.         rNFADDR = (addr>>16)&0xff;  
  255.      
  256.         for (p=0;p<2048;p++)  //写入一页  
  257.         {  
  258.             temp=temp+1;  
  259.             if (temp>size)  
  260.             {  
  261.                 rNFDATA8 = 0xff;   //多余的填写0xff  
  262.             }  
  263.             else  
  264.             {  
  265.                 rNFDATA8 = *(bu+p);  
  266.             }  
  267.         }  
  268.         //delay_lhg(100,100);//  
  269.     #ifdef USE_ECC  
  270.         ecc_main_end(); //锁定main区ecc  
  271.         ecc=rNFMECC0;     
  272.     
  273.         ecc_spare_start();   //解锁spare区ECC  
  274.         //main ECC值写入备用区的头0~4个地址内  
  275.         rNFDATA8 = ecc&0xff;  
  276.         rNFDATA8 = (ecc>>8)&0xff;  
  277.         rNFDATA8 = (ecc>>16)&0xff;  
  278.         rNFDATA8 = (ecc>>24)&0xff;  
  279.         ecc_spare_end(); //锁定spare区ECC  
  280.         // delay_lhg(100,100);//  
  281.         ecc = rNFSECC;     //spare ECC值写入备用区的5~6两个地址内  
  282.         rNFDATA8 = ecc&0xff;  
  283.         rNFDATA8 = (ecc>>8)&0xff;  
  284.     #endif  
  285.     
  286.         bu=bu+2048; //页增量  
  287.         addr++;  
  288.     
  289.         rNFCMD  = NAND_CMD_WRITE_PAGE_2st;  
  290.         detect_nand_busy();//检测忙  
  291.         rNFCMD =NAND_CMD_READ_STATUS; //读状态  
  292.         if (rNFDATA8&1)  
  293.         {  
  294.             #ifdef NAND_DEBUG  
  295.             Uart_Printf("/r/n nand write page error: page addr=0x%d",addr-1); //写入失败,以后改进  
  296.             #endif  
  297.             control_end();  //关控制  
  298.             nand_mask_bad_block((addr-1)/64);//登记为坏块  
  299.             return -1;  //写入错误返回-1  
  300.         }  
  301.         control_end();  //关控制  
  302.     }  
  303.     return 1;  //成功返回1  
  304. }  
  305. int nand_page_read(U32 addr,U8 *buffer,U32 size)  //addr开始页地址,从每页00地址开始读,size为需要读的字节数  
  306. {    
  307.     U32 i,n,p,temp,ecc;  
  308.     U8 *bu,no;  
  309.     bu=buffer;  
  310.     temp=0;  
  311.      
  312.     n=size/2048+(((size%2048)==0)?0:1);  //计算出要读的页数,小于一页的部分当作一页  
  313.    
  314.     for (i=0;i
  315.     {  
  316.         control_start();    //开控制  
  317.         nand_reset();   //复位  
  318.         #ifdef USE_ECC  
  319.         rNFESTAT0 = 0;  //复位错误标志位  
  320.         ecc_main_init();  
  321.         ecc_main_start();   //可以产生main区ECC  
  322.         #endif  
  323.         
  324.         rNFCMD  = NAND_CMD_READ_1st;  
  325.         rNFADDR = 0;  
  326.         rNFADDR = 0;  
  327.         rNFADDR = addr&0xff;  
  328.         rNFADDR = (addr>>8)&0xff;  
  329.         rNFADDR = (addr>>16)&0xff;  
  330.         rNFCMD  = NAND_CMD_READ_2st;  
  331.         detect_nand_busy();  
  332.         for (p=0;p<2048;p++)  
  333.         {  
  334.             temp=temp+1;  
  335.             if (temp>size)  
  336.             {  
  337.                 no=rNFDATA8;  //多余的读出来扔掉  
  338.             }  
  339.             else  
  340.             {  
  341.                 *(bu+p) = rNFDATA8;  
  342.             }  
  343.         }  
  344.      
  345.         #ifdef USE_ECC  
  346.         rNFESTAT0=0;  
  347.         ecc_main_end();  //锁定main区ECC  
  348.         //delay_lhg(100,100);//  
  349.         ecc_spare_start();  //解锁spare区ecc  
  350.         ecc=rNFDATA8;  //从flash读出main区ECC,四个字节  
  351.         no=rNFDATA8;  
  352.         ecc |= ((U32)no)<<8;  
  353.         no=rNFDATA8;    
  354.         ecc |= ((U32)no)<<16;  
  355.         no=rNFDATA8;  
  356.         ecc |= ((U32)no)<<24;  
  357.         rNFMECCD0 = ((ecc&0xff00)<<8)|(ecc&0xff);  //硬件检验main ECC     
  358.         rNFMECCD1 = ((ecc&0xff000000)>>8)|((ecc&0xff0000)>>16);   
  359.         ecc_spare_end();//锁定spare区ecc  
  360.         // delay_lhg(100,100);//  
  361.         ecc=rNFDATA8;//从flash读出spare区ECC的值  
  362.         no=rNFDATA8;  
  363.         ecc |= ((U32)no)<<8;  
  364.       
  365.         rNFSECCD = ((ecc&0xff00)<<8)|(ecc&0xff);//硬件检验spare ECC   
  366.         //delay_lhg(100,100);//延时一会  
  367.         ecc=rNFESTAT0&0xffffff;  //ecc只是临时用一下错误状态,并非ecc内容  
  368.       
  369.         if (ecc!=0)//有错误  
  370.         {  
  371.             //以后再优化  
  372.             #ifdef NAND_DEBUG  
  373.             Uart_Printf("/r/n Nand ecc check error... page addr=0x%x,NFESTAT0=0x%x ",addr,ecc);  
  374.             #endif  
  375.             nand_mask_bad_block((addr+i)/64);//登记为坏块  
  376.             return -1;  
  377.         }  
  378.         #endif  
  379.      
  380.         bu=bu+2048;  
  381.         addr++;  
  382.         control_end();//关控制  
  383.     }  
  384.     return 1;  
  385. }  
  386. int nand_random_read(U32 paddr,U32 offset,U8 *data) //随机读数据 paddr页地址,offset页内偏移地址  
  387. {  
  388.    control_start();   //开控制  
  389.    nand_reset();   //复位  
  390.     
  391.    rNFCMD  = NAND_CMD_READ_1st;  
  392.    rNFADDR = 0;  
  393.    rNFADDR = 0;  
  394.    rNFADDR = paddr&0xff;  
  395.    rNFADDR = (paddr>>8)&0xff;  
  396.    rNFADDR = (paddr>>16)&0xff;  
  397.    rNFCMD  = NAND_CMD_READ_2st;    
  398.     
  399.    detect_nand_busy();  
  400.    rNFCMD  = NAND_CMD_RANDOM_READ_1st;  
  401.    rNFADDR = offset&0xff;  //写入页内偏移地址  
  402.    rNFADDR = (offset>>8)&0xff;  
  403.    rNFCMD  = NAND_CMD_RANDOM_READ_2st;  
  404.     
  405.    *data  = rNFDATA8;  
  406.    control_end();  
  407.    return 1;  
  408. }  
  409. int nand_random_write(U32 paddr,U32 offset,U8 data)//随机写,paddr页地址,offset页内偏移地址  
  410. {  
  411.    control_start();  //开控制  
  412.    nand_reset();  //复位  
  413.     
  414.    rNFCMD  = NAND_CMD_WRITE_PAGE_1st;  
  415.    rNFADDR = 0;  
  416.    rNFADDR = 0;  
  417.    rNFADDR = paddr&0xff;  
  418.    rNFADDR = (paddr>>8)&0xff;  
  419.    rNFADDR = (paddr>>16)&0xff;  
  420.     
  421.    rNFCMD  = NAND_CMD_RANDOM_WRITE;  
  422.    rNFADDR = offset&0xff; //写入页内偏移地址  
  423.    rNFADDR = (offset>>8)&0xff;  
  424.     
  425.    rNFDATA8 = data;  
  426.    rNFCMD  = NAND_CMD_WRITE_PAGE_2st;  
  427.    detect_nand_busy();  //检测忙  
  428.     
  429.    rNFCMD =NAND_CMD_READ_STATUS; //读状态  
  430.     if (rNFDATA8&1)  
  431.     {  
  432.     #ifdef NAND_DEBUG  
  433.      Uart_Printf("/r/n Error:nand random write error... paddr=0x%x,offset=0x%x ",paddr,offset);  
  434.     #endif  
  435.      return -1;//删除错误返回0  
  436.     }  
  437.      
  438.     control_end();  
  439.     return 1;//成功返回1  
  440. }  
  441. void nand_test_bad_block(void) //测试坏块函数,并标记spare区最后一个地址,如果非0xff则为坏块  
  442. {  
  443.    
  444.     U8 dest[64*2048];   //一个块的main区容量  
  445.     U8 src [64*2048];  
  446.     U32 i,k;  
  447.   
  448.    #ifdef NAND_DEBUG  
  449.    Uart_Printf("/r/n test and mask bad block is begain. /r/n");  
  450.    #endif  
  451.    
  452.  //main区检测  
  453.  for (i=0;i<64*2048;i++)  
  454.  {  
  455.     dest[i]=0xff;   //初始化缓冲区  
  456.     src [i]=0;  
  457.  }  
  458.  //删除所有块  
  459.  for (i=0;i
  460.  {  
  461.     nand_block_erase(i);  
  462.  }  
  463.    
  464.  for (i=0;i
  465.  {  
  466.     nand_page_write(i*64,src,64*2048);  
  467.     nand_page_read(i*64,dest,64*2048);//使用了ecc校验读出来即可登记坏块信息  
  468.  }  
  469.  for (i=0;i<64*2048;i++)  
  470.  {  
  471.     dest[i]=0;//初始化缓冲区  
  472.     src [i]=0xff;  
  473.  }  
  474.    
  475.  //删除所有块  
  476.  for (i=0;i
  477.  {  
  478.     nand_block_erase(i);  
  479.  }  
  480.    
  481.  for (i=0;i
  482.  {  
  483.      nand_page_write(i*64,src,64*2048);  
  484.      nand_page_read(i*64,dest,64*2048);//使用了ecc校验读出来即可登记坏块信息  
  485.  }  
  486.     
  487.  //  
  488.  //spare区检测  
  489.  for (i=0;i<64;i++)  
  490.  {  
  491.     dest[i]=0xff;//初始化缓冲区  
  492.     src [i]=0;  
  493.  }  
  494.    
  495.  //删除所有块  
  496.  for (i=0;i
  497.  {  
  498.     nand_block_erase(i);  
  499.  }  
  500.    
  501.  for (i=0;i
  502.  {  
  503.    if ( nand_bbi.area[i/64] ==1 ) //如果是坏块则跳过  
  504.    continue;  
  505.     
  506.    for (k=0;k<64;k++)  
  507.    {  
  508.         nand_random_write(i,2048+k,src[k]);  
  509.         nand_random_read(i,2048+k,&dest[k]);  
  510.         if (dest[k]!=src[k])//不相等则登记为坏块  
  511.         {  
  512.             nand_mask_bad_block(i/64);  
  513.             break;  
  514.         }  
  515.    }  
  516.     
  517.  }  
  518.    
  519.   for (i=0;i<64;i++)  
  520.  {  
  521.   dest[i]=0x0;//初始化缓冲区  
  522.   src [i]=0xff;  
  523.  }  
  524.    
  525.  //删除所有块  
  526.  for (i=0;i
  527.  {  
  528.     nand_block_erase(i);  
  529.  }  
  530.    
  531.  for (i=0;i
  532.  {  
  533.    if ( nand_bbi.area[i/64] ==1 )//如果是坏块则跳过  
  534.    continue;  
  535.     
  536.    for (k=0;k<64;k++)  
  537.    {  
  538.     nand_random_write(i,2048+k,src[k]);  
  539.     nand_random_read(i,2048+k,&dest[k]);  
  540.     if (dest[k]!=src[k])//不相等则登记为坏块  
  541.     {  
  542.     nand_mask_bad_block(i/64);  
  543.     break;  
  544.     }  
  545.    }  
  546.  }  
  547.   
  548.    #ifdef NAND_DEBUG  
  549.    Uart_Printf("/r/n test and mask bad block is over. /r/n");  
  550.    #endif  
  551. }  
  552. void nand_flash_init(void)//初始化  
  553. {  
  554.   #ifdef NAND_DEBUG  
  555.   Uart_Printf("/r/nNAND FLASH init");//  
  556.   #endif  
  557.    
  558.   //中断入口地址  
  559.   pISR_NFCON = (U32)nandINT;  
  560.    
  561.   //配置GPIO  
  562.   rGPGUP |= 0x7<<13; //GPG13~15关闭上位  
  563.   rGPGCON &= ~((U32)0x3f<<26);//GPG13~15为输入  
  564.    
  565.   //初始化各寄存器  
  566.   S3C2440_NFCONF_init();  
  567.   S3C2440_NFCONT_init();  
  568.   S3C2440_NFSTAT_init();  
  569.   S3C2440_NFESTAT0_init();  
  570.   S3C2440_NFESTAT1_init();  
  571.    
  572.   //关于中断  
  573.   rINTMSK &= ~(0x1<
  574.   rINTMOD &= ~(0x1<
  575.   rSRCPND |= 0x1<
  576.   rINTPND |= 0x1<
  577.    
  578.  // init_nand_bbi();//初始化全局变量  
  579.   nand_read_id();//读ID  
  580.  // nand_test_bad_block();//测试并登记坏块  
  581. }  

 

 

关键字:NANDFlashd  读写  s3c2440 引用地址:NANDFlashd的读写(基于s3c2440)

上一篇:s3c2440串口调试函数
下一篇:s3c2440的触摸屏校正与测试

推荐阅读最新更新时间:2024-03-16 14:52

单片机定时器中断原理及s3c2440的定时器使用方法
在程序中,需要延时的时候,通常状况下有两种方法:1、循环语句实现,这种方法简单易用,但是无法得到一个精确的延时时间;2、定时器定时,可达到精确延时。 中断的概念 什么是中断:CPU在处理某一事件A时,发生的另外某一事件B请求CPU去处理(产生了中断),随后CPU暂时中断当前正在执行的任务,去对事件B进行处理,CPU处理完事件B后再返回之前中断的位置继续执行原来的事件A,这一过程总称为中断。 中断流程示意图 使CPU中断的事件称中断源。中断源向CPU发出中断请求,CPU暂时中断原来执行的事件A转去做事件B。事件B处理完毕后继续返回原先中断的地方(该过程称中断返回,原先中断的地方为断点),继续执行原先的事件。 中断的优
[单片机]
单片机定时器中断原理及<font color='red'>s3c2440</font>的定时器使用方法
ARM9(2440)对nand flash的读写操作
s3c2440对nandflash的操作(K9F2G08) nandflash在对大容量的数据存储中发挥着重要的作用。相对于norflash,它具有一些优势,但它的一个劣势是很容易产生坏块,因此在使用nandflash时,往往要利用校验算法发现坏块并标注出来,以便以后不再使用该坏块。nandflash没有地址或数据总线,如果是8位nandflash,那么它只有8个IO口,这8个IO口用于传输命令、地址和数据。nandflash主要以page(页)为单位进行读写,以block(块)为单位进行擦除。每一页中又分为main区和spare区,main区用于正常数据的存储,spare区用于存储一些附加信息,如块好坏的标记、块的逻辑地址、页内
[单片机]
USB118a U盘读写51汇编测试程序
/************************************************************************************************ * * U盘文件读写模块 以字节为单位进行U盘文件读写。 * MCS-51 单片机 汇编示例程序 * 硬件连接方式: 4线制串口(电源,地,输入,输出) * *************************************************************************************************/ /*-------------------------------- 初始化
[单片机]
u-boot2009.11 s3c2440移植手记
奋战了好几天了 U-BOOT终于有点眉目了,虽然nandflash还没有弄好,目前还不支持从nandflash启动。先来张图片吧哈哈。 u-boot作为现在主流的bootloader同样分为boot 和 loader两部分。 boot:(靴子呵呵基础支撑作用)为第一阶段,主要是硬件设备的初始化。 loader:(装载机)为第二阶段完成初始化后将flash的内容搬运到内存ram中运行。 具体步骤我就不说了 网上很多大侠都说过了 我第一阶段boot的调试方法:点灯 (1)——cpu/arm920t/start.S 汇编 完成第一阶段后点一个灯,现象是LED1亮 (2)——board/..../xx2440.c 在init bo
[单片机]
u-boot2009.11 <font color='red'>s3c2440</font>移植手记
04-S3C2440u-boot学习之u-boot分析(2)之Makefile结构分析
看uboot说明知道,uboot编译需要 (1)先配置 make 。。。 (2)make。 一:配置过程 make 100ask24x0 (1)解压打号补丁的u-boot-1.1.6,打开makefile。 (2)make 100ask24x0_config相当于执行: a.首先执行make uconfig,删除相关配置文件。 b.@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0 MKCONFIG:= $(SRCTREE)/mkconfig(根目录下有个mkconfig脚本文件) $(@:_config=)
[单片机]
04-S3C2440u-boot学习之u-boot分析(2)之Makefile结构分析
s3c2440之IIS(2)I2S音频总线学习-数字音频技术
IIS音频总线学习(一)数字音频技术 一、声音的基本概念 声音是通过一定介质传播的连续的波。 重要指标: 振幅:音量的大小 周期:重复出现的时间间隔 频率:指信号每秒钟变化的次数 声音按频率分类: 声音的传播携带了信息,它是人类传播信息的一种主要媒体。 声音的三种类型: 波形声音:包含了所有声音形式 语音:不仅是波形声音,而且还有丰富的语言内涵(抽象→提取特征→意义理解) 音乐:与语音相比,形式更规范。音乐是符号化的声音。 二、声音的数字化 1.声音信号的类型 模拟信号(自然界、物理) 数字信号(计算机) 2.声音数字化过程 3.声音数字化过程示意图 4.声音数字
[单片机]
<font color='red'>s3c2440</font>之IIS(2)I2S音频总线学习-数字音频技术
基于S3C2440处理器和WinCE的智能车载仪表设计
iframe height=250 src="http://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=0.0857261547378197&zoneid=138" frameBorder=0 width=300 scrolling=no /iframe   随着高性能电子显示技术的发展,汽车仪表电子化的程度越来越高。国内外已开发出了多功能全电子显示仪表、平视显示仪表、汽车导航系统、行车记录仪等高技术产品。未来,车用电子化嵌入式仪表具有以下优点:提供大量复杂的信息,使汽车的电子控制程度越来越高;满足小型、轻量化的要求,使有限的驾驶空间更人性化;高精度和高可靠
[单片机]
基于<font color='red'>S3C2440</font>处理器和WinCE的智能车载仪表设计
非接触式RFID读写器系统的研究
1 引言   近年来,自动识别方法在服务领域、货物销售与后勤、商业、生产企业和材料流通领域得到快速的普及和推广。自动识别的目的是提供关于个人、动物、货物和商品的信息。   目前市面上的射频卡的工作频率为125kHz,功耗很大,因此要求应答器的线圈必须达到几百匝,由此产生的较大绕线界面及需要附加的电容器很难封装在小型塑料卡片内。   本方案采用13.56MHz工作频率的应答器系统,它的应答器线圈由约5匝绕线组成,体积大大减小,便于携带,拥有新的市场,例如用非接触IC卡(射频卡)作为公共交通车票,也适用于门禁、考勤、会议签到以及高速公路、加油站、停车场、公交等收费系统。同时还可考虑将其用于盲人导航系统,读写器安装在拐杖中,射频卡只有一
[应用]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved