MCU 記憶體映射(memory map)
想像一條長街,每間房子都有門牌號,但房子大不相同:有些是圖書館(你只能讀)、有些是便條本(可讀可寫)、有些根本不是房子,而是控制外面機器的操作面板。MCU 記憶體映射正是如此:一段連號的位址範圍(例如 32 位元晶片上從 0x00000000 到 0xFFFFFFFF),其中每個數字區段都接到不同種類的東西。
在典型的 Cortex-M 微控制器上,這張映射有幾個關鍵區段。快閃(程式記憶體)通常起於約 0x08000000(或同時對映在 0x00000000):這是非揮發、以讀為主的儲存,你編譯後的程式與常數資料永久住在這裡——斷電也不會消失。RAM(SRAM)通常起於約 0x20000000:這是給變數、堆疊與堆積用的快速可讀寫記憶體,但它是揮發性的(斷電就忘光一切)。再來是週邊區段,常落在約 0x40000000:這些位址「根本不是記憶體」——讀或寫它們其實是在和硬體對話。寫進某個週邊位址可能點亮一盞 LED;讀某個位址可能回傳感測器當下的溫度。這稱為記憶體映射輸入輸出(memory-mapped I/O)。更高處約 0xE0000000 是系統區段,內含中斷控制器與核心週邊。完整映射可在晶片的參考手冊裡查到。
它之所以重要,是因為沒有作業系統替你抽象這些,你的程式、連結器指令稿與指標都直接使用這些原始位址。關鍵的誠實重點:週邊區段的位址「不是」一般記憶體——往那裡寫會對外在世界產生副作用,往那裡讀也可能改變裝置狀態,所以你必須把那些存取標成 volatile,絕不可讓編譯器把它們最佳化掉。把週邊暫存器當成一般變數對待,是典型的嵌入式臭蟲之一。
典型 Cortex-M 32 位元位址映射: 0x00000000 快閃別名 / 啟動 0x08000000 快閃 (程式 + 常數資料,以讀為主) 0x20000000 SRAM (.data、.bss、堆疊、堆積;揮發 / RAM) 0x40000000 週邊 (GPIO、UART、計時器——記憶體映射 I/O) 0xE0000000 系統 (NVIC、SysTick、除錯) 0xFFFFFFFF 4 GiB 定址空間頂端
快閃放程式碼、RAM 放變數,而週邊區段的位址接到硬體而非儲存。
最大的陷阱:週邊位址不是 RAM。往那裡讀可能有副作用、往那裡寫會改變硬體,所以必須透過 volatile 指標存取——而確切位址要查晶片的參考手冊,不能用猜的。