From e0e42c2a52cb8371f4102832d20ffc5a52453a03 Mon Sep 17 00:00:00 2001 From: Robin Krens Date: Wed, 10 Jul 2019 18:40:58 +0800 Subject: [PATCH] init vector implementation --- Makefile | 5 ++-- include/mmap.h | 37 +++++++++++++++++++++++++ include/stm32.h | 3 ++ ivt.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ link.ld | 17 ++++++++---- main.c | 6 ++++ start.asm | 35 +++++++++++++++++++----- uart.c | 24 +--------------- 8 files changed, 175 insertions(+), 37 deletions(-) create mode 100644 include/mmap.h create mode 100644 ivt.c diff --git a/Makefile b/Makefile index f75c606..58ae9ac 100644 --- 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 index 0000000..ad45038 --- /dev/null +++ b/include/mmap.h @@ -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)) diff --git a/include/stm32.h b/include/stm32.h index 0928463..e4409f2 100644 --- a/include/stm32.h +++ b/include/stm32.h @@ -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 index 0000000..fadf533 --- /dev/null +++ b/ivt.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include + +/* 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 --- 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 --- 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(;;) { diff --git a/start.asm b/start.asm index 3c92e9b..294a718 100644 --- 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 --- a/uart.c +++ b/uart.c @@ -2,29 +2,7 @@ #include #include #include - -#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 void uart_init() { -- 2.7.4