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