[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [avr-gcc-list] Read wrong value from array of structures in Flash in 4.1.1?,
Bob Paddock <=