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 
00067 #elif CPU_ARM
00068 
00069     #ifdef __IAR_SYSTEMS_ICC__
00070 
00071         #include <inarm.h>
00072 
00073         #if __CPU_MODE__ == 1 /* Thumb */
00074             /* Use stubs */
00075             extern cpu_flags_t get_CPSR(void);
00076             extern void set_CPSR(cpu_flags_t flags);
00077         #else
00078             #define get_CPSR __get_CPSR
00079             #define set_CPSR __set_CPSR
00080         #endif
00081 
00082         #define IRQ_DISABLE __disable_interrupt()
00083         #define IRQ_ENABLE  __enable_interrupt()
00084 
00085         #define IRQ_SAVE_DISABLE(x) \
00086         do { \
00087             (x) = get_CPSR(); \
00088             __disable_interrupt(); \
00089         } while (0)
00090 
00091         #define IRQ_RESTORE(x) \
00092         do { \
00093             set_CPSR(x); \
00094         } while (0)
00095 
00096         #define IRQ_ENABLED() \
00097             ((bool)(get_CPSR() & 0xb0))
00098 
00099     #else /* !__IAR_SYSTEMS_ICC__ */
00100 
00101         #define IRQ_DISABLE \
00102         do { \
00103             asm volatile ( \
00104                 "mrs r0, cpsr\n\t" \
00105                 "orr r0, r0, #0xc0\n\t" \
00106                 "msr cpsr_c, r0" \
00107                 ::: "r0" \
00108             ); \
00109         } while (0)
00110 
00111         #define IRQ_ENABLE \
00112         do { \
00113             asm volatile ( \
00114                 "mrs r0, cpsr\n\t" \
00115                 "bic r0, r0, #0xc0\n\t" \
00116                 "msr cpsr_c, r0" \
00117                 ::: "r0" \
00118             ); \
00119         } while (0)
00120 
00121         #define IRQ_SAVE_DISABLE(x) \
00122         do { \
00123             asm volatile ( \
00124                 "mrs %0, cpsr\n\t" \
00125                 "orr r0, %0, #0xc0\n\t" \
00126                 "msr cpsr_c, r0" \
00127                 : "=r" (x) \
00128                 : /* no inputs */ \
00129                 : "r0" \
00130             ); \
00131         } while (0)
00132 
00133         #define IRQ_RESTORE(x) \
00134         do { \
00135             asm volatile ( \
00136                 "msr cpsr_c, %0" \
00137                 : /* no outputs */ \
00138                 : "r" (x) \
00139             ); \
00140         } while (0)
00141 
00142         #define CPU_READ_FLAGS() \
00143         ({ \
00144             cpu_flags_t sreg; \
00145             asm volatile ( \
00146                 "mrs %0, cpsr\n\t" \
00147                 : "=r" (sreg) \
00148                 : /* no inputs */ \
00149             ); \
00150             sreg; \
00151         })
00152 
00153         #define IRQ_ENABLED() ((CPU_READ_FLAGS() & 0xc0) != 0xc0)
00154 
00155         #if CONFIG_KERN_PREEMPT
00156             EXTERN_C void asm_irq_switch_context(void);
00157 
00164             #define IRQ_ENTRY() asm volatile ( \
00165                         "sub    lr, lr, #4\n\t" \
00166                         "stmfd  sp!, {r0-r3, ip, lr}\n\t")
00167             #define IRQ_EXIT()  asm volatile ( \
00168                         "b  asm_irq_switch_context\n\t")
00169 
00179             #define ISR_FUNC __attribute__((naked))
00180 
00207             #define DECLARE_ISR_CONTEXT_SWITCH(func)    \
00208                 void ISR_FUNC func(void);       \
00209                 static void __isr_##func(void);     \
00210                 void ISR_FUNC func(void)        \
00211                 {                   \
00212                     IRQ_ENTRY();            \
00213                     IRQ_DISABLE;            \
00214                     __isr_##func();         \
00215                     IRQ_EXIT();         \
00216                 }                   \
00217                 static void __isr_##func(void)
00218 
00222             #define ISR_PROTO_CONTEXT_SWITCH(func)  \
00223                 void ISR_FUNC func(void)
00224 
00234             #if CONFIG_KERN_PRI
00235                 #define DECLARE_ISR(func) \
00236                     DECLARE_ISR_CONTEXT_SWITCH(func)
00237 
00238                 #define ISR_PROTO(func) \
00239                     ISR_PROTO_CONTEXT_SWITCH(func)
00240             #endif /* !CONFIG_KERN_PRI */
00241         #endif /* CONFIG_KERN_PREEMPT */
00242 
00243         #ifndef DECLARE_ISR
00244             #define DECLARE_ISR(func) \
00245                 void __attribute__((interrupt)) func(void)
00246         #endif
00247         #ifndef DECLARE_ISR_CONTEXT_SWITCH
00248             #define DECLARE_ISR_CONTEXT_SWITCH(func) \
00249                 void __attribute__((interrupt)) func(void)
00250         #endif
00251         #ifndef ISR_PROTO
00252             #define ISR_PROTO(func) \
00253                 void __attribute__((interrupt)) func(void)
00254         #endif
00255         #ifndef ISR_PROTO_CONTEXT_SWITCH
00256             #define ISR_PROTO_CONTEXT_SWITCH(func)  \
00257                 void __attribute__((interrupt)) func(void)
00258         #endif
00259 
00260     #endif /* !__IAR_SYSTEMS_ICC_ */
00261 
00262 #elif CPU_PPC
00263 
00264     /* Get IRQ_* definitions from the hosting environment. */
00265     #include <cfg/os.h>
00266     #if OS_EMBEDDED
00267         #define IRQ_DISABLE         FIXME
00268         #define IRQ_ENABLE          FIXME
00269         #define IRQ_SAVE_DISABLE(x) FIXME
00270         #define IRQ_RESTORE(x)      FIXME
00271         #define IRQ_ENABLED()       FIXME
00272     #endif /* OS_EMBEDDED */
00273 
00274 #elif CPU_DSP56K
00275 
00276     #define IRQ_DISABLE             do { asm(bfset #0x0200,SR); asm(nop); } while (0)
00277     #define IRQ_ENABLE              do { asm(bfclr #0x0200,SR); asm(nop); } while (0)
00278 
00279     #define IRQ_SAVE_DISABLE(x)  \
00280         do { (void)x; asm(move SR,x); asm(bfset #0x0200,SR); } while (0)
00281     #define IRQ_RESTORE(x)  \
00282         do { (void)x; asm(move x,SR); } while (0)
00283 
00284     static inline bool irq_running(void)
00285     {
00286         extern void *user_sp;
00287         return !!user_sp;
00288     }
00289     #define IRQ_RUNNING() irq_running()
00290 
00291     static inline bool irq_enabled(void)
00292     {
00293         uint16_t x;
00294         asm(move SR,x);
00295         return !(x & 0x0200);
00296     }
00297     #define IRQ_ENABLED() irq_enabled()
00298 
00299 #elif CPU_AVR
00300 
00301     #define IRQ_DISABLE   asm volatile ("cli" ::)
00302     #define IRQ_ENABLE    asm volatile ("sei" ::)
00303 
00304     #define IRQ_SAVE_DISABLE(x) \
00305     do { \
00306         __asm__ __volatile__( \
00307             "in %0,__SREG__\n\t" \
00308             "cli" \
00309             : "=r" (x) : /* no inputs */ : "cc" \
00310         ); \
00311     } while (0)
00312 
00313     #define IRQ_RESTORE(x) \
00314     do { \
00315         __asm__ __volatile__( \
00316             "out __SREG__,%0" : /* no outputs */ : "r" (x) : "cc" \
00317         ); \
00318     } while (0)
00319 
00320     #define IRQ_ENABLED() \
00321     ({ \
00322         uint8_t sreg; \
00323         __asm__ __volatile__( \
00324             "in %0,__SREG__\n\t" \
00325             : "=r" (sreg)  /* no inputs & no clobbers */ \
00326         ); \
00327         (bool)(sreg & 0x80); \
00328     })
00329     #if CONFIG_KERN_PREEMPT
00330         #define DECLARE_ISR_CONTEXT_SWITCH(vect)        \
00331             INLINE void __isr_##vect(void);         \
00332             ISR(vect)                   \
00333             {                       \
00334                 __isr_##vect();             \
00335                 IRQ_PREEMPT_HANDLER();          \
00336             }                       \
00337             INLINE void __isr_##vect(void)
00338 
00349         #if CONFIG_KERN_PRI
00350             #define DECLARE_ISR(func) \
00351                 DECLARE_ISR_CONTEXT_SWITCH(func)
00352 
00356             #define ISR_PROTO(func) \
00357                 ISR_PROTO_CONTEXT_SWITCH(func)
00358         #endif /* !CONFIG_KERN_PRI */
00359     #endif
00360 
00361     #ifndef ISR_PROTO
00362         #define ISR_PROTO(vect) ISR(vect)
00363     #endif
00364     #ifndef DECLARE_ISR
00365         #define DECLARE_ISR(vect) ISR(vect)
00366     #endif
00367     #ifndef DECLARE_ISR_CONTEXT_SWITCH
00368         #define DECLARE_ISR_CONTEXT_SWITCH(vect) ISR(vect)
00369     #endif
00370     #ifndef ISR_PROTO_CONTEXT_SWITCH
00371         #define ISR_PROTO_CONTEXT_SWITCH(func) ISR(vect)
00372     #endif
00373 
00374 #else
00375     #error No CPU_... defined.
00376 #endif
00377 
00378 #ifdef IRQ_RUNNING
00380     #define ASSERT_IRQ_CONTEXT()  ASSERT(IRQ_RUNNING())
00381 
00383     #define ASSERT_USER_CONTEXT() ASSERT(!IRQ_RUNNING())
00384 #else
00385     #define ASSERT_USER_CONTEXT()  do {} while(0)
00386     #define ASSERT_IRQ_CONTEXT()   do {} while(0)
00387 #endif
00388 
00389 #ifdef IRQ_ENABLED
00391     #define IRQ_ASSERT_ENABLED()  ASSERT(IRQ_ENABLED())
00392 
00394     #define IRQ_ASSERT_DISABLED() ASSERT(!IRQ_ENABLED())
00395 #else
00396     #define IRQ_ASSERT_ENABLED() do {} while(0)
00397     #define IRQ_ASSERT_DISABLED() do {} while(0)
00398 #endif
00399 
00400 
00401 #ifndef IRQ_PREEMPT_HANDLER
00402     #if CONFIG_KERN_PREEMPT
00403 
00406         INLINE void IRQ_PREEMPT_HANDLER(void)
00407         {
00408             if (proc_needPreempt())
00409                 proc_preempt();
00410         }
00411     #else
00412         #define IRQ_PREEMPT_HANDLER() /* Nothing */
00413     #endif
00414 #endif
00415 
00421 #define ATOMIC(CODE) \
00422     do { \
00423         cpu_flags_t __flags; \
00424         IRQ_SAVE_DISABLE(__flags); \
00425         CODE; \
00426         IRQ_RESTORE(__flags); \
00427     } while (0)
00428 
00429 #endif /* CPU_IRQ_H */