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>
00048
00049 #include <cfg/compiler.h>
00050 #include "cfg/cfg_proc.h"
00051
00052 #if CPU_I196
00053 #define IRQ_DISABLE disable_interrupt()
00054 #define IRQ_ENABLE enable_interrupt()
00055 #elif CPU_X86
00056
00057
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
00065
00066 #elif CPU_CM3
00067
00068
00069
00070
00071
00072
00073
00074
00075 #define IRQ_PRIO 0x80
00076 #define IRQ_PRIO_MIN 0xf0
00077 #define IRQ_PRIO_MAX 0
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #define IRQ_PRIO_DISABLED 0x40
00090 #define IRQ_PRIO_ENABLED 0
00091
00092 #define IRQ_DISABLE \
00093 ({ \
00094 register cpu_flags_t reg = IRQ_PRIO_DISABLED; \
00095 asm volatile ( \
00096 "msr basepri, %0" \
00097 : : "r"(reg) : "memory", "cc"); \
00098 })
00099
00100 #define IRQ_ENABLE \
00101 ({ \
00102 register cpu_flags_t reg = IRQ_PRIO_ENABLED; \
00103 asm volatile ( \
00104 "msr basepri, %0" \
00105 : : "r"(reg) : "memory", "cc"); \
00106 })
00107
00108 #define CPU_READ_FLAGS() \
00109 ({ \
00110 register cpu_flags_t reg; \
00111 asm volatile ( \
00112 "mrs %0, basepri" \
00113 : "=r"(reg) : : "memory", "cc"); \
00114 reg; \
00115 })
00116
00117 #define IRQ_SAVE_DISABLE(x) \
00118 ({ \
00119 x = CPU_READ_FLAGS(); \
00120 IRQ_DISABLE; \
00121 })
00122
00123 #define IRQ_RESTORE(x) \
00124 ({ \
00125 asm volatile ( \
00126 "msr basepri, %0" \
00127 : : "r"(x) : "memory", "cc"); \
00128 })
00129
00130 #define IRQ_ENABLED() (CPU_READ_FLAGS() == IRQ_PRIO_ENABLED)
00131
00132 INLINE bool irq_running(void)
00133 {
00134 register uint32_t ret;
00135
00136
00137
00138
00139
00140
00141 asm volatile (
00142 "mrs %0, msp\n\t"
00143 "cmp sp, %0\n\t"
00144 "ite ne\n\t"
00145 "movne %0, #0\n\t"
00146 "moveq %0, #1\n\t" : "=r"(ret) : : "cc");
00147 return ret;
00148 }
00149 #define IRQ_RUNNING() irq_running()
00150
00151 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT)
00152
00153 #define DECLARE_ISR_CONTEXT_SWITCH(func) \
00154 void func(void); \
00155 INLINE void __isr_##func(void); \
00156 void func(void) \
00157 { \
00158 __isr_##func(); \
00159 if (!proc_needPreempt()) \
00160 return; \
00161
00162
00163
00164
00165
00166
00167
00168 \
00169 HWREG(NVIC_INT_CTRL) = NVIC_INT_CTRL_PEND_SV; \
00170 } \
00171 INLINE void __isr_##func(void)
00172
00183 #if CONFIG_KERN_PRI
00184 #define DECLARE_ISR(func) \
00185 DECLARE_ISR_CONTEXT_SWITCH(func)
00186
00190 #define ISR_PROTO(func) \
00191 ISR_PROTO_CONTEXT_SWITCH(func)
00192 #endif
00193 #endif
00194
00195 #ifndef ISR_PROTO
00196 #define ISR_PROTO(func) void func(void)
00197 #endif
00198 #ifndef DECLARE_ISR
00199 #define DECLARE_ISR(func) void func(void)
00200 #endif
00201 #ifndef DECLARE_ISR_CONTEXT_SWITCH
00202 #define DECLARE_ISR_CONTEXT_SWITCH(func) void func(void)
00203 #endif
00204 #ifndef ISR_PROTO_CONTEXT_SWITCH
00205 #define ISR_PROTO_CONTEXT_SWITCH(func) void func(void)
00206 #endif
00207
00208 #elif CPU_ARM
00209
00210 #ifdef __IAR_SYSTEMS_ICC__
00211
00212 #include <inarm.h>
00213
00214 #if __CPU_MODE__ == 1
00215
00216 extern cpu_flags_t get_CPSR(void);
00217 extern void set_CPSR(cpu_flags_t flags);
00218 #else
00219 #define get_CPSR __get_CPSR
00220 #define set_CPSR __set_CPSR
00221 #endif
00222
00223 #define IRQ_DISABLE __disable_interrupt()
00224 #define IRQ_ENABLE __enable_interrupt()
00225
00226 #define IRQ_SAVE_DISABLE(x) \
00227 do { \
00228 (x) = get_CPSR(); \
00229 __disable_interrupt(); \
00230 } while (0)
00231
00232 #define IRQ_RESTORE(x) \
00233 do { \
00234 set_CPSR(x); \
00235 } while (0)
00236
00237 #define IRQ_ENABLED() \
00238 ((bool)(get_CPSR() & 0xb0))
00239
00240 #else
00241
00242 #define IRQ_DISABLE \
00243 do { \
00244 cpu_flags_t sreg; \
00245 asm volatile ( \
00246 "mrs %0, cpsr\n\t" \
00247 "orr %0, %0, #0xc0\n\t" \
00248 "msr cpsr_c, %0\n\t" \
00249 : "=r" (sreg) : : "memory", "cc"); \
00250 } while (0)
00251
00252 #define IRQ_ENABLE \
00253 do { \
00254 cpu_flags_t sreg; \
00255 asm volatile ( \
00256 "mrs %0, cpsr\n\t" \
00257 "bic %0, %0, #0xc0\n\t" \
00258 "msr cpsr_c, %0\n\t" \
00259 : "=r" (sreg) : : "memory", "cc"); \
00260 } while (0)
00261
00262 #define IRQ_SAVE_DISABLE(x) \
00263 do { \
00264 register cpu_flags_t sreg; \
00265 asm volatile ( \
00266 "mrs %0, cpsr\n\t" \
00267 "orr %1, %0, #0xc0\n\t" \
00268 "msr cpsr_c, %1\n\t" \
00269 : "=r" (x), "=r" (sreg) \
00270 : : "memory", "cc"); \
00271 } while (0)
00272
00273 #define IRQ_RESTORE(x) \
00274 do { \
00275 asm volatile ( \
00276 "msr cpsr_c, %0\n\t" \
00277 : : "r" (x) : "memory", "cc"); \
00278 } while (0)
00279
00280 #define CPU_READ_FLAGS() \
00281 ({ \
00282 cpu_flags_t sreg; \
00283 asm volatile ( \
00284 "mrs %0, cpsr\n\t" \
00285 : "=r" (sreg) : : "memory", "cc"); \
00286 sreg; \
00287 })
00288
00289 #define IRQ_ENABLED() ((CPU_READ_FLAGS() & 0xc0) != 0xc0)
00290
00291 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT)
00292 EXTERN_C void asm_irq_switch_context(void);
00293
00300 #define IRQ_ENTRY() asm volatile ( \
00301 "sub lr, lr, #4\n\t" \
00302 "stmfd sp!, {r0-r3, ip, lr}\n\t")
00303 #define IRQ_EXIT() asm volatile ( \
00304 "b asm_irq_switch_context\n\t")
00305
00315 #define ISR_FUNC __attribute__((naked))
00316
00343 #define DECLARE_ISR_CONTEXT_SWITCH(func) \
00344 void ISR_FUNC func(void); \
00345 static NOINLINE void __isr_##func(void); \
00346 void ISR_FUNC func(void) \
00347 { \
00348 IRQ_ENTRY(); \
00349 IRQ_DISABLE; \
00350 __isr_##func(); \
00351 IRQ_EXIT(); \
00352 } \
00353 static NOINLINE void __isr_##func(void)
00354
00358 #define ISR_PROTO_CONTEXT_SWITCH(func) \
00359 void ISR_FUNC func(void)
00360
00370 #if CONFIG_KERN_PRI
00371 #define DECLARE_ISR(func) \
00372 DECLARE_ISR_CONTEXT_SWITCH(func)
00373
00374 #define ISR_PROTO(func) \
00375 ISR_PROTO_CONTEXT_SWITCH(func)
00376 #endif
00377 #endif
00378
00379 #ifndef ISR_FUNC
00380 #define ISR_FUNC __attribute__((naked))
00381 #endif
00382 #ifndef DECLARE_ISR
00383 #define DECLARE_ISR(func) \
00384 void ISR_FUNC func(void); \
00385
00386
00387
00388
00389
00390
00391
00392
00393 \
00394 static NOINLINE void __isr_##func(void); \
00395 void ISR_FUNC func(void) \
00396 { \
00397 asm volatile ( \
00398 "sub lr, lr, #4\n\t" \
00399 "stmfd sp!, {r0-r3, ip, lr}\n\t"); \
00400 __isr_##func(); \
00401 asm volatile ( \
00402 "ldmfd sp!, {r0-r3, ip, pc}^\n\t"); \
00403 } \
00404 static NOINLINE void __isr_##func(void)
00405 #endif
00406 #ifndef DECLARE_ISR_CONTEXT_SWITCH
00407 #define DECLARE_ISR_CONTEXT_SWITCH(func) DECLARE_ISR(func)
00408 #endif
00409 #ifndef ISR_PROTO
00410 #define ISR_PROTO(func) void ISR_FUNC func(void)
00411 #endif
00412 #ifndef ISR_PROTO_CONTEXT_SWITCH
00413 #define ISR_PROTO_CONTEXT_SWITCH(func) ISR_PROTO(func)
00414 #endif
00415
00416 #endif
00417
00418 #elif CPU_PPC
00419
00420
00421 #include <cfg/os.h>
00422 #if OS_EMBEDDED
00423 #define IRQ_DISABLE FIXME
00424 #define IRQ_ENABLE FIXME
00425 #define IRQ_SAVE_DISABLE(x) FIXME
00426 #define IRQ_RESTORE(x) FIXME
00427 #define IRQ_ENABLED() FIXME
00428 #endif
00429
00430 #elif CPU_DSP56K
00431
00432 #define IRQ_DISABLE do { asm(bfset #0x0200,SR); asm(nop); } while (0)
00433 #define IRQ_ENABLE do { asm(bfclr #0x0200,SR); asm(nop); } while (0)
00434
00435 #define IRQ_SAVE_DISABLE(x) \
00436 do { (void)x; asm(move SR,x); asm(bfset #0x0200,SR); } while (0)
00437 #define IRQ_RESTORE(x) \
00438 do { (void)x; asm(move x,SR); } while (0)
00439
00440 static inline bool irq_running(void)
00441 {
00442 extern void *user_sp;
00443 return !!user_sp;
00444 }
00445 #define IRQ_RUNNING() irq_running()
00446
00447 static inline bool irq_enabled(void)
00448 {
00449 uint16_t x;
00450 asm(move SR,x);
00451 return !(x & 0x0200);
00452 }
00453 #define IRQ_ENABLED() irq_enabled()
00454
00455 #elif CPU_AVR
00456
00457 #define IRQ_DISABLE asm volatile ("cli" ::)
00458 #define IRQ_ENABLE asm volatile ("sei" ::)
00459
00460 #define IRQ_SAVE_DISABLE(x) \
00461 do { \
00462 __asm__ __volatile__( \
00463 "in %0,__SREG__\n\t" \
00464 "cli" \
00465 : "=r" (x) : : "cc" \
00466 ); \
00467 } while (0)
00468
00469 #define IRQ_RESTORE(x) \
00470 do { \
00471 __asm__ __volatile__( \
00472 "out __SREG__,%0" : : "r" (x) : "cc" \
00473 ); \
00474 } while (0)
00475
00476 #define IRQ_ENABLED() \
00477 ({ \
00478 uint8_t sreg; \
00479 __asm__ __volatile__( \
00480 "in %0,__SREG__\n\t" \
00481 : "=r" (sreg) \
00482 ); \
00483 (bool)(sreg & 0x80); \
00484 })
00485 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT)
00486 #define DECLARE_ISR_CONTEXT_SWITCH(vect) \
00487 INLINE void __isr_##vect(void); \
00488 ISR(vect) \
00489 { \
00490 __isr_##vect(); \
00491 IRQ_PREEMPT_HANDLER(); \
00492 } \
00493 INLINE void __isr_##vect(void)
00494
00505 #if CONFIG_KERN_PRI
00506 #define DECLARE_ISR(func) \
00507 DECLARE_ISR_CONTEXT_SWITCH(func)
00508
00512 #define ISR_PROTO(func) \
00513 ISR_PROTO_CONTEXT_SWITCH(func)
00514 #endif
00515 #endif
00516
00517 #ifndef ISR_PROTO
00518 #define ISR_PROTO(vect) ISR(vect)
00519 #endif
00520 #ifndef DECLARE_ISR
00521 #define DECLARE_ISR(vect) ISR(vect)
00522 #endif
00523 #ifndef DECLARE_ISR_CONTEXT_SWITCH
00524 #define DECLARE_ISR_CONTEXT_SWITCH(vect) ISR(vect)
00525 #endif
00526 #ifndef ISR_PROTO_CONTEXT_SWITCH
00527 #define ISR_PROTO_CONTEXT_SWITCH(vect) ISR(vect)
00528 #endif
00529
00530 #else
00531 #error No CPU_... defined.
00532 #endif
00533
00534 #ifdef IRQ_RUNNING
00535
00536 #define ASSERT_IRQ_CONTEXT() ASSERT(IRQ_RUNNING())
00537
00539 #define ASSERT_USER_CONTEXT() ASSERT(!IRQ_RUNNING())
00540 #else
00541 #define IRQ_RUNNING() false
00542 #define ASSERT_USER_CONTEXT() do {} while(0)
00543 #define ASSERT_IRQ_CONTEXT() do {} while(0)
00544 #endif
00545
00546 #ifdef IRQ_ENABLED
00547
00548 #define IRQ_ASSERT_ENABLED() ASSERT(IRQ_ENABLED())
00549
00551 #define IRQ_ASSERT_DISABLED() ASSERT(!IRQ_ENABLED())
00552 #else
00553 #define IRQ_ASSERT_ENABLED() do {} while(0)
00554 #define IRQ_ASSERT_DISABLED() do {} while(0)
00555 #endif
00556
00557
00558 #ifndef IRQ_PREEMPT_HANDLER
00559 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT)
00560
00563 INLINE void IRQ_PREEMPT_HANDLER(void)
00564 {
00565 if (proc_needPreempt())
00566 proc_preempt();
00567 }
00568 #else
00569 #define IRQ_PREEMPT_HANDLER()
00570 #endif
00571 #endif
00572
00578 #define ATOMIC(CODE) \
00579 do { \
00580 cpu_flags_t __flags; \
00581 IRQ_SAVE_DISABLE(__flags); \
00582 CODE; \
00583 IRQ_RESTORE(__flags); \
00584 } while (0)
00585
00586 #endif