FreeRTOS allocation error - c

I am using FreeRTOS V6.1.1 on a STM32F107VC and get frequent malloc errors. The heap area is defined in the linker script but it keeps getting stuck in this loop of pvPortMalloc() after a few allocations:
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
{
pxPreviousBlock = pxBlock;
pxBlock = pxBlock->pxNextFreeBlock;
}
pxBlock: 0x20002300
pxPreviousBlock: 0x20002300
pxNewBlockLink: 0x00
xHeapHasBeenInitialised: 0x01
linker script:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20010000; /* end of 64K RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = 0x200; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
}
...
How can this be?

This was probably caused by fragmentation in heap_2.c. Even though the allocations were pretty small, the behaviour was consistent. Using heap_4.c solved it.

Related

Tell the linker to avoid a region

Esteemed Colleagues!
If I want the linker to not place anything into an area of memory, I can simply omit the region from the "MEMORY" section in the linker script file. I could also put a comment in there to make it clear what I'm doing. Perhaps like this:
MEMORY
{
...
good_one : ORIGIN = 0x00400000, LENGTH = 0x00010000 /* 64 kiB */
/* Avoid the "special" area 0x00410000 -> 0x00480000 */
good_two : ORIGIN = 0x00480000, LENGTH = 0x00010000 /* 64 kiB */
...
}
Instead, is there a way that I could define a memory region, but attach attributes to it to keep the linker from placing anything in there? Perhaps like this:
MEMORY
{
...
good_one : ORIGIN = 0x00400000, LENGTH = 0x00010000 /* 64 kiB */
avoid (!rwiax) : ORIGIN = 0x00410000, LENGTH = 0x00070000 /* 448 kiB */
good_two : ORIGIN = 0x00480000, LENGTH = 0x00010000 /* 64 kiB */
...
}
Could I also create some symbols (and "KEEP" them) in the linker script file that would show up in the ELF to clearly indicate what is going on? Perhaps like this:
SECTIONS
{
...
avoid 0x00410000 (NOLOAD) :
{
_avoid_region_start = . ; /* KEEP() ??? */
. = . + 0x00070000 ;
_avoid_region_end = . ; /* KEEP() ??? */
} > avoid ;
...
I'm using a wide variety of GNU "ld" versions (from 2.20.51 through 2.36.1), cross-compiling to a broad set of target architectures (riscv32/64, aarch32/64, etc...), if that matters...

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.

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!

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