Gast
#1681461
Habe ein Problem mit einer Routine, welche eine volatile Variable mit einer anderen vergleicht. Das ganze sollte eine FIFO für den USART1 darstellen. Hier das problematische Codesegment (vollständiger Teil und generiertes Assemblerlisting im Anhang) :
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
Das Problem liegt in der Funktion get_btrx(). Wenn ich den mit -Os Optimierung erzeugten Assembler-Code richtig interpretiere, wird der if(bt_rx_rdptr!=bt_rx_wrptr) - Vergleich nur einmal aufgerufen und die do-while-Schleife springt wieder zum Anfang des _delay_us(50) statt zurück zum if-Vergleich. Bei der Optimierung -O0 ist alles OK, bei -O2 funktioniert es auch nicht. Die Deklaration des bt_rx_rdptr Zeigers als volatile bringt keine Änderung (ist auch nicht sinnvoll, da der USART-Rx-Interrupt sie auch nicht ändert). Die USART-Konfiguration und die ISR für den USART1_RX_vect habe ich getestet. Das Zeichen wird korrekt empfangen und auch im Puffer gespeichert. Der erste Aufruf von get_btrx() ergibt ein Timeout (obwohl vor Ablauf des Timeouts ein Zeichen über die USART empfangen wurde). Nachfolgende Aufrufe liefern das vorherige Zeichen aus dem Ringpuffer. Ich finde keinen Fehler im C-Code und vermute ein Bug im gcc. Kann ich als Workaround die Optimierung für diesen Bereich gezielt abschalten ? AVR-GCC-Version : 4.4.3 , avr-libc 1.6.8 Zielprozessor : ATMega128A Host: Ubuntu-Linux 8.04 Gruesse aus Mülheim ;-) Burkhard