I have somewhat of a similar problem, in that I need to adjust task sizes to keep the program from crashing. My memory situation is opposite, in that I have sufficient memory because I added a QSPI memory to all of my designs. (I am only using L5 and U5 processors, which have that interface.) My programming is in C++, and I have a callable routine that sets up all the drivers and queues the system uses, then creates the main application task (which creates application specific chip drivers and various tasks).
This won’t solve your problem, but it can give you another handle on what’s going on.
What I did was to add a statistics option, which is conditionally enabled. It reports FreeRTOS stack every time it’s called, along with the filename and location of the call. It stores to the memory segment used for trace data (which I don’t use at this time).
The call looks like:
#ifdef _STATISTICS
statistics_tag(__FILE__, __LINE__, (char*) "Beginning of APPLICATION CREATE");
#endif
while the routine itself is:
struct statistics_data STATISTICS[_MAX_STATISTICS] = {0};
//struct statistics_data __attribute__((section (".trace_data"))) STATISTICS[_MAX_STATISTICS] = {0};
#include "../COMMON_CPP/CPP_LINK.hpp"
//#ifdef _XHEAP
// #include "../HARDWARE_CPP\xheap.hpp"
// Xheap* xheap;
//#endif
#ifdef __cplusplus
extern "C"
{
#endif
void statistics_tag(const void* filename, unsigned int linenumber, char* comment)
{
int i=0;
// BlockLink_t* pxBlock;
HeapStats_t pxHeapStats;
TaskHandle_t current_task;
while ((STATISTICS[i].filename != NULL) && (i < _MAX_STATISTICS))
{
i++;
}
if (i < _MAX_STATISTICS)
{
//strncpy(STATISTICS[i].filename,(char*)filename,49);
STATISTICS[i].filename = (char*)filename;
STATISTICS[i].line_number = linenumber;
// strncpy(STATISTICS[i].comment,comment,49);
current_task = xTaskGetCurrentTaskHandle();
if (current_task != 0)
{
strncpy(STATISTICS[i].active_task,pcTaskGetName(current_task ),49);
}
else
{
strcpy(STATISTICS[i].active_task,(char*) "NO ACTIVE TASK");
}
// #ifdef _XHEAP
// STATISTICS[i].xxheapsize = xheap->get_free();
// #endif
STATISTICS[i].comment = comment;
vPortGetHeapStats(&pxHeapStats);
// taskENTER_CRITICAL();
// {
STATISTICS[i].FreeRTOS_heap_free = pxHeapStats.xAvailableHeapSpaceInBytes;
STATISTICS[i].FreeRTOS_heap_lowest = pxHeapStats.xMinimumEverFreeBytesRemaining;
STATISTICS[i].FreeRTOS_heap_allocated = pxHeapStats.xAvailableHeapSpaceInBytes;
if (i == 0)
{
STATISTICS[i].delta_from_last = 0;
}
else
{
STATISTICS[i].delta_from_last = STATISTICS[i].FreeRTOS_heap_free - STATISTICS[i-1].FreeRTOS_heap_free;
// #ifdef _XHEAP
// STATISTICS[i].xxheapdelta= STATISTICS[i].xxheapsize - STATISTICS[i-1].xxheapsize;
// #endif;
}
// }
// taskEXIT_CRITICAL();
}
}
#ifdef __cplusplus
}
#endif // END FREERTOS LOOP
and the data structure is:
struct statistics_data
{
char* filename;
int line_number;
char* comment;
char active_task[50];
int FreeRTOS_heap_free;
int FreeRTOS_heap_lowest;
int FreeRTOS_heap_allocated;
int delta_from_last;
int xxheapsize;
int xxheapdelta;
};
xheap is a C++ routine that has a memory manager allowing a separate memory space in extended memory, it uses a first fit algorithm. Since it’s C++, calling it from C routines is a bit messy, so I disabled that part. I’d need to duplicate the memory statistics in C accessible variables, just didn’t get to it.
What I did, program structure wise, is run my task creation routines out side of the default task. You don’t really need it inside, and it was just chewing up memory (This is the default “see what we’re doing for you” CubeMXIDE generated task. It’s automatically created, but I use a minimal stack and have it do a 10 second delay loop. Task creation is done in the section of main labeled “FreeRTOSS queues” since there’s no labeled place to put it, but it does need to be after the oskernel init and before the call to run the tasks,
This at least gives me an idea of what is being asked of the FreeRTOS heap.
I got some interesting answers about task high water marks.
I use an external RTOS heap, put some programs in xheap memory, and am still messing with the process.
Hope this helps a bit.