83b2df20ba32a5fe9f3eeaa1c5b4b492c9a4d8ee
[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/tinyprintf.h>
34 #include <lib/string.h>
35
36  
37 void kpool_init(mem_pool_t * pool, size_t size_arg, unsigned int blocks_arg, unsigned char* entry_SRAM) {
38
39          pool->blocks = blocks_arg;
40          pool->block_size = size_arg;
41          pool->blocks_init = 0;
42          pool->SRAM_entry = entry_SRAM;
43          memset(entry_SRAM, 0x00, (sizeof(char) * (size_arg * blocks_arg)));
44          pool->free_blocks = blocks_arg;
45          pool->m_next = pool->SRAM_entry;
46  }
47
48  /* void deletepool()  {
49          pool->SRAM_entry = NULL;
50  } */
51
52 /* Helper functions */
53 unsigned char* AddrFromIndex(mem_pool_t * pool, unsigned int i)  {
54         return pool->SRAM_entry + ( i * pool->block_size );
55
56  }
57  
58 unsigned int IndexFromAddr(mem_pool_t * pool, const unsigned char* p) {
59         return (((unsigned int)(p - pool->SRAM_entry)) / pool->block_size);
60
61 }
62
63 /* alloc and free */ 
64 void * kalloc(mem_pool_t * pool) {
65         if (pool->blocks_init < pool->blocks ) {
66                  unsigned int * p = (unsigned int *)AddrFromIndex(pool, pool->blocks_init );
67                 *p = pool->blocks_init + 1;
68                  pool->blocks_init++;
69          }
70
71          void* ret = NULL;
72          if ( pool->free_blocks > 0 ) {
73                  ret = (void*)pool->m_next;
74                  --pool->free_blocks;
75          if (pool->free_blocks!=0) {
76                 pool->m_next = AddrFromIndex(pool, *((unsigned int*)pool->m_next) );
77          }
78          else {
79                  pool->m_next = NULL;
80          }
81         }
82          
83          return ret;
84  }
85
86 void kfree(mem_pool_t * pool, void* p)  {
87          if (pool->m_next != NULL) {
88                  (*(unsigned int *)p) = IndexFromAddr(pool, pool->m_next );
89                  pool->m_next = (unsigned char*)p;
90         }
91          else {
92                  *((unsigned int*)p) = pool->blocks;
93                  pool->m_next = (unsigned char*) p;
94          }
95                 
96          ++pool->free_blocks;
97 }
98
99 /* Heap info helper functions */
100
101 void kheap_info(mem_pool_t * pool) {
102
103
104         printf("HEAP INFO:\n");
105         printf("BLOCKS FREE: %d\n", pool->free_blocks);
106
107         unsigned char* curr_addr = pool->SRAM_entry;
108
109         // Loop over heap blocks
110         for (int i = 0; i < pool->blocks; i++) {
111                 printf("\nBLOCK %d", i+1);
112                 for (int j = 0; j < (pool->block_size-1); j++) {
113
114                         if (j % 10 == 0)
115                                 printf("\n%x ", curr_addr);
116                         printf("%#x ", *curr_addr);
117                         curr_addr++;
118                 }
119                 printf("\n");
120                 curr_addr++;
121                 
122         }
123         printf("\n");
124
125 }
126
127
128