?? norflash驅動寫法.c
字號:
//**************************************************************************************************
//*** linux-2.6內核中等待的使用例子 : norflash擦除時等待
static int erase_one_block(struct map_info *map, struct flchip *chip,
unsigned long addr, unsigned long size)
{
schedule_timeout(HZ);
while (flash_is_busy(map, chip->start))
{
unsigned long timeout = jiffies + HZ;
/* OK Still waiting */
if (time_after(jiffies, timeout))
{
// 在規定時間沒有等到的出錯處理
chip->state = FL_READY;
spin_unlock_bh(chip->mutex);
printk(KERN_WARNING "%s: waiting for erase to complete "
"timed out.\n", map->name);
return -EIO;
}
}
}
//**************************************************************************************************
//***
(1)對norflash的認識:
1.norflash有生產ID(用于區分某個廠商的flash)和設備ID(用于區分一個廠商的某種型號的flash)之分
2.norflash的block分為兩類:parameter block 和main block
一般parameter block的總的size為一個main block的size
3.
塊:是norflash擦除的單位(有32KB和128KB兩種)
分區:屬于同一個分區的共享同一個狀態寄存器
//**************************************************************************************************
//*** norflash操作原理:假設現在討論的norflash連接在cpu的地址空間的0x0C000000位置的intel L18F256 32MB norflash(塊大小為128KB)
/*
intel E28F128J3A150 16MB 16bit norflash 和bf561相連的接法為 :
bf561 <=> E28F128J3A150
A[23:1] => A[23:1] //bf561給norflash的地址信號
D[15:0] => D[15:0] //bf561給norflash的數據信號
/AMS0 => /CE //bf561給norflash的片選信號
/AOE => /OE //bf561給norflash的讀信號
/AWE => /WE //bf561給norflash的寫信號
/BYTE //上拉為高
VPEN //上拉為高
/RP //上拉為高
*/
1.norflash讀取生產ID和設備ID的步驟:
1)執行相應的命令序列:=>向norflash的基地址發送命
*(0x0C000000 + 0x5555) = 0x00AA;
*(0x0C000000 + 0x2AAA) = 0x0055;
*(0x0C000000 + 0x5555) = 0x0090;
2)開始讀取生產ID:
(u16)mnfID=*(0x0C000000+0x0);
3)開始讀取設備ID:
(u16)devID=*(0x0C000000+0x2);
2.以塊為單位擦除norflash的步驟:(假設擦除uboot所在分區:0x0C100000)
1)禁止flash的寫保護: //設置EMIFS_CONFIG寄存器的最低位為1(即讓wp引腳輸出為高)
2)Block unlock
*((short*)0x0C100000) = 0x0060; //塊對齊地址
*((short*)0x0C100000) = 0x00D0; //塊對齊地址
while(!(*((short*)0x0C100000) & 0x0080)); //塊對齊地址
*((short*)0x0C100000) = 0x00FF; //設置norflash為read array模式
3)執行擦除命令序列:=>向要操作的塊地址發送命令
*((short*)0x0C100000) = 0x0020; //塊對齊地址,INTEL_ERASE_CMD0
*((short*)0x0C100000) = 0x00D0; //塊對齊地址,INTEL_ERASE_CMD1
while (!(*((short*)0x0C100000) & 0x0080)); //塊對齊地址,等待直到擦除結束
5)設置norflash為read array模式
*((short*)0x0C100000) = 0x00FF; //讓norflash重新進入read array模式
6)使能flash的寫保護://設置EMIFS_CONFIG寄存器的最低位為0(即讓wp引腳輸出為低)
3.以塊為單位寫norflash的步驟:(假設寫uboot所在分區:0x0C100000)
/*
發送寫命令(0xE8)->發送數據->發送確認寫命令(0xD0)->確認狀態寄存器命令(0x70)->清掉狀態寄存器命令(0x50)
塊對齊 字對齊 塊對齊 字對齊 字對齊
*/
1)禁止flash的寫保護://設置EMIFS_CONFIG寄存器的最低位為1(即讓wp引腳輸出為高)
2)發送寫命令: //塊對齊地址
*((short*)0x0C100000)=0x00E8; //塊對齊地址,program setup command
while(!(*0x0C100000 & 0x0080)); //塊對齊地址
3)開始發送要寫到flash的數據 =>(這些數據會在norflash芯片內部的buffer中鎖存起來) =>每次2個字節,因為數據總線寬度為16位
(short *)ulData = 0x10010000 =>SDRAM的地址
(long *)psAddress = 0x0C000000 =>Norflash的地址
for(i=0; i<15; i++)
{
*psAddress = ulData[i];
psAddress++;
}
4)通知norflash將存在自己buffer中的數據寫到norflash的介質上:
*((short*)0x0C100000)=0x00D0; //塊對齊地址
5)讀狀態寄存器,確保步驟4)已經完成
*0x0C100000 = 0x0070; //Check Status Register ,這里是字對齊的地址
while(!(*0x0C100000 & BIT7)); //字對齊地址
6)// Check program status.
if ( *0x0C100000 & 0x0010 ) //字對齊地址
{
*0x0C100000 = 0x0050; //字對齊地址, Clear Status
*((short*)0x0C100000) = 0x00FF; //塊對齊地址 Put chip back into read array mode.
return 1;
}
7)使能flash的寫保護://設置EMIFS_CONFIG寄存器的最低位為0(即讓wp引腳輸出為低)
//**************************************************************************************************
//*** norflash操作原理:假設現在討論的norflash連接在cpu的地址空間的0x0C000000位置的st stm29w640d 8MB norflash(塊大小為64KB,16位寬度)
//=> 注意ST和intel norflash是有區別的 :
// ST的norflash A0可用, 故對16bit的接法為A1接A0,后面引腳類推
//intel的norflash A0不可用,故對16bit的接法為A1接A1,后面引腳類推
//
/*
1).st stm29w640d 8MB 16bit norflash 和bf561相連的接法為 :
bf561 <=> stm29w640d
/ABE3 => A0 //注意ABE[3]在這里被當成A1來使用:
A[22:2] => A[21:1] //bf561給norflash的地址信號
D[15:0] => D[15:0] //bf561給norflash的數據信號
/AMS0 => /CE //bf561給norflash的片選信號
/AOE => /OE //bf561給norflash的讀信號
/AWE => /WE //bf561給norflash的寫信號
RDY //上拉為高
/BYTE //上拉為高
WP_/VPP //上拉為高
/RP //上拉為高
2).注意ABE[3]在這里被當成A1來使用:
The ABE[3] pin of bf561 has two different functions. When the AMC is configured
to do 16-bit data packing via the Asynchronous Memory Global Control
Register,the ABE[3] pin of bf561 functions as the least significant bit of the address bus (ABE[3] = A1).
*/
1.norflash讀取生產ID和設備ID的步驟:
1)執行相應的命令序列:=>向norflash的基地址發送命
*(0x0C000000 + 0x5555) = 0x00AA;
*(0x0C000000 + 0x2AAA) = 0x0055;
*(0x0C000000 + 0x5555) = 0x0090;
2)開始讀取生產ID:
(u16)mnfID=*(0x0C000000+0x0);
3)開始讀取設備ID:
(u16)devID=*(0x0C000000+0x2);
2.以塊為單位擦除norflash的步驟:(假設擦除uboot所在分區:0x0C100000)
1)禁止flash的寫保護: //設置EMIFS_CONFIG寄存器的最低位為1(即讓wp引腳輸出為高)
2)Block unlock //無
3)執行擦除命令序列:=>向要操作的塊地址發送命令
*((short*)0x0C100000 + 0x555) = 0x00AA;
*((short*)0x0C100000 + 0x2AA) = 0x0055;
*((short*)0x0C100000 + 0x555) = 0x0080;
*((short*)0x0C100000 + 0x555) = 0x00AA;
*((short*)0x0C100000 + 0x2AA) = 0x0055;
*((short*)0x0C100000) = 0x0030; //塊對齊地址
while (!(*((short*)0x0C100000) & 0x0080)); //塊對齊地址,等待直到擦除結束
5)設置norflash為read array模式
*((short*)0x0C100000) = 0x00FF; //讓norflash重新進入read array模式
6)使能flash的寫保護://設置EMIFS_CONFIG寄存器的最低位為0(即讓wp引腳輸出為低)
3.以塊為單位寫norflash的步驟:(假設寫uboot所在分區:0x0C100000)
/*
*/
1)禁止flash的寫保護: //設置EMIFS_CONFIG寄存器的最低位為1(即讓wp引腳輸出為高)
2)發送寫命令: //塊對齊地址
*((short*)0x0C100000 + 0x555) = 0x00AA;
*((short*)0x0C100000 + 0x2AA) = 0x0055;
*((short*)0x0C100000 + 0x555) = 0x00A0;
3)開始發送要寫到flash的數據 =>(這些數據會在norflash芯片內部的buffer中鎖存起來) =>每次2個字節,因為數據總線寬度為16位
*(volatile U16 *)0x0C100000 = j;
4)通知norflash將存在自己buffer中的數據寫到norflash的介質上:
5)讀狀態寄存器,確保步驟4)已經完成
while(!(*0x0C100000 & 0x80)); //字對齊地址
6)// Check program status.
7)使能flash的寫保護://設置EMIFS_CONFIG寄存器的最低位為0(即讓wp引腳輸出為低)
4.讀norflash的步驟:(假設寫uboot所在分區:0x0C100000)
1)方法一:
*((short*)0x0C100000 + 0x555) = 0x00AA;
*((short*)0x0C100000 + 0x2AA) = 0x0055;
(short)data = *((short *)0x0C100000+);
2)方法二:直接讀
(short)data = *((short *)0x0C100000+);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -