GCC some data outside sections - c

This is my linker file memory definition (Cortex M4 MCU with flash memory starting at 0x0 address):
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x0000A000, LENGTH = 0x00000410
m_text (RX) : ORIGIN = 0x0000A410, LENGTH = 0x00050BF0
m_data (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001F000
m_data_2 (RW) : ORIGIN = 0x2000F000, LENGTH = 0x00001000
}
I want to offset my flash from 0x0 to 0xA000 to keep the beginning of the flash clean.
However, when I generate my output (bin) file for my project, I can see the beginning of the flash is still occupied by some data. From .map file I think this is .ARM.attributes, .debug_info, .debug_abbrev, etc. I don't know what it is, but I want the beginning of my flash to be clean, not programmed by anything. How to remove these data from my output bin file or how to move this data to the end of the output bin file?

Related

Linker with overlapping memory definitions

I made an ld script with the following memory layout:
MEMORY
{
FLASH (rx) : ORIGIN = 0x00027000, LENGTH = 0xC8000
RAM (rwx) : ORIGIN = 0x20003FC0, LENGTH = 0x3B040
RRAM (rwx) : ORIGIN = 0x2000F000, LENGTH = 0x01000
}
As you can see, the RRAM (from 0x2000F000 to 0x2000FFFF) portion overlaps with the RAM portion (from 0x20003FC0 to 0x2002FFF). The code compiles and links with no warnings or errors.
My question is: during normal code execution,.will the system still be able to use the memory from 0x2001000 up to 0x2002FFF? Or does this unusual layout stop the code from using anything after the end of RRAM (unless explicitly allocated to an address)?

How to place program code in several memory regions?

There are several memory regions
MEMORY
{
rom1 (rx) : ORIGIN = 0x00000000, LENGTH = 256k
rom2 (rwx) : ORIGIN = 0x10000000, LENGTH = 16M
ram1 (rw!x) : ORIGIN = 0x20000000, LENGTH = 64k
ram2 (rwx) : ORIGIN = 0x21000000, LENGTH = 16M
}
How to place .text sections of all input files in the memory area of rom1, and if there is not enough space, then the remaining characters to place in rom2? Only one memory region can be specified in the description of the output section.
.text :
{
*(.text)
} > rom1
As far as I know, there is no way to distribute a section over several non-contiguous memory regions.
As suggested here, the section should be divided into several sections and then assigned to the memory regions.
In general this is a very handy documentation about the different possibilities.

AVR-GCC Linker: "Data"-Section overflows

I am using the Atmel AVR-GCC for compiling a project based on Atmel's Zigbee Bitcloud. On the Atmega256rfr2( 256k Flash, 32k RAM)
After adding more code, I am approaching the limit of the memory (seems like it).
I figured out, that if the linker added too much to the "data-section", it leads to unpredictable behaviour of the program. The problem is the linker does not help me to find this point. So I am struggling to find a stable solution.
I am using the following linker file provided by Atmel:
OUTPUT_FORMAT("elf32-avr")
OUTPUT_ARCH(avr:6)
MEMORY
{
text (rx) : ORIGIN = 0x00000000, LENGTH = 256K
boot (rx) : ORIGIN = 0x0003F000, LENGTH = 4K
access (rx) : ORIGIN = 0x0003FFF0, LENGTH = 16
data (rw!x) : ORIGIN = 0x00800200, LENGTH = 32K - 500 /* leave 500 bytes for stack */
eeprom (rw!x) : ORIGIN = 0x00810000, LENGTH = 8K
}
SECTIONS
{
.text :
{
PROVIDE(__text_start = .);
*(.vectors)
KEEP(*(.vectors))
. = ALIGN(0x400);
/* PDS NV memory section */
PROVIDE(__d_nv_mem_start = .);
. = ALIGN(0x4400);
PROVIDE(__d_nv_mem_end = .);
/* Non-volatile file system PDS_FF section */
PROVIDE(__pds_ff_start = .);
KEEP(*(.pds_ff))
PROVIDE(__pds_ff_end = .);
/* Non-volatile file system PDS_FD section */
PROVIDE(__pds_fd_start = .);
KEEP(*(.pds_fd))
PROVIDE(__pds_fd_end = .);
*(.progmem.gcc*)
*(.progmem*)
. = ALIGN(2);
*(.trampolines*)
*(.jumptables*)
*(.lowtext*)
*(.init0)
KEEP (*(.init0))
*(.init1)
KEEP (*(.init1))
*(.init2)
KEEP (*(.init2))
*(.init3)
KEEP (*(.init3))
*(.init4)
KEEP (*(.init4))
*(.init5)
KEEP (*(.init5))
*(.init6)
KEEP (*(.init6))
*(.init7)
KEEP (*(.init7))
*(.init8)
KEEP (*(.init8))
*(.text.main)
KEEP (*(.text*main))
*(.text)
*(.text.*)
PROVIDE(__text_end = .);
} > text
.data : AT (ADDR(.text) + SIZEOF(.text))
{
PROVIDE(__data_start = .);
*(.data*)
*(.rodata*)
*(.gnu.linkonce.d*)
. = ALIGN(2);
PROVIDE(__data_end = .);
} > data
.bss __data_end :
{
PROVIDE(__bss_start = .);
*(.bss*)
*(COMMON)
PROVIDE(__bss_end = .);
} > data
.noinit __bss_end :
{
*(.noinit*)
PROVIDE(__heap_start = .);
} > data
__stack_start = .;
__data_load_start = LOADADDR(.data);
__data_load_end = __data_load_start + SIZEOF(.data);
.access_section :
{
KEEP(*(.access_section*))
*(.access_section*)
} > access
.boot_section :
{
*(.boot_section*)
} > boot
.eeprom :
{
FILL(0xff)
BYTE(0xff)
. = . + LENGTH(eeprom)-1;
} > eeprom
/DISCARD/ :
{
*(.init9)
*(.fini9)
}
}
I managed to figure out at which amount of data the code is definitely not working any more and until which amount I do not have an obvious malfunction.
The program is working for a size output of:
text data bss dec hex filename
210260 10914 25427 246601 3c349 (TOTALS)
avr-gcc-size -A:
section size addr
.data 2722 8389120
.text 209468 0
.bss 25426 8391842
.noinit 1 8417268
.access_section 4 262128
.boot_section 798 258048
.eeprom 8192 8454144
.debug_info 538541 0
.debug_abbrev 46706 0
.debug_loc 73227 0
.debug_aranges 5704 0
.debug_ranges 6032 0
.debug_line 108276 0
.debug_str 89073 0
.comment 92 0
.debug_frame 14252 0
Total 1128514
I have obvious malfunction at a size of:
210260 10918 25427 246605 3c34d (TOTALS)
Increasing only the text, but not the data, does not lead to any though:
210270 10914 25427 246611 3c353 (TOTALS)
Does anyone has an idea, why the program fails at this point? And how can I predict the limit in the future or make the linker give me a warning, when this might happen?
I do not get any linker error message or Warning. The program just crashes at this point.
Everything in the .data section takes up Flash and RAM. The part in Flash is used to initialize the part in RAM. You're probably running out of RAM. So my suggestion is to mark as much as possible as const. Doing that thing will be moved into the .text segment, where it occupies just Flash and leaves RAM for better things.
There's some serious misconceptions going on here.
0x00800200, LENGTH = 32K - 500. 200h is not the same as 500, but the same as 512. Also, 0x00810000 - 0x00800000 is not 32k but 64kib. There are lots of such errors all over, whoever setup this linker file didn't quite know what they were doing and they didn't know hexadecimal numbers.
"The Program is working for a size output of..." 10914 + 25427 = 36341 bytes. How can it work fine, you just said that you have 32kib of physical RAM available on the chip. And you also reserve 512 bytes for the stack. It does not work fine, it might seem to work for now, by pure chance.
If you think that your program can work fine when you allocate more memory than what is physically available, there is no hope for you to ever recover this program. Memory cannot be allocated in thin air. Similarly, you cannot have RW sections that are larger than 256k added together unless there's some special boot area ROM on this chip.
The reason why you don't get any linker warnings might be because you have told the linker that you have 64kib available, while the physical chip only got 32kib.
Your bss+data sections (both probably go to data region) exceed your data region for few kB.
Probably due to some random behavior, you write over your stack at some point, which crashes your program.
Linker should warn you if section does not fit the region.
I think only way to be sure no issues will occur is to extend data region (if yor board has more RAM), or decrease size of your initialized + uninitialized data.
Or maybe some of your initialized data goes to eprom region, and only after you add few bytes you overflow data. To be sure use avr-something-size -A yourexecutable, which should show more detail.

Send variable to linker via source code

In some header I've got FLASH_BASE and FLASH_SIZE makro and I would like to use them in linker script. I have tried something like this:
// main.c
long CURRENT_FLASH_START = FLASH_BASE + FLASH_SIZE / 2;
int main(void) {
return 0;
}
// s_FLASH.ld
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
RAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 16K
FLASH (rx) : ORIGIN = CURRENT_FLASH_START, LENGTH = 256K
}
But in map file I see that place for code in flash starts at address 0. Is there any possibilty to use variable from makro (from .h file) in linker script file? I use Ac6 STM32 MCU GCC with Gnu Make builder.

Why won't debug linker file compile (ld:200 cannot move location counter backwards)

Now before you you tell me my program is using too much memory...
I know what "cannot move location counter backwards means"...
here is the real problem...
I have a linker file that WILL compile no problem.
call this linker file release version....
MEMORY
{
/* SOFTCONSOLE FLASH USE: microsemi-smartfusion2-envm */
rom (rx) : ORIGIN = 0x20000000, LENGTH = 35k
/* SmartFusion2 internal eSRAM */
ram (rwx) : ORIGIN = 0x20008C00, LENGTH = 29k
}
RAM_START_ADDRESS = 0x20008C00; /* Must be the same value MEMORY region ram ORIGIN above. */
RAM_SIZE = 29k; /* Must be the same value MEMORY region ram LENGTH above. */
MAIN_STACK_SIZE = 11k; /* Cortex main stack size. */
MIN_SIZE_HEAP = 512; /* needs to be calculated for your application */
notice the entire space occupied is 64k... this compiles
but when I try to use the following linker file (debug); I get the location counter error
MEMORY
{
/* SmartFusion2 internal eSRAM */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64k
}
RAM_START_ADDRESS = 0x20000000; /* Must be the same value MEMORY region ram ORIGIN above. */
RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
MAIN_STACK_SIZE = 11k; /* Cortex main stack size. */
MIN_SIZE_HEAP = 512; /* needs to be calculated for your application */
THE ONLY differences between the two linker files are show plus anywhere there is a >rom or >ram AT>rom directive in the release version, it is replace by >ram in the debug version...
I am using the same exact optimize and debugging flags
When I try to link the debug version i get the following error
ld:200 cannot move location counter backwards (from 20011d80 to 2000d400)
Anyone have any ideas???

Resources