cancel
Showing results for 
Search instead for 
Did you mean: 

Big binary file, after moving code to different memory regions.

ChrisH
Associate III
Posted on December 06, 2017 at 07:39

Hi, after I moved my .bss and .data sections to SRAM2 on L476 my binary file blows into 400mb I know this question was raised here before but I still don't understand in my example why is this happening in this case. In my case, I place all the buffers and heap and stack in SRAM1 so, in reality, this is all uninitialized data which is later initialized to 0 in startup code. Why is it referenced anyway in a binary file? Also if I define sections like so placing them in:

RAM AT>FLASH

code links into small binary, but I guess it's not allowed since this is reservedfor variables initialised with constant data from flash.

/*
*****************************************************************************
**
** File : LinkerScript.ld
**
** Abstract : Linker script for STM32L476RGTx Device with
** 1024KByte FLASH, 96KByte 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>&copy; COPYRIGHT(c) 2014 Ac6</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 Ac6 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 = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
RAM2BLVAR (xrw): ORIGIN = 0x10000000, LENGTH = 0x20
RAM2 (xrw) : ORIGIN = 0x10000020, LENGTH = 0x7FE0
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1020K
VERSION(rx): ORIGIN = 0x808F000,LENGTH = 2K
CONFIG (xrw): ORIGIN = 0x808F800, LENGTH = 2K
}
/* Define output sections */
SECTIONS
{
 /* The startup code goes first into FLASH */
 .isr_vector :
 {
 . = ALIGN(8);
 KEEP(*(.isr_vector)) /* Startup code */
 . = ALIGN(8);
 } >FLASH
 /* The program code and other data goes into FLASH */
 .text :
 {
 . = ALIGN(8);
 *(.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(8);
 _etext = .; /* define a global symbols at end of code */
 } >FLASH
 /* Constant data goes into FLASH */
 .rodata :
 {
 . = ALIGN(8);
 *(.rodata) /* .rodata sections (constants, strings, etc.) */
 *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
 . = ALIGN(8);
 } >FLASH
 .ARM.extab :
 {
 . = ALIGN(8);
 *(.ARM.extab* .gnu.linkonce.armextab.*)
 . = ALIGN(8);
 } >FLASH
 .ARM : {
. = ALIGN(8);
 __exidx_start = .;
 *(.ARM.exidx*)
 __exidx_end = .;
. = ALIGN(8);
 } >FLASH
 .preinit_array :
 {
. = ALIGN(8);
 PROVIDE_HIDDEN (__preinit_array_start = .);
 KEEP (*(.preinit_array*))
 PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(8);
 } >FLASH
 .init_array :
 {
. = ALIGN(8);
 PROVIDE_HIDDEN (__init_array_start = .);
 KEEP (*(SORT(.init_array.*)))
 KEEP (*(.init_array*))
 PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(8);
 } >FLASH
 .fini_array :
 {
. = ALIGN(8);
 PROVIDE_HIDDEN (__fini_array_start = .);
 KEEP (*(SORT(.fini_array.*)))
 KEEP (*(.fini_array*))
 PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(8);
 } >FLASH
 /* placing my named section at given address: */
 .verSection :
 {
 KEEP(*(.verSection)) /* keep my variable even if not referenced */
 } > VERSION
 /* used by the startup to initialize data */
 _sidata = LOADADDR(.data);
 /* Initialized data sections goes into RAM, load LMA copy after code */
 .data :
 {
 . = ALIGN(8);
 _sdata = .; /* create a global symbol at data start */
 *(.data) /* .data sections */
 *(.data*) /* .data* sections */
 . = ALIGN(8);
 _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
 /* RTOS Heap goes into RAM */
 .rtosHeap :
 {
 . = ALIGN(4);
 _srtosHeap = .;
 __rtosHeap_start__ = _srtosHeap;
 *(.rtosHeap)
 *(.rtosHeap*)
 . = ALIGN(4);
 _ertosHeap = .;
 __rtosHeap_end__ = _ertosHeap;
 } >RAM
 .ramSection :
 {
 . = ALIGN(4);
 _sramSection = .;
 __ramSection_start__ = _sramSection;
 *(.ramSection)
 *(.ramSection*)
 . = ALIGN(4);
 _eramSection = .;
 __ramSection_end__ = _eramSection;
 } >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) }
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

1 ACCEPTED SOLUTION

Accepted Solutions
AVI-crak
Senior
Posted on December 06, 2017 at 13:58

GCC collects the file for the programmer in * .elf format. This is a data data container with precise instructions for programming the chip. There can be used areas of memory with large steps and small size, for example flash microprocessor and an external flash. Binary data areas that have addresses that are not available to the programmer will be ignored. The total size of the firmware in * .elf format will be slightly larger than the sum of the two areas. But a simple binary format * .bin does not have a markup for writing to the required addresses. It does not contain any additional information at all - just data. For this reason, the binary format * .bin fills all the spaces between sections with zeros, the physical size is huge. For example, using the external 25q64 makes 2 gigabytes of * .bin firmware.

Solution: use the compiler settings to create the firmware in * .elf format. Use additional commands to extract a binary file from * .elf format - for the possibility of separate programming, or encryption.

Example.

arm-none-eabi-objcopy -O binary -j .section_name filename.elf sw.bin

Hint:

Sections that do not require memory can have a boot prohibition label.

.bss (NOLOAD):

View solution in original post

8 REPLIES 8
Uwe Bonnes
Principal II
Posted on December 06, 2017 at 13:02

If you have gaps in the memory map, a binary file must fill these gaps. So the size is normal, however inconveniant.

AVI-crak
Senior
Posted on December 06, 2017 at 13:58

GCC collects the file for the programmer in * .elf format. This is a data data container with precise instructions for programming the chip. There can be used areas of memory with large steps and small size, for example flash microprocessor and an external flash. Binary data areas that have addresses that are not available to the programmer will be ignored. The total size of the firmware in * .elf format will be slightly larger than the sum of the two areas. But a simple binary format * .bin does not have a markup for writing to the required addresses. It does not contain any additional information at all - just data. For this reason, the binary format * .bin fills all the spaces between sections with zeros, the physical size is huge. For example, using the external 25q64 makes 2 gigabytes of * .bin firmware.

Solution: use the compiler settings to create the firmware in * .elf format. Use additional commands to extract a binary file from * .elf format - for the possibility of separate programming, or encryption.

Example.

arm-none-eabi-objcopy -O binary -j .section_name filename.elf sw.bin

Hint:

Sections that do not require memory can have a boot prohibition label.

.bss (NOLOAD):
Posted on December 07, 2017 at 18:13

Thanks a lot, one more question if why arm-none-eabi-size would report .bsssection as that big:

 text data bss dec hexfilename
 182736 3190 100168 286094 45d8exxxxxx.elf�?�?

while in reality it's much smaller as reported from elf header...

Section Headers:
 [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
 [ 0] NULL 00000000 000000 000000 00 0 0 0
 [ 1] .isr_vector PROGBITS 08000000 010000 000188 00 A 0 0 1
 [ 2] .text PROGBITS 080001c0 0101c0 029fe8 00 AX 0 0 64
 [ 3] .rodata PROGBITS 0802a1a8 03a1a8 002858 00 A 0 0 8
 [ 4] .ARM.extab PROGBITS 0802ca00 04f006 000000 00 W 0 0 1
 [ 5] .ARM ARM_EXIDX 0802ca00 03ca00 000008 00 AL 2 0 4
 [ 6] .preinit_array PREINIT_ARRAY 0802ca08 04f006 000000 00 WA 0 0 1
 [ 7] .init_array INIT_ARRAY 0802ca08 03ca08 000008 00 WA 0 0 4
 [ 8] .fini_array FINI_ARRAY 0802ca10 03ca10 000008 00 WA 0 0 4
 [ 9] .verSection PROGBITS 0808f000 04f000 000006 00 WA 0 0 4
 [10] .data PROGBITS 10000020 040020 000c60 00 WA 0 0 8
 [11] .bss NOBITS 10000c80 040c80 002b30 00 WA 0 0 4
 [12] .rtosHeap NOBITS 20000000 050000 00fa00 00 WA 0 0 4
 [13] .ramSection NOBITS 2000fa00 050000 005c18 00 WA 0 0 8
 [14] ._user_heap_stack NOBITS 20015618 050000 000600 00 WA 0 0 1
 [15] .ARM.attributes ARM_ATTRIBUTES 00000000 04f006 000030 00 0 0 1
 [16] .debug_frame PROGBITS 00000000 04f038 00f36c 00 0 0 4
 [17] .debug_info PROGBITS 00000000 05e3a4 07208e 00 0 0 1
 [18] .debug_abbrev PROGBITS 00000000 0d0432 00cf65 00 0 0 1
 [19] .debug_loc PROGBITS 00000000 0dd397 0349dd 00 0 0 1
 [20] .debug_aranges PROGBITS 00000000 111d78 003e58 00 0 0 8
 [21] .debug_ranges PROGBITS 00000000 115bd0 003a48 00 0 0 8
 [22] .debug_macro PROGBITS 00000000 119618 047bbd 00 0 0 1
 [23] .debug_line PROGBITS 00000000 1611d5 05d4c9 00 0 0 1
 [24] .debug_str PROGBITS 00000000 1be69e 118891 01 MS 0 0 1
 [25] .comment PROGBITS 00000000 2d6f2f 00006e 01 MS 0 0 1
 [26] .shstrtab STRTAB 00000000 2ed9bc 000137 00 0 0 1
 [27] .symtab SYMTAB 00000000 2d6fa0 0103d0 10 28 3047 4
 [28] .strtab STRTAB 00000000 2e7370 00664c 00 0 0 1�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Posted on December 08, 2017 at 15:24

The GCC log line is a simplified message. GCC does not list all available sections, but collects data by groups.

DATA - all sections requiring memory and preset.

BSS - all sections requiring memory.

Sections that do not require memory clearing, but explicitly use the address in memory, are not counted in the log. For this reason, it is undesirable to take seriously the GCC control line of the log.

Jack Peacock
Associate II
Posted on December 09, 2017 at 03:39

Your LD file isn't distinguishing between flash and SRAM as far as output is concerned.  For the sections which do not go to flash add the NOLOAD option:

.bss (NOLOAD) :

This excludes the SRAM regions from what will be downloaded to flash.

  Jack Peacock

S.Ma
Principal
Posted on December 09, 2017 at 12:32

A binary file is just a contiguous memory data file (bin file)

A S19/HEX file is a collection of slide of data anywhere in the memory space (text file)

Don't know if you can spilt your bin file and prevent erasing when programming with the second one...

Posted on December 09, 2017 at 15:11

The BSS typically contains some data that is initialized, and the rest is zeroed out, the linker should accumulate the data at the front.

The .ELF file has two size fields, one describes the size of the region, the other describes the size of data in the file, which can be smaller.

As another note, Keil's FromELF can output .BIN files, and can split multiple sparse regions into unique .BIN files under different directories.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 09, 2017 at 15:14

Keil's FromELF splits multi-section files into multiple .BIN files. There might have been a post here, or on Keil's forum, where someone used an AT directive that created .BIN files in subdirectories which they didn't expect.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..