0e0b94d4897153458cecc01a87cb845e57c7418f
[cortex-from-scratch] / 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 #include <stm32.h>
32 #include <mmap.h>
33
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 /*       uint32_t * a =  alloc();
60          uint32_t * b = alloc();
61          uint32_t * c = alloc();
62          free(c);
63          uint32_t * d = alloc();
64
65          addrtohex(a);
66          addrtohex(b);
67          addrtohex(c);
68          addrtohex(d); */
69
70  }
71
72
73  /* void deletepool()  {
74          mem.SRAM_entry = NULL;
75  } */
76
77 /* Helper functions */
78 uint32_t * AddrFromIndex(unsigned int i)  {
79         return mem.SRAM_entry + ( i * mem.block_size );
80
81  }
82  
83 unsigned int IndexFromAddr(const uint32_t * p) {
84         return (((unsigned int)(p - mem.SRAM_entry)) / mem.block_size);
85
86 }
87
88 /* alloc and free */ 
89 void * alloc() {
90         if (mem.blocks_alloc < mem.blocks ) {
91                  unsigned int * p = (unsigned int *)AddrFromIndex( mem.blocks_alloc );
92                 *p = mem.blocks_alloc + 1;
93                  mem.blocks_alloc++;
94          }
95
96          void* ret = NULL;
97          if ( mem.free_blocks > 0 ) {
98                  ret = (void*)mem.m_next;
99                  --mem.free_blocks;
100          if (mem.free_blocks!=0) {
101                 mem.m_next = AddrFromIndex( *((unsigned int*)mem.m_next) );
102          }
103          else {
104                  mem.m_next = NULL;
105          }
106         }
107          
108          return ret;
109  }
110
111 void free(void* p)  {
112          if (mem.m_next != NULL) {
113                  (*(unsigned int *)p) = IndexFromAddr( mem.m_next );
114                  mem.m_next = (uint32_t *)p;
115         }
116          else {
117                  *((unsigned int*)p) = mem.blocks;
118                  mem.m_next = (uint32_t *) p;
119          }
120                 
121          ++mem.free_blocks;
122  }