diff --git a/trunk/avr-libc/include/avr/interrupt.h b/trunk/avr-libc/include/avr/interrupt.h index a36e2ba6..844289df 100644 --- a/trunk/avr-libc/include/avr/interrupt.h +++ b/trunk/avr-libc/include/avr/interrupt.h @@ -125,9 +125,9 @@ # define ISR(vector, [attributes]) #else /* real code */ -#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) && !defined(__clang__) # define __INTR_ATTRS __used__, __externally_visible__ -#else /* GCC < 4.1 */ +#else /* GCC < 4.1 or clang */ # define __INTR_ATTRS __used__ #endif diff --git a/trunk/avr-libc/include/avr/wdt.h b/trunk/avr-libc/include/avr/wdt.h index 73517e3e..8d6253bf 100644 --- a/trunk/avr-libc/include/avr/wdt.h +++ b/trunk/avr-libc/include/avr/wdt.h @@ -41,6 +41,13 @@ #include #include +/* Workaround for clang: This gives the I/O address of the given register if it can be used + * as immediate value, otherwise an incorrect address is returned that does fulfill the constraint + * "I" but must not be used. The programmer has to make sure that inline assembly using this macro + * is only executed, if _SFR_IO_REG_P(x) is true + */ +#define _SFR_IO_ADDR_WORKAROUND(x) (_SFR_IO_ADDR(x) & 0x3f) + /** \file */ /** \defgroup avr_watchdog : Watchdog timer handling \code #include \endcode @@ -266,7 +273,7 @@ void wdt_enable (const uint8_t value) : /* no outputs */ : [CCPADDRESS] "n" (_SFR_MEM_ADDR(CCP)), [SIGNATURE] "r" ((uint8_t)0xD8), - [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), + [WDTREG] "I" (_SFR_IO_ADDR_WORKAROUND(_WD_CONTROL_REG)), [WDVALUE] "r" ((uint8_t)((value & 0x08 ? _WD_PS3_MASK : 0x00) | _BV(WDE) | (value & 0x07) )) : "r0" @@ -282,7 +289,7 @@ void wdt_enable (const uint8_t value) "sts %[WDTREG],%[WDVALUE]" "\n\t" "out __SREG__,__tmp_reg__" "\n\t" : /* no outputs */ - : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), + : [CCPADDRESS] "I" (_SFR_IO_ADDR_WORKAROUND(CCP)), [SIGNATURE] "r" ((uint8_t)0xD8), [WDTREG] "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), [WDVALUE] "r" ((uint8_t)((value & 0x08 ? _WD_PS3_MASK : 0x00) @@ -300,9 +307,9 @@ void wdt_enable (const uint8_t value) "out %[WDTREG],%[WDVALUE]" "\n\t" "out __SREG__,__tmp_reg__" "\n\t" : /* no outputs */ - : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), + : [CCPADDRESS] "I" (_SFR_IO_ADDR_WORKAROUND(CCP)), [SIGNATURE] "r" ((uint8_t)0xD8), - [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), + [WDTREG] "I" (_SFR_IO_ADDR_WORKAROUND(_WD_CONTROL_REG)), [WDVALUE] "r" ((uint8_t)((value & 0x08 ? _WD_PS3_MASK : 0x00) | _BV(WDE) | (value & 0x07) )) : "r0" @@ -350,7 +357,7 @@ void wdt_disable (void) : /*no output */ : [CCPADDRESS] "n" (_SFR_MEM_ADDR(CCP)), [SIGNATURE] "r" ((uint8_t)0xD8), - [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), + [WDTREG] "I" (_SFR_IO_ADDR_WORKAROUND(_WD_CONTROL_REG)), [TEMP_WD] "d" (temp_wd), [WDVALUE] "n" (1 << WDE) : "r0" @@ -369,7 +376,7 @@ void wdt_disable (void) "sts %[WDTREG],%[TEMP_WD]" "\n\t" "out __SREG__,__tmp_reg__" "\n\t" : /*no output */ - : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), + : [CCPADDRESS] "I" (_SFR_IO_ADDR_WORKAROUND(CCP)), [SIGNATURE] "r" ((uint8_t)0xD8), [WDTREG] "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), [TEMP_WD] "d" (temp_wd), @@ -390,9 +397,9 @@ void wdt_disable (void) "out %[WDTREG],%[TEMP_WD]" "\n\t" "out __SREG__,__tmp_reg__" "\n\t" : /*no output */ - : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), + : [CCPADDRESS] "I" (_SFR_IO_ADDR_WORKAROUND(CCP)), [SIGNATURE] "r" ((uint8_t)0xD8), - [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), + [WDTREG] "I" (_SFR_IO_ADDR_WORKAROUND(_WD_CONTROL_REG)), [TEMP_WD] "d" (temp_wd), [WDVALUE] "n" (1 << WDE) : "r0" @@ -416,7 +423,7 @@ void wdt_enable (const uint8_t value) "out __SREG__,__tmp_reg__" "\n\t" "out %0, %2" "\n \t" : /* no outputs */ - : "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), + : "I" (_SFR_IO_ADDR_WORKAROUND(_WD_CONTROL_REG)), "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))), "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | _BV(WDE) | (value & 0x07)) ) @@ -459,7 +466,7 @@ void wdt_disable (void) "out %[WDTREG],__zero_reg__" "\n\t" "out __SREG__,__tmp_reg__" "\n\t" : [TEMPREG] "=d" (temp_reg) - : [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), + : [WDTREG] "I" (_SFR_IO_ADDR_WORKAROUND(_WD_CONTROL_REG)), [WDCE_WDE] "n" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))) : "r0" );