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

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

[avr-gcc-list] Read wrong value from array of structures in Flash in 4.1


From: Bob Paddock
Subject: [avr-gcc-list] Read wrong value from array of structures in Flash in 4.1.1?
Date: Tue, 15 May 2007 10:21:26 -0400
User-agent: Opera Mail/9.10 (Win32)


/*

Am I doing something here that is stupidly obvious that
I keep overlooking or is this a big in GCC 4.1.1,
for the AT90SCAN64?

The idea here is to have a table of constants so I can
reprogram the CLKPR register on the fly to save power.
Values like the baud rate and timer rates need
to be changed with changes in CLKPR, which
are entered in a table of structures in Flash.

What I'm seeing is that the values accessed from the
end of the structure are off by one.

For example SPI should be 0x55, but instead
is the next value, 0xAA.  CLKPR should be 0xAA
but is the next value, 0x99, that in the real code was
past the end of the array.

The optimization level also changes the results
(should that ever happen?).

Try the following code with -O0 and -Os.

With -O0 the code reads the wrong value from the array.

With -Os the first read from the table never even happens.
The second read still returns the same wrong value.

This is for a AT90SCAN64 part.

If move the errent enteries at the end of the table
to the top of the table I get the correct results,
at least for -O0, didn't check that with -Os.

*/

#include <avr/io.h>             /* CAN64 */
#include <inttypes.h>           /* C99 types */
#include <avr/pgmspace.h>       /* Flash */

#ifdef UART_BAUD_CALCULATE /* Undefine the one for the standard F_CPU frequency in hardware.h */
#undef UART_BAUD_CALCULATE
#endif
#define UART_BAUD_CALCULATE(F_FREQ,UART_BAUD_RATE) ((F_FREQ + UART_BAUD_RATE * 8L) / (UART_BAUD_RATE * 16L) - 1)

typedef struct /* Define the structure 'frequency_control' */
{
  uint16_t seconds_prescaler_value_u16;

  uint16_t baudrate_uart0_u16;
  uint16_t baudrate_uart1_u16;

  uint16_t delay_50ms_u16;

  uint8_t  delay_10us_u8;
  uint8_t  quarter_second_ticks_u8;

  uint8_t  a2d_clk_u8;
  uint8_t  a2d_timer_reload_u8;

  uint8_t  tmr0_prescaller_u8;
  uint8_t  tmr0_ocr_u8;

  uint8_t  spi_u8;
  uint8_t  clkpr_u8;
  uint8_t  bad_u8;
}frequency_control;

static frequency_control frequency_table[] PROGMEM = /* Declare a constant object of type 'frequency_control' */
  {
    /* F_CPU: 7372800: */
    {
400, /* Seconds Prescaler */

UART_BAUD_CALCULATE( 7372800UL, 19200UL ), /* UART0 Baud Rate */ UART_BAUD_CALCULATE( 7372800UL, 9600UL ), /* UART1 Baud Rate */

      46080,                                            /* 50 ms delay */
      18,                                               /* 10 us delay */

(_BV(ADEN)|_BV(ADIE)|_BV(ADPS2)|_BV(ADPS1)), /* Enable A/D, F_CPU/64 for clock, timer will start first conversion */ 7, /* A2D Timer Reload */

(_BV(WGM01)| _BV(CS02)| _BV(CS00) ), /* Timer0 Prescaler, F_CPU divide by 1024, CTC mode */
      17,                                               /* Timer0 Reload */

0x55,//(1<<SPE)|(1<<MSTR)|(1<<SPR0) /* Enable SPI, Master, set clock rate fck/16 */
      0xAA,                                             /* clkpr /1 */
      0x99                                              /* Junk */
    }
  };

uint8_t byte_u8;

void frequency_set( uint16_t freq_select_u16 );
void frequency_set( uint16_t freq_select_u16 )
{
  uint8_t arg0_u8;

  arg0_u8 = pgm_read_byte( &frequency_table[ freq_select_u16 ].spi_u8 );
  byte_u8 = arg0_u8; /* So AVRStudio will show it */

  arg0_u8 = pgm_read_byte( &frequency_table[ freq_select_u16 ].clkpr_u8 );
  byte_u8 = arg0_u8; /* So AVRStudio will show it */
}

int main( void )
{
  frequency_set( (uint16_t) 0 );
  return( -1 );
}
/* End Example */

Output of -Os:

00000094 <frequency_table>:
  94:   90 01 17 00 2f 00 00 b4 12 8e 07 0d 11 55 aa 99     ..../........U..
        ...

000000e0 <frequency_set>:
uint8_t byte_u8;

void frequency_set( uint16_t freq_select_u8 );
void frequency_set( uint16_t freq_select_u8 )
{
  e0:   21 e1           ldi     r18, 0x11       ; 17
  e2:   30 e0           ldi     r19, 0x00       ; 0
  e4:   82 9f           mul     r24, r18
  e6:   f0 01           movw    r30, r0
  e8:   83 9f           mul     r24, r19
  ea:   f0 0d           add     r31, r0
  ec:   92 9f           mul     r25, r18
  ee:   f0 0d           add     r31, r0
  f0:   11 24           eor     r1, r1
  f2:   ed 55           subi    r30, 0x5D       ; 93
  f4:   ff 4f           sbci    r31, 0xFF       ; 255
  f6:   e4 91           lpm     r30, Z
  uint8_t arg0_u8;

  arg0_u8 = pgm_read_byte( &frequency_table[ freq_select_u8 ].spi_u8 );
  byte_u8 = arg0_u8; /* So AVRStudio will show it */

  arg0_u8 = pgm_read_byte( &frequency_table[ freq_select_u8 ].clkpr_u8 );
  byte_u8 = arg0_u8; /* So AVRStudio will show it */
  f8:   e0 93 00 01     sts     0x0100, r30
  fc:   08 95           ret

000000fe <main>:
}

int main( void )
{
  fe:   80 e0           ldi     r24, 0x00       ; 0
 100:   90 e0           ldi     r25, 0x00       ; 0
 102:   0e 94 70 00     call    0xe0    ; 0xe0 <frequency_set>
  frequency_set( (uint16_t) 0 );
  return( -1 );
}
 106:   8f ef           ldi     r24, 0xFF       ; 255
 108:   9f ef           ldi     r25, 0xFF       ; 255
 10a:   08 95           ret


Output of -O0

00000094 <frequency_table>:
  94:   90 01 17 00 2f 00 00 b4 12 8e 07 0d 11 55 aa 99     ..../........U..

000000e0 <frequency_set>:
uint8_t byte_u8;

void frequency_set( uint16_t freq_select_u8 );
void frequency_set( uint16_t freq_select_u8 )
{
  e0:   cf 93           push    r28
  e2:   df 93           push    r29
  e4:   cd b7           in      r28, 0x3d       ; 61
  e6:   de b7           in      r29, 0x3e       ; 62
  e8:   29 97           sbiw    r28, 0x09       ; 9
  ea:   0f b6           in      r0, 0x3f        ; 63
  ec:   f8 94           cli
  ee:   de bf           out     0x3e, r29       ; 62
  f0:   0f be           out     0x3f, r0        ; 63
  f2:   cd bf           out     0x3d, r28       ; 61
  f4:   99 87           std     Y+9, r25        ; 0x09
  f6:   88 87           std     Y+8, r24        ; 0x08
  uint8_t arg0_u8;

  arg0_u8 = pgm_read_byte( &frequency_table[ freq_select_u8 ].spi_u8 );
  f8:   28 85           ldd     r18, Y+8        ; 0x08
  fa:   39 85           ldd     r19, Y+9        ; 0x09
  fc:   81 e1           ldi     r24, 0x11       ; 17
  fe:   90 e0           ldi     r25, 0x00       ; 0
 100:   ac 01           movw    r20, r24
 102:   24 9f           mul     r18, r20
 104:   c0 01           movw    r24, r0
 106:   25 9f           mul     r18, r21
 108:   90 0d           add     r25, r0
 10a:   34 9f           mul     r19, r20
 10c:   90 0d           add     r25, r0
 10e:   11 24           eor     r1, r1
 110:   0e 96           adiw    r24, 0x0e       ; 14
 112:   8c 56           subi    r24, 0x6C       ; 108
 114:   9f 4f           sbci    r25, 0xFF       ; 255
 116:   9e 83           std     Y+6, r25        ; 0x06
 118:   8d 83           std     Y+5, r24        ; 0x05
 11a:   ed 81           ldd     r30, Y+5        ; 0x05
 11c:   fe 81           ldd     r31, Y+6        ; 0x06
 11e:   84 91           lpm     r24, Z
 120:   8c 83           std     Y+4, r24        ; 0x04
 122:   8c 81           ldd     r24, Y+4        ; 0x04
 124:   8f 83           std     Y+7, r24        ; 0x07
  byte_u8 = arg0_u8; /* So AVRStudio will show it */
 126:   8f 81           ldd     r24, Y+7        ; 0x07
 128:   80 93 00 01     sts     0x0100, r24

  arg0_u8 = pgm_read_byte( &frequency_table[ freq_select_u8 ].clkpr_u8 );
 12c:   28 85           ldd     r18, Y+8        ; 0x08
 12e:   39 85           ldd     r19, Y+9        ; 0x09
 130:   81 e1           ldi     r24, 0x11       ; 17
 132:   90 e0           ldi     r25, 0x00       ; 0
 134:   ac 01           movw    r20, r24
 136:   24 9f           mul     r18, r20
 138:   c0 01           movw    r24, r0
 13a:   25 9f           mul     r18, r21
 13c:   90 0d           add     r25, r0
 13e:   34 9f           mul     r19, r20
 140:   90 0d           add     r25, r0
 142:   11 24           eor     r1, r1
 144:   0f 96           adiw    r24, 0x0f       ; 15
 146:   8c 56           subi    r24, 0x6C       ; 108
 148:   9f 4f           sbci    r25, 0xFF       ; 255
 14a:   9b 83           std     Y+3, r25        ; 0x03
 14c:   8a 83           std     Y+2, r24        ; 0x02
 14e:   ea 81           ldd     r30, Y+2        ; 0x02
 150:   fb 81           ldd     r31, Y+3        ; 0x03
 152:   84 91           lpm     r24, Z
 154:   89 83           std     Y+1, r24        ; 0x01
 156:   89 81           ldd     r24, Y+1        ; 0x01
 158:   8f 83           std     Y+7, r24        ; 0x07
  byte_u8 = arg0_u8; /* So AVRStudio will show it */
 15a:   8f 81           ldd     r24, Y+7        ; 0x07
 15c:   80 93 00 01     sts     0x0100, r24
 160:   29 96           adiw    r28, 0x09       ; 9
 162:   0f b6           in      r0, 0x3f        ; 63
 164:   f8 94           cli
 166:   de bf           out     0x3e, r29       ; 62
 168:   0f be           out     0x3f, r0        ; 63
 16a:   cd bf           out     0x3d, r28       ; 61
 16c:   df 91           pop     r29
 16e:   cf 91           pop     r28
 170:   08 95           ret

00000172 <main>:
}

int main( void )
{
 172:   cf 93           push    r28
 174:   df 93           push    r29
 176:   cd b7           in      r28, 0x3d       ; 61
 178:   de b7           in      r29, 0x3e       ; 62
  frequency_set( (uint16_t) 0 );
 17a:   80 e0           ldi     r24, 0x00       ; 0
 17c:   90 e0           ldi     r25, 0x00       ; 0
 17e:   0e 94 70 00     call    0xe0    ; 0xe0 <frequency_set>
  return( -1 );
 182:   8f ef           ldi     r24, 0xFF       ; 255
 184:   9f ef           ldi     r25, 0xFF       ; 255
 186:   df 91           pop     r29
 188:   cf 91           pop     r28
 18a:   08 95           ret









reply via email to

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