Nor Flash上電后處於數據讀取狀態(Reading Array Data)。此狀態可以進行正常的讀。這和讀取SDRAM/SRAM/ROM一樣。(要是不一樣的話,芯片上電后如何從NorFlash中讀取啟動代碼。~)
一般再對Flash進行操作前都要讀取芯片信息比如設備ID號。這樣做的主要目的是為了判斷自己寫的程序是否支持該設備。 Nor Flash支持2種方式獲取ID號。一種是編程器所用的方法需要高電壓(11.5V-12.5V)。另一種方法就是所謂的in-system方法,就是在系統中通過NorFlash的命令寄存器來完成。本文中只對in-system方法進行說明。此時需要切換到自動選擇(Autoselect Command),這要通過發送命令來完成。命令類型見下圖。注意:
進入自動選擇(Autoselect Command)模式后需要發送復位命令才能回到數據讀取狀態(Reading Array Data)。
在完成信息獲取后一般就要擦除數據。 NorFlash支持扇區擦(Sector Erase)除和整片擦除(Chip Erase)。這2種模式都有對應的命令序列。在完成擦除命令后會自動返回到數據讀取(Reading Array Data)狀態。在返回前可查詢編程的狀態。
完成擦除后就需要對芯片進行寫入操作也就是編程。這就需要進入編程(Program)狀態。在完成編程命令后會自動返回到數據讀取(Reading Array Data)狀態。在返回前可查詢編程的狀態。注意:編程前一定要先擦除。因為編程只能將’1’改寫為’0’,通過擦寫可以將數據全部擦寫為‘1’。
以上是主要的操作其他操作還有寫保護等,請參考芯片數據手冊。
圖1-1 命令與模式
(2) Nor Flash 硬件連接
圖2-2 TQ2440中實際連接
上圖中要注意的幾個地方:
1. 引腳47 為BYTE# :當其為高電平時數據輸出為16bit模式(此時地址線為A19:A0).低電平為8bit模式. (此時地址線為A19:A1)上圖中Pin47加VCC選用的是16bit模式有效地址線為A19:A0.
2. 對於16bit模式要16bit對齊因此S3C2440A的LADDR1要與A0連接.此時要注意的是NorFlash片內地址0x555對應S3C2440A的地址為baseaddr+0x555*2;其中baseaddr與NorFlash映射的地址有關。一般NorFlash放在Bank0.所以baseaddr=0,但是開啟mmu后baseaddr=地址0映射到的新地址。0x555*2的原因是LADDR1與A0連接。也就是0x555表示片內第0x555個word(16bit).
3. 引腳15為RYBY#輸出引腳。用於輸出Ready與Busy信號。實際用時可以不接。可用命令查詢NorFlash狀態代替.
(3) Nor Flash 模式編程
1. 讀ID
上圖中表明 讀id共有4個指令周期,錢3個為寫周期,最后一個為讀周期;
#define flash_base 0x00000000 //flash接到bank0上
#define CMD_ADDR0 *((volatile U16 *)(0x555*2+flash_base))
#define CMD_ADDR1 *((volatile U16 *)(0x2aa*2+flash_base))
#define CMD_ADDR2 *((volatile U16 *)(0xaaa*2+flash_base))
/*** 讀取 Am29LV800D 的ID ***/
U32 Get_Am29LV800D_ID(void)
{
U32 i="0";
CMD_ADDR0 = 0xaa; CMD_ADDR1 = 0x55; CMD_ADDR0 = 0x90;
i = (*(U16 *)(0*2+flash_base))<<16;//Manufacturer ID = 01
CMD_ADDR0 = 0xaa; CMD_ADDR1 = 0x55; CMD_ADDR0 = 0x90;
i |= *(U16 *)(1*2+flash_base);//device ID = 2249
return i;
}
2. 扇區擦除(Sector Erase)
扇區擦除命令序列的每個周期均為寫周期。
void Am29LV800D_SectorErase(U32 SA)
{
CMD_ADDR0 = 0xAA; CMD_ADDR1 = 0x55; CMD_ADDR0 = 0x80;
CMD_ADDR0 = 0xAA; CMD_ADDR1 = 0x55;//Word 模式命令序列
*((volatile U16 *)(SA)) = 0x30;
Waitfor_endofprg();//狀態查詢
}
3. 編程(Program)
編程 命令序列的每個周期均為寫周期。
int Am29LV800D_WordProg (U32 PA,U16 PD)
{
CMD_ADDR0 = 0xAA; CMD_ADDR1 = 0x55; CMD_ADDR0 = 0xA0;
*((volatile U16 *)(PA)) = PD;// word模式,以上為4個命令周期
return(Waitfor_endofprg());//狀態查詢
}
4. 寫操作狀態(WRITE OPERATION STATUS)
NorFlash 提供幾個數據位來確定一個寫操作的狀態,它們分別是: DQ2, DQ3, DQ5, DQ6,DQ7, and RY/BY#. 如上圖所示。其中DQ7, RY/BY#引腳, 和 DQ6 中的每一個都提供了一種方法來判斷一個編程或者擦除操作是否已經完成或正在進行中。實際編程中只需要使用其中的一種。
DQ7:Data# Polling bit,DQ7在編程時的狀態變化.
在編程過程中從正在編程的地址中讀出的數據的DQ7為要寫入數據的補碼。比如寫入的數據為0x0000,及輸入的DQ7為‘0’,則在編程中讀出的數據為‘1’;當編程完成時讀出的數據又變回輸入的數據即’0’.
在擦除過程中DQ7輸出為’0’;擦除完成后輸出為’1’;注意讀取的地址必須是擦除范圍內的地址。
RY/BY#:高電平表示‘就緒’,低電平表示‘忙’。
DQ6:輪轉位1(Toggle Bit 1)。
在編程和擦除期間,讀任意地址都會導致DQ6的輪轉(0,1間相互變換).。當操作完成后,DQ6停止轉換。
DQ2:輪轉位2(Toggle Bit 2)。當某個扇區被選中擦除時,讀有效地址(地址都在擦除的扇區范圍內)會導致DQ2的輪轉。
注意:DQ2只能判斷一個特定的扇區是否被選中擦除。但不能區分這個快是否正在擦除中或者正處於擦除暫停狀態。相比之下,DQ6可以區分NorFlash是否處於擦除中或者擦除狀態,但不能區分哪個快被選中擦除。因此需要這2個位來確定扇區和模式狀態信息。
DQ5: 超時位(Exceeded Timing Limits),當編程或擦除操作超過了一個特定內部脈沖計數是DQ5=1;這表明操作失敗。當編程時把’0’改為’1’就會導致DQ5=1,因為只有擦除擦做才能把’0’改為’1’。當錯誤發生后需要執行復位命令(見圖1-1)才能返回到讀數據狀態。
DQ3: (扇區擦除計時位)Sector Erase Timer,只在扇區擦除指令時起作用。當擦除指令真正開始工作是DQ3=1,此時輸入的命令(除擦除暫停命令外)都被忽略。DQ3=0,是可以添加附加的扇區用於多扇區擦除。
以上講了這些狀態為,實際只需要使用幾個就行,比較簡單的就是選擇DQ5,DQ6/DQ2.如下例。
/****** Am29LV800D 的檢測 ******/
int Waitfor_endofprg(void)
{
volatile U16 flashStatus,old;
old=*((volatile U16 *)0x0);//先讀一次狀態
while(1)
{
flashStatus=*((volatile U16 *)0x0);//再讀一次狀態
if( (old&0x40) == (flashStatus&0x40) ) break;//比較DQ6.相同說明設備已經就緒
if( flashStatus&0x20 ) //判斷DQ5,為‘1’則超時
{
old=*((volatile U16 *)0x0);
flashStatus=*((volatile U16 *)0x0);//在讀取比較一次。因為可能在超時前剛好玩
//成操作。
if( (old&0x40) == (flashStatus&0x40) )
return 1;
else return 0;
}
old=flashStatus;
}
return 1;
}
NorFlash的擦除&編程問題
最近在試驗norFlash的編程:
每次在擦除sector時,若采用延時的方法,操作都可以成功.但用toggle位檢測的方法每次都失敗.百思不得其解,其間我還參考了《32位嵌入式系統硬件設計與調試》(張侖著)一書,在網上也搜索了不少參考代碼,卻總是不行。。。 ^_^
在此方面有經驗的朋友,請給點意見,若能提供經過實戰檢驗的toggle或polling檢測程序,將不甚感激!!!