irq_cm3.c
Go to the documentation of this file.00001
00038 #include <cfg/debug.h>
00039 #include <cfg/log.h>
00040 #include <cpu/irq.h>
00041 #include "irq_cm3.h"
00042
00043 static void (*irq_table[NUM_INTERRUPTS])(void)
00044 __attribute__((section("vtable")));
00045
00046
00047 static const uint32_t nvic_prio_reg[] =
00048 {
00049
00050 0, NVIC_SYS_PRI1, NVIC_SYS_PRI2, NVIC_SYS_PRI3,
00051
00052
00053 NVIC_PRI0, NVIC_PRI1, NVIC_PRI2, NVIC_PRI3,
00054 NVIC_PRI4, NVIC_PRI5, NVIC_PRI6, NVIC_PRI7,
00055 NVIC_PRI8, NVIC_PRI9, NVIC_PRI10, NVIC_PRI11,
00056 NVIC_PRI12, NVIC_PRI13
00057 };
00058
00059
00060 static NAKED NORETURN void unhandled_isr(void)
00061 {
00062 register uint32_t reg;
00063
00064 asm volatile ("mrs %0, ipsr" : "=r"(reg));
00065 LOG_ERR("unhandled IRQ %lu\n", reg);
00066 while (1)
00067 PAUSE;
00068 }
00069
00070 void sysirq_setPriority(sysirq_t irq, int prio)
00071 {
00072 uint32_t pos = (irq & 3) * 8;
00073 reg32_t reg = nvic_prio_reg[irq >> 2];
00074 uint32_t val;
00075
00076 val = HWREG(reg);
00077 val &= ~(0xff << pos);
00078 val |= prio << pos;
00079 HWREG(reg) = val;
00080 }
00081
00082 static void sysirq_enable(sysirq_t irq)
00083 {
00084
00085 if (irq >= 16 && irq < 48)
00086 NVIC_EN0_R = 1 << (irq - 16);
00087 else if (irq >= 48)
00088 NVIC_EN1_R = 1 << (irq - 48);
00089 }
00090
00091 void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler)
00092 {
00093 cpu_flags_t flags;
00094
00095 ASSERT(irq < NUM_INTERRUPTS);
00096
00097 IRQ_SAVE_DISABLE(flags);
00098 irq_table[irq] = handler;
00099 sysirq_setPriority(irq, IRQ_PRIO);
00100 sysirq_enable(irq);
00101 IRQ_RESTORE(flags);
00102 }
00103
00104 void sysirq_freeHandler(sysirq_t irq)
00105 {
00106 cpu_flags_t flags;
00107
00108 ASSERT(irq < NUM_INTERRUPTS);
00109
00110 IRQ_SAVE_DISABLE(flags);
00111 irq_table[irq] = unhandled_isr;
00112 IRQ_RESTORE(flags);
00113 }
00114
00115 void sysirq_init(void)
00116 {
00117 cpu_flags_t flags;
00118 int i;
00119
00120 IRQ_SAVE_DISABLE(flags);
00121 for (i = 0; i < NUM_INTERRUPTS; i++)
00122 irq_table[i] = unhandled_isr;
00123
00124
00125 NVIC_VTABLE_R = (size_t)irq_table;
00126 IRQ_RESTORE(flags);
00127 }