Adjusting heap and stack size

Hi.

I’m new with FREERTOS or with STM32 :slight_smile:
currently using STM32F767Z.

I’m using FREERTOS - 3 tasks.
task 1 - generate and send messages with SPI
task 2 - retransmitting the messages also with SPI
task 3 - reads from CAN and UART and updating one of the structs.

the code is using pvPortMalloc() and vPortFree() functions.
initializing a new array and allocating memory with pvPortMalloc
when I’m running with debug mode I get stuck on HardFault_Handler() due to memset function (my implementation- the function is ok) on the new array.
seems like bad memory allocation.
it happens before the tasks start to execute… (in the init section)

I did some digging on this issue and I understand I must adjust the tasks stacks and the total heap size.
I have enabled the USE_MALLOC_FAILED_HOOK option and added a breakpoint in the vApplicationMallocFailedHook function and the code stoped there

I tried to read the comments in the ioc file but I don’t understand how to do it right.

this is the RAM configuration

_Min_Heap_Size = 0x200; / required amount of heap /
_Min_Stack_Size = 0x400; / required amount of stack /

/ Memories definition /
MEMORY
{
*** RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K ***
*** FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K ***
}

using heap_4

this is the map file
MCU-MAP-FILE.zip (46.9 KB)

please help me :sweat:

Hi m-z,

if you wrote your memset() function yourself AND the fault reliably occurrs during your memset(), it should be easy for you to devise debugging strategies yourself!

What I would do is record source and target pointer to your memset() upon entry. I’m fairly certain that your memset() faults whenever the target pointer is corrupted (typically a 0 pointer due to a malloc() fail).

You should also add the minimum useful information (eg which port you use and which x in heap_x.c).

Using FreeRTOS heap_4 how much is configTOTAL_HEAP_SIZE and is it sufficient for the arrays you need to allocate ?

Hi,

thanks for the fast replay!
I think I wasn’t clear.

it is not related to the memset because when I’m disabling the memset function I get NULL from the pvPortMalloc() function and the code goes to the vApplicationMallocFailedHook() function.

I’m using heap_4.c
what do you mean with “port”?

configTOTAL_HEAP_SIZE = 30000 bytes (not sure if this is ok)

the arrays I’m allocating are not more then size 1000.
and also I implemented a linked list queue that uses pvPortMalloc for each node

The port is the portable layer dealing with/abstracting the actual MCU (core) and compiler you’re using.
I guess in your case it’s (Source/portable/GCC/)ARM_CM3 or Source/portable/GCC/ARM_CM4F when using FPU.

you mean this maybe?

Heap seems sufficient at the 1st place but maybe it isn’t.
Are you able to estimate the required amount of memory you allocate ?
When stopping in the failed hook on a breakpoint you can usually follow back the call stack to see which call with which arguments you came from with the debugger.
Try to step through init code to see that the linked list size and the number of arrays isn’t too big unexpectedly (due to programming bug).

No, you weren’t clear, and as far as I’m concerned, you still aren’t.

In your original post you wrote “I get stuck on HardFault_Handler() due to memset function (my implementation- the function is ok) on the new array.”

Now you write that your problem is NOT related to the call to memset() but reason that without the memset() your code ends in a valid code path?

Again, record all parameters to memset() upon entry, in particular check that the size you memset() to does not exceed the size you allocated.

@RAc He added to his OP

It seems to be an out-of-memory issue. memset set was probably just called with an (unchecked) NULL pointer from a failed pvPortMalloc.

So I think Cube (?) selected the right portable layer for you :wink:

1 Like

the code execute this line only and then goes to vApplicationMallocFailedHook() function:

sensor_info.prev_signals = pvPortMalloc( sensor_info.signals_len * sizeof( S_HOLDER ) );

explanation:
sensor_info.prev_signals - sensor_info is a struct
sensor_info.prev_signals - prev_signals is " S_HOLDER *prev_signals; "

typedef struct signal_holder{
int index;
long double value;
char binary_value[BINARY_VALUE_MAX_LEN];

} S_HOLDER;

sensor_info.signals_len = 254 (int)

is it may be because this is an array of structures?

Well, just do the math: How much is 254 * sizeof( S_HOLDER ) ?
That’s easy to calculate, right ? Especially what’s BINARY_VALUE_MAX_LEN ?

1 Like

sensor_info.signals_len = 254 (int)
sizeof( S_HOLDER ) = 272
BINARY_VALUE_MAX_LEN = 255

so …
254 * 272 = 69088
so I need to increase the heap size?
already tried that … didn’t work

What exactly doesn’t work ? It will work if the heap is big enough for ALL your allocations. Note there is more memory taken from heap e.g. the memory needed for the tasks itself including their stack.
Also each allocation usually needs a bit more memory than asked for required for heap internal buffer management.

ok, so I have 4 memory allocations on 4 different arrays.
let’s assume I’m calculating all 4 of them like we just did in the example above.

then I also have a linked list queue and I’m using pvPortMalloc for the new node each time I have to add a new SPI message to the queue.

I don’t know how many nodes will be created during run.
it depends on the SPI messages.
so it’s hard to calculate how much memory is taken from the heap in this case.

in summary:
I have 4 different arrays with different sizes - we can calculate their memory usage
I have linked list queue that I can calculate each node memory size but I can’t know how many nodes will be created.
and the memory needed for the tasks

Yes - you can estimate the statically needed amount of heap (if the arrays are static you could declare them static and don’t use the heap, but it doesn’t really matter. RAM is RAM, almost regardless from where it’s taken, data section or heap).
Sure, the dynamic memory requirements can be harder to estimate. But you need a certain idea to start with and then testing is required with the alloc failed hook enabled.
Then you know if it’s sufficient or not :wink:
Basically it has nothing to do with FreeRTOS. It’s just C (embedded) application programming.

1 Like

well, there’s nobody here who can help you with that question. It’s part of the project to calculate how much memory your system requires in total and then choose the hardware to provide that.

1 Like

@hs2 - thanks you for all the help and explanations :slight_smile:

@RAc -
thank you :slight_smile:
i appriciate the help