This article introduces the basic knowledge of memory management, detailed source analysis See " FreeRTOS Advanced Chapter 7---freertos Memory management analysis "
FreeRTOS provides several memory heap management schemes, with complex and simple ones. One of the simplest management strategies can also meet the requirements of many applications, such as security-demanding applications that do not allow dynamic memory allocation at all.
FreeRTOS also allows you to implement memory heap management yourself, even allowing you to use two memory heap management scenarios at the same time. Implementing both memory heaps allows the task stack and other RTOs objects to be placed into fast internal RAM, and application data is placed to low-speed external ram.
Each time a task, queue, mutex, software timer, semaphore, or event group is created, the RTOs kernel allocates RAM for them. The malloc () and free () functions in the standard library can sometimes be used to accomplish this task, but:
In embedded systems, they are not always available; they take up more valuable code space; they are not thread-protected; they are not deterministic (the time each call executes may be different);
Therefore, it is often necessary to provide an alternative memory allocation scheme.
Embedded/real-time systems have vastly varying RAM and time requirements, so a RAM memory allocation algorithm may only belong to a subset of applications.
To avoid this problem, FreeRTOS retains the memory allocation API function at the migration layer. The porting layer is outside the RTOs core code source file (not part of the core source code), which allows different applications to provide their own application implementations. When the RTOs kernel requires RAM, the Pvportmallo () function is called instead of the malloc () function. When RAM is to be freed, call the Vportfree () function instead of the free () function.
5 Simple memory allocation implementations are available in the FreeRTOS download package, which is described later in this article. The user can choose one of them appropriately, or they can design their own memory allocation policy.
The memory allocation schemes provided by FreeRTOS are located in different source files (heap_1.c, heap_2.c, heap_3.c, heap_4.c, heap_5.c), and the source files are located in the download package \freertos\source\portable\ The Memmang folder. Other implementations can be added as needed. If you want to use the memory heap allocation scheme provided by FreeRTOS, the selected source files must be properly included in the project file. 1.heap_1.c
This is the simplest of all implementations. Once memory is allocated, it does not even allow the allocated memory to be freed. In spite of this, heap_1.c is suitable for most embedded applications. This is because most deep embedded (deeplyembedded) applications simply create all tasks, queues, semaphores, etc. at system startup and use them until the end of the program and never need to delete them.
When allocating RAM is required, this memory allocation scheme simply subdivides a large array out of a subset. The capacity size of a large array is set by the Configtotal_heap_size macro in the FreeRTOSConfig.h file.
The API function Xportgetfreeheapsize () returns the total amount of unallocated stack space, which can be set reasonably by the return value of the function configtotal_heap_size.
Heap_1 Feature Description:
For applications that never delete tasks, queues, semaphores, mutexes, etc. (in fact most applications that use FreeRTOS meet this condition) execution time is deterministic and does not produce a memory fragmentation implementation and allocation process is very simple, the required memory is allocated from a static array, This means that memory allocations are typically only applicable to applications that do not perform dynamic memory allocations.
2.heap_2.c
Unlike scenario 1, this scenario uses a best-fit algorithm that allows freeing previously allocated blocks of memory. It does not synthesize adjacent free blocks into a larger block (in other words, it causes memory fragmentation).
The effective stack space size is defined by the Configtotal_heap_size macro located in the FreeRTOSConfig.h file.
The API function Xportgetfreeheapsize () returns the size of the remaining unallocated stack space (which can be used to optimize the value of the set Configtotal_heap_size macro), but does not provide fragmentation detail information for unallocated memory.
Heap_2 Feature Description:
Applications that can be used to repeatedly allocate and delete tasks, queues, semaphores, mutexes, and so on that have the same stack space, regardless of memory fragmentation. cannot be used in an application that allocates and frees random bytes of stack space if an application dynamically creates and deletes tasks, and the stack space assigned to the task is always the same size, then in most cases heap_2.c is available. However, if the stack that is assigned to the task is not always equal, the freed valid memory may be fragmented, forming many small chunks of memory. In the end, memory allocation fails because there is not enough contiguous stack space. In this case, heap_4.c is a good choice. If an application dynamically creates and deletes queues, and in each case the queue storage area (which refers to the number of queue items multiplied by each queue length) is the same, then in most cases heap_2.c can be used. However, if the queue store is not always equal in each case, the freed valid memory may be fragmented, forming many small chunks of memory. In the end, memory allocation fails because there is not enough contiguous stack space. In this case, heap_4.c is a good choice. Applications call the Pvportmalloc () and Vportfree () functions directly, not just indirectly through the FreeRTOS API. If the queues, tasks, semaphores, mutexes, and so on in your application are in an unpredictable order, it can cause a memory fragmentation problem, although this is a small probability event, but you must keep in mind. is not deterministic, but it is much more efficient than the malloc function in a standard library.
The heap_2.c is suitable for most small real-time systems that require dynamic creation of tasks (smallreal. 3.heap_3.c
Heap_3.c simply wraps the malloc () and free () functions in the standard library, and the Wrapped malloc () and free () functions are thread-protected.
HEAP_3.C Feature Description:
The linker is required to set up a stack, and the compiler library provides the malloc () and free () functions. Not deterministic can significantly increase the code size of the RTOs kernel
Note: When using Heap_3, the Configtotal_heap_size macro definition in the FreeRTOSConfig.h file does not work. 4.heap_4.c
This scenario uses a best-fit algorithm, but not as in Scenario 2. It merges contiguous blocks of free memory into a larger block (containing a merge algorithm).
The effective stack space size is defined by the configtotal_heap_size that is located in the FreeRTOSConfig.h file.
The API function Xportgetfreeheapsize () returns the size of the remaining unallocated stack space (which can be used to optimize the value of the set Configtotal_heap_size macro), but does not provide fragmentation detail information for unallocated memory.
HEAP_4.C Feature Description:
Applications that can be used to repeatedly assign, delete tasks, queues, semaphores, mutexes, and so on. Can be used to allocate and release random bytes of memory, and does not produce serious fragmentation like heap_2.c. is not deterministic, but it is much more efficient than the malloc function in a standard library.
HEAP_4.C is also particularly useful for porting layer code, which can be used to allocate and free memory directly using the Pvportmalloc () and Vportfree () functions. 5.heap_5.c (V8.1.0 new)
This scenario also implements the merge algorithm in HEAP_4.C and allows the stack to span multiple noncontiguous memory areas.
Heap_5 is initialized by calling the Vportdefineheapregions () function, which does not allow memory allocation and deallocation until the function is completed. Creating an RTOs object (task, queue, semaphore, and so on) implies calling Pvportmalloc (), so it's important to note that the Vportdefineheapregions () function is executed before any objects are created using Heap_5.
The Vportdefineheapregions () function requires only a single argument. This parameter is an array of heapregion_t struct types. Heapregion_t is defined in Portable.h as follows:
typedef struct HEAPREGION
{/
* memory block start address for memory heap */
uint8_t *pucstartaddress;
/* Memory block Size */
size_t xsizeinbytes;
} heapregion_t;
This array must end with a null pointer and a 0-byte element, and the starting address must be arranged from small to large. The following code snippet provides an example. The MSVCWin32 Simulator demo routine uses heap_5, so it can be used as a reference routine.
/* Allocates two memory blocks in memory for the memory heap. The first memory block 0x10000 bytes, the starting address is 0x80000000, the
second memory block 0xa0000 bytes, and the starting address is 0x90000000. The memory block with the starting address of 0x80000000 The
starting address is lower, so it is placed in the first position of the array. *
/const heapregion_t xheapregions[] =
{
{(uint8_t *) 0x80000000ul, 0x10000},< c5/>{(uint8_t *) 0x90000000ul, 0xa0000},
{NULL, 0}/* end of array. */
};
/* Pass array parameters to function vportdefineheapregions (). */