*
* Macros to aid debugging of a user application.
*/
+
+/** \defgroup Group_GlobalInt Global Interrupt Macros
+ * \brief Convenience macros for the management of interrupts globally within the device.
+ *
+ * Macros and functions to create and control global interrupts within the device.
+ */
#ifndef __LUFA_COMMON_H__
#define __LUFA_COMMON_H__
#include <string.h>
#include <stddef.h>
+ #if defined(USE_LUFA_CONFIG_HEADER)
+ #include "LUFAConfig.h"
+ #endif
+
+ #include "CompilerSpecific.h"
#include "Architectures.h"
#include "Attributes.h"
#include "BoardTypes.h"
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
/* Architecture specific utility includes: */
#if defined(__DOXYGEN__)
- /** Type define for an unsigned integer the same width as the selected architecture's machine register. */
+ /** Type define for an unsigned integer the same width as the selected architecture's machine register.
+ * This is distinct from the non-specific standard int data type, whose width is machine dependant but
+ * which may not reflect the actual machine register width on some targets (e.g. AVR8).
+ */
typedef MACHINE_REG_t uint_reg_t;
#elif (ARCH == ARCH_AVR8)
#include <avr/io.h>
#define pgm_read_byte(x) *x
#define memcmp_P(...) memcmp(__VA_ARGS__)
#define memcpy_P(...) memcpy(__VA_ARGS__)
- // ==================================================
+ // =================================================
typedef uint32_t uint_reg_t;
#if (ARCH == ARCH_AVR8) || defined(__DOXYGEN__)
/** Defines a volatile \c NOP statement which cannot be optimized out by the compiler, and thus can always
- * be set as a breakpoint in the resulting code. Useful for debugging purposes, where the optimiser
+ * be set as a breakpoint in the resulting code. Useful for debugging purposes, where the optimizer
* removes/reorders code to the point where break points cannot reliably be set.
*
+ * \note This macro is not available for all architectures.
+ *
* \ingroup Group_Debugging
*/
#define JTAG_DEBUG_POINT() __asm__ __volatile__ ("NOP" ::)
/** Defines an explicit JTAG break point in the resulting binary via the assembly \c BREAK statement. When
* a JTAG is used, this causes the program execution to halt when reached until manually resumed.
*
+ * \note This macro is not available for all architectures.
+ *
* \ingroup Group_Debugging
*/
#define JTAG_DEBUG_BREAK() __asm__ __volatile__ ("BREAK" ::)
- #if !defined(pgm_read_ptr) || defined(__DOXYGEN__)
- /** Reads a pointer out of PROGMEM space on the AVR8 architecture. This is currently a wrapper for the
- * avr-libc \c pgm_read_ptr() macro with a \c void* cast, so that its value can be assigned directly
- * to a pointer variable or used in pointer arithmetic without further casting in C. In a future
- * avr-libc distribution this will be part of the standard API and will be implemented in a more formal
- * manner.
- *
- * \param[in] Addr Address of the pointer to read.
- *
- * \return Pointer retrieved from PROGMEM space.
- */
- #define pgm_read_ptr(Addr) (void*)pgm_read_word(Addr)
- #endif
-
/** Macro for testing condition "x" and breaking via \ref JTAG_DEBUG_BREAK() if the condition is false.
*
- * \param[in] Condition Condition that will be evaluated,
+ * \note This macro is not available for all architectures.
+ *
+ * \param[in] Condition Condition that will be evaluated.
*
* \ingroup Group_Debugging
*/
*
* The output takes the form "{FILENAME}: Function {FUNCTION NAME}, Line {LINE NUMBER}: Assertion {Condition} failed."
*
+ * \note This macro is not available for all architectures.
+ *
* \param[in] Condition Condition that will be evaluated,
*
* \ingroup Group_Debugging
#define STDOUT_ASSERT(Condition) MACROS{ if (!(x)) { printf_P(PSTR("%s: Function \"%s\", Line %d: " \
"Assertion \"%s\" failed.\r\n"), \
__FILE__, __func__, __LINE__, #Condition); } }MACROE
- #endif
-
- /** Forces GCC to use pointer indirection (via the device's pointer register pairs) when accessing the given
- * struct pointer. In some cases GCC will emit non-optimal assembly code when accessing a structure through
- * a pointer, resulting in a larger binary. When this macro is used on a (non \c const) structure pointer before
- * use, it will force GCC to use pointer indirection on the elements rather than direct store and load
- * instructions.
- *
- * \param[in, out] StructPtr Pointer to a structure which is to be forced into indirect access mode.
- */
- #define GCC_FORCE_POINTER_ACCESS(StructPtr) __asm__ __volatile__("" : "=b" (StructPtr) : "0" (StructPtr))
- /** Forces GCC to create a memory barrier, ensuring that memory accesses are not reordered past the barrier point.
- * This can be used before ordering-critical operations, to ensure that the compiler does not re-order the resulting
- * assembly output in an unexpected manner on sections of code that are ordering-specific.
- */
- #define GCC_MEMORY_BARRIER() __asm__ __volatile__("" ::: "memory");
+ #if !defined(pgm_read_ptr) || defined(__DOXYGEN__)
+ /** Reads a pointer out of PROGMEM space on the AVR8 architecture. This is currently a wrapper for the
+ * avr-libc \c pgm_read_ptr() macro with a \c void* cast, so that its value can be assigned directly
+ * to a pointer variable or used in pointer arithmetic without further casting in C. In a future
+ * avr-libc distribution this will be part of the standard API and will be implemented in a more formal
+ * manner.
+ *
+ * \note This macro is not available for all architectures.
+ *
+ * \param[in] Address Address of the pointer to read.
+ *
+ * \return Pointer retrieved from PROGMEM space.
+ */
+ #define pgm_read_ptr(Address) (void*)pgm_read_word(Address)
+ #endif
+ #endif
#if !defined(ISR) || defined(__DOXYGEN__)
/** Macro for the definition of interrupt service routines, so that the compiler can insert the required
* 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.
+ * \note This macro is only supplied on some architectures, where the standard library does not include a valid
+ * definition. If an existing definition exists, the alternative definition here will be ignored.
+ *
+ * \ingroup Group_GlobalInt
*
* \param Name Unique name of the interrupt service routine.
*/
- #define ISR(Name, ...) void Name (void) __attribute__((__interrupt__)); void Name (void)
+ #define ISR(Name, ...) void Name (void) __attribute__((__interrupt__)) __VA_ARGS__; void Name (void)
#endif
/* Inline Functions: */
*
* \param[in] Milliseconds Number of milliseconds to delay
*/
+ static inline void Delay_MS(uint8_t Milliseconds) ATTR_ALWAYS_INLINE;
static inline void Delay_MS(uint8_t Milliseconds)
{
#if (ARCH == ARCH_AVR8)
- if (__builtin_constant_p(Milliseconds))
+ if (GCC_IS_COMPILE_CONST(Milliseconds))
{
_delay_ms(Milliseconds);
}
* 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().
*
+ * \ingroup Group_GlobalInt
+ *
* \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;
* 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.
*
+ * \ingroup Group_GlobalInt
+ *
* \param[in] GlobalIntState Global Interrupt Enable Mask value to use
*/
static inline void SetGlobalInterruptMask(const uint_reg_t GlobalIntState) ATTR_ALWAYS_INLINE;
GCC_MEMORY_BARRIER();
}
- /** Enables global interrupt handling for the device, allowing interrupts to be handled. */
+ /** Enables global interrupt handling for the device, allowing interrupts to be handled.
+ *
+ * \ingroup Group_GlobalInt
+ */
static inline void GlobalInterruptEnable(void) ATTR_ALWAYS_INLINE;
static inline void GlobalInterruptEnable(void)
{
GCC_MEMORY_BARRIER();
}
- /** Disabled global interrupt handling for the device, preventing interrupts from being handled. */
+ /** Disabled global interrupt handling for the device, preventing interrupts from being handled.
+ *
+ * \ingroup Group_GlobalInt
+ */
static inline void GlobalInterruptDisable(void) ATTR_ALWAYS_INLINE;
static inline void GlobalInterruptDisable(void)
{
GCC_MEMORY_BARRIER();
}
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
#endif
/** @} */