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 #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
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
00165
00166
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
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
00194
00195
00196
00197
00198
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
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
00246
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
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 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT)
00323 EXTERN_C void asm_irq_switch_context(void);
00324
00331 #define IRQ_ENTRY() asm volatile ( \
00332 "sub lr, lr, #4\n\t" \
00333 "stmfd sp!, {r0-r3, ip, lr}\n\t")
00334 #define IRQ_EXIT() asm volatile ( \
00335 "b asm_irq_switch_context\n\t")
00336
00346 #define ISR_FUNC __attribute__((naked))
00347
00374 #define DECLARE_ISR_CONTEXT_SWITCH(func) \
00375 void ISR_FUNC func(void); \
00376 static NOINLINE void __isr_##func(void); \
00377 void ISR_FUNC func(void) \
00378 { \
00379 IRQ_ENTRY(); \
00380 IRQ_DISABLE; \
00381 __isr_##func(); \
00382 IRQ_EXIT(); \
00383 } \
00384 static NOINLINE void __isr_##func(void)
00385
00389 #define ISR_PROTO_CONTEXT_SWITCH(func) \
00390 void ISR_FUNC func(void)
00391
00401 #if CONFIG_KERN_PRI
00402 #define DECLARE_ISR(func) \
00403 DECLARE_ISR_CONTEXT_SWITCH(func)
00404
00405 #define ISR_PROTO(func) \
00406 ISR_PROTO_CONTEXT_SWITCH(func)
00407 #endif
00408 #endif
00409
00410 #ifndef ISR_FUNC
00411 #define ISR_FUNC __attribute__((naked))
00412 #endif
00413 #ifndef DECLARE_ISR
00414 #define DECLARE_ISR(func) \
00415 void ISR_FUNC func(void); \
00416
00417
00418
00419
00420
00421
00422
00423
00424 \
00425 static NOINLINE void __isr_##func(void); \
00426 void ISR_FUNC func(void) \
00427 { \
00428 asm volatile ( \
00429 "sub lr, lr, #4\n\t" \
00430 "stmfd sp!, {r0-r3, ip, lr}\n\t"); \
00431 __isr_##func(); \
00432 asm volatile ( \
00433 "ldmfd sp!, {r0-r3, ip, pc}^\n\t"); \
00434 } \
00435 static NOINLINE void __isr_##func(void)
00436 #endif
00437 #ifndef DECLARE_ISR_CONTEXT_SWITCH
00438 #define DECLARE_ISR_CONTEXT_SWITCH(func) DECLARE_ISR(func)
00439 #endif
00440 #ifndef ISR_PROTO
00441 #define ISR_PROTO(func) void ISR_FUNC func(void)
00442 #endif
00443 #ifndef ISR_PROTO_CONTEXT_SWITCH
00444 #define ISR_PROTO_CONTEXT_SWITCH(func) ISR_PROTO(func)
00445 #endif
00446
00447 #endif
00448
00449 #elif CPU_PPC
00450
00451
00452 #include <cfg/os.h>
00453 #if OS_EMBEDDED
00454 #define IRQ_DISABLE FIXME
00455 #define IRQ_ENABLE FIXME
00456 #define IRQ_SAVE_DISABLE(x) FIXME
00457 #define IRQ_RESTORE(x) FIXME
00458 #define IRQ_ENABLED() FIXME
00459 #endif
00460
00461 #elif CPU_DSP56K
00462
00463 #define IRQ_DISABLE do { asm(bfset #0x0200,SR); asm(nop); } while (0)
00464 #define IRQ_ENABLE do { asm(bfclr #0x0200,SR); asm(nop); } while (0)
00465
00466 #define IRQ_SAVE_DISABLE(x) \
00467 do { (void)x; asm(move SR,x); asm(bfset #0x0200,SR); } while (0)
00468 #define IRQ_RESTORE(x) \
00469 do { (void)x; asm(move x,SR); } while (0)
00470
00471 static inline bool irq_running(void)
00472 {
00473 extern void *user_sp;
00474 return !!user_sp;
00475 }
00476 #define IRQ_RUNNING() irq_running()
00477
00478 static inline bool irq_enabled(void)
00479 {
00480 uint16_t x;
00481 asm(move SR,x);
00482 return !(x & 0x0200);
00483 }
00484 #define IRQ_ENABLED() irq_enabled()
00485
00486 #elif CPU_AVR
00487
00488 #define IRQ_DISABLE asm volatile ("cli" ::)
00489 #define IRQ_ENABLE asm volatile ("sei" ::)
00490
00491 #define IRQ_SAVE_DISABLE(x) \
00492 do { \
00493 __asm__ __volatile__( \
00494 "in %0,__SREG__\n\t" \
00495 "cli" \
00496 : "=r" (x) : : "cc" \
00497 ); \
00498 } while (0)
00499
00500 #define IRQ_RESTORE(x) \
00501 do { \
00502 __asm__ __volatile__( \
00503 "out __SREG__,%0" : : "r" (x) : "cc" \
00504 ); \
00505 } while (0)
00506
00507 #define IRQ_ENABLED() \
00508 ({ \
00509 uint8_t sreg; \
00510 __asm__ __volatile__( \
00511 "in %0,__SREG__\n\t" \
00512 : "=r" (sreg) \
00513 ); \
00514 (bool)(sreg & 0x80); \
00515 })
00516 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT)
00517 #define DECLARE_ISR_CONTEXT_SWITCH(vect) \
00518 INLINE void __isr_##vect(void); \
00519 ISR(vect) \
00520 { \
00521 __isr_##vect(); \
00522 IRQ_PREEMPT_HANDLER(); \
00523 } \
00524 INLINE void __isr_##vect(void)
00525
00536 #if CONFIG_KERN_PRI
00537 #define DECLARE_ISR(func) \
00538 DECLARE_ISR_CONTEXT_SWITCH(func)
00539
00543 #define ISR_PROTO(func) \
00544 ISR_PROTO_CONTEXT_SWITCH(func)
00545 #endif
00546 #endif
00547
00548 #ifndef ISR_PROTO
00549 #define ISR_PROTO(vect) ISR(vect)
00550 #endif
00551 #ifndef DECLARE_ISR
00552 #define DECLARE_ISR(vect) ISR(vect)
00553 #endif
00554 #ifndef DECLARE_ISR_CONTEXT_SWITCH
00555 #define DECLARE_ISR_CONTEXT_SWITCH(vect) ISR(vect)
00556 #endif
00557 #ifndef ISR_PROTO_CONTEXT_SWITCH
00558 #define ISR_PROTO_CONTEXT_SWITCH(vect) ISR(vect)
00559 #endif
00560
00561 #elif CPU_MSP430
00562
00563
00564 #include <signal.h>
00565 #define IRQ_DISABLE dint()
00566 #define IRQ_ENABLE eint()
00567
00568 #else
00569 #error No CPU_... defined.
00570 #endif
00571
00572 #ifdef IRQ_RUNNING
00573
00574 #define ASSERT_IRQ_CONTEXT() ASSERT(IRQ_RUNNING())
00575
00577 #define ASSERT_USER_CONTEXT() ASSERT(!IRQ_RUNNING())
00578 #else
00579 #define IRQ_RUNNING() false
00580 #define ASSERT_USER_CONTEXT() do {} while(0)
00581 #define ASSERT_IRQ_CONTEXT() do {} while(0)
00582 #endif
00583
00584 #ifdef IRQ_ENABLED
00585
00586 #define IRQ_ASSERT_ENABLED() ASSERT(IRQ_ENABLED())
00587
00589 #define IRQ_ASSERT_DISABLED() ASSERT(!IRQ_ENABLED())
00590 #else
00591 #define IRQ_ASSERT_ENABLED() do {} while(0)
00592 #define IRQ_ASSERT_DISABLED() do {} while(0)
00593 #endif
00594
00595
00596 #ifndef IRQ_PREEMPT_HANDLER
00597 #if (CONFIG_KERN && CONFIG_KERN_PREEMPT)
00598
00601 INLINE void IRQ_PREEMPT_HANDLER(void)
00602 {
00603 if (proc_needPreempt())
00604 proc_preempt();
00605 }
00606 #else
00607 #define IRQ_PREEMPT_HANDLER()
00608 #endif
00609 #endif
00610
00616 #define ATOMIC(CODE) \
00617 do { \
00618 cpu_flags_t __flags; \
00619 IRQ_SAVE_DISABLE(__flags); \
00620 CODE; \
00621 IRQ_RESTORE(__flags); \
00622 } while (0)
00623
00624 #endif