From 1e39e7e486eedd57a41a34ab281690e079efe28c Mon Sep 17 00:00:00 2001 From: Thomas Eichinger Date: Thu, 24 Oct 2013 13:53:09 +0200 Subject: [PATCH] change to the mc1322x IRQ handling since mc1322x lacks a VIC this is a kind of SW VIC with low latency and compatibility to the VIC API in mind. --- cpu/arm_common/common.s | 5 ++++ cpu/mc1322x/cpu.c | 39 +++++++++++---------------- cpu/mc1322x/hwtimer_cpu.c | 23 ++++++++++++++-- cpu/mc1322x/include/cpu.h | 12 +++++++-- cpu/mc1322x/include/mc1322x.h | 15 ++++++++--- cpu/mc1322x/isr.c | 50 +++++++++++++++++++++++++++++++++++ cpu/mc1322x/startup.s | 2 +- 7 files changed, 113 insertions(+), 33 deletions(-) create mode 100644 cpu/mc1322x/isr.c diff --git a/cpu/arm_common/common.s b/cpu/arm_common/common.s index 66646adef4..9b3164a356 100644 --- a/cpu/arm_common/common.s +++ b/cpu/arm_common/common.s @@ -136,8 +136,13 @@ arm_irq_handler: MRS R1, CPSR MSR SPSR, R1 +#if CPU != mc1322x /* jump into vic interrupt */ mov r0, #0xffffff00 /* lpc23xx */ +#else + /* mc1322x seems to lack a VIC, distinction of IRQ has to be done in SW */ + ldr r0, =isr /* mc1322x */ +#endif ldr r0, [r0] add lr,pc,#4 diff --git a/cpu/mc1322x/cpu.c b/cpu/mc1322x/cpu.c index 7e90e141b7..456a5e7a08 100644 --- a/cpu/mc1322x/cpu.c +++ b/cpu/mc1322x/cpu.c @@ -1,6 +1,7 @@ /* * cpu.c - MC1322X architecture common support functions * Copyright (C) 2013 Oliver Hahm + * Thomas Eichinger * * This source code is licensed under the GNU Lesser General Public License, * Version 2. See the file LICENSE for more details. @@ -10,7 +11,9 @@ */ #include "mc1322x.h" +#include "cpu.h" #include "lpm.h" +#include "arm_cpu.h" __attribute__((naked,noreturn)) void arm_reset(void) { @@ -20,37 +23,25 @@ __attribute__((naked,noreturn)) void arm_reset(void) } enum lpm_mode lpm_set(enum lpm_mode target) { + (void) target; return LPM_ON; } /****************************************************************************** -** Function name: cpu_install_irq +** Function name: install_irq ** -** Descriptions: Install interrupt handler -** parameters: Interrupt number, interrupt handler address, -** interrupt priority -** Returned value: true or false, return false if IntNum is out of range +** Descriptions: Install interrupt handler. +** A wrapper to register_isr to be consistant to lpc2387 +** implementation. +** parameters: Interrupt number, interrupt handler address, +** interrupt priority +** Returned value: true or false, return false if IntNum is out of range ** ******************************************************************************/ -#define VIC_BASE_ADDR 0xFFFFF000 -bool cpu_install_irq(int IntNumber, void *HandlerAddr, int Priority) +bool install_irq(int int_number, void *handler_addr, int priority) { - int *vect_addr; - int *vect_cntl; - - VICIntEnClr = 1 << IntNumber; /* Disable Interrupt */ - - if (IntNumber >= VIC_SIZE) { - return (false); - } - else { - /* find first un-assigned VIC address for the handler */ - vect_addr = (int *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber * 4); - vect_cntl = (int *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber * 4); - *vect_addr = (int)HandlerAddr; /* set interrupt vector */ - *vect_cntl = Priority; - VICIntEnable = 1 << IntNumber; /* Enable Interrupt */ - return(true); - } + (void) priority; + register_isr(int_number, handler_addr); + return (true); } diff --git a/cpu/mc1322x/hwtimer_cpu.c b/cpu/mc1322x/hwtimer_cpu.c index 4f53f4d42a..6e37f800a2 100644 --- a/cpu/mc1322x/hwtimer_cpu.c +++ b/cpu/mc1322x/hwtimer_cpu.c @@ -11,12 +11,31 @@ #include #include "mc1322x.h" +#include "cpu.h" #include "hwtimer_arch.h" #include "irq.h" /* High level interrupt handler */ static void (*int_handler)(int); +#define TMRx_ANY_INTERRUPT 0xa800 + +void tmr_isr(void) { + /* detemine which timer caused the interrupt */ + if (TMR0->SCTRL & TMRx_ANY_INTERRUPT) { + int_handler(TMR0_BASE); + } + else if (TMR1->SCTRL & TMRx_ANY_INTERRUPT) { + int_handler(TMR1_BASE); + } + else if (TMR2->SCTRL & TMRx_ANY_INTERRUPT) { + int_handler(TMR2_BASE); + } + else if (TMR3->SCTRL & TMRx_ANY_INTERRUPT) { + int_handler(TMR3_BASE); + } +} + void timer_x_init(volatile struct TMR_struct* const TMRx) { /* Reset the timer */ TMRx->ENBL = 0; @@ -45,8 +64,6 @@ void timer_x_init(volatile struct TMR_struct* const TMRx) { TMRx->CTRLbits.OUTPUT_MODE = 0x00; /* OFLAG is asserted while counter is active */ TMRx->ENBL = 0xf; /* enable all the timers --- why not? */ - - /* TODO: install ISR */ } void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) { @@ -59,6 +76,8 @@ void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) { timer_x_init(TMR1); timer_x_init(TMR2); timer_x_init(TMR3); + + install_irq(INT_NUM_TMR, &tmr_isr, 0); } /*---------------------------------------------------------------------------*/ diff --git a/cpu/mc1322x/include/cpu.h b/cpu/mc1322x/include/cpu.h index f37db452d5..82b307bf4a 100644 --- a/cpu/mc1322x/include/cpu.h +++ b/cpu/mc1322x/include/cpu.h @@ -15,10 +15,18 @@ #ifndef CPU_H #define CPU_H -#include +/** + * @defgroup mc1322x Freescale mc1322x + * @ingroup cpu + * @{ + */ + +#include #include "arm_cpu.h" #include "mc1322x.h" -extern uintptr_t __stack_start; ///< end of user stack memory space +extern uintptr_t __stack_start; ///< end of user stack memory space +bool install_irq(int int_number, void *handler_addr, int priority); +/** @} */ #endif /* CPU_H */ diff --git a/cpu/mc1322x/include/mc1322x.h b/cpu/mc1322x/include/mc1322x.h index 20409bf445..d8c7c74e0d 100644 --- a/cpu/mc1322x/include/mc1322x.h +++ b/cpu/mc1322x/include/mc1322x.h @@ -415,12 +415,11 @@ enum interrupt_nums { x; \ __int_enable(); } while(0) +extern void register_isr(uint8_t interrupt, void (*isr)(void)); -extern void tmr0_isr(void) __attribute__((weak)); -extern void tmr1_isr(void) __attribute__((weak)); -extern void tmr2_isr(void) __attribute__((weak)); -extern void tmr3_isr(void) __attribute__((weak)); +extern void tmr_isr(void) __attribute__((weak)); +extern void crm_isr(void) __attribute__((weak)); extern void rtc_isr(void) __attribute__((weak)); extern void kbi4_isr(void) __attribute__((weak)); extern void kbi5_isr(void) __attribute__((weak)); @@ -438,4 +437,12 @@ extern void asm_isr(void) __attribute__((weak)); extern void i2c_isr(void) __attribute__((weak)); +extern void spif_isr(void) __attribute__((weak)); + +extern void ssi_isr(void) __attribute__((weak)); + +extern void adc_isr(void) __attribute__((weak)); + +extern void spi_isr(void) __attribute__((weak)); + #endif /* MC1322X_H */ diff --git a/cpu/mc1322x/isr.c b/cpu/mc1322x/isr.c new file mode 100644 index 0000000000..533f21729b --- /dev/null +++ b/cpu/mc1322x/isr.c @@ -0,0 +1,50 @@ +/* + * isr.c - mc1322x specific isr + * Copyright (C) 2013 Thomas Eichinger + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "mc1322x.h" + +#define MAX_IRQ_INDEX 10 +#define MAX_IRQ_NUM 11 + +static void (*isr_funcs[11])(void) = { + asm_isr, + uart1_isr, + uart2_isr, + crm_isr, + i2c_isr, + tmr_isr, + spif_isr, + maca_isr, + ssi_isr, + adc_isr, + spi_isr +}; + +void register_isr(uint8_t interrupt, void (*isr)(void)) { + if (interrupt <= MAX_IRQ_INDEX) { + isr_funcs[interrupt] = isr; + } +} + +void isr(void) +{ + /* set irq_num to an invalid value */ + uint8_t irq_num = MAX_IRQ_NUM; + + /* pending interrupt? */ + while (ITC->NIPEND) { + /* get interrupt source, range 0-10 */ + irq_num = ITC->NIVECTOR; + /* call corresponding ISR */ + if (isr_funcs[irq_num] != 0) { + (isr_funcs[irq_num])(); + } + } +} diff --git a/cpu/mc1322x/startup.s b/cpu/mc1322x/startup.s index 07f2c08a14..c454a6cd80 100644 --- a/cpu/mc1322x/startup.s +++ b/cpu/mc1322x/startup.s @@ -176,7 +176,7 @@ SWI_Addr: .word ctx_switch PAbt_Addr: .word PABT_Routine DAbt_Addr: .word DABT_Routine _not_used: .word not_used -IRQ_Addr: .word irq +IRQ_Addr: .word arm_irq_handler _fiq: .word fiq .balignl 16, 0xdeadbeef