Freertos memory managment

dinohammer wrote on Friday, May 03, 2019:

Hello!
I have a fairly large project regarding freertos and microcontrollers, and we are using the arduino mega 2560 for this project.

But regarding the size of the project(its not as big now as it will be in the future), how can i best controll memory and not get the stackoverflow?

Have searched the web and cant find any good ideas of how to best manage memory.

Hope to get some great advice! :slight_smile:

  • Dino

rtel wrote on Friday, May 03, 2019:

Using FreeRTOS makes very little difference to the stack size - the
stack size depends on how the compiler uses it (which will be different
at different optimisation levels), the function call nesting depth, and
the variables your code places on the stack - just like in any C
program. The difference when using FreeRTOS (or any preemptive RTOS) is
that you have more than one stack - one per task - so you can try to
minimise the number of tasks you create.

Some C libraries are real stack hogs too, so choose an optmized library
implementation.

You can view stack sizes using several functions, including
https://www.freertos.org/uxTaskGetStackHighWaterMark.html - that enables
you to tune the size as you can see if the current size is too large or
too small. Likewise you can tune the heap size using
xPortGetMinimumEverFreeHeapSize().

dinohammer wrote on Friday, May 03, 2019:

Okey, so by using the uxuxHighWaterMark method i can fine tune the amount of stacksize needed for each task?
If i then understand you correctly, rtos will do the memory handling for me? So i dont need any realloc(); or malloc(); from freertos lib?

richarddamon wrote on Friday, May 03, 2019:

As you say, you can use uxHighWaterMark to check stack usage and adjust your stack size based on it (be sure to leave a bit of slack). FreeRTOS will aquire the needed memory to create that stack for you (unless you use the ‘Static’ task creation routine, where you provide the needed array, assume to be allocated as static memory)

If your tasks need any dynamic memory, they will need to call the allocation functions themselves. This is just like for any normal program, the only difference is that with multiple tasks, you have multiple task stacks, so you have to allocate the desired amount to each of them.

dinohammer wrote on Monday, May 06, 2019:

When im trying to use the uxHighwatermark function i get an error from visual studio:
Compiling .pioenvs\megaatmega2560\src\main.cpp.o
src\main.cpp:16:63: error: ambiguating new declaration of ‘UBaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t)’
UBaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t Startpump);
^
In file included from lib\FreeRTOS\src/FreeRTOSVariant.h:56:0,
from lib\FreeRTOS\src/Arduino_FreeRTOS.h:1270,
from src\main.cpp:2:
lib\FreeRTOS\src/task.h:1440:24: note: old declaration ‘uint16_t uxTaskGetStackHighWaterMark(TaskHandle_t)’
configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
^
*** [.pioenvs\megaatmega2560\src\main.cpp.o] Error 1

How to fix?

rtel wrote on Monday, May 06, 2019:

First thought is that you are mixing source files from different
versions of FreeRTOS.

dinohammer wrote on Monday, May 06, 2019:

I am currently using 10.2.0v of freertos, i have also read more about usage of uxTaskGetStackHighWatermark, and now it prints, but all i get is a questionmark symbol for each time the task is used.

A snip of my code:

void Startpump(void *pvParameters);

xTaskCreate(
Startpump, // Function name
“Turn on pump”, // What it does
128, // Stack size in words
NULL, // Parameter for task, usually NULL
1, // Priority of the task
NULL // Task handle, usually NULL
);

vTaskStartScheduler();

The funtion itself: 

void Startpump(void *pvParameters)

{

// Initialize on and off button
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(motorPin, OUTPUT);
pinMode(greenLedPin, OUTPUT);
pinMode(redLedPin, OUTPUT);



// Task commands for delay og minnehåndtering(sjekke verdier hver task spytter ut)
// Delay mellom task
const TickType_t xDelay = 100 / portTICK_PERIOD_MS;

uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );

for (;;)
{
	// Leser status på knappene
	buttonStatus1 = digitalRead(buttonPin1);
	buttonStatus2 = digitalRead(buttonPin2);
	

	if (buttonStatus1 == HIGH && buttonStatus2 == LOW) // På knappen trykket
	{
		digitalWrite(motorPin, HIGH);
		digitalWrite(greenLedPin, HIGH);
		digitalWrite(redLedPin, LOW);
		LEDstatus = 1;
		uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
		Serial.println(uxTaskGetStackHighWaterMark(NULL));
		vTaskDelay(xDelay);
	}
	else if(buttonStatus1 == LOW && buttonStatus2 == HIGH) // Av knappen er trykket
	{
		digitalWrite(motorPin, LOW);
		digitalWrite(greenLedPin, LOW);
		digitalWrite(redLedPin, HIGH);
		LEDstatus = 0;
		Serial.print(F("Watermark stack er: "));
		uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
		Serial.println(uxTaskGetStackHighWaterMark(NULL));
		vTaskDelay(xDelay);
	
	}
	
}

}

Comments are in norwegian :slight_smile:

Am i using it right?

rtel wrote on Monday, May 06, 2019:

Which bit is not working? Just the printing? If so, can’t help you
there as the print function you are using is not something we wrote -
but to check the uxTaskGetStackHighWaterMark() function you can simple
place a break point in the code to see its return value.

dinohammer wrote on Monday, May 06, 2019:

It wont print values as it says it should. Ill try that, otherwise i have to find another way to get the right values :slight_smile: thanks!