深入理解STM32之儲存器和總線架構2(基於STM32F411)

本文轉載自http://blog.csdn.net/charmingsun/article/details/52295018

官方文檔: 
STM32F411 參考手冊 
STM32F411 數據手冊 
Cortex™-M4F 編程手冊 
STM32 微控制器系統存儲器自舉模式應用筆記 
STM32™ 自舉程序中使用的 USART 協議 
ARM Cortex™-M Programming Guide to Memory Barrier Instructions

三、Flash接口中的自適應實時存儲器加速器

有關 Cortex-M4 處理器三級指令流水線知識的補充: 
指令流水線以及相關名詞的定義: 
指令流水線是爲提高處理器執行指令的效率,把一條指令的操作分成多個細小的步驟,每個步驟由專門的電路完成的方式。Cortex-M4 處理器採用三級流水線的哈佛結構,一條指令的執行分爲取指階段 (Fetch stage)、譯碼階段 (Decode stage)、執行階段 (Execute stage)三個階段,所以稱爲三級流水線。把每個階段所消耗的時間定義爲一個機器週期(也有人把從內存讀取一條指令字的最短時間定義爲一個機器週期),把執行完一條指令需要花費的時間定義爲一個指令週期。

採用指令流水線的意義: 
如果不採用三級流水線技術,則此時的指令週期爲三個機器週期。如果採用三級流水線技術,那麼當前一條指令執行完取指階段進入譯碼階段之後,執行取指階段的電路就可以對下一條指令進行取指了。以此類推,在理想情況下,當一條指令正處於執行階段時,此時 CPU 中還有一條執行處於譯碼階段、一條指令處於取指階段,這樣 CPU 的指令週期就縮短爲一個機器週期。非理想情況是指處理非順序執行的代碼(有分支)時,指令可能並不存在於當前使用的或預取的指令行中,此時 CPU 將重新取指,即流水線將被清空。直接修改程序計數器 PC 中的數值等特殊情況也會導致流水線被清空,也屬於非理想情況。

每個階段的詳細解釋: 
取指階段之前 Cortex-M4 內核先通過AHB總線向存儲器發送請求指令的地址,待存儲器取出地址中的指令後,再進入取指階段將對應地址中的指令發回給Cortex-M4 內核,其中存儲器從收到地址到取出指令之間的這段時間稱爲等待週期。

取指階段是指將一條指令從存儲器中取到指令寄存器的過程。程序計數器 PC 總是指向當前正在被取指的指令的地址,當一條指令取指完畢後 PC 中的數值將自動增加 4,在使用 32 位指令的情況下指向下一條被取指的指令,在使用 16 位指令的情況下指向下下一條被取指的指令(因爲在使用 16 位指令的情況下一次取兩條指令)。因爲執行階段處於第三階段,所以當一條指令處於執行階段時,PC 寄存器的值已經相比於這條指令處於取指階段時的 PC 值增加了 8。

在譯碼階段,指令譯碼器按照預定的指令格式,對取回的指令進行拆分和解釋,識別區分出不同的指令類別以及各種獲取操作數的方法。

執行階段又分爲三個子階段:訪存取數階段 (Reg Read)、邏輯運算階段 (Shift/ALU)、結果寫回階段 (Reg Write)。訪存取數階段的任務是根據指令需要,可能需要訪問寄存器或者存儲器、讀取操作數。邏輯運算階段的任務是完成指令所規定的各種操作,具體實現指令的功能。結果寫回階段的任務是把邏輯運算階段的運行結果數據“寫回”到寄存器或者存儲器。

Cortex-M4 使用的是 Thumb-2 指令集,其中大部分爲 16 位指令,少部分爲 32 位指令。由於 Cortex-M3 和 Cortex-M4 的指令緩衝區的存在,它的流水線操作不同於傳統的精簡指令集處理器: 
● 一個機器週期內最多取兩條指令,因爲大部分指令都是 16 位的; 
● 一條指令可以在譯碼和執行階段之前的數個機器週期內被取出。 
圖示爲 Cortex-M4 使用 16 位指令時的三級流水線: 
使用 16 位指令時的三級流水線

專有的自適應實時 (ART) 存儲器加速器面向 STM32 工業標準 ARM® Cortex™-M4F 處理器進行了優化。該加速器很好地體現了 ARM Cortex M4F 的固有性能優勢,克服了通常條件下,高速的處理器在運行中需要經常等待 FLASH 讀取的情況。

爲了發揮處理器的全部性能,該加速器將實施指令預取隊列和分支緩存,從而提高了 128 位 Flash 的程序執行速度。根據 CoreMark 基準測試,憑藉 ART 加速器所獲得的性能相當於 Flash 在 CPU 頻率高達 100 MHz 時以 0 個等待週期執行程序。

指令預取

每個 Flash 讀操作可讀取 128 位,可以是 4 行 32 位指令,也可以是 8 行 16 位指令,具體取決於燒寫在 Flash 中的程序。因此對於順序執行的代碼,至少需要 4 個 CPU 週期來執行前一次讀取的 128 位指令行。在 CPU 請求當前指令行時,可使用 I-Code 總線的預取操作讀取 Flash 中的下一個連續存放的 128 位指令行。可將 FLASH_ACR 寄存器中的 PRFTEN 位置 1,來使能預取功能。當訪問 Flash 至少需要一個等待週期時,此功能非常有用。

下圖所示爲需要 3 WS(3 個等待週期)訪問 Flash 時連續 32 位指令的執行過程,圖中分別介紹了使用和不使用預取操作兩種情況。

連續 32 位指令的執行過程(使用預取操作): 
32 位連續指令的執行(有預取) 
連續 32 位指令的執行過程(不使用預取操作): 
32 位連續指令的執行(無預取) 
處理非順序執行的代碼(有分支)時,指令可能並不存在於當前使用的或預取的指令行中。這種情況下,CPU 等待時間至少等於等待週期數。

指令緩存存儲器

爲了減少因指令跳轉而產生的時間損耗,可將 64 行 128 位的指令保存到指令緩存存儲器中。可將 FLASH_ACR 寄存器中的指令緩存使能 (ICEN) 位置 1,來使能這一特性。每當出現指令缺失(即請求的指令未存在於當前使用的指令行、預取指令行或指令緩存存儲器中)時,系統會將新讀取的行復制到指令緩存存儲器中。如果 CPU 請求的指令已存在於指令緩存區中,則無需任何延時即可立即獲取。指令緩存存儲器存滿後,可採用 LRU(最近最少使用)策略確定指令緩存存儲器中待替換的指令行。此特性非常適用於包含循環的代碼。

數據管理 
在 CPU 流水線執行階段,將通過 D-Code 總線訪問 Flash 中的數據緩衝池。因此,直到提供了請求的數據後,CPU 流水線纔會繼續執行。爲了減少因此而產生的時間損耗,通過 AHB 數據總線 D-Code 進行的訪問優先於通過 AHB 指令總線 I-Code 進行的訪問。

如果頻繁使用某些數據,可將 FLASH_ACR 寄存器中的數據緩存使能 (DCEN) 位置 1,來使能數據緩存存儲器。此特性的工作原理與指令緩存存儲器類似,但保留的數據大小限制在 8 行 128 位/行以內。

注意:用戶配置扇區中的數據無法緩存。

四、STM32 程序的存儲器映射

單片機的存儲器分爲兩種,一種是 ROM ( Read-Only Memory,相當於計算機中的硬盤),一種是 RAM (Random-Access Memory,相當於計算機中的內存)。ROM 主要指 NAND Flash、Nor Flash,RAM 主要指 SRAM、SDRAM、DDRAM、PSRAM。還有一種 XOM (Execute-Only Memory) 僅僅被 ARMv7-M 和 ARMv8-M 指令集架構所支持,這裏不作介紹。

一個 C 語言程序被編譯成 ELF 格式的可執行鏡像文件可以分爲四種不同屬性的輸出節:RO 節(只讀)、RW 節(可讀寫)、XO 節(僅可執行)、ZI 節(未初始化)。它們在加載程序和執行程序時在存儲器中的分佈如下圖: 
1、不包含僅可執行 (XO) 節的鏡像的加載視圖和執行視圖 
不包含僅可執行 (XO) 節的鏡像的加載視圖和執行視圖 
2、包含僅可執行 (XO) 節的鏡像的加載視圖和執行視圖: 
包含僅可執行 (XO) 節的鏡像的加載視圖和執行視圖

有關 ARM ELF 鏡像結構的詳細內容,請參考我的另一篇博客:ARM ELF 鏡像結構

五、再談 I 總線、 D 總線、 S 總線的分工

由於 STM32F411 採用的Cortex-M4架構屬於具有三級流水線的哈佛結構,所以指令和數據使用不同的總線傳輸。

存儲器採用固定的存儲器映射,代碼區域起始地址爲 0x0000 0000(通過 ICode/DCode 總線訪問),而數據區域起始地址爲 0x2000 0000(通過系統總線訪問)。Cortex™-M4F CPU 始終通過 ICode 總線獲取復位向量,這意味着只有代碼區域(通常爲 Flash)可以提供自舉空間。如果器件從 SRAM 自舉,在應用程序初始化代碼中,需要使用 NVIC 異常及中斷向量表和偏移寄存器來重新分配 SRAM 中的向量表。

I 總線負責從代碼區(0x0000 0000到0x1FFF FFFF的地址空間,共512MB)讀取指令。Flash 儲存器在此地址空間之內,而 SRAM 屬於0x2000 0000到0x3FFF FFFF這段 512MB 的地址空間之內。所以如果需要運行 SRAM 中的程序,則需要將 SRAM 的地址物理映射到這一地址空間之內才能使用 I 總線從 SRAM 中讀取指令。否則要運行SRAM中的程序只能通過 S 總線讀取SRAM中的指令。不過SRAM一般用於保存數據而不是程序,因爲SRAM不能掉電保存數據,相當於電腦的內存。

D 總線負責從代碼區或者數據區(SRAM區,從0x2000 0000到0x3FFF FFFF這段 512MB 的地址空間)讀取指令中位於指定地址的數據,從代碼區中的Flash讀取常量,從SRAM中讀取變量。該總線在指令的執行階段中的讀寄存器操作時進行寄存器尋址。

S總線根據指令操作數據,寫SRAM中的變量和堆棧,也可以用S總線執行SRAM中的指令、訪問外設寄存器。

發佈了10 篇原創文章 · 獲贊 214 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章