www.pudn.com > nandflash_1G08U0A.rar > drv_nandflash.c
//////////////////////////////////////////////////////////////////////// // ÎļþÃû £ºdrv_nandflash.c // Îļþ¹¦ÄÜ £ºÏµÍ³¶ÁÈ¡Nand FlashÇý¶¯ // ×÷Õß £ºcxl // ´´½¨Ê±¼ä £º2005Äê11ÔÂ11ÈÕ // ´¦ÀíÆ÷ : Epson C33L05 // ÏîÄ¿Ãû³Æ £º // ±¸×¢ £º // ¿ÉÒÔÇý¶¯µÄNand FlashÐͺţº K9F1G08U0A SAMSUNG //////////////////////////////////////////////////////////////////////// //Sys include file #include "..\include\common.h" #include "..\include\8timer.h" #include "..\include\16timer.h" #include "..\include\io.h" #include "..\include\presc.h" //Nand Flash driver file #include "comm_drv.h" #include "drv_nandfls.h" //#undef USE_K9F5616 //#undef USE_K9F2808U0M //#define USE_K9F1208U0M t_nand_fls_id this_nand_fls_id,*p_nand_fls_id; int nand_fls_init(void) { unsigned short i; //read id p_nand_fls_id = &this_nand_fls_id; memset(p_nand_fls_id,0,sizeof(t_nand_fls_id)); /*select ALE, CLE port as output*/ SET_ALE_L; SET_ALE_OUTPUT; SET_CLE_L; SET_CLE_OUTPUT; /* select CE15,16 data is high (P51)*/ SET_NAND_CE_H; /*select CE/GPIO port function as CE*/ SET_NAND_CE_CE; /*select CE as output*/ SET_NAND_CE_OUTPUT; /* set flash device mode*/ SET_DEVICE_8; /*select NAND flashmap to area 15 and boot function*/ SET_NAND_AREA; /*select SMWE,SMRD port function as flash I/F function */ //CLR_SMIFREG; SET_SMIF_WE; SET_SMIF_RD; /*set by/ry signal as input*/ SET_BUSY_INPUT; /*disable write protect*/ SET_WP_H; SET_WP_GPIO; /*set wp pin as output */ SET_WP_OUTPUT; SET_NAND_CE_L; asm("nop"); for(i=0;i<10000;i++){ asm("nop"); } //write read ID command SET_CLE_H; REG_CHAR(Nand_Fls_COMM_ADD)=0x90; SET_CLE_L; //write address 0 SET_ALE_H; REG_CHAR(Nand_Fls_Reg_ADD)=0x00; SET_ALE_L; //read maker id p_nand_fls_id->maker_code = REG_CHAR(Nand_Fls_Data_ADD); p_nand_fls_id->device_code = REG_CHAR(Nand_Fls_Data_ADD); p_nand_fls_id->rev1 = REG_CHAR(Nand_Fls_Data_ADD); p_nand_fls_id->mutiplane_code = REG_CHAR(Nand_Fls_Data_ADD); SET_NAND_CE_H; asm("nop"); if((p_nand_fls_id->maker_code == 0xEC)&&(p_nand_fls_id->device_code == 0xF1)\ &&(p_nand_fls_id->mutiplane_code == 0x15)) return NAND_INIT_OK; return NAND_INIT_ERROR; } void nand_fls_Reset(void){ int i; SET_CLE_H; /*set CLE H*/ *(volatile unsigned short*)NAND_Flash_BASE_ADDRESS=RESET_CMD; /*write RESET command*/ SET_CLE_L; /*set CE L*/ /*Wait flash R/#B ready (worst case 500us reset when erase; delay 1ms for safe)*/ for (i=0; i<800; i++) { asm("nop"); } return; } //ÕâÀïÓõ½µÄµØÖ·Èë¿Ú²ÎÊý¶¼ÊÇ×Ö½ÚµØÖ·£¬·¶Î§ÊÇ0--->128MB+4MB-1. //µØÖ·µÄ¸ñʽÊÇ:A7--A0,0000+A11---A8,A19--A12,A27--A20. //ÉÏÃæÕâÖÖÀí½âÊÇ´íÎóµÄ¡ //retÓÃÀ´¼ì²â²Á³ýÊÇ·ñÕýÈ·£¬ÔÚÄÚ´æÖÐ unsigned char ret; int nand_fls_erase_block(unsigned int Block_Number) { //unsigned char tmp_char; int i; SET_NAND_CE_L; asm("nop"); //Step 1 Write auto block erase setup command SET_CLE_H; REG_CHAR(Nand_Fls_COMM_ADD) = BLOCK_Er_SETUP_COMMAND; SET_CLE_L; //Step 2 Write address SET_ALE_H; //row address 1 REG_SHORT(Nand_Fls_Reg_ADD) = 0xff&(Block_Number<<6); //row address 2 REG_SHORT(Nand_Fls_Reg_ADD) = (0xff00&(Block_Number<<6))>>8; SET_ALE_L; //Step 3 Write erase command SET_CLE_H; REG_CHAR(Nand_Fls_COMM_ADD) = Er_COMMAND; SET_CLE_L; asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); do{} while (!CHECK_BUSY); /*wait R/#B to high*/ //Step 4 Write read status command SET_CLE_H; REG_CHAR(Nand_Fls_COMM_ADD) = READ_St_COMMAND; SET_CLE_L; if(REG_CHAR(Nand_Fls_Data_ADD) & ERASE_ERROR_FLAG) { SET_NAND_CE_H; ret = 1; return -1; } else { SET_NAND_CE_H; ret = 0; return 0; } } //ÕâÀï°ÑÕâ¸öµØÖ·²ÎÊýpage_num¿´³ÉÊÇÈÎÒâÒ»¸ö×ֽڵĵØÖ·¡£ //ÉÏÃæµÄ¿´·¨ÊÇ´íÎóµÄ int nand_fls_write_page(unsigned char *data,unsigned int page_num,unsigned int block_num) { unsigned short sWriteCount; int i; SET_NAND_CE_L; asm("nop"); //write page program command SET_CLE_H; REG_CHAR(Nand_Fls_COMM_ADD) = SEQ_DATA_IN_COMMAND; SET_CLE_L; //write column address SET_ALE_H; //column address 1 REG_SHORT(Nand_Fls_Reg_ADD) = 0; //colunm addr 2 REG_SHORT(Nand_Fls_Reg_ADD) = 0; //row addr 1 REG_SHORT(Nand_Fls_Reg_ADD) = 0xff&((block_num<<6)+page_num); //row addr 2 REG_SHORT(Nand_Fls_Reg_ADD) = (0xff00&((block_num<<6)+page_num))>>8; SET_ALE_L; //write data to nandflash for(sWriteCount = 0; sWriteCount < NAND_FLS_ALL; sWriteCount++) { REG_CHAR(Nand_Fls_Data_ADD) = REG_CHAR(data + sWriteCount); } //write program command 0x10 SET_CLE_H; REG_CHAR(Nand_Fls_COMM_ADD) = PROG_COMMAND; SET_CLE_L; asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); do{} while (!CHECK_BUSY); /*wait R/#B to high*/ //write read status command SET_CLE_H; REG_CHAR(Nand_Fls_COMM_ADD) = READ_St_COMMAND; SET_CLE_L; if(REG_CHAR(Nand_Fls_Data_ADD) & PROG_ERROR) { SET_NAND_CE_H; return -1; } else { SET_NAND_CE_H; return 0; } } int nand_fls_read_page(unsigned char *data,unsigned int page_num,unsigned int block_num) { unsigned short sReadCount; unsigned short i; SET_NAND_CE_L; asm("nop"); //write read command SET_CLE_H; REG_CHAR(Nand_Fls_COMM_ADD) = 0x00; SET_CLE_L; //write column address SET_ALE_H; REG_SHORT(Nand_Fls_Reg_ADD) = 0; REG_SHORT(Nand_Fls_Reg_ADD) = 0; REG_SHORT(Nand_Fls_Reg_ADD) = 0xff&((block_num<<6)+page_num); REG_SHORT(Nand_Fls_Reg_ADD) = (0xff00&((block_num<<6)+page_num))>>8; SET_ALE_L; //write read command 2 SET_CLE_H; REG_CHAR(Nand_Fls_COMM_ADD) = 0x30; SET_CLE_L; asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); do{} while (!CHECK_BUSY); /*wait R/#B to high*/ asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); for(i=0;i