From: arighi Date: Tue, 13 Apr 2010 13:13:34 +0000 (+0000) Subject: CM3: generic IRQ management module. X-Git-Tag: 2.5.0~485 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=9a332b1eebc9dba4b9cc5cfa901fe414824ceea1;p=bertos.git CM3: generic IRQ management module. Define an IRQ management module generic for all the Cortex-M3 family processors. Moreover, automatically set the appropriate priority and enable the IRQ when registering an ISR via sysirq_setHandler(). git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3423 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/bertos/cpu/cortex-m3/drv/irq_cm3.c b/bertos/cpu/cortex-m3/drv/irq_cm3.c new file mode 100644 index 00000000..a21439a7 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/irq_cm3.c @@ -0,0 +1,127 @@ +/** + * \file + * + * + * \brief Cortex-M3 IRQ management. + * + * \author Andrea Righi + */ + +#include /* ASSERT() */ +#include /* LOG_ERR() */ +#include +#include "irq_cm3.h" + +static void (*irq_table[NUM_INTERRUPTS])(void) + __attribute__((section("vtable"))); + +/* Priority register / IRQ number table */ +static const uint32_t nvic_prio_reg[] = +{ + /* System exception registers */ + 0, NVIC_SYS_PRI1, NVIC_SYS_PRI2, NVIC_SYS_PRI3, + + /* External interrupts registers */ + NVIC_PRI0, NVIC_PRI1, NVIC_PRI2, NVIC_PRI3, + NVIC_PRI4, NVIC_PRI5, NVIC_PRI6, NVIC_PRI7, + NVIC_PRI8, NVIC_PRI9, NVIC_PRI10, NVIC_PRI11, + NVIC_PRI12, NVIC_PRI13 +}; + +/* Unhandled IRQ */ +static NAKED NORETURN void unhandled_isr(void) +{ + register uint32_t reg; + + asm volatile ("mrs %0, ipsr" : "=r"(reg)); + LOG_ERR("unhandled IRQ %lu\n", reg); + while (1) + PAUSE; +} + +void sysirq_setPriority(sysirq_t irq, int prio) +{ + uint32_t pos = (irq & 3) * 8; + reg32_t reg = nvic_prio_reg[irq >> 2]; + uint32_t val; + + val = HWREG(reg); + val &= ~(0xff << pos); + val |= prio << pos; + HWREG(reg) = val; +} + +static void sysirq_enable(sysirq_t irq) +{ + /* Enable the IRQ line (only for generic IRQs) */ + if (irq >= 16 && irq < 48) + HWREG(NVIC_EN0) = 1 << (irq - 16); + else if (irq >= 48) + HWREG(NVIC_EN1) = 1 << (irq - 48); +} + +void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler) +{ + cpu_flags_t flags; + + ASSERT(irq < NUM_INTERRUPTS); + + IRQ_SAVE_DISABLE(flags); + irq_table[irq] = handler; + sysirq_setPriority(irq, IRQ_PRIO); + sysirq_enable(irq); + IRQ_RESTORE(flags); +} + +void sysirq_freeHandler(sysirq_t irq) +{ + cpu_flags_t flags; + + ASSERT(irq < NUM_INTERRUPTS); + + IRQ_SAVE_DISABLE(flags); + irq_table[irq] = unhandled_isr; + IRQ_RESTORE(flags); +} + +void sysirq_init(void) +{ + cpu_flags_t flags; + int i; + + IRQ_SAVE_DISABLE(flags); + for (i = 0; i < NUM_INTERRUPTS; i++) + irq_table[i] = unhandled_isr; + + /* Update NVIC to point to the new vector table */ + HWREG(NVIC_VTABLE) = (size_t)irq_table; + IRQ_RESTORE(flags); +} diff --git a/bertos/cpu/cortex-m3/drv/irq_cm3.h b/bertos/cpu/cortex-m3/drv/irq_cm3.h new file mode 100644 index 00000000..a3f2ded4 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/irq_cm3.h @@ -0,0 +1,57 @@ +/** + * \file + * + * + * \brief IRQ management for the Cortex-M3 processor. + * + * \author Andrea Righi + */ + +#ifndef DRV_CORTEX_M3_SYSIRQ_H +#define DRV_CORTEX_M3_SYSIRQ_H + +#if CPU_CM3_LM3S + #include +/*#elif Add other families here */ +#else + #error Unknown CPU +#endif + +typedef void (*sysirq_handler_t)(void); +typedef unsigned int sysirq_t; + +void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler); +void sysirq_setPriority(sysirq_t irq, int prio); +void sysirq_freeHandler(sysirq_t irq); + +void sysirq_init(void); + +#endif /* DRV_CORTEX_M3_SYSIRQ_H */ diff --git a/bertos/cpu/cortex-m3/drv/irq_lm3s.c b/bertos/cpu/cortex-m3/drv/irq_lm3s.c deleted file mode 100644 index 98112cad..00000000 --- a/bertos/cpu/cortex-m3/drv/irq_lm3s.c +++ /dev/null @@ -1,117 +0,0 @@ -/** - * \file - * - * - * \brief Cortex-M3 IRQ management. - * - * \author Andrea Righi - */ - -#include /* ASSERT() */ -#include /* LOG_ERR() */ -#include -#include -#include "irq_lm3s.h" - -static void (*irq_table[NUM_INTERRUPTS])(void) - __attribute__((section("vtable"))); - -/* Unhandled IRQ */ -static NAKED NORETURN void unhandled_isr(void) -{ - register uint32_t reg; - - asm volatile ("mrs %0, ipsr" : "=r"(reg)); - LOG_ERR("unhandled IRQ %lu\n", reg); - while (1) - PAUSE; -} - -void sysirq_setPriority(sysirq_t irq, int prio) -{ - uint32_t pos = (irq & 3) * 8; - reg32_t reg; - - switch (irq >> 2) - { - case 1: - reg = NVIC_SYS_PRI1; - break; - case 2: - reg = NVIC_SYS_PRI2; - break; - case 3: - reg = NVIC_SYS_PRI3; - break; - default: - ASSERT(0); - return; - } - HWREG(reg) &= ~(0xff << pos); - HWREG(reg) |= prio << pos; -} - -void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler) -{ - cpu_flags_t flags; - - ASSERT(irq < NUM_INTERRUPTS); - - IRQ_SAVE_DISABLE(flags); - irq_table[irq] = handler; - sysirq_setPriority(irq, IRQ_PRIO); - IRQ_RESTORE(flags); -} - -void sysirq_freeHandler(sysirq_t irq) -{ - cpu_flags_t flags; - - ASSERT(irq < NUM_INTERRUPTS); - - IRQ_SAVE_DISABLE(flags); - irq_table[irq] = unhandled_isr; - IRQ_RESTORE(flags); -} - -void sysirq_init(void) -{ - cpu_flags_t flags; - int i; - - IRQ_SAVE_DISABLE(flags); - for (i = 0; i < NUM_INTERRUPTS; i++) - irq_table[i] = unhandled_isr; - - /* Update NVIC to point to the new vector table */ - HWREG(NVIC_VTABLE) = (size_t)irq_table; - IRQ_RESTORE(flags); -} diff --git a/bertos/cpu/cortex-m3/drv/irq_lm3s.h b/bertos/cpu/cortex-m3/drv/irq_lm3s.h deleted file mode 100644 index 8913183d..00000000 --- a/bertos/cpu/cortex-m3/drv/irq_lm3s.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * \file - * - * - * \brief IRQ management for the Cortex M3 processor. - * - * \author Andrea Righi - */ - -#ifndef DRV_CORTEX_M3_SYSIRQ_H -#define DRV_CORTEX_M3_SYSIRQ_H - -typedef void (*sysirq_handler_t)(void); -typedef unsigned int sysirq_t; - -void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler); -void sysirq_setPriority(sysirq_t irq, int prio); -void sysirq_freeHandler(sysirq_t irq); - -void sysirq_init(void); - -#endif /* DRV_CORTEX_M3_SYSIRQ_H */ diff --git a/bertos/cpu/cortex-m3/drv/timer_lm3s.c b/bertos/cpu/cortex-m3/drv/timer_lm3s.c index 096bff92..49b9fa8e 100644 --- a/bertos/cpu/cortex-m3/drv/timer_lm3s.c +++ b/bertos/cpu/cortex-m3/drv/timer_lm3s.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "timer_lm3s.h" INLINE void timer_hw_setPeriod(unsigned long period) diff --git a/bertos/cpu/cortex-m3/hw/init_lm3s.c b/bertos/cpu/cortex-m3/hw/init_lm3s.c index caac9d09..0c0a05b7 100644 --- a/bertos/cpu/cortex-m3/hw/init_lm3s.c +++ b/bertos/cpu/cortex-m3/hw/init_lm3s.c @@ -42,7 +42,7 @@ #include /* PAUSE */ #include /* IRQ_DISABLE */ #include -#include +#include #include #include #include "switch_ctx_cm3.h" diff --git a/examples/lm3s1968/lm3s1968.mk b/examples/lm3s1968/lm3s1968.mk index dbbea22b..e90b31d1 100644 --- a/examples/lm3s1968/lm3s1968.mk +++ b/examples/lm3s1968/lm3s1968.mk @@ -41,11 +41,11 @@ lm3s1968_CSRC = \ bertos/kern/preempt.c \ bertos/kern/signal.c \ bertos/cpu/cortex-m3/drv/gpio_lm3s.c \ - bertos/cpu/cortex-m3/drv/irq_lm3s.c \ bertos/cpu/cortex-m3/drv/timer_lm3s.c \ bertos/cpu/cortex-m3/drv/clock_lm3s.c \ bertos/cpu/cortex-m3/drv/kdebug_lm3s.c \ bertos/cpu/cortex-m3/drv/ssi_lm3s.c \ + bertos/cpu/cortex-m3/drv/irq_cm3.c \ bertos/cpu/cortex-m3/hw/switch_ctx_cm3.c \ bertos/cpu/cortex-m3/hw/init_lm3s.c