This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Since there is nobody in StarterWare forum who is able to shed some light on this, and since it seems to be more of a compiler-related question I'll try to ask this here. I'm using following linker command file in my project:
-stack 0x00000008 /* SOFTWARE STACK SIZE */ -heap 0x04000000 /* HEAP AREA SIZE 64 MBytes */ -e Entry --diag_suppress=10063 MEMORY { DDR_MEM : org = 0x80000000 len = 0x7FFFFFF /* RAM */ IRAM_MEM : org = 0x40300000 len = 0x000FFFF /* RAM */ } SECTIONS { // for relocation GROUP { IRAM_CODE : { } IRAM_DATA : { } }load=DDR_MEM, run=IRAM_MEM, START(iram_start), SIZE(iram_size), RUN_START(relocstart) GROUP: load = 0x80000000 { .text:Entry : .text : /* CODE */ .data : /* INITIALIZED GLOBAL AND STATIC VARIABLES */ .const : /* GLOBAL CONSTANTS */ } .bss: load > DDR_MEM /* UNINITIALIZED OR ZERO INITIALIZED */ RUN_START(bss_start) RUN_END(bss_end) .sysmem: load > DDR_MEM .stack : load > 0x87FFFFF0 /* SOFTWARE SYSTEM STACK */ }
The GROUP section at the beginning is for some code that is relocated from DDR-RAM to CPU-internal RAM (AM3358 on BeagleBone Black). The heap is defined with a size of 64 MBytes. When I use the linker command file as shown above, the resulting .bin file has a size of about 64 MBytes while the whole code itself should be less than 200 kBytes. So it seems the whole heap memory is integrated in resulting binary.
This seems to be related with some relocation-pragmas within my code, as soon as I remove some statements like
#pragma CODE_SECTION(DMTimerIsr, "IRAM_CODE") #pragma DATA_SECTION(setStandbyFreq, "IRAM_DATA")
that are used to define code/data for CPU-internal RAM, the .bin file is no longer that huge.
Now when I keep these pragmas and replace
.sysmem: load > DDR_MEM
by
.const : load > DDR_MEM
within the used linker command file, I get a warning
warning #10247-D: creating output section ".sysmem" without a SECTIONS specification
but the problem is fixed, the resulting .bin file is no longer that unneccesary huge.
So...can anybody explain this behaviour? Why do the pragmas shown above influence this? And can I ignore the warning or should I add ".sysmem" to the file?
Thanks!
There is no industry standard for what a .bin file contains. My presumption is that it is the same as the .bin file you get when using the Linux command objcopy. If that presumption is wrong, then this entire post is wrong.
The following description comes from the man page for objcopy ...
When objcopy generates a raw binary file, it will essentially produce a memory dump of the contents of the input object file. All symbols and relocation information will be discarded. The memory dump will start at the load address of the lowest section copied into the output file.
The key thing to realize is that the size of the binary file is given by ...
address of the highest initialized memory location - address of the lowest initialized memory location
So every time an uninitialized section (.bss, .sysmem, and .stack) gets in between two or more initialized sections (all the rest), the size of the .bin file is larger than necessary. In your specific case, it seems the 64 megabyte .sysmem section is getting initialized sections on either side of it.
So, how might you fix this? I hesitate to recommend anything at this point. I need to understand more about why your link command file is written like that. Where does it come from?
Thanks and regards,
-George
While I am not the originator of this thread, I think the linker command structure came from the suggestions in Linker command file: Mark memory area behind code for usage?, which was an attempt to group all initialized sections in contiguous memory to minimize the size of the .bin file used to boot the target.George Mock said:I need to understand more about why your link command file is written like that. Where does it come from?
Chester Gillon said:While I am not the originator of this thread, I think the linker command structure came from the suggestions in Linker command file: Mark memory area behind code for usage?,
That's partially correct. The linker command file in this thread worked for some time until I added some more DATA_SECTION/CODE_SECTION pragmas. For the current version I could add .sysmem as very last to the command file to let it work...until I removed some of the DATA_SECTION/CODE_SECTION pragmas.
So it seems the whole thing does not really show a deterministic behaviour, means there seems to be no chance to really understand it...
I have repeated that problem by modifying the StarterWare game example and adding the linker command file and the DMTimerIsr / setStandbyFreq declarations with pragmas.Hans M��ller said:The heap is defined with a size of 64 MBytes. When I use the linker command file as shown above, the resulting .bin file has a size of about 64 MBytes while the whole code itself should be less than 200 kBytes. So it seems the whole heap memory is integrated in resulting binary.
However, I haven't yet worked a robust way of writing the linker command file to get the initialized sections adjacent in memory to reduce the .bin file size.
The warning #10247-D means the linker is choosing an arbitrary section to place the .sysmem section. If the linker choses the DDR_MEM section the program will run. If the linker choses a different section the program may fail. i.e. that warning means the program may fail unless you check the memory map, and so isn't a robust solution.Hans M��ller said:within the used linker command file, I get a warning
warning #10247-D: creating output section ".sysmem" without a SECTIONS specification
Chester Gillon said:I haven't yet worked a robust way of writing the linker command file to get the initialized sections adjacent in memory to reduce the .bin file size.
I have a suggestion. Normally, when I post a suggestion, I have a very high degree of confidence that it will work. Not just for the exact case at hand, but for lots of cases which might be similar. I know lots of folks find these threads with search, and act on what they find. I feel a debt of responsibility to all of them. I lack that confidence this time around. I'm going ahead anyway for two reasons. One, this thread has been going on a while. Two, I highly doubt a better suggestion is coming any time soon.
The idea is to apply the HIGH location specifier to all the uninitialized sections. Read about it in the section titled Controlling Allocation Using The HIGH Location Specifier in the ARM assembly manual. It might look like this ...
/* These lines inside the SECTIONS directive */ .bss > MEM (HIGH) .sysmem > MEM (HIGH) .stack > MEM (HIGH) .data > MEM (HIGH) /* EABI ONLY! */
The .data section is uninitialized in EABI builds. The .data section is not used by the compiler in COFF ABI builds. If it is used at all, it is an initialized section.
I know this works in straightforward command files. However, these StarterWare command files are a bit more complicated. That's why my confidence is reduced. I will try to get a StarterWare expert to comment on this thread.
Thanks and regards,
-George
I modified the linker command file for my example which previously showed the problem of the large bin file to be:George Mock said:The idea is to apply the HIGH location specifier to all the uninitialized sections.
-stack 0x0008 /* SOFTWARE STACK SIZE */ -heap 67108864 /* HEAP AREA SIZE */ -e Entry /* Since we used 'Entry' as the entry-point symbol the compiler issues a */ /* warning (#10063-D: entry-point symbol other than "_c_int00" specified: */ /* "Entry"). The CCS Version (5.1.0.08000) stops building from command */ /* line when there is a warning. So this warning is suppressed with the */ /* below flag. */ --diag_suppress=10063 /* SPECIFY THE SYSTEM MEMORY MAP */ MEMORY { DDR_MEM : org = 0x80000000 len = 0x7FFFFFF /* RAM */ IRAM_MEM : org = 0x40300000 len = 0x000FFFF /* RAM */ } /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */ SECTIONS { // for relocation GROUP { IRAM_CODE : { } IRAM_DATA : { } }load=DDR_MEM, run=IRAM_MEM, START(iram_start), SIZE(iram_size), RUN_START(relocstart) .text:Entry : load > 0x80000000 .text : load > DDR_MEM /* CODE */ .data : load > DDR_MEM /* INITIALIZED GLOBAL AND STATIC VARIABLES */ .bss : load > DDR_MEM(HIGH) /* UNINITIALIZED OR ZERO INITIALIZED */ /* GLOBAL & STATIC VARIABLES */ RUN_START(bss_start) RUN_END(bss_end) .const : load > DDR_MEM /* GLOBAL CONSTANTS */ .stack : load > 0x87FFFFF0 /* SOFTWARE SYSTEM STACK */ .sysmem: load > DDR_MEM(HIGH) }
With the changes to use DDR_MEM(HIGH) as suggested the size of the generated .bin file reduced from >64 Mbytes to 209 Kbytes. The linker command file shows that the initialized sections have been allocated consecutive addresses in DDR_RAM:
SEGMENT ALLOCATION MAP
run origin load origin length init length attrs members
---------- ----------- ---------- ----------- ----- -------
40300000 80033f90 00000018 00000018 r-x
40300000 80033f90 00000018 00000018 r-x IRAM_CODE
40300018 80033fa8 00000004 00000000 rw-
40300018 80033fa8 00000004 00000000 rw- IRAM_DATA
80000000 80000000 00033f90 00033f90 r-x
80000000 80000000 000000d4 000000d4 r-x .text:Entry
800000d4 800000d4 0002707e 0002707e r-- .const
80027154 80027154 0000ce3c 0000ce3c r-x .text
80033fac 80033fac 00000140 00000140 rw-
80033fac 80033fac 00000140 00000140 rw- .data
83ef4000 83ef4000 00109e10 00000000 rw-
83ef4000 83ef4000 00109e10 00000000 rw- .bss
83fffff0 83fffff0 04000008 00000000 rw-
83fffff0 83fffff0 04000000 00000000 rw- .sysmem
87fffff0 87fffff0 00000008 00000000 rw- .stack
Are you sure about that?George Mock said:The .data section is uninitialized in EABI builds.
The StarterWare game example used was set to EABI, and with TI ARM compiler 5.1.3 the .data section is shown as initialized in the Segment Alocation Map - and so to avoid a large .bin file size I had to use ".data : load > DDR_MEM" in the linker command file.
George Mock said:I will try to get a StarterWare expert to comment on this thread.
Also, the StarterWare linker command files set the size of the .stack segment to only 8 bytes. With the above modified the linker command file the .sysmem segment is adjacent to the .stack segment. Need to check if that will cause the stack to corrupt the .sysmem segment (heap). It would be useful if a StarterWare expert could also comment on how the stack is used. i.e. was the stack set to 8 bytes at the top of memory with the assumption that the stack would grow downwards and that there wouldn't be any other memory used below the initial stack location?
Hi,
The StarterWare stack section is placed at the top of memory and it will grow downwards. As you mentioned the assumption is that there wouldn't be any other memory below the initial stack location.
If you want to place other memory sections below stack you need to allocate proper size for stack as per your application requirement. so that stack wont grow in to other sections.
Regards
Baskaran