dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_heap.c
Go to the documentation of this file.
1 
11 /*
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20  * for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, see <http://www.gnu.org/licenses/>
24  */
25 
26 /* Project Includes */
27 #include "pios.h" /* PIOS_INCLUDE_* */
28 
29 #include "pios_heap.h" /* External API declaration */
30 
31 #include <stdio.h> /* NULL */
32 #include <stdint.h> /* uintptr_t */
33 #include <stdbool.h> /* bool */
34 
35 #define DEBUG_MALLOC_FAILURES 0
36 static volatile bool malloc_failed_flag = false;
37 static void malloc_failed_hook(void)
38 {
39  malloc_failed_flag = true;
40 #if DEBUG_MALLOC_FAILURES
41  static volatile bool wait_here = true;
42  while(wait_here);
43  wait_here = true;
44 #endif
45 }
46 
48 {
49  return malloc_failed_flag;
50 }
51 
52 #if defined(PIOS_INCLUDE_RTOS)
53 #include "pios_thread.h"
54 #endif
55 
56 struct pios_heap {
57  const uintptr_t start_addr;
58  uintptr_t end_addr;
59  uintptr_t free_addr;
60 };
61 
62 static bool is_ptr_in_heap_p(const struct pios_heap *heap, void *buf)
63 {
64  uintptr_t buf_addr = (uintptr_t)buf;
65 
66  return ((buf_addr >= heap->start_addr) && (buf_addr <= heap->end_addr));
67 }
68 
69 static void * simple_malloc(struct pios_heap *heap, size_t size)
70 {
71  if (heap == NULL)
72  return NULL;
73 
74  void * buf = NULL;
75  uint32_t align_pad = (sizeof(uintptr_t) - (size & (sizeof(uintptr_t) - 1))) % sizeof(uintptr_t);
76 
77 #if defined(PIOS_INCLUDE_RTOS)
79 #endif /* PIOS_INCLUDE_RTOS */
80 
81  if (heap->free_addr + size <= heap->end_addr) {
82  buf = (void *)heap->free_addr;
83  heap->free_addr += size + align_pad;
84  }
85 
86 #if defined(PIOS_INCLUDE_RTOS)
88 #endif /* PIOS_INCLUDE_RTOS */
89 
90  return buf;
91 }
92 
93 static void simple_free(struct pios_heap *heap, void *buf)
94 {
95  /* This allocator doesn't support free */
96 }
97 
98 static size_t simple_get_free_bytes(struct pios_heap *heap)
99 {
100  if (heap->free_addr > heap->end_addr)
101  return 0;
102 
103  return heap->end_addr - heap->free_addr;
104 }
105 
106 static void simple_extend_heap(struct pios_heap *heap, size_t bytes)
107 {
108  heap->end_addr += bytes;
109 }
110 
111 /*
112  * Standard heap. All memory in this heap is DMA-safe.
113  */
114 extern const void * _eheap; /* defined in linker script */
115 extern const void * _sheap; /* defined in linker script */
116 
117 static struct pios_heap pios_standard_heap = {
118  .start_addr = (const uintptr_t)&_sheap,
119  .end_addr = (const uintptr_t)&_eheap,
120  .free_addr = (uintptr_t)&_sheap,
121 };
122 
123 
124 void * pvPortMalloc(size_t size) __attribute__((alias ("PIOS_malloc"), weak));
125 void * PIOS_malloc(size_t size)
126 {
127  void *buf = simple_malloc(&pios_standard_heap, size);
128 
129  if (buf == NULL)
131 
132  return buf;
133 }
134 
135 /*
136  * Fast heap. Memory in this heap is NOT DMA-safe.
137  * Note: This should not be used to allocate RAM for task stacks since a task may pass
138  * automatic variables into underlying PIOS functions which *may* use DMA.
139  * Note: Falls back to using the standard heap when allocations cannot be satisfied.
140  */
141 #if defined(PIOS_INCLUDE_FASTHEAP)
142 
143 extern const void * _efastheap; /* defined in linker script */
144 extern const void * _sfastheap; /* defined in linker script */
145 static struct pios_heap pios_nodma_heap = {
146  .start_addr = (const uintptr_t)&_sfastheap,
147  .end_addr = (const uintptr_t)&_efastheap,
148  .free_addr = (uintptr_t)&_sfastheap,
149 };
150 void * PIOS_malloc_no_dma(size_t size)
151 {
152  void * buf = simple_malloc(&pios_nodma_heap, size);
153 
154  if (buf == NULL)
155  buf = PIOS_malloc(size);
156 
157  if (buf == NULL)
159 
160  return buf;
161 }
162 
163 #else /* PIOS_INCLUDE_FASTHEAP */
164 
165 /* This platform only has a standard heap. Fall back directly to that */
166 void * PIOS_malloc_no_dma(size_t size)
167 {
168  return PIOS_malloc(size);
169 }
170 
171 #endif /* PIOS_INCLUDE_FASTHEAP */
172 
173 void vPortFree(void * buf) __attribute__((alias ("PIOS_free")));
174 void PIOS_free(void * buf)
175 {
176 #if defined(PIOS_INCLUDE_FASTHEAP)
177  if (is_ptr_in_heap_p(&pios_nodma_heap, buf))
178  return simple_free(&pios_nodma_heap, buf);
179 #endif /* PIOS_INCLUDE_FASTHEAP */
180 
181  if (is_ptr_in_heap_p(&pios_standard_heap, buf))
182  return simple_free(&pios_standard_heap, buf);
183 }
184 
186 size_t PIOS_heap_get_free_size(void)
187 {
188 #if defined(PIOS_INCLUDE_RTOS)
190 #endif /* PIOS_INCLUDE_RTOS */
191 
192  size_t free_bytes = simple_get_free_bytes(&pios_standard_heap);
193 
194 #if defined(PIOS_INCLUDE_RTOS)
196 #endif /* PIOS_INCLUDE_RTOS */
197 
198  return free_bytes;
199 }
200 
201 
202 #if defined(PIOS_INCLUDE_FASTHEAP)
203 
204 size_t PIOS_fastheap_get_free_size(void)
205 {
206 #if defined(PIOS_INCLUDE_RTOS)
208 #endif /* PIOS_INCLUDE_RTOS */
209 
210  size_t free_bytes = simple_get_free_bytes(&pios_nodma_heap);
211 
212 #if defined(PIOS_INCLUDE_RTOS)
214 #endif /* PIOS_INCLUDE_RTOS */
215 
216  return free_bytes;
217 }
218 
219 #else
220 
222 {
223  return 0;
224 }
225 
226 #endif // PIOS_INCLUDE_FASTHEAP
227 
229 {
230  /* NOP for the simple allocator */
231 }
232 
234 {
235 #if defined(PIOS_INCLUDE_RTOS)
237 #endif /* PIOS_INCLUDE_RTOS */
238 
239  simple_extend_heap(&pios_standard_heap, bytes);
240 
241 #if defined(PIOS_INCLUDE_RTOS)
243 #endif /* PIOS_INCLUDE_RTOS */
244 }
245 
246 
247 /* Provide an implementation of _sbrk for library functions.
248  * Right now it returns failure always.
249  */
250 static uintptr_t sbrk_pool[1024];
251 static uintptr_t brk_ptr = (uintptr_t) sbrk_pool;
252 
253 void *_sbrk(int incr) {
254  uintptr_t orig = brk_ptr;
255  uintptr_t new = brk_ptr + incr;
256 
257  uintptr_t end = ((uintptr_t) sbrk_pool) + sizeof(sbrk_pool);
258 
259  if (new > end) {
260  return (void *) -1;
261  }
262 
263  brk_ptr = new;
264 
265  return (void *)orig;
266 }
267 
static uintptr_t sbrk_pool[1024]
Definition: pios_heap.c:250
static uintptr_t brk_ptr
Definition: pios_heap.c:251
static void simple_free(struct pios_heap *heap, void *buf)
Definition: pios_heap.c:93
void weak
Definition: pios_heap.c:124
Main PiOS header to include all the compiled in PiOS options.
size_t PIOS_fastheap_get_free_size(void)
Definition: pios_heap.c:221
static size_t simple_get_free_bytes(struct pios_heap *heap)
Definition: pios_heap.c:98
const void * _eheap
void PIOS_Thread_Scheduler_Suspend(void)
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
void * _sbrk(int incr)
Definition: pios_heap.c:253
void * PIOS_malloc_no_dma(size_t size)
Definition: pios_heap.c:166
uint8_t bytes[2]
Definition: storm32bgc.c:156
void PIOS_heap_increase_size(size_t bytes)
Definition: pios_heap.c:233
void vPortFree(void *buf) __attribute__((alias("PIOS_free")))
static void malloc_failed_hook(void)
Definition: pios_heap.c:37
size_t xPortGetFreeHeapSize(void)
Definition: pios_heap.c:185
void PIOS_heap_initialize_blocks(void)
Definition: pios_heap.c:228
uintptr_t end_addr
Definition: pios_heap.c:58
struct pios_heap __attribute__
void * pvPortMalloc(size_t size) __attribute__((alias("PIOS_malloc")
static struct pios_heap pios_standard_heap
Definition: pios_heap.c:117
void PIOS_free(void *buf)
Definition: pios_heap.c:174
static bool is_ptr_in_heap_p(const struct pios_heap *heap, void *buf)
Definition: pios_heap.c:62
static volatile bool malloc_failed_flag
Definition: pios_heap.c:36
uintptr_t free_addr
Definition: pios_heap.c:59
bool PIOS_heap_malloc_failed_p(void)
Definition: pios_heap.c:47
static void simple_extend_heap(struct pios_heap *heap, size_t bytes)
Definition: pios_heap.c:106
void PIOS_Thread_Scheduler_Resume(void)
const uintptr_t start_addr
Definition: pios_heap.c:57
static void * simple_malloc(struct pios_heap *heap, size_t size)
Definition: pios_heap.c:69
size_t PIOS_heap_get_free_size(void)
Definition: pios_heap.c:74
const void * _sheap