摘要:玩單片機的難免要和內存和屏幕打交道,那就不得不說一下FSMC,掌握了他基本你就知道單片機是如何與他們進行通訊的了。本文較長因此分了兩篇文章來說明,如有不同意見請在評論區留言。
一、概述
STM32控制器芯片內部有一定大小的SRAM及FLASH作為內存和程序存儲空間,但當程序較大,內存和程序空間不足時,就需要在 STM32芯片的外部擴展存儲器了。
擴展內存時一般使用SRAM和SDRAM存儲器,但STM32F407系列的芯片不支持擴展 SDRAM(STM32F429系列支持),它僅支持使用FSMC外設擴展 SRAM,我們以SRAM為例講解如何為STM32擴展內存。
給STM32芯片擴展內存與給PC擴展內存的原理是一樣的,只是PC上一般以內存條的形式擴展,內存條實質是由多個內存顆粒(即SRAM芯片)組成的通用標準模塊,而STM32直接與SRAM 芯片連接。
二、SRAM的簡介
大家都知道,當電腦運行比較卡的時候,我們可以通過給電腦加裝內存條來改善電腦的性能。那么號稱微型計算機的單片機能不能像電腦一樣加裝內存條呢?裝內存條倒是不行,但是我們可以給單片機外加和內存條效果一樣的SRAM來提升單片機的性能。下面以STM32F407ZGT6單片機來講解一下來擴展外部SRAM。
原理:給STM32芯片擴展內存與給PC擴展內存的原理是一樣的,只是PC上一般以內存條的形式擴展,內存條實質是由多個內存顆粒(即SRAM芯片)組成的通用標準模塊,而STM32直接與SRAM芯片連接。
SRAM,型號IS62WV51216,管腳圖如下:
一種 SRAM 芯片的內部結構框圖
IS62WV51216的管腳總的來說大致分為:電源線、地線、地址線、數據線、片選線、寫使能端、讀使能端和數據掩碼信號線。
數據手冊截圖,原汁原味
什么是數據掩碼信號呢UB#和LB#?
用UB#或LB#線控制數據寬度,例如,當要訪問寬度為16位的數據時,使用行地址線指出地址,然后把UB#和LB#線都設置為低電平,那么 I/O0-I/O15線都有效,它們一起輸出該地址的16位數據(或者接收16位數據到該地址);當要訪問寬度為 8位的數據時,使用行地址線指出地址,然后把UB#或LB#其中一個設置為低電平,I/O會對應輸出該地址的高8位和低8位數據,因此它們被稱為數據掩碼信號。如果不太明白接著往下看。
因為IS62WV51216是有LB和UB引腳的,可以控制字節的有效性,所以編程操作的時候我們是可以進行任意字節位寬的數據操作的。如果換作其他不支持字節通道訪問的芯片的話,那就需要對齊芯片的數據位寬進行數據操作了。在網上查資料時看到有人問“在操作不同的數據位寬時,FSMC_NBL1,FSMC_NBL0是受什么控制輸出高低電平給UB,LB的?”,這個應該是屬于硬件自動實現的,是FSMC的硬件機制。
從這個圖中我們可以看出IS62WV51216有19根地址線和16根數據線,從這些數據中我們可以分析出IS62WV51216的存儲大小為1M,那么這個1M是怎么分析出來的呢?我們得來說說IS62WV51216的存儲原理。首先,我們來談一談一般的RAM的存儲原理。
CPU編址以字節(8bit)為單位。存儲器編址:以其位寬為單位,也就是說每個存儲器地址下的數據位數為位寬。芯片有19根數據線,那么它的芯片的可尋址空間大小就是2^19=254288=512K,又因為它的數據位寬位16(16根數據線),所以這個芯片的容量位512KB*16bit=8192Kbit=1024KByte=1MByte。
2.1 RAM的存儲原理
RAM是“Random Access Memory”的縮寫,被譯為隨機存儲器。所謂隨機存取,指的是當存儲器中的消息被讀取或寫入時,所需要的時間與這段信息所在的位置無關。根據 RAM的存儲機制,又分為動態隨機存儲器 DRAM(Dynamic RAM)以及靜態隨機存儲器 SRAM(Static RAM)兩種。不管是DRAM還是SRAM他們都是在RAM前面加了一個頭而已。
2.2 靜態隨機存儲器SRAM
靜態隨機存儲器SRAM(Static RAM)顧名思義電路結構不需要定時刷新充電,就能保持狀態(當然,如果斷電了,數據還是會丟失的),因為不需要定時刷心充電,所以SRAM的存儲單元以鎖存器來存儲數據,這種存儲器被稱為“靜態(Static)”RAM。
2.3 動態隨機存儲器DRAM
而動態隨機存儲器DRAM(Dynamic RAM)顧名思義電路結構是需要定時刷新充電,因為需要定時刷心充電所以DRAM的存儲單元以電容的電荷來表示數據,這種存儲器被稱為“動態(Dynamic)”RAM。
SRAM的存儲單元 | ? |
DRAM的存儲單元 |
從他們的存儲單元的結構圖我們就知道DRAM的結構比SRAM的結構簡單的多,所以所以生產相同容量的存儲器,DRAM 的成本要更低,且集成度更高。而DRAM中的電容結構則決定了它的存取速度不如SRAM。這種結論是不需要死記硬背的,看結構圖就知道了。
但是我們可能還聽說過SDRAM,我們把它叫做同步動態隨機存儲器SDRAM(Synchronous DRAM),同步顧名思義就是利用時鐘進行同步的通訊時序,它在時鐘的上升沿表示有效數據。
2.4 SRAM的存儲模型
SRAM 存儲陣列模型
SRAM的存儲模型我們可以用矩陣來說明:
SRAM內部包含的存儲陣列,可以把它理解成一張表格,數據就填在這張表格上。和表格查找一樣,指定一個行地址和列地址,就可以精確地找到目標單元格,這是SRAM芯片尋址的基本原理。這樣的每個單元格被稱為存儲單元,而這樣的表則被稱為存儲矩陣。地址譯碼器把N根地址線轉換成2的N次方根信號線,每根信號線對應一行或一列存儲單元,通過地址線找到具體的存儲單元,實現尋址。如果存儲陣列比較大,地址線會分成行和列地址,或者行、列分時復用同一地址總線,訪問數據尋址時先用地址線傳輸行地址再傳輸列地址。
但是呢?你會發現,這個原理好像不太適用于IS62WV51216,為什么呢?
其實不然,因為我們使用的SRAM比較小(IS62WV51216容量是1MB),IS62WV51216沒有列地址線。它只有19根行地址線,那么,我們就可以這么來解釋:IS62WV51216有16根數據線,也就是說它的數據寬度為16位,一個行地址也就對應16位,即一個行地址對應 2字節空間。
好,那現在來計算一下IS62WV51216有多少個行地址。2的19次方等于512K,在512K的基礎之上在乘我們之前計算的2字節,不正好是1024K,也就是1M嗎?1M后面的單位是B,即Byte,而不是Bit哦。這樣的話你就會發現IS62WV51216這個名字中本身就包含了大量的信息:IS62WV51216共有512K個行地址,數據寬度為16位,再加以計算就可以得到它的存儲大小為1M啦,有趣吧!另外,該芯片支持兩種不同的高速訪問時間,分別為45ns和55ns,該時間表示進行一次數據讀寫的最短時間要求,本文選擇55ns的模式。
2.5 通信方式
異步通訊,無須時鐘,無須刷新,與STM32F407單片機通過FSMC接口相連。
SRAM的讀寫流程
數據手冊上的SRAM 的讀時序 | ? |
翻譯過來的SRAM 的讀時序 |
數據手冊上的SRAM 的寫時序 | ? |
翻譯過來的SRAM 的寫時序 |
讀寫時序的流程很類似,下面我們統一解說:
(1) 主機使用地址信號線發出要訪問的存儲器目標地址;
(2) 控制片選信號 CS1#及 CS2#使能存儲器芯片;
(3) 若是要進行讀操作,則控制讀使能信號OE#表示要讀數據,若進行寫操作則控制寫使能信號 WE#表示要寫數據;
(4) 使用掩碼信號LB#與UB#指示要訪問目標地址的高、低字節部分;
(5) 若是讀取過程,存儲器會通過數據線向主機輸出目標數據,若是寫入過程,主要使用數據線向存儲器傳輸目標數據。
在讀寫時序中,有幾個比較重要的時間參數,在使用 STM32 控制的時候需要參考。
IS62WV51216BLL-55ns型號SRAM的時間參數
三、FSMC簡介
FSMC的本質就是內核想要訪問存儲器,但是內核不能生成硬件時序,FSMC外設就幫忙做了這個硬件時序這個事情。有了這個外設我們操作外部SRAM就不需要自己在那里寫讀寫時序了,FSMC就幫我們解決了。怎么解決的?它有各種寄存器結構體啊,直接按照要求配置就可以了。
STM32F407或STM32F417系列芯片都帶有FSMC接口,FSMC,即靈活的靜態存儲控制器,能夠與同步或異步存儲器和16位PC存儲器卡連接,STM32F4的FSMC 接口支持包括SRAM、NAND FLASH、NOR FLASH和 PSRAM 等存儲器。
**注意:FSMC不能驅動如SDRAM 這種動態的存儲器,而在STM32F429系列的控制器中,它具有FMC外設,支持控制 SDRAM 存儲器**。其他我們不用管,從上面我們可以總結的是,STM32雇傭FSMC這個管家來管理我們的IS62WV51216。來來來,我們來看看FSMC的廬山真面目:
FSMC 的框圖如圖所示:
FSMC時鐘來源
FSMC—STM32F4XX參考手冊
FSMC—STM32F4XX參考手冊
蒙了吧!又是這么多信號線,不要怕,我們還是來總結歸納下。我們FSMC控制SRAM為例來說明:通過查看STM32F407xx參考手冊。
外部存儲器接口信號—STM32F4xx參考手冊
上圖打碼的地方是PSRAM偽靜態隨機存儲器的引腳,不需要理會,只需要看SRAM的部分即可。
你會發現居然和SRAM中的線居然高度統一(那是當然喏,我們就是講的FSMC嘛!)
1、FSMC_NBL[1]、FSMC_NBL[0]分別對應于LBn、UBn,有什么用呢?提供數據掩碼信號。貝體是怎么回事昵?還記得前面提到的行地址線嗎?
一根行地址線對應16位的數據,我們可以把16位的數據分為高字節和低字節。當要訪問寬度為16位的數據時,使用行地址線指出地址,然后把UBn(n表示低電平有效)和LBn線都設置為低電平(FSMC_NBL0和 FSMC_NBL為低電平),那么I/O0-I/O15線(FSMC_D0到 FSMC_D15)都有效,它們一起輸出該地址的16位數據(或者接收16位數據到該地址);當要訪問寬度為8位的數據時,使用行地址線指出地址,然后把UBn(FSMC_NBL0)設置為低電平,I/O0-I/O15(FSMC_D8到 FSMC_D15)會對應輸出該地址的高8位,l/O0-I/O7的信號無效(或者把LBn(FSMC_NBL1)設置為低電平,I/O0-/O7(FSMC_D0到SMCD7)會對應輸出該地址的低8位,I/O8-/I/O15的信號無效。這樣是不是有部分信號沒有用呢?好像被掩蓋了。因此它們被稱為數據掩碼信號。
要注意的是FSMC_NBL[1]、FSMC_NBL[0]分別對應于LBn、UBn,這兩個引腳的電平不是我們用程序控制的,如果用程序控制就太麻煩了,這兩個引腳應該是FSMC的內部硬件機制完成的,不需要我們人為操作。
2、FSMC_NE[1:4]是個很有趣的東西,它決定了FSMC可以控制多個存儲器。這里就要提及FSMC的地址映射啦!
FSMC存儲區域—STM32F4XX參考手冊
首先,有一點我們必須明白,對于32位的STM32單片機來說,它能夠管理的地址大小為4GB,而STM32將4GB的地址空間中的0X60000到0X9FFFF共1GB的空間分給外部內存,所以這1GB的空間就成了我們的小天地,供我們自由玩耍。
STM32F407數據手冊英文版—MemoryMap
野火407手冊
STM32F417數據手冊—中文版
然后強勢的FSMC就接管了這1GB的空間,FSMC將圖中的1GB大小的外部RAM存儲區域分成了4個Bank區域,每個Bank對應于STM32內部尋址空間的不同地址范圍。
那么為什么要分為不同的Bank區域呢?
因為不同的Bank可以來管理不同的外部存儲設備,比如NOR_Flash及SRAM存儲器只能使用Bank1的地址,NAND_Flash存儲器只能使用Bank2和Bank3的地址等。
細心的你肯定還會發現,每個Bank中居然還有4x64MB這種文宇,這是什么意思呢?
FSMC存儲區域—STM32F4XX參考手冊
Bank內部的256MB空間又被分成4個小塊,每塊64M,各自有相應的控制引腳用于連接片選信號。FSMC_NE[4:1]信號線就分別對應圖中的 FSMC bank1 NOR/PSRAM4到FSMC bank1 NOR/PSRAM1。當STM32訪問0×6800000—0x6BFFF址空間時,會訪問到Bank1的第3小塊區域:FSMC bank1 NOR/PSRAM3,相應的FSMC_NE3信號線會輸出控制信號(即片選信號),如果這個時候FSMC_NE3處剛好接上IS62WV51216的CS端,那么IS62WV51216就可以任由我們擺布啦。因此,對于你使IS62WV51216來說,一定要注意你的CS端是接的FSMC的哪個FSMC_NE端,這決定你在程序訪問哪個地址范圍。
STM32F4 的 FSMC 存儲塊 1(Bank1)被分為 4 個區,每個區管理64M 字節空間,每個區都有獨立的寄存器對所連接的存儲器進行配置。Bank1 的 256M 字節空間由28根地址線(HADDR[27:0])尋址。
為什么是28根地址線?因為2^28=268435456B=262144KB=256MB,正好管理這Bank1的256M 字節空間。
當Bank1接的是16位寬度存儲器的時候:HADDR[25:1]→FSMC_A[24:0]。當Bank1接的是8位寬度存儲器的時候:HADDR[25:0]→ FSMC_A[25:0]。不論外部接8位/16位寬設備,FSMC_A0永遠接在外部設備地址A[0]。
這里感覺很不好理解,簡單地分析如下:
對于16位SRAM,FSMC地址線要向右移一位(非常重要)。
以0x6800 0000這個地址為例,它分解成二進制是0110 1000 0000 0000 0000 0000 0000 0000,由于一個BANK是64M的地址空間,而2^25=64M,故0x6800 0000的位[25:0]是FSMC向外部SRAM傳遞的真實地址,對于0x6800 0000,FSMC向外部SRAM發的地址是位[25:0],即00 0000 0000 0000 0000 0000 0000,這很好理解。
同理,對于0x6800 0002,FSMC向外部SRAM發送的地址是00 00000000 0000 0000 0000 0010。若FSMC不自動右移一位,這個地址明顯發錯了,因為期望讀取的SRAM地址為0x0000 0001中的數據。
為了解決這一問題,當在初始化FSMC時,若選擇外部SRAM為16位,則FSMC在向外部SRAM發地址時,會自動右移一位,例如剛才的0x6800 0002,FSMC在向外部發SRAM地址時,00 0000 0000 0000 0000 0000 0010會自動右移一位,變成00 0000 00000000 0000 0000 0001,即0x0000 0001,該地址正好是期望的外部SRAM地址。接著,外部SRAM從地址為0x0000 0001中取出16位數據傳送給FSMC,由FSMC將這個16位數據保存在以映射地址0x6800 0002起始的兩個8位存儲單元中。
地址映射如下:
這樣的話,當16位數據寬度時,地址的問題解決了,還有一個問題,是往高字節寫入還是低字節寫入呢?
這也就是NBL0和NBL1的作用了,如果你要進行字節操作 :如stm32發送地址0x0001讀取一個字節。右移一位對應的是sram地址0x0000處的16位數據, FSMC會根據A0(最后一根地址線)來控制NBL0和NBL1。當A0 = 1時,讀取高字節數據(僅NBL1有效);A0 = 0時,讀取低字節數據僅NBL0有效),當進行16位讀寫時,NBL0和NBL1都有效。
經過了上面的分析,再來重新觀察數據的寫入過程:
當地址為0x6800 ?0000,會訪問到SRAM的第0個16位地址,而此時A0 = 0(低字節有效),實際會訪問的是16位 0地址的低字節;當地址為0x6800 ?0001時,A0 = 1,訪問16位 0地址的高字節。依次。
因此,想讓地址線的最后一位產生0或1,應該在前一位做出改變(stm32會自動右移):
我們的SRAM芯片使用的是Bank1 的第三個區,即使用FSMC_NE3來連接外部設備的時候,即對應了HADDR[27:26]=10(這是內部硬件配置,不需要我們管),我們要做的就是配置對應第3區的寄存器組,來適應外部設備即可。
STM32F4的FSMC各Bank配置寄存器如下表
STM32的FSMC存儲塊1支持的異步突發訪問模式包括:模式1、模式A~D等多種時序模型,驅動SRAM時一般使用模式1或者模式A,這里我們使用模式A來驅動SRAM用,其他模式說明詳見:STM32中文參考手冊-FSMC章節。
FSMC外設支持輸出多種不同的時序以便于控制不同的存儲器,它具有 ABCD 四種模式,下面我們僅針對控制 SRAM 使用的模式 A進行講解。
模式A讀時序
模式A寫時序
對于NOR FLASH/PSRAM(包括SRAM)控制器(存儲塊1),通過FSMC_BCRX、FSMC_BTRX和FSMCBWTRx寄存器設置(其中x=1~4,對應4個區)。由于我們硬件是把blank的第三個區給外部SRAM使用,所以對于SRAM芯片的片選引腳為FSMC_NE3。所以就要配置FSMC_BCR3、FSMC_BTR3和FSMCBWTR3這3個寄存器。正點原子F407板子的SRAM的片選引腳是FSMC_NE3,LCD顯存芯片的片選引腳是FSMC_NE4。
原子的F407的SRAM是blank NE3 LCD是blank NE3
野火的F407的SRAM blank NE4 | ? |
野火F407的LCD blank NE3 |
四、SRAM的FSMC寄存器配置
4.1 SRAM/NOR-Flash片選控制寄存器
EXTMOD:擴展模式使能位,控制是否允許讀寫不同的時序,需設置為1。
WREN:寫使能位。我們需要向SRAM寫數據,故該位必須設置為1。
MWID[1:0]:存儲器數據總線寬度。00,表示8位數據模式;01表示16位數據模式;10和11保留。我們的SRAM是16位數據線,所以設置WMID[1:0]=01。
MTYP[1:0]:存儲器類型。00表示SRAM、ROM;01表示PSRAM;10表示NOR FLASH;11保留。我們使用SRAM,所以需要設置MTYP[1:0]=00。
MBKEN:存儲塊使能位。需設置為1。
STM32F4XX中文參考手冊
4.2 SRAM/NOR-Flash片選時序寄存器
ACCMOD[1:0]:訪問模式。00:模式A;01:模式B;10:模式C;11:模式D。
DATAST[7:0]:數據保持時間,等于:DATAST個HCLK時鐘周期,DATAST最大為255。對STM32F1,一個HCLK=13.8ns(1/72M),設置為15;對STM32F4,一個HCLK=6ns(1/168M),設置為60。
ADDSET[3:0]:地址建立時間。表示:ADDSET個HCLK周期,ADDSET最大為15。STM32F1的FSMC性能存在問題,即便設置為0,RD也有190ns的高電平,我們這里設置為1。而對STM32F4,則設置為15。
4.3 SRAM/NOR-Flash寫入時序寄存器
ACCMOD[1:0]:訪問模式。00:模式A;01:模式B;10:模式C;11:模式D。
DATASTI7:01:數據保持時間,等于:DATAST個HCLK時鐘周期,DATAST最大為255。對ILI9341來說,其實就是WR低電平持續時間,為15ns,不過ILI9320等則需要50ns。考慮兼容性,對STM32F1,一個HCLK=13.8ns(1/72M),設置為3;對STM32F4,一個HCLK=6ns(1/168M),設置為9。
ADDSET[3:0]:地址建立時間。表示:ADDSET個HCLK周期,ADDSET最大為15。對lL19341來說,這里相當于WR高電平持續時間,為15ns。同樣考慮兼容IL19320,對STM32F1,這里即便設置為1,WR也有100ns的高電平,我們這里設置為1。而對STM32F4,則設置為8。
在MDK的寄存器定義里面,并沒有定義FSMC_BCRx、FSMC_BTRx、FSMC_BWTRx等這個單獨的寄存器,而是將他們進行了一些組合。
FSMC_BCRx和FSMC_BTRx,組合成BTCR[8]寄存器組,他們的對應關系如下:
BTCR[0] 對應 FSMC_BCR1,BTCR[1] 對應 FSMC_BTR1BTCR[2] 對應 FSMC_BCR2,BTCR[3] 對應 FSMC_BTR2BTCR[4] 對應 FSMC_BCR3,BTCR[5] 對應 FSMC_BTR3BTCR[6] 對應 FSMC_BCR4,BTCR[7] 對應 FSMC_BTR4
FSMC_BWTRx則組合成BWTR[7],他們的對應關系如下:
BWTR[0]對應 FSMC_BWTR1,BWTR[2]對應 FSMC_BWTR2,BWTR[4]對應 FSMC_BWTR3,BWTR[6]對應 FSMC_BWTR4,BWTR[1]、BWTR[3]和 BWTR[5]保留,沒有用到。
本篇到此結束,下一篇將講解FSMC的先關代碼,并使用STM32CubeMX進行配置。
審核編輯:劉清
評論