目錄
內存映射
1. 核心概念:內存映射 (Memory Map)
2. 啟動過程與地址重映射 (Remapping)
關鍵:啟動引腳 (Boot Pins)
這個過程可以類比:
3. 為什么設計成這樣?
4. 一圖流總結
圖解說明:
核心要點:
總結
5. 關于上文的“重映射控制器”
核心區別:ARM Cortex-M 內核 vs. 芯片廠商的實現
“重映射”的具體實現方式
以STM32F1系列為例(來自ST的參考手冊)
總結
內存映射
? ? ? ? 在上一篇博客中,我們解析了arm內核架構中的icode、dcode、s-bus總線和總線矩陣。需要注意的是,不論是icode、dcode、s-bus 在訪問物理內存時都經過了內存映射(或者叫寄存器映射)
內存重映射的機制是由芯片廠商設計的一部分硬件邏輯實現的,而這部分邏輯通常與總線矩陣緊密集成,或者說是總線矩陣功能的一部分。
上篇博客:https://blog.csdn.net/leilei050213/article/details/151442621?spm=1001.2014.3001.5501
1. 核心概念:內存映射 (Memory Map)
ARM Cortex-M內核設計了一個固定的內存映射架構。這意味著CPU內核“認為”4GB的地址空間(從0x0000_0000
到0xFFFF_FFFF
)的特定區域永遠對應特定類型的內存或設備。
這種固定映射的好處是極大的可移植性。任何為Cortex-M編寫的軟件都知道:
-
代碼在
0x0000_0000
和0x0800_0000
。 -
數據RAM在
0x2000_0000
。 -
外設在
0x4000_0000
。 -
內核寄存器在
0xE000_0000
。
無需為不同的芯片重新配置基本內存布局。
2. 啟動過程與地址重映射 (Remapping)
現在我們從一個疑問來探究地址重映射的過程:為什么代碼物理上存儲在0x08000000,但CPU卻從0x00000000開始取指?
答案是通過一個叫做地址重映射的機制。這是由芯片廠商(如ST、NXP)在微控制器內部通過硬件實現的。
關鍵:啟動引腳 (Boot Pins)
很多MCU都有啟動引腳(如BOOT0, BOOT1)。這些引腳在上電復位時的電平,決定了芯片將什么物理內存映射到啟動地址0x0000_0000。
以STM32為例,常見的啟動選項有:
-
從主Flash啟動 (通常模式):
-
將引腳配置為從主Flash啟動。
-
此時,芯片內部的內存控制器會做一個簡單的地址偏移映射:
-
所有對地址
0x0000_0000
的訪問,都會被重定向到0x0800_0000
。 -
訪問
0x0000_0001
-> 變成訪問0x0800_0001
-
訪問
0x0000_FFFF
-> 變成訪問0x0800_FFFF
-
-
iCode總線去
0x0000_0000
取指令,內存控制器悄悄地將這個請求轉給了0x0800_0000
位置的Flash存儲器。CPU內核完全不知道這個重映射過程,它以為指令就在0x0000_0000
。
-
-
從系統存儲器啟動 (ISP模式):
-
芯片內部有一塊特殊的BootROM,里面預燒了廠家的串口/USB下載程序。它的物理地址可能是在
0x1FFF_0000
。 -
當配置為從系統存儲器啟動時,對
0x0000_0000
的訪問會被重定向到這片BootROM。
-
-
從內置SRAM啟動:
-
用于調試。將SRAM(物理地址
0x2000_0000
)映射到0x0000_0000
。
-
這個過程可以類比:
-
你的家(Flash) 實際地址是:幸福路808號(0x0800_0000)。
-
但市政規定,所有寄到 市中心1號(0x0000_0000) 的包裹,都會自動被郵局轉到 幸福路808號。
-
CPU(郵差) 只知道把包裹送到“市中心1號”,它不知道轉交過程,但這個包裹最終總能正確送達你的家。
3. 為什么設計成這樣?
這種設計非常巧妙,主要有兩個優點:
-
統一的入口點:
-
無論芯片內部Flash的物理地址在哪里,無論你有多少種啟動方式,ARM內核CPU硬件永遠、且只需要從同一個地址
0x0000_0000
開始取指令。 -
這簡化了CPU內核的設計,使其不需要關心外部世界的復雜變化。
-
-
極大的靈活性:
-
芯片廠商可以通過啟動引腳和重映射邏輯,提供多種啟動模式,而無需修改CPU核心。
-
開發者可以靈活選擇從程序Flash啟動、從BootLoader啟動、或者從RAM啟動進行調試,硬件幫你搞定地址轉換問題。
-
4. 一圖流總結
圖解說明:
-
起點 (CPU請求):
-
CPU 內核的 iCode 總線嚴格按照 ARM 架構設計,永遠從邏輯地址
0x0000 0000
開始取指。這是它的固定行為。
-
-
路由 (總線矩陣):
-
這個取指請求首先到達總線矩陣,這是芯片內部的“交通樞紐”。
-
-
決策 (啟動配置):
-
總線矩陣會根據啟動引腳(BOOT0, BOOT1) 的電平狀態,決定將這個請求路由到哪里。最常見的情況(用戶Flash啟動)就是路由到重映射控制器。
-
-
轉換 (地址重映射):
-
所謂的“重映射控制器”是這個過程的核心。它接收到一個針對
0x0000 0000
的訪問請求,然后根據廠家預設的規則,悄悄地將這個請求轉換為對物理地址0x0800 0000
的訪問。
-
-
目的地 (物理Flash):
-
轉換后的請求最終抵達實際的物理硬件:主Flash存儲器。指令數據從這里被取出。
-
-
返回數據:
-
數據沿著原路返回:Flash -> 重映射控制器 -> 總線矩陣 -> CPU。
-
CPU 始終認為自己是從
0x0000 0000
讀到了數據,它對背后發生的重映射過程一無所知。
-
核心要點:
-
邏輯地址 vs. 物理地址:
0x0000 0000
是CPU視角的邏輯地址(它認為的世界)。0x0800 0000
是Flash芯片的物理地址(真實的世界)。 -
重映射是橋梁: 芯片內部的“重映射”負責將CPU的“邏輯世界”和存儲器的“物理世界”連接起來。
-
對程序員透明: 整個重映射過程由硬件完成,軟件工程師無需干預。你只需要知道你的程序被燒錄到了
0x0800 0000
,并且CPU會正確地從那里開始執行。
總結
-
CPU從
0x0000_0000
開始執行:這是ARM Cortex-M架構規定的、不可改變的硬件行為。 -
Flash物理地址在
0x0800_0000
:這是芯片廠商根據ARM的內存映射建議分配的物理地址。 -
連接二者的橋梁:是芯片內部的重映射機制。它根據啟動引腳的配置,將CPU對“啟動地址”的訪問透明地重定向到不同的物理存儲器上(Flash、SRAM或BootROM)。
-
iCode總線:它負責執行取指操作,它發出的是“邏輯地址”(
0x0000_0000
),但經過重映射后,這個請求被傳遞到了“物理地址”(0x0800_0000
)上的Flash存儲器。
所以,0x0000 0000 和 0x0800 0000 這兩個地址都是存在的,它們描述的是不同層面的概念:一個是CPU視角的邏輯地址,一個是存儲器的物理地址。重映射技術則將這兩個視角巧妙地統一了起來。
5. 關于上文的“重映射控制器”
在 ARM Cortex-M3 Technical Reference Manual (cortex-m3技術參考手冊) 中,我們不會找到一個名為 “Remapping Controller” (重映射控制器) 的獨立模塊。
“重映射控制器”是一個為了易于理解而使用的一個功能性的統稱,它實際上指向了芯片廠商實現的一系列機制。
核心區別:ARM Cortex-M 內核 vs. 芯片廠商的實現
首先要理解一個關鍵區別:
-
ARM Cortex-M 內核: 它定義了CPU核心本身的行為(如寄存器、指令集、NVIC)和它期望看到的固定內存映射(即CPU發出的地址
0x0000_0000
應該對應什么)。 -
芯片廠商 (如ST, NXP, TI): 他們購買ARM的IP授權,然后圍繞Cortex-M內核設計自己的芯片(MCU)。他們負責實現內存控制器、Flash、SRAM、外設,并決定如何將物理存儲器映射到CPU所期望的地址空間。
我們找不到“重映射控制器”的原因在于:這個“重映射”功能是芯片廠商在它們自己的芯片設計中加入的,不屬于ARM Cortex-M核心的標準部分。因此,它不會出現在內核的技術參考手冊中,而是描述在芯片廠商的數據手冊 (Datasheet) 和參考手冊 (Reference Manual) 里。
“重映射”的具體實現方式
芯片廠商通常通過以下兩種主要方式來實現地址 0x0000_0000
的“重映射”:
-
地址別名 (Address Aliasing) - 最常見的方式
這是最簡單、最低成本的方式。它不是一個復雜的“控制器”,而更像是一個固定的地址連線偏移。
-
工作原理: 在芯片的內部總線結構中,將CPU對地址塊
0x0000_0000
-0x0007_FFFF
(例如) 的訪問請求,其地址線最高位直接忽略或重新編碼,從而定向到物理地址塊0x0800_0000
-0x0807_FFFF
。 -
類比: 這就像是一棟大樓。CPU總是說“我要去101房間”,而大樓的管理系統(芯片設計)硬性規定“所有101房間的請求都自動引導到201房間”。沒有復雜的計算,只是一個簡單的、固定的規則。
-
特點: 這種方式是靜態的、固定的。一旦芯片制造好,
0x0000_0000
就永遠別名到0x0800_0000
。啟動模式的選擇可能是通過改變別名到的目標地址來實現的(見下一條)。
-
內存地址重映射開關 (Memory Remap Switch)
一些更復雜的芯片(或Cortex-A系列)會有一個真正的可編程重映射控制器,通常稱為 “Remap” 或 “Memory Controller” 功能。
-
工作原理: 芯片內部存在一個可配置的開關電路。CPU可以通過配置一個特定的控制寄存器來改變這個開關的狀態。
-
這個寄存器: 允許軟件動態地改變地址
0x0000_0000
映射到哪一塊物理存儲器(Flash, SRAM, BootROM)。 -
在哪里描述: 這個寄存器是芯片廠商自定義的,它的地址、位定義都會寫在芯片的參考手冊中,通常是在系統配置(System Configuration)或內存控制器(Memory Controller)的章節里。例如,在STM32的參考手冊中,你會找到類似“Boot configuration”的寄存器。
以STM32F1系列為例(來自ST的參考手冊)
在STM32中,實現“重映射”的機制是上述兩種方式的結合:
-
固定別名區域: CPU地址
0x0000_0000
-0x1FFF_FFFF
這塊512MB的區域被設計為可重映射的區域。它本身不固定對應任何物理內存。 -
Boot引腳配置開關: 芯片上電復位時,會采樣BOOT0和BOOT1引腳的電平。
-
硬件自動配置: 根據引腳電平,芯片內部的硬件邏輯會自動設置一個隱藏的開關,將這個“可重映射區域”連接到三塊物理存儲器中的一塊:
-
BOOT1=0, BOOT0=0
-> 映射到 Main Flash (物理地址0x0800_0000
) -
BOOT1=0, BOOT0=1
-> 映射到 System Memory (BootROM, 物理地址0x1FFF_0000
等) -
BOOT1=1, BOOT0=1
-> 映射到 Embedded SRAM (物理地址0x2000_0000
)
-
這個過程在復位后由硬件瞬間完成,無需軟件初始化。之后,這個映射關系就固定了,直到下一次復位。
總結
-
關于“內存重映射”該查閱哪里:
-
要理解CPU視角的內存布局,看 《Cortex-M3 Technical Reference Manual》。
-
要理解物理芯片的內存布局和重映射實現細節,看 芯片的數據手冊 (Datasheet) 和 參考手冊 (Reference Manual)。查找 “Boot configuration”、 “Memory organization” 或 “Controller registers” 等章節。
-
-
對程序員的意義:
-
對于絕大多數應用程序開發者來說,這個重映射過程是完全透明的。你只需要知道程序計數器從
0x0000_0000
開始,而你的代碼鏈接在0x0800_0000
,硬件會幫你處理好一切。 -
只有當你在編寫Bootloader或進行非常底層的系統調試時,才需要深入了解BOOT引腳的配置和芯片具體的重映射機制。
-