init vector implementation
authorRobin Krens <robin@robinkrens.nl>
Wed, 10 Jul 2019 10:40:58 +0000 (18:40 +0800)
committerRobin Krens <robin@robinkrens.nl>
Wed, 10 Jul 2019 10:40:58 +0000 (18:40 +0800)
Makefile
include/mmap.h [new file with mode: 0644]
include/stm32.h
ivt.c [new file with mode: 0644]
link.ld
main.c
start.asm
uart.c

index f75c606..58ae9ac 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -14,11 +14,12 @@ 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
-       $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o
+       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o ivt.o ivt.c 
+       $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o
        $(MKIMG) -Obinary -R .data start.out kernel.bin
 
 run:
-       qemu-system-arm -serial stdio -M lm3s6965evb -kernel kernel.bin
+       qemu-system-arm -serial stdio  -M lm3s6965evb -kernel kernel.bin
 
 examine:
        arm-none-eabi-objdump -S start.out
diff --git a/include/mmap.h b/include/mmap.h
new file mode 100644 (file)
index 0000000..ad45038
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+ * 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
+ * 
+ * Peaceļ¼
+ * */
+
+/* VECTOR TABLE */
+#define NVIC_VECTTBL ((volatile unsigned long *)( 0xE000ED08))
+#define NVIC_EN0 ((volatile unsigned long *)( 0xE000E100))
+#define NVIC_EN1 ((volatile unsigned long *)( 0xE000E104))
+
+/* SYSTEM CONTROL REGISTERS */
+#define SYSCTRL_RCC ((volatile unsigned long *)(0x400FE060))
+#define SYSCTRL_RIS ((volatile unsigned long *)(0x400FE050))
+#define SYSCTRL_RCGC1 ((volatile unsigned long *)(0x400FE104))
+#define SYSCTRL_RCGC2 ((volatile unsigned long *)(0x400FE108))
+#define GPIOPA_AFSEL ((volatile unsigned long *)(0x40004420))
+
+/* USART REGISTERS */
+#define UART0_DATA ((volatile unsigned long *)(0x4000C000))
+#define UART0_FLAG ((volatile unsigned long *)(0x4000C018))
+#define UART0_IBRD ((volatile unsigned long *)(0x4000C024))
+#define UART0_FBRD ((volatile unsigned long *)(0x4000C028))
+#define UART0_LCRH ((volatile unsigned long *)(0x4000C02C))
+#define UART0_CTRL ((volatile unsigned long *)(0x4000C030))
+#define UART0_RIS ((volatile unsigned long *)(0x4000C03C))
+
+#define UART1_DATA ((volatile unsigned long *)(0x4000D000))
+#define UART1_FLAG ((volatile unsigned long *)(0x4000D018))
+#define UART1_IBRD ((volatile unsigned long *)(0x4000D024))
+#define UART1_FBRD ((volatile unsigned long *)(0x4000D028))
+#define UART1_LCRH ((volatile unsigned long *)(0x4000D02C))
+#define UART1_CTRL ((volatile unsigned long *)(0x4000D030))
+#define UART1_RIS ((volatile unsigned long *)(0x4000D03C))
index 0928463..e4409f2 100644 (file)
@@ -14,4 +14,7 @@ extern void uart_init();
 extern void uart_putc(unsigned char);
 extern void uart_puts(unsigned char *);
 
+/* IVT.C */
+extern void ivt_init();
+
 #endif
diff --git a/ivt.c b/ivt.c
new file mode 100644 (file)
index 0000000..fadf533
--- /dev/null
+++ b/ivt.c
@@ -0,0 +1,85 @@
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stm32.h>
+#include <mmap.h>
+
+/* TIMER, TODO: move to timer.c */
+
+
+
+/* Interrupt vector can contain 16 exceptions and up to 256 interrupts
+ * In this code we use 16 exceptions and 36 interrupts  
+ * (note: this should be aligned to the vector table size) 
+ * Offsets of each entry is:  0x0, 0x80, 0x100, 0x180 .. */
+
+/* interrupt vector 1-15: processor exceptions
+ * interrupt vector 16-43: irq0 - irq .. */
+uint32_t ivt[43];
+
+/* * base is location of interrupt service request
+ * */
+void ivt_set_gate(unsigned char num, void * isr(), short pri) {
+
+       ivt[num] = (uint32_t) isr;
+       // TODO priority
+}
+
+// test Interrupt service routine
+void * test_ISR() {
+       uart_puts("PING!");
+}
+
+/* Initialize interrupt vector  */
+
+void ivt_init() {
+
+       /* clear entiry IVT, in SRAM location for SRAM + .data (in .bss section) */
+       memset(&ivt, 0, (sizeof(uint32_t) * 44));
+
+       // stack top is loaded from the first entry table on boot/reset
+       // don't need to relocate or init this here
+
+       // copy old vectors 
+       extern void * reset,  * nmi, * hardfault;
+       //extern uint32_t reset, nmi, hardfault;
+       //ivt[1] = &reset;
+       //ivt[2] = &nmi;
+       //ivt[3] = &hardfault;
+
+       ivt_set_gate(1, test_ISR, 0);
+       ivt_set_gate(2, test_ISR, 0);
+       ivt_set_gate(3, test_ISR, 0);
+       ivt_set_gate(15, test_ISR ,0);
+
+       // enable all interrupts
+       
+       *SYSCTRL_RCGC1 = *SYSCTRL_RCGC1 | 0x00010000;
+
+       // TODO systimer 
+       // ivt[15]
+       *NVIC_EN0 = *NVIC_EN0 | 0x00008003;
+//     *NVIC_EN1 = (volatile uint32_t) 0xFFFFFFFF; // TODO not all registers
+
+       // priority levels are 0 by default (only executable by kernel)
+       
+       /* disable all interrupts
+        * MOV R0, #1 ; disable all
+        * MSR PRIMASK, R0 
+        * MOV R0, #0 ; allow all
+        * MSR PRIMASK, R0 */
+
+       
+       
+       /* relocate the vector table to (S)RAM 
+        * vector table starts at 0x0. since the address 0x0 point to bootcode, it is on ROM or FLASH. 
+        * the value cannot be changed during runtime. however, the vector table can be
+        * relocated to other memory locations in the code or RAM later on
+        *
+        * we can do this by setting a register in the NVIC called
+        * the vector table offset register (address 0xE000ED08).  */
+
+
+       *NVIC_VECTTBL = (volatile unsigned long) &ivt; 
+
+}
diff --git a/link.ld b/link.ld
index 5791784..096fb5d 100644 (file)
--- a/link.ld
+++ b/link.ld
@@ -1,21 +1,28 @@
-MEMORY
+/* 
+ * MEMORY MAP
 {
        FLASH (xr) : ORIGIN = 0x00000000, LENGTH = 512K
        SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
-}
+} */
 
 ENTRY(_start) 
 
 SECTIONS
 {
+       . = 0x0;
        .text : ALIGN(4)
        {
                /* (.vector_table */ 
                *(.text)
 
-       } > FLASH
-       .data : 
+       } 
+       . = 0x20000000;
+       .data :  
        {
                *(.data)
-       } > SRAM
+       }
+       .bss : ALIGN(256)
+       {
+               *(.bss)
+       }
 }
diff --git a/main.c b/main.c
index 87b45e7..c17c664 100644 (file)
--- a/main.c
+++ b/main.c
@@ -56,6 +56,12 @@ void main()
 {
        uart_init();
        uart_puts("LOADING SYSTEM...\n");
+
+       ivt_init();
+
+       //extern void stub();
+       //stub();
+
        // loop
        for(;;) {
 
index 3c92e9b..294a718 100644 (file)
--- a/start.asm
+++ b/start.asm
@@ -1,19 +1,40 @@
        .equ STACK_TOP, 0x20000800
        .text
        .global _start
+       .global reset, nmi, hardfault
        .code 16
        .syntax unified
 _start:
-       .word STACK_TOP, start
-       .type start, function
+       .word STACK_TOP, reset, nmi, hardfault
+       .type reset, function
 
-/* Start of main program */
-start:
+/* A reset vector (or bootcode) will call main in main.c
+   this is the so called 'entry to C' */
+reset:
        b main
-       b start
+       b reset 
+
+/* These are consequently the nmi and hardfault vector handlers
+   before booting and entering main, these can actually be called
+   (machine somehow has a failure). That's why they are included here.
+   Later the interrupt vector
+   will be relocated to SRAM and the will be copied / modified.  */
+
+nmi:
+       b nmi
+
+hardfault: 
+       b hardfault
+.global stub
+stub:
+       mov r1, #'z'
+       ldr r0, [r1]
+       bx lr
+       /* ldr R0,=10
+       mov R1,#0
+       udiv.w R2, R0, R1 */
 
        .data
-Result:
-       .word 'X' /* results now is in 0x20000008 (0x20000000 + 2 w) */
+       .word 'x'
        .end
 
diff --git a/uart.c b/uart.c
index 1cc5c03..bfef4b4 100644 (file)
--- a/uart.c
+++ b/uart.c
@@ -2,29 +2,7 @@
 #include <stddef.h>
 #include <stdint.h>
 #include <stm32.h>
-
-#define SYSCTRL_RCC ((volatile unsigned long *)(0x400FE060))
-#define SYSCTRL_RIS ((volatile unsigned long *)(0x400FE050))
-#define SYSCTRL_RCGC1 ((volatile unsigned long *)(0x400FE104))
-#define SYSCTRL_RCGC2 ((volatile unsigned long *)(0x400FE108))
-#define GPIOPA_AFSEL ((volatile unsigned long *)(0x40004420))
-
-#define UART0_DATA ((volatile unsigned long *)(0x4000C000))
-#define UART0_FLAG ((volatile unsigned long *)(0x4000C018))
-#define UART0_IBRD ((volatile unsigned long *)(0x4000C024))
-#define UART0_FBRD ((volatile unsigned long *)(0x4000C028))
-#define UART0_LCRH ((volatile unsigned long *)(0x4000C02C))
-#define UART0_CTRL ((volatile unsigned long *)(0x4000C030))
-#define UART0_RIS ((volatile unsigned long *)(0x4000C03C))
-
-#define UART1_DATA ((volatile unsigned long *)(0x4000D000))
-#define UART1_FLAG ((volatile unsigned long *)(0x4000D018))
-#define UART1_IBRD ((volatile unsigned long *)(0x4000D024))
-#define UART1_FBRD ((volatile unsigned long *)(0x4000D028))
-#define UART1_LCRH ((volatile unsigned long *)(0x4000D02C))
-#define UART1_CTRL ((volatile unsigned long *)(0x4000D030))
-#define UART1_RIS ((volatile unsigned long *)(0x4000D03C))
-
+#include <mmap.h>
 
 void uart_init() {