mdk keil 指定變量、函數存儲位置,使用 Scatter-Loading Description File, __attribute__(("section“))
阿新 • • 發佈:2018-05-12
最大 type 內存分區 stdin script bsp attr 出現 name
0. 數據類型說明
主要包括4類:
- Code (inc. data) ,屬於RO,也就是寫的函數代碼(包括代碼中的變量)
- RO Data , 屬於RO,使用const修飾的變量。
- RW Data, 屬於RW,變量。
- ZI Data, 屬於RW,沒有初始化的變量。
1. mdk 設置Scatter 文件
默認情況下,片內會有兩大存儲塊IROM(只讀存儲器RO,用來存常量、代碼等),IRAM(讀寫存儲器RW,用來存變量,包括被默認初始化為0的變量),如下圖 "Target"選項卡。
來看“Linker”選項卡,下面介紹操作:
1. 默認的選項是使用的“Target”的內存分區,需要把這個勾去掉。
2. 去掉勾後會出現一個“.sct"文件,點擊Edit就可以修改了,對文件做了註釋說明如下:
LR_IROM1 0x08000000 0x00080000 { ; load region size_region, 裝載區域 ; LR_IROM1, 這是一個名字,隨便起。可以理解為一塊存儲器的名字。 ; 0x08000000,這是起始地址。 ; 0x00080000,代表size,也就是存儲器的最大空間。ER_IROM1 0x08000000 0x00080000 { ; load address = execution address, 執行區域 *.o (RESET, +First) ; *.o, 是說對於任意的".o"文件 ; RESET 是說含有“RESET”的section名稱的 ; +First 是說最先匹配 ; 合起來就是在所有的“.o”文件中找到含有“RESET”字段的內容放到“ER_IROM1"這塊存儲區域內*(InRoot$$Sections) .ANY (+RO) ; ‘.ANY‘ 可以理解成 ‘*‘ ,是說把剩下的RO類型的數據(常量和代碼)放到這裏。 } RW_IRAM1 0x20000000 0x00010000 { ; RW data .ANY (+RW +ZI) ; 是說把剩下的RW,ZI類型的數據(常量和代碼)放到這裏。 } }
從上面可以看到這裏只做了兩個區分,大體上就是RO和RW的區別,下面說明自定義區域。
3. 這裏我們定義兩個區域,一個用來存放函數,一個用來存放數據:
LR_IROM1 0x08000000 0x00080000 { ; load region size_region ER_IROM1 0x08000000 0x00080000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } MY_FUN 0x20000000 0x00000080 { ; 自定義函數存儲位置,地址及大小僅作說明。 .ANY (pg_fun) } MY_DATA 0x20000080 0x00000080 { ; 自定義數據存儲位置,地址及大小僅作說明。 .ANY (pg_data) } RW_IRAM2 0x20000100 0x0000FF00 { .ANY (+RW +ZI) ; RW data } }
4. 在“inc.h"頭文件中:
#define PG_FUN_ATTRIBUTES __attribute__ ((section("pg_fun"))) #define PG_DATA_ATTRIBUTES __attribute__ ((section("pg_data"))) void test1 (void);
5. 在”test.c"文件中:
#include "inc.h" typedef struct tt{ // 自定義結構體 int a; double b; }tt_t; // 變量定義,分配到定義的數據區域內 static tt_t t0 PG_DATA_ATTRIBUTES = { .a = 1, .b = 2, }; static char t1[10] PG_DATA_ATTRIBUTES; // 函數定義,分配到定義的函數區域內 void test1 PG_FUN_ATTRIBUTES() { t0.a = 1; }
6. 在“main.c"文件中:
#include "stm32f10x.h" #include <stdint.h> #include "inc.h" #include <stdio.h> static char tc2[5] PG_DATA_ATTRIBUTES; void foo PG_FUN_ATTRIBUTES() { tc2[0] = 2; } int main() { foo(); test1(); return 0; }
7. 文件“test.map" 查看結果:
Execution Region MY_FUN (Base: 0x20000000, Size: 0x00000018, Max: 0x00000080, ABSOLUTE) Base Addr Size Type Attr Idx E Section Name Object 0x20000000 0x0000000c Code RO 5 pg_fun main.o 0x2000000c 0x0000000c Code RO 150 pg_fun test.o Execution Region MY_DATA (Base: 0x20000080, Size: 0x0000002c, Max: 0x00000080, ABSOLUTE) Base Addr Size Type Attr Idx E Section Name Object 0x20000080 0x00000005 Data RW 6 pg_data main.o 0x20000085 0x00000003 PAD 0x20000088 0x00000022 Data RW 151 pg_data test.o
可以看到,函數和代碼都以如願以償。
結構體編譯出錯,參考這篇文章:MDK KEIL 機構體初始化。
mdk keil 指定變量、函數存儲位置,使用 Scatter-Loading Description File, __attribute__(("section“))