個人對nandflash驅動的總結(ok6410版)
1,首先說明要用nandflash的原因,當你從nand啟動時,6410中的硬體會自動將nand中的8k內容拷貝到開發板中記憶體空間的iRAM中,然後iRAM再將這8k內容拷貝到內從中進行執行,一旦nand中的內容大於8k則多餘的那些將無法被拷貝機執行,因此需要一個驅動程式來將多餘的程式碼移到記憶體中那就是nandflash驅動程式
2 其次說說使用了nandflash之後的程式碼搬移過程;第一步,硬體會自動將nand中的8k內容拷貝到開發板中記憶體空間的iRAM中,然後iRAM再將這8k內容拷貝到內從中進行執行, 第二步,將nand中剩餘的程式碼直接拷貝到記憶體中接著執行
3現在到了程式碼編寫時間,其他的不多說因為已經總結完了,就說自己被卡的地方
就在頁讀這裡出錯了結果導致整個程式有問題,之後參考了正確的程式碼,執行出來了
程式碼如下;
#define NFCONF (*((volatile unsigned long*)0x70200000))
#define NFCONT (*((volatile unsigned long*)0x70200004))
#define NFCMMD (*((volatile unsigned char*)0x70200008))
#define NFSTAT (*((volatile unsigned char*)0x70200028))
#define NFADDR (*((volatile unsigned char*)0x7020000c))
#define NFDATA (*((volatile unsigned char*)0x70200010))
void select_ship(void)
{
NFCONT &= ~(1<<1);
}
void delselect_ship(void)
{
NFCONT |= (1<<1);
}
void clean_RnB()
{
NFSTAT |= (1<<4);
}
void nand_cmd(unsigned char cmd)
{
NFCMMD = cmd;
}
void wait_RnB(void)
{
while(!(NFSTAT & 0x1));
}
void nand_addr(unsigned char addr)
{
NFADDR = addr;
}
void nand_reset(void)
{
/* 選中 */
select_ship();
/* 清除RnB */
clean_RnB();
/* 發出復位訊號 */
nand_cmd(0xff);
/* 等待就緒 */
wait_RnB();
/* 取消選中 */
delselect_ship();
}
void nand_init(void)
{
/*
HCLK的頻率為100MHZ,週期就為10ns
TACLS > 0 ns
TWRPH0 > 15ns
TWRPH1 > 5ns
TACLS的值 = HCLK x TACLS > 0ns
TWRPH0的值 = HCLK x (TWRPH0 + 1) > 15ns
TWRPH1的值 = HCLK x (TWRPH1 +1) > 5ns
*/
/* 設定時間引數 */
#define TACLS 1
#define TWRPH0 2
#define TWRPH1 1
NFCONF &= ~((7<<12)|(7<<8)|(7<<4));
NFCONF |= (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* 使能 nandflash controller*/
NFCONT = 1 | (1<<1);
/* 復位 */
nand_reset();
}
void NF_PageRead(unsigned long addr,unsigned char* buff)
{
int i;
/* 選中晶片 */
select_ship();
/* 清除RnB */
clean_RnB();
/* 發出命令0x00 */
nand_cmd(0x00);
/* 發出列地址 */
nand_addr(0x00);
nand_addr(0x00);
/* 發出行地址 */
nand_addr(addr&0xff);
nand_addr((addr >>8 ) & (0xff));
nand_addr((addr >>16 ) & (0xff));
/* 發出命令0x30 */
nand_cmd(0x30);
/* 等待就緒 */
wait_RnB();
/* 讀資料 */
for(i = 0; i<1024*4; i++)
{
buff[i] = NFDATA;
}
/* 取消片選 */
delselect_ship();
}
void nand_to_ram(unsigned long start_addr,unsigned char* sdram_addr,int size)
{
/* i為頁號、sdram_addr為記憶體中的位置、size拷貝資料的大小 */
int i;
unsigned int page_shift = 12;
/* 頁的起始地址給i(i為頁號),這個start_addr包含列地址和行地址,我們只需要頁地址(行地址) */
/*for(i=(start_addr >> 12);size>0;)
{
NF_PageRead(i,sdram_addr); //讀一頁的資料
size -= 1024*4; //ok6410頁的大小是4K
start_addr += 1024*4;
i++;
}
*/
/* Read pages */
for (i = 0; i < 4; i++, sdram_addr+=(1<<(page_shift-1)))
{
NF_PageRead(i,sdram_addr);
}
/* Read pages */
for (i = 4; i < (0x3c000>>page_shift); i++, sdram_addr+=(1<<page_shift))
{
NF_PageRead(i,sdram_addr);
}
}
int NF_Erase(unsigned long addr)
{
int ret;
//選中flash晶片
select_ship();
//清除RnB
clean_RnB();
//傳送命令60
nand_cmd(0x60);
//傳送行地址(3個週期)
nand_addr(addr&0xff);
nand_addr((addr >>8 ) & (0xff));
nand_addr((addr >>16 ) & (0xff));
//傳送命令D0
nand_cmd(0xD0);
//等待RnB
wait_RnB();
//傳送命令70
nand_cmd(0x70);
//讀取擦除結果
ret = NFDATA;
//取消選中flash晶片
delselect_ship();
return ret;
}
int NF_WritePage(unsigned long addr,unsigned char* buff)
{
int ret,i;
//選中flash晶片
select_ship();
//清除RnB
clean_RnB();
//傳送命令80
nand_cmd(0x80);
//傳送列地址(2個週期)
nand_addr(0x00);
nand_addr(0x00);
//傳送行地址(3個週期)
nand_addr(addr&0xff);
nand_addr((addr >>8 ) & (0xff));
nand_addr((addr >>16 ) & (0xff));
//寫入資料
for(i=0;i<1024*4;i++)
{
NFDATA = buff[i];
}
//傳送命令10
nand_cmd(0x10);
//等待RnB
wait_RnB();
//傳送命令70
nand_cmd(0x70);
//讀取寫入結果
ret = NFDATA;
//取消選中flash晶片
delselect_ship();
return ret;
}