[应用相关] FAQ0086--AT32 Eclipse中实现分散加载的方法

[复制链接]
147|1
手机看帖
扫描二维码
随时随地手机跟帖
林堪堪|  楼主 | 2022-6-21 19:31 | 显示全部楼层 |阅读模式
本帖最后由 林堪堪 于 2022-6-23 19:49 编辑

Questions:如何在Eclipse中实现分散加载?


Answer:
修改脚本链接文件可以将某些函数和数据编排到特定的区域内。

1.        链接脚本文件一般是放在根目录下的ldscripts文件夹内,后缀为.ld。添加脚本链接文件的方法是“Project -> Properties -> C/C++ Build -> Setting -> Tool Settings -> “GNU ARM Cross C Linker” -> “General” -> 添加脚本链接文件。
image1.png

2.        修改脚本链接文件将某些函数和数据编排到特定的区域内,脚本链接文件可以使用记事本打开。以AT32F413xC(FLASH=256K,SRAM=32K)为例,其划分区块默认如下:
/* Specify the memory areas */
MEMORY
{
FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 256K
RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 32K
}

r代表read-only,x代表可执行代码,w代表read/write,ORIGIN是该区块的起始地址,LENGTH是该区块的大小。
如果需要将某些函数和数据编排到特定的FLASH区域内,则可以将FLASH划分为几个区域,以下是将FLASH划分为3个区域,可以将函数和数据编排到任意一个区域内。
/* Specify the memory areas */
MEMORY
{
FLASH_1 (rx)    : ORIGIN = 0x08000000, LENGTH = 128K
FLASH_2 (rx)    : ORIGIN = 0x08020000, LENGTH = 64K
FLASH_3 (rx)    : ORIGIN = 0x08030000, LENGTH = 64K
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 32K
}

比如需要把算法文件algorithm_1.c和algorithm_2.c内的函数和数据编排到FLASH_2区域内;把算法文件algorithm_3.c和algorithm_4.c内的函数和数据编排到FLASH_3区域内。则需要在SECTIONS添加设置,如下红色部分。完整的脚本链接文件请参考附录1。
/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH_1

  .algorithm_code1 :
  {
    . = ALIGN(4);
    *algorithm_1.o (.text .text*);
    *algorithm_2.o (.text .text*);
    . = ALIGN(4);
  } > FLASH_2  

  .algorithm_code2 :
  {
    . = ALIGN(4);
    *algorithm_3.o (.text .text*);
    *algorithm_4.o (.text .text*);
    . = ALIGN(4);
  } > FLASH_3

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)            /* .text sections (code) */
    *(.text*)           /* .text* sections (code) */
*(EXCLUDE_FILE (*algorithm_1.o * algorithm_2.o) .text .text*)
*(EXCLUDE_FILE (*algorithm_3.o * algorithm_4.o) .text .text*)
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH_1

1)        .algorithm_code1和.algorithm_code2是自行命名的 section 名称,用户在实际编写时可以自定义名称。 { } 包含的 .o 文件就是要放进section 内的代码,{  } 末尾的 > FLASH_2 就是将 .algorithm_code1 这个 section 指定到先前定义的 FLASH_2 区块。例如algorithm_1.o、algorithm_2.o就是 algorithm_1.c 、algorithm_2.c这两个 c 代码文档编译后的 object code, 写在这个c 文档里的函数和数据,就全部会被编排到此section 内。假设有10个函数,那 10 个函数就都会被放进来。
注意:
1)        .o 文件名前面都要加 * 号, 代表要将这个文件中的全部代码和数据都编排进来;
2)        .text 和 .text* 是可执行的代码;
3)        section 名称后的冒号与section 名称之间要加空格,如:.algorithm_ code1 :。
2)        将.text{ } section指定到FLASH_1 区块。一定要加入 EXECLUDE_FILE这个命令,使用 EXCLUDE_FILE标示的代码就不会被编排到FLASH_1,不然前面第1)点所作的设置就会失效。此区段内的*(.text)和 *(.text*), 就是告诉 linker 将EXCLUDE_FILE标示以外的代码都放到 .text 这个 section 内。
3.        对于AT32F403/AT32F413/AT32F403A/AT32F407等FLASH有零等待和非零等待的MCU,如果需要将某些函数和数据编排到零等待或者非零等待域内,则可以将FLASH划分为2个区域,如下是以AT32F413xC(FLASH=256K,SRAM=32K)为例,可以将函数和数据编排到任意一个区域内。
/* Specify the memory areas */
MEMORY
{
FLASH_ZW (rx)      : ORIGIN = 0x08000000, LENGTH = 96K
FLASH_NZW (rx)     : ORIGIN = 0x08018000, LENGTH = 160K
RAM (xrw)          : ORIGIN = 0x20000000, LENGTH = 32K
}

比如需要把对速率要求高的代码放到零等待,那么就可以将对速率要求不高的代码放到非零等待,留出零等待区存放对速率要求高的代码。比如将nzw_1.c和nzw_2.c内的函数和数据编排到FLASH_NZW区域内,则需要在SECTIONS添加设置,如下红色部分。完整的脚本链接文件请参考附录2。
/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH_ZW

  .nzw_code :
  {
    . = ALIGN(4);
    *nzw_1.o (.text .text*);
    *nzw_2.o (.text .text*);
    . = ALIGN(4);
  } > FLASH_NZW  

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)            /* .text sections (code) */
    *(.text*)           /* .text* sections (code) */
    *(EXCLUDE_FILE (*nzw_1.o * nzw_2.o) .text .text*)   
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH_ZW

1)        .nzw_code是自行命名的 section 名称,用户在实际编写时可以自定义名称。 { } 包含的 .o 文件就是要放进section 内的代码,{  } 末尾的 > FLASH_NZW就是将 .nzw_code这个 section 指定到先前定义的 FLASH_NZW区块。例如nzw_1.o、nzw_2.o就是 nzw_1.c 、nzw_2.c这两个 c 代码文档编译后的 object code, 写在这个c 文档里的函数和数据,就全部会被编排到此section 内。假设有10个函数,那 10 个函数就都会被放进来。
注意:
1)        .o 文件名前面都要加 * 号, 代表要将这个文件中的全部代码或数据都编排进来;
2)        .text 和 .text* 是可执行的代码;
3)        section 名称后的冒号与section 名称之间要加空格,如:.nzw_code :。
2)        将.text{ } section指定到FLASH_ZW 区块。一定要加入 EXECLUDE_FILE这个命令,使用 EXCLUDE_FILE标示的代码就不会被编排到FLASH_ZW,不然前面第 1)点所作的设置就会失效。此区段内的*(.text)和 *(.text*), 就是告诉 linker 将EXCLUDE_FILE标示以外的代码都放到 .text 这个 section 内。

附录1
/*
*****************************************************************************
**
**  File        : AT32F413xC_FLASH.ld
**
**  Abstract    : Linker script for AT32F413xC Device with
**                256KByte FLASH, 32KByte RAM
**
**                Set heap size, stack size and stack location according
**                to application requirements.
**
**                Set memory bank area and size if external memory is used.
**
**  Target      : Artery Tek AT32
**
**  Environment : Arm gcc toolchain
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20008000;    /* end of RAM */

/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
FLASH_1 (rx)    : ORIGIN = 0x08000000, LENGTH = 128K
FLASH_2 (rx)    : ORIGIN = 0x08020000, LENGTH = 64K
FLASH_3 (rx)    : ORIGIN = 0x08030000, LENGTH = 64K
RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 32K
}

/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH_1

  .algorithm_code1 :
  {
    . = ALIGN(4);
    *algorithm_1.o (.text .text*);
    *algorithm_2.o (.text .text*);
    . = ALIGN(4);
  } > FLASH_2  

  .algorithm_code2 :
  {
    . = ALIGN(4);
    *algorithm_3.o (.text .text*);
    *algorithm_4.o (.text .text*);
    . = ALIGN(4);
  } > FLASH_3  

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)            /* .text sections (code) */
    *(.text*)           /* .text* sections (code) */
    *(EXCLUDE_FILE (*algorithm_1.o *algorithm_2.o) .text .text*)
    *(EXCLUDE_FILE (*algorithm_3.o *algorithm_4.o) .text .text*)   
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH_1

  /* Constant data goes into FLASH */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */     
    . = ALIGN(4);
  } >FLASH_1

  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH_1
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH_1

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH_1

  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH_1

  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH_1

  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH_1

  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM



  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

附录2
/*
*****************************************************************************
**
**  File        : AT32F413xC_FLASH.ld
**
**  Abstract    : Linker script for AT32F413xC Device with
**                256KByte FLASH, 32KByte RAM
**
**                Set heap size, stack size and stack location according
**                to application requirements.
**
**                Set memory bank area and size if external memory is used.
**
**  Target      : Artery Tek AT32
**
**  Environment : Arm gcc toolchain
**
*****************************************************************************
*/

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20007FFF;    /* end of RAM */

/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
FLASH_ZW (rx)      : ORIGIN = 0x08000000, LENGTH = 96K
FLASH_NZW (rx)     : ORIGIN = 0x08018000, LENGTH = 160K
RAM (xrw)          : ORIGIN = 0x20000000, LENGTH = 32K
}

/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH_ZW

  .nzw_code :
  {
    . = ALIGN(4);
*nzw_1.o (.text .text*);
*nzw_2.o (.text .text*);
. = ALIGN(4);
  } > FLASH_NZW

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(EXCLUDE_FILE (*nzw_1.o *nzw_2.o) .text .text*)
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH_ZW

  /* Constant data goes into FLASH */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */  
    . = ALIGN(4);
  } >FLASH_ZW

  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH_ZW
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH_ZW

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH_ZW
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH_ZW
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH_ZW

  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH_ZW

  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM

  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}






FAQ0086_Eclipse中实现分散加载的方法_V2.0.0.pdf

511.46 KB

使用特权

评论回复
ufbycd| | 2022-6-21 21:41 | 显示全部楼层
分清下概念吧,GCC工具链这边不叫“分散加载”,而是叫链接, 这个链接配置文件叫做“链接脚本”。
另外,不用把.o文件写死是链接脚本里,这样不灵活。灵活的做法是:在源文件里把符号指定到一个段(section),然后在链接脚本里指明这个段的链接区域即可。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则