3      Copyright (C) Dean Camera, 2009. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, and distribute this software 
  13   and its documentation for any purpose and without fee is hereby 
  14   granted, provided that the above copyright notice appear in all 
  15   copies and that both that the copyright notice and this 
  16   permission notice and warranty disclaimer appear in supporting 
  17   documentation, and that the name of the author not be used in 
  18   advertising or publicity pertaining to distribution of the 
  19   software without specific, written prior permission. 
  21   The author disclaim all warranties with regard to this 
  22   software, including all implied warranties of merchantability 
  23   and fitness.  In no event shall the author be liable for any 
  24   special, indirect or consequential damages or any damages 
  25   whatsoever resulting from loss of use, data or profits, whether 
  26   in an action of contract, negligence or other tortious action, 
  27   arising out of or in connection with the use or performance of 
  33  *  Dynamic, auto-defragmenting block memory allocator library. This library provides a convenient replacement for 
  34  *  the standard avr-libc dynamic memory allocation routines. Memory is handed out in block chunks, to reduce the 
  35  *  management memory overhead. 
  37  *  Unlike the normal memory allocation routines, this library gives out handles to memory which must be dereferenced 
  38  *  at the exact time of use, rather than handing back direct memory pointers. By using library managed handles 
  39  *  instead of pointers, allocated memory blocks can be shifted around as needed transparently to defragment the 
  40  *  memory as more blocks are requested. 
  42  *  The memory heap is static, thus the total memory usage of the compiled application (as reported by the avr-size 
  43  *  tool of the AVR-GCC toolchain) includes the dynamic memory heap. 
  45  *  The constants NUM_BLOCKS, BLOCK_SIZE and NUM_HANDLES must be defined in the project makefile (and passed to the 
  46  *  preprocessor via the -D GCC switch) for this library to compile. 
  48  *  NUM_BLOCKS indicates the number of memory blocks in the memory psudoheap which can be chaned together and handed 
  49  *  to the application via a memory handle. NUM_HANDLES is the maximum number of memory handles (pointing to one or 
  50  *  more chained memory blocks) which can be handed out simultaneously before requring a handle (and its associated 
  51  *  memory) to be freed. BLOCK_SIZE gives the number of bytes in each memory block. 
  62         /* Preprocessor Checks: */ 
  63                 #if (!defined(NUM_BLOCKS) || !defined(BLOCK_SIZE) || !defined(NUM_HANDLES)) 
  64                         #error NUM_BLOCKS, BLOCK_SIZE and NUM_HANDLES must be defined before use via makefile. 
  67         /* Public Interface - May be used in end-application: */ 
  69                         /** Macro to dereference a given memory handle into the given type. The given type should be a pointer 
  70                          *  if the memory is to contain an array of items, or should be a standard type (such as a primative or 
  71                          *  structure) if the memory is to hold a single item of a single type. */ 
  72                         #define DEREF(handle, type)       (*(type*)handle) 
  74                         /** Constant, giving the total heap size in bytes. */ 
  75                         #define ALLOCABLE_BYTES           (1UL * NUM_BLOCKS * BLOCK_SIZE) 
  78                         /** Memory handle type, used to store handles given by the library functions. */ 
  79                         typedef const void** Mem_Handle_t
; 
  81                         #if (ALLOCABLE_BYTES > 0xFFFF) || defined(__DOXYGEN__) 
  82                                 /** Type define for the size (in bytes) for an allocation for passing to the library functions. 
  83                                  *  The exact type width varies depending on the value of ALLOCABLE_BYTES to ensure that a single 
  84                                  *  allocation can request the entire heap if needed. 
  86                                 typedef uint32_t Alloc_Size_t
; 
  87                         #elif (ALLOCABLE_BYTES > 0xFF) 
  88                                 typedef uint16_t Alloc_Size_t
; 
  90                                 typedef uint8_t  Alloc_Size_t
; 
  93                         #if (NUM_BLOCKS > 0xFFFF) || defined(__DOXYGEN__) 
  94                                 /** Type define for a block number in the heap. The exact type width varies depending on the 
  95                                  *   value of NUM_BLOCKS to ensure that the type can store an index to any block in the block pool. 
  97                                 typedef uint32_t Block_Number_t
; 
  98                         #elif (NUM_BLOCKS > 0xFF) 
  99                                 typedef uint16_t Block_Number_t
; 
 101                                 typedef uint8_t  Block_Number_t
; 
 104                         #if (NUM_HANDLES > 0xFFFF) || defined(__DOXYGEN__) 
 105                                 /** Type define for a handle number. The exact type width varies depending on the value of NUM_HANDLES 
 106                                  *  to ensure that the type can store the index of any handle in the handle pool. 
 108                                 typedef uint32_t Handle_Number_t
; 
 109                         #elif (NUM_HANDLES > 0xFF) 
 110                                 typedef uint16_t Handle_Number_t
; 
 112                                 typedef uint8_t  Handle_Number_t
; 
 115                 /* Function Prototypes: */ 
 116                         /** Allocates a given number of blocks from the heap (calculated from the requested number of bytes) and 
 117                          *  returns a handle to the newly allocated memory. 
 119                          *  \param Bytes  The number of bytes requested to be allocated from the heap 
 121                          *  \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds 
 123                         Mem_Handle_t    
Mem_Alloc(const Alloc_Size_t Bytes
); 
 125                         /** Allocates a given number of blocks from the heap (calculated from the requested number of bytes) and 
 126                          *  returns a handle to the newly allocated memory. Calloced memory is automatically cleared to all 0x00 
 127                          *  values at the time of allocation. 
 129                          *  \param Bytes  The number of pre-cleared bytes requested to be allocated from the heap 
 131                          *  \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds 
 133                         Mem_Handle_t    
Mem_Calloc(const Alloc_Size_t Bytes
); 
 135                         /** Deallocates a given memory handle, and attempts to allocates the given number of blocks from the heap 
 136                          *  (calculated from the requested number of bytes) immediately following the deallocation. The new memory 
 137                          *  may be located in the same area as the previous memory, but this is not guaranteed. 
 139                          *  \param CurrAllocHdl  Handle to an already allocated section of memory in the heap to deallocate 
 140                          *  \param Bytes         The number of bytes requested to be allocated from the heap following the 
 143                          *  \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds 
 145                          *  \warning Even if the allocation fails, the deallocation will still occur. Care should be taken to ensure 
 146                          *           that the previously allocated memory is not used following an unsuccessful realloc(). 
 148                         Mem_Handle_t    
Mem_Realloc(Mem_Handle_t CurrAllocHdl
, const Alloc_Size_t Bytes
); 
 150                         /** Deallocates a given previously allocated section of memory from the heap. 
 152                          *  \param CurrAllocHdl  Handle to a previously allocated section of memory in the heap 
 154                         void            Mem_Free(Mem_Handle_t CurrAllocHdl
); 
 156                         /** Returns the total number of unallocated blocks in the heap. 
 158                          *  \return Number of free blocks in the heap, as a Block_Number_t integer 
 160                         Block_Number_t  
Mem_TotalFreeBlocks(void); 
 162                         /** Returns the total number of unallocated handles in the handle pool. 
 164                          *  \return Number of free handles in the handle pool, as a Handle_Number_t integer 
 166                         Handle_Number_t 
Mem_TotalFreeHandles(void); 
 168         /* Private Interface - For use in library only: */ 
 169         #if !defined(__DOXYGEN__) 
 171                         #define BLOCK_USED_MASK           (1 << 0) 
 172                         #define BLOCK_LINKED_MASK         (1 << 1) 
 174                 /* Function Prototypes: */ 
 175                         #if defined(INCLUDE_FROM_DYNALLOC_C) 
 176                                 static uint8_t Mem_GetBlockFlags(const Block_Number_t BlockNum
); 
 177                                 static void    Mem_SetBlockFlags(const Block_Number_t BlockNum
, const uint8_t Flags
); 
 178                                 static void    Mem_Defrag(void);