内存分配基础:修改SCT文件的简单例子

发布于:2025-06-13 ⋅ 阅读:(17) ⋅ 点赞:(0)

一个简单例子,熟悉最基本的语法,有个初步的理解

一、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 ~ 0x08180000
	MyGpio.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
  }

}
  1. 加载区域表示代码和数据下载到芯片时存储到哪段地址,可以存储到片上Flash,也可以存储到片外Flash,也可以存储到RAM里。
  • 对于代码,为只读类型,运行时无法更改,因此存储在Flash中即加载区域是Flash地址段。
  • 对于数据,其分成几类:
    • 对于RO只读数据,比如const类型、字符串等等,其存储在Flash,因此加载区域也是Flash地址段;
    • 对于RW读写数据,比如.data,如果其有初值,那么初值要存放在Flash中,运行时先从Flash中取出初值对RW数据进行赋值,然后运行时RW数据的访问地址是在RAM里,也就是RW数据的加载区域是Flash地址段,执行区域是RAM地址段;
    • 对于ZI数据,比如.bss和stack、heap,表示初始化为零的全局变量,因此无需在Flash中存放初值,也就无所谓加载区域,只有执行区域,执行区域也就是程序运行时,如果要访问这个变量,要去哪个地址段寻找。
  1. 执行区域表示上电运行后程序和数据从哪个地址开始执行
  • 对于代码:也就是从哪个地址开始读取代码语句并执行,一般是程序存储在哪里,就从哪里执行,代码的执行区域和加载区域保持一致。
  • 对于数据:表示程序运行起来后,去哪个地址可以访问数据,
  • 对于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        Object

    0x6000c000   0x08000340   0x00000008   Data   RW           39    .data               myuart.o
    0x6000c008        -       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 ~ 0x08180000
	MyGpio.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 由编译器自动分配,分配到了片上RAMADC_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没有加载区域,只有执行区域0x20000000ADC_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        Object

    0x60000000   0x08000354   0x00000010   Data   RW            4    .fpga_adc_reg       main.o



    Execution 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        Object

    0x60000010   0x08000354   0x00000010   Data   RW            5    .fpga_pwm_reg       main.o
  1. 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

  1. 程序和只读变量的加载区域和执行区域一致,都是0x08000000
Image Entry point : 0x08000189

  Load 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        Object

    0x08000000   0x08000000   0x00000188   Data   RO           30    RESET               startup_stm32f40xx.o
    0x08000188   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.o
    0x080001c4   0x080001c4   0x00000024   Code   RO          109    .text               mc_w.l(init.o)
    0x080001e8   0x080001e8   0x00000002   Code   RO            1    i.SystemInit        main.o
    0x080001ea   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.o
    0x08000290   0x08000290   0x00000090   Data   RO          111    Region$$Table       anon$$obj.o
  1. STACK属于ZI变量,定义在启动文件里,这里是由编译器自动分配地址,分配到起始地址0x20000008,栈所在空间大小是0x00000400。也可以修改SCT文件,达到用户指定其地址的效果。
Stack_Size      EQU     0x00000400

                AREA    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        Object

    0x20000000   0x08000350   0x00000001   Data   RW            3    .data               main.o
    0x20000001   0x08000351   0x00000007   PAD
    0x20000008        -       0x00000400   Zero   RW           29    STACK               startup_stm32f40xx.o
  1. 程序和SCT文件配合将变量ADC_REGPWM_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        Object

    0x60000000   0x08000320   0x00000010   Data   RW            3    .fpga_adc_reg       main.o


    Execution 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        Object

    0x60000010   0x08000330   0x00000010   Data   RW            4    .fpga_pwm_reg       main.o
  1. 修改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 ****
  1. MyUart.c文件中的RW和ZI变量,即uart_bauduart存放到段EX_RAM_DATA_UART,此变量有加载地址和执行地址
volatile const unsigned int uart_baud[2] = {9600,115200};
volatile unsigned char uart[16];
  1. MyGpio.c文件中的RW和ZI变量,即gpio_portgpio存放到段EX_RAM_DATA_GPIO,此变量有加载地址和执行地址
volatile const unsigned char gpio_port[2] = {1,2};
volatile unsigned char gpio[32];
  1. MyTest.c文件中的RW和ZI变量,即user通过attribute指令存放到段.my_data_usertest通过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        Object

    0x6000c000   0x08000340   0x00000008   Data   RW           39    .data               myuart.o
    0x6000c008        -       0x00000010   Zero   RW           38    .bss                myuart.o


    Execution 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        Object

    0x6000d000   0x08000348   0x00000002   Data   RW           59    .data               mygpio.o
    0x6000d002   0x0800034a   0x00000002   PAD
    0x6000d004        -       0x00000020   Zero   RW           58    .bss                mygpio.o


    Execution 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        Object

    0x6000e000   0x0800034c   0x0000000a   Data   RW           78    .my_data_user       mytest.o


    Execution 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        Object

    0x6000f000   0x08000358   0x00000014   Data   RW           77    .my_data_test       mytest.o
  1. 未在此段存放数据或代码,因此报了告警: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 ****
  1. 修改SCT文件划分出了片外Flash段,用于外接Flash设备的情况,可以将一些代码或者RO数据存放到片外Flash,能够灵活启动程序,比如从外部Flash启动程序,并且外部Flash可以做成可插拔替换的形式,那么只需更换外部Flash,就可以执行不同的程序,而无需重新烧写程序。片外Flash划分成两段使用,这是Part1
  • MyUart.c文件中所有RORO数据和Code都放在这个地址段0x08100000 ~ 0x08180000
  • MyGpio.c文件中所有RORO数据和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        Object

    0x08100000   0x08100000   0x00000024   Code   RO           57    i.gpio_test         mygpio.o
    0x08100024   0x08100024   0x00000020   Code   RO           37    i.uart_test         myuart.o
  1. 片外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        Object

    0x08180000   0x08180000   0x00000024   Code   RO           56    ex_flash_all_code   mygpio.o
    0x08180024   0x08180024   0x00000028   Code   RO           76    ex_flash_all_code   mytest.o
    0x0818004c   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)

在这里插入图片描述
在这里插入图片描述