/*
LUFA Library
- Copyright (C) Dean Camera, 2011.
+ Copyright (C) Dean Camera, 2012.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
* @{
*/
-/** \defgroup Group_Debugging Debugging Macros
- * \brief Convenience macros to aid in debugging applications.
+/** \defgroup Group_GlobalInt Global Interrupt Macros
+ * \brief Convenience macros for the management of interrupts globally within the device.
*
- * Macros to aid debugging of a user application.
+ * Macros and functions to create and control global interrupts within the device.
*/
#ifndef __LUFA_COMMON_H__
/* Macros: */
#define __INCLUDE_FROM_COMMON_H
-
+
/* Includes: */
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stddef.h>
-
+
+ #if defined(USE_LUFA_CONFIG_HEADER)
+ #include "LUFAConfig.h"
+ #endif
+
#include "Architectures.h"
- #include "Attributes.h"
#include "BoardTypes.h"
-
+ #include "ArchitectureSpecific.h"
+ #include "CompilerSpecific.h"
+ #include "Attributes.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>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/boot.h>
+ #include <math.h>
#include <util/delay.h>
-
+
typedef uint8_t uint_reg_t;
-
+
#define ARCH_HAS_EEPROM_ADDRESS_SPACE
#define ARCH_HAS_FLASH_ADDRESS_SPACE
#define ARCH_HAS_MULTI_ADDRESS_SPACE
#define pgm_read_byte(x) *x
#define memcmp_P(...) memcmp(__VA_ARGS__)
#define memcpy_P(...) memcpy(__VA_ARGS__)
- // ==================================================
+ // =================================================
typedef uint32_t uint_reg_t;
-
+
#define ARCH_BIG_ENDIAN
#include "Endianness.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include <avr/io.h>
+ #include <avr/interrupt.h>
+ #include <avr/pgmspace.h>
+ #include <avr/eeprom.h>
+ #include <math.h>
+ #include <util/delay.h>
+
+ typedef uint8_t uint_reg_t;
+
+ #define ARCH_HAS_EEPROM_ADDRESS_SPACE
+ #define ARCH_HAS_FLASH_ADDRESS_SPACE
+ #define ARCH_HAS_MULTI_ADDRESS_SPACE
+ #define ARCH_LITTLE_ENDIAN
+
+ #include "Endianness.h"
#else
#error Unknown device architecture specified.
#endif
* \return The larger of the two input parameters
*/
#if !defined(MAX) || defined(__DOXYGEN__)
- #define MAX(x, y) ((x > y) ? x : y)
+ #define MAX(x, y) (((x) > (y)) ? (x) : (y))
#endif
/** Convenience macro to determine the smaller of two values.
* \return The smaller of the two input parameters
*/
#if !defined(MIN) || defined(__DOXYGEN__)
- #define MIN(x, y) ((x < y) ? x : y)
+ #define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
- #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
- * removes/reorders code to the point where break points cannot reliably be set.
+ #if !defined(STRINGIFY) || defined(__DOXYGEN__)
+ /** Converts the given input into a string, via the C Preprocessor. This macro puts literal quotation
+ * marks around the input, converting the source into a string literal.
*
- * \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.
+ * \param[in] x Input to convert into a string literal.
*
- * \ingroup Group_Debugging
+ * \return String version of the input.
*/
- #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,
- *
- * \ingroup Group_Debugging
- */
- #define JTAG_DEBUG_ASSERT(Condition) MACROS{ if (!(Condition)) { JTAG_DEBUG_BREAK(); } }MACROE
+ #define STRINGIFY(x) #x
- /** Macro for testing condition "x" and writing debug data to the stdout stream if \c false. The stdout stream
- * must be pre-initialized before this macro is run and linked to an output device, such as the microcontroller's
- * USART peripheral.
- *
- * The output takes the form "{FILENAME}: Function {FUNCTION NAME}, Line {LINE NUMBER}: Assertion {Condition} failed."
+ /** Converts the given input into a string after macro expansion, via the C Preprocessor. This macro puts
+ * literal quotation marks around the expanded input, converting the source into a string literal.
*
- * \param[in] Condition Condition that will be evaluated,
+ * \param[in] x Input to expand and convert into a string literal.
*
- * \ingroup Group_Debugging
+ * \return String version of the expanded input.
*/
- #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
+ #define STRINGIFY_EXPANDED(x) STRINGIFY(x)
#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(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: */
* etc.
*
* \param[in] Byte Byte of data whose bits are to be reversed.
+ *
+ * \return Input data with the individual bits reversed (mirrored).
*/
static inline uint8_t BitReverse(uint8_t Byte) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
static inline uint8_t BitReverse(uint8_t Byte)
*
* \param[in] Milliseconds Number of milliseconds to delay
*/
- static inline void Delay_MS(uint8_t Milliseconds)
+ static inline void Delay_MS(uint16_t Milliseconds) ATTR_ALWAYS_INLINE;
+ static inline void Delay_MS(uint16_t Milliseconds)
{
#if (ARCH == ARCH_AVR8)
- if (__builtin_constant_p(Milliseconds))
+ if (GCC_IS_COMPILE_CONST(Milliseconds))
{
_delay_ms(Milliseconds);
}
while (Milliseconds--)
{
__builtin_mtsr(AVR32_COUNT, 0);
- while (__builtin_mfsr(AVR32_COUNT) < (F_CPU / 1000));
+ while ((uint32_t)__builtin_mfsr(AVR32_COUNT) < (F_CPU / 1000));
+ }
+ #elif (ARCH == ARCH_XMEGA)
+ if (GCC_IS_COMPILE_CONST(Milliseconds))
+ {
+ _delay_ms(Milliseconds);
+ }
+ else
+ {
+ while (Milliseconds--)
+ _delay_ms(1);
}
#endif
}
* 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;
#if (ARCH == ARCH_AVR8)
return SREG;
#elif (ARCH == ARCH_UC3)
- return __builtin_mfsr(AVR32_SR);
+ return __builtin_mfsr(AVR32_SR);
+ #elif (ARCH == ARCH_XMEGA)
+ return SREG;
#endif
GCC_MEMORY_BARRIER();
* 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;
__builtin_ssrf(AVR32_SR_GM_OFFSET);
else
__builtin_csrf(AVR32_SR_GM_OFFSET);
+ #elif (ARCH == ARCH_XMEGA)
+ SREG = GlobalIntState;
#endif
-
+
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)
{
sei();
#elif (ARCH == ARCH_UC3)
__builtin_csrf(AVR32_SR_GM_OFFSET);
+ #elif (ARCH == ARCH_XMEGA)
+ sei();
#endif
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)
{
cli();
#elif (ARCH == ARCH_UC3)
__builtin_ssrf(AVR32_SR_GM_OFFSET);
+ #elif (ARCH == ARCH_XMEGA)
+ cli();
#endif
GCC_MEMORY_BARRIER();
}
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
#endif
/** @} */