From dd84fc9066262c4d2872cdd510c36a03e5204324 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 21 Jun 2015 23:56:38 +0200 Subject: [PATCH] Basic interrupt handling; enough so that timers work. --- Kernel/kernel430x.def | 2 + Kernel/lowlevel-msp430x.S | 21 +++++++++ Kernel/platform-msp430fr5969/build.mk | 1 + Kernel/platform-msp430fr5969/config.h | 2 +- Kernel/platform-msp430fr5969/crt0.S | 47 ++++++++++++++++---- Kernel/platform-msp430fr5969/devices.c | 25 +++++++++++ Kernel/platform-msp430fr5969/globals.h | 7 +++ Kernel/platform-msp430fr5969/msp430fr5969.ld | 3 +- 8 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 Kernel/lowlevel-msp430x.S create mode 100644 Kernel/platform-msp430fr5969/globals.h diff --git a/Kernel/kernel430x.def b/Kernel/kernel430x.def index 7f3f74a5..f0431a3c 100644 --- a/Kernel/kernel430x.def +++ b/Kernel/kernel430x.def @@ -1,3 +1,5 @@ +U_DATA = udata + ; Keep these in sync with struct u_data!! #define U_DATA__U_PTAB (U_DATA+0) ; struct p_tab* #define U_DATA__U_PAGE (U_DATA+2) ; uint16_t diff --git a/Kernel/lowlevel-msp430x.S b/Kernel/lowlevel-msp430x.S new file mode 100644 index 00000000..b269fdc1 --- /dev/null +++ b/Kernel/lowlevel-msp430x.S @@ -0,0 +1,21 @@ +#include "kernel430x.def" + +.section ".lowtext" +.globl interrupt_handler +interrupt_handler: + /* Interrupts are off here and we're running on... a... stack. This + * may be the user process or the kernel's. We haven't saved any + * registers yet. */ + + mov SP, &istack_switched_sp ; save old stack (16 bit!) + mov #istack_top, SP ; load new one + + pushm.a #13, r15 ; save all registers (r15 to r3) + + calla #platform_interrupt + + popm.a #13, r15 ; restore all registers (r15 to r3) + + mov &istack_switched_sp, SP ; restore stack + reti + diff --git a/Kernel/platform-msp430fr5969/build.mk b/Kernel/platform-msp430fr5969/build.mk index 3db60b51..b6c4b7ed 100644 --- a/Kernel/platform-msp430fr5969/build.mk +++ b/Kernel/platform-msp430fr5969/build.mk @@ -17,6 +17,7 @@ kernel.srcs = \ ../dev/mbr.c \ ../devio.c \ ../filesys.c \ + ../lowlevel-msp430x.S \ ../kdata.c \ ../process.c \ ../simple.c \ diff --git a/Kernel/platform-msp430fr5969/config.h b/Kernel/platform-msp430fr5969/config.h index 77aa7b3d..701f1372 100644 --- a/Kernel/platform-msp430fr5969/config.h +++ b/Kernel/platform-msp430fr5969/config.h @@ -41,7 +41,7 @@ extern unsigned char vt_mangle_6847(unsigned char c); extern int __user_base; -#define TICKSPERSEC 100 /* Ticks per second */ +#define TICKSPERSEC 64 /* Ticks per second */ #define PROGBASE ((uint16_t)(size_t)&__user_base) /* also data base */ #define PROGLOAD PROGBASE /* also data base */ #define PROGTOP 0xfe00 /* Top of program */ diff --git a/Kernel/platform-msp430fr5969/crt0.S b/Kernel/platform-msp430fr5969/crt0.S index c748f1bc..d7910a95 100644 --- a/Kernel/platform-msp430fr5969/crt0.S +++ b/Kernel/platform-msp430fr5969/crt0.S @@ -1,6 +1,7 @@ #include "msp430fr5969.h" #include "kernel.def" #include "kernel430x.def" +#include "globals.h" ; imported symbols .globl fuzix_main @@ -13,13 +14,14 @@ .section ".noinit" ; The interrupt stack. +.globl istack_top istack_base: .fill 254 istack_top: -; The saved interrupt pointer. -.globl istack_switch_sp -.comm istack_switch_sp, 2 +; The saved interrupt pointer. Stacks must be in low memory. +.globl istack_switched_sp +.comm istack_switched_sp, 2 ; The userdata/system stack structure. See Kernel/include/kernel.h. .globl udata @@ -37,8 +39,23 @@ __main: mov.b #CSKEY>>8, &CSCTL0_H ; Unlock clock registers mov.w #DCOFSEL_3 | DCORSEL, &CSCTL1 ; DCO to 8MHz ; ACLK = VLO; SMCLK = MCLK = DCO - mov.w #(SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK), &CSCTL2 + mov.w #(SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK), &CSCTL2 mov.w #(DIVA__1 | DIVS__1 | DIVM__1), &CSCTL3 + + ; Configure the LFXT. + mov.w #0, &PJSEL1 + mov.w #BIT4|BIT5, &PJSEL0 + bis.w #LFXTDRIVE_3|HFXTOFF, &CSCTL4 + bic.w #LFXTBYPASS|LFXTOFF, &CSCTL4 + + ; Wait for oscillators to settle. + +1: + bic.w #LFXTOFFG|HFXTOFFG, &CSCTL5 + bic.w #OFIFG, &SFRIFG1 + bit.w #OFIFG, &SFRIFG1 + jnz 1b + mov.b #0, &CSCTL0_H ; Relock clock registers ; Init stack. @@ -108,6 +125,18 @@ irqrestore: .word __main .text +.globl last_interrupt +.comm last_interrupt, 1 + +#define standard_interrupt(name, irq) \ + .globl name ## _trampoline { \ + .section ".lowtext", "ax", @progbits { \ + name ## _trampoline: \ + mov.b #(irq), &last_interrupt { \ + bra #interrupt_handler { \ + .section #name, "ax", @progbits { \ + .word name ## _trampoline + #define fallback_interrupt(name) \ .text { \ 1: mov #3f, r12 { \ @@ -115,11 +144,13 @@ irqrestore: calla #kprintf { \ 2: jmp 2b { \ .data { \ - 3: .asciz name { \ - .section name, "ax", @progbits { \ + 3: .asciz #name { \ + .section #name, "ax", @progbits { \ .word 1b ;fallback_interrupt("__interrupt_vector_comp_e") -fallback_interrupt("__interrupt_vector_unmi") -fallback_interrupt("__interrupt_vector_sysnmi") +fallback_interrupt(__interrupt_vector_unmi) +fallback_interrupt(__interrupt_vector_sysnmi) + +standard_interrupt(__interrupt_vector_wdt, INTERRUPT_WDT) diff --git a/Kernel/platform-msp430fr5969/devices.c b/Kernel/platform-msp430fr5969/devices.c index 5381b2e6..5f671299 100644 --- a/Kernel/platform-msp430fr5969/devices.c +++ b/Kernel/platform-msp430fr5969/devices.c @@ -4,6 +4,12 @@ #include #include #include +#include +#include +#include "msp430fr5969.h" +#include "globals.h" + +extern uint8_t last_interrupt; struct devsw dev_tab[] = /* The device driver switch table */ { @@ -34,7 +40,26 @@ bool validdev(uint16_t dev) void device_init(void) { + /* Configure the watchdog timer to use ACLK as the system interrupt. + * ACLK was set up in the boot sequence to use the LFXT clock, which runs + * (relatively accurately) at 32kHz. 512 ticks at 32kHz is 64Hz. + */ + + WDTCTL = WDTPW | WDTSSEL__ACLK | WDTTMSEL | WDTCNTCL | WDTIS__512; + SFRIE1 |= WDTIE; + devsd_init(); } +/* This is called with interrupts off. */ +void platform_interrupt(void) +{ + switch (last_interrupt) + { + case INTERRUPT_WDT: + timer_interrupt(); + break; + } +} + diff --git a/Kernel/platform-msp430fr5969/globals.h b/Kernel/platform-msp430fr5969/globals.h new file mode 100644 index 00000000..7db92577 --- /dev/null +++ b/Kernel/platform-msp430fr5969/globals.h @@ -0,0 +1,7 @@ +#ifndef GLOBALS_H +#define GLOBALS_H + +#define INTERRUPT_WDT 0 + +#endif + diff --git a/Kernel/platform-msp430fr5969/msp430fr5969.ld b/Kernel/platform-msp430fr5969/msp430fr5969.ld index f7deec55..ed363cd0 100644 --- a/Kernel/platform-msp430fr5969/msp430fr5969.ld +++ b/Kernel/platform-msp430fr5969/msp430fr5969.ld @@ -221,8 +221,7 @@ SECTIONS KEEP (*(.dtors)) } > HIROM - .text : - { + .text : { . = ALIGN(2); PROVIDE (_start = .); KEEP (*(SORT(.crt_*))) -- 2.34.1