stm32可以將代碼直接下載到RAM中時行程序調試,同時可以有效避開STM32 Flash 擦寫次數有限問題,其實除了仿真調試時將程序設置在RAM中可以解決FLASH擦寫次數問題外,如果程序實際運行時能直接在RAM中運行,其代碼的運行效率也會有一定的提高,那么怎么實現實際運行時讓程序在RAM中運行呢, 實現這一操作。
示例詳解
基於硬件平台: STM32F10C8T6最小系統板, MCU 的型號是 STM32F103c8t6, 使用stm32cubemx 工具自動產生的配置工程,使用KEIL5編譯代碼。
本示例所用的最小系統板原理圖:
-
- 關於CUBEMX工具及KEIL工具的操作將不再細講,如果還有不熟悉的可以查看之前的教程文檔。下面直接介紹工程配置:
- 系統時鍾樹
- 關於CUBEMX工具及KEIL工具的操作將不再細講,如果還有不熟悉的可以查看之前的教程文檔。下面直接介紹工程配置:
-
-
- 定時器配置
-
-
-
- 引腳配置
-
-
-
- 中斷配置(保持默認)
-
-
- 工程代碼
-
-
- 使用KEIL時需要將部分或者全部程序放到RAM中運行,實現方法有多種:
-
方法一:通過#pragma arm section code = “RAMCODE ”和#pragma arm section。這種方式,可以同時將多個函數放到指定的section。具體方法如下:
1. 修改.sct文件,自定義一個叫做RAMCODE的section,放在RW_IRAM1執行區域,地址范圍0x20000000~0x20005000。
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00010000 { ; load region size_region
ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00005000 { ; RW data
*.o(RAMCODE)
.ANY (+RW +ZI)
}
}
2. 在工程中使用前面修改的.sct文件
3.以#pragma arm section code = “RAMCODE” 開頭,以#pragma arm section結尾。將所有需要放到RAMCODE section的函數包括進來。編譯時,編譯器會自動將這些函數放到RAMCODE所在0x20000000開始的區域。
4.從map文件里,可以看到這幾個函數都已經被放到了SRAM中。
方法二:通過__attribute__((section(“name ”)))
在KEIL中可以通過__attribute__((at(address)))的方式將變量放到指定的位置。通過__attribute__((section(“name ”)))的方式將變量或者函數放到指定的位置。
1.同樣,我們需要修改.sct文件,自定義一個叫做RAMCODE的section,並在工程選項的linker頁面中,選擇定義好的.sct文件。
2.在需要放到RAM中的函數前,用__attribute__((section("RAMCODE")))聲明該函數放在RAMCODE section中。注意,該函數中調用到的所有函數也要放到RAMCODE section中。
3.從編譯后的map文件可以看出,ToggleLED以及它調用到的所有函數都被到了RAM中。
方法二可以覆蓋方法一,也就是說如果你同時用方法一和方法二對同一個函數的執行區域做了說明。最終起作用的是方法二如:
其實際結果為:
前面我們介紹了將一個或多個程序放到指定地址執行的方法。如果需要放到指定地址的程序比較多,我們還可以將這些需要放到指定地址的程序集中放到一個或幾個C文件中,然后在.sct文件中將這些C文件生成的目標文件放到指定地址。在這里,我們將嘗試將整個程序放到SRAM中執行。復位后程序從FLASH啟動,之后將從SRAM執行所有的程序。下面是具體的步驟:
1.將中斷向量表和中斷處理程序放到SRAM中,新建一個startup_stm32f103xb_ram.s文件並將其放在0x20000000處(在SCT文件中修改),其內容為,:
2,在后面的.sct中將把RESET_ram這個section放到SRAM開始的位置上,並將要放到SRAM中的程序模塊也加到SRAM中,如下圖:
2.在工程的Options for Target ->C/C++選項卡中加入VECT_TAB_SRAM宏定義:
3. 編譯完成后,從map文件可以看到程序的運行地址是在SRAM區間:
如量沒有將對應的程序模塊加載到SRAM中(SCT文件中沒加),則是下面的情況:
-
-
- 在main.c中加入如下圖所示代碼:
-
-
- 編譯工程無錯誤后,下載運行程序可以看到LED功能正常(500ms亮滅交替):
OK, 完成!