I'm trying to bring up a new board that uses a Tiny88. I'm compiling the code as C++ code, using WinAVR 20081205/4.3.2, using -Os. Makefile was produced by MFile.
This is the test program, main.cpp: ============= #if defined(__cplusplus) && __cplusplus extern "C" { #endif #include <avr/io.h> #include <inttypes.h> #if defined(__cplusplus) && __cplusplus } #endif #define BUTTON_BIT (2) #define BUTTON _BV(BUTTON_BIT) #define LED0H_BIT (6) #define LED0H _BV(LED0H_BIT) #define LED2H_BIT (5) #define LED2H _BV(LED2H_BIT) #define VpumpH_BIT (2) #define VpumpH _BV(VpumpH_BIT) #define VpumpL_BIT (1) #define VpumpL _BV(VpumpL_BIT) /* *************************************************************************************** */ int main( void ) { SMCR = 0; /* Sleep mode disabled */ GPIOR2 = MCUSR; /* Save the cause of reset in General Purpose Register Two */ MCUSR = 0; /* Clear the flags for the next pass */ WDTCSR = (_BV(WDCE)|_BV(WDE)); /* Disable Watchdog, which can only be done if WDRF is clear in MCUSR */ WDTCSR = 0; /* Must be done within four instructions of above WDTCSR */ PORTB = VpumpH; /* Deassert all outputs */ DDRB = 0xFF; PORTA = 0x00; DDRA = 0xFF; PORTC = 0x00; DDRC = 0xFF; PORTD = BUTTON; /* Pull Up on BUTTON, all others output low */ DDRD = (uint8_t) ~BUTTON; for(;;) { uint8_t byte_u8 = LED2H; // Start LED // Charge pump off: byte_u8 |= VpumpH; byte_u8 &= (uint8_t) ~VpumpL; PORTB = byte_u8; byte_u8 <<= 1; // Key to failing seems to be this line // without this the produced code would be // what the compiler is really generating // When All LEDs have been lit, start over: if( 0 == (byte_u8 & (uint8_t) ~VpumpH)) { byte_u8 = (uint8_t) LED0H; } } } ============= which generates this very broken code: ============= /* *************************************************************************************** */ int main( void ) { SMCR = 0; /* Sleep mode disabled */ 60: 13 be out 0x33, r1 ; 51 GPIOR2 = MCUSR; /* Save the cause of reset in General Purpose Register Two */ 62: 84 b7 in r24, 0x34 ; 52 64: 8b bd out 0x2b, r24 ; 43 MCUSR = 0; /* Clear the flags for the next pass */ 66: 14 be out 0x34, r1 ; 52 WDTCSR = (_BV(WDCE)|_BV(WDE)); /* Disable Watchdog, which can only be done if WDRF is clear in MCUSR */ 68: 88 e1 ldi r24, 0x18 ; 24 6a: 80 93 60 00 sts 0x0060, r24 WDTCSR = 0; /* Must be done within four instructions of above WDTCSR */ 6e: 10 92 60 00 sts 0x0060, r1 PORTB = VpumpH; /* Deassert all outputs */ 72: 94 e0 ldi r25, 0x04 ; 4 74: 95 b9 out 0x05, r25 ; 5 DDRB = 0xFF; 76: 8f ef ldi r24, 0xFF ; 255 78: 84 b9 out 0x04, r24 ; 4 PORTA = 0x00; 7a: 1e b8 out 0x0e, r1 ; 14 DDRA = 0xFF; 7c: 8d b9 out 0x0d, r24 ; 13 PORTC = 0x00; 7e: 18 b8 out 0x08, r1 ; 8 DDRC = 0xFF; 80: 87 b9 out 0x07, r24 ; 7 PORTD = BUTTON; /* Pull Up on BUTTON, all others output low */ 82: 9b b9 out 0x0b, r25 ; 11 DDRD = (uint8_t) ~BUTTON; 84: 8b ef ldi r24, 0xFB ; 251 86: 8a b9 out 0x0a, r24 ; 10 uint8_t byte_u8 = LED2H; byte_u8 |= VpumpH; byte_u8 &= (uint8_t) ~VpumpL; PORTB = byte_u8; 88: 84 e2 ldi r24, 0x24 ; 36 8a: 85 b9 out 0x05, r24 ; 5 8c: fe cf rjmp .-4 ; 0x8a <main+0x2a> 0000008e <_exit>: 8e: f8 94 cli 00000090 <__stop_program>: 90: ff cf rjmp .-2 ; 0x90 <__stop_program> ============= It appears everything involving modifying/testing byte_u8 in the for(;;) has been optimized out of existence. Why? This is not an interrupt, so the usual FAQ issue of volatile doesn't seem like it applies here. If you change this: for(;;) { uint8_t byte_u8 = LED2H; ... to this: uint8_t byte_u8 = LED2H; for(;;) { ... the compiler at least tells you that byte_u8 is assigned but not used. Something here is failing the "least surprise" test. What is it I'm not understanding? _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list