avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] Should this code work? 4.1.1


From: Bob Paddock
Subject: [avr-gcc-list] Should this code work? 4.1.1
Date: Fri, 02 Mar 2007 15:59:13 -0500
User-agent: Opera Mail/9.10 (Win32)


In what many or may not be a continuation of
my problems with out-of-order code execution,
with 4.1.1, I'd like to know why this code does
not work (comments below the code):

/* Code for AT90CAN64. */

#include <avr/io.h>
#include <util/delay.h>

void SPI_MasterInit(void);
void SPI_MasterInit(void)
{
  /* Enable SPI, Master, set clock rate fck/16 */
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_MasterTransmit(char cData);
void SPI_MasterTransmit(char cData)
{
  /* Start transmission */
  SPDR = cData;

  /* Wait for transmission complete */
  while(!(SPSR & (1<<SPIF)))
    ;
}

int main( void )
{
/* Data Direction et.al. setup by the bootloader, before we get to this main() */

  SPI_MasterInit();
  PORTB &= (uint8_t) ~_BV(4); /* Display Output enable */

  for(;;)
    {
      /* volatile */ uint16_t shift = 1;

      SPI_MasterTransmit( 0x3F );
      SPI_MasterTransmit( (uint8_t) shift );
      SPI_MasterTransmit( (uint8_t) (shift>>8) );

      shift <<= 1;
      if( 0 == shift )
        {
          shift = 1;
        }
      PORTA |= (uint8_t)  _BV(6); /* Load the data into latch, */
      _delay_us( 5.0 );
      PORTA &= (uint8_t) ~_BV(6); /* return line low */

      _delay_ms( 32.5 );
      _delay_ms( 32.5 );
      _delay_ms( 32.5 );
      _delay_ms( 32.5 );
    }
}

With 'volatile' commented out the variable 'shift'
is no place to be found in 'main.lss'. The
fixed values 0x3F,0x01,0x00 are output.  With 'volatile'
present, but I don't understand why it is needed in this
context, the 'shift' code is present, but non-functional.

 /* volatile */ uint16_t shift = 1;

What I mean by non-functional is that if
you look at the produced main.lss
file, or run the program on the real hardware:

  f8:   21 e0           ldi     r18, 0x01       ; 1
  fa:   30 e0           ldi     r19, 0x00       ; 0
  fc:   5f e3           ldi     r21, 0x3F       ; 63
  fe:   4c e0           ldi     r20, 0x0C       ; 12
 100:   e0 e0           ldi     r30, 0x00       ; 0
 102:   fa ee           ldi     r31, 0xEA       ; 234

  for(;;)
    {
      volatile uint16_t shift = 1;
 104:   3a 83           std     Y+2, r19        ; 0x02
 106:   29 83           std     Y+1, r18        ; 0x01
 ...
 166:   ce cf           rjmp    .-100           ; 0x104 <main+0x26>

you see that the last rjmp is jumping to the point where shift
is reinitialized with '1' (r18/r19).

Moving 'uint16_t shift = 1;' out of the for(;;){} and into
the top of main(){} makes the code work ok.

Is it my understanding, or the compiler that is broken here?







reply via email to

[Prev in Thread] Current Thread [Next in Thread]