主题 : 带1BIT ECC校验的6410 nandflash读写程序(带ID识别) 复制链接 | 浏览器收藏 | 打印
级别: 侠客
UID: 39247
精华: 2
发帖: 51
金钱: 355 两
威望: 71 点
贡献值: 2 点
综合积分: 142 分
注册时间: 2011-03-07
最后登录: 2015-05-31
楼主  发表于: 2011-05-28 10:13

 带1BIT ECC校验的6410 nandflash读写程序(带ID识别)

管理提醒: 本帖被 xoom 设置为精华(2011-05-28)
复制代码
  1. #include "utils.h"
  2. #include "s3c6410_addr.h"
  3. #include "interrupt.h"
  4. #include "defs.h"
  5. //CFG
  6. #define TACLS    7
  7. #define TWRPH0    7
  8. #define TWRPH1    7
  9. #define _1BIT_ECC    0
  10. #define _4BIT_ECC    2
  11. #define _8BIT_ECC    1
  12. #define ECC_TYPE(val)    { rNFCONF = rNFCONF & ~(3<<23) | (val<<23); }
  13. #define _512B        0
  14. #define _24B        1
  15. #define MSG_LEN(val)    { rNFCONF = rNFCONF & ~(1<<25) | (val<<25); }
  16. //CONTROL
  17. #define    DISABLE        1
  18. #define ENABLE        0
  19. #define NCE0(data)    { rNFCONT = rNFCONT & ~(1 << 1) | (data << 1); }
  20. #define ECC_DEC_INT        12
  21. #define ILLEGAL_ACC_INT    10
  22. #define RNB_INT            9
  23. #define EN_INT(bit)        { rNFCONT = rNFCONT | (1<<bit); }
  24. #define DIS_INT(bit)                          { rNFCONT &= ~(1<<bit); }
  25. #define INIT_MECC()        { rNFCONT |= (1<<5); }
  26. #define INIT_SECC()        { rNFCONT |= (1<<4); }
  27. #define MECC_LOCK()        { rNFCONT |= (1<<7); }
  28. #define SECC_LOCK()        { rNFCONT |= (1<<6); }
  29. #define MECC_UNLOCK()    { rNFCONT &= ~(1<<7); }
  30. #define SECC_UNLOCK()    { rNFCONT &= ~(1<<6); }
  31. //COMMAND
  32. #define CMD_GETID    0x90
  33. #define CMD(cmd)     { rNFCMD = cmd; }
  34. #define ADDR(addr)    { rNFADDR = addr; }
  35. #define READ()        (rNFDATA)
  36. #define WRITE(data)    { rNFDATA = data; }
  37. //STATUS
  38. #define RNB_STATUS    0
  39. #define RNB_DETECT    4
  40. #define ILLEGAL_ACC    5
  41. #define ECC4_DONE    6
  42. #define NFSTAT(bit) (rNFSTAT & (1<<bit))
  43. #define CLEAR_RNB()    { rNFSTAT |= (1<<RNB_DETECT); }
  44. #define CLEAR_ECC_DONE() { rNFSTAT |= (1<<ECC4_DONE); }
  45. static volatile U8 done;
  46. static U8 buffer[2048];
  47. static U8 spare_data[8] = {
  48.         0xff, 0xff, 0xff, 0xff,
  49.         0xff, 0xff, 0xff, 0xff
  50. };
  51. void __irq nf_int(void)
  52. {
  53.     done = 1;
  54.     if(NFSTAT(RNB_STATUS)){
  55.         //Uart_Printf("device is ready\n");
  56.         CLEAR_RNB();
  57.     }
  58.     if(NFSTAT(ILLEGAL_ACC))
  59.         Uart_Printf("illegal access\n");
  60.     if(NFSTAT(ECC4_DONE)){
  61.         Uart_Printf("4bit ecc decoding done\n");
  62.         CLEAR_ECC_DONE();
  63.     }
  64.     INTC_ClearVectAddr();
  65. }
  66. void nf_init(void)
  67. {
  68.     rGPOCON = rGPOCON & ~0xf | 0xa;//nCS[3:2]
  69.     rGPOPUD &= ~0xf;
  70.     rGPPCON = rGPPCON & ~(0xfff << 4) | (0xaaa << 4);//nWAIT, FALE, FCLE,
  71.     rGPPPUD &= ~(0xfff << 4);//FWEn, FREn, FRnB
  72.     INTC_SetIntISR(INT_NFC, nf_int);
  73.     INTC_Enable(INT_NFC);
  74.     rNFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4) | (1<<2);
  75.     rNFCONT = (0<<8) | 1;
  76. }
  77. U16 nf_getid(void)
  78. {
  79.     U16 id;
  80.     U8 tmp;
  81.     NCE0(ENABLE);
  82.     CMD(CMD_GETID);
  83.     ADDR(0x0);
  84.     id = (U16)READ();
  85.     NCE0(DISABLE);
  86.     tmp = id >> 8;
  87.     id = (U16)(id<<8) | (tmp);
  88.     return id;
  89. }
  90. void nf_erase_block(U16 block)
  91. {
  92.     block <<= 6;
  93.     
  94.     EN_INT(ILLEGAL_ACC_INT);
  95.     EN_INT(RNB_INT);
  96.     NCE0(ENABLE);
  97.     CLEAR_RNB();//注意在这里清除rnb检测信号
  98.     CMD(0x60);
  99.     ADDR(block&0xff);
  100.     ADDR((block>>8)&0xff);
  101.     ADDR((block>>16)&0xff);
  102.     done = 0;
  103.     CMD(0xd0);
  104.     while(!done);
  105.     CMD(0x70)
  106.     if(READ()&0x1)
  107.         Uart_Printf("erase error\n");
  108.     DIS_INT(RNB_INT);
  109.     DIS_INT(ILLEGAL_ACC_INT);
  110.     NCE0(DISABLE);
  111. }
  112. void nf_write_page(U16 block, U8 page, U8 const *buffer)
  113. {
  114.     U32 addr, tmp, mecc, secc;
  115.     U16 i;
  116.     U8 j;
  117.     addr = block << 6 + page;
  118.     EN_INT(ILLEGAL_ACC_INT);
  119.     EN_INT(RNB_INT);
  120.     NCE0(ENABLE);
  121.     CLEAR_RNB();
  122.     ECC_TYPE(_1BIT_ECC);
  123.     INIT_MECC();
  124.     INIT_SECC();
  125.     CMD(0x80);
  126.     ADDR(0);
  127.     ADDR(0);
  128.     ADDR(addr&0xff);
  129.     ADDR((addr>>8)&0xff);
  130.     ADDR((addr>>16)&0xff);
  131.     MECC_UNLOCK();
  132.     for(i = 0; i < 2048; i+=4){
  133.         tmp = 0;
  134.         for(j = 0; j < 4; j++){
  135.             tmp |= buffer[i+j] << (8*j);
  136.         }
  137.         WRITE(tmp);
  138.     }
  139.     MECC_LOCK();
  140.     mecc = rNFMECC0;
  141.     spare_data[0] = mecc & 0xff;
  142.     spare_data[1] = (mecc>>8) & 0xff;
  143.     spare_data[2] = (mecc>>16) & 0xff;
  144.     spare_data[3] = (mecc>>24) & 0xff;
  145.     SECC_UNLOCK();
  146.     tmp = 0xffffffff;
  147.     WRITE(tmp);
  148.     tmp = 0;
  149.     for(j = 0; j < 4; j++)
  150.         tmp |= spare_data[j] << (8*j);
  151.     WRITE(tmp);
  152.     SECC_LOCK();
  153.     secc = rNFSECC;
  154.     spare_data[4] = secc & 0xff;
  155.     spare_data[5] = (secc>>8) & 0xff;
  156.     tmp = 0;
  157.     for(j = 0; j < 2; j++)
  158.         tmp |= spare_data[4+j] << (8*j);
  159.     WRITE(tmp);
  160.     done = 0;
  161.     CMD(0x10);
  162.     while(!done);
  163.     CMD(0x70);
  164.     if(READ()&0x1)
  165.         Uart_Printf("write error\n");
  166.     DIS_INT(ILLEGAL_ACC_INT);
  167.     DIS_INT(RNB_INT);
  168.     NCE0(DISABLE);
  169. }
  170. void nf_read_page(U16 block, U8 page, U8 *buffer)
  171. {
  172.     U32 addr, tmp, mecc, secc;
  173.     U16 i;
  174.     U8 j;
  175.     addr = block << 6 + page;
  176.     EN_INT(ILLEGAL_ACC_INT);
  177.     EN_INT(RNB_INT);
  178.     NCE0(ENABLE);
  179.     CLEAR_RNB();
  180.     ECC_TYPE(_1BIT_ECC);
  181.     INIT_MECC();
  182.     INIT_SECC();
  183.     CMD(0x0);
  184.     ADDR(0);
  185.     ADDR(0);
  186.     ADDR(addr&0xff);
  187.     ADDR((addr>>8)&0xff);
  188.     ADDR((addr>>16)&0xff);
  189.     done = 0;
  190.     CMD(0x30);
  191.     while(!done);
  192.     MECC_UNLOCK();
  193.     for(i = 0; i < 2048; i+=4){
  194.         tmp = READ();
  195.         for(j = 0; j < 4; j++){
  196.             buffer[i+j] = (U8)(tmp>>(8*j));
  197.         }
  198.     }
  199.     MECC_LOCK();
  200.     SECC_UNLOCK();
  201.     mecc = READ();
  202.     rNFMECCD0 = (mecc&0xff) | ((mecc&0xff00) << 8);
  203.     rNFMECCD1 = ((mecc&0xff0000)>>16) | ((mecc&0xff000000) >> 8);
  204.     secc = READ();
  205.     SECC_LOCK();
  206.     rNFSECCD = (secc&0xff) | ((secc&0xff00)<<8);
  207.     if(rNFECCERR0 & 0xf)
  208.         Uart_Printf("ecc error\n");
  209.     else
  210.         Uart_Printf("ecc ok\n");
  211.     DIS_INT(ILLEGAL_ACC_INT);
  212.     DIS_INT(RNB_INT);
  213.     NCE0(DISABLE);
  214. }
  215. void xmain(void)
  216. {
  217.     U16 i;
  218.     Uart_Init();
  219.     nf_init();
  220.     Uart_Printf("the id is %x\n", nf_getid());
  221.     nf_erase_block(2047);
  222.     for(i = 0; i < 2048; i++)
  223.         buffer[i] = (U8)i;
  224.     nf_write_page(2047, 0, buffer);
  225.     for(i = 0; i < 2048; i++)
  226.         buffer[i] = 0;
  227.     nf_read_page(2047, 0, buffer);
  228.     for(i = 0; i < 256; i++){
  229.         Uart_Printf("%3x", buffer[i]);
  230.         if((i+1) % 16 == 0)
  231.             Uart_Printf("\n");
  232.     }
  233.     while(1);
  234. }
[ 此帖被venkee.com在2011-06-17 20:02重新编辑 ]
菜鸟在路上
级别: 圣骑士
UID: 42749
精华: 6
发帖: 241
金钱: 1530 两
威望: 306 点
贡献值: 6 点
综合积分: 602 分
注册时间: 2011-04-11
最后登录: 2016-07-19
1楼  发表于: 2011-06-16 21:43
楼主,代码要以插入代码方式贴出来,不然好多错误啊