How to place program code in several memory regions? - c

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.

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)?

GCC some data outside sections

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?

Alignment in linker scripts

I am looking at trezor's bootloader linker script:
/* TREZORv2 bootloader linker script */
ENTRY(reset_handler)
MEMORY {
FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 128K
CCMRAM (wal) : ORIGIN = 0x10000000, LENGTH = 64K
SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K
}
main_stack_base = ORIGIN(CCMRAM) + LENGTH(CCMRAM); /* 8-byte aligned full descending stack */
/* used by the startup code to populate variables used by the C code */
data_lma = LOADADDR(.data);
data_vma = ADDR(.data);
data_size = SIZEOF(.data);
/* used by the startup code to wipe memory */
ccmram_start = ORIGIN(CCMRAM);
ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM);
/* used by the startup code to wipe memory */
sram_start = ORIGIN(SRAM);
sram_end = ORIGIN(SRAM) + LENGTH(SRAM);
_codelen = SIZEOF(.flash) + SIZEOF(.data);
SECTIONS {
.header : ALIGN(4) {
KEEP(*(.header));
} >FLASH AT>FLASH
.flash : ALIGN(512) {
KEEP(*(.vector_table));
. = ALIGN(4);
*(.text*);
. = ALIGN(4);
*(.rodata*);
. = ALIGN(512);
} >FLASH AT>FLASH
.data : ALIGN(4) {
*(.data*);
. = ALIGN(512);
} >CCMRAM AT>FLASH
.bss : ALIGN(4) {
*(.bss*);
. = ALIGN(4);
} >CCMRAM
.stack : ALIGN(8) {
. = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */
} >CCMRAM
}
It can be found here.
I understand that the code needs to be 32bit ( ALIGN(4) ) aligned, because the ARM processor can crash if it tries to access unaligned address, but I do not understand why the stack alignment is 8 bytes and furthermore why the hell do you need to waste(?) 512 bytes for alignment of the flash section?!
I would like to understand how the alignment is decided when writing a linker script.
Thank you in advance for your answers!
EDIT:
I think i answered my own question:
1. .flash section:
It is aligned like that, because the vector table, that is inside it always needs to be "32-word aligned". This can also be seen be the case in Trezor's boardloader linker script. As you can see the vector table is 512 byte (4 x 32-word) aligned.
2. .stack section:
According to ARM's own documentation the stack section needs to always be 8 byte aligned.
P.S. Of course if this is not the case, please correct me.
Okay, so since cooperised confirmed my theory I can now close this question.
1. .flash section:
It is aligned like that, because the vector table, that is inside it always needs to be "32-word aligned". This can also be seen be the case in Trezor's boardloader linker script. As you can see the vector table is 512 byte (4 x 32-word) aligned.
2. .stack section:
According to ARM's own documentation the stack section needs to always be 8 byte aligned.
Thank you cooperised for the confirmation!

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.

Can GNU LD print memory usage by memory space, rather then just as a bulk percentage?

I'm working on an embedded project on an ARM mcu that has a custom linker file with several different memory spaces:
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00200000
data_tcm (rw) : ORIGIN = 0x20000000, LENGTH = 0x00008000
prog_tcm (rwx) : ORIGIN = 0x00000000, LENGTH = 0x00008000
ram (rwx) : ORIGIN = 0x20400000, LENGTH = 0x00050000
sdram (rw) : ORIGIN = 0x70000000, LENGTH = 0x00200000
}
Specifically, I have a number of different memory devices with different characteristics (TCM, plain RAM (with a D-Cache in the way), and an external SDRAM), all mapped as part of the same address space.
I'm specifically placing different variables in the different memory spaces, depending on the requirements (am I DMA'ing into it, do I have cache-coherence issues, do I expect to overflow the D-cache, etc...).
If I exceed any one of the sections, I get a linker error. However, unless I do so, the linker only prints the memory usage as bulk percentage:
Program Memory Usage : 33608 bytes 1.6 % Full
Data Memory Usage : 2267792 bytes 91.1 % Full
Given that I have 3 actively used memory spaces, and I know for a fact that I'm using 100% of one of them (the SDRAM), it's kind of a useless output.
Is there any way to make the linker output the percentage of use for each memory space individually? Right now, I have to manually open the .map file, search for the section header, and then manually subtract the size from the total available memory specified in the .ld file.
While this is kind of a minor thing, it'd sure be nice to just have the linker do:
Program Memory Usage : 33608 bytes 1.6 % Full
Data Memory Usage : 2267792 bytes 91.1 % Full
data_dtcm : xxx bytes xx % Full
ram : xxx bytes xx % Full
sdram : xxx bytes xx % Full
This is with GCC-ARM, and therefore GCC-LD.
Arrrgh, so of course, I find the answer right after asking the question:
--print-memory-usage
Used as -Wl,--print-memory-usage, you get the following:
Memory region Used Size Region Size %age Used
rom: 31284 B 2 MB 1.49%
data_tcm: 26224 B 32 KB 80.03%
prog_tcm: 0 GB 32 KB 0.00%
ram: 146744 B 320 KB 44.78%
sdram: 2 MB 2 MB 100.00%

Resources