??????? 最近在调试低功耗,需要修改变量的分配地址,所以研究了一下。研究过程中学习了一下ld文件的规则,参考了以下文章:
LD 文件:规则详解_申小白-CSDN博客_ld文件
STM32 .ld链接文件分析及一次bug解决过程 - 回归的世界线 - 博客园
第一种 修改变量默认的分配地址到SRAM2
??????? 举例,定义了变量a,代码为:int a;? 修改后,此变量会被定义到 SRAM2。
????????STM32L475VE有两块内部SRAM,SRAM2的起始地址在? 0x10000000,大小为32k;SRAM1的起始地址在 0x20000000,大小为96k;全计128k。其中SRAM2在低功耗模式下是可以实现不掉电的,即内容不丢失。默认情况下,变量是分配在SRAM1,这个是由ld链接文件决定的。可以通过修改ld链接文件重新定义变量的分配区域。
ld文件的全文如下:
?//***************************************** ld 文件开始************************************************//
/* ***************************************************************************** **
**? File??????? : stm32_flash.ld ** **? Author?? ??? ?: Auto-generated by TrueSTUDIO for STM32 ** **? Abstract??? : Linker script for STM32L475VE Device with **??????????????? 512KByte FLASH, 128KByte 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????? : STMicroelectronics STM32 ** **? Distribution: The file is distributed as is, without any warranty **??????????????? of any kind. ** ***************************************************************************** ** @attention ** ** <h2><center>© COPYRIGHT(c) 2019 STMicroelectronics</center></h2> ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: **?? 1. Redistributions of source code must retain the above copyright notice, **????? this list of conditions and the following disclaimer. **?? 2. Redistributions in binary form must reproduce the above copyright notice, **????? this list of conditions and the following disclaimer in the documentation **????? and/or other materials provided with the distribution. **?? 3. Neither the name of STMicroelectronics nor the names of its contributors **????? may be used to endorse or promote products derived from this software **????? without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ***************************************************************************** */
/* Entry Point */ ENTRY(Reset_Handler)
/* Highest address of the user mode stack */ _estack = 0x20018000;??? /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x800;????? /* required amount of heap? */ _Min_Stack_Size = 0xC00; /* required amount of stack */
/* Specify the memory areas */ MEMORY { RAM (xrw)????? : ORIGIN = 0x20000000, LENGTH = 96K RAM2 (xrw)????? : ORIGIN = 0x10000000, LENGTH = 32K FLASH (rx)????? : ORIGIN = 0x0800C000, LENGTH = 464K??? /* 此处修改了地址,flash地址前部分面用于bootload*/ }
/* Define output sections */ SECTIONS { ? /* The startup code goes first into FLASH */ ? .isr_vector : ? { ??? . = ALIGN(4); ??? KEEP(*(.isr_vector)) /* Startup code */ ??? . = ALIGN(4); ? } >FLASH
? /* The program code and other data goes into FLASH */ ? .text : ? { ??? . = ALIGN(4); ??? *(.text)?????????? /* .text sections (code) */ ??? *(.text*)????????? /* .text* sections (code) */ ??? *(.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
? /* Constant data goes into FLASH */ ? .rodata : ? { ??? . = ALIGN(4); ??? *(.rodata)???????? /* .rodata sections (constants, strings, etc.) */ ??? *(.rodata*)??????? /* .rodata* sections (constants, strings, etc.) */ ??? . = ALIGN(4); ? } >FLASH
? .ARM.extab?? : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH ? .ARM : { ??? __exidx_start = .; ??? *(.ARM.exidx*) ??? __exidx_end = .; ? } >FLASH
? .preinit_array???? : ? { ??? PROVIDE_HIDDEN (__preinit_array_start = .); ??? KEEP (*(.preinit_array*)) ??? PROVIDE_HIDDEN (__preinit_array_end = .); ? } >FLASH ? .init_array : ? { ??? PROVIDE_HIDDEN (__init_array_start = .); ??? KEEP (*(SORT(.init_array.*))) ??? KEEP (*(.init_array*)) ??? PROVIDE_HIDDEN (__init_array_end = .); ? } >FLASH ? .fini_array : ? { ??? PROVIDE_HIDDEN (__fini_array_start = .); ??? KEEP (*(SORT(.fini_array.*))) ??? KEEP (*(.fini_array*)) ??? PROVIDE_HIDDEN (__fini_array_end = .); ? } >FLASH
? /* 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
? ? /* 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) } }
//***************************************** ld 文件结束************************************************//
??????? 其中 MEMORY 关键定定义了内存的地址情况,其中有RAM,RAM2和FLASH,我们需要做的是将全部变量定义到RAM2,只需要将.data段,.bss段的地址修改为RAM2即可,如下:
/* 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 */ ? } >RAM2 AT> FLASH
? ? /* 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; ? } >RAM2
??????? 这里没有把._user_heap_stack 分配到RAM2,在我修改时编译会报错,应该是由于ld文件中的第二行代码没有改造成的: _estack = 0x20018000; ? ? 0x20018000属于RAM1区域,在.s文件中
_estack 会被赋值给 sp指针。
第二种 强制个别变量的地址到SRAM1
??????? 当变量默认的分配地址被修改到 SRAM2 区域后,代码中个别的变量需要定义到 SRAM1,按照以下方法可以实现。
??????? 按照上面第一种,通常全局变量是被定义在 .data 段的,我们可以新建出一个名为 ram1_data? 的数据段
??? /* ram1_data section,? 自定义的 ram1_data 段,*/ ? .ram1_data : ? { ??? . = ALIGN(4); ??? __RAM1DATA_START_SYMBOLS = .; ??? *(.ram1_data) ??? *(.ram1_data*) ??? . = ALIGN(4); ??? __RAM1DATA_END_SYMBOLS = .; ? } >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
??????? 然后就可以在源程序中使用这个 ram1_data? 段,如下定义变量:
????????char IOT_SendBuff[IOT_SEND_BUFF_SIZE] __attribute__((section(".ram1_data")));
??????? 以上代码是定义了一个 IOT_SendBuff数组,且分配到 ram1_data 段,而ram1_data段是被定义在SRAM1(即上面的RAM),所以 SendBuff 是定义在 SRAM1 的。如下图可以看到:
需要注意到变量 IOT_SendBuff 定义时是没有初始化的,所以和 .bss 段无关,当需要初始化时,bss段怎么处理需要后期再测试。
|