📄 k9f1208.c
字号:
/****************************************Copyright (c)**************************************************
** evoc
**
** http://www.evoc.com
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: main.c
** Last modified Date:
** Last Version:
** Description:
**
**------------------------------------------------------------------------------------------------------
** Created By: kuangyaowen
** Created date: 2007.12.03
** Version:
** Descriptions:nand flash 驱动程序
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/
#include "config.h"
/*NAND操作定义*/
#define NAND_ADDRESS_BASE (0xffe00000)
#define NAND_ALE (*(volatile unsigned char *)0xffc00002) /*bit 0*/
#define NAND_CLE (*(volatile unsigned char *)0xffc00002) /*bit 1*/
#define NAND_CE (*(volatile unsigned char *)0xffc00002) /*bit 2*/
#define NANF_CE_LOW() NAND_CE = NAND_CE & (~0x4)
#define NANF_CE_HIGH() NAND_CE = NAND_CE | 0x4
/* NAND Flash控制器命令字定义*/
#define CMD_READ0 0x00
#define CMD_READ1 0x01
#define CMD_PAGEPROG 0x10
#define CMD_READOOB 0x50
#define CMD_ERASE1 0x60
#define CMD_STATUS 0x70
#define CMD_SEQIN 0x80
#define CMD_READID 0x90
#define CMD_ERASE2 0xD0
#define CMD_RESET 0xFF
#define MAX_BLOCK_NUM 4096
#define PAGE0 0
#define PAGE1 1
UINT8 eccbufw[3]={0xff,0xff,0xff};
UINT8 eccbufr[3]={0,0,0};
#define NAND_READ_DATA() (*(volatile UINT8 *)NAND_ADDRESS_BASE)
/*用于存放NAN FLASH 坏块信息*/
UINT8 nan_valid_block_bitmap[MAX_BLOCK_NUM] = {0};
void cle()
{
int i;
for(i=0;i<10;i++)
{
NAND_CLE =0x55;
taskDelay(1);
printf("cle %d= 0x%x\n",i,NAND_CLE);
}
for(i=0;i<10;i++)
{
NAND_CLE =0xaa;
taskDelay(1);
printf("cle %d= 0x%x\n",i,NAND_CLE);
}
}
/*命令锁存(CLE) 取消*/
void nand_cle_low()
{
int i;
for(i=0;i<1000;i++)
{
NAND_CLE &=~0x2 ;
if((NAND_CLE &0x2) == 0x00)
{
break;
}
}
if(i==1000)
{
printf("CLE low time out ...\n");
}
}
/*命令锁存(CLE) 置位*/
void nand_cle_high()
{
int i;
for(i=0;i<1000;i++)
{
NAND_CLE |=0x2 ;
if((NAND_CLE &0x2) == 0x2)
{
break;
}
}
if(i==1000)
{
printf("CLE high time out ...\n");
return;
}
}
/*地址锁存(ALE) 取消*/
void nand_ale_low()
{
int i;
for(i=0;i<1000;i++)
{
NAND_ALE &=~0x1 ;
if((NAND_ALE&0x1) == 0x00)
{
break;
}
}
if(i==1000)
{
printf("ALE low time out ...\n");
}
}
/*地址锁存(ALE) 置位*/
void nand_ale_high()
{
int i;
for(i=0;i<1000;i++)
{
NAND_ALE |=0x1 ;
if((NAND_ALE&0x1) == 0x1)
{
break;
}
}
if(i==1000)
{
printf("ALE high time out ...\n");
return;
}
}
/*nand flash片选有效*/
void nand_ce_low()
{
int i;
for(i=0;i<1000;i++)
{
NAND_CE &=~0x4 ;
if((NAND_CE&0x4) == 0x00)
{
break;
}
}
if(i==1000)
{
printf("CE low time out ...\n");
}
}
/*nand flash片选取消*/
void nand_ce_high()
{
int i;
for(i=0;i<1000;i++)
{
NAND_CE |=0x4 ;
if((NAND_CE&0x4) == 0x4)
{
break;
}
}
if(i==1000)
{
printf("CE high time out ...\n");
return;
}
}
/*发送nand flash操作命令*/
void nand_write_command(UINT8 command)
{
nand_cle_high();
*(volatile UINT8 *)NAND_ADDRESS_BASE = command;
nand_cle_low();
}
/*发送地址*/
void nand_write_address(UINT8 address)
{
*(volatile UINT8 *)NAND_ADDRESS_BASE = address;
}
/*读取数据*/
UINT8 nand_read_data()
{
return (*(volatile UINT8 *)NAND_ADDRESS_BASE);
}
/*发送数据*/
void nand_write_data(UINT8 data)
{
*(volatile UINT8 *)NAND_ADDRESS_BASE = data;
}
/*复位nand flash芯片*/
void nand_reset()
{
nand_ce_low(); /*片选有效*/
nand_write_command(0xff); /*发送复位命令*/
taskDelay(2);
nand_ce_high(); /*片选取消*/
}
/*nand flash操作初始化*/
void nand_init()
{
sysPciConfigWrite(0,0,0,0xf6,2,0x1440); /*MCCR2 (mpc107)
bit28-25 :0b1010 (10 clocks) AS rise time
bit24-21 :0b1010 (10 clocks) AS fall time*/
nand_cle_low();
nand_ale_low();
nand_ce_high();
nand_reset();
}
/*********************************************************************************************************
** Function name: nand_get_id
** Descriptions: 读取器件ID (ID Read1)
** Input: 无
** Output: 返回值即时读出的4字节ID信号 (先读出的数据放在最高字节处)
** Created by:
** Created Date:2007-11-13
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int nand_get_id(void)
{
int id = 0;
/*发送命令和地址*/
nand_ce_low(); /*片选有效*/
nand_write_command(CMD_READID); /*发送读ID命令*/
nand_ale_high();
nand_write_address(0x00); /*发送地址0*/
nand_ale_low();
taskDelay(1);
/*读取ID信息*/
id += nand_read_data(); /*manufacture ID*/
id <<= 8;
id += nand_read_data(); /*device code*/
id <<= 8;
id += nand_read_data(); /**/
id <<= 8;
id += nand_read_data(); /**/
nand_ce_high(); /*片选取消*/
return id;
}
/*********************************************************************************************************
** Function name: nand_erase_block
** Descriptions: 块擦除操作
** Input: block: 擦除某个块 (不算空闲区,即64MB的地址)
** Output: 擦除成功返回0,否则返回-1
** Created by:
** Created Date: 2007-11-13
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int nand_erase_block(UINT32 block)
{
UINT32 blockpage; /*块地址*/
UINT8 status;
UINT32 n = 0;
blockpage = block<<5;/* block 00000 (A8 0000 0000:not send),所以左移5位 */
/* 发送命令和地 址 */
nand_ce_low(); /*片选有效*/
nand_write_command(CMD_ERASE1); /* 发送块擦除命令0x60*/
/*注意只送了3个周期*/
nand_ale_high();
nand_write_address(blockpage&0xff); /* 发送地址A9--A16*/
nand_write_address((blockpage>>8) & 0xff); /* 发送地址A17--A24*/
nand_write_address((blockpage>>16)& 0x01); /* 发送地址A25 */
nand_ale_low();
nand_write_command(CMD_ERASE2); /*0xd0*/
taskDelay(1);
nand_write_command(CMD_STATUS); /* 发送读取状态命令0x70 */
status = nand_read_data();
/*等待操作完成*/
while(!(status&0x40)) /* I/O(6) ==1 */
{
n++;
nand_write_command(CMD_STATUS);
status = nand_read_data();
if(n>10000)
{
printf("nand_erase_block time out!\n");
break;
}
}
nand_ce_high(); /*片选取消*/
/*printf("status = 0x%x\n",status);*/
if(status&0x01)
{
return (-1); /*erase fail*/
}
else
{
return (0); /*erase success */
}
}
/*********************************************************************************************************
** Function name: nand_wite_page
** Descriptions: 写一页数据
** Input: block: 块号
page 页号
** Output :
** Created by:
** Created Date: 2007-11-13
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int nand_wite_page(UINT32 block,UINT8 page,UINT8 *buf)
{
UINT32 blockpage;
UINT32 i;
UINT8 status;
UINT32 n=0;
blockpage=(block<<5)+page;
/*NF_RSTECC();*/ /*ECC使能*/
nand_ce_low(); /*片选有效*/
nand_write_command(CMD_READ0); /*从0x00位置开始写一页*/
nand_write_command(CMD_SEQIN); /*0x80*/
nand_ale_high();
nand_write_address(0x00); /*A7-A0为0x00*/
nand_write_address(blockpage&0xff); /*A9-A16*/
nand_write_address((blockpage>>8)&0xff);/*A17-A24*/
nand_write_address((blockpage>>16)&0x01); /*A25*/
nand_ale_low();
/*load data to nandflash*/
for(i=0;i<512;i++)
{
nand_write_data(buf[i]);
}
#if 0
/*写OOB区数据,只写前面的三个为了测试*/
/*
eccbuf[0]=rNF_ECC0;
eccbuf[1]=rNF_ECC1;
eccbuf[2]=rNF_ECC2; /*两种方法都可以*/
*/
i=0x55;
eccbuf[0]=i&0xff;
eccbuf[1]=(i>>8)&0xff;
eccbuf[2]=(i>>16)&0xff;
printf("W_EEC0:0x%x,W_EEC1:0x%x,W_EEC2:0x%x\n",eccbuf[0],eccbuf[1],eccbuf[2]);
for(i=0;i<3;i++)
{
nand_write_data(eccbuf[i]);
}
#endif
for(i=0;i<3;i++)
{
nand_write_data(eccbufw[i]);
}
nand_write_command(CMD_PAGEPROG); /*发送编程命令0x10*/
/*taskDelay(1);*/
nand_write_command(CMD_STATUS); /* 发送读取状态命令0x70 */
status = nand_read_data();
/*等待操作完成*/
while(!(status&0x40)) /* I/O(6) ==1 */
{
n++;
nand_write_command(CMD_STATUS);
status = nand_read_data();
if(n>10000)
{
printf("nand_wite_page time out!\n");
break;
}
}
nand_ce_high(); /*片选取消*/
/*printf("status = 0x%x\n",status);*/
if(status&0x01)
{
return -1;
}
else
{
return 0;
}
}
/*********************************************************************************************************
** Function name: nand_read_page
** Descriptions: 读一页数据
** Input: block: 块号 (0-4095)
page 页号(0-31)
** Output :
** Created by:
** Created Date: 2007-11-14
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int nand_read_page(UINT32 block,UINT8 page,UINT8 *buf_ret)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -