__attribute__((section("RAMCODE")))
__weak void HAL_Delay(__IO uint32_t Delay)
{ uint32_t tickstart = 0;
tickstart = HAL_GetTick();
while((HAL_GetTick() - tickstart) < Delay)
{ }
}
3.從編譯后的map文件可以看出,ToggleLED以及它調用到的所有函數都被到了RAM中。
方法二可以覆蓋方法一,也就是說如果你同時用方法一和方法二對同一個函數的執行區域做了說明。最終起作用的是方法二。還是通過上面提到的代碼來說明。
修改.sct文件。將SRAM分為兩個執行區RW_IRAM1和RW_IRAM2。Section RAMCODE1,RAMCODE2分別位于0x20000000開始,和0x20010000開始的兩個64KB的區域。
LR_IROM1 0x08000000 0x00080000 { ; load region size_region ER_IROM1 0x08000000 0x00080000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00010000 { ; RW data
*.o(RAMCODE1)
.ANY (+RW +ZI)
}
RW_IRAM2 0x20010000 0x00010000 {
*.o(RAMCODE2) }
}
2.在代碼中, HAL_GetTick被放在了#pragma的作用域內被聲明放在RAMCODE1 section,同時又用__attribute__( ( section ( "RAMCODE2" ) ) ) 將其放在RAMCODE2的section內。
#pragma arm section code = "RAMCODE1"
void ToggleLED(void)
{ HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
/* Insert a 100ms delay */
HAL_Delay(100); }
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{ /* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->ODR ^= GPIO_Pin;
}
__attribute__( ( section ( "RAMCODE2" ) ) )
uint32_t HAL_GetTick(void)
{ return tick; }
void HAL_Delay(__IO uint32_t Delay)
{ uint32_t tickstart = 0;
tickstart = HAL_GetTick();
while((HAL_GetTick() - tickstart) < Delay) { }
}
#pragma arm section
3.編譯完成后,我們看看map文件中HAL_GetTick被放到了哪個section。
從map里可以看到,最終HAL_GetTick被放在了RAMCODE2 section中。
**如何將整個程序放到SRAM中執行
前面介紹了將一個或多個程序放到指定地址執行的方法。如果需要放到指定地址的程序比較多,我們還可以將這些需要放到指定地址的程序集中放到一個或幾個C文件中,然后在.sct文件中將這些C文件生成的目標文件放到指定地址。
在這里,我們將嘗試將整個程序放到SRAM中執行。復位后程序從FLASH啟動,之后將從SRAM執行所有的程序。下面是具體的步驟。
1.將中斷向量表和中斷處理程序放到SRAM中
新建一個startup_stm32f411xe_ram.s文件,放到0x20000000開始的位置(在.sct文件中修改)。注意這里是新建,而不是直接將原來的文件放到SRAM中,為什么呢?大家可以思考一下。在startup_stm32f411xe_ram.s里定義新的SECTION,叫做RESET_ram(還有其他的修改,請對照參考代碼)。在后面的.sct中將把RESET_ram這個section放到SRAM開始的位置上(見第3步)。
Vector Table Mapped to Address 0 at Reset
AREA RESET_ram, DATA, READONLY
EXPORT __Vectors_ram
EXPORT __Vectors_End_ram
EXPORT __Vectors_Size_ram
__Vectors_ram DCD 0 ; Top of Stack
DCD 0 ; Reset Handler
DCD NMI_Handler ; NMI Handler
……
2.在SystemInit中將中斷向量表的偏移地址設置為0x20000000。使能VECT_TAB_SRAM。
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
3.修改.sct文件,將運行時需要的所有目標文件都放到SRAM執行區中。這里中斷向量表有同樣的兩份,一份在0x08000000開始的位置,一份在0x20000000開始的位置。
LR_IROM1 0x08000000 0x00080000 { ; load region size_region
ER_IROM1 0x08000000 0x00080000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00020000 { ; RW data
*.o (RESET_ram, +First)
startup_stm32f411xe_ram.o(+RO)
main.o(+RO +RW)
stm32f4xx_it.o(+RO +RW)
stm32f4xx_hal.o(+RO +RW)
stm32f4xx_hal_gpio.o(+RO +RW)
stm32f4xx_hal_rcc.o(+RO +RW)
stm32f4xx_hal_cortex.o(+RO +RW)
.ANY (+RW +ZI)
}
}
4. 編譯完成后,從map文件或者跟蹤調試的結果都可以看到。系統復位以后,從main函數開始,所有的程序都在RAM中運行了。
另外,如果你的程序中有用到ARM底層的庫,可以在.sct文件中加入*armlib*(+RO)來將所有用到的庫文件放到SRAM中。
STM32/STM8
意法半導體/ST/STM
評論