本章參考資料:《 STM32F4xx 參考手冊 2》、《 STM32F4xx 規格書》、庫幫助文檔
《 stm32f4xx_dsp_stdperiph_lib_um.chm》。
關於 SDRAM 存儲器,請參考前面的“ 常用存儲器介紹”章節,實驗中 SDRAM 芯片
的具體參數,請參考其規格書《 IS42-45S16400J》 來了解。
SDRAM 控制原理
STM32 控制器芯片內部有一定大小的 SRAM 及 FLASH 作為內存和程序存儲空間,但
當程序較大,內存和程序空間不足時,就需要在 STM32 芯片的外部擴展存儲器了。
STM32F429 系列芯片擴展內存時可以選擇 SRAM 和 SDRAM,由於 SDRAM 的“容量
/價格”比較高,即使用 SDRAM 要比 SRAM 要划算得多。我們以 SDRAM 為例講解如何
為 STM32 擴展內存。
給 STM32 芯片擴展內存與給 PC 擴展內存的原理是一樣的,只是 PC 上一般以內存條
的形式擴展,內存條實質是由多個內存顆粒(即 SDRAM 芯片)組成的通用標准模塊,而
STM32 直接與 SDRAM 芯片連接。見圖 26-2,這是一種型號為 IS42-45S16400J 的 SDRAM
芯片內部結構框圖,以它為模型進行學習。
控制邏輯
SDRAM 內部的“控制邏輯”指揮着整個系統的運行,外部可通過 CS、 WE、 CAS、
RAS 以及地址線來向控制邏輯輸入命令,命令經過“命令器譯碼器”譯碼,並將控制參數
保存到“模式寄存器中”,控制邏輯依此運行。
地址控制
SDRAM 包含有“ A”以及“ BA”兩類地址線, A 類地址線是行(Row)與列(Column)共
用的地址總線, BA 地址線是獨立的用於指定 SDRAM 內部存儲陣列號(Bank)。在命令模式
下, A 類地址線還用於某些命令輸入參數。
SDRAM 內部包含的存儲陣列,可以把它理解成一張表格,數據就填在這張表格上。
和表格查找一樣,指定一個行地址和列地址,就可以精確地找到目標單元格,這是
SDRAM 芯片尋址的基本原理。這樣的每個單元格被稱為存儲單元,而這樣的表則被稱為
存儲陣列(Bank),目前設計的 SDRAM 芯片基本上內部都包含有 4 個這樣的 Bank,尋址時
指定 Bank 號以及行地址,然后再指定列地址即可尋找到目標存儲單元。 SDRAM 內部具有
多個 Bank 時的結構見圖 26-4。
SDRAM 芯片向外部提供有獨立的 BA 類地址線用於 Bank 尋址,而行與列則共用 A 類
地址線。
圖 26-2 標號4中表示的就是它內部的存儲陣列結構, 通訊時當 RAS 線為低電平, 則
“行地址選通器”被選通,地址線 A[11:0]表示的地址會被輸入到“行地址譯碼及鎖存器”
中,作為存儲陣列中選定的行地址,同時地址線 BA[1:0]表示的 Bank 也被鎖存,選中了要
操作的 Bank 號;接着控制 CAS 線為低電平,“列地址選通器”被選通,地址線 A[11:0]表
示的地址會被鎖存到“列地址譯碼器”中作為列地址,完成尋址過程。
數據輸入輸出
若是寫 SDRAM 內容,尋址完成后, DQ[15:0]線表示的數據經過圖 26-2 標號5中的輸
入數據寄存器,然后傳輸到存儲器陣列中,數據被保存;數據輸出過程相反。
本型號的 SDRAM 存儲陣列的“數據寬度”是 16 位(即數據線的數量),在與 SDRAM
進行數據通訊時, 16 位的數據是同步傳輸的,但實際應用中我們可能會以 8 位、 16 位的寬
度存取數據,也就是說 16 位的數據線並不是所有時候都同時使用的,而且在傳輸低寬度數
據的時候,我們不希望其它數據線表示的數據被錄入。如傳輸 8 位數據的時候,我們只需
要 DQ[7:0]表示的數據,而 DQ[15:8]數據線表示的數據必須忽略,否則會修改非目標存儲
空間的內容。所以數據輸入輸出時,還會使用 DQM[1:0]線來配合,每根 DQM 線對應 8 位 數據,如“ DQM0(LDQM)”為低電平, “ DQM1(HDQM)” 為高電平時,數據線 DQ[7:0]
表示的數據有效, 而 DQ[15:8]表示的數據無效。
1. 命令禁止
只要 CS 引腳為高電平,即表示“命令禁止” (COMMAND INHBIT),它用於禁止
SDRAM 執行新的命令,但它不能停止當前正在執行的命令。
2. 空操作
“ 空操作” (NO OPERATION), “命令禁止”的反操作, 用於選中 SDRAM,以便接
下來發送命令。
3. 行有效
進行存儲單元尋址時,需要先選中要訪問的 Bank 和行,使它處於激活狀態。該操作
通過“行有效” (ACTIVE)命令實現,見圖 26-5,發送行有效命令時, RAS 線為低電平,
同時通過 BA 線以及 A 線發送 Bank 地址和行地址。
4. 列讀寫
行地址通過“行有效”命令確定后,就要對列地址進行尋址了。“讀命令” (READ)和
“寫命令” (WRITE)的時序很相似,見圖 26-6,通過共用的地址線 A 發送列地址,同時使
用 WE 引腳表示讀/寫方向, WE 為低電平時表示寫,高電平時表示讀。數據讀寫時,使用
DQM 線表示有效的 DQ 數據線。
本型號的 SDRAM 芯片表示列地址時僅使用 A[7:0]線,而 A10 線用於控制是否“自動預充電”,該線為高電平時使能,低電平時關閉。
預充電
SDRAM 的尋址具有獨占性,所以在進行完讀寫操作后,如果要對同一個 Bank 的另
一行進行尋址,就要將原來有效( ACTIVE)的行關閉,重新發送行/列地址。 Bank 關閉當
前工作行,准備打開新行的操作就是預充電( Precharge)。
預充電可以通過獨立的命令控制,也可以在每次發送讀寫命令的同時使用“ A10”線
控制自動進行預充電。實際上,預充電是一種對工作行中所有存儲陣列進行數據重寫,並
對行地址進行復位,以准備新行的工作。
獨立的預充電命令時序見圖 26-7。該命令配合使用 A10 線控制,若 A10 為高電平時,
所有 Bank 都預充電; A10 為低電平時,使用 BA 線選擇要預充電的 Bank。
6.刷新
SDRAM 要不斷進行刷新(Refresh)才能保留住數據,因此它是 DRAM 最重要的操作。
刷新操作與預充電中重寫的操作本質是一樣的。
但因為預充電是對一個或所有 Bank 中的工作行操作,並且不定期,而刷新則是有固
定的周期,依次對所有行進行操作,以保證那些久久沒被訪問的存儲單元數據正確。
刷新操作分為兩種:“自動刷新”( Auto Refresh)與“自我刷新” (Self Refresh),發
送命令后 CKE 時鍾為有效時(低電平),使用自動刷新操作,否則使用自我刷新操作。不論
是何種刷新方式,都不需要外部提供行地址信息,因為這是一個內部的自動操作。
對於“自動刷新”, SDRAM 內部有一個行地址生成器(也稱刷新計數器)用來自動
地依次生成行地址,每收到一次命令刷新一行。 在刷新過程中,所有 Bank 都停止工作,
而每次刷新所占用的時間為 N 個時鍾周期(視 SDRAM 型號而定,通常為 N=9), 刷新結束
之后才可進入正常的工作狀態,也就是說在這 N 個時鍾期間內,所有工作指令只能等待而
無法執行。一次次地按行刷新,刷新完所有行后,將再次對第一行重新進行刷新操作,這
個對同一行刷新操作的時間間隔,稱為 SDRAM 的刷新周期,通常為 64ms。 顯然刷新會對
SDRAM 的性能造成影響, 但這是它的 DRAM 的特性決定的, 也是 DRAM 相對於 SRAM
取得成本優勢的同時所付出的代價。
“自我刷新”則主要用於休眠模式低功耗狀態下的數據保存,也就是說即使外部控制
器不工作了, SDRAM 都能自己確保數據正常。在發出“自我刷新”命令后,將 CKE 置於
無效狀態(低電平),就進入自我刷新模式,此時不再依靠外部時鍾工作,而是根據 SDRAM
內部的時鍾進行刷新操作。在自我刷新期間除了 CKE 之外的所有外部信號都是無效的,只
有重新使 CKE 有效才能退出自我刷新模式並進入正常操作狀態。
7. 加載模式寄存器
前面提到 SDRAM 的控制邏輯是根據它的模式寄存器來管理整個系統的,而這個寄存
器的參數就是通過“加載模式寄存器”命令(LOAD MODE REGISTER)來配置的。發送該
命令時,使用地址線表示要存入模式寄存器的參數“ OP-Code”,各個地址線表示的參數
見圖 26-8。
SDRAM 的初始化流程
最后我們來了解 SDRAM 的初始化流程。 SDRAM 並不是上電后立即就可以開始讀寫
數據的,它需要按步驟進行初始化,對存儲矩陣進行預充電、刷新並設置模式寄存器,見
圖 26-10。
該流程說明如下:
(1) 給 SDRAM 上電,並提供穩定的時鍾,至少 100us;
(2) 發送“空操作” (NOP)命令;
(3) 發送“預充電” (PRECHARGE)命令,控制所有 Bank 進行預充電,並等待 tRP 時間,
tRP 表示預充電與其它命令之間的延遲;
(4) 發送至少 2 個“自動刷新” (AUTO REFRESH)命令,每個命令后需等待 tRFC 時間, tRFC
表示自動刷新時間;
(5) 發送“加載模式寄存器” (LOAD MODE REGISTER)命令,配置 SDRAM 的工作參數,
並等待 tMRD 時間, tMRD 表示加載模式寄存器命令與行有行或刷新命令之間的延遲;
(6) 初始化流程完畢,可以開始讀寫數據。
其中 tRP、 tRFC、 tMRD 等時間參數跟具體的 SDRAM 有關,可查閱其數據手冊獲知,STM32 FMC 訪問時配置需要這些參數。
SDRAM 的讀寫流程
初始化步驟完成,開始讀寫數據,其時序流程見圖 26-11 及圖 26-12。
(1) 發送“行有效” (ACTIVE)命令,發送命令的同時包含行地址和 Bank 地址,然后
等待 tRCD 時間, tRCD 表示行有效命令與讀/寫命令之間的延遲;
(2) 發送“讀/寫” (READ/WRITE)命令,在發送命令的同時發送列地址,完成尋址的
地址輸入。對於讀命令,根據模式寄存器的 CL 定義,延遲 CL 個時鍾周期后,
SDRAM 的數據線 DQ 才輸出有效數據,而寫命令是沒有 CL 延遲的,主機在發送
寫命令的同時就可以把要寫入的數據用 DQ 輸入到 SDRAM 中,這是讀命令與寫
命令的時序最主要的區別。圖中的讀/寫命令都通過地址線 A10 控制自動預充電,
而 SDRAM 接收到帶預充電要求的讀/寫命令后,並不會立即預充電,而是等待
tWR 時間才開始, tWR 表示寫命令與預充電之間的延遲;
(3) 執行“預充電” (auto precharge)命令后,需要等待 tRP時間, tRP 表示預充電與其它
命令之間的延遲;
(4) 圖中的標號處的 tRAS,表示自刷新周期,即在前一個“行有效”與 “預充電”
命令之間的時間;
(5) 發送第二次“行有效” (ACTIVE)命令准備讀寫下一個數據,在圖中的標號處的
tRC,表示兩個行有效命令或兩個刷新命令之間的延遲。
其中 tRCD、 tWR、 tRP、 tRAS 以及 tRC 等時間參數跟具體的 SDRAM 有關,可查閱其數據
手冊獲知, STM32 FMC 訪問時配置需要這些參數。
FMC 簡介
STM32F429 使用 FMC 外設來管理擴展的存儲器, FMC 是 Flexible Memory Controller
的縮寫,譯為可變存儲控制器。它可以用於驅動包括 SRAM、 SDRAM、 NOR FLASH 以及
NAND FLSAH 類型的存儲器。在其它系列的 STM32 控制器中,只有 FSMC 控制器
(Flexible Static Memory Controller),譯為可變靜態存儲控制器,所以它們不能驅動 SDRAM
這樣的動態存儲器,因為驅動 SDRAM 時需要定時刷新, STM32F429 的 FMC 外設才支持
該功能,且只支持普通的 SDRAM,不支持 DDR 類型的 SDRAM。我們只講述 FMC 的
SDRAM 控制功能。
時鍾控制邏輯
FMC 外設掛載在 AHB3 總線上,時鍾信號來自於 HCLK(默認 180MHz),控制器的時
鍾輸出就是由它分頻得到。如 SDRAM 控制器的 FMC_SDCLK 引腳輸出的時鍾,是用於與
SDRAM 芯片進行同步通訊,它的時鍾頻率可通過 FMC_SDCR1 寄存器的 SDCLK 位配置,
可以配置為 HCLK 的 1/2 或 1/3,也就是說,與 SDRAM 通訊的同步時鍾最高頻率為
90MHz。
FMC 的地址映射
FMC 連接好外部的存儲器並初始化后,就可以直接通過訪問地址來讀寫數據,這種地
址訪問與 I2C EEPROM、 SPI FLASH 的不一樣,后兩種方式都需要控制 I2C 或 SPI 總線給
存儲器發送地址,然后獲取數據;在程序里,這個地址和數據都需要分開使用不同的變量
存儲,並且訪問時還需要使用代碼控制發送讀寫命令。而使用 FMC 外接存儲器時,其存
儲單元是映射到 STM32 的內部尋址空間的;在程序里,定義一個指向這些地址的指針,然
后就可以通過指針直接修改該存儲單元的內容, FMC 外設會自動完成數據訪問過程,讀寫
命令之類的操作不需要程序控制。 FMC 的地址映射見圖 26-14。
中左側的是 Cortex-M4 內核的存儲空間分配,右側是 STM32 FMC 外設的地址映射。
可以看到 FMC 的 NOR/PSRAM/SRAM/NAND FLASH 以及 PC 卡的地址都在 External RAM
地址空間內,而 SDRAM 的地址是分配到 External device 區域的。正是因為存在這樣的地
址映射,使得訪問 FMC 控制的存儲器時,就跟訪問 STM32 的片上外設寄存器一樣(片上外
設的地址映射即圖中左側的“Peripheral”區域)。
External RAM 與 External device 的區別
比較遺憾的是 FMC 給 SDRAM 分配的區域不在 External RAM 區,這個區域可以直接
執行代碼,而 SDRAM 所在的 External device 區卻不支持這個功能。這里說的可直接執行
代碼的特性就是在“常用存儲器”章節介紹的 XIP(eXecute In Place)特性,即存儲器上若存
儲了代碼, CPU 可直接訪問代碼執行,無需緩存到其它設備上再運行;而且 XIP 特性還對
存儲器的種類有要求, SRAM/SDRAM 及 NOR Flash 都支持這種特性, 而 NAND FLASH
及 PC 卡是不支持 XIP 的。結合存儲器的特性和 STM32 FMC 存儲器種類的地址分配,就
發現它的地址規划不合理了, NAND FLASH 和 PC 卡這些不支持 XIP 的存儲器卻占據了
External RAM 的空間,而支持 XIP 的 SDRAM 存儲器的空間卻被分配到了 Extern device 區。
為了解決這個問題,通過配置“SYSCFG_MEMRMP”寄存器的“SWP_FMC”寄存器位可
用於交換 SDRAM 與 NAND/PC 卡的地址映射,使得存儲在 SDRAM 中的代碼能被執行,
只是由於 SDRAM 的最高同步時鍾是 90MHz,代碼的執行速度會受影響。
本章主要講解當 STM32 的片內 SRAM 不夠用時使用 SDRAM 擴展內存,但假如程序
太大,它的程序空間 FLASH 不夠用怎么辦呢?首先是裁剪代碼,目前 STM32F429 系列芯
片內部 FLASH 空間最高可達 2MB,實際應用中只要我們把代碼中的圖片、字模等占據大
空間的內容放到外部存儲器中,純粹的代碼很難達到 2MB。如果還不夠用,非要擴展程序
空間的話,一種方法是使用 FMC 擴展 NOR FLASH,把程序存儲到 NOR 上,程序代碼能
夠直接在 NOR FLASH 上執行。另一種方法是把程序存儲在其它外部存儲器,如 SD 卡,
需要時把存儲在 SD 卡上的代碼加載到 SRAM 或 SDRAM 上,再在 RAM 上執行代碼。
如果 SDRAM 不是用於存儲可執行代碼,只是用來保存數據的話,在 External RAM 或
Exteranl device 區域都沒有區別,不需要與 NAND 的映射地址交換。
要想把SDRAM程序從頭寫到尾,實在不現實,這個底層其實直接用現成的就行了,主要是先了解FMC可以做什么。了解FMC的初始化結構體,一開始就想什么都自己寫,時間精力也不允許。並不是說這個難,而是對照手冊,寫這么多寄存器和時序實在太浪費時間,懂得取舍,時間不等人了。