diff options
author | Dean Camera <dean@fourwalledcubicle.com> | 2011-04-08 05:40:25 +0000 |
---|---|---|
committer | Dean Camera <dean@fourwalledcubicle.com> | 2011-04-08 05:40:25 +0000 |
commit | c263ea837ae7e3c0e963b798afdffd501790ce2c (patch) | |
tree | a899d943856b48f6889cf1fe9f5b97ccc58ca598 /LUFA/Common | |
parent | de9bd767dc8578a45a195fb1e37dd4ff26ae9567 (diff) | |
download | lufa-c263ea837ae7e3c0e963b798afdffd501790ce2c.tar.gz lufa-c263ea837ae7e3c0e963b798afdffd501790ce2c.tar.bz2 lufa-c263ea837ae7e3c0e963b798afdffd501790ce2c.zip |
Move global interrupt enable/disable functions out to Common.h and document them.
Diffstat (limited to 'LUFA/Common')
-rw-r--r-- | LUFA/Common/Common.h | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/LUFA/Common/Common.h b/LUFA/Common/Common.h index a54512a51..4e697ad18 100644 --- a/LUFA/Common/Common.h +++ b/LUFA/Common/Common.h @@ -97,7 +97,7 @@ typedef uint32_t uint_reg_t; - #define ARCH_BIG_ENDIAN + #define ARCH_BIG_ENDIAN #include "Endianness.h" #else @@ -217,6 +217,22 @@ */ #define GCC_MEMORY_BARRIER() __asm__ __volatile__("" ::: "memory"); + #if !defined(ISR) || defined(__DOXYGEN__) + /** Macro for the definition of interrupt service routines, so that the compiler can insert the required + * prologue and epilogue code to properly manage the interrupt routine without affecting the main thread's + * state with unintentional side-effects. + * + * Interrupt handlers written using this macro may still need to be registered with the microcontroller's + * Interrupt Controller (if present) before they will properly handle incoming interrupt events. + * + * \note This is supplied on some architectures where the standard library does not include a valid + * definition. If an existing definition exists, the definition here will be ignored. + * + * \param Name Unique name of the interrupt service routine. + */ + #define ISR(Name, ...) void Name (void) __attribute__((__interrupt__)); void Name (void) + #endif + /* Inline Functions: */ /** Function to reverse the individual bits in a byte - i.e. bit 7 is moved to bit 0, bit 6 to bit 1, * etc. @@ -260,6 +276,79 @@ #endif } + /** Retrieves a mask which contains the current state of the global interrupts for the device. This + * value can be stored before altering the global interrupt enable state, before restoring the + * flag(s) back to their previous values after a critical section using \ref SetGlobalInterruptMask(). + * + * \return Mask containing the current Global Interrupt Enable Mask bit(s). + */ + static inline uint_reg_t GetGlobalInterruptMask(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; + static inline uint_reg_t GetGlobalInterruptMask(void) + { + GCC_MEMORY_BARRIER(); + + #if (ARCH == ARCH_AVR8) + return SREG; + #elif (ARCH == ARCH_UC3) + return __builtin_mfsr(AVR32_SR); + #endif + + GCC_MEMORY_BARRIER(); + } + + /** Sets the global interrupt enable state of the microcontroller to the mask passed into the function. + * This can be combined with \ref GetGlobalInterruptMask() to save and restore the Global Interrupt Enable + * Mask bit(s) of the device after a critical section has completed. + * + * \param[in] GlobalIntState Global Interrupt Enable Mask value to use + */ + static inline void SetGlobalInterruptMask(const uint_reg_t GlobalIntState) ATTR_ALWAYS_INLINE; + static inline void SetGlobalInterruptMask(const uint_reg_t GlobalIntState) + { + GCC_MEMORY_BARRIER(); + + #if (ARCH == ARCH_AVR8) + SREG = GlobalIntState; + #elif (ARCH == ARCH_UC3) + if (GlobalIntState & AVR32_SR_GM) + __builtin_ssrf(AVR32_SR_GM_OFFSET); + else + __builtin_csrf(AVR32_SR_GM_OFFSET); + #endif + + GCC_MEMORY_BARRIER(); + } + + /** Enables global interrupt handling for the device, allowing interrupts to be handled. */ + static inline void GlobalInterruptEnable(void) ATTR_ALWAYS_INLINE; + static inline void GlobalInterruptEnable(void) + { + GCC_MEMORY_BARRIER(); + + #if (ARCH == ARCH_AVR8) + sei(); + #elif (ARCH == ARCH_UC3) + __builtin_csrf(AVR32_SR_GM_OFFSET); + #endif + + GCC_MEMORY_BARRIER(); + } + + /** Disabled global interrupt handling for the device, preventing interrupts from being handled. */ + static inline void GlobalInterruptDisable(void) ATTR_ALWAYS_INLINE; + static inline void GlobalInterruptDisable(void) + { + GCC_MEMORY_BARRIER(); + + #if (ARCH == ARCH_AVR8) + cli(); + #elif (ARCH == ARCH_UC3) + __builtin_ssrf(AVR32_SR_GM_OFFSET); + #endif + + GCC_MEMORY_BARRIER(); + } + #endif /** @} */ |