學習目標:
1、了解nor flash存儲芯片的概念和特性
2、掌握使用s3c2440芯片對外掛的nor flash進行讀寫擦除操作
1、NOR Flash的簡單介紹
NOR Flash最早是由Intel公司於1988年開發出的,是現在市場上兩種主要的非易失性存儲器之一,它的出現徹底改變了存儲器市場上由EPROM(Erasable Programmable Read-Only-Memory電可編程序只讀存儲器)和EEPROM(電可擦只讀存儲器Electrically Erasable Programmable Read - Only Memory)一統天下的局面。NOR Flash最大特點是支持XIP(Execute On Chip),既程序可以直接在NOR flash的片內執行,在NOR Flash中的代碼運行時不需要重定位復制到RAM內。NOR Flash的地址線和數據線分開,數據的讀取和RAM很類似,只要能夠提供數據地址,數據總線就能正確給出數據。不過不能直接對它進行寫操作,執行寫操作之前需要先發送固定的命令序列,然后發送寫操作的地址和數據。
NOR Flash存儲器的最小訪問單元一般分為8位和16位的,也有一些NOR Flash器件同時支持8位和16位模式,這種Flash的位寬可以在設計硬件時選擇,當芯片的BYTE#引腳接為高電平,芯片工作在位寬16位模式,BYTE#引腳設為低電平時,芯片工作在位寬8位模式。
NOR Flash一般有多個扇區,扇區是NOR Flash擦除的最小單位,Nor Flash中每個扇區的大小也不是固定的,扇區的排放一般分為兩種模式Top Boot part 和Bottom Boot part 。這兩種形式的區別是小塊的扇區在NOR Flash芯片中放置的位置不同,Bottom Boot類型的NOR Flash小塊地址位於芯片0地址,而Top Boot part類型的NOR Flash小塊地址位於芯片的高地址上。
2、NOR Flash引腳介紹(以MX29LV60DBTI芯片為例)
MX29LV60DBTI是16M-BIT的NOR Flash芯片,它的引腳如下圖所示:
引腳描述表
符號 | 管腳名 | 功能 |
A0~A19 | 地址輸入 | 地址信號,表示要讀寫數據的地址信息 |
Q0~Q15 | 數據輸入/輸出 | 數據輸入/輸出引腳,讀周期內輸出數據,寫周期內輸入數據 |
CE# | 芯片使能 | CE#為低電平時,芯片被選中,后續執行的操作才會有效 |
WE# | 寫使能 | 配合CE#和OE#以及地址引腳和數據引腳一起使用,當CE#低電平,OE#高電平,WE#為低電平時,Q0~Q15上數據被寫入到A0~A19表示地址中 |
BYTE# | 字或字節選擇輸入 | 當其為高電平時,數據輸出為16bit模式;低電平時,數據輸出為8bit模式 |
RESET# | 硬件復位/扇區保護解鎖引腳 | 硬件復位引腳,當輸入信號為低電平時,芯片復位 |
OE# | 輸出使能 | 配合CE#和WE#以及地址引腳和數據引腳一起使用,當CE#低電平,WE#高電平,OE#為低電平時,將地址A0~A19內存中的數據傳送到Q0~A15上 |
RY/BY# | RY/BY#輸出引腳 | 用於輸出Ready和Busy信號,實際用時可以不接,可以用命令查詢NOR Flash狀態代替 |
VCC | 電源供應引腳(2.7v~3.6v) | 芯片供電電源 |
GND | 地引腳 | 芯片電源地 |
WP#/ACC | 硬件寫保護/加速引腳 | 硬件寫保護引腳,低電平有效 |
NC | 不連接內部引腳 | 不用連接 |
3、NOR Flash於S3C2440連接圖
NOR Flash的數據寬度是16位的,與2440處理器的連接時,地址線必須錯位進行連接。s3c2440的地址線A0懸空,A1連接NOR Flash的地址線A0,A2連接NOR Flash的地址線A1,依次排序。需要錯位連接的原因是:2440處理器的每個地址對應的是一個BYTE 的數據單元,而 16-BIT 的 NOR FLASH 的每個地址對應的是一個HALF-WORD(16-BIT)的數據單元。為了保持匹配,所以必須錯位連接。這樣,從2440處理器發送出來的地址信號的最低位A0對16-BIT FLASH來說就被屏蔽掉了。
上面的描述過程太過抽象了,下面通過畫圖來解釋錯位連接的原因:
①、ARM處理器需要從地址0x0讀取一個BYTE
- ARM處理器在地址線An-A0上送出信號0x0;
- 由於2440的A1連接NOR Flash A0,16-BIT FLASH在自己的地址信號An-A0上看到的地址是0x0,然后將地址0x0對應的16-BIT數據單元輸出到D15-D0上;
- ARM處理器知道訪問的是16-BIT的FLASH,從D7-D0上讀取所需要的一個BYTE的數據。
②、ARM處理器需要從地址0x1讀取一個BYTE
- ARM處理器在地址線An-A0上送出信號0x1;
- 由於2440的A1連接NOR Flash A0,16-BIT FLASH在自己的地址信號An-A0上看到的地址依然是0x0, 然后將地址0x0對應的16-BIT數據單元輸出到D15-D0上;
- ARM處理器知道訪問的是16-BIT的FLASH,從D15-D8 上讀取所需要的一個BYTE 的數據。
注意:有些ARM處理器內部可以設置地址的錯位。對於支持軟件選擇地址錯位的處理器,在連接16-BIT FLASH的時候,硬件上不需要把地址線錯位。在設計的時候,應該參考芯片的數據手冊,以手冊為准,以免造成不必要的麻煩(如stm32連接是A0~A0)。
4、S3C2440驅動NOR Flash時序配置
s2c2440內存控制器接讀NOR Flash時序圖
上圖為s3c2440操作NOR Flash的讀時序,Tacs表示片選使能前地址信號的設置時間(既地址信號需要設置多久,才能使能片選信號),Tcos表示OE#信號使能前片選使能的設置時間,Tacc表示數據的訪問周期,Tcoh表示OE#信號釋放后片選信號的保持時間,Tcah表示片選信號釋放后地址信號的保持時間。由於s3c2440為通用性能的處理器,他的外部可能接不同公司生成的不同型號的NOR Flash,所以這些參數值要根據所接型號的NOR Flash的時序圖進行設置。
下面根據NOR Flash芯片MX29LV60DBTI時序圖來配置上述參數,MX29LV60DBTI的時序圖如下圖所示:
NOR Flash芯片MX29LV60DBTI讀操作內部時序圖
NOR Flash芯片MX29LV60DBTI時序圖各參數具體值
Tce:片選信號使能后多久輸出數據有效,最大值為70ns
Toe:讀信號發出后多久輸出數據有效,最大值為30ns
Taa:地址信號發出后數據有效,最大值為70ns
Trc:讀周期時間,最小70ns
Tdf:OE#或CE#高時,數據引腳浮空時間,最大30ns(可以忽略設置,當讀取數據結束后,新的讀取信號發出,要過70ns,數據線上數據有效,這段引腳浮空時間無影響)
上述最大值表示發出該信號后,間隔最大值的時間后,數據引腳的信號一定是有效的,在這個范圍之內,數據信號的引腳可能有效。
為簡單,我們一般設置2440的CE#、OE#、ADD控制信號同時發出,保持70ns后進行讀取數據引腳的數據。NOR Flash連接s3c2440的Bank0地址,配置時序的寄存器為BANKCON0,該寄存器的各個位如下圖所示:
內存控制器的時鍾信號由HCLK時鍾信號提供,假設設置的HCLK的值為100M,1clock = 10ns。根據前面分析,Tacs、Tcos寄存器位設置為0,Tacc寄存器的為設置為101 = 8clocks。
5、NOR Flash的讀操作
NOR Flash是類似於內存類的接口,讀操作和內存的讀取一樣,直接發送相應的地址便能獲取相應數據
unsigned int nor_read_word(unsigned int base, unsigned int offset) { volatile unsigned short *p = (volatile unsigned short *)(base + offset); return *p; } unsigned int nor_dat(unsigned int offset) { return nor_read_word(NOR_FLASH_BASE, offset); }
6、NOR Flash的扇區擦除
擦除NOR Flash扇區時,應先發送相應的命令,發送命令的順序如下:
第1個總線周期:往555地址中寫入AA
第2個總線周期:往2AA地址中寫入55
第3個總線周期:往555地址中寫入80
第4個總線周期:往555地址中寫入AA
第5個總線周期:往2AA地址中寫入55
第6個總線周期:往要擦除的扇區寫入30
void nor_write_word(unsigned int base, unsigned int offset, unsigned int val) { volatile unsigned short *p = (volatile unsigned short *)(base + offset); *p = val; } /* offset是基於cpu的角度看到 */ void nor_cmd(unsigned int offset, unsigned int cmd) { nor_write_word(NOR_FLASH_BASE, offset, cmd); }
/* 等待燒寫完成 : 讀數據, Q6無變化時表示結束 */
void wait_ready(unsigned int addr)
{
unsigned int val;
unsigned int pre;
pre = nor_dat(addr);
val = nor_dat(addr);
while ((val & (1<<6)) != (pre & (1<<6)))
{
pre = val;
val = nor_dat(addr);
}
}
void erase_nor_flash_sector(unsigned int addr) { printf("erasing ...\n\r"); nor_cmd(0x555<<1, 0xaa); /* 解鎖 */ nor_cmd(0x2aa<<1, 0x55); nor_cmd(0x555<<1, 0x80); /* erase sector */ nor_cmd(0x555<<1, 0xaa); /* 解鎖 */ nor_cmd(0x2aa<<1, 0x55); nor_cmd(addr, 0x30); /* 發出扇區地址 */ wait_ready(addr); /* 等待操作完成 */ }
CPU外接NOR Flash,實際上就是將NOR Flash地址映射為CPU的統一編址。由於nor_cmd函數的offset是基於CPU的角度看到地址,而芯片手冊上NOR Flash寫入命令的地址從NOR Flash的實際物理地址,NOR Flash是16位的,它的0地址應該對應CPU的0地址和1地址。因此,NOR Flash的物理地址從CPU的角度來看,地址值應該是NOR Flash角度來看的兩倍,所以在向某地址寫入命令時,要將NOR Flash角度來看的地址右移一位。
7、NOR Flash的寫操作
向NOR Flash地址中寫入數據時,也應先發送相應的命令,發送命令的順序如下:
第1個總線周期:往555地址中寫入AA
第2個總線周期:往2AA地址中寫入55
第3個總線周期:往555地址中寫入A0
第4個總線周期:往要目標地址寫入數據
void write_nor_flash(unsigned int addr,unsigned int val) { /* 燒寫 */ nor_cmd(0x555<<1, 0xaa); /* 解鎖 */ nor_cmd(0x2aa<<1, 0x55); nor_cmd(0x555<<1, 0xa0); /* program */ nor_cmd(addr, val); /* 等待燒寫完成 : 讀數據, Q6無變化時表示結束 */ wait_ready(addr);
}
寫操作時值得注意的是,只有寫入的目標的地址內容為0xff時,數據才能正確的寫入,因此,一般情況下NOR Flash在寫入時要對扇區進行擦除操作。NOR Flash在寫入數據時只能將地址中的某位由1變0,而不能將某位由0變1。
假設NOR Flash某地址中存放字符a(0x61),如果未進行擦除前向該地址中寫入字符G(0x47),最后該地址內容為A(0x41)。原因如下:
字符a化為二進制--->1100001
字符G化為二進制--->1000111
由於寫入時數據位只能由0變為1,最終結果100001,相當於執行原始數據和新寫入數據進行&操作
向NOR Flash執行上述步驟,驗證上述過程
①、向0x80000地址寫入a字符
②、未進行擦除扇區向0x80000地址寫入G字符,接着讀取這個地址里的數據,實際讀取內容為0x41,不是0x47,結果符合上面描述。