Embedded Artistry libmemory
Memory library for embedded systems (malloc and friends)
malloc_freertos.c
Go to the documentation of this file.
1 /*
2  * Copyright © 2018 Embedded Artistry LLC.
3  * License: MIT. See LICENSE file for details.
4  */
5 
6 #include <assert.h>
7 #include <freertos/FreeRTOS.h>
8 #include <freertos/task.h>
9 #include <malloc.h>
10 #include <stdbool.h>
11 #include <stdint.h>
12 #include <stdlib.h>
13 
20 #pragma mark - Definitions
21 
25 #ifndef FREERTOS_HEAP_REGION_CNT
26 #define FREERTOS_HEAP_REGION_CNT 2
27 #endif
28 
29 #pragma mark - Declarations -
30 
33 
35 static volatile uint8_t heap_region_cnt = 0;
36 
44 static HeapRegion_t heap_regions[FREERTOS_HEAP_REGION_CNT + 1];
45 
50 static volatile bool initialized_ = false;
51 
52 #pragma mark - Private Functions -
53 
54 static int cmp_heap(const void* a, const void* b)
55 {
56  const HeapRegion_t* ua = a;
57  const HeapRegion_t* ub = b;
58 
59  return ((ua->pucStartAddress < ub->pucStartAddress)
60  ? -1
61  : ((ua->pucStartAddress != ub->pucStartAddress)));
62 }
63 
69 void malloc_addblock(void* addr, size_t size)
70 {
71  assert(addr && (size > 0));
72  assert((heap_region_cnt < heap_region_max) && "Too many heap regions!");
73 
74  // Increment the count early to claim a spot in case of multi-threads
75  uint8_t cnt = heap_region_cnt++;
76 
77  if(cnt < heap_region_max)
78  {
79  // We have space - add it to the table
80  heap_regions[cnt].pucStartAddress = (uint8_t*)addr;
81  heap_regions[cnt].xSizeInBytes = size;
82  }
83  else
84  {
85  // Decrement the count if we don't have space
87  }
88 }
89 
90 __attribute__((weak)) void malloc_init()
91 {
92  assert((heap_region_cnt > 0) && !initialized_);
93 
94  if(heap_region_cnt > 0 && !initialized_)
95  {
96  // Sort the heap regions so addresses are in the correct order
97  qsort(heap_regions, heap_region_cnt, sizeof(HeapRegion_t), cmp_heap);
98 
99  // Pass the array into vPortDefineHeapRegions() to enable malloc()
100  vPortDefineHeapRegions(heap_regions);
101 
102  // Signal to any waiting threads that we are done initializing
103  initialized_ = true;
104  }
105 }
106 
107 void* malloc(size_t size)
108 {
109  void* ptr = NULL;
110 
111  while(!initialized_)
112  {
113  // Thread blocks until application malloc has been correctly initialized
114  vTaskDelay(1);
115  }
116 
117  if(size > 0)
118  {
119  // We simply wrap the FreeRTOS call into a standard form
120  ptr = pvPortMalloc(size);
121  } // else NULL if there was an error
122 
123  return ptr;
124 }
125 
126 void free(void* ptr)
127 {
129  assert(initialized_);
130 
131  if(ptr)
132  {
133  // We simply wrap the FreeRTOS call into a standard form
134  vPortFree(ptr);
135  }
136 }
#define FREERTOS_HEAP_REGION_CNT
static HeapRegion_t heap_regions[FREERTOS_HEAP_REGION_CNT+1]
static volatile bool initialized_
static const uint8_t heap_region_max
Maximum number of heap regions that can be specified.
static volatile uint8_t heap_region_cnt
Current number of allocated heap regions.
static int cmp_heap(const void *a, const void *b)
__attribute__((weak))
void malloc_addblock(void *addr, size_t size)
Assign blocks of memory for use by malloc().
void free(void *ptr)
void malloc_init(void)
Initialize Malloc.
void * malloc(size_t size)