]> robinkrens.nl - git repository - cortex-from-scratch/commitdiff
fixed-sized memory pool allocator
authorRobin Krens <robin@robinkrens.nl>
Mon, 22 Jul 2019 18:22:23 +0000 (02:22 +0800)
committerRobin Krens <robin@robinkrens.nl>
Mon, 22 Jul 2019 18:22:23 +0000 (02:22 +0800)
AUTHORS [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makefile
include/mmap.h
include/stm32.h
ivt.c
link.ld
main.c
mm.c
pool.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..eb5ac97
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+You are free to:
+       
+       * Share — copy and redistribute the material in any medium or format
+       * Adapt — remix, transform, and build upon the material
+
+Under the following terms:
+
+       * Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
+       * NonCommercial — You may not use the material for commercial purposes.
+       * ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
+
+
+
index 788955b5fde1992c9de171a285e5f42eba3ab48e..d7e165283e817d24d8ca22f7c55b0c6a8e020c79 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,33 +1,39 @@
 # Copyright 2019 - Robin Krens
+#
+# TODO: Somehow integrate this assembly start.asm (start.o)
+#
+
 # Cross compilers links
 CC=arm-none-eabi-gcc
 LD=arm-none-eabi-ld
-AR=$(TOOLROOT)/arm-none-eabi-ar
 AS=arm-none-eabi-as
 MKIMG=arm-none-eabi-objcopy
 
 # Compiler flags
 # TODO:Cortex-m3 or Cortex-m0?
 LDFLAGS+= -mthumb -mcpu=cortex-m3 
-CFLAGS+= -mcpu=cortex-m3 -mthumb -g 
+ASFLAGS+= -mcpu=cortex-m3 -mthumb -g
+CFLAGS+= -mcpu=cortex-m3 -mthumb -g -ffreestanding 
+
+ODIR = obj
+_OBJ = main.o uart.o ivt.o systick.o sysinfo.o lib.o regf.o pool.o
+OBJ = $(patsubst %, $(ODIR)/%,$(_OBJ))
+
+
+$(ODIR)/%.o: %.c $(DEPS)
+       @mkdir -p $(@D)
+       $(CC) -c $< $(CFLAGS) -I./include -o $@
 
 # Start up machine assembly
 as: 
-       $(AS) $(CFLAGS) -o start.o start.asm
+       $(AS) $(ASFLAGS) -o start.o start.asm
 
 # Compile and link all
-all:
-       $(AS) $(CFLAGS) -o start.o start.asm
-       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o main.o main.c
-       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o uart.o uart.c
-       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o ivt.o ivt.c 
-       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o systick.o systick.c 
-       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o sysinfo.o sysinfo.c 
-       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o lib.o lib.c 
-       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o mm.o mm.c 
-       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o regf.o regf.c 
-       $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o systick.o sysinfo.o lib.o mm.o regf.o
-       $(MKIMG) -Obinary -R .data start.out kernel.bin
+kernel: $(OBJ)
+       $(AS) $(ASFLAGS) -o start.o start.asm
+       $(LD) -nostartfiles -Map $@.MAP -T link.ld -o $@.ELF start.o $^ --print-memory-usage
+       @echo "Creating binary..."
+       $(MKIMG) -Obinary -R .data $@.ELF $@.bin
 
 # Run in Qemu; note this is a patched version for stm32-f103c8
 run:
@@ -35,23 +41,28 @@ run:
 
 # Examine all sections
 examine-all:
-       arm-none-eabi-objdump -D start.out | less
+       arm-none-eabi-objdump -D kernel.ELF | less
 
 # Examine just headers
 examine-header:
-       arm-none-eabi-objdump -x start.out | less
+       arm-none-eabi-objdump -x kernel.ELF | less
 
 # Flash kernel to board
 flash:
        stm32flash -w kernel.bin -v /dev/ttyUSB0
 
+.PHONY: clean
 
-%.o: %.c
-       $(CC) -c $(CFLAGS) $< -o $@
-       $(CC) -MM $(CFLAGS) $< > $*.d
+clean:
+       rm -rf $(ODIR)/*.o start.o kernel.*
 
-%.o: %.s
-       $(CC) -c $(CFLAGS) $< -o $@
+# Altijd handig deze template
+#%.o: %.c
+#      $(CC) -c $(CFLAGS) $< -o $@
+#      $(CC) -MM $(CFLAGS) $< > $*.d
+#
+#%.o: %.s
+#      $(CC) -c $(CFLAGS) $< -o $@
 
 
 
index 6f4fabb576e83c2f1088d15fd30931de145aba04..aa8a90294c414c63be1f450734b18c200df51511 100644 (file)
@@ -16,6 +16,7 @@
 /* SYSTEM CONTROL BLOCK REGISTER */
 #define SCB_VTOR ((volatile uint32_t *)( 0xE000ED08)) // VECTOR TABLE
 #define SCB_VTOR_ST ((volatile uint32_t *)( 0xE000ED04)) // STATUS OF VECTOR
+#define SCB_CCR ((volatile uint32_t *)( 0xE000ED14)) // SET SOFTWARE TRAPS
 
 /* NESTED VECTOR INTERRUPT CONTROL REGISTER */
 #define NVIC_ISER0 ((volatile uint32_t*)( 0xE000E100)) // interrupt set enable register
index 62ee93e5023b37875b01b351cb88ef32543ca84d..bc510d4e7eb16c0ae745d647f686e47bfe09e7f6 100644 (file)
@@ -30,10 +30,15 @@ extern void addrtohex(const uint32_t);
 
 /* MM.C */
 extern void mm_init();
-extern void * mm_alloc(size_t);
+extern void * malloc(size_t);
 extern void free(void *);
 extern void test_memory(uint32_t *);
 
+/* POOL.c */
+extern void pool_init(size_t, unsigned int, uint32_t *);
+extern void * alloc();
+extern void free();
+
 /* REGF.C */ 
 extern void regw_u8(volatile uint32_t *, uint8_t, short, short);
 extern void regw_u32(volatile uint32_t *, uint32_t, short, short);
diff --git a/ivt.c b/ivt.c
index 973d3062221170fa2eacfa6dc47ab8ef35910ed0..33a2bd4294311c4e37ba55d68d55e80a758df3cc 100644 (file)
--- a/ivt.c
+++ b/ivt.c
@@ -1,3 +1,13 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/20 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * 
+ * */
+
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -105,10 +115,11 @@ void ivt_init() {
        // don't need to relocate or init this here
        extern void * reset,  * nmi, * hardfault;
 
-       for (int i = 1; i <= 6 ; i++) {
+       for (int i = 1; i <= 64 ; i++) {
                ivt_set_gate(i, dummy_isr, 0);
        }
 
+
        /* the vector table starts at 0x0. Since the address 0x0 point to 
         * bootcode, it is on ROM or FLASH. The vector table can be
         * relocated to other memory locations. We can do this by setting 
diff --git a/link.ld b/link.ld
index 085ab79e349b6080ef4dcef63e518afff0108017..db378882b9c9371cbda11c9ef7eaf7954ec3631a 100644 (file)
--- a/link.ld
+++ b/link.ld
@@ -21,7 +21,7 @@ SECTIONS
        {
                *(.data)
        } 
-       .bss : ALIGN(256)
+       .bss : ALIGN(256) 
        {
                *(.bss)
        }
diff --git a/main.c b/main.c
index 73e55e06c9894123b20fb5447044a854623678d5..19d0eb55e92f784d5b207bc45996118ef40370c2 100644 (file)
--- a/main.c
+++ b/main.c
@@ -48,11 +48,11 @@ void main()
        uart_init();
        //uart_puts("LOADING SYSTEM 0.1 ...\n");
        systick_init();
-       mm_init();
+//     mm_init();
        sysinfo();
 
-       //int * p2 = mm_alloc(512);
-       //memset(p2, 'a', 512);
+
+       pool_init(20, 5, 0x20000800);
 
        //addrtohex(p2);
        //addrtohex(*p2);
diff --git a/mm.c b/mm.c
index 77029e769f2fb85d623cbae4b9a8c091428888bd..1e20f755c1abe2873b3848058d50abc7b509dac7 100644 (file)
--- a/mm.c
+++ b/mm.c
@@ -1,59 +1,82 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/20 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * Simple bitmap on bitband memory implementation for kernel
+ * heap. Sensitive to fragmentation over time. Bitband 
+ * memory makes it possible to access each bit of memory
+ * atomically. 
+ * 
+ * DEPRECATED
+ *
+ * */
+
+
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stm32.h>
 #include <mmap.h>
 
-/* TOTAL SRAM MEMORY: 64kB 
- * 64 chunks of 1kB 
- * 128 chunks of 512 bytes
- * SIMPLE BITMAP IMPLEMENTATION
+
+#define CHUNKS 256
+
+#define MEM_VALUE(addr) *((volatile uint32_t *) (addr))
+#define MEM_ADDR(addr) ((uint32_t *) (addr))
+#define BITBAND(a, b) ((a & 0xF0000000) + 0x02000000 + ((a &0xFFFFF)<<5) + (b<<2))
+#define INDEXTOADDR(a) (((a & 0xFFFFF) >> 5) + ((a & 0xFF000000) - 0x02000000))
+
+
+/* Total SRAM: ~ 64kB 
+ * Divided into chunks (256 bytes)
+ * Each bit will index a chunk
+ * Bits needed: 0x100 (= 4 uint32_t)
  * */
 
+//uint32_t chunk_index[4];
 
-#define CHUNKS  128
-#define FREE   0x00
-#define ALLOC  0x01
+void mm_init() {
 
-#define BASE 0x20000400
 
-#define SET_SIZE(s)    (s << 8)
-#define SET_FLAGS(f)   (f << 24)
-#define IS_ALLOC(c)    ((c >> 24) & 0x0F )
-#define PADDR(i)       (0x20000400 + (i * 0x200))
-#define I_OFFSET(p)     ((p  - 0x20000400))
+//     memset(&chunk_index, 0, sizeof(uint32_t) * 4);
 
-uint32_t chunk[CHUNKS];
 
-/* 
- * | FLAGS | SIZE   | RESERVED |
- * | 0x00  | 0x0000 | 0x00             |
- *
- * */
+//     uint32_t *p = MEM_ADDR(0x20000278);
+       
+//     extern stub();
+//     stub();
+       // __asm__ __volatile__ ("udiv r1, r3 ,%0" :: "r"(0)); 
+//
+//     for(;;);
+//     *p = (uint32_t volatile) 0x12345678;
+//     *x = (uint32_t volatile) 0x12345679;
+//     addrtohex(p);
+//     addrtohex(*p);
+//     MEM_ADDR(x) = 0x1;
+//
+       
 
+//     char * new = malloc(10);
+//     addrtohex(new);
+//     char * new2 = malloc(10);
+//     addrtohex(new2);
 
-void mm_init() {
 
-       // interrupt vector
-       chunk[0] = SET_SIZE(96) | SET_FLAGS(ALLOC); 
+       //uint32_t * test = MEM_ADDR(0x20000000);
+       //uint32_t random_location = MEM_VALUE(0x20000000);
 
-       // test
-       /* uart_puts("ALLOC:\n");
-       int * p = mm_alloc(100);
-       *p = 0x12345678;
+       //uint32_t random_location = 0x20000900;
 
-       addrtohex(p);
-       addrtohex(*p);
+       //MEM_VALUE(random_location);
+       //MEM_VALUE(BITBAND(random_location, 0)) = 0x1;
 
-       uart_puts("FREE:\n");
+       //addrtohex(MEM_VALUE(random_location));
 
-       int * p2 = mm_alloc(100);
-       *p2 = 0xFFFFAAAA;
-       addrtohex(p2);
-       addrtohex(*p2);
 
-       free(p);
-       free(p2); */
+       
 }
 
  void test_memory(uint32_t * ptr) {
@@ -66,37 +89,43 @@ void mm_init() {
 
 } 
 
+/* BIT BAND SCAN */
 
-void * mm_alloc(size_t size) { // in bytes
+ /* uint32_t fits(uint32_t * current, size_t size) {
+       uint32_t addr_start = current;
+       for (int i = 1; i < size; i++) {
+               current + 4; // next bit offset is 0x4
+               if ((MEM_VALUE(current)) == 0x1) 
+                       return 0x0;
+       }
+       return addr_start;
+ } */
 
-       if (size > 512) {
-               uart_puts("SYSERROR: WE CAN'T ALLOCATE THAT MUCH!\n");
-               return NULL; 
-       }
 
-       /* check which chunk is free */
-       for (int i = 1; i < CHUNKS; i++) {
-               if (!IS_ALLOC(chunk[i])) {
-                       chunk[i] = SET_SIZE(size) | SET_FLAGS(ALLOC);
-                       return (void *) PADDR(i);
-               }
-       }
-       
-       uart_puts("SYSERROR: OUT OF MEMORY\n");
-       return NULL;
-}
+/* void * malloc(size_t size) {
 
-void free(void *ptr) {
+       if (size < 256) {
 
-       uint32_t index = (uint32_t) I_OFFSET(ptr) / 0x200;
+               extern char * _endofbss;
 
-       uint32_t tmp = chunk[index];
-       if (!IS_ALLOC(tmp))
-               uart_puts("SYSERROR: ALREADY FREED!\n");
+               uint32_t start = (uint32_t) &chunk_index[0];    
+               uint32_t current;
+               int offset = 0x100;
 
-       else if(index < CHUNKS) {
-               chunk[index] = SET_FLAGS(FREE) | SET_SIZE(0);
+               uint32_t * index = MEM_ADDR(BITBAND(start, 0));
+               for(int i = 0; i < CHUNKS; i++) {
+                       if (*index == 0x0) {
+                               addrtohex(*index);
+                               *index = 0x1;
+                               return INDEXTOADDR(((uint32_t)index)) + (i * offset);
+                       }
+                       index += 0x04;
+               }
+               return NULL;
        }
-               
-}
+} */
+
 
diff --git a/pool.c b/pool.c
new file mode 100644 (file)
index 0000000..fa08c29
--- /dev/null
+++ b/pool.c
@@ -0,0 +1,122 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/20 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * Fixed-sized memory pool allocation. A so called
+ * memory-pool (i.e. 4kB * 12 blocks) can be 
+ * initialized. Note: this allocator is for use on
+ * processors without an MMU (memory management 
+ * unit). A MPU (memory protection unit), if 
+ * available can be used to protect certain zones.
+ *
+ * This work is based on an article of Ben Kenwright
+ * 
+ * Preconditions: programmer should make sure the 
+ * SRAM entry point + (blocks * blocksize) is free. 
+ *
+ * $SAMPLE USAGE$
+ * KERNEL: can use initialize a big pool for all
+ * user tasks
+ *
+ * USER TASKS/PROCESS: can use this to dynamically
+ * allocate their own memory (i.e. heap)
+ * 
+ * 
+ * * */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stm32.h>
+#include <mmap.h>
+
+
+struct MEMPOOL {
+
+       unsigned short blocks; 
+       unsigned short block_size; 
+       unsigned short free_blocks;
+       unsigned short blocks_alloc; 
+       uint32_t * SRAM_entry;
+       uint32_t * m_next; 
+
+};
+
+struct MEMPOOL mem;
+
+void pool_init(size_t size_arg, unsigned int blocks_arg, uint32_t * entry_SRAM) {
+
+        mem.blocks = blocks_arg;
+        mem.block_size = size_arg;
+        mem.SRAM_entry = entry_SRAM;
+        memset(entry_SRAM, 0x00, (sizeof(char) * (size_arg * blocks_arg)));
+        mem.free_blocks = blocks_arg;
+        mem.m_next = mem.SRAM_entry;
+
+
+/*      uint32_t * a =  alloc();
+        uint32_t * b = alloc();
+        uint32_t * c = alloc();
+        free(c);
+        uint32_t * d = alloc();
+
+        addrtohex(a);
+        addrtohex(b);
+        addrtohex(c);
+        addrtohex(d); */
+
+ }
+
+
+ /* void deletepool()  {
+        mem.SRAM_entry = NULL;
+ } */
+
+uint32_t * AddrFromIndex(unsigned int i)  {
+       return mem.SRAM_entry + ( i * mem.block_size );
+
+ }
+unsigned int IndexFromAddr(const uint32_t * p) {
+       return (((unsigned int)(p - mem.SRAM_entry)) / mem.block_size);
+
+}
+
+void * alloc() {
+       if (mem.blocks_alloc < mem.blocks ) {
+                unsigned int * p = (unsigned int *)AddrFromIndex( mem.blocks_alloc );
+               *p = mem.blocks_alloc + 1;
+                mem.blocks_alloc++;
+        }
+
+        void* ret = NULL;
+        if ( mem.free_blocks > 0 ) {
+                ret = (void*)mem.m_next;
+                --mem.free_blocks;
+        if (mem.free_blocks!=0) {
+               mem.m_next = AddrFromIndex( *((unsigned int*)mem.m_next) );
+        }
+        else {
+                mem.m_next = NULL;
+        }
+       }
+        
+        return ret;
+ }
+
+void free(void* p)  {
+        if (mem.m_next != NULL) {
+                (*(unsigned int *)p) = IndexFromAddr( mem.m_next );
+                mem.m_next = (uint32_t *)p;
+       }
+        else {
+                *((unsigned int*)p) = mem.blocks;
+                mem.m_next = (uint32_t *) p;
+        }
+               
+        ++mem.free_blocks;
+ }