SAM4S-EK_FreeRTOS+FAT-SL  1.0
An example project to test the functionality of FreeRTOS+FAT-SL using SD card as data storage medium
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Modules
heap_4.c
Go to the documentation of this file.
1 /*
2  FreeRTOS V8.0.1 - Copyright (C) 2014 Real Time Engineers Ltd.
3  All rights reserved
4 
5  VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
6 
7  ***************************************************************************
8  * *
9  * FreeRTOS provides completely free yet professionally developed, *
10  * robust, strictly quality controlled, supported, and cross *
11  * platform software that has become a de facto standard. *
12  * *
13  * Help yourself get started quickly and support the FreeRTOS *
14  * project by purchasing a FreeRTOS tutorial book, reference *
15  * manual, or both from: http://www.FreeRTOS.org/Documentation *
16  * *
17  * Thank you! *
18  * *
19  ***************************************************************************
20 
21  This file is part of the FreeRTOS distribution.
22 
23  FreeRTOS is free software; you can redistribute it and/or modify it under
24  the terms of the GNU General Public License (version 2) as published by the
25  Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
26 
27  >>! NOTE: The modification to the GPL is included to allow you to !<<
28  >>! distribute a combined work that includes FreeRTOS without being !<<
29  >>! obliged to provide the source code for proprietary components !<<
30  >>! outside of the FreeRTOS kernel. !<<
31 
32  FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
33  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34  FOR A PARTICULAR PURPOSE. Full license text is available from the following
35  link: http://www.freertos.org/a00114.html
36 
37  1 tab == 4 spaces!
38 
39  ***************************************************************************
40  * *
41  * Having a problem? Start by reading the FAQ "My application does *
42  * not run, what could be wrong?" *
43  * *
44  * http://www.FreeRTOS.org/FAQHelp.html *
45  * *
46  ***************************************************************************
47 
48  http://www.FreeRTOS.org - Documentation, books, training, latest versions,
49  license and Real Time Engineers Ltd. contact details.
50 
51  http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
52  including FreeRTOS+Trace - an indispensable productivity tool, a DOS
53  compatible FAT file system, and our tiny thread aware UDP/IP stack.
54 
55  http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
56  Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
57  licenses offer ticketed support, indemnification and middleware.
58 
59  http://www.SafeRTOS.com - High Integrity Systems also provide a safety
60  engineered and independently SIL3 certified version for use in safety and
61  mission critical applications that require provable dependability.
62 
63  1 tab == 4 spaces!
64 */
65 
66 /*
67  * A sample implementation of pvPortMalloc() and vPortFree() that combines
68  * (coalescences) adjacent memory blocks as they are freed, and in so doing
69  * limits memory fragmentation.
70  *
71  * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the
72  * memory management pages of http://www.FreeRTOS.org for more information.
73  */
74 #include <stdlib.h>
75 
76 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
77 all the API functions to use the MPU wrappers. That should only be done when
78 task.h is included from an application file. */
79 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
80 
81 #include "FreeRTOS.h"
82 #include "task.h"
83 
84 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
85 
86 /* Block sizes must not get too small. */
87 #define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
88 
89 /* Assumes 8bit bytes! */
90 #define heapBITS_PER_BYTE ( ( size_t ) 8 )
91 
92 /* A few bytes might be lost to byte aligning the heap start address. */
93 #define heapADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
94 
95 /* Allocate the memory for the heap. */
96 static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
97 
98 /* Define the linked list structure. This is used to link free blocks in order
99 of their memory address. */
100 typedef struct A_BLOCK_LINK
101 {
102  struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
103  size_t xBlockSize; /*<< The size of the free block. */
104 } BlockLink_t;
105 
106 /*-----------------------------------------------------------*/
107 
108 /*
109  * Inserts a block of memory that is being freed into the correct position in
110  * the list of free memory blocks. The block being freed will be merged with
111  * the block in front it and/or the block behind it if the memory blocks are
112  * adjacent to each other.
113  */
114 static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
115 
116 /*
117  * Called automatically to setup the required heap structures the first time
118  * pvPortMalloc() is called.
119  */
120 static void prvHeapInit( void );
121 
122 /*-----------------------------------------------------------*/
123 
124 /* The size of the structure placed at the beginning of each allocated memory
125 block must by correctly byte aligned. */
126 static const uint16_t heapSTRUCT_SIZE = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
127 
128 /* Ensure the pxEnd pointer will end up on the correct byte alignment. */
129 static const size_t xTotalHeapSize = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
130 
131 /* Create a couple of list links to mark the start and end of the list. */
132 static BlockLink_t xStart, *pxEnd = NULL;
133 
134 /* Keeps track of the number of free bytes remaining, but says nothing about
135 fragmentation. */
136 static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
137 static size_t xMinimumEverFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
138 
139 /* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
140 member of an BlockLink_t structure is set then the block belongs to the
141 application. When the bit is free the block is still part of the free heap
142 space. */
143 static size_t xBlockAllocatedBit = 0;
144 
145 /*-----------------------------------------------------------*/
146 
147 void *pvPortMalloc( size_t xWantedSize )
148 {
149 BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
150 void *pvReturn = NULL;
151 
152  vTaskSuspendAll();
153  {
154  /* If this is the first call to malloc then the heap will require
155  initialisation to setup the list of free blocks. */
156  if( pxEnd == NULL )
157  {
158  prvHeapInit();
159  }
160  else
161  {
163  }
164 
165  /* Check the requested block size is not so large that the top bit is
166  set. The top bit of the block size member of the BlockLink_t structure
167  is used to determine who owns the block - the application or the
168  kernel, so it must be free. */
169  if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
170  {
171  /* The wanted size is increased so it can contain a BlockLink_t
172  structure in addition to the requested amount of bytes. */
173  if( xWantedSize > 0 )
174  {
175  xWantedSize += heapSTRUCT_SIZE;
176 
177  /* Ensure that blocks are always aligned to the required number
178  of bytes. */
179  if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
180  {
181  /* Byte alignment required. */
182  xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
183  }
184  else
185  {
187  }
188  }
189  else
190  {
192  }
193 
194  if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
195  {
196  /* Traverse the list from the start (lowest address) block until
197  one of adequate size is found. */
198  pxPreviousBlock = &xStart;
199  pxBlock = xStart.pxNextFreeBlock;
200  while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
201  {
202  pxPreviousBlock = pxBlock;
203  pxBlock = pxBlock->pxNextFreeBlock;
204  }
205 
206  /* If the end marker was reached then a block of adequate size
207  was not found. */
208  if( pxBlock != pxEnd )
209  {
210  /* Return the memory space pointed to - jumping over the
211  BlockLink_t structure at its start. */
212  pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );
213 
214  /* This block is being returned for use so must be taken out
215  of the list of free blocks. */
216  pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
217 
218  /* If the block is larger than required it can be split into
219  two. */
220  if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
221  {
222  /* This block is to be split into two. Create a new
223  block following the number of bytes requested. The void
224  cast is used to prevent byte alignment warnings from the
225  compiler. */
226  pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
227 
228  /* Calculate the sizes of two blocks split from the
229  single block. */
230  pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
231  pxBlock->xBlockSize = xWantedSize;
232 
233  /* Insert the new block into the list of free blocks. */
234  prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
235  }
236  else
237  {
239  }
240 
241  xFreeBytesRemaining -= pxBlock->xBlockSize;
242 
243  if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
244  {
245  xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
246  }
247  else
248  {
250  }
251 
252  /* The block is being returned - it is allocated and owned
253  by the application and has no "next" block. */
254  pxBlock->xBlockSize |= xBlockAllocatedBit;
255  pxBlock->pxNextFreeBlock = NULL;
256  }
257  else
258  {
260  }
261  }
262  else
263  {
265  }
266  }
267  else
268  {
270  }
271 
272  traceMALLOC( pvReturn, xWantedSize );
273  }
274  ( void ) xTaskResumeAll();
275 
276  #if( configUSE_MALLOC_FAILED_HOOK == 1 )
277  {
278  if( pvReturn == NULL )
279  {
280  extern void vApplicationMallocFailedHook( void );
282  }
283  else
284  {
286  }
287  }
288  #endif
289 
290  return pvReturn;
291 }
292 /*-----------------------------------------------------------*/
293 
294 void vPortFree( void *pv )
295 {
296 uint8_t *puc = ( uint8_t * ) pv;
297 BlockLink_t *pxLink;
298 
299  if( pv != NULL )
300  {
301  /* The memory being freed will have an BlockLink_t structure immediately
302  before it. */
303  puc -= heapSTRUCT_SIZE;
304 
305  /* This casting is to keep the compiler from issuing warnings. */
306  pxLink = ( void * ) puc;
307 
308  /* Check the block is actually allocated. */
309  configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
310  configASSERT( pxLink->pxNextFreeBlock == NULL );
311 
312  if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
313  {
314  if( pxLink->pxNextFreeBlock == NULL )
315  {
316  /* The block is being returned to the heap - it is no longer
317  allocated. */
318  pxLink->xBlockSize &= ~xBlockAllocatedBit;
319 
320  vTaskSuspendAll();
321  {
322  /* Add this block to the list of free blocks. */
323  xFreeBytesRemaining += pxLink->xBlockSize;
324  traceFREE( pv, pxLink->xBlockSize );
325  prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
326  }
327  ( void ) xTaskResumeAll();
328  }
329  else
330  {
332  }
333  }
334  else
335  {
337  }
338  }
339 }
340 /*-----------------------------------------------------------*/
341 
342 size_t xPortGetFreeHeapSize( void )
343 {
344  return xFreeBytesRemaining;
345 }
346 /*-----------------------------------------------------------*/
347 
349 {
350  return xMinimumEverFreeBytesRemaining;
351 }
352 /*-----------------------------------------------------------*/
353 
355 {
356  /* This just exists to keep the linker quiet. */
357 }
358 /*-----------------------------------------------------------*/
359 
360 static void prvHeapInit( void )
361 {
362 BlockLink_t *pxFirstFreeBlock;
363 uint8_t *pucHeapEnd, *pucAlignedHeap;
364 
365  /* Ensure the heap starts on a correctly aligned boundary. */
366  pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) );
367 
368  /* xStart is used to hold a pointer to the first item in the list of free
369  blocks. The void cast is used to prevent compiler warnings. */
370  xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
371  xStart.xBlockSize = ( size_t ) 0;
372 
373  /* pxEnd is used to mark the end of the list of free blocks and is inserted
374  at the end of the heap space. */
375  pucHeapEnd = pucAlignedHeap + xTotalHeapSize;
376  pucHeapEnd -= heapSTRUCT_SIZE;
377  pxEnd = ( void * ) pucHeapEnd;
378  configASSERT( ( ( ( uint32_t ) pxEnd ) & ( ( uint32_t ) portBYTE_ALIGNMENT_MASK ) ) == 0UL );
379  pxEnd->xBlockSize = 0;
380  pxEnd->pxNextFreeBlock = NULL;
381 
382  /* To start with there is a single free block that is sized to take up the
383  entire heap space, minus the space taken by pxEnd. */
384  pxFirstFreeBlock = ( void * ) pucAlignedHeap;
385  pxFirstFreeBlock->xBlockSize = xTotalHeapSize - heapSTRUCT_SIZE;
386  pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
387 
388  /* The heap now contains pxEnd. */
389  xFreeBytesRemaining -= heapSTRUCT_SIZE;
390 
391  /* Work out the position of the top bit in a size_t variable. */
392  xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
393 }
394 /*-----------------------------------------------------------*/
395 
396 static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
397 {
398 BlockLink_t *pxIterator;
399 uint8_t *puc;
400 
401  /* Iterate through the list until a block is found that has a higher address
402  than the block being inserted. */
403  for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
404  {
405  /* Nothing to do here, just iterate to the right position. */
406  }
407 
408  /* Do the block being inserted, and the block it is being inserted after
409  make a contiguous block of memory? */
410  puc = ( uint8_t * ) pxIterator;
411  if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
412  {
413  pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
414  pxBlockToInsert = pxIterator;
415  }
416  else
417  {
419  }
420 
421  /* Do the block being inserted, and the block it is being inserted before
422  make a contiguous block of memory? */
423  puc = ( uint8_t * ) pxBlockToInsert;
424  if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
425  {
426  if( pxIterator->pxNextFreeBlock != pxEnd )
427  {
428  /* Form one big block from the two blocks. */
429  pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
430  pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
431  }
432  else
433  {
434  pxBlockToInsert->pxNextFreeBlock = pxEnd;
435  }
436  }
437  else
438  {
439  pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
440  }
441 
442  /* If the block being inserted plugged a gab, so was merged with the block
443  before and the block after, then it's pxNextFreeBlock pointer will have
444  already been set, and should not be set here as that would make it point
445  to itself. */
446  if( pxIterator != pxBlockToInsert )
447  {
448  pxIterator->pxNextFreeBlock = pxBlockToInsert;
449  }
450  else
451  {
453  }
454 }
455 
#define mtCOVERAGE_TEST_MARKER()
Definition: FreeRTOS.h:717
void vPortInitialiseBlocks(void)
Definition: heap_4.c:354
void vTaskSuspendAll(void) PRIVILEGED_FUNCTION
Definition: tasks.c:1543
#define configASSERT(x)
size_t xPortGetMinimumEverFreeHeapSize(void)
Definition: heap_4.c:348
#define heapMINIMUM_BLOCK_SIZE
Definition: heap_4.c:87
struct A_BLOCK_LINK * pxNextFreeBlock
Definition: heap_4.c:102
#define configTOTAL_HEAP_SIZE
#define heapBITS_PER_BYTE
Definition: heap_4.c:90
void vPortFree(void *pv)
Definition: heap_4.c:294
#define heapADJUSTED_HEAP_SIZE
Definition: heap_4.c:93
#define traceFREE(pvAddress, uiSize)
Definition: FreeRTOS.h:559
struct A_BLOCK_LINK BlockLink_t
void vApplicationMallocFailedHook(void)
FreeRTOS hook (or callback) functions that are defined in this file.
void * pvPortMalloc(size_t xWantedSize)
Definition: heap_4.c:147
BaseType_t xTaskResumeAll(void) PRIVILEGED_FUNCTION
Definition: tasks.c:1581
#define portPOINTER_SIZE_TYPE
Definition: FreeRTOS.h:319
#define portBYTE_ALIGNMENT
Definition: portmacro.h:109
#define traceMALLOC(pvAddress, uiSize)
Definition: FreeRTOS.h:555
size_t xPortGetFreeHeapSize(void)
Definition: heap_4.c:342
size_t xBlockSize
Definition: heap_4.c:103