cpu/irq.h
Go to the documentation of this file.
00001 00041 #ifndef CPU_IRQ_H 00042 #define CPU_IRQ_H 00043 00044 #include "detect.h" 00045 #include "types.h" 00046 00047 #include <kern/proc.h> /* proc_needPreempt() / proc_preempt() */ 00048 00049 #include <cfg/compiler.h> /* for uintXX_t */ 00050 #include "cfg/cfg_proc.h" /* CONFIG_KERN_PREEMPT */ 00051 00052 #if CPU_I196 00053 #define IRQ_DISABLE disable_interrupt() 00054 #define IRQ_ENABLE enable_interrupt() 00055 #elif CPU_X86 00056 00057 /* Get IRQ_* definitions from the hosting environment. */ 00058 #include <cfg/os.h> 00059 #if OS_EMBEDDED 00060 #define IRQ_DISABLE FIXME 00061 #define IRQ_ENABLE FIXME 00062 #define IRQ_SAVE_DISABLE(x) FIXME 00063 #define IRQ_RESTORE(x) FIXME 00064 #endif /* OS_EMBEDDED */ 00065 00066 #elif CPU_CM3 00067 /* Cortex-M3 */ 00068 00069 /* 00070 * Interrupt priority. 00071 * 00072 * NOTE: 0 means that an interrupt is not affected by the global IRQ 00073 * priority settings. 00074 */ 00075 #define IRQ_PRIO 0x80 00076 #define IRQ_PRIO_MIN 0xf0 00077 #define IRQ_PRIO_MAX 0 00078 /* 00079 * To disable interrupts we just raise the system base priority to a 00080 * number lower than the default IRQ priority. In this way, all the 00081 * "normal" interrupt can't be triggered. High-priority interrupt can 00082 * still happen (at the moment only the soft-interrupt svcall uses a 00083 * priority greater than the default IRQ priority). 00084 * 00085 * To enable interrupts we set the system base priority to 0, that 00086 * means IRQ priority mechanism is disabled, and any interrupt can 00087 * happen. 00088 */ 00089 #define IRQ_PRIO_DISABLED 0x40 00090 #define IRQ_PRIO_ENABLED 0 00091 00092 #ifdef __IAR_SYSTEMS_ICC__ 00093 INLINE cpu_flags_t CPU_READ_FLAGS(void) 00094 { 00095 return __get_BASEPRI(); 00096 } 00097 00098 INLINE void CPU_WRITE_FLAGS(cpu_flags_t flags) 00099 { 00100 __set_BASEPRI(flags); 00101 } 00102 00103 extern uint32_t CPU_READ_IPSR(void); 00104 extern bool irq_running(void); 00105 00106 #define IRQ_DISABLE CPU_WRITE_FLAGS(IRQ_PRIO_DISABLED) 00107 00108 #define IRQ_ENABLE CPU_WRITE_FLAGS(IRQ_PRIO_ENABLED) 00109 00110 #define IRQ_SAVE_DISABLE(x) \ 00111 do { \ 00112 x = CPU_READ_FLAGS(); \ 00113 IRQ_DISABLE; \ 00114 } while (0) 00115 00116 #define IRQ_RESTORE(x) \ 00117 do { \ 00118 CPU_WRITE_FLAGS(x); \ 00119 } while (0) 00120 #else /* !__IAR_SYSTEMS_ICC__ */ 00121 #define IRQ_DISABLE \ 00122 ({ \ 00123 register cpu_flags_t reg = IRQ_PRIO_DISABLED; \ 00124 asm volatile ( \ 00125 "msr basepri, %0" \ 00126 : : "r"(reg) : "memory", "cc"); \ 00127 }) 00128 00129 #define IRQ_ENABLE \ 00130 ({ \ 00131 register cpu_flags_t reg = IRQ_PRIO_ENABLED; \ 00132 asm volatile ( \ 00133 "msr basepri, %0" \ 00134 : : "r"(reg) : "memory", "cc"); \ 00135 }) 00136 00137 #define CPU_READ_FLAGS() \ 00138 ({ \ 00139 register cpu_flags_t reg; \ 00140 asm volatile ( \ 00141 "mrs %0, basepri" \ 00142 : "=r"(reg) : : "memory", "cc"); \ 00143 reg; \ 00144 }) 00145 00146 #define IRQ_SAVE_DISABLE(x) \ 00147 ({ \ 00148 x = CPU_READ_FLAGS(); \ 00149 IRQ_DISABLE; \ 00150 }) 00151 00152 #define IRQ_RESTORE(x) \ 00153 ({ \ 00154 asm volatile ( \ 00155 "msr basepri, %0" \ 00156 : : "r"(x) : "memory", "cc"); \ 00157 }) 00158 00159 INLINE bool irq_running(void) 00160 { 00161 register uint32_t ret; 00162 00163 /* 00164 * Check if the current stack pointer is the main stack or 00165 * process stack: we use the main stack only in Handler mode, 00166 * so this means we're running inside an ISR. 00167 */ 00168 asm volatile ( 00169 "mrs %0, msp\n\t" 00170 "cmp sp, %0\n\t" 00171 "ite ne\n\t" 00172 "movne %0, #0\n\t" 00173 "moveq %0, #1\n\t" : "=r"(ret) : : "cc"); 00174 return ret; 00175 } 00176 #endif /* __IAR_SYSTEMS_ICC__ */ 00177 00178 #define IRQ_ENABLED() (CPU_READ_FLAGS() == IRQ_PRIO_ENABLED) 00179 00180 #define IRQ_RUNNING() irq_running() 00181 00182 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT) 00183 00184 #define DECLARE_ISR_CONTEXT_SWITCH(func) \ 00185 void func(void); \ 00186 INLINE void __isr_##func(void); \ 00187 void func(void) \ 00188 { \ 00189 __isr_##func(); \ 00190 if (!proc_needPreempt()) \ 00191 return; \ 00192 /* 00193 * Set a PendSV request. 00194 * 00195 * The preemption handler will be called immediately 00196 * after this ISR in tail-chaining mode (without the 00197 * overhead of hardware state saving and restoration 00198 * between interrupts). 00199 */ \ 00200 HWREG(NVIC_INT_CTRL) = NVIC_INT_CTRL_PEND_SV; \ 00201 } \ 00202 INLINE void __isr_##func(void) 00203 00214 #if CONFIG_KERN_PRI 00215 #define DECLARE_ISR(func) \ 00216 DECLARE_ISR_CONTEXT_SWITCH(func) 00217 00221 #define ISR_PROTO(func) \ 00222 ISR_PROTO_CONTEXT_SWITCH(func) 00223 #endif /* !CONFIG_KERN_PRI */ 00224 #endif 00225 00226 #ifndef ISR_PROTO 00227 #define ISR_PROTO(func) void func(void) 00228 #endif 00229 #ifndef DECLARE_ISR 00230 #define DECLARE_ISR(func) void func(void) 00231 #endif 00232 #ifndef DECLARE_ISR_CONTEXT_SWITCH 00233 #define DECLARE_ISR_CONTEXT_SWITCH(func) void func(void) 00234 #endif 00235 #ifndef ISR_PROTO_CONTEXT_SWITCH 00236 #define ISR_PROTO_CONTEXT_SWITCH(func) void func(void) 00237 #endif 00238 00239 #elif CPU_ARM 00240 00241 #ifdef __IAR_SYSTEMS_ICC__ 00242 00243 #include <inarm.h> 00244 00245 #if __CPU_MODE__ == 1 /* Thumb */ 00246 /* Use stubs */ 00247 extern cpu_flags_t get_CPSR(void); 00248 extern void set_CPSR(cpu_flags_t flags); 00249 #else 00250 #define get_CPSR __get_CPSR 00251 #define set_CPSR __set_CPSR 00252 #endif 00253 00254 #define IRQ_DISABLE __disable_interrupt() 00255 #define IRQ_ENABLE __enable_interrupt() 00256 00257 #define IRQ_SAVE_DISABLE(x) \ 00258 do { \ 00259 (x) = get_CPSR(); \ 00260 __disable_interrupt(); \ 00261 } while (0) 00262 00263 #define IRQ_RESTORE(x) \ 00264 do { \ 00265 set_CPSR(x); \ 00266 } while (0) 00267 00268 #define IRQ_ENABLED() \ 00269 ((bool)(get_CPSR() & 0xb0)) 00270 00271 #else /* !__IAR_SYSTEMS_ICC__ */ 00272 00273 #define IRQ_DISABLE \ 00274 do { \ 00275 cpu_flags_t sreg; \ 00276 asm volatile ( \ 00277 "mrs %0, cpsr\n\t" \ 00278 "orr %0, %0, #0xc0\n\t" \ 00279 "msr cpsr_c, %0\n\t" \ 00280 : "=r" (sreg) : : "memory", "cc"); \ 00281 } while (0) 00282 00283 #define IRQ_ENABLE \ 00284 do { \ 00285 cpu_flags_t sreg; \ 00286 asm volatile ( \ 00287 "mrs %0, cpsr\n\t" \ 00288 "bic %0, %0, #0xc0\n\t" \ 00289 "msr cpsr_c, %0\n\t" \ 00290 : "=r" (sreg) : : "memory", "cc"); \ 00291 } while (0) 00292 00293 #define IRQ_SAVE_DISABLE(x) \ 00294 do { \ 00295 register cpu_flags_t sreg; \ 00296 asm volatile ( \ 00297 "mrs %0, cpsr\n\t" \ 00298 "orr %1, %0, #0xc0\n\t" \ 00299 "msr cpsr_c, %1\n\t" \ 00300 : "=r" (x), "=r" (sreg) \ 00301 : : "memory", "cc"); \ 00302 } while (0) 00303 00304 #define IRQ_RESTORE(x) \ 00305 do { \ 00306 asm volatile ( \ 00307 "msr cpsr_c, %0\n\t" \ 00308 : : "r" (x) : "memory", "cc"); \ 00309 } while (0) 00310 00311 #define CPU_READ_FLAGS() \ 00312 ({ \ 00313 cpu_flags_t sreg; \ 00314 asm volatile ( \ 00315 "mrs %0, cpsr\n\t" \ 00316 : "=r" (sreg) : : "memory", "cc"); \ 00317 sreg; \ 00318 }) 00319 00320 #define IRQ_ENABLED() ((CPU_READ_FLAGS() & 0xc0) != 0xc0) 00321 00322 #define IRQ_RUNNING() ((CPU_READ_FLAGS() & 0x0F) == 0x02) 00323 00324 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT) 00325 EXTERN_C void asm_irq_switch_context(void); 00326 00333 #define IRQ_ENTRY() asm volatile ( \ 00334 "sub lr, lr, #4\n\t" \ 00335 "stmfd sp!, {r0-r3, ip, lr}\n\t") 00336 #define IRQ_EXIT() asm volatile ( \ 00337 "b asm_irq_switch_context\n\t") 00338 00348 #define ISR_FUNC __attribute__((naked)) 00349 00376 #define DECLARE_ISR_CONTEXT_SWITCH(func) \ 00377 void ISR_FUNC func(void); \ 00378 static NOINLINE void __isr_##func(void); \ 00379 void ISR_FUNC func(void) \ 00380 { \ 00381 IRQ_ENTRY(); \ 00382 IRQ_DISABLE; \ 00383 __isr_##func(); \ 00384 IRQ_EXIT(); \ 00385 } \ 00386 static NOINLINE void __isr_##func(void) 00387 00391 #define ISR_PROTO_CONTEXT_SWITCH(func) \ 00392 void ISR_FUNC func(void) 00393 00403 #if CONFIG_KERN_PRI 00404 #define DECLARE_ISR(func) \ 00405 DECLARE_ISR_CONTEXT_SWITCH(func) 00406 00407 #define ISR_PROTO(func) \ 00408 ISR_PROTO_CONTEXT_SWITCH(func) 00409 #endif /* !CONFIG_KERN_PRI */ 00410 #endif /* CONFIG_KERN_PREEMPT */ 00411 00412 #ifndef ISR_FUNC 00413 #define ISR_FUNC __attribute__((naked)) 00414 #endif 00415 #ifndef DECLARE_ISR 00416 #define DECLARE_ISR(func) \ 00417 void ISR_FUNC func(void); \ 00418 /* \ 00419 * FIXME: avoid the inlining of this function. \ 00420 * \ 00421 * This is terribly inefficient, but it's a \ 00422 * reliable workaround to avoid gcc blowing \ 00423 * away the stack (see the bug below): \ 00424 * \ 00425 * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41999 \ 00426 */ \ 00427 static NOINLINE void __isr_##func(void); \ 00428 void ISR_FUNC func(void) \ 00429 { \ 00430 asm volatile ( \ 00431 "sub lr, lr, #4\n\t" \ 00432 "stmfd sp!, {r0-r3, ip, lr}\n\t"); \ 00433 __isr_##func(); \ 00434 asm volatile ( \ 00435 "ldmfd sp!, {r0-r3, ip, pc}^\n\t"); \ 00436 } \ 00437 static NOINLINE void __isr_##func(void) 00438 #endif 00439 #ifndef DECLARE_ISR_CONTEXT_SWITCH 00440 #define DECLARE_ISR_CONTEXT_SWITCH(func) DECLARE_ISR(func) 00441 #endif 00442 #ifndef ISR_PROTO 00443 #define ISR_PROTO(func) void ISR_FUNC func(void) 00444 #endif 00445 #ifndef ISR_PROTO_CONTEXT_SWITCH 00446 #define ISR_PROTO_CONTEXT_SWITCH(func) ISR_PROTO(func) 00447 #endif 00448 00449 #endif /* !__IAR_SYSTEMS_ICC_ */ 00450 00451 #elif CPU_PPC 00452 00453 /* Get IRQ_* definitions from the hosting environment. */ 00454 #include <cfg/os.h> 00455 #if OS_EMBEDDED 00456 #define IRQ_DISABLE FIXME 00457 #define IRQ_ENABLE FIXME 00458 #define IRQ_SAVE_DISABLE(x) FIXME 00459 #define IRQ_RESTORE(x) FIXME 00460 #define IRQ_ENABLED() FIXME 00461 #endif /* OS_EMBEDDED */ 00462 00463 #elif CPU_DSP56K 00464 00465 #define IRQ_DISABLE do { asm(bfset #0x0200,SR); asm(nop); } while (0) 00466 #define IRQ_ENABLE do { asm(bfclr #0x0200,SR); asm(nop); } while (0) 00467 00468 #define IRQ_SAVE_DISABLE(x) \ 00469 do { (void)x; asm(move SR,x); asm(bfset #0x0200,SR); } while (0) 00470 #define IRQ_RESTORE(x) \ 00471 do { (void)x; asm(move x,SR); } while (0) 00472 00473 static inline bool irq_running(void) 00474 { 00475 extern void *user_sp; 00476 return !!user_sp; 00477 } 00478 #define IRQ_RUNNING() irq_running() 00479 00480 static inline bool irq_enabled(void) 00481 { 00482 uint16_t x; 00483 asm(move SR,x); 00484 return !(x & 0x0200); 00485 } 00486 #define IRQ_ENABLED() irq_enabled() 00487 00488 #elif CPU_AVR 00489 00490 #define IRQ_DISABLE asm volatile ("cli" ::) 00491 #define IRQ_ENABLE asm volatile ("sei" ::) 00492 00493 #define IRQ_SAVE_DISABLE(x) \ 00494 do { \ 00495 __asm__ __volatile__( \ 00496 "in %0,__SREG__\n\t" \ 00497 "cli" \ 00498 : "=r" (x) : /* no inputs */ : "cc" \ 00499 ); \ 00500 } while (0) 00501 00502 #define IRQ_RESTORE(x) \ 00503 do { \ 00504 __asm__ __volatile__( \ 00505 "out __SREG__,%0" : /* no outputs */ : "r" (x) : "cc" \ 00506 ); \ 00507 } while (0) 00508 00509 #define IRQ_ENABLED() \ 00510 ({ \ 00511 uint8_t sreg; \ 00512 __asm__ __volatile__( \ 00513 "in %0,__SREG__\n\t" \ 00514 : "=r" (sreg) /* no inputs & no clobbers */ \ 00515 ); \ 00516 (bool)(sreg & 0x80); \ 00517 }) 00518 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT) 00519 #define DECLARE_ISR_CONTEXT_SWITCH(vect) \ 00520 INLINE void __isr_##vect(void); \ 00521 ISR(vect) \ 00522 { \ 00523 __isr_##vect(); \ 00524 IRQ_PREEMPT_HANDLER(); \ 00525 } \ 00526 INLINE void __isr_##vect(void) 00527 00538 #if CONFIG_KERN_PRI 00539 #define DECLARE_ISR(func) \ 00540 DECLARE_ISR_CONTEXT_SWITCH(func) 00541 00545 #define ISR_PROTO(func) \ 00546 ISR_PROTO_CONTEXT_SWITCH(func) 00547 #endif /* !CONFIG_KERN_PRI */ 00548 #endif 00549 00550 #ifndef ISR_PROTO 00551 #define ISR_PROTO(vect) ISR(vect) 00552 #endif 00553 #ifndef DECLARE_ISR 00554 #define DECLARE_ISR(vect) ISR(vect) 00555 #endif 00556 #ifndef DECLARE_ISR_CONTEXT_SWITCH 00557 #define DECLARE_ISR_CONTEXT_SWITCH(vect) ISR(vect) 00558 #endif 00559 #ifndef ISR_PROTO_CONTEXT_SWITCH 00560 #define ISR_PROTO_CONTEXT_SWITCH(vect) ISR(vect) 00561 #endif 00562 00563 #elif CPU_MSP430 00564 00565 /* Get the compiler defined macros */ 00566 #include <signal.h> 00567 #define IRQ_DISABLE dint() 00568 #define IRQ_ENABLE eint() 00569 00570 #else 00571 #error No CPU_... defined. 00572 #endif 00573 00574 #ifdef IRQ_RUNNING 00575 00576 #define ASSERT_IRQ_CONTEXT() ASSERT(IRQ_RUNNING()) 00577 00579 #define ASSERT_USER_CONTEXT() ASSERT(!IRQ_RUNNING()) 00580 #else 00581 #define IRQ_RUNNING() false 00582 #define ASSERT_USER_CONTEXT() do {} while(0) 00583 #define ASSERT_IRQ_CONTEXT() do {} while(0) 00584 #endif 00585 00586 #ifdef IRQ_ENABLED 00587 00588 #define IRQ_ASSERT_ENABLED() ASSERT(IRQ_ENABLED()) 00589 00591 #define IRQ_ASSERT_DISABLED() ASSERT(!IRQ_ENABLED()) 00592 #else 00593 #define IRQ_ASSERT_ENABLED() do {} while(0) 00594 #define IRQ_ASSERT_DISABLED() do {} while(0) 00595 #endif 00596 00597 00598 #ifndef IRQ_PREEMPT_HANDLER 00599 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT) 00600 00603 INLINE void IRQ_PREEMPT_HANDLER(void) 00604 { 00605 if (proc_needPreempt()) 00606 proc_preempt(); 00607 } 00608 #else 00609 #define IRQ_PREEMPT_HANDLER() /* Nothing */ 00610 #endif 00611 #endif 00612 00618 #define ATOMIC(CODE) \ 00619 do { \ 00620 cpu_flags_t __flags; \ 00621 IRQ_SAVE_DISABLE(__flags); \ 00622 CODE; \ 00623 IRQ_RESTORE(__flags); \ 00624 } while (0) 00625 00626 #endif /* CPU_IRQ_H */
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)