分散加載說明以GD32F103ZE為例,分別用Keil、IAR和Embedded Builder工具實現:將函數放置某個地址、將常量放置某個地址、將函數放在RAM中運行的三種效果。
1、將led_toggle()函數放在0x08040000地址后。
2、將tempbuf[1024]常量放在0x08020000地址后。
3、將void led_flow(void) 函數在RAM中運行,放在0x20008000地址后面。
1.Keil IDE example
1.1.將函數放置某個地址
生成.sct 文件
單擊 MDK 的 Option -> linker 取消勾選“Use memory layout from target Dialog”。
單擊“Scatter file”中的“Edit” ,keil 工程會出現“.sct”文件。

修改.sct 文件,將 512k flash 分成 LR_IROM1 和 LR_IROM2 兩個加載區域,分別為 256K 的 flash。

將 void led_toggle(void)函數添加到 LR_IROM2 地址內。
led.o 表示 led.c 文件生成的.o 文件。led_toggle 表示所添加的函數。

void led_toggle(void)函數需要添加“attribute”,代碼如下。
void led_toggle(void) attribute((section ("led_toggle")));其中“led_toggle”名稱可以任意。

雙擊工程名“Tartget1” 生成.map 文件,查看是否加載成功。

查看.map 文件。led_toggle 函數 在地址 0x08040000 后。說明加載成功。

1.2.將常量放置某個地址
將 tempbuf[1024]放置到 0x08020000,添加如下代碼。此時可以不用修改.sct 文件。const uint8_t tempbuf [1024] attribute((at(0x08020000))) = {0};

查看.map 文件。常量 tempbuf[1024]在地址 0x08020000 后。說明加載成功。

1.3.將函數放置 RAM 中運行
在 led.c 文件將 led_flow(void)申明,代碼添加如下。
void led_flow(void) attribute((section ("led_flow")));

修改.sct 文件,將 mcu 的 64K RAM 分成 RW_IRAM1 和 RW_IRAM2 兩個區,分別32K 大小 。在 LR_IROM2 增加 RW_IRAM2 執行區域和 led_flow 函數,如圖。

查看.map 文件,led_flow 函數在地址 0x20008000 后。說明加載成功。

1.4.將程序中所有 const 快速放置在 data 區域
專門劃分出一塊區域 0x08040000-0x08080000 放置 const 數據

修改 sct 文件如下:

代碼編譯出來效果如下:

2.IAR IDE example
2.1.將函數放置某個地址
打開配置文件.icf
Option -> linker -> config 勾選“override default”。單擊“Edit”進行修改。

修改 icf 文件,將 512K flash 分成 ROM 和 ROM1,各 256K 加載區,添加代碼如下:
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; define symbol __ICFEDIT_region_ROM1_start__ = 0x08040000; define symbol __ICFEDIT_region_ROM1_end__ = 0x0807FFFF; define region ROM1_region=mem:[from__ICFEDIT_region_ROM1_start__to __ICFEDIT_region_ROM1_end__]

修改 icf 文件,將 void led_toggle(void)函數放置在地址 0x08040000 后,添加代碼如下。
place at address mem:0x08040000 { readonly section led_toggle };

在 led.c 文件中添加函數屬性。添加代碼如下。
void led_toggle(void)@ “led_toggle”其中“led_toggle”名稱可以任意。

生成.map 文件,查看是否加載成功。在 IAR 中 Option -> linker -> List 勾選“generate linker map file”。

查看.map 文件。led_toggle 函數 在地址 0x08040000 后。說明加載成功。

2.2.將常量放置某個地址
將tempbuf[1024]放置到0x08020000,添加如下代碼。此時可以不用修改.icf 文件。const uint8_t tempbuf [1024] attribute((at(0x08020000))) = {0};

查看.map 文件。函數 tempbuf 在地址 0x08020000 后。說明加載成功。

2.3.將函數放在 RAM 中運行
在 led.c 文件設置 led_flow 屬性,添加代碼如下。void led_flow(void) @"led_flow";

修改.sct 文件,將 MCU 的 64K RAM 分成 RAM 和 RW_IRAM1 兩個 區,分別 32K 大小。

將函數從 flash copy 到 RAM 中,添加代碼如下。
initialize by copy { readwrite,section led_flow };

將 void led_flow(void)函數放置地址 0x20008000 后,需要增加如下函數。如圖。
place at address mem:0x20008000 { section led_flow };

查看.map 文件,函數 led_flow 在地址 0x20008000 后說明加載成功。

2.4. 將程序中的 const data 快速的放置到某個區域
相關語法如下:place at address mem:0x08040000 { section .rodata };

運行效果如下:

3. Embedded Builder IDE example
直接使用手動編寫的 ld 文件,在 Embedded Builder 中的的“ Window->ShowView->Project
Explore->ldscripts” 中 雙 擊 gd32f10x_flash.ld 文件或者也可到工程目錄
“GD32F4xx_ScatterLoading_v1.0.0_Eclipse\ldscripts\gd32f4xx_flash.ld”下打開編輯, 代碼下圖所示:

3.1.將函數放置某個地址
將 led_toggle()函數放置在 flash 的 0x08003400 位置

3.2.將常量放置某個地址
將常量數組放置在 flash 的 0x08003000 地址,

在 gd32f10x_flash.ld 中 添加如下語句

3.3.將函數放置 RAM 中運行
將函數 gd_eval_led_toggle 放在 SRAM 中運行,在 gd32f10x_flash.ld 添加如下代碼
/* memory map */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K RAM1 (xrw) : ORIGIN = 0x20000400, LENGTH = 1K } ENTRY(Reset_Handler) SECTIONS { __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; /* ISR vectors */ .vectors : { . = ALIGN(4); KEEP(*(.vectors)) . = ALIGN(4); __Vectors_End = .; __Vectors_Size = __Vectors_End - __gVectors; } >FLASH /* Load .sram1_text and gd32f4xx_it.o to RAM1 starting address */ _ram1_text = 0x08003500; .ram1_text : AT(_ram1_text) { . = ALIGN(4); _sram1_text = .; *(.sram1_text) *(.sram1_text*) *gd32f10x_it.o(.text .text.*) . = ALIGN(4); _erma1_text = .; } > RAM1
上述代碼將.sram1_text 段和 gd32f10x_it.o 文件加載到 RAM1(0x20005000)起始地址處,在啟動文件startup_gd32f10x_md.S 中加入如下匯編代碼
CopyData3: ldr r3, =_ram1_text ldr r3, [r3, r1] str r3, [r0, r1] adds r1, r1, #4 b LoopCopyDataInit2 LoopCopyDataInit2: ldr r0, =_sram1_text ldr r3, =_erma1_text adds r2, r0, r1 cmp r2, r3 bcc CopyData3
上述匯編代碼完成將.sram1_text 段和 gd32f10x_it.o 文件由 flash 搬運到指定的 ram 地址中。
在函數前加上attribute ((section(".sram1_text")))。
/*! \brief toggle selected led \param[in] lednum: specify the led to be toggled \arg LED2 \arg LED3 \arg LED4 \arg LED5 \param[out] none \retval none */ __attribute__ ((section(".sram1_text"))) void gd_eval_led_toggle(led_typedef_enum lednum) { gpio_bit_write(GPIO_PORT[lednum], GPIO_PIN[lednum], (bit_status)(1-gpio_input_bit_get(GPIO_PORT[lednum], GPIO_PIN[lednum]))); }
調試運行驗證函數地址

-
單片機
+關注
關注
6063文章
44915瀏覽量
646818 -
嵌入式
+關注
關注
5141文章
19526瀏覽量
314857 -
IAR
+關注
關注
5文章
369瀏覽量
37239 -
開發板
+關注
關注
25文章
5503瀏覽量
102189 -
keil
+關注
關注
69文章
1223瀏覽量
168967
發布評論請先 登錄
GD32 MCU 入門教程】GD32 MCU 常見外設介紹(12)FMC 模塊介紹

GD32單片機利用分散加載避免前后Flash速度不一致
兆易創新GD32 MCU選型手冊,適用于GD32全系列MCU
【GD32 MCU 入門教程】一、GD32 MCU 開發環境搭建(1)使用Keil開發GD32

【GD32 MCU 入門教程】一、GD32 MCU 開發環境搭建(2)使用 IAR 開發 GD32

【GD32 MCU 入門教程】一、GD32 MCU 開發環境搭建(3)使用 Embedded Builder 開發 GD32

【GD32 MCU 入門教程】二、GD32 MCU 燒錄說明(1)ISP 燒錄

【GD32 MCU 入門教程】二、GD32 MCU 燒錄說明(3)脫機燒錄

【GD32 MCU 入門教程】GD32 MCU 常見外設介紹(14)RTC 模塊介紹

【GD32 MCU入門教程】GD32 MCU GPIO 結構與使用注意事項

評論