--- /dev/null
+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.
+
+
+
# 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:
# 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 $@
/* 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
/* 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);
+/* (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>
// 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
{
*(.data)
}
- .bss : ALIGN(256)
+ .bss : ALIGN(256)
{
*(.bss)
}
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);
+/* (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) {
}
+/* 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;
}
-
-}
+} */
+
+
--- /dev/null
+/* (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;
+ }