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