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
.PHONY: clean
clean:
- rm -rf $(ODIR)/*.o start.o $(BIN)/kernel.*
+ rm -rf $(ODIR)/* start.o $(BIN)/kernel.*
# Altijd handig deze template
#%.o: %.c
--- /dev/null
+Note to self: Place drivers or loadable modules here
+
--- /dev/null
+#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]);
+ }
+}
+
--- /dev/null
+#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
--- /dev/null
+/* 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);
--- /dev/null
+/* 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);
--- /dev/null
+/*
+ * Not really "standard" but doable
+ * for small programs
+ * */
+extern char getchar();
+extern void cputchar(char);
+extern void cputs(unsigned char *);
+extern char * readline();
--- /dev/null
+/* 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 *);
+++ /dev/null
-/* (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)
+++ /dev/null
-#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
--- /dev/null
+/* (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)
--- /dev/null
+#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
* 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
* 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 {
*
* 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];
}
-/* 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(;;);
}
/* 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
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);
}
+++ /dev/null
-#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]);
- }
-}
-
-
-
-
-
--- /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 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;
+ }
--- /dev/null
+#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];
+}
--- /dev/null
+#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;
+ }
+ }
+}
--- /dev/null
+#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;
+}
+/* (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(;;) {
+++ /dev/null
-/* (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;
- }
-} */
-
-
-
+++ /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 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;
- }
+++ /dev/null
-#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;
- }
-}
-
-
stub:
ldr R0,=10
mov R1,#0
+ ldc2 11, cr0, [r1, #4]
udiv.w R2, R0, R1
.data
#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
}
tmp = (tmp >> 16);
- uart_puts("# REVISION: ");
+ cputs("# REVISION: ");
switch (tmp) {
case 0x1000:
cputs("REVISION A\n");
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');
}
#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 {
#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() {
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;
- }
- }
-}
+++ /dev/null
-#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]);
- }
-}
-