NandFlash驅動除錯筆記(K9F1G08

xuefeng_baggio發表於2010-04-09

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);
}
 

 

相關文章