Using FreeRTOS heap_5 in MCUXpresso SDK.

cancel
Showing results for 
Search instead for 
Did you mean: 

Using FreeRTOS heap_5 in MCUXpresso SDK.

No ratings

Using FreeRTOS heap_5 in MCUXpresso SDK.

 

FreeRTOS supports multiple heap allocation schemes. Scheme 5 allows the heap to span multiple non adjacent (non-contiguous) memory regions. Heap_5 is useful when RAM provided by the system on which FreeRTOS is running does not appear as a single contiguous block in the system’s memory map. With heap_5, developers can combine multiple memory blocks for a virtual combined memory heap.

In this article, I will take FrdmK82f hello_world_freertos as an example to illustrate how to use FreeRTOS heap 5 memory scheme with MCUXpresso SDK. Like some other Kinetis MCUs, Frdmk82f has two memory controllers, one for the SRAM_UPPER (192k byters) and one or SRAM_Lower as below (64K byters).

danielchen_0-1605037919108.png

 With FreeRTOS heap_4, application developers cannot have memory objects crossing that memory boundary 0x2000,000, they can only use SRAM_UPPER or SRAM_LOWER as FreeRTOS heap, with heap_5, they can combine SRAM_UPPER and SRAM_LOWER as a huge virtual FreeRTOS memory map.

1    Define multiple memory blocks

Each separate memory areas is described by a structure of type HeapRegion_t. A description of all the available memory areas is passed into vPortDefineHeapRegions( ) as an array of HeapRegion_t structures.

/* Used by heap_5.c to define the start address and size of each memory region

that together comprise the total FreeRTOS heap space. */

typedef struct HeapRegion

{

    uint8_t *pucStartAddress;

    size_t xSizeInBytes;

} HeapRegion_t;

 

We can create an array of these structures to define our different memory blocks that can be assigned to the heap.

For FrdmK82f, we can define two memory blocks, SRAM_UPPER and SRAM_LOWER. But SRAM_UPPER is the main RAM, it is not possible to allocate all the RAM to heap, leaving no RAM free for use by other variables. It is good to declare an array called ucHeap, it becomes part of the data allocated to RAM by linker.

/*define the start address and size of SRAM_LOWER region not used by the the linker*/

#define SRAM_LOWER_START_ADDRESS  ( (uint8_t*) 0x1fff0000 )

#define SRAM_LOWER_SIZE           ( 0X10000)

 

/*Declare an array that will be part of the heap used by heap_5.  The array will be placed in SRAM_UPPER by the linker*/

#define SRAM_UPPOER_HEAP_SIZE (80 * 1024)

static __attribute__ ((used,section(".noinit_RAM2"))) uint8_t ucHeap[SRAM_UPPOER_HEAP_SIZE]; /* placed in in no_init section inside SRAM_UPPER */

 

/*Create an array of HeapRegion_t definitions. this array will be passed to vPortDefineHeapRegions( )

*/

 

const HeapRegion_t xHeapRegions[] =

{

        {SRAM_LOWER_START_ADDRESS, SRAM_LOWER_SIZE },

        {ucHeap, SRAM_UPPOER_HEAP_SIZE },

        {NULL, 0}

};

 

Please note that the array should be terminated with a NULL zero sized region definition and the memory regions defined in the array must appear in address order from low address to high address.

 

2     FreeRTOS heap_5 Initialization

 

Heap_5 memory allocation scheme must be explicitly initialized before pvPortMalloc( ) can be used.  Heap_5 is initialized using the vPortDefineheapRegions( ) API function. It is used to specify the start address and size of each separate memory area that together makes up the total memory used by heap_5. When heap_5 is used, vPortDefineHeapRegions( ) must be called before any kernel objects (tasks, queues, semaphores, etc) can be created.  Usually this API is called in main function.

 

    vPortDefineHeapRegions(xHeapRegions);  

/*pass the array into vPortDefineHeapRegions(), must be called first*/

 

3    Configure FreeRTOS memory scheme

To use Scheme, make sure heap_5.c is used in the application as below picture shows.

ConfigFRTOS_MEMORY_SCHEME should be configured to ‘5’ in FreeRTOSConfig.h.

 
 
 

scheme.png 

4     Using multiple FreeRTOS memory regions and Debugging

Next I will allocate 100K memory with pvPortMalloc API in the hello_task.

 

int i;

    unsigned char *handle;

    for (i=0; i<10; i++)

    {

        handle =  pvPortMalloc(10*1024);

        if (NULL == handle)

        {

            PRINTF("Malloc failed \r\n");

        }

        else

        {

            PRINTF("allocated buffer[%d], size 10K, address is 0x%x\r\n", i, handle);

        }

    }

The console output is as below picture.  From the allocated address, we can see that 60K is allocated from SRAM_LOWER and 40K is from SRAM_UPPER.

 

SEGGER J-Link GDB Server V6.86e - Terminal output channel

heapsize is 147432!.

allocated buffer[0], size 10K, address is 0x1fff09c8

allocated buffer[1], size 10K, address is 0x1fff31d0

allocated buffer[2], size 10K, address is 0x1fff59d8

allocated buffer[3], size 10K, address is 0x1fff81e0

allocated buffer[4], size 10K, address is 0x1fffa9e8

allocated buffer[5], size 10K, address is 0x1fffd1f0

allocated buffer[6], size 10K, address is 0x20000298

allocated buffer[7], size 10K, address is 0x20002aa0

allocated buffer[8], size 10K, address is 0x200052a8

allocated buffer[9], size 10K, address is 0x20007ab0

 

From the heap and usage view, we can see the detailed memory info.

 heap.png

 

 

 

 

 

Version history
Revision #:
1 of 1
Last update:
‎11-10-2020 01:08 PM
Updated by:
 
Contributors