Prusa MINI Firmware overview
heap_4.c File Reference
#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"

Classes

struct  A_BLOCK_LINK
 

Macros

#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 
#define heapMINIMUM_BLOCK_SIZE   ( ( size_t ) ( xHeapStructSize << 1 ) )
 
#define heapBITS_PER_BYTE   ( ( size_t ) 8 )
 

Typedefs

typedef struct A_BLOCK_LINK BlockLink_t
 

Functions

static void prvInsertBlockIntoFreeList (BlockLink_t *pxBlockToInsert)
 
static void prvHeapInit (void)
 
voidpvPortMalloc (size_t xWantedSize)
 
void vPortFree (void *pv)
 
size_t xPortGetFreeHeapSize (void)
 
size_t xPortGetMinimumEverFreeHeapSize (void)
 
void vPortInitialiseBlocks (void)
 

Variables

static uint8_t ucHeap [configTOTAL_HEAP_SIZE]
 
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK )
 
static BlockLink_t xStart
 
static BlockLink_tpxEnd = NULL
 
static size_t xFreeBytesRemaining = 0U
 
static size_t xMinimumEverFreeBytesRemaining = 0U
 
static size_t xBlockAllocatedBit = 0
 

Macro Definition Documentation

◆ MPU_WRAPPERS_INCLUDED_FROM_API_FILE

#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE

◆ heapMINIMUM_BLOCK_SIZE

#define heapMINIMUM_BLOCK_SIZE   ( ( size_t ) ( xHeapStructSize << 1 ) )

◆ heapBITS_PER_BYTE

#define heapBITS_PER_BYTE   ( ( size_t ) 8 )

Typedef Documentation

◆ BlockLink_t

typedef struct A_BLOCK_LINK BlockLink_t

Function Documentation

◆ prvInsertBlockIntoFreeList()

static void prvInsertBlockIntoFreeList ( BlockLink_t pxBlockToInsert)
static
420 {
421 BlockLink_t *pxIterator;
422 uint8_t *puc;
423 
424  /* Iterate through the list until a block is found that has a higher address
425  than the block being inserted. */
426  for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
427  {
428  /* Nothing to do here, just iterate to the right position. */
429  }
430 
431  /* Do the block being inserted, and the block it is being inserted after
432  make a contiguous block of memory? */
433  puc = ( uint8_t * ) pxIterator;
434  if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
435  {
436  pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
437  pxBlockToInsert = pxIterator;
438  }
439  else
440  {
442  }
443 
444  /* Do the block being inserted, and the block it is being inserted before
445  make a contiguous block of memory? */
446  puc = ( uint8_t * ) pxBlockToInsert;
447  if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
448  {
449  if( pxIterator->pxNextFreeBlock != pxEnd )
450  {
451  /* Form one big block from the two blocks. */
452  pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
453  pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
454  }
455  else
456  {
457  pxBlockToInsert->pxNextFreeBlock = pxEnd;
458  }
459  }
460  else
461  {
462  pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
463  }
464 
465  /* If the block being inserted plugged a gab, so was merged with the block
466  before and the block after, then it's pxNextFreeBlock pointer will have
467  already been set, and should not be set here as that would make it point
468  to itself. */
469  if( pxIterator != pxBlockToInsert )
470  {
471  pxIterator->pxNextFreeBlock = pxBlockToInsert;
472  }
473  else
474  {
476  }
477 }
Here is the caller graph for this function:

◆ prvHeapInit()

static void prvHeapInit ( void  )
static
372 {
373 BlockLink_t *pxFirstFreeBlock;
374 uint8_t *pucAlignedHeap;
375 size_t uxAddress;
376 size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;
377 
378  /* Ensure the heap starts on a correctly aligned boundary. */
379  uxAddress = ( size_t ) ucHeap;
380 
381  if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
382  {
383  uxAddress += ( portBYTE_ALIGNMENT - 1 );
384  uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
385  xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
386  }
387 
388  pucAlignedHeap = ( uint8_t * ) uxAddress;
389 
390  /* xStart is used to hold a pointer to the first item in the list of free
391  blocks. The void cast is used to prevent compiler warnings. */
392  xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
393  xStart.xBlockSize = ( size_t ) 0;
394 
395  /* pxEnd is used to mark the end of the list of free blocks and is inserted
396  at the end of the heap space. */
397  uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
398  uxAddress -= xHeapStructSize;
399  uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
400  pxEnd = ( void * ) uxAddress;
401  pxEnd->xBlockSize = 0;
403 
404  /* To start with there is a single free block that is sized to take up the
405  entire heap space, minus the space taken by pxEnd. */
406  pxFirstFreeBlock = ( void * ) pucAlignedHeap;
407  pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
408  pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
409 
410  /* Only one block exists - and it covers the entire usable heap space. */
411  xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
412  xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
413 
414  /* Work out the position of the top bit in a size_t variable. */
415  xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
416 }
Here is the caller graph for this function:

◆ pvPortMalloc()

void* pvPortMalloc ( size_t  xWantedSize)
156 {
157 BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
158 void *pvReturn = NULL;
159 
160  vTaskSuspendAll();
161  {
162  /* If this is the first call to malloc then the heap will require
163  initialisation to setup the list of free blocks. */
164  if( pxEnd == NULL )
165  {
166  prvHeapInit();
167  }
168  else
169  {
171  }
172 
173  /* Check the requested block size is not so large that the top bit is
174  set. The top bit of the block size member of the BlockLink_t structure
175  is used to determine who owns the block - the application or the
176  kernel, so it must be free. */
177  if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
178  {
179  /* The wanted size is increased so it can contain a BlockLink_t
180  structure in addition to the requested amount of bytes. */
181  if( xWantedSize > 0 )
182  {
183  xWantedSize += xHeapStructSize;
184 
185  /* Ensure that blocks are always aligned to the required number
186  of bytes. */
187  if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
188  {
189  /* Byte alignment required. */
190  xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
191  configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
192  }
193  else
194  {
196  }
197  }
198  else
199  {
201  }
202 
203  if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
204  {
205  /* Traverse the list from the start (lowest address) block until
206  one of adequate size is found. */
207  pxPreviousBlock = &xStart;
208  pxBlock = xStart.pxNextFreeBlock;
209  while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
210  {
211  pxPreviousBlock = pxBlock;
212  pxBlock = pxBlock->pxNextFreeBlock;
213  }
214 
215  /* If the end marker was reached then a block of adequate size
216  was not found. */
217  if( pxBlock != pxEnd )
218  {
219  /* Return the memory space pointed to - jumping over the
220  BlockLink_t structure at its start. */
221  pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
222 
223  /* This block is being returned for use so must be taken out
224  of the list of free blocks. */
225  pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
226 
227  /* If the block is larger than required it can be split into
228  two. */
229  if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
230  {
231  /* This block is to be split into two. Create a new
232  block following the number of bytes requested. The void
233  cast is used to prevent byte alignment warnings from the
234  compiler. */
235  pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
236  configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 );
237 
238  /* Calculate the sizes of two blocks split from the
239  single block. */
240  pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
241  pxBlock->xBlockSize = xWantedSize;
242 
243  /* Insert the new block into the list of free blocks. */
244  prvInsertBlockIntoFreeList( pxNewBlockLink );
245  }
246  else
247  {
249  }
250 
251  xFreeBytesRemaining -= pxBlock->xBlockSize;
252 
254  {
256  }
257  else
258  {
260  }
261 
262  /* The block is being returned - it is allocated and owned
263  by the application and has no "next" block. */
264  pxBlock->xBlockSize |= xBlockAllocatedBit;
265  pxBlock->pxNextFreeBlock = NULL;
266  }
267  else
268  {
270  }
271  }
272  else
273  {
275  }
276  }
277  else
278  {
280  }
281 
282  traceMALLOC( pvReturn, xWantedSize );
283  }
284  ( void ) xTaskResumeAll();
285 
286  #if( configUSE_MALLOC_FAILED_HOOK == 1 )
287  {
288  if( pvReturn == NULL )
289  {
290  extern void vApplicationMallocFailedHook( void );
291  vApplicationMallocFailedHook();
292  }
293  else
294  {
296  }
297  }
298  #endif
299 
300  configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 );
301  return pvReturn;
302 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vPortFree()

void vPortFree ( void pv)
306 {
307 uint8_t *puc = ( uint8_t * ) pv;
308 BlockLink_t *pxLink;
309 
310  if( pv != NULL )
311  {
312  /* The memory being freed will have an BlockLink_t structure immediately
313  before it. */
314  puc -= xHeapStructSize;
315 
316  /* This casting is to keep the compiler from issuing warnings. */
317  pxLink = ( void * ) puc;
318 
319  /* Check the block is actually allocated. */
320  configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
321  configASSERT( pxLink->pxNextFreeBlock == NULL );
322 
323  if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
324  {
325  if( pxLink->pxNextFreeBlock == NULL )
326  {
327  /* The block is being returned to the heap - it is no longer
328  allocated. */
329  pxLink->xBlockSize &= ~xBlockAllocatedBit;
330 
331  vTaskSuspendAll();
332  {
333  /* Add this block to the list of free blocks. */
334  xFreeBytesRemaining += pxLink->xBlockSize;
335  traceFREE( pv, pxLink->xBlockSize );
336  prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
337  }
338  ( void ) xTaskResumeAll();
339  }
340  else
341  {
343  }
344  }
345  else
346  {
348  }
349  }
350 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xPortGetFreeHeapSize()

size_t xPortGetFreeHeapSize ( void  )
354 {
355  return xFreeBytesRemaining;
356 }

◆ xPortGetMinimumEverFreeHeapSize()

size_t xPortGetMinimumEverFreeHeapSize ( void  )
360 {
362 }

◆ vPortInitialiseBlocks()

void vPortInitialiseBlocks ( void  )
366 {
367  /* This just exists to keep the linker quiet. */
368 }

Variable Documentation

◆ ucHeap

◆ xHeapStructSize

const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK )
static

◆ xStart

BlockLink_t xStart
static

◆ pxEnd

BlockLink_t * pxEnd = NULL
static

◆ xFreeBytesRemaining

size_t xFreeBytesRemaining = 0U
static

◆ xMinimumEverFreeBytesRemaining

size_t xMinimumEverFreeBytesRemaining = 0U
static

◆ xBlockAllocatedBit

size_t xBlockAllocatedBit = 0
static
ucHeap
static uint8_t ucHeap[configTOTAL_HEAP_SIZE]
Definition: heap_4.c:106
A_BLOCK_LINK::xBlockSize
size_t xBlockSize
Definition: heap_4.c:114
pxEnd
static BlockLink_t * pxEnd
Definition: heap_4.c:140
configASSERT
#define configASSERT(x)
Definition: FreeRTOSConfig.h:162
A_BLOCK_LINK
Definition: heap_4.c:111
heapMINIMUM_BLOCK_SIZE
#define heapMINIMUM_BLOCK_SIZE
Definition: heap_4.c:95
traceMALLOC
#define traceMALLOC(pvAddress, uiSize)
Definition: FreeRTOS.h:570
NULL
#define NULL
Definition: usbd_def.h:53
heapBITS_PER_BYTE
#define heapBITS_PER_BYTE
Definition: heap_4.c:98
xMinimumEverFreeBytesRemaining
static size_t xMinimumEverFreeBytesRemaining
Definition: heap_4.c:145
portBYTE_ALIGNMENT
#define portBYTE_ALIGNMENT
Definition: portmacro.h:117
xFreeBytesRemaining
static size_t xFreeBytesRemaining
Definition: heap_4.c:144
xBlockAllocatedBit
static size_t xBlockAllocatedBit
Definition: heap_4.c:151
A_BLOCK_LINK::pxNextFreeBlock
struct A_BLOCK_LINK * pxNextFreeBlock
Definition: heap_4.c:113
configTOTAL_HEAP_SIZE
#define configTOTAL_HEAP_SIZE
Definition: FreeRTOSConfig.h:112
void
void
Definition: png.h:1083
prvInsertBlockIntoFreeList
static void prvInsertBlockIntoFreeList(BlockLink_t *pxBlockToInsert)
Definition: heap_4.c:419
traceFREE
#define traceFREE(pvAddress, uiSize)
Definition: FreeRTOS.h:574
uint8_t
const uint8_t[]
Definition: 404_html.c:3
prvHeapInit
static void prvHeapInit(void)
Definition: heap_4.c:371
xHeapStructSize
static const size_t xHeapStructSize
Definition: heap_4.c:137
xStart
static BlockLink_t xStart
Definition: heap_4.c:140
xTaskResumeAll
PRIVILEGED_FUNCTION BaseType_t xTaskResumeAll(void)
Definition: tasks.c:2017
vTaskSuspendAll
PRIVILEGED_FUNCTION void vTaskSuspendAll(void)
Definition: tasks.c:1944
mtCOVERAGE_TEST_MARKER
#define mtCOVERAGE_TEST_MARKER()
Definition: FreeRTOS.h:748