在 Keil 中將 STM32 工程下載到 RAM 進行調試運行
在使用 STM32 進行調試時,默認情況下代碼會被燒寫到 Flash 中運行。然而,Flash 寫入速度較慢,擦寫次數有限,且調試過程中頻繁燒寫可能影響開發效率。在某些場景下(如快速驗證代碼或避免 Flash 擦寫),我們可以將代碼直接下載到 STM32 的內部 RAM 中運行并進行調試。
本文以 STM32H750 為例,詳細介紹如何在 Keil 中配置工程,使代碼下載到 RAM 并進行調試。其他 STM32 系列芯片的配置方法類似,只需根據芯片的 RAM 地址和大小進行調整。
1. 關閉默認的 Memory Layout 配置
在 Keil 中,打開工程配置窗口:
- 點擊菜單欄 Project -> Options for Target。
- 切換到 Linker 選項卡。
- 取消勾選 Use Memory Layout from Target Dialog。
說明:
取消該選項后,Keil 將不再使用 Target 選項卡中配置的 ROM 和 RAM 地址,而是完全依賴用戶自定義的 Scatter File (.sct) 來定義代碼和數據的內存布局。這一步是實現 RAM 調試的關鍵。
2. 配置 Scatter File (.sct)
由于取消了默認內存布局,需要創建一個分散加載文件(.sct 文件)來指定代碼和數據的存儲位置。
在 Options for Target -> Linker 中,啟用 Use Scatter File 選項,并創建一個 .sct
文件,用于定義代碼和數據的內存分配。
以下是以 STM32H750 為例的 .sct
文件內容:
; *************************************************************
; *** Scatter-Loading Description File for STM32H750 RAM Debug ***
; *************************************************************LR_IROM1 0x24000000 0x00080000 { ; Load region: AXI SRAM (512KB)ER_IROM1 0x24000000 0x00080000 { ; Execution region: Code and constants*.o (RESET, +First) ; Reset vector and Reset_Handler*(InRoot$$Sections) ; Linker-specific root sections.ANY (+RO) ; Read-only sections (code and constants).ANY (+XO) ; Execute-only sections (if any)}RW_IRAM1 0x20000000 0x00020000 { ; Execution region: DTCM RAM (128KB).ANY (+RW +ZI) ; Read-write and zero-initialized data}
}
說明:
- LR_IROM1:定義加載區域,起始地址為
0x24000000
(STM32H750 的 AXI SRAM 起始地址),大小為512KB
。 - ER_IROM1:定義代碼和常量數據的執行區域,放置在 AXI SRAM 中。
*.o (RESET, +First)
:將復位向量表和Reset_Handler
放在執行區域的開頭。*(InRoot$$Sections)
:包含鏈接器需要的根區段(如初始化代碼)。.ANY (+RO)
:將所有只讀數據(代碼和常量)分配到該區域。.ANY (+XO)
:將僅執行代碼(若有)分配到該區域。
- RW_IRAM1:定義讀寫數據和零初始化數據的執行區域,起始地址為
0x20000000
(DTCM RAM 起始地址),大小為128KB
。.ANY (+RW +ZI)
:將讀寫數據和零初始化數據分配到 DTCM RAM。
注意:
- 不同 STM32 芯片的 RAM 地址和大小不同,請參考芯片的參考手冊或數據手冊(如 STM32H750 的 AXI SRAM 和 DTCM RAM 地址)。
- 確保程序的代碼和數據總大小不超過目標 RAM 的容量。
3. 禁用 Flash 編程算法
由于我們希望代碼運行在 RAM 中,而不是 Flash 中,因此需要禁用 Keil 的 Flash 編程功能:
- 打開 Options for Target -> Utilities。
- 取消勾選 Use Target Driver for Flash Programming。
- 選擇 Use External Tool for Flash Programming。
說明:
禁用 Flash 編程算法后,Keil 不會嘗試將代碼寫入 Flash,而是直接將程序加載到指定的 RAM 地址。
4. 配置調試初始化文件 (.ini)
為了確保程序從 RAM 正確啟動,需要配置一個調試初始化文件(.ini
),用于設置棧指針(SP)、程序計數器(PC)以及向量表偏移寄存器(VTOR)。在 Options for Target -> Debug 中,啟用 Initialization File 選項,并創建一個 .ini
文件,
內容如下:
/***********************************************************/
/* Debug_RAM.ini: Initialization File for Debugging from RAM */
/***********************************************************/FUNC void Setup (void) {SP = _RDWORD(0x24000000); // Set Stack Pointer (SP) from RAM vector tablePC = _RDWORD(0x24000004); // Set Program Counter (PC) from RAM reset vector_WDWORD(0xE000ED08, 0x24000000); // Set Vector Table Offset Register (VTOR) to RAM
}FUNC void OnResetExec (void) { // Executes upon software resetSetup(); // Reinitialize runtime environment
}LOAD %L INCREMENTAL // Load the .axf file to RAM
Setup(); // Call Setup function to initialize runtime
g, main // Jump to main function
說明:
- _RDWORD(addr):從指定地址讀取一個 4 字節的字。
- _WDWORD(addr, val):向指定地址寫入一個 4 字節的字。
- SP = _RDWORD(0x24000000):從 RAM 的起始地址(AXI SRAM)讀取棧指針初值。
- PC = _RDWORD(0x24000004):從 RAM 的復位向量地址讀取程序計數器初值。
- _WDWORD(0xE000ED08, 0x24000000):將向量表偏移寄存器(VTOR)設置為 RAM 起始地址,確保中斷向量表正確指向 RAM。
- LOAD %L INCREMENTAL:將編譯生成的
.axf
文件加載到 RAM。 - g, main:跳轉到
main
函數開始執行。
注意:
- 確保
.ini
文件中的地址與.sct
文件中的 RAM 地址一致。 - 如果芯片的 RAM 地址不同,需要相應修改
.ini
文件中的地址。
5. 配置調試和下載選項
為了確保程序只加載到 RAM 而不影響 Flash,需要調整調試和下載設置:
- 打開 Options for Target -> Debug -> Settings -> Flash Download。
- 在 Programming Algorithm 中,刪除所有與 Flash 相關的算法。
- 在 Download Function 中:
- 選擇 Do not Erase。
- 取消勾選 Program。
說明:
這些設置確保 Keil 不會擦除或寫入 Flash,而是直接將程序加載到 RAM 中運行。
6. 編譯并進入調試模式
完成以上配置后:
- 點擊 Build 編譯工程,確保無錯誤。
- 點擊 Debug -> Start/Stop Debug Session 進入調試模式。
- 程序將自動下載到 RAM 并從 RAM 啟動運行。
驗證:
- 在調試模式下,檢查程序計數器(PC)是否指向 RAM 地址(如
0x24000000
開頭的地址)。 - 確保中斷和函數調用正常工作。
常見問題與注意事項
-
RAM 大小限制
確保程序的代碼和數據總大小不超過目標 RAM 的容量。例如,STM32H750 的 AXI SRAM 為 512KB,DTCM RAM 為 128KB。如果程序過大,可能需要優化代碼或選擇其他 RAM 區域。 -
復位向量地址
在.sct
文件中,RESET
段必須位于 RAM 的起始地址(如0x24000000
),否則程序無法正確啟動。 -
中斷向量表
確保.ini
文件中正確設置了 VTOR 寄存器(如_WDWORD(0xE000ED08, 0x24000000)
),以將中斷向量表重定位到 RAM,否則中斷可能無法正常工作。 -
硬件斷點限制
在 RAM 調試時,調試器支持的硬件斷點數量可能有限(通常為 6-8 個,具體取決于調試器和芯片)。如果需要設置更多斷點,可以考慮使用軟件斷點(需確保代碼支持)。 -
調試器兼容性
確保使用的調試器(如 ST-Link、J-Link)支持 RAM 調試。某些低端調試器可能對 RAM 調試支持有限。 -
初始化代碼
如果程序依賴特定的硬件初始化(如時鐘或外設),確保這些代碼在 RAM 運行時仍然有效。某些外設可能需要額外的配置以支持 RAM 執行。
總結
通過以上步驟,您可以在 Keil 中將 STM32 工程配置為從 RAM 運行并進行調試,從而避免頻繁擦寫 Flash,提高調試效率。關鍵步驟包括:
- 使用
.sct
文件手動定義內存布局。 - 配置
.ini
文件以設置 RAM 啟動環境。 - 禁用 Flash 編程算法,僅將程序加載到 RAM。
此方法適用于快速調試、驗證代碼邏輯或需要保護 Flash 的場景。希望這篇教程能幫助您順利實現 STM32 的 RAM 調試!🚀