This is my first time to use FreeRTOS to build STM32 project. I have stepped on many pitfalls and found that I lack the knowledge of memory and space allocation of the operating system, so I wrote down the document to record the learning results.
Finally, the problem to be solved is how to properly allocate the space of heap and task stack in FreeRTOS. But in the understanding of the concept, we also need to know the knowledge of STM32 memory. So let’s first give a brief introduction to the memory structure of STM32.
STM32 memory structure
STM32 data is stored in RAM and flash. RAM can be read and written, and reset after power failure. Flash can be read and not written, but it can be stored after power down, and the space is much larger than RAM.
On the issue of how to use ram and flash, STM32 memory has the concept of six storage data segments and three storage attribute areas.
6 storage segments
Data segment, which stores initialized global variables and static variables that are not initialized to 0.
Block Started by Symbol。 Stores global and static variables that are not initialized or initialized to 0.
Code segment to store program code.
Store read-only constants.
Heap is used to store the memory segments that are dynamically allocated during the process. It can be used to define the size of the startup file
startup_stm32fxx.sUsed by programmers
free()Function to allocate and release.
Stack, whose size is defined in the boot file
startup_stm32fxx.sIt is automatically allocated and released by the system. It can store local variables, function parameters and return values, and can save the scene when the interrupt occurs. However, the local static variables declared by static are not stored in the stack, but in the data section.
Three storage property areas
Burn it into flash, and it can be saved for a long time. Both the text snippet and constdata belong to ro. Due to the need for power down storage, a copy of data is also saved in RO.
It is stored in RAM. Data belongs to this area. When power on, MCU will copy the data type data saved in flash to ram for reading and writing.
The zero initialization area is also stored in RAM. When the system is powered on, the data in this area will be initialized by 0. BSS, heap and stack all belong to this region.
STM32 ram has RW and Zi attribute areas, which contain data, BSS, heap and stack. This is where the program runs.
Flash has ro area, including text, constdata and data. Here is the program body.
Heap in FreeRTOS
The heap in FreeRTOS also belongs to the Zi area, but it does not occupy the same space as the heap in STM32 memory structure. The two heaps exist at the same time. The heap shown below represents the FreeRTOS heap. In addition, the heap with the size defined in the STM32 boot file is called the system heap.
The main memory management functions used by FreeRTOS kernel are as follows:
void *pvPortMalloc( size_ T xsize); / / request memory
The above functions control the FreeRTOS heap; the system heap should use the
free()To distribute and release.
FreeRTOS has five ways to implement heap, which is the default in stm32cubemx
heap_4.c. This way can meet most of the needs of users, without paying attention to its implementation details.
The size of this heap is defined in
#define configTOTAL_HEAP_SIZE ((size_t)3072)
When FreeRTOS creates a task, the default task stack size is 128 words, which is 128 * 4 = 512byte in 32-bit system. In addition, the TCB block occupies 84byte, which is 596byte in total. The heap size of 3072byte allows the creation of three such tasks, which takes about 1800byte. The rest of the heap stores the system kernel, semaphore, queue, task notification and other data.
When more tasks need to be created, the size of the heap can be changed by itself. Subtracting the allocated space from the RAM space is the maximum space that can be allocated to the heap
FreeRTOS heap and task space allocation techniques
FreeRTOS heap and task stack are very dynamic in operation, and its size is difficult to estimate.
In practical use, we can first adjust the space to be larger. After the program runs normally, we can check the remaining space of the stack through some APIs to estimate the maximum memory space required during the program running. Finally, the maximum value is multiplied by a safety factor to get the final space size that should be allocated. The safety factor is recommended to be 1.3 to 1.5.
The APIs to view the remaining heap space are as follows:
size_ T xportgetfreeheapsize (void); / / get the current unallocated memory heap size
They return values in bytes.
It should be noted that,
heap_3.cCan’t be called when;
xPortGetMinimumEverFreeHeapSize(）It can only be used in
heap_5.cIt will take effect at the end of the year.
FreeRTOS also has an API to view the remaining space of the task stack
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
This function can obtain the historical minimum remaining value (highwatermark) of the task stack space from the time when a task is created to the time when this function is called. When using this function, it should be noted that the unit of its return value is word (one word in STM32 is 4 bytes long).
The API is off by default. You need to manually add the macro to the cube MX (or configuration file)
INCLUDE_uxTaskGetStackHighWaterMarkSet to 1.
After using these APIs, I found that they also occupy a considerable amount of memory space, especially the
uxTaskGetStackHighWaterMark(), will slow down the task. So in the official version of the program, they should be removed.