复制代码- #include "utils.h"
- #include "s3c6410_addr.h"
- #include "interrupt.h"
- #include "defs.h"
- //CFG
- #define TACLS 7
- #define TWRPH0 7
- #define TWRPH1 7
- #define _1BIT_ECC 0
- #define _4BIT_ECC 2
- #define _8BIT_ECC 1
- #define ECC_TYPE(val) { rNFCONF = rNFCONF & ~(3<<23) | (val<<23); }
- #define _512B 0
- #define _24B 1
- #define MSG_LEN(val) { rNFCONF = rNFCONF & ~(1<<25) | (val<<25); }
- //CONTROL
- #define DISABLE 1
- #define ENABLE 0
- #define NCE0(data) { rNFCONT = rNFCONT & ~(1 << 1) | (data << 1); }
- #define ECC_DEC_INT 12
- #define ILLEGAL_ACC_INT 10
- #define RNB_INT 9
- #define EN_INT(bit) { rNFCONT = rNFCONT | (1<<bit); }
- #define DIS_INT(bit) { rNFCONT &= ~(1<<bit); }
- #define INIT_MECC() { rNFCONT |= (1<<5); }
- #define INIT_SECC() { rNFCONT |= (1<<4); }
- #define MECC_LOCK() { rNFCONT |= (1<<7); }
- #define SECC_LOCK() { rNFCONT |= (1<<6); }
- #define MECC_UNLOCK() { rNFCONT &= ~(1<<7); }
- #define SECC_UNLOCK() { rNFCONT &= ~(1<<6); }
- //COMMAND
- #define CMD_GETID 0x90
- #define CMD(cmd) { rNFCMD = cmd; }
- #define ADDR(addr) { rNFADDR = addr; }
- #define READ() (rNFDATA)
- #define WRITE(data) { rNFDATA = data; }
- //STATUS
- #define RNB_STATUS 0
- #define RNB_DETECT 4
- #define ILLEGAL_ACC 5
- #define ECC4_DONE 6
- #define NFSTAT(bit) (rNFSTAT & (1<<bit))
- #define CLEAR_RNB() { rNFSTAT |= (1<<RNB_DETECT); }
- #define CLEAR_ECC_DONE() { rNFSTAT |= (1<<ECC4_DONE); }
- static volatile U8 done;
- static U8 buffer[2048];
- static U8 spare_data[8] = {
- 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff
- };
- void __irq nf_int(void)
- {
- done = 1;
- if(NFSTAT(RNB_STATUS)){
- //Uart_Printf("device is ready\n");
- CLEAR_RNB();
- }
- if(NFSTAT(ILLEGAL_ACC))
- Uart_Printf("illegal access\n");
- if(NFSTAT(ECC4_DONE)){
- Uart_Printf("4bit ecc decoding done\n");
- CLEAR_ECC_DONE();
- }
- INTC_ClearVectAddr();
- }
- void nf_init(void)
- {
- rGPOCON = rGPOCON & ~0xf | 0xa;//nCS[3:2]
- rGPOPUD &= ~0xf;
- rGPPCON = rGPPCON & ~(0xfff << 4) | (0xaaa << 4);//nWAIT, FALE, FCLE,
- rGPPPUD &= ~(0xfff << 4);//FWEn, FREn, FRnB
- INTC_SetIntISR(INT_NFC, nf_int);
- INTC_Enable(INT_NFC);
- rNFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4) | (1<<2);
- rNFCONT = (0<<8) | 1;
- }
- U16 nf_getid(void)
- {
- U16 id;
- U8 tmp;
- NCE0(ENABLE);
- CMD(CMD_GETID);
- ADDR(0x0);
- id = (U16)READ();
- NCE0(DISABLE);
- tmp = id >> 8;
- id = (U16)(id<<8) | (tmp);
- return id;
- }
- void nf_erase_block(U16 block)
- {
- block <<= 6;
-
- EN_INT(ILLEGAL_ACC_INT);
- EN_INT(RNB_INT);
- NCE0(ENABLE);
- CLEAR_RNB();//注意在这里清除rnb检测信号
- CMD(0x60);
- ADDR(block&0xff);
- ADDR((block>>8)&0xff);
- ADDR((block>>16)&0xff);
- done = 0;
- CMD(0xd0);
- while(!done);
- CMD(0x70)
- if(READ()&0x1)
- Uart_Printf("erase error\n");
- DIS_INT(RNB_INT);
- DIS_INT(ILLEGAL_ACC_INT);
- NCE0(DISABLE);
- }
- void nf_write_page(U16 block, U8 page, U8 const *buffer)
- {
- U32 addr, tmp, mecc, secc;
- U16 i;
- U8 j;
- addr = block << 6 + page;
- EN_INT(ILLEGAL_ACC_INT);
- EN_INT(RNB_INT);
- NCE0(ENABLE);
- CLEAR_RNB();
- ECC_TYPE(_1BIT_ECC);
- INIT_MECC();
- INIT_SECC();
- CMD(0x80);
- ADDR(0);
- ADDR(0);
- ADDR(addr&0xff);
- ADDR((addr>>8)&0xff);
- ADDR((addr>>16)&0xff);
- MECC_UNLOCK();
- for(i = 0; i < 2048; i+=4){
- tmp = 0;
- for(j = 0; j < 4; j++){
- tmp |= buffer[i+j] << (8*j);
- }
- WRITE(tmp);
- }
- MECC_LOCK();
- mecc = rNFMECC0;
- spare_data[0] = mecc & 0xff;
- spare_data[1] = (mecc>>8) & 0xff;
- spare_data[2] = (mecc>>16) & 0xff;
- spare_data[3] = (mecc>>24) & 0xff;
- SECC_UNLOCK();
- tmp = 0xffffffff;
- WRITE(tmp);
- tmp = 0;
- for(j = 0; j < 4; j++)
- tmp |= spare_data[j] << (8*j);
- WRITE(tmp);
- SECC_LOCK();
- secc = rNFSECC;
- spare_data[4] = secc & 0xff;
- spare_data[5] = (secc>>8) & 0xff;
- tmp = 0;
- for(j = 0; j < 2; j++)
- tmp |= spare_data[4+j] << (8*j);
- WRITE(tmp);
- done = 0;
- CMD(0x10);
- while(!done);
- CMD(0x70);
- if(READ()&0x1)
- Uart_Printf("write error\n");
- DIS_INT(ILLEGAL_ACC_INT);
- DIS_INT(RNB_INT);
- NCE0(DISABLE);
- }
- void nf_read_page(U16 block, U8 page, U8 *buffer)
- {
- U32 addr, tmp, mecc, secc;
- U16 i;
- U8 j;
- addr = block << 6 + page;
- EN_INT(ILLEGAL_ACC_INT);
- EN_INT(RNB_INT);
- NCE0(ENABLE);
- CLEAR_RNB();
- ECC_TYPE(_1BIT_ECC);
- INIT_MECC();
- INIT_SECC();
- CMD(0x0);
- ADDR(0);
- ADDR(0);
- ADDR(addr&0xff);
- ADDR((addr>>8)&0xff);
- ADDR((addr>>16)&0xff);
- done = 0;
- CMD(0x30);
- while(!done);
- MECC_UNLOCK();
- for(i = 0; i < 2048; i+=4){
- tmp = READ();
- for(j = 0; j < 4; j++){
- buffer[i+j] = (U8)(tmp>>(8*j));
- }
- }
- MECC_LOCK();
- SECC_UNLOCK();
- mecc = READ();
- rNFMECCD0 = (mecc&0xff) | ((mecc&0xff00) << 8);
- rNFMECCD1 = ((mecc&0xff0000)>>16) | ((mecc&0xff000000) >> 8);
- secc = READ();
- SECC_LOCK();
- rNFSECCD = (secc&0xff) | ((secc&0xff00)<<8);
- if(rNFECCERR0 & 0xf)
- Uart_Printf("ecc error\n");
- else
- Uart_Printf("ecc ok\n");
- DIS_INT(ILLEGAL_ACC_INT);
- DIS_INT(RNB_INT);
- NCE0(DISABLE);
- }
- void xmain(void)
- {
- U16 i;
- Uart_Init();
- nf_init();
- Uart_Printf("the id is %x\n", nf_getid());
- nf_erase_block(2047);
- for(i = 0; i < 2048; i++)
- buffer[i] = (U8)i;
- nf_write_page(2047, 0, buffer);
- for(i = 0; i < 2048; i++)
- buffer[i] = 0;
- nf_read_page(2047, 0, buffer);
- for(i = 0; i < 256; i++){
- Uart_Printf("%3x", buffer[i]);
- if((i+1) % 16 == 0)
- Uart_Printf("\n");
- }
- while(1);
- }
|