《極海芯得》系列內(nèi)容為用戶使用極海系列產(chǎn)品的經(jīng)驗(yàn)總結(jié),均轉(zhuǎn)載自21ic論壇極海半導(dǎo)體專區(qū),全文未作任何修改,未經(jīng)原文作者授權(quán)禁止轉(zhuǎn)載。
1、APM32F4xx SMC 簡(jiǎn)介
SMC,全稱是 Static Memory Controller ,即靜態(tài)存儲(chǔ)控制器。該外設(shè)用于驅(qū)動(dòng)靜態(tài)存儲(chǔ)設(shè)備,比如 SRAM、PSRAM、NandFlash、NorFlash、PCCard 。APM32F4xx SMC 內(nèi)部有四個(gè)存儲(chǔ)塊,每個(gè)存儲(chǔ)塊都對(duì)應(yīng)控制不同類型的存儲(chǔ)器,通過配置 SMC 控制寄存器選擇不同的存儲(chǔ)器類型;任一時(shí)刻只能訪問一個(gè)外部設(shè)備;每個(gè)存儲(chǔ)塊都可以單獨(dú)配置,SMC 控制時(shí)序可編程以適用不同的外部存儲(chǔ)設(shè)備。
1.1 SMC 結(jié)構(gòu)框圖
SMC 主要由五個(gè)部分組成:AHB 總線接口、配置寄存器、NORFlash 控制器、NANDFlash/PC 卡控制器和外部設(shè)備接口信號(hào),具體情況如下圖:

1.2 SMC 的地址映射
使用 APM32F4xx SMC 外設(shè)外接存儲(chǔ)器擴(kuò)展存儲(chǔ)空間時(shí),外部的存儲(chǔ)器存儲(chǔ)空間會(huì)映射到 MCU 的內(nèi)存存儲(chǔ)空間,而且不同的外部存儲(chǔ)設(shè)備對(duì)應(yīng)不同的地址空間,如下表所示:

可以看到,SMC 把內(nèi)部 1GB 的存儲(chǔ)空間劃分為了 4 個(gè) 256MB 的存儲(chǔ)塊,每個(gè)存儲(chǔ)塊有各自的地址空間以及適用的存儲(chǔ)器類型,存儲(chǔ)塊 1 用于控制 NOR/PSRAM 存儲(chǔ)器,而存儲(chǔ)塊 2、3、4 用于控制 NAND 閃存和 PC 卡。
此外,對(duì)于每個(gè)存儲(chǔ)塊的內(nèi)部,又劃分為 4 塊 64MB 同等大小的區(qū)域,每個(gè)小塊都有對(duì)應(yīng)的控制引腳用于連接外部存儲(chǔ)器的片選信號(hào),從而決定外部存儲(chǔ)器具體連接到的是哪個(gè) 64MB 的存儲(chǔ)區(qū)域。比如對(duì)于存儲(chǔ)塊 1 ,有對(duì)應(yīng)的控制信號(hào)線 SMC_NE[4 : 1] ,用于選擇存儲(chǔ)塊 1 內(nèi)部的 4 個(gè) 64MB 的地址空間,具體地址分配如下:

2. SRAM 簡(jiǎn)介
2.1 SRAM 存儲(chǔ)結(jié)構(gòu)
SRAM(Static Random Access Memory)是一種靜態(tài)隨機(jī)存取存儲(chǔ)器,它是一種主要用于 CPU 內(nèi)部的高速緩存(Cache)或者集成在 MCU 內(nèi)部作為數(shù)據(jù)存儲(chǔ)器。SRAM 的所謂的“靜態(tài)”,指的就是只要保持在通電狀態(tài),存儲(chǔ)在其內(nèi)部的數(shù)據(jù)就可以一直保存,一般是和 DRAM ,即動(dòng)態(tài)存儲(chǔ)器相比較而言的。
SRAM 的存儲(chǔ)單元結(jié)構(gòu)以鎖存器來存儲(chǔ)數(shù)據(jù),存儲(chǔ)單元電路如下:

2.2 APM32F4xx SMC 與 SRAM 的信號(hào)連接
盡管市面上有各種不同廠商、不同型號(hào)的 SRAM 芯片,但是 SRAM 芯片的引腳信號(hào)基本都是一致的,有地址線、數(shù)據(jù)線、控制線三種類型。下面以常見的 SRAM 芯片型號(hào) IS62WV12816 ,給出該 SRAM 芯片與 APM32 SMC 外設(shè)的信號(hào)引腳連接關(guān)系:

對(duì)于數(shù)據(jù)位寬為 8bit 的 SRAM 型號(hào),高位數(shù)據(jù)線 D8-D15 可以不用連接。
3. APM32F4xx SMC 外設(shè)初始化參數(shù)說明
通過 APM32 SMC 驅(qū)動(dòng)外部 SRAM 芯片時(shí),需要配置 SMC 的時(shí)序寄存器以及控制寄存器,但是 APM32F4xx 的固件庫中,對(duì) SMC 相關(guān)的操作已經(jīng)封裝好了,有兩個(gè)結(jié)構(gòu)體是比較重要的,分別是時(shí)序結(jié)構(gòu)體和初始化配置結(jié)構(gòu)體,下面對(duì)這些結(jié)構(gòu)體成員變量作一些解釋及配置說明。
3.1 時(shí)序結(jié)構(gòu)體
時(shí)序結(jié)構(gòu)體的代碼如下:
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] Timing parameters for NOR/SRAM Banks
*/
typedef struct
{
uint8_t addressSetupTime; /*!< Set address setup time */
uint8_t addressHodeTime; /*!< Set address-hold setup time */
uint8_t dataSetupTime; /*!< Set data setup time */
uint8_t busTurnaroundTime; /*!< Set bus turnaround time */
uint8_t clockDivision; /*!< Set clock divide radio */
uint8_t dataLatency; /*!< Set data latency */
SMC_ACCESS_MODE_T accessMode; /*!< Set access mode */
} SMC_NORSRAMTimingConfig_T;
該結(jié)構(gòu)體的成員都是 NorFlash/SRAM 讀寫過程中與時(shí)間相關(guān)的各項(xiàng)參數(shù),對(duì)這些結(jié)構(gòu)體成員說明如下:
(1) addressSetupTime :本成員用于設(shè)置地址建立時(shí)間,可設(shè)置為 0-15 個(gè) HCLK 時(shí)鐘周期數(shù)。APM32F4xx 的 HCLK 時(shí)鐘頻率是168MHz,那么一個(gè) HCLK 時(shí)鐘周期就是 1/168 微秒。
(2) addressHodeTime :本成員用于設(shè)置地址保持時(shí)間,同樣也可以設(shè)置為 0-15 個(gè) HCLK 時(shí)鐘周期數(shù)。
(3) dataSetupTime :本成員用于設(shè)置數(shù)據(jù)建立時(shí)間,可設(shè)置為 0-15 個(gè) HCLK 時(shí)鐘周期數(shù)。
(4) busTurnaroundTime :本成員用于設(shè)置總線轉(zhuǎn)換周期,只適用于總線復(fù)用模式的 NorFlash 存儲(chǔ)器。
(5) clockDivision :本成員用于配置時(shí)鐘分頻系數(shù),可以把 HCLK 時(shí)鐘作為輸入源,配置為 0-16 分頻,用于需要時(shí)鐘同步的存儲(chǔ)器。
(6) dataLatency :本成員設(shè)置數(shù)據(jù)保持時(shí)間,用于配置在讀取第一個(gè)數(shù)據(jù)前等待的存儲(chǔ)器周期數(shù)目,可設(shè)置為 0-15 個(gè)時(shí)鐘周期。該成員僅適用于同步突發(fā)模式的 NorFlash 操作。
(7) accessMode :本成員配置訪問存儲(chǔ)器的模式,可配置為 A/B/C/D 模式,不同的模式下 SMC 輸出的時(shí)序不同。對(duì)應(yīng) SRAM 來說,一般使用模式 A 即可。
對(duì)于時(shí)序結(jié)構(gòu)體所有與時(shí)間相關(guān)的參數(shù),單位都是 HCLK 個(gè)時(shí)鐘周期,APM32F4xx 的 HCLK 時(shí)鐘為 168MHz ,那么 1 個(gè) HCLK 時(shí)鐘周期就是 1/168 us ,即約等于 6ns.
3.2 初始化配置結(jié)構(gòu)體
初始化配置結(jié)構(gòu)體的代碼如下:
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] SMC NOR/SRAM Config structure
*/
typedef struct
{
SMC_BANK1_NORSRAM_T bank; /*!< NORSRAM bank selection */
SMC_DATA_ADDRESS_MUX_T dataAddressMux; /*!< Data address bus multiplexing selection */
SMC_MEMORY_TYPE_T memoryType; /*!< Memory type selection */
SMC_MEMORY_DATA_WIDTH_T memoryDataWidth; /*!< Data width selection */
SMC_BURST_ACCESS_MODE_T burstAcceesMode; /*!< Set burst access mode */
SMC_ASYNCHRONOUS_WAIT_T asynchronousWait; /*!< Set asynchronous wait */
SMC_WAIT_SIGNAL_POLARITY_T waitSignalPolarity; /*!< Set wait signal polarity */
SMC_WRAP_MODE_T wrapMode; /*!< Set wrapped burst mode */
SMC_WAIT_SIGNAL_ACTIVE_T waitSignalActive; /*!< Set wait timing */
SMC_WRITE_OPERATION_T writeOperation; /*!< Set write operation */
SMC_WAITE_SIGNAL_T waiteSignal; /*!< Set wait signal */
SMC_EXTENDEN_MODE_T extendedMode; /*!< Set extended mode */
SMC_WRITE_BURST_T writeBurst; /*!< Set write burst */
SMC_NORSRAMTimingConfig_T* readWriteTimingStruct; /*!< Read and write timing */
SMC_NORSRAMTimingConfig_T* writeTimingStruct; /*!< Write timing */
} SMC_NORSRAMConfig_T;
該結(jié)構(gòu)體主要是在配置 SMC 初始化時(shí)所需要的參數(shù),最底層的代碼其實(shí)就是配置 SMC 的片選控制、片選時(shí)序、寫時(shí)序這 3 個(gè)寄存器,下面簡(jiǎn)單介紹下這些結(jié)構(gòu)體成員:
(1) bank:選擇 SRAM 類型的哪個(gè)存儲(chǔ)區(qū)域,該參數(shù)需要根據(jù)片選引腳的連接不同進(jìn)行選擇,前面也有介紹不同的片選信號(hào)對(duì)應(yīng)的是哪個(gè)存儲(chǔ)區(qū)域。
(2) dataAddressMux :用于設(shè)置地址線與數(shù)據(jù)線是否進(jìn)行復(fù)用。對(duì)于 NorFlash 存儲(chǔ)器類型,地址線與數(shù)據(jù)線是可以分時(shí)復(fù)用的,這樣可以減少 GPIO 引腳的使用,該參數(shù)僅對(duì) NorFlash 有效。
(3) memoryType :配置存儲(chǔ)器類型,可以配置的存儲(chǔ)器類型有:SRAM、PSRAM、NorFlash。
(4) memoryDataWidth :配置控制存儲(chǔ)器的數(shù)據(jù)位寬,可惡意配置為 8 位或者 16 位。
(5) burstAcceesMode :本成員用于配置是否使用突發(fā)訪問模式。突發(fā)訪問模式是指發(fā)送一個(gè)地址后連續(xù)訪問多個(gè)數(shù)據(jù),非突發(fā)模式下每訪問一個(gè)數(shù)據(jù)都需要輸入一個(gè)地址。該成員只對(duì)同步模式下才有效。
(6) asynchronousWait :用于配置是否使能同步等待信號(hào),對(duì)于同步類型的 NorFlash 或者 PSRAM 存儲(chǔ)器,可以使用 SMC_NWAIT 引腳插入等待狀態(tài)。
(7) waitSignalPolarity :該成員用于配置等待信號(hào)極性,可設(shè)置要求等待的信號(hào)是高電平還是低電平。
(8) wrapMode :配置是否使能非對(duì)齊突發(fā)模式,僅在突發(fā)模式下才有效。
(9) waitSignalActive :用于配置等待信號(hào)是在等待之前有效還是等待期間有效,只在突發(fā)模式下有效。
(10) writeOperation :用于配置是否開啟寫使能,如果禁止寫使能,那么 SMC 外設(shè)對(duì)存儲(chǔ)器只能進(jìn)行讀操作,寫操作此時(shí)是禁止的。
(11) waiteSignal :該成員用于設(shè)置是否使能 NWAIT 信號(hào)插入等待狀態(tài),只對(duì)突發(fā)模式下有效。
(12) extendedMode :該成員用于設(shè)置是否使能擴(kuò)展模式,在擴(kuò)展模式下,讀寫時(shí)序可以分別配置不同的時(shí)序寄存器,即讀寫時(shí)序可以不一樣;而在費(fèi)擴(kuò)展模式下,讀寫時(shí)序的配置都是一樣的。
(13) writeBurst :用于配置是否使能寫突發(fā)操作,只在突發(fā)模式下有效。
(14) readWriteTimingStruct :讀寫時(shí)序結(jié)構(gòu)體。在不使用擴(kuò)展模式時(shí),該成員可同時(shí)配置讀寫時(shí)序;在擴(kuò)展模式下,只配置讀時(shí)序。
(15) writeTimingStruct:寫時(shí)序結(jié)構(gòu)體,在擴(kuò)展模式時(shí),可以配置寫時(shí)序;在非擴(kuò)展模式下,配置無效。
3.3 APM32F4xx SMC 控制 SRAM 時(shí)序計(jì)算
APM32F4xx SMC 要控制外部 SRAM 存儲(chǔ)器,必須要正確配置時(shí)序結(jié)構(gòu)體中的兩個(gè)時(shí)序參數(shù):地址建立時(shí)間和數(shù)據(jù)建立時(shí)間,其他的時(shí)序參數(shù)沒有用到,設(shè)置為 0 即可。
下面以 SRAM 芯片型號(hào)IS62WV12816為例,介紹 APM32F4xx SMC 控制 SRAM 芯片的時(shí)序計(jì)算。根據(jù) IS62WV12816 芯片手冊(cè),其關(guān)鍵的時(shí)序參數(shù)如下:

寫時(shí)序參數(shù)要求:

APM32F4xx SMC 控制外部 SRAM 的讀寫時(shí)序有多種不同的模式,下面展示的是模式 A 的讀寫時(shí)序,如下圖所示:

SMC 寫 SRAM 時(shí)序:

根據(jù) IS62WV12816 芯片的時(shí)間參數(shù)要求,以及 SMC 讀寫 SRAM 的時(shí)序圖,可以得到 IS62WV12816 芯片的時(shí)間參數(shù)計(jì)算公式如下:
tWC = ADDSET + DATASET + 1 >= 55ns
tPWE = DATASET >= 40ns
tRC = ADDSET + DATASET >= 55ns
對(duì)時(shí)序結(jié)構(gòu)體進(jìn)行賦值的 ADDSET 和 DATASET 參數(shù),它的單位都是 1 個(gè) HCLK 周期,而 APM32F4xx 的 HCLK 時(shí)鐘頻率是 168MHz ,那么 1 個(gè) HCLK 周期就是 1/168 us = 6ns .
根據(jù)前面的 IS62WV12816 關(guān)鍵的時(shí)間參數(shù)表格可知,地址建立時(shí)間是 0 ,所以時(shí)序結(jié)構(gòu)體的 ADDSET 參數(shù)賦值為 0 即可;然后根據(jù)上面的三條表達(dá)式,為了同時(shí)滿足讀寫時(shí)序的要求,可得出 DATASET 參數(shù)賦值為 10 ,這樣就可以滿足 SRAM 讀寫的時(shí)間要求了。
4. APM32F4xx SMC 讀寫外部SRAM例程
4.1 硬件設(shè)計(jì)
外部 SRAM 芯片使用的是 IS62WV12816 型號(hào),SRAM 芯片和 APM32F4xx 連接的原理圖如下:

可以看到,SRAM 芯片有很多的信號(hào)線需要與 APM32F4xx 的相連,其中 SRAM 芯片的大部分信號(hào)線都是與 MCU 連接固定的引腳的,只有片選引腳可以讓我們選擇連接 SMC_NE1 - NE4,而片選引腳的連接不同,會(huì)映射到 MCU 不同的地址空間。
上面的原理圖片選引腳連接的是 SMC_NE1 ,那么 SRAM 的存儲(chǔ)空間會(huì)被映射到 MCU 內(nèi)部的 0x60000000 ~ 0x63FFFFFF 這一片地址空間上。對(duì)于 IS62WV12816 型號(hào),其內(nèi)存大小是 256KB ,那么當(dāng) MCU 訪問 0x60000000 開始的 256KB 的內(nèi)存空間時(shí),SMC 外設(shè)會(huì)根據(jù)初始化的配置,產(chǎn)生相應(yīng)的訪問時(shí)序,從而實(shí)現(xiàn)外部 SRAM 的讀寫操作。
4.2 軟件設(shè)計(jì)
要通過 APM32F4xx SMC 實(shí)現(xiàn)外部 SRAM 存儲(chǔ)器的訪問,只要配置使用到的 SMC 外設(shè)相關(guān)的 GPIO 引腳以及配置好 SMC 的時(shí)序結(jié)構(gòu)體和初始化結(jié)構(gòu)體即可。代碼實(shí)現(xiàn)流程圖如下:

4.2.1 SMC GPIO引腳配置
對(duì) SMC 外設(shè)所使用到的 GPIO 引腳,全部都配置為復(fù)用功能輸出模式,具體代碼如下:
static void SMC_SRAM_GPIOConfig(void)
{
GPIO_Config_T gpioConfig;
/**
+--------------------+--------------------+
| PD0 <-> SMC_D2 | PE0 <-> SMC_NBL1 |
| PD1 <-> SMC_D3 | PE1 <-> SMC_NBL0 |
| PD4 <-> SMC_NOE | PE7 <-> SMC_D4 |
| PD5 <-> SMC_NWE | PE8 <-> SMC_D5 |
| PD7 <-> SMC_NE1 | PE9 <-> SMC_D6 |
| PD8 <-> SMC_D13 | PE10 <-> SMC_D7 |
| PD9 <-> SMC_D14 | PE11 <-> SMC_D8 |
| PD10 <-> SMC_D15 | PE12 <-> SMC_D9 |
| PD11 <-> SMC_A16 | PE13 <-> SMC_D10 |
| PD12 <-> SMC_A17 | PE14 <-> SMC_D11 |
| PD13 <-> SMC_A18 | PE15 <-> SMC_D12 |
| PD14 <-> SMC_D0 | |
| PD15 <-> SMC_D1 | |
+--------------------+--------------------+
| PF0 <-> SMC_A0 | PG0 <-> SMC_A10 |
| PF1 <-> SMC_A1 | PG1 <-> SMC_A11 |
| PF2 <-> SMC_A2 | PG2 <-> SMC_A12 |
| PF3 <-> SMC_A3 | PG3 <-> SMC_A13 |
| PF4 <-> SMC_A4 | PG4 <-> SMC_A14 |
| PF5 <-> SMC_A5 | PG5 <-> SMC_A15 |
| PF12 <-> SMC_A6 | |
| PF13 <-> SMC_A7 | |
| PF14 <-> SMC_A8 | |
| PF15 <-> SMC_A9 | |
+--------------------+--------------------+
*/
/* Enable GPIO Clock */
RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOD | RCM_AHB1_PERIPH_GPIOE |
RCM_AHB1_PERIPH_GPIOF | RCM_AHB1_PERIPH_GPIOG);
/* SMC SRAM GPIO Config */
gpioConfig.speed = GPIO_SPEED_100MHz;
gpioConfig.mode = GPIO_MODE_AF;
gpioConfig.otype = GPIO_OTYPE_PP;
gpioConfig.pupd = GPIO_PUPD_UP;
gpioConfig.pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_7 |
GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
GPIO_Config(GPIOD, &gpioConfig);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_0, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_1, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_4, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_5, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_7, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_8, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_9, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_10, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_11, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_12, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_13, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_14, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_15, GPIO_AF_FSMC);
gpioConfig.pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |
GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 |
GPIO_PIN_15;
GPIO_Config(GPIOE, &gpioConfig);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_0, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_1, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_7, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_8, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_9, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_10, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_11, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_12, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_13, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_14, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_15, GPIO_AF_FSMC);
gpioConfig.pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 |
GPIO_PIN_5 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
GPIO_Config(GPIOF, &gpioConfig);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_0, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_1, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_2, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_3, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_4, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_5, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_12, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_13, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_14, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_15, GPIO_AF_FSMC);
gpioConfig.pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 |
GPIO_PIN_5;
GPIO_Config(GPIOG, &gpioConfig);
GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_0, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_1, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_2, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_3, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_4, GPIO_AF_FSMC);
GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_5, GPIO_AF_FSMC);
}
4.2.2 SMC 初始化配置
PM32F4xx 固件庫已經(jīng)對(duì) SMC 外設(shè)對(duì)時(shí)序控制以及初始化配置相關(guān)的參數(shù)封裝在時(shí)序結(jié)構(gòu)體和初始化配置結(jié)構(gòu)體了,SMC 外設(shè)的初始化配置,主要就是對(duì)這兩個(gè)結(jié)構(gòu)體成員變量進(jìn)行賦值,最后調(diào)用固件庫函數(shù)提供的初始化配置函數(shù)實(shí)現(xiàn) SMC 外設(shè)的初始化配置,具體代碼如下:
void SMC_SRAM_Init(void)
{
SMC_NORSRAMConfig_T SMC_NORSRAM_ConfigStruct;
SMC_NORSRAMTimingConfig_T readWriteTimingStruct;
/* SMC SRAM GPIO Config */
SMC_SRAM_GPIOConfig();
/* Enable SMC Clock */
RCM_EnableAHB3PeriphClock(RCM_AHB3_PERIPH_EMMC);
/* SMC SRAM Timing Config */
readWriteTimingStruct.addressSetupTime = 0x00;
readWriteTimingStruct.addressHodeTime = 0x00;
readWriteTimingStruct.dataSetupTime = 0x0A;
readWriteTimingStruct.busTurnaroundTime = 0x00;
readWriteTimingStruct.clockDivision = 0x00;
readWriteTimingStruct.dataLatency = 0x00;
readWriteTimingStruct.accessMode = SMC_ACCESS_MODE_A;
/* SMC SRAM Init Config */
SMC_NORSRAM_ConfigStruct.bank = SMC_BANK1_NORSRAM_1;
SMC_NORSRAM_ConfigStruct.dataAddressMux = SMC_DATA_ADDRESS_MUX_DISABLE;
SMC_NORSRAM_ConfigStruct.memoryType = SMC_MEMORY_TYPE_SRAM;
SMC_NORSRAM_ConfigStruct.memoryDataWidth = SMC_MEMORY_DATA_WIDTH_16BIT;
SMC_NORSRAM_ConfigStruct.burstAcceesMode = SMC_BURST_ACCESS_MODE_DISABLE;
SMC_NORSRAM_ConfigStruct.asynchronousWait = SMC_ASYNCHRONOUS_WAIT_DISABLE;
SMC_NORSRAM_ConfigStruct.waitSignalPolarity = SMC_WAIT_SIGNAL_POLARITY_LOW;
SMC_NORSRAM_ConfigStruct.wrapMode = SMC_WRAP_MODE_DISABLE;
SMC_NORSRAM_ConfigStruct.waitSignalActive = SMC_WAIT_SIGNAL_ACTIVE_BEFORE_WAIT_STATE;
SMC_NORSRAM_ConfigStruct.writeOperation = SMC_WRITE_OPERATION_ENABLE;
SMC_NORSRAM_ConfigStruct.waiteSignal = SMC_WAITE_SIGNAL_DISABLE;
SMC_NORSRAM_ConfigStruct.extendedMode = SMC_EXTENDEN_MODE_DISABLE;
SMC_NORSRAM_ConfigStruct.writeBurst = SMC_WRITE_BURST_DISABLE;
SMC_NORSRAM_ConfigStruct.readWriteTimingStruct = &readWriteTimingStruct;
SMC_NORSRAM_ConfigStruct.writeTimingStruct = &readWriteTimingStruct;
SMC_ConfigNORSRAM(&SMC_NORSRAM_ConfigStruct);
}
對(duì)于時(shí)序結(jié)構(gòu)體 SMC_NORSRAMTimingConfig_T 相關(guān)的參數(shù)配置,需要根據(jù) SRAM 的芯片手冊(cè)提供的時(shí)間參數(shù)要求,計(jì)算出對(duì)應(yīng)結(jié)構(gòu)體成員的值,從而對(duì)各成員參數(shù)進(jìn)行合理配置,本例程所使用的 SRAM 芯片型號(hào)是 IS62WV12816 。
4.2.3 SMC 訪問外部 SRAM 存儲(chǔ)器
通過原理圖可以確定,外部 SRAM 芯片的片選引腳連接到的是 SMC_NE1 引腳,那么外部 SRAM 的存儲(chǔ)空間會(huì)映射到 MCU 內(nèi)部的 0x60000000 ~ 0x63FFFFFF 范圍內(nèi)的地址空間。對(duì)于本例程所使用的 IS62WV12816 型號(hào),其存儲(chǔ)空間大小是 256KB ,所以我們?cè)L問外部 SRAM 的起始地址是 0x60000000 ,結(jié)束地址是 0x60040000 。
只要初始化了 SMC 外設(shè)之后,對(duì)外部 SRAM 的讀寫訪問就是對(duì)內(nèi)存的讀寫操作。而對(duì)于 C 語言的話,通過指針就可以實(shí)現(xiàn)對(duì)特定內(nèi)存地址進(jìn)行讀寫操作,例如:
對(duì) SRAM 的 0x6000000 地址,讀取 1 個(gè)字節(jié)數(shù)據(jù):
uint8_t data = *(uint8_t *)0x6000000;
對(duì) SRAM 的 0x6000000 地址,寫入 1 個(gè)字節(jié)數(shù)據(jù):
*(uint8_t *)0x6000000 = (uint8_t)0x55;
如果我們想要定義變量在指定的內(nèi)存地址上,可以使用編譯器提供的擴(kuò)展關(guān)鍵字來修飾變量,比如對(duì)于 ARM-CC 編譯器變量定義如下:
uint8_t data[256 * 1024] __attribute__((at(0x60000000)));
下面是對(duì)外部 SRAM 讀寫操作的函數(shù)封裝:
void SMC_SRAM_WriteBufferWord(uint32_t address, const uint32_t *pdata, uint32_t len)
{
uint32_t i = 0;
for (i = 0; i < len / 4; i++)
{
*(__IO uint32_t *)(SRAM_START_ADDR + address) = pdata[i];
address += 4;
}
}
void SMC_SRAM_ReadBufferWord(uint32_t address, uint32_t *pdata, uint32_t len)
{
uint32_t i = 0;
for (i = 0; i < len / 4; i++)
{
pdata[i] = *(__IO uint32_t *)(SRAM_START_ADDR + address);
address += 4;
}
}
5. 基于外部SRAM存儲(chǔ)器的應(yīng)用案例
后續(xù)計(jì)劃補(bǔ)充基于SRAM存儲(chǔ)器的應(yīng)用案例,待定。
上述關(guān)于APM32F4 SMC SRAM的代碼附件也上傳了,以供大家參考。
注:文章作者在原帖中提供了代碼文件,有需要請(qǐng)至原文21ic論壇
原文地址:https://bbs.21ic.com/icview-3307152-1-1.html?_dsign=f70f669f
-
控制器
+關(guān)注
關(guān)注
114文章
17956瀏覽量
196425 -
存儲(chǔ)
+關(guān)注
關(guān)注
13文章
4964瀏覽量
90496 -
sram
+關(guān)注
關(guān)注
6文章
851瀏覽量
117841
原文標(biāo)題:極海芯得 EP.83 | APM32F4xx SMC SRAM使用介紹
文章出處:【微信號(hào):geehysemi,微信公眾號(hào):Geehy極海半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
【極海APM32F030R8 MINI開發(fā)板試用體驗(yàn)】+官方dma接收usart程序軟件
極海推出APM32A系列車規(guī)級(jí)MCU芯片
極海半導(dǎo)體新品上市—工業(yè)增強(qiáng)型APM32F091xC系列MCU
RT-Thread已經(jīng)全面支持極海APM32F1系列MCU
APM32F407VGT6_SMC_SMC訪問外部SRAM時(shí)讀寫出錯(cuò)
喜報(bào)頻傳!極海APM32工業(yè)級(jí)/車規(guī)級(jí)MCU產(chǎn)品接連榮獲三項(xiàng)大獎(jiǎng)
極海推出首款電機(jī)控制專用芯片APM32F035系列MCU
極海APM32F4xx MCU的SMC SRAM使用介紹
評(píng)論