tested working terminal and reordering of code
[cortex-from-scratch] / lib / pool.c
1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
2  * 
3  * $LOG$
4  * 2019/7/20 - ROBIN KRENS      
5  * Initial version 
6  * 
7  * $DESCRIPTION$
8  * Fixed-sized memory pool allocation. A so called * memory-pool
9  * (i.e. 4kB * 12 blocks) can be initialized. Note: this allocator
10  * is for use on processors without an MMU (memory management 
11  * unit). A MPU (memory protection unit), if available can be used
12  * to protect certain zones.
13  *
14  * This work is based on an article of Ben Kenwright.
15  * 
16  * Preconditions: programmer should make sure the SRAM entry point
17  * + (blocks * blocksize) is free. 
18  *
19  * $SAMPLE USAGE$
20  * KERNEL: can initialize a big pool for all user tasks
21  *
22  * USER TASKS/PROCESS: can use this to dynamically allocate their
23  * own memory (i.e. heap)
24  * 
25  * 
26  * * */
27
28 #include <stdbool.h>
29 #include <stddef.h>
30 #include <stdint.h>
31
32 #include <lib/pool.h>
33 #include <lib/string.h>
34
35 struct MEMPOOL {
36
37         unsigned short blocks; 
38         unsigned short block_size; 
39         unsigned short free_blocks;
40         unsigned short blocks_alloc; 
41         uint32_t * SRAM_entry;
42         uint32_t * m_next; 
43
44 };
45
46 struct MEMPOOL mem;
47
48  
49 void pool_init(size_t size_arg, unsigned int blocks_arg, uint32_t * entry_SRAM) {
50
51          mem.blocks = blocks_arg;
52          mem.block_size = size_arg;
53          mem.SRAM_entry = entry_SRAM;
54          memset(entry_SRAM, 0x00, (sizeof(char) * (size_arg * blocks_arg)));
55          mem.free_blocks = blocks_arg;
56          mem.m_next = mem.SRAM_entry;
57  }
58
59  /* void deletepool()  {
60          mem.SRAM_entry = NULL;
61  } */
62
63 /* Helper functions */
64 uint32_t * AddrFromIndex(unsigned int i)  {
65         return mem.SRAM_entry + ( i * mem.block_size );
66
67  }
68  
69 unsigned int IndexFromAddr(const uint32_t * p) {
70         return (((unsigned int)(p - mem.SRAM_entry)) / mem.block_size);
71
72 }
73
74 /* alloc and free */ 
75 void * alloc() {
76         if (mem.blocks_alloc < mem.blocks ) {
77                  unsigned int * p = (unsigned int *)AddrFromIndex( mem.blocks_alloc );
78                 *p = mem.blocks_alloc + 1;
79                  mem.blocks_alloc++;
80          }
81
82          void* ret = NULL;
83          if ( mem.free_blocks > 0 ) {
84                  ret = (void*)mem.m_next;
85                  --mem.free_blocks;
86          if (mem.free_blocks!=0) {
87                 mem.m_next = AddrFromIndex( *((unsigned int*)mem.m_next) );
88          }
89          else {
90                  mem.m_next = NULL;
91          }
92         }
93          
94          return ret;
95  }
96
97 void free(void* p)  {
98          if (mem.m_next != NULL) {
99                  (*(unsigned int *)p) = IndexFromAddr( mem.m_next );
100                  mem.m_next = (uint32_t *)p;
101         }
102          else {
103                  *((unsigned int*)p) = mem.blocks;
104                  mem.m_next = (uint32_t *) p;
105          }
106                 
107          ++mem.free_blocks;
108  }