您的位置:首页 > 其它

NandFlash驱动调试笔记(K9F1G08

2010-04-09 09:16 302 查看
NandFlash驱动调试笔记(K9F1G08)
Nand Flash结构与读写分析

NAND Flash 的数据是以bit 的方式保存在memory cell,一般来说,一个cell 中只能存储一个bit。这些cell 以8 个或者16 个为单位,连成bit line,形成所谓的byte(x8)/word(x16),这就是NAND Device 的位宽。这里1g08有两种128M*8bit和64M*16bit,这里要根据数据线来区分。这些Line 会再组成Page,(Nand Flash 有多种结构,我使用的Nand Flash 是K9F1G08,下面内容针对三星的K9F1G08U0M),每页2KByte,每64 个page 形成一个Block, Sizeof(block)=128kByte 。1 block=128kbyte, Numberof(block)=1024 1block=64page, 1page=2064byte=2kbyte(Main Area)+64byte(Spare Area)。
Nand flash 以页为单位读写数据,而以块为单位擦除数据。按照这样的组织方式可以形成所谓的三类地址: --Block Address -- Page Address --Column Address(即为页内偏移地址)
对于1g08来说,每一页有2kByte,所以A[0-11]就是Column Address ,而64个page占用了A[12-27] page address(文档中有说明)。地址传送顺序是Column Address,Page Address,Block Address。
Nand Flash的寻址
Nand Flash的地址寄存器把一个完整的Nand Flash地址分解成Column Address与Page Address.进行寻址。
Column Address: 列地址。Column Address其实就是指定Page上的某个Byte,指定这个Byte其实也就是指定此页的读写起始地址。
Paage Address:页地址。由于页地址总是以2kBytes对齐的,确定读写操作是在Flash上的哪个页进行的。
Nand flash 读命令
Read命令是0x00,读操作有4个cycle,首先发送读命令0x00,之后是4个cycle,1st cycle A[0-7] 和2st cycle A[8-11]是发送Column Address,3st cycle A[12-19]和 4st cycle A[20-27]是发送Row address (page address)
Nand flash 驱动函数讲解
1. FMD_Init()
// HCLK=133Mhz
#define TACLS 0
#define TWRPH0 6
#define TWRPH1 0
这里为什么rNFCONF配置这几个参数,可以根据cpu文档和1g08文档的时序来分析。
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
rNFCONT = 0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0);
rNFSTAT = 0;
2. ReadFlashID()
void NF_ReadID(){
USHORT wData1, wData2;
S8 i;
// First we enable chip select
NF_CE_L();
NF_CLEAR_RB();
// Issue commands to the controller
NF_CMD(CMD_READID);
NF_ADDR(0x00);
for (i = 0; i < 100; i++){ }
wData1 = (BYTE)NF_DATA_R();
wData2 = (BYTE)NF_DATA_R();
NF_CE_H();
Uart_SendString("Nand Mfg: ");
Uart_SendDWORD((DWORD)wData1, TRUE);
Uart_SendString("Nand Dev: ");
Uart_SendDWORD((DWORD)wData
3. FMD_ReadSector()
BOOL FMD_ReadSector1G08(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{ ULONG SectorAddr = (ULONG)startSectorAddr;
int i;
BOOL bLastMode = SetKMode(TRUE);
NF_RSTECC(); // Initialize ECC.
NF_nFCE_L(); // Select the flash chip.
NF_CLEAR_RB();
NF_CMD(CMD_RESET); // Send reset command.
for(i=0;i<10;i++);
NF_DETECT_RB();
while (dwNumSectors--)// dwNumSectors表示读取多少个页 如果要读取3个block dwNumSectors=64*3(Nboot)
{
ULONG blockPage = SectorAddr;//页地址如果要从nand的第2个开始读blockPage = 64*2
if(pSectorBuff)//读取数据存放buf pSectorBuff = 0x30080000(nboot)
{
NF_CLEAR_RB();
NF_CMD(CMD_READ); // Send read command.
NF_ADDR(0); // Column (A[7:0]) = 0
NF_ADDR(0); // A[11:8] 因为这里是从每一页的开始开始读所以列地址都是0
NF_ADDR((blockPage)&0xff); // A[19:12]这里是从哪一页(blockPage)开始读取数据
NF_ADDR((blockPage>>8)&0xff); // A[27:20]
NF_CLEAR_RB();
NF_CMD(0x30); // 2'nd command
NF_DETECT_RB();
if((DWORD) pSectorBuff&0x3) {
RdPage2048Unalign (pSectorBuff,(PULONG)&s2440NAND->NFDATA); }
else {
RdPage2048(pSectorBuff,(PULONG)&s2440NAND->NFDATA); // Read page/sector data.}}
++SectorAddr;
pSectorBuff += NAND_PAGE_SIZE; }
NF_nFCE_H(); // Deselect the flash chip.
return(TRUE);
}
4. FMD_EraseBlock()
BOOL FMD_EraseBlock1G08(BLOCK_ID blockID)
{
BYTE Status;
ULONG blockPage = (blockID * NAND_PAGE_CNT); // Convert block address to page address.

BOOL bLastMode = SetKMode(TRUE);

NF_nFCE_L(); // Select the flash chip.
NF_CLEAR_RB();
NF_CMD(CMD_ERASE); // Send block erase command.
// Address 2-cycle
NF_ADDR((blockPage)&0xff); // Page number=0
NF_ADDR((blockPage>>8)&0xff);
NF_CMD(CMD_ERASE2); // Send block erase confirm command.
//NF_WAITRB(); // Wait for flash to complete command.
NF_DETECT_RB();
// Check the status
NF_CMD(CMD_STATUS);
Status = NF_RDDATA(); // Read command status.
NF_nFCE_H(); // Deselect the flash chip.

SetKMode (bLastMode);
return((Status & 1) ? FALSE : TRUE);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: