S5PV210裸机之Nandflash
NAND Flash
關(guān)于NAND Flash
S5PV210的NAND Flash控制器有如下特點(diǎn):
1) 支持512byte,2k,4k,8k的頁(yè)大小
2) 通過(guò)各種軟件模式來(lái)進(jìn)行NAND Flash的讀寫擦除等
3) 8bit的總線
4) 支持SLC和MCL的NAND Flash
5) 支持1/4/8/12/16bit的ECC
6) 支持以字節(jié)/半字/字為單位訪問(wèn)數(shù)據(jù)/ECC寄存器,以字為單位訪問(wèn)其他寄存器。
注意:在此使用的Mini210S的NAND Flash類型為SLC,大小為1G,型號(hào)為K9K8G08U0A。所以本章的內(nèi)容是針對(duì)SLC類型的NAND Flash(包括256M/512M/1GB等),并不適用MLC類型的NAND Flash。
程序例子:(完整代碼見(jiàn)鏈接)
代碼多了nand.c這個(gè)文件,里面包含了對(duì)NAND Flash的相關(guān)操作。
/*nand.c*/
<1> NAND Flash初始化函數(shù)nand_init(),代碼如下
void nand_init(void)?
{?
// 1. 配置NAND Flash?
NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<3)|(0<<2)|(1<<1)|(0<<0);?
NFCONT =(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0x3<<1)|(1<<0);?
// 2. 配置引腳?
MP0_1CON = 0x22333322;?
MP0_2CON = 0x00002222;?
MP0_3CON = 0x22222222;?
// 3. 復(fù)位?
nand_reset();
}?
共3個(gè)步驟:
第一步 配置NAND Flash
主要是設(shè)置NFCONF和NFCONT兩個(gè)寄存器
NFCONF寄存器
AddrCycle = 1,When page size is 2K or 4K, 1 = 5 address cycle,Mini210S的NAND Flash的頁(yè)大小為2k,所有是5個(gè)地址周期;?
PageSize = 0,When MLCFlash is 0, the value of PageSize is as follows: 0 = 2048 Bytes/page,Mini210S使用的是SLC NAND Flash且每頁(yè)大小為2k;?
MLCFlash = 0,在此使用的是SLC NAND Flash;?
TWRPH1/TWRPH0/TACLS是關(guān)于訪問(wèn)時(shí)序的設(shè)置,需對(duì)照NAND Flash芯片手冊(cè)設(shè)置,這里不再詳細(xì)解釋,分別取TWRPH1=1,TWRPH0=4,TACLS=1;?
ECCType0/MsgLength,我們的裸機(jī)代碼沒(méi)有使用到ECC,所有不用設(shè)置這兩個(gè)標(biāo)志。
MODE = 1,使能NAND Flash控制器;?
Reg_nCE0 = 1,取消片選,需要操作NAND Flash時(shí)再發(fā)片選;?
Reg_nCE1 = 1, 取消片選,需要操作NAND Flash時(shí)再發(fā)片選;?
InitMECC/InitSECC/SECCLock/MECCLock,我們的裸機(jī)代碼不涉及ECC,這4個(gè)標(biāo)志位隨便設(shè)置即可;
RnB_TransMode = 0,Detect rising edge,RnB是NAND Flash的狀態(tài)探測(cè)引腳,我們使用上升沿觸發(fā);?
EnbRnBINT = 0 ,禁止RnB中斷;?
EnbIllegalAccINT = 0,禁止Illegal access 中斷 ;?
EnbMLCDecInt/EnbMLCEncInt為MCL相關(guān),不用設(shè)置;?
LOCK = 0,我們沒(méi)有用到Soft Lock,所以禁止Soft Lock;?
LockTight = 0,我們沒(méi)有用到Lock-tight,所有禁止Lock-tight;?
MLCEccDirection,MLC相關(guān),可不用設(shè)置
第二步 配置引腳
用于NAND Flash相關(guān)功能;
第三步 復(fù)位
復(fù)位函數(shù)nand_reset的相關(guān)代碼如下:?
static void nand_reset(void)?
{?
??? nand_select_chip();
??? nand_send_cmd(NAND_CMD_RES);?
??? nand_wait_idle();?
??? nand_deselect_chip();?
}?
NAND Flash的復(fù)位操作共4個(gè)步驟:
1) 發(fā)片選,實(shí)質(zhì)就是NFCONT &= ~(1<<1);往NFCONT的bit[1]寫0;
2) 發(fā)命令復(fù)位命令NAND_CMD_RES (0xff);實(shí)質(zhì)就是NFCMMD = cmd;將命令寫到NFCMMD寄存器;完整的NAND Flash命令信息見(jiàn)下圖:
3) 等待NAND Flash 就緒;實(shí)質(zhì)就是while( !(NFSTAT & (BUSY<<4)) ),讀NFSTAT的bit[4]檢查NAND Flash是否就緒;
4) 取消片選,實(shí)質(zhì)就是NFCONT |= (1<<1); 往NFCONT的bit[1]寫1;
<2> NAND Flash讀ID函數(shù)nand_read_id(),代碼如下
void nand_read_id(void)?
{?
nand_id_info nand_id;?
// 1. 發(fā)片選?
nand_select_chip();?
// 2. 讀ID?
nand_send_cmd(NAND_CMD_READ_ID);?
nand_send_addr(0x00);?
nand_wait_idle();?
nand_id.IDm = nand_read();?
nand_id.IDd = nand_read();
nand_id.ID3rd = nand_read();?
nand_id.ID4th = nand_read();?
nand_id.ID5th = nand_read();?
printf("NANDFlash: makercode = %x,devicecode = %x\r\n",nand_id.IDm,nand_id.IDd);?
nand_deselect_chip();?
}
NAND Flash 讀ID操作
根據(jù)上圖,NAND Flash的讀ID操作共4個(gè)步驟:
第一步 發(fā)片選;
第二步 發(fā)讀ID命令NAND_CMD_READ_ID(0x90);
第三步 發(fā)地址0x00;調(diào)用函數(shù)nand_send_addr();
第四步 等待NAND Flash 就緒;
第五步 讀ID;調(diào)用了nand_read()函數(shù),實(shí)質(zhì)就是讀NFDATA寄存器;
下面解釋一下函數(shù)nand_send_addr(),核心代碼如下:?
{?
// 列地址,即頁(yè)內(nèi)地址?
col = addr % NAND_PAGE_SIZE;?
// 行地址,即頁(yè)地址?
row = addr / NAND_PAGE_SIZE;?
// Column Address A0~A7?
NFADDR = col & 0xff;?
for(i=0; i<10; i++);
// Column Address A8~A11?
NFADDR = (col >> 8) & 0x0f;?
for(i=0; i<10; i++);?
// Row Address A12~A19?
NFADDR = row & 0xff;
for(i=0; i<10; i++);?
// Row Address A20~A27?
NFADDR = (row >> 8) & 0xff;?
for(i=0; i<10; i++);?
// Row Address A28~A30?
NFADDR = (row >> 16) & 0xff;?
for(i=0; i<10; i++);?
}?
首先根據(jù)頁(yè)大小來(lái)獲取頁(yè)地址和頁(yè)內(nèi)偏移地址,然后通過(guò)5個(gè)周期將地址發(fā)送出去,實(shí)質(zhì)就是寫NFADDR寄存器,具體每個(gè)周期如何發(fā)送,查閱NAND Flash芯片手冊(cè)可知,見(jiàn)下圖:
發(fā)送地址后,就可以連續(xù)讀出5個(gè)ID了,其中第一個(gè)是MAKDER CODE, 第二個(gè)是DEVICE CODE。
<3> NAND Flash擦除函數(shù)nand_erase(),核心代碼如下:
{?
// 獲得row地址,即頁(yè)地址?
unsigned long row = block_num * NAND_BLOCK_SIZE;?
// 1. 發(fā)出片選信號(hào)?
nand_select_chip();?
// 2. 擦除:第一個(gè)周期發(fā)命令0x60,第二個(gè)周期發(fā)塊地址,第三個(gè)周期發(fā)命令0xd0 nand_send_cmd(NAND_CMD_BLOCK_ERASE_1st);
for(i=0; i<10; i++);?
// Row Address A12~A19?
NFADDR = row & 0xff;?
for(i=0; i<10; i++);?
// Row Address A20~A27?
NFADDR = (row >> 8) & 0xff;?
for(i=0; i<10; i++);?
// Row Address A28~A30?
NFADDR = (row >> 16) & 0xff;?
NFSTAT = (NFSTAT)|(1<<4);?
nand_send_cmd(NAND_CMD_BLOCK_ERASE_2st);?
for(i=0; i<10; i++);?
// 3. 等待就緒?
nand_wait_idle();?
// 4. 讀狀態(tài)?
unsigned char status = read_nand_status();?
}
根據(jù)上圖,NAND Flash的擦除操作共6個(gè)步驟:
第一步 發(fā)片選;
第二步 發(fā)擦除命令1 NAND_CMD_BLOCK_ERASE_1(0x60);
第三步 發(fā)頁(yè)地址,只需發(fā)頁(yè)地址;
第四步 發(fā)擦除命令2 NAND_CMD_BLOCK_ERASE_2st(0xD0);
第五步 等待NAND Flash就緒;
第六步 讀狀態(tài),判斷擦除是否成功。若擦除失敗,則打印是壞塊再取消片選;否則直接直接取消片選即可。讀狀態(tài)調(diào)用了函數(shù)read_nand_status(),它的實(shí)質(zhì)就是nand_send_cmd(NAND_CMD_READ_STATUS);ch = nand_read();先發(fā)讀狀態(tài)命令NAND_CMD_READ_STATUS,然后再讀狀態(tài)值。???
<4> NAND Flash讀函數(shù)copy_nand_to_sdram(),從NAND Flash中讀數(shù)據(jù)到DRAM,核心代碼如下:
{?
// 1. 發(fā)出片選信號(hào) nand_select_chip();
// 2. 從nand讀數(shù)據(jù)到sdram,第一周期發(fā)命令0x00,第二周期發(fā)地址nand_addr,第三個(gè)周期發(fā)命令0x30,可讀一頁(yè)(2k)的數(shù)據(jù)
while(length)?
{?
nand_send_cmd(NAND_CMD_READ_1st);?
nand_send_addr(nand_addr);?
NFSTAT = (NFSTAT)|(1<<4);?
nand_send_cmd(NAND_CMD_READ_2st);?
nand_wait_idle();?
// 列地址,即頁(yè)內(nèi)地址?
unsigned long col = nand_addr % NAND_PAGE_SIZE;?
i = col;?
// 讀一頁(yè)數(shù)據(jù),每次拷1byte,共拷2048次(2k),直到長(zhǎng)度為length的數(shù)據(jù)拷貝完畢?
for(; i<NAND_PAGE_SIZE && length!=0; i++,length--)?
{?
*sdram_addr = nand_read();?
sdram_addr++; nand_addr++;?
}?
}?
// 3. 讀狀態(tài)?
unsigned char status = read_nand_status();?
}
NAND Flash 讀操作
根據(jù)上圖,NAND Flash的讀操作共7個(gè)步驟:
第一步 發(fā)片選;
第二步 發(fā)讀命令1 NAND_CMD_READ_1st(0x00);
第三步 發(fā)地址,調(diào)用函數(shù)nand_send_cmd(),發(fā)5個(gè)地址周期;
第四步 發(fā)讀命令2 NAND_CMD_READ_2st(0xD0);
第五步 等待NAND Flash就緒;
第六步 從頁(yè)內(nèi)偏移地址開(kāi)始讀,讀到頁(yè)結(jié)尾即結(jié)束,每次讀1byte;
第七步 讀狀態(tài),判斷是否讀成功。
<5> NAND Flash寫函數(shù)copy_sdram_to_nand (),從DRAM寫數(shù)據(jù)到NAND Flash,核心代碼如下:
{?
// 1. 發(fā)出片選信號(hào)?
nand_select_chip();?
// 2. 從sdram讀數(shù)據(jù)到nand,第一周期發(fā)命令0x80,第二周期發(fā)地址nand_addr,第三個(gè)周期寫一頁(yè)(2k)數(shù)據(jù),第四周期發(fā)0x10?
while(length)?
{?
nand_send_cmd(NAND_CMD_WRITE_PAGE_1st);?
nand_send_addr(nand_addr);?
// 列地址,即頁(yè)內(nèi)地址?
unsigned long col = nand_addr % NAND_PAGE_SIZE;?
i = col;?
// 寫一頁(yè)數(shù)據(jù),每次拷1byte,共拷2048次(2k),直到長(zhǎng)度為length的數(shù)據(jù)拷貝完畢?
for(; i<NAND_PAGE_SIZE && length!=0; i++,length--)?
{?
nand_write(*sdram_addr);?
sdram_addr++;?
nand_addr++;?
}?
NFSTAT = (NFSTAT)|(1<<4);?
nand_send_cmd(NAND_CMD_WRITE_PAGE_2st);?
nand_wait_idle();?
}?
// 3. 讀狀態(tài)?
unsigned char status = read_nand_status();
}
根據(jù)上圖,NAND Flash的寫操作共7個(gè)步驟:
第一步 發(fā)片選;
第二步 發(fā)寫命令1 NAND_CMD_WRITE_PAGE_1st (0x80);
第三步 發(fā)地址地址,調(diào)用函數(shù)nand_send_cmd(),發(fā)5個(gè)地址周期;
第四步 發(fā)讀命令2 NAND_CMD_WRITE_PAGE_2st (0x10);
第五步 等待NAND Flash就緒;
第六步 從頁(yè)內(nèi)偏移地址開(kāi)始寫,讀到頁(yè)結(jié)尾即結(jié)束,每次寫1byte;
第七步 讀狀態(tài),判斷是否讀成功。
2. main.c
在main.c中,首先會(huì)調(diào)用nand_init()來(lái)初始化NAND Flash,然后打印一個(gè)菜單,提供4種選擇測(cè)試NAND Flash:?
讀ID功能(nand_read_id());?
擦除功能(nand_erase());?
讀功能(copy_nand_to_sdram());?
寫功能(copy_sdram_to_nand());
總結(jié)
以上是生活随笔為你收集整理的S5PV210裸机之Nandflash的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: FreeModbus保持寄存器
- 下一篇: STM32之窗口看门狗原理