From: Robin Krens <robin@robinkrens.nl>
Date: Wed, 24 Jul 2019 20:26:08 +0000 (+0800)
Subject: tested working terminal and reordering of code
X-Git-Url: https://robinkrens.nl/gitweb/?a=commitdiff_plain;h=918e9bbf26d44cb0087d35637e2e0f90ca37d7c3;p=cortex-from-scratch

tested working terminal and reordering of code
---

diff --git a/Makefile b/Makefile
index b4a4133..520f0f1 100644
--- a/Makefile
+++ b/Makefile
@@ -15,24 +15,42 @@ LDFLAGS+= -mthumb -mcpu=cortex-m3
 ASFLAGS+= -mcpu=cortex-m3 -mthumb -g
 CFLAGS+= -mcpu=cortex-m3 -mthumb -g -ffreestanding 
 
+INCLUDE+= -Iinclude 
+
 BIN = bin
 
 ODIR = obj
-_OBJ = ivt.o uart.o systick.o sysinfo.o lib.o regf.o pool.o term.o main.o
+_OBJ = ivt.o systick.o sysinfo.o term.o main.o 
 OBJ = $(patsubst %, $(ODIR)/%,$(_OBJ))
 
+DDIR = obj/drivers
+_DRIVERS = uart.o
+DRIVERS = $(patsubst %, $(DDIR)/%,$(_DRIVERS))
+
+LDIR = obj/lib
+_LIBS = string.o stdio.o regfunc.o pool.o  
+LIBS = $(patsubst %, $(LDIR)/%,$(_LIBS))
+
+$(DDIR)/%.o: drivers/%.c
+	@mkdir -p $(@D) 
+	$(CC) -c $< $(CFLAGS) $(INCLUDE) -o $@
+
 $(ODIR)/%.o: %.c 
 	@mkdir -p $(@D)
 	$(CC) -c $< $(CFLAGS) -I./include -o $@
 
+$(LDIR)/%.o: lib/%.c 
+	@mkdir -p $(@D)
+	$(CC) -c $< $(CFLAGS) -I./include -o $@
+
 # Start up machine assembly
 as: 
 	$(AS) $(ASFLAGS) -o start.o start.asm
 
 # Compile and link all
-kernel: $(OBJ)
+kernel: $(OBJ) $(DRIVERS) $(LIBS) 
 	$(AS) $(ASFLAGS) -o start.o start.asm
-	$(LD) -nostartfiles -Map $@.MAP -T link.ld -o $(BIN)/$@.ELF start.o $^ --print-memory-usage
+	$(LD) -nostartfiles -Map $(BIN)/$@.MAP -T link.ld -o $(BIN)/$@.ELF start.o $^ --print-memory-usage
 	@echo "Creating binary..."
 	@mkdir -p $(BIN)
 	$(MKIMG) -Obinary -R .data $(BIN)/$@.ELF  $(BIN)/$@.bin
@@ -56,7 +74,7 @@ flash:
 .PHONY: clean
 
 clean:
-	rm -rf $(ODIR)/*.o start.o $(BIN)/kernel.*
+	rm -rf $(ODIR)/* start.o $(BIN)/kernel.*
 
 # Altijd handig deze template
 #%.o: %.c
diff --git a/drivers/README b/drivers/README
new file mode 100644
index 0000000..61c2416
--- /dev/null
+++ b/drivers/README
@@ -0,0 +1,2 @@
+Note to self: Place drivers or loadable modules here
+
diff --git a/drivers/uart.c b/drivers/uart.c
new file mode 100644
index 0000000..6fc940b
--- /dev/null
+++ b/drivers/uart.c
@@ -0,0 +1,111 @@
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/mmap.h>
+#include <sys/robsys.h>
+
+#include <lib/regfunc.h>
+#include <lib/string.h>
+
+#include <drivers/uart.h>
+
+#define RXNE ((*USART1_SR >> 5) & 0x1)
+#define UARTBUF 256
+#define ECHO 1
+
+static struct {
+       	 uint8_t buf[UARTBUF];
+         uint32_t rpos;
+       	 uint32_t wpos;
+} linefeed;
+
+
+void * uart_handler() {
+
+	//uart_puts("echo: ");
+ 	while (RXNE) {
+		char echochar = *USART1_DR;
+//		uart_putc(echochar);
+                linefeed.buf[linefeed.wpos++] = echochar;
+                 if (linefeed.wpos == UARTBUF)
+                         linefeed.wpos = 0;
+		//regw_u32(USART1_DR, echochar, 0, O_WRITE);
+	}
+	//uart_putc('\n');
+      		
+}
+
+void uart_init() {
+
+	linefeed.rpos = 0; 
+	linefeed.wpos = 0;
+
+	//memset(&linefeed, 0, (sizeof(struct linefeed) ));
+	regw_u32(RCC_APB2ENR, 0x4005, 0, SETBIT);// enable clock to UART1, AFIO and GPIOA
+	
+	/* (after enable GPIOA), on PA9&PA10 and set mode
+	 *  to alternative output */
+	regw_u32(GPIOA_CRH, 0x444444D4, 0, OWRITE);
+	regw_u8(AFIO_EVCR, 0x89, 0, OWRITE);// set event control register, output on PA, Pin 9
+
+	//disable temporarily to set values
+	regw_u8(USART1_CR1, 0x0, 13, SETBIT);
+
+	/* baud rate 115200,  8MHz / (16 * USARTDIV)
+	 * USARTDIV = 4.34
+	 * FRACTION: 16 x 0.34 = 0d5.44 0d5 -> 0x5
+	 * MANTISSA: 0d4.34 0d4 -> 0x4 
+	 * USART_BRR = 0x45*/
+
+	regw_u32(USART1_BRR, 0x00000045, 0, OWRITE);
+	regw_u32(USART1_CR2, 0x0000, 0, OWRITE); //set stop bit, default is 1 stop bit 0x00
+	
+	/* parity = 8 bit, UART1 enabled,
+	 * TX and RX enabled, interrupts enabled */
+	//regw_u32(USART1_CR1, 0x000030AC, 0, O_WRITE);
+	regw_u32(USART1_CR1, 0x0000302C, 0, OWRITE);
+
+	ivt_set_gate(53, uart_handler, 0);
+	
+	*NVIC_ISER1 = (1 << 5); // Enable UART interrupt at NVIC
+}
+
+static void wait() {
+	for (int i = 0; i < 100; i++);
+}
+
+extern void uart_putc(unsigned char ch) {
+	
+  	if (ch == '\n') {
+		while (*USART1_SR & 0x0C) { } // transmit data register empty and complete
+		regw_u8(USART1_DR, 0x0D, 0, OWRITE); // return line
+	}
+
+	while (*USART1_SR & 0x0C) {} 
+		regw_u8(USART1_DR, ch, 0, OWRITE);
+
+	wait();
+}
+
+char uart_getc(void) {
+         char c;
+
+         if (linefeed.rpos != linefeed.wpos) {
+                 c = linefeed.buf[linefeed.rpos++];
+                 if (linefeed.rpos == UARTBUF)
+                         linefeed.rpos = 0;
+                 return c;
+         }
+         return 0;
+ }
+
+
+// move to library 
+extern void uart_puts(unsigned char *str) {
+    int i;
+    for (i = 0; i < strlen(str); i++)     {
+        uart_putc(str[i]);
+    }
+}
+
diff --git a/include/drivers/uart.h b/include/drivers/uart.h
new file mode 100644
index 0000000..5b0badc
--- /dev/null
+++ b/include/drivers/uart.h
@@ -0,0 +1,12 @@
+#ifndef __UART_H
+#define __UART_H
+
+/* SERIAL INIT AND BASIC I/O 
+ * DON'T USE DIRECTLY USE, RATHER
+ * USE HIGHER LEVEL I/O 
+ * */
+extern void uart_init();
+extern void uart_putc(unsigned char ch); 
+char uart_getc(void); 
+
+#endif
diff --git a/include/lib/pool.h b/include/lib/pool.h
new file mode 100644
index 0000000..9204d36
--- /dev/null
+++ b/include/lib/pool.h
@@ -0,0 +1,4 @@
+/* Fixed size memory pool allocation  */
+extern void pool_init(size_t size_arg, unsigned int blocks_arg, uint32_t * entry_SRAM); 
+extern void * alloc();
+extern void free(void* p); 
diff --git a/include/lib/regfunc.h b/include/lib/regfunc.h
new file mode 100644
index 0000000..6b0c50b
--- /dev/null
+++ b/include/lib/regfunc.h
@@ -0,0 +1,4 @@
+/* regfunc.h */
+extern char * regtohex(uint32_t );
+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/include/lib/stdio.h b/include/lib/stdio.h
new file mode 100644
index 0000000..cf3075b
--- /dev/null
+++ b/include/lib/stdio.h
@@ -0,0 +1,8 @@
+/* 
+ * Not really "standard" but doable 
+ * for small programs 
+ * */
+extern char getchar();
+extern void cputchar(char);
+extern void cputs(unsigned char *);
+extern char * readline();
diff --git a/include/lib/string.h b/include/lib/string.h
new file mode 100644
index 0000000..e8e52f7
--- /dev/null
+++ b/include/lib/string.h
@@ -0,0 +1,5 @@
+/* string.h TODO */
+extern void *memcpy(void*, void*, size_t);
+extern void *memset(void*, unsigned char, size_t);
+extern unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count);
+extern int strlen(const char *);
diff --git a/include/mmap.h b/include/mmap.h
deleted file mode 100644
index e88c752..0000000
--- a/include/mmap.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
- * 
- * $LOG$
- * 2019/7/20 - ROBIN KRENS	
- * Initial version 
- * 
- * $DESCRIPTION$
- * Example memory map for the Cortex-A3
- * Implementations vary among manufacturers. This one is
- * a STM32F013RC6. Addresses of peripherals vary amongst 
- * manufacturers of boards with similar chips
- *
- * $USAGE$
- * These are volatile memory addresses of 32 bit. The macro's
- * MEM_VALUE and MEM_ADDR should used.
- * In case you want to use a address on the lside of a assigment
- * use volatile uint32_t * p = MEM_ADDR(0x20000000); 
- *
- * */
-
-#define OWRITE	0x01
-#define SETBIT	0x02
-#define CLRBIT	0x03
-
-/* Safety macro's to get the address or value */
-#define MEM_VALUE(addr) *((volatile uint32_t(*) (addr))
-#define MEM_ADDR(addr) ((volatile uint32_t *) (addr))
-
-/* SYSTEM INFO AND DEBUG */
-#define MCU_ID MEM_ADDR(0xE000ED00) 
-#define FLASH_MEM MEM_ADDR(0x1FFFF000) 
-
-/* SYSTEM CONTROL BLOCK REGISTER */
-#define SCB_VTOR MEM_ADDR(0xE000ED08) // VECTOR TABLE
-#define SCB_VTOR_ST MEM_ADDR(0xE000ED04) // STATUS OF VECTOR
-#define SCB_CCR MEM_ADDR(0xE000ED14) // SET SOFTWARE TRAPS
-
-/* NESTED VECTOR INTERRUPT CONTROL REGISTER */
-#define NVIC_ISER0 MEM_ADDR(0xE000E100) // interrupt set enable register
-#define NVIC_ISER1 MEM_ADDR(0xE000E104) // interrupt set enable register
-
-/* SYSTICK REGISTER */
-#define STK_CTRL MEM_ADDR(0xE000E010)
-#define STK_RELOAD MEM_ADDR(0xE000E014)
-
-/* CLOCK REGISTER */
-#define RCC_CR MEM_ADDR(0x40021000)
-#define RCC_CFGR MEM_ADDR(0x40021004)
-
-/* SYSTEM CONTROL REGISTER */
-#define SYSCTRL_RCC MEM_ADDR(0x40021000)
-#define RCC_APB2ENR MEM_ADDR(0x40021018) // register to enable USART1
-
-#define SYSCTRL_RIS MEM_ADDR(0x400FE050)
-#define SYSCTRL_RCGC1 MEM_ADDR(0x400FE104)
-#define SYSCTRL_RCGC2 MEM_ADDR(0x400FE108)
-#define GPIOPA_AFSEL MEM_ADDR(0x40004420)
-
-#define GPIOA_CRH MEM_ADDR(0x40010804)
-
-#define AFIO_EVCR MEM_ADDR(0x40010000)
-
-/* EXTERNAL INTERRUPTS */
-#define EXTI_IMR MEM_ADDR(0x40010400)
-#define EXTI_RTSR MEM_ADDR(0x40010408)
-
-/* UART1 REGISTERS */
-#define USART1_BASE MEM_ADDR(0x40013800)
-#define USART1_SR MEM_ADDR(0x40013800)
-#define USART1_DR MEM_ADDR(0x40013804)
-#define USART1_BRR MEM_ADDR(0x40013808)
-#define USART1_CR1 MEM_ADDR(0x4001380C)
-#define USART1_CR2 MEM_ADDR(0x40013810)
-#define USART1_CR3 MEM_ADDR(0x40013814)
diff --git a/include/stm32.h b/include/stm32.h
deleted file mode 100644
index 433c5d4..0000000
--- a/include/stm32.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef __SYSTEM_H
-#define __SYSTEM_H
-
-/* MAIN.C */
-extern void *memcpy(void*, void*, size_t);
-extern void *memset(void*, unsigned char, size_t);
-extern unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count);
-extern int strlen(const char *);
-
-/* CLOCK.C */
-extern void clock_init();
-
-/* UART.C */
-extern void uart_init();
-extern void uart_putc(unsigned char);
-extern void uart_puts(unsigned char *);
-extern char uart_getc(); 
-
-/* IVT.C */
-extern void ivt_init();
-extern void ivt_set_gate(unsigned char, void *(), short);
-
-/* SYSTICK.C */
-extern void systick_init();
-
-/* SYSINFO.C */
-extern void sysinfo();
-
-/* LIB.C */
-extern void addrtohex(const uint32_t);
-
-/* MM.C */
-extern void mm_init();
-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);
-
-/* TERM.C */
-extern char getchar();
-extern void cputchar(char);
-extern void cputs(unsigned char *);
-extern char * readline();
-extern void terminal();
-
-#endif
diff --git a/include/sys/mmap.h b/include/sys/mmap.h
new file mode 100644
index 0000000..a5921d2
--- /dev/null
+++ b/include/sys/mmap.h
@@ -0,0 +1,74 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/20 - ROBIN KRENS	
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * Memory map for the Cortex-A3
+ * Implementations vary among manufacturers. This one is
+ * a STM32F013RC6. Addresses of peripherals vary amongst 
+ * manufacturers of boards with similar chips
+ *
+ * $USAGE$
+ * These are volatile memory addresses of 32 bit. The macro's
+ * MEM_VALUE and MEM_ADDR should used.
+ * In case you want to use a address on the lside of a assigment
+ * use volatile uint32_t * p = MEM_ADDR(0x20000000); 
+ *
+ * */
+
+#define OWRITE	0x01
+#define SETBIT	0x02
+#define CLRBIT	0x03
+
+/* Safety macro's to get the address or value */
+#define MEM_VALUE(addr) *((volatile uint32_t(*) (addr))
+#define MEM_ADDR(addr) ((volatile uint32_t *) (addr))
+
+/* SYSTEM INFO AND DEBUG */
+#define MCU_ID MEM_ADDR(0xE000ED00) 
+#define FLASH_MEM MEM_ADDR(0x1FFFF000) 
+
+/* SYSTEM CONTROL BLOCK REGISTER */
+#define SCB_VTOR MEM_ADDR(0xE000ED08) // VECTOR TABLE
+#define SCB_VTOR_ST MEM_ADDR(0xE000ED04) // STATUS OF VECTOR
+#define SCB_CCR MEM_ADDR(0xE000ED14) // SET SOFTWARE TRAPS
+
+/* NESTED VECTOR INTERRUPT CONTROL REGISTER */
+#define NVIC_ISER0 MEM_ADDR(0xE000E100) // interrupt set enable register
+#define NVIC_ISER1 MEM_ADDR(0xE000E104) // interrupt set enable register
+
+/* SYSTICK REGISTER */
+#define STK_CTRL MEM_ADDR(0xE000E010)
+#define STK_RELOAD MEM_ADDR(0xE000E014)
+
+/* CLOCK REGISTER */
+#define RCC_CR MEM_ADDR(0x40021000)
+#define RCC_CFGR MEM_ADDR(0x40021004)
+
+/* SYSTEM CONTROL REGISTER */
+#define SYSCTRL_RCC MEM_ADDR(0x40021000)
+#define RCC_APB2ENR MEM_ADDR(0x40021018) // register to enable USART1
+
+#define SYSCTRL_RIS MEM_ADDR(0x400FE050)
+#define SYSCTRL_RCGC1 MEM_ADDR(0x400FE104)
+#define SYSCTRL_RCGC2 MEM_ADDR(0x400FE108)
+#define GPIOPA_AFSEL MEM_ADDR(0x40004420)
+
+#define GPIOA_CRH MEM_ADDR(0x40010804)
+
+#define AFIO_EVCR MEM_ADDR(0x40010000)
+
+/* EXTERNAL INTERRUPTS */
+#define EXTI_IMR MEM_ADDR(0x40010400)
+#define EXTI_RTSR MEM_ADDR(0x40010408)
+
+/* UART1 REGISTERS */
+#define USART1_BASE MEM_ADDR(0x40013800)
+#define USART1_SR MEM_ADDR(0x40013800)
+#define USART1_DR MEM_ADDR(0x40013804)
+#define USART1_BRR MEM_ADDR(0x40013808)
+#define USART1_CR1 MEM_ADDR(0x4001380C)
+#define USART1_CR2 MEM_ADDR(0x40013810)
+#define USART1_CR3 MEM_ADDR(0x40013814)
diff --git a/include/sys/robsys.h b/include/sys/robsys.h
new file mode 100644
index 0000000..e02eded
--- /dev/null
+++ b/include/sys/robsys.h
@@ -0,0 +1,31 @@
+#ifndef __SYSTEM_H
+#define __SYSTEM_H
+
+/* CLOCK.C */
+extern void clock_init();
+
+/* IVT.C */
+extern void ivt_init();
+extern void ivt_set_gate(unsigned char, void *(), short);
+
+/* SYSTICK.C */
+extern void systick_init();
+
+/* SYSINFO.C */
+extern void sysinfo();
+
+/* MM.C DELETE TODO */
+//extern void mm_init();
+//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();
+
+/* TERM.C */
+extern void terminal();
+
+#endif
diff --git a/ivt.c b/ivt.c
index b3854f1..a6761d0 100644
--- a/ivt.c
+++ b/ivt.c
@@ -5,14 +5,31 @@
  * Initial version 
  * 
  * $DESCRIPTION$
+ * Set up of basic exceptions and interrupts. These interrupts
+ * don't do much, except for halting the system. 
+ * ivt_set_gate(interrupt nr, function, priority) can be used
+ * later to define more appropriate handling. See timer (timer.c) 
+ * or serial or (uart.c) handling for non-trivial examples.
+ *
+ * The actual code is not much, but there are a lot of details
+ * to consider. Besides that, in case more control is desired over
+ * entering and exiting interrupts (what is pushed on the stack) 
+ * A so-called naked function can be used. See below for more
+ * details.
  * 
+ *
  * */
 
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <stm32.h>
-#include <mmap.h>
+
+#include <sys/robsys.h>
+#include <sys/mmap.h>
+
+#include <lib/stdio.h>
+#include <lib/string.h>
+#include <lib/regfunc.h>
 
 /* 
  * These values are pushed on the stack just before
@@ -22,7 +39,7 @@
  * gives me a little bit more control over the caller
  *
  * The following register are pushed to the stack
- * in reverse order
+ * in reverse order:
  *
  * */
 struct interrupt_frame {
@@ -43,6 +60,8 @@ struct interrupt_frame {
  *
  * interrupt vector 1-15: processor exceptions
  * interrupt vector 16-92: irq0 - irq ..
+ *
+ * Vector table needs to be aligned in memory.
  * */
 
 uint32_t __attribute__((aligned(0x100))) ivt[92];
@@ -92,15 +111,17 @@ void ivt_set_gate(unsigned char num, void * isr(), short pri) {
 }
 
 
-/* Dummy interrupt */
+/* Dummy interrupt: comment out the comment to use a naked f
+ * function */
+
 // __attribute__ ((interrupt)) 
 void * dummy_isr(/* struct interrupt_frame * frame */) {
 
 	uint8_t nr = *SCB_VTOR_ST & 0xFF;
 	
-	uart_puts("EXCEPTION: ");
-	uart_puts(exception_message(nr));
-	uart_puts("\nSYSTEM HALTED\n");
+	cputs("EXCEPTION: ");
+	cputs(exception_message(nr));
+	cputs("\nSYSTEM HALTED\n");
 	
 	for(;;);
 }
@@ -108,7 +129,7 @@ void * dummy_isr(/* struct interrupt_frame * frame */) {
 /* Initialize interrupt vector  */
 void ivt_init() {
 
-	/* clear entiry IVT, in SRAM location for SRAM + .data (in .bss section) */
+	/* clear entire IVT, in SRAM location for SRAM + .data (in .bss section) */
 	memset(&ivt, 0, (sizeof(uint32_t) * 92));
 
 	// stack top is loaded from the first entry table on boot/reset
@@ -119,13 +140,10 @@ void ivt_init() {
 		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
+	/* The vector table is intially at 0x0. The vector table can be
 	 * relocated to other memory locations. We can do this by setting 
 	 * a register in the NVIC called the vector table offset register */
 
-	//*SCB_VTOR = (volatile uint32_t) &ivt; 
 	regw_u32(SCB_VTOR, (uint32_t) &ivt, 0, OWRITE);
 
 }
diff --git a/lib.c b/lib.c
deleted file mode 100644
index ba55c01..0000000
--- a/lib.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stm32.h>
-//#include <mmap.h>
-
-/* Temporary libc functions, which can later be 
- * replaced by a *real* library */
-
-char hexbuf[8];
-
-/* Still kind of a debug function */
-void addrtohex(uint32_t addr) {
-	char tmpbuf[6] = {'A', 'B', 'C', 'D', 'E', 'F'};
-	memset(&hexbuf, 0, sizeof(uint32_t) * 8);
-
-	for (int i = 0; i < 8 ; i++) {
-		uint32_t tmp = addr;
-	 	tmp = tmp >> (i * 4);
-		tmp = tmp & 0xF;
-		if ((tmp >= 0) && tmp < 10) {
-			hexbuf[i] = (char) tmp + 48;
-		}
-		else {
-			hexbuf[i] = tmpbuf[tmp - 10];
-		}
-	}
-
-	 for (int i = 7; i >= 0; i--) {
-		cputchar(hexbuf[i]);
-	} 
-}
-
-
-
-
-
diff --git a/lib/pool.c b/lib/pool.c
new file mode 100644
index 0000000..63cf3fd
--- /dev/null
+++ b/lib/pool.c
@@ -0,0 +1,108 @@
+/* (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 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 <lib/pool.h>
+#include <lib/string.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;
+ }
+
+ /* void deletepool()  {
+	 mem.SRAM_entry = NULL;
+ } */
+
+/* Helper functions */
+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);
+
+}
+
+/* alloc and free */ 
+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;
+ }
diff --git a/lib/regfunc.c b/lib/regfunc.c
new file mode 100644
index 0000000..6add220
--- /dev/null
+++ b/lib/regfunc.c
@@ -0,0 +1,64 @@
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <lib/regfunc.h>
+#include <lib/string.h>
+#include <lib/stdio.h>
+
+#include <sys/mmap.h>
+
+/* write value (uint8_t) to register */
+void regw_u8(volatile uint32_t * reg, uint8_t val, short shift, short flag) {
+
+	switch(flag) {
+		case OWRITE:
+			*reg = (val << shift);
+			break;
+		case SETBIT:
+			*reg = *reg | (val << shift);
+			break;
+		case CLRBIT:
+			*reg = (val << shift);
+			break;
+	}
+}
+
+/* write value (uint32_t) to register */
+void regw_u32(volatile uint32_t * reg, uint32_t val, short shift, short flag) {
+
+	switch(flag) {
+		case OWRITE:
+			*reg = (val << shift);
+			break;
+		case SETBIT:
+			*reg = *reg | (val << shift);
+			break;
+		case CLRBIT:
+			break;
+	}
+}
+
+/* Print out the hexidecimal representation of an integer
+   After implementation of a printf function, this code
+   will be obsolete.  */
+
+char hexbuf[8];
+char * regtohex(uint32_t addr) {
+	char tmpbuf[6] = {'A', 'B', 'C', 'D', 'E', 'F'};
+	memset(&hexbuf, 0, sizeof(uint32_t) * 8);
+
+
+	for (int i = 0; i < 8 ; i++) {
+		uint32_t tmp = addr;
+	 	tmp = tmp >> (28 - (i * 4));
+		tmp = tmp & 0xF;
+		if ((tmp >= 0) && tmp < 10) {
+			hexbuf[i] = (char) tmp + 48;
+		}
+		else {
+			hexbuf[i] = tmpbuf[tmp - 10];
+		}
+	}
+	return &hexbuf[0];	
+}
diff --git a/lib/stdio.c b/lib/stdio.c
new file mode 100644
index 0000000..ac26165
--- /dev/null
+++ b/lib/stdio.c
@@ -0,0 +1,72 @@
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <lib/stdio.h>
+#include <lib/string.h>
+#include <drivers/uart.h>
+
+#define SERIAL 1
+#define TFT 0
+#define BUFSIZE 256
+
+static char stdbuf[BUFSIZE];
+
+/* Abstraction layer for I/O communication */
+
+char getchar(void) {
+        char c;
+	if (SERIAL) {
+	         while ((c = uart_getc()) == 0);
+                /* do nothing */
+	}
+        return c;
+}
+
+void cputchar(char c) {
+
+	if (SERIAL) {
+		uart_putc(c);
+	}
+
+}
+
+void cputs(unsigned char *str) {
+     
+     int i;
+     for (i = 0; i < strlen(str); i++)     {
+         cputchar(str[i]);
+    }
+
+}
+
+char * readline(char *prompt)
+{
+	int i, c, echoing;
+
+	if (prompt != NULL)
+		cputs(prompt); 
+
+	i = 0;
+	echoing = 1;
+	while (1) {
+		c = getchar();
+		if (c < 0) {
+			cputs("read error");
+			return NULL;
+		} else if ((c == '\b' || c == '\x7f') && i > 0) {
+			if (echoing)
+				cputchar('\b');
+			i--;
+		} else if (c >= ' ' && i < BUFSIZE-1) {
+			if (echoing)
+				cputchar(c);
+			stdbuf[i++] = c;
+		} else if (c == '\n' || c == '\r') {
+			if (echoing)
+				cputchar('\n');
+			stdbuf[i] = 0;
+			return stdbuf;
+		}
+	}
+}
diff --git a/lib/string.c b/lib/string.c
new file mode 100644
index 0000000..b1618b0
--- /dev/null
+++ b/lib/string.c
@@ -0,0 +1,38 @@
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <lib/string.h> 
+
+// TODO: add more
+void *memcpy(void *dest, void *src, size_t count)
+{   
+    const char *sp = (const char *)src;
+    char *dp = (char *)dest;
+    for(; count != 0; count--) *dp++ = *sp++;
+    return dest;
+}
+
+/* fillout memory with 'val' (i.e. all zeroes)
+ */
+void *memset(void *dest, unsigned char val, size_t count)
+{
+    char *temp = (char *)dest;
+    for( ; count != 0; count--) *temp++ = val;
+    return dest;
+}
+
+/* same as above but shorter */
+unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count)
+{
+    unsigned short *temp = (unsigned short *)dest;
+    for( ; count != 0; count--) *temp++ = val;
+    return dest;
+}
+
+int strlen(const char *str)
+{
+    int retval;
+    for(retval = 0; *str != '\0'; str++) retval++;
+    return retval;
+}
diff --git a/main.c b/main.c
index 2b6fdba..35b718e 100644
--- a/main.c
+++ b/main.c
@@ -1,55 +1,35 @@
+/* (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>
-#include <stm32.h> // <-- my own header file located located in ./include
-#include <mmap.h>
-
-
-void *memcpy(void *dest, void *src, size_t count)
-{   
-    const char *sp = (const char *)src;
-    char *dp = (char *)dest;
-    for(; count != 0; count--) *dp++ = *sp++;
-    return dest;
-}
-
-/* fillout memory with 'val' (i.e. all zeroes)
- */
-void *memset(void *dest, unsigned char val, size_t count)
-{
-    char *temp = (char *)dest;
-    for( ; count != 0; count--) *temp++ = val;
-    return dest;
-}
-
-/* same as above but shorter */
-unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count)
-{
-    unsigned short *temp = (unsigned short *)dest;
-    for( ; count != 0; count--) *temp++ = val;
-    return dest;
-}
-
-int strlen(const char *str)
-{
-    int retval;
-    for(retval = 0; *str != '\0'; str++) retval++;
-    return retval;
-}
-
 
+#include <sys/robsys.h> 
+#include <sys/mmap.h>
 
+#include <drivers/uart.h>
 
 void main()
 {
-
 	ivt_init();
 	uart_init();
-	
+
 	systick_init();
 	
 	sysinfo();
 
+	extern void stub();
+	//stub();
+	//__asm__ __volatile__ ("ldc p1, cr1, r0");
+
 	terminal();
 
 	for(;;) {
diff --git a/mm.c b/mm.c
deleted file mode 100644
index 1e20f75..0000000
--- a/mm.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/* (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>
-
-
-#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];
-
-void mm_init() {
-
-
-//	memset(&chunk_index, 0, sizeof(uint32_t) * 4);
-
-
-//	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);
-
-
-	//uint32_t * test = MEM_ADDR(0x20000000);
-	//uint32_t random_location = MEM_VALUE(0x20000000);
-
-	//uint32_t random_location = 0x20000900;
-
-	//MEM_VALUE(random_location);
-	//MEM_VALUE(BITBAND(random_location, 0)) = 0x1;
-
-	//addrtohex(MEM_VALUE(random_location));
-
-
-	
-}
-
- void test_memory(uint32_t * ptr) {
-
-	*ptr = 0xEEEEEEEE;
-	for (int i = 0; i < 100; i++) {
-		ptr++;
-		*ptr = 0xEEEEEEEE;
-	}
-
-} 
-
-/* BIT BAND SCAN */
-
- /* 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;
- } */
-
-
-/* void * malloc(size_t size) {
-
-	if (size < 256) {
-
-		extern char * _endofbss;
-
-		uint32_t start = (uint32_t) &chunk_index[0];	
-		uint32_t current;
-		int offset = 0x100;
-
-		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
deleted file mode 100644
index 0e0b94d..0000000
--- a/pool.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/* (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 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;
- } */
-
-/* Helper functions */
-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);
-
-}
-
-/* alloc and free */ 
-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;
- }
diff --git a/regf.c b/regf.c
deleted file mode 100644
index 75f0a3c..0000000
--- a/regf.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stm32.h>
-#include <mmap.h>
-
-/* write value (uint8_t) to register */
-void regw_u8(volatile uint32_t * reg, uint8_t val, short shift, short flag) {
-
-	switch(flag) {
-		case OWRITE:
-			*reg = (val << shift);
-			break;
-		case SETBIT:
-			*reg = *reg | (val << shift);
-			break;
-		case CLRBIT:
-			*reg = (val << shift);
-			break;
-	}
-}
-
-/* write value (uint32_t) to register */
-void regw_u32(volatile uint32_t * reg, uint32_t val, short shift, short flag) {
-
-	switch(flag) {
-		case OWRITE:
-			//*reg = (val << shift);
-			*reg = (val << shift);
-			break;
-		case SETBIT:
-			*reg = *reg | (val << shift);
-			break;
-		case CLRBIT:
-			//
-			break;
-	}
-}
-
-
diff --git a/start.asm b/start.asm
index ba161a2..54d2b91 100644
--- a/start.asm
+++ b/start.asm
@@ -29,6 +29,7 @@ hardfault:
 stub:
 	ldr R0,=10
 	mov R1,#0
+	ldc2 11, cr0, [r1, #4]
 	udiv.w R2, R0, R1 
 
 	.data
diff --git a/sysinfo.c b/sysinfo.c
index fe544ee..e9b2429 100644
--- a/sysinfo.c
+++ b/sysinfo.c
@@ -1,8 +1,12 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <stm32.h>
-#include <mmap.h>
+
+#include <sys/robsys.h>
+#include <sys/mmap.h>
+
+#include <lib/stdio.h>
+#include <lib/regfunc.h>
 
 #define MEM_SIZE	0x00010000 
 #define MEM_OFFSET	0x20000000
@@ -22,7 +26,7 @@ void sysinfo() {
 	}
 
 	tmp = (tmp >> 16);
-	uart_puts("# REVISION: ");
+	cputs("# REVISION: ");
 	switch	(tmp) {
 		case 0x1000:
 		      cputs("REVISION A\n");
@@ -45,13 +49,13 @@ void sysinfo() {
 	uint32_t mem_free = MEM_SIZE - stack_usage - data_bss;
 
 	cputs("# TOTAL MEMORY: ");
-	addrtohex(MEM_SIZE);
+	cputs(regtohex(MEM_SIZE));
 	cputchar('\n');
 	cputs("# FREE MEMORY: ");
-	addrtohex(mem_free);
+	cputs(regtohex(mem_free));
 	cputchar('\n');
 	cputs("# STACK USAGE: ");
-	addrtohex(stack_usage);
+	cputs(regtohex(stack_usage));
 	cputchar('\n');
 
 }
diff --git a/systick.c b/systick.c
index 40e7862..1d632ec 100644
--- a/systick.c
+++ b/systick.c
@@ -1,8 +1,11 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <stm32.h>
-#include <mmap.h>
+
+#include <sys/robsys.h>
+#include <sys/mmap.h>
+
+#include <lib/regfunc.h> // TODO
 
 struct interrupt_frame {
 
diff --git a/term.c b/term.c
index 8b81255..0628e1e 100644
--- a/term.c
+++ b/term.c
@@ -1,40 +1,41 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <stm32.h>
-#include <mmap.h>
+
+#include <sys/robsys.h>
+#include <sys/mmap.h>
+
+#include <lib/stdio.h>
 
 #define SERIAL 1
-#define BUFSIZE 256
+#define BUFSIZE 200
 
-static char buf[BUFSIZE];
 
-/* Abstraction layer for I/O communication */
+int help(int, char**);
 
-char getchar(void) {
-        char c;
-	if (SERIAL) {
-	         while ((c = uart_getc()) == 0);
-                /* do nothing */
-	}
-        return c;
-}
+/* 
+ * Built in commands
+ * 	info -- shows basic info of system
+ * 	reset -- software reset
+ * 	show [ADDRESS-ADDRESS] -- shows SRAM range
+ * 	switchmode -- switch to unprivileged mode
+ * */
 
-void cputchar(char c) {
+static char buf[BUFSIZE];
 
-	if (SERIAL) {
-		uart_putc(c);
-	}
 
-}
+struct cmd {
+	char * name;
+	char * description;
+	int (*function)(int argc, char ** argsv);
+};
 
-void cputs(unsigned char *str) {
-     
-     int i;
-     for (i = 0; i < strlen(str); i++)     {
-         cputchar(str[i]);
-    }
+static struct cmd builtin[] = 
+	{ "info", "show info", help};
 
+int help(int argc, char ** argsv) {
+	sysinfo();
+	return 0;
 }
 
 void terminal() {
@@ -43,40 +44,9 @@ void terminal() {
         cputs("Terminal running!\n");
  
          while (1) {
-                 buf = readline("> ");
+                 buf = readline("root# ");
                  /* if (buf != NULL)
                          if (runcmd(buf, tf) < 0)
                                  break; */
          }
 }
-
-char * readline(char *prompt)
-{
-	int i, c, echoing;
-
-	if (prompt != NULL)
-		cputs(prompt); 
-
-	i = 0;
-	echoing = 1;
-	while (1) {
-		c = getchar();
-		if (c < 0) {
-			cputs("read error");
-			return NULL;
-		} else if ((c == '\b' || c == '\x7f') && i > 0) {
-			if (echoing)
-				cputchar('\b');
-			i--;
-		} else if (c >= ' ' && i < BUFSIZE-1) {
-			if (echoing)
-				cputchar(c);
-			buf[i++] = c;
-		} else if (c == '\n' || c == '\r') {
-			if (echoing)
-				cputchar('\n');
-			buf[i] = 0;
-			return buf;
-		}
-	}
-}
diff --git a/uart.c b/uart.c
deleted file mode 100644
index 9dbc01c..0000000
--- a/uart.c
+++ /dev/null
@@ -1,102 +0,0 @@
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stm32.h>
-#include <mmap.h>
-#include <drivers.h>
-
-#define RXNE ((*USART1_SR >> 5) & 0x1)
-#define UARTBUF 256
-#define ECHO 1
-
-static struct {
-       	 uint8_t buf[UARTBUF] ;
-         uint32_t rpos;
-       	 uint32_t wpos;
-} linefeed;
-
-
-void * uart_handler() {
-
-	//uart_puts("echo: ");
- 	while (RXNE) {
-		char echochar = *USART1_DR;
-		//uart_putc(echochar);
-                linefeed.buf[linefeed.wpos++] = echochar;
-                 if (linefeed.wpos == UARTBUF)
-                         linefeed.wpos = 0;
-		//regw_u32(USART1_DR, echochar, 0, O_WRITE);
-	}
-	//uart_putc('\n');
-      		
-}
-
-void uart_init() {
-
-	regw_u32(RCC_APB2ENR, 0x4005, 0, SETBIT);// enable clock to UART1, AFIO and GPIOA
-	
-	/* (after enable GPIOA), on PA9&PA10 and set mode
-	 *  to alternative output */
-	regw_u32(GPIOA_CRH, 0x444444D4, 0, OWRITE);
-	regw_u8(AFIO_EVCR, 0x89, 0, OWRITE);// set event control register, output on PA, Pin 9
-
-	//disable temporarily to set values
-	regw_u8(USART1_CR1, 0x0, 13, SETBIT);
-
-	/* baud rate 115200,  8MHz / (16 * USARTDIV)
-	 * USARTDIV = 4.34
-	 * FRACTION: 16 x 0.34 = 0d5.44 0d5 -> 0x5
-	 * MANTISSA: 0d4.34 0d4 -> 0x4 
-	 * USART_BRR = 0x45*/
-
-	regw_u32(USART1_BRR, 0x00000045, 0, OWRITE);
-	regw_u32(USART1_CR2, 0x0000, 0, OWRITE); //set stop bit, default is 1 stop bit 0x00
-	
-	/* parity = 8 bit, UART1 enabled,
-	 * TX and RX enabled, interrupts enabled */
-	//regw_u32(USART1_CR1, 0x000030AC, 0, O_WRITE);
-	regw_u32(USART1_CR1, 0x0000302C, 0, OWRITE);
-
-	ivt_set_gate(53, uart_handler, 0);
-	
-	*NVIC_ISER1 = (1 << 5); // Enable UART interrupt at NVIC
-}
-
-static void wait() {
-	for (int i = 0; i < 100; i++);
-}
-
-extern void uart_putc(unsigned char ch) {
-	
-  	if (ch == '\n') {
-		while (*USART1_SR & 0x0C) { } // transmit data register empty and complete
-		regw_u8(USART1_DR, 0x0D, 0, OWRITE); // return line
-	}
-
-	while (*USART1_SR & 0x0C) {} 
-		regw_u8(USART1_DR, ch, 0, OWRITE);
-
-	wait();
-}
-
-char uart_getc(void) {
-         char c;
-
-         if (linefeed.rpos != linefeed.wpos) {
-                 c = linefeed.buf[linefeed.rpos++];
-                 if (linefeed.rpos == UARTBUF)
-                         linefeed.rpos = 0;
-                 return c;
-         }
-         return 0;
- }
-
-
-// move to library 
-extern void uart_puts(unsigned char *str) {
-    int i;
-    for (i = 0; i < strlen(str); i++)     {
-        uart_putc(str[i]);
-    }
-}
-