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);
}
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);
}
相关文章推荐
- linux设备驱动学习笔记--内核调试方法之printk
- pl022 ssp 驱动调试笔记
- NAND FLASH学习笔记之MTD下nand flash驱动(七)---我的调试
- 学习笔记 --- LINUX 驱动调试之根据栈信息来分析
- S3C2440Camera驱动调试笔记
- MT6573 驱动调试笔记
- MTK平台驱动调试笔记
- passthru驱动调试笔记
- k9f1g08 2K page nand flash驱动调试
- 使用bindview自动安装passthru驱动的调试笔记
- MPU6500驱动调试笔记(STM32F407+SPI)
- linux 驱动调试笔记二----LCD驱动01
- 学习笔记 --- LINUX 驱动调试之使用proc
- android TP驱动移植调试笔记
- [RK3288][Android6.0] 调试笔记 --- 通用GPIO驱动控制LED
- 学习笔记 --- LINUX MTD设备之NANDFLASH驱动分析
- passthru驱动调试笔记
- android TP驱动移植调试笔记(转)
- asm以太网驱动调试笔记
- LED字符设备驱动调试笔记