内存分配基础:修改SCT文件的简单例子
一个简单例子,熟悉最基本的语法,有个初步的理解
一、SCT文件修改
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************;片上Flash
LR_IROM1 0x08000000 0x00100000 { ; load region size_region 0x08000000是片上Flash的首地址,表示程序的存放地址ER_IROM1 0x08000000 0x00100000 { ; load address = execution address ER_IROM1表示运行时从哪里开始执行程序*.o (RESET, +First) ;*通配符,匹配所有文件,*.o 则表示所有以.o结尾的文件*(InRoot$$Sections) ;表示系统初始化文件即C库.ANY (+RO) ;.ANY表示所有文件,但是是*之后的.ANY (+XO)}RW_IRAM1 0x20000000 0x00020000 {.ANY (+RW +ZI)};FSMC外部总线,运行时才有,输入加载区域; 1、FPGA区域FPGA_ADC_REG 0x60000000 UNINIT 0x00000010 { ; adc data*(.fpga_adc_reg) ; 确保段名fpga_adc_reg与代码中一致,*通配符,匹配所有文件}FPGA_PWM_REG 0x60000010 UNINIT 0x00000010 { ; pwm data*(.fpga_pwm_reg) ; 确保段名fpga_pwm_reg与代码中一致,*通配符,匹配所有文件}; 2、外部SRAM区域EX_RAM_DATA 0x60008000 0x00004000 { .ANY (+RW +ZI) ;扩充片上RAM,用于RW和ZI变量,128KB}EX_RAM_DATA_UART 0x6000C000 0x00001000 { ;指定变量存放地址MyUart.o (+RW +ZI) ;MyUart.c文件中用到的所有RW和ZI数据都放在这个地址段0x0x6000C000 ~ 0x0x6000D000}EX_RAM_DATA_GPIO 0x6000D000 0x00001000 { MyGpio.o (+RW +ZI) ;MyGpio.c文件中用到的所有RW和ZI数据都放在这个地址段0x0x6000D000 ~ 0x0x6000E000}EX_RAM_DATA_USER 0x6000E000 0x00001000 { *(.my_data_user) ;*通配符,匹配所有文件,包括数据和代码}EX_RAM_DATA_TEST 0x6000F000 0x00001000 { *(.my_data_test)}EX_RAM_CODE 0x60010000 0x00080000 { ;运行起来时将程序复制到RAM区域,运行更快,256KB*(.copy_code)}; ... 加载域可以在这一直划分扩展下去
};片外Flash,比如QSPI型,将其划分成两段使用
EX_ROM_PART1 0x08100000 0x00080000 { ;表示程序的存放地址EX_ROM1 0x08100000 0x00080000 { ;表示程序运行起来后从哪个地址开始执行MyUart.o (+RO) ;MyUart.c文件中所有RO即RO数据和Code都放在这个地址段0x08100000 ~ 0x08180000MyGpio.o (+RO) ;MyGpio.c文件中所有RO即RO数据和Code都放在这个地址段0x08100000 ~ 0x08180000}}EX_ROM_PART2 0x08180000 0x00080000 {EX_ROM2 0x08180000 0x00080000 { ;表示程序运行起来后从哪个地址开始执行MyUart.o (ex_flash_uart_code) ;为MyUart.c文件分配一个代码存储段ex_flash_uart_code,只能存放MyUart.c中的代码*.o(ex_flash_all_code) ;为所有.c文件分配一个代码存储段ex_flash_all_code}}
- 加载区域表示代码和数据下载到芯片时存储到哪段地址,可以存储到片上
Flash
,也可以存储到片外Flash
,也可以存储到RAM
里。
- 对于代码,为只读类型,运行时无法更改,因此存储在
Flash
中即加载区域是Flash
地址段。 - 对于数据,其分成几类:
- 对于
RO
只读数据,比如const
类型、字符串等等,其存储在Flash
,因此加载区域也是Flash
地址段; - 对于
RW
读写数据,比如.data
,如果其有初值,那么初值要存放在Flash
中,运行时先从Flash
中取出初值对RW
数据进行赋值,然后运行时RW
数据的访问地址是在RAM
里,也就是RW
数据的加载区域是Flash地址段,执行区域是RAM
地址段; - 对于ZI数据,比如
.bss和stack、heap
,表示初始化为零的全局变量,因此无需在Flash
中存放初值,也就无所谓加载区域,只有执行区域,执行区域也就是程序运行时,如果要访问这个变量,要去哪个地址段寻找。
- 对于
- 执行区域表示上电运行后程序和数据从哪个地址开始执行。
- 对于代码:也就是从哪个地址开始读取代码语句并执行,一般是程序存储在哪里,就从哪里执行,代码的执行区域和加载区域保持一致。
- 对于数据:表示程序运行起来后,去哪个地址可以访问数据,
- 对于
RO
数据,例如const
,需要存储在Flash
中,因此其执行区域地址就处在Flash
中,对应到ER_IROM1
里的这个内存分配语句.ANY (+RO) ;.ANY表示所有文件,但是是*之后的
,程序运行起来后也是去Flash
地址段访问const
变量,因此其执行区域也是Flash
地址段,两个区域保持一致
ER_IROM1 0x08000000 0x00100000 { ; load address = execution address ER_IROM1表示运行时从哪里开始执行程序*.o (RESET, +First) ;*通配符,匹配所有文件,*.o 则表示所有以.o结尾的文件*(InRoot$$Sections) ;表示系统初始化文件即C库.ANY (+RO) ;.ANY表示所有文件,但是是*之后的.ANY (+XO)}
- 对于
RW
数据,如果初值不为零,那么初值需要存储到Flash
中(即使初值为零,加载区域似乎也是Flash
段),则其加载区域是Flash
地址段,运行时访问RW
数据则要去RAM
里,因此执行区域是RAM
地址段。例如
(1)在MyUart.c
中定义一个RW
变量uart_baud
,带有非零初始值,注意这里是volatile
类型,会有点不同,会变成RW
类型。没有volatile
修饰则就是RO
类型
volatile const unsigned int uart_baud[2] = {9600,115200};
(2)修改SCT
文件,将MyUart.c
中的RW
变量存放到0x6000C000
地址
EX_RAM_DATA_UART 0x6000C000 0x00001000 { ;指定变量存放地址MyUart.o (+RW +ZI) ;MyUart.c文件中用到的所有RW和ZI数据都放在这个地址段0x0x6000C000 ~ 0x0x6000D000}
(3)查看Map
文件,确认RW
变量uart_baud
的地址是0x6000C000
,并且可以看到属性是myuart.o(.data)
,表示是myuart.c
文件中的.data
变量即RW
类型
uart_baud 0x6000c000 Data 8 myuart.o(.data)
(4)查看Map
文件,uart_baud
的执行区域是0x6000C000
即指定地址,加载区域则是0x08000340
,由编译器分配
Execution Region EX_RAM_DATA_UART (Exec base: 0x6000c000, Load base: 0x08000340, Size: 0x00000018, Max: 0x00001000, ABSOLUTE)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x6000c000 0x08000340 0x00000008 Data RW 39 .data myuart.o0x6000c008 - 0x00000010 Zero RW 38 .bss myuart.o
(5)在MyGpio.c
中
- 定义常量
gpio_port
和全局变量gpio
//没有volatile的const
const unsigned char gpio_port[2] = {1,2};
volatile unsigned char gpio[32];
- 设置常量
gpio_port
的存储地址是EX_ROM1
,设置全局变量gpio
的村粗地址是EX_RAM_DATA_GPIO
;RW执行区域EX_RAM_DATA_GPIO 0x6000D000 0x00001000 { MyGpio.o (+RW +ZI) ;MyGpio.c文件中用到的所有RW和ZI数据都放在这个地址段0x0x6000D000 ~ 0x0x6000E000};片外Flash,比如QSPI型,将其划分成两段使用
EX_ROM_PART1 0x08100000 0x00080000 { ;表示程序的存放地址EX_ROM1 0x08100000 0x00080000 { ;表示程序运行起来后从哪个地址开始执行MyUart.o (+RO) ;MyUart.c文件中所有RO即RO数据和Code都放在这个地址段0x08100000 ~ 0x08180000MyGpio.o (+RO) ;MyGpio.c文件中所有RO即RO数据和Code都放在这个地址段0x08100000 ~ 0x08180000}}
- 变量
uart_baud
的地址是0x6000C000
,并且可以看到属性是myuart.o(.data)
,表示是myuart.c
文件中的.data
变量即RW
类型 - 变量
uart
的地址是0x6000c008
,并且可以看到属性是myuart.o(.bss)
,表示是myuart.c
文件中的.bss
变量即ZI
类型 - 常量
gpio_port
的地址是0x08100044
,并且可以看到属性是mygpio.o(.constdata)
,表示是mygpio.c
文件中的const
变量即RO
类型 - 变量
gpio
的地址是0x6000D000
,并且可以看到属性是mygpio.o(.bss)
,表示是mygpio.c
文件中的.bss
变量即ZI
类型
gpio_port 0x08100044 Data 2 mygpio.o(.constdata)gpio 0x6000d000 Data 32 mygpio.o(.bss)uart_baud 0x6000c000 Data 8 myuart.o(.data)uart 0x6000c008 Data 16 myuart.o(.bss)
总结:
【1】const
变量如果被volatile
修饰,则会变成RW
类型
【2】ZI
类型如果被attribute
指定执行地址,则会变成RW
类型
- 对于
ZI
数据,如果没有通过SCT
文件修改其执行地址即编译器自动确定,则其只有执行区域,没有加载区域,但如果通过SCT
文件修改了其执行区域,则似乎变成了RW
类型,就会出现加载区域,例如
(1)在main.c
中定义两个初值为零的全局变量,可读可写
unsigned char test_i;
__attribute__((section(".fpga_adc_reg"))) volatile ST_REG ADC_REG[16];
__attribute__((section(".fpga_pwm_reg"))) ST_REG PWM_REG[16];
(2)修改SCT
文件,将ADC_REG
存放到指定地址0x60000000
FPGA_ADC_REG 0x60000000 UNINIT 0x00000010 { ; adc data*(.fpga_adc_reg) ; 确保段名fpga_adc_reg与代码中一致,*通配符,匹配所有文件}FPGA_PWM_REG 0x60000010 UNINIT 0x00000010 { ; pwm data*(.fpga_pwm_reg) ; 确保段名fpga_pwm_reg与代码中一致,*通配符,匹配所有文件}
(3)查看Map
文件,test_i
由编译器自动分配,分配到了片上RAM
,ADC_REG
由用户指定,分配到0x60000000
地址
test_i 0x20000000 Data 1 main.o(.data)ADC_REG 0x60000000 Data 16 main.o(.fpga_adc_reg)PWM_REG 0x60000010 Data 16 main.o(.fpga_pwm_reg)
(4)查看Map
文件,test_i
没有加载区域,只有执行区域0x20000000
,ADC_REG
既有加载区域0x08000354
,又有执行区域0x60000000
Execution Region FPGA_ADC_REG (Exec base: 0x60000000, Load base: 0x08000354, Size: 0x00000010, Max: 0x00000010, ABSOLUTE, UNINIT)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x60000000 0x08000354 0x00000010 Data RW 4 .fpga_adc_reg main.oExecution Region FPGA_PWM_REG (Exec base: 0x60000010, Load base: 0x08000354, Size: 0x00000010, Max: 0x00000010, ABSOLUTE, UNINIT)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x60000010 0x08000354 0x00000010 Data RW 5 .fpga_pwm_reg main.o
- SCT文件的基础语法
语法 | 说明 |
---|---|
LR_IROM1 | 加载域(Load Region)名称,名字自定义 |
0x08000000 | 加载域起始地址即程序和数据存放的起始地址 |
0x00080000 | 加载域的空间大小即留给程序和数据的最大存储空间 |
ER_IROM1 | 执行域(Execution Region)名称,名字自定义 |
*.o | * 表示通配符,*.o 表示所有以.o 为结尾的文件 |
*.o (RESET, +First) | 存放所有.o 文件时将 RESET 段(中断向量表)的变量放在最开头的位置,其他.o 存放顺序不做严格要求 |
*(InRoot$$Sections) | 表示所有的系统初始化代码即C 库的初始化代码(如 __main ) |
.ANY (+RO) | 代表程序里用到的所有只读(Read-Only )数据 |
.ANY (+RW +ZI) | 代表程序里用到的所有可读写(RW)和零初始化(ZI)数据 |
+ZI | 代表程序里用到的Zero-Initialized 数据(如未初始化的全局变量.bss、stack、heap ) |
MyGpio.o (+RO) | 代表MyGpio.c 文件里用到的所有只读(Read-Only )数据 |
MyGpio.o (gpio_section) | 代表为MyGpio.c 划分出一个段即名字是gpio_section ,用于存放MyGpio.c 文件中的数据或代码 |
* (.all_section) | 代表为所有文件划分出一个段即名字是.all_section ,所有文件都可以往这个段放数据或者代码 |
二、MyUart.c文件
volatile const unsigned int uart_baud[2] = {9600,115200};volatile unsigned char uart[16];void uart_test()
{for(unsigned char i = 0; i < 16; i++){uart[i] = i + uart_baud[0];}}__attribute__((section("ex_flash_uart_code"))) void uart_ex_flash()
{uart_test();for(unsigned char i = 0; i < 16; i++){uart[i]--;}}
三、MyGpio.c文件
volatile const unsigned char gpio_port[2] = {1,2};volatile unsigned char gpio[32];void gpio_test()
{for(unsigned char i = 0; i < 32; i++){gpio[i] = i*2 + gpio_port[0];}}__attribute__((section("ex_flash_all_code"))) void gpio_ex_flash()
{gpio_test();for(unsigned char i = 0; i < 16; i++){gpio[i]--;}}
四、MyTest.c文件
__attribute__((section(".my_data_user"))) volatile unsigned char user[10];__attribute__((section(".my_data_test"))) volatile unsigned char test[20];__attribute__((section("ex_flash_all_code"))) void my_test()
{for(unsigned char i = 0; i < 10; i++){user[i] = i*2;test[i] = i*3;}}
五、主函数里要调用
typedef struct
{unsigned char bit0:1;unsigned char bit1:1;unsigned char bit2:1;unsigned char bit3:1;unsigned char bit4:1;unsigned char bit5:1;unsigned char bit6:1;unsigned char bit7:1;
}ST_BITS; //位域,按位访问typedef union
{unsigned char all;ST_BITS bits;
}ST_REG; //按位或者整体访问__attribute__((section(".fpga_adc_reg"))) volatile ST_REG ADC_REG[16];
__attribute__((section(".fpga_pwm_reg"))) volatile ST_REG PWM_REG[16]; void my_test();
void uart_ex_flash();
void gpio_ex_flash();int main(void)
{ unsigned char i= 0; /* 1、分散加载文件指定FPGA变量存放地址 */for(i = 0; i<16;i++){ADC_REG[i].all=i;PWM_REG[i].bits.bit0 = i+0;}/* 2、分散加载文件测试 */my_test();uart_ex_flash();gpio_ex_flash();while(1){}}
一定要调用这些变量和函数,否则编译器会将其优化移除,也就看不到存储到指定地址的效果了
六、查看Map表
6.1 Memory Map of the image
- 程序和只读变量的加载区域和执行区域一致,都是
0x08000000
Image Entry point : 0x08000189Load Region LR_IROM1 (Base: 0x08000000, Size: 0x0000036c, Max: 0x00100000, ABSOLUTE)Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x00000320, Max: 0x00100000, ABSOLUTE)
Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x00000320, Max: 0x00100000, ABSOLUTE)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x08000000 0x08000000 0x00000188 Data RO 30 RESET startup_stm32f40xx.o0x08000188 0x08000188 0x00000000 Code RO 90 * .ARM.Collect$$$$00000000 mc_w.l(entry.o)0x08000188 0x08000188 0x00000004 Code RO 93 .ARM.Collect$$$$00000001 mc_w.l(entry2.o)0x0800018c 0x0800018c 0x00000004 Code RO 96 .ARM.Collect$$$$00000004 mc_w.l(entry5.o)0x08000190 0x08000190 0x00000000 Code RO 98 .ARM.Collect$$$$00000008 mc_w.l(entry7b.o)0x08000190 0x08000190 0x00000000 Code RO 100 .ARM.Collect$$$$0000000A mc_w.l(entry8b.o)0x08000190 0x08000190 0x00000008 Code RO 101 .ARM.Collect$$$$0000000B mc_w.l(entry9a.o)0x08000198 0x08000198 0x00000004 Code RO 108 .ARM.Collect$$$$0000000E mc_w.l(entry12b.o)0x0800019c 0x0800019c 0x00000000 Code RO 103 .ARM.Collect$$$$0000000F mc_w.l(entry10a.o)0x0800019c 0x0800019c 0x00000000 Code RO 105 .ARM.Collect$$$$00000011 mc_w.l(entry11a.o)0x0800019c 0x0800019c 0x00000004 Code RO 94 .ARM.Collect$$$$00002712 mc_w.l(entry2.o)0x080001a0 0x080001a0 0x00000024 Code RO 31 .text startup_stm32f40xx.o0x080001c4 0x080001c4 0x00000024 Code RO 109 .text mc_w.l(init.o)0x080001e8 0x080001e8 0x00000002 Code RO 1 i.SystemInit main.o0x080001ea 0x080001ea 0x0000000e Code RO 113 i.__scatterload_copy mc_w.l(handlers.o)0x080001f8 0x080001f8 0x00000002 Code RO 114 i.__scatterload_null mc_w.l(handlers.o)0x080001fa 0x080001fa 0x0000000e Code RO 115 i.__scatterload_zeroinit mc_w.l(handlers.o)0x08000208 0x08000208 0x00000088 Code RO 2 i.main main.o0x08000290 0x08000290 0x00000090 Data RO 111 Region$$Table anon$$obj.o
STACK
属于ZI
变量,定义在启动文件里,这里是由编译器自动分配地址,分配到起始地址0x20000008
,栈所在空间大小是0x00000400
。也可以修改SCT
文件,达到用户指定其地址的效果。
Stack_Size EQU 0x00000400AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x08000350, Size: 0x00000408, Max: 0x00020000, ABSOLUTE)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x20000000 0x08000350 0x00000001 Data RW 3 .data main.o0x20000001 0x08000351 0x00000007 PAD0x20000008 - 0x00000400 Zero RW 29 STACK startup_stm32f40xx.o
- 程序和
SCT
文件配合将变量ADC_REG
和PWM_REG
存放到指定地址段,修改了执行地址,变成了RW
变量,RW
变量有加载区域和执行区域。ADC_REG
的执行区域是0x60000000
即去0x60000000
地址可以访问到ADC_REG
变量,加载区域是0x08000320
,即上电运行时先从Flash
地址0x08000320
取数据赋值给ADC_REG
变量作为初值。
__attribute__((section(".fpga_adc_reg"))) volatile ST_REG ADC_REG[16];
__attribute__((section(".fpga_pwm_reg"))) volatile ST_REG PWM_REG[16];
Execution Region FPGA_ADC_REG (Exec base: 0x60000000, Load base: 0x08000320, Size: 0x00000010, Max: 0x00000010, ABSOLUTE, UNINIT)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x60000000 0x08000320 0x00000010 Data RW 3 .fpga_adc_reg main.oExecution Region FPGA_PWM_REG (Exec base: 0x60000010, Load base: 0x08000330, Size: 0x00000010, Max: 0x00000010, ABSOLUTE, UNINIT)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x60000010 0x08000330 0x00000010 Data RW 4 .fpga_pwm_reg main.o
- 修改
SCT
文件划分出段EX_RAM_DATA
,用于存放运行时的任意RW和ZI数据
,用于补充片上RAM
空间不足的问题。但这个程序片上RAM
空间足够,因此编译器没有将变量放到段EX_RAM_DATA
,编译时也就报了个警告:No section assigned to this execution region
EX_RAM_DATA 0x60008000 0x00004000 { .ANY (+RW +ZI) ;扩充片上RAM,用于RW和ZI变量,128KB}
Execution Region EX_RAM_DATA (Exec base: 0x60008000, Load base: 0x08000340, Size: 0x00000000, Max: 0x00004000, ABSOLUTE)**** No section assigned to this execution region ****
MyUart.c
文件中的RW和ZI
变量,即uart_baud
和uart
存放到段EX_RAM_DATA_UART
,此变量有加载地址和执行地址
volatile const unsigned int uart_baud[2] = {9600,115200};
volatile unsigned char uart[16];
MyGpio.c
文件中的RW和ZI
变量,即gpio_port
和gpio
存放到段EX_RAM_DATA_GPIO
,此变量有加载地址和执行地址
volatile const unsigned char gpio_port[2] = {1,2};
volatile unsigned char gpio[32];
MyTest.c
文件中的RW和ZI
变量,即user
通过attribute
指令存放到段.my_data_user
,test
通过attribute
指令存放到段.my_data_test
,此变量有加载地址和执行地址
__attribute__((section(".my_data_user"))) volatile unsigned char user[10];
__attribute__((section(".my_data_test"))) volatile unsigned char test[20];
Execution Region EX_RAM_DATA_UART (Exec base: 0x6000c000, Load base: 0x08000340, Size: 0x00000018, Max: 0x00001000, ABSOLUTE)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x6000c000 0x08000340 0x00000008 Data RW 39 .data myuart.o0x6000c008 - 0x00000010 Zero RW 38 .bss myuart.oExecution Region EX_RAM_DATA_GPIO (Exec base: 0x6000d000, Load base: 0x08000348, Size: 0x00000024, Max: 0x00001000, ABSOLUTE)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x6000d000 0x08000348 0x00000002 Data RW 59 .data mygpio.o0x6000d002 0x0800034a 0x00000002 PAD0x6000d004 - 0x00000020 Zero RW 58 .bss mygpio.oExecution Region EX_RAM_DATA_USER (Exec base: 0x6000e000, Load base: 0x0800034c, Size: 0x0000000c, Max: 0x00001000, ABSOLUTE)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x6000e000 0x0800034c 0x0000000a Data RW 78 .my_data_user mytest.oExecution Region EX_RAM_DATA_TEST (Exec base: 0x6000f000, Load base: 0x08000358, Size: 0x00000014, Max: 0x00001000, ABSOLUTE)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x6000f000 0x08000358 0x00000014 Data RW 77 .my_data_test mytest.o
- 未在此段存放数据或代码,因此报了告警:
No section assigned to this execution region
Execution Region EX_RAM_CODE (Exec base: 0x60010000, Load base: 0x0800036c, Size: 0x00000000, Max: 0x00080000, ABSOLUTE)**** No section assigned to this execution region ****
- 修改
SCT
文件划分出了片外Flash
段,用于外接Flash
设备的情况,可以将一些代码或者RO
数据存放到片外Flash
,能够灵活启动程序,比如从外部Flash
启动程序,并且外部Flash
可以做成可插拔替换的形式,那么只需更换外部Flash
,就可以执行不同的程序,而无需重新烧写程序。片外Flash
划分成两段使用,这是Part1
:
MyUart.c
文件中所有RO
即RO
数据和Code
都放在这个地址段0x08100000 ~ 0x08180000
MyGpio.c
文件中所有RO
即RO
数据和Code
都放在这个地址段0x08100000 ~ 0x08180000
i.gpio_test 0x08100000 Section 0 mygpio.o(i.gpio_test)
i.uart_test 0x08100024 Section 0 myuart.o(i.uart_test)
Load Region EX_ROM_PART1 (Base: 0x08100000, Size: 0x00000044, Max: 0x00080000, ABSOLUTE)Execution Region EX_ROM1 (Exec base: 0x08100000, Load base: 0x08100000, Size: 0x00000044, Max: 0x00080000, ABSOLUTE)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x08100000 0x08100000 0x00000024 Code RO 57 i.gpio_test mygpio.o0x08100024 0x08100024 0x00000020 Code RO 37 i.uart_test myuart.o
- 片外
Flash
划分成两段使用,这是Part2
:
- 为
MyUart.c
文件分配一个代码存储段ex_flash_uart_code
,只能存放MyUart.c
中的代码; - 为所有
.c
文件分配一个代码存储段ex_flash_all_code
EX_ROM_PART2 0x08180000 0x00080000 {EX_ROM2 0x08180000 0x00080000 { ;表示程序运行起来后从哪个地址开始执行MyUart.o (ex_flash_uart_code) ;为MyUart.c文件分配一个代码存储段ex_flash_uart_code,只能存放MyUart.c中的代码*.o(ex_flash_all_code) ;为所有.c文件分配一个代码存储段ex_flash_all_code}
}__attribute__((section("ex_flash_uart_code"))) void uart_ex_flash()__attribute__((section("ex_flash_all_code"))) void gpio_ex_flash()
__attribute__((section("ex_flash_all_code"))) void my_test()
gpio_ex_flash 0x08180001 Thumb Code 30 mygpio.o(ex_flash_all_code)my_test 0x08180025 Thumb Code 30 mytest.o(ex_flash_all_code)uart_ex_flash 0x0818004d Thumb Code 30 myuart.o(ex_flash_uart_code)
Load Region EX_ROM_PART2 (Base: 0x08180000, Size: 0x00000070, Max: 0x00080000, ABSOLUTE)Execution Region EX_ROM2 (Exec base: 0x08180000, Load base: 0x08180000, Size: 0x00000070, Max: 0x00080000, ABSOLUTE)Exec Addr Load Addr Size Type Attr Idx E Section Name Object0x08180000 0x08180000 0x00000024 Code RO 56 ex_flash_all_code mygpio.o0x08180024 0x08180024 0x00000028 Code RO 76 ex_flash_all_code mytest.o0x0818004c 0x0818004c 0x00000024 Code RO 36 ex_flash_uart_code myuart.o
6.2 Image Symbol Table
i.main 0x08000208 Section 0 main.o(i.main)i.gpio_test 0x08100000 Section 0 mygpio.o(i.gpio_test)i.uart_test 0x08100024 Section 0 myuart.o(i.uart_test).constdata 0x08100044 Section 2 mygpio.o(.constdata)ex_flash_all_code 0x08180000 Section 0 mygpio.o(ex_flash_all_code)ex_flash_all_code 0x08180024 Section 0 mytest.o(ex_flash_all_code)ex_flash_uart_code 0x0818004c Section 0 myuart.o(ex_flash_uart_code).data 0x20000000 Section 1 main.o(.data)STACK 0x20000008 Section 1024 startup_stm32f40xx.o(STACK).fpga_adc_reg 0x60000000 Section 16 main.o(.fpga_adc_reg).fpga_pwm_reg 0x60000010 Section 16 main.o(.fpga_pwm_reg).data 0x6000c000 Section 8 myuart.o(.data).bss 0x6000c008 Section 16 myuart.o(.bss).bss 0x6000d000 Section 32 mygpio.o(.bss).my_data_user 0x6000e000 Section 10 mytest.o(.my_data_user).my_data_test 0x6000f000 Section 20 mytest.o(.my_data_test)
main 0x08000209 Thumb Code 146 main.o(i.main)Region$$Table$$Base 0x080002b0 Number 0 anon$$obj.o(Region$$Table)Region$$Table$$Limit 0x08000340 Number 0 anon$$obj.o(Region$$Table)gpio_test 0x08100001 Thumb Code 26 mygpio.o(i.gpio_test)uart_test 0x08100025 Thumb Code 24 myuart.o(i.uart_test)gpio_port 0x08100044 Data 2 mygpio.o(.constdata)gpio_ex_flash 0x08180001 Thumb Code 30 mygpio.o(ex_flash_all_code)my_test 0x08180025 Thumb Code 30 mytest.o(ex_flash_all_code)uart_ex_flash 0x0818004d Thumb Code 30 myuart.o(ex_flash_uart_code)test_i 0x20000000 Data 1 main.o(.data)__initial_sp 0x20000408 Data 0 startup_stm32f40xx.o(STACK)ADC_REG 0x60000000 Data 16 main.o(.fpga_adc_reg)PWM_REG 0x60000010 Data 16 main.o(.fpga_pwm_reg)uart_baud 0x6000c000 Data 8 myuart.o(.data)uart 0x6000c008 Data 16 myuart.o(.bss)gpio 0x6000d000 Data 32 mygpio.o(.bss)user 0x6000e000 Data 10 mytest.o(.my_data_user)test 0x6000f000 Data 20 mytest.o(.my_data_test)