From: Robin Krens Date: Wed, 10 Jul 2019 20:11:15 +0000 (+0800) Subject: implementation of interrupts, SysTick exception X-Git-Url: https://robinkrens.nl/gitweb/?a=commitdiff_plain;h=2ad654f037bae2ec8f0223179c4b96c23308c34d;p=cortex-from-scratch implementation of interrupts, SysTick exception --- diff --git a/Makefile b/Makefile index 58ae9ac..dbcbc85 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,12 @@ all: $(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 - $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o + $(CC) $(CFLAGS) -c -I./include -ffreestanding -o systick.o systick.c + $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o systick.o $(MKIMG) -Obinary -R .data start.out kernel.bin run: - qemu-system-arm -serial stdio -M lm3s6965evb -kernel kernel.bin + /usr/local/bin/qemu-system-arm -serial stdio -M stm32-f103c8 -kernel kernel.bin examine: arm-none-eabi-objdump -S start.out diff --git a/include/mmap.h b/include/mmap.h index ad45038..7caee1d 100644 --- a/include/mmap.h +++ b/include/mmap.h @@ -4,15 +4,23 @@ * 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)) +/* RANDOM DEBUG LOCATION */ +#define RANDOM_ADDR ((volatile uint32_t *)(0x21000000)) -/* SYSTEM CONTROL REGISTERS */ +/* SYSTEM CONTROL BLOCK REGISTER */ +#define SCB_VTOR ((volatile uint32_t *)( 0xE000ED08)) // VECTOR TABLE + +/* NESTED VECTOR INTERRUPT CONTROL REGISTER */ +#define NVIC_ISER0 ((volatile uint32_t*)( 0xE000E100)) // interrupt set enable register + +/* SYSTICK REGISTER */ +#define STK_CTRL ((volatile uint32_t *)(0xE000E010)) +#define STK_RELOAD ((volatile uint32_t *)(0xE000E014)) + + +/* SYSTEM CONTROL REGISTER */ #define SYSCTRL_RCC ((volatile unsigned long *)(0x400FE060)) #define SYSCTRL_RIS ((volatile unsigned long *)(0x400FE050)) #define SYSCTRL_RCGC1 ((volatile unsigned long *)(0x400FE104)) diff --git a/include/stm32.h b/include/stm32.h index e4409f2..2d1544c 100644 --- a/include/stm32.h +++ b/include/stm32.h @@ -6,8 +6,6 @@ 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 *); -extern unsigned char inportb (uint32_t _addr); -extern void outportb (uint32_t _addr, unsigned char _data); /* UART.C */ extern void uart_init(); @@ -16,5 +14,9 @@ extern void uart_puts(unsigned char *); /* IVT.C */ extern void ivt_init(); +extern void ivt_set_gate(unsigned char, void *(), short); + +/* SYSTICK.C */ +extern void systick_init(); #endif diff --git a/ivt.c b/ivt.c index fadf533..ba617ef 100644 --- a/ivt.c +++ b/ivt.c @@ -4,82 +4,49 @@ #include #include -/* TIMER, TODO: move to timer.c */ - - +/* + * Vector table, each entry contains an interrupt + * service routine: * + * + * interrupt vector 1-15: processor exceptions + * interrupt vector 16-32: irq0 - irq .. + * */ -/* 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 .. */ +uint32_t ivt[32]; -/* 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 + *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F)); + /* Priorities */ } -// test Interrupt service routine -void * test_ISR() { - uart_puts("PING!"); + +/* Dummy interrupt */ +void * dummy_isr() { + } /* 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)); + memset(&ivt, 0, (sizeof(uint32_t) * 87)); // 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). */ + ivt_set_gate(1, dummy_isr, 0); + ivt_set_gate(2, dummy_isr, 0); + ivt_set_gate(3, 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 + * a register in the NVIC called the vector table offset register */ - *NVIC_VECTTBL = (volatile unsigned long) &ivt; + *SCB_VTOR = (volatile uint32_t) &ivt; } diff --git a/link.ld b/link.ld index 096fb5d..d1a01dd 100644 --- a/link.ld +++ b/link.ld @@ -1,7 +1,7 @@ /* * MEMORY MAP { - FLASH (xr) : ORIGIN = 0x00000000, LENGTH = 512K + FLASH (xr) : ORIGIN = 0x08000000, LENGTH = 512K SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K } */ diff --git a/main.c b/main.c index c17c664..58e4771 100644 --- a/main.c +++ b/main.c @@ -36,31 +36,17 @@ int strlen(const char *str) return retval; } -unsigned char inportb (uint32_t _addr) -{ - unsigned char rv; - //__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); - return rv; - -} -void outportb (uint32_t _addr, unsigned char _data) -{ - // __asm__ __volatile__ ("str %1, %0" : "=r" (_data) : "m" (_addr) ); - - // __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); -} void main() { - uart_init(); - uart_puts("LOADING SYSTEM...\n"); + //uart_init(); + //uart_puts("LOADING SYSTEM...\n"); ivt_init(); - - //extern void stub(); - //stub(); + systick_init(); +// asm("cpsie i"); // enable irq , cpsied f (disable faukts( // loop for(;;) { diff --git a/systick.c b/systick.c new file mode 100644 index 0000000..b9c8756 --- /dev/null +++ b/systick.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include + + +void * systick_handler() { + + *RANDOM_ADDR = (volatile uint32_t) 0x10101010 ; +} + +void systick_init() { + + /* Enable the counter and enable the interrupt + * associated with it */ + *STK_CTRL = (volatile uint32_t) 0x00000003; + + /* The counter reload register here holds + * 0x1000 -- that's 4096 clock cycles -- if + * it is down to zero it is restores the value */ + *STK_RELOAD = (volatile uint32_t) 0x00000400; + + /* Every time the counter counts down to zero + * a systick exception is asserted. Systick has + * exception number 15. in the vector table */ + ivt_set_gate(15, systick_handler, 0); +}