OS consuming more memory than it should

mishung wrote on Friday, February 10, 2017:

Hello, I am running in bit of a memory allocation problem here. I am using a FreeRTOS on xmega32d4, the compiler I am using is AVR-GCC, optimisation set to max (-O3).
Even without any custom tasks created, 528 bytes from stack is being used.
*185 bytes get allocated in task.c line 3134 **
pxStack=(StackType_t
)pvPortMallocAligned((((size_t)usStackDepth)sizeof(StackType_t)),puxStackBuffer);
37 bytes get allocated in task.c line 3140
pxNewTCB=(TCB_t
)pvPortMalloc(sizeof(TCB_t));
306 bytes get allocated in task.c line 1565
xReturn = xTimerCreateTimerTask();

The timer task is configured to allocate minimal stack size which is set to 185 bytes so why does it take 306 bytes?

Also, whenever I create a task, it takes more stack space from heap than it should. Every task takes exactly 37 bytes more than what I allocate for it.

Here are my OS settings:

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

#include <avr/io.h>

#define configCALL_STACK_SIZE	20

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. 
 *
 * See http://www.freertos.org/a00110.html.
 *----------------------------------------------------------*/

/* define priority level names*/
#define PRIORITY_LOW  (tskIDLE_PRIORITY+1)
#define PRIORITY_MED  (tskIDLE_PRIORITY+2)
#define PRIORITY_HI   (tskIDLE_PRIORITY+3)

#define configMAX_PRIORITIES		  4

/* config */
#define configUSE_PREEMPTION	  	0
#define configUSE_IDLE_HOOK		  	0
#define configUSE_TICK_HOOK		  	0
#define configCPU_CLOCK_HZ			  (F_CPU)
#define configTICK_RATE_HZ			  ((TickType_t)1000)
#define configMINIMAL_STACK_SIZE	(185U)
#define configTOTAL_HEAP_SIZE		  ((size_t)(1400))
#define configMAX_TASK_NAME_LEN		8
#define configUSE_TRACE_FACILITY	1
#define configUSE_16_BIT_TICKS		1
#define configIDLE_SHOULD_YIELD		1

#define configUSE_TASK_NOTIFICATIONS             0
#define configUSE_MUTEXES                        1
#define configUSE_RECURSIVE_MUTEXES              0
#define configUSE_COUNTING_SEMAPHORES            0
#define configQUEUE_REGISTRY_SIZE                1
#define configUSE_QUEUE_SETS                     0
#define configUSE_TIME_SLICING                   1
#define configUSE_NEWLIB_REENTRANT               0
#define configENABLE_BACKWARD_COMPATIBILITY      0
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS  0

#define configCHECK_FOR_STACK_OVERFLOW   2
 
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 		       0
#define configMAX_CO_ROUTINE_PRIORITIES  2

/* XMEGA port specific configuration */
/* for info see ... */

#define configPORT_DISABLE_ALL_INTERRUPTS_DURING_CONTEXT_SWITCH  0
#define configPORT_SAVE_RAMPZ_ON_CONTEXT_SWITCH                  0	//is zero for small MCUs
#define configPORT_TICK_TIMER                                   D0	//tick timer
#define configPORT_TICK_TIMER_INTCTRLA_ADDRESS              0x0906	//tick timer INTCTRLA address


/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet                1
#define INCLUDE_uxTaskPriorityGet               0
#define INCLUDE_vTaskDelete                     1
#define INCLUDE_vTaskSuspend                    1
#define INCLUDE_xResumeFromISR                  0
#define INCLUDE_vTaskDelayUntil                 0
#define INCLUDE_vTaskDelay                      1
#define INCLUDE_xTaskGetSchedulerState          0
#define INCLUDE_xTaskGetCurrentTaskHandle       0
#define INCLUDE_uxTaskGetStackHighWaterMark     1
#define INCLUDE_xTaskGetIdleTaskHandle          0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle  0
#define INCLUDE_pcTaskGetTaskName               0
#define INCLUDE_eTaskGetState                   1
#define INCLUDE_xEventGroupSetBitFromISR        0
#define INCLUDE_xTimerPendFunctionCall          0

#define configUSE_TIMERS                    1
#define configTIMER_TASK_PRIORITY           1
#define configTIMER_QUEUE_LENGTH            10
#define configTIMER_TASK_STACK_DEPTH        configMINIMAL_STACK_SIZE

#endif /* FREERTOS_CONFIG_H */

rtel wrote on Friday, February 10, 2017:

configMINIMAL_STACK_SIZE can be set much smaller on an AVR (85?) unless
you are doing something stack heavy from the idle task hook function.
In your case you are using the setting to dimension the stack for both
the idle and timer task.

In all the cases you highlight you can step through the code and see
exactly where every byte is going.

Lets take xTimerCreateTimerTask() as an example. I’m not stepping
through the code, just viewing it:

The first thing xTimerCreateTimerTask() does is call
prvCheckForValidListAndQueue(). That calls xQueueCreate(), which will
allocate the queue data structure and the queue storage area. You have
configTIMER_QUEUE_LENGTH set to 10, so the storage area by itself will
use 10 * sizof( DaemonTaskMessage_t ) bytes.

Next xTimerCreateTimerTask() calls xTaskCreate(), which will allocate
the task’s TCB (the size of which depends on other config options in
FreeRTOSConfig.h - you can look at the data structure in tasks.c), and
the task’s stack, which you have set to probably about 100 bytes larger
than it needs to be unless you are using the idle hook function.

mishung wrote on Sunday, February 12, 2017:

Thank you, I’ll try lowering the configMINIMAL_STACK_SIZE and see if it works out.

mishung wrote on Tuesday, February 14, 2017:

I was able to set the configMINIMAL_STACK_SIZE to 135 Bytes, that helped a bit.