NandFlash驅動除錯筆記(K9F1G08
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);
}
相關文章
- 如何編寫linux下nandflash驅動-4LinuxNaN
- JSP筆記-除錯JS筆記除錯
- SPI轉can晶片CSM300詳解以及Linux驅動移植除錯筆記晶片Linux除錯筆記
- 筆記|軟體除錯的技巧筆記除錯
- VS斷點除錯簡單筆記斷點除錯筆記
- h5學習筆記:動態載入vconsole 除錯工具H5筆記除錯
- Linux核心模組驅動載入與dmesg除錯Linux除錯
- Bug除錯專項訓練三筆記除錯筆記
- Bug除錯專項訓練四筆記除錯筆記
- HP筆記本驅動安裝教程筆記
- RealSence 驅動及ROS包配置筆記ROS筆記
- 海康ID2013掃碼槍除錯筆記除錯筆記
- spark學習筆記--Spark調優與除錯Spark筆記除錯
- 除錯一記除錯
- 驅動除錯—還原 QQ 過濾驅動對關鍵核心設施所做的修改(Part II)除錯
- Linux驅動開發筆記(一):helloworld驅動原始碼編寫、makefile編寫以及驅動編譯Linux筆記原始碼編譯
- dvd驅動器怎麼刪除 win10如何刪除dvd驅動器Win10
- 嵌入式開發筆記——除錯元件SEGGER_RTT筆記除錯元件
- 嵌入式開發筆記——除錯元件SEGGER_HardFaultHandle筆記除錯元件
- 《實現領域驅動設計》筆記——架構筆記架構
- win10在哪更新驅動程式 win10筆記本更新驅動怎麼弄Win10筆記
- GDB除錯使用記錄除錯
- kx音效卡驅動win10沒有聲音怎麼除錯Win10除錯
- Xcode動態除錯原理XCode除錯
- Python 學習除錯記錄Python除錯
- GitHub學習除錯記錄Github除錯
- Supervisor 安裝除錯記錄除錯
- 驅動除錯——挫敗 QQ.EXE 的核心模式保護機制(part I)除錯模式
- 【職場筆記】遊戲工程師如何自我驅動成長?筆記遊戲工程師
- 嵌入式系統除錯Uboot串列埠互動除錯除錯boot串列埠
- Linux驅動開發筆記(四):裝置驅動介紹、熟悉雜項裝置驅動和ubuntu開發雜項裝置DemoLinux筆記Ubuntu
- Linux驅動開發筆記(三):基於ubuntu的驅動、makefile編寫以及編譯載入流程Linux筆記Ubuntu編譯
- 除錯篇——除錯物件與除錯事件除錯物件事件
- Apk_動態除錯方案APK除錯
- phpstorm進行動態除錯PHPORM除錯
- 移動端網頁除錯網頁除錯
- [Flutter]啟動:除錯執行Flutter除錯
- Laravel 佇列 --- database 驅動(今天剛學習了佇列,記錄下筆記)Laravel佇列Database筆記
- AMD承諾改進筆記本銳龍APU顯示卡驅動:每年提供至少兩次驅動更新筆記