Selbst bei einfachen Programmen kommt bei mir manchmal nicht das
erwünschte Ergebnis aus dem Compiler (avr-gcc (GCC) 3.4.3; Atmega8).
Selbst einfache For-schleifen bringen ihn manchmal zum Aufhängen (der
verwendete Variablentyp stimmt). Wenn man dann die Optimierung
ausschaltet, dann gehts manchmal plötzlich! Also programmiert man
gemütlich so weiter. Und irgendwann mit einer ganz harmlosen Zeile Code
dreht der Controller wieder durch. Wenn man dann Glück hat, gehts mit
einer anderen Optimierungsstufe wieder. Irgendwann war ich dann an dem
Punkt, an dem keine Optimierungsstufe mehr einwandfrei funkioniert hat.
Aber in jeder ging irgendwas anderes nicht. Absolut nicht
nachvollziehbar. Ich hab jetzt auch gemerkt, dass die "hex"-Datei
nicht mit der "lss"-Datei übereinstimmt (Die Adressen der Funktionen
stimmen nicht). Kann das sein? Ist das ganze eventuell eine
Einstellungssache?
Controller und Frequenz sind in der Makefile eingetragen.
#include <avr/io.h>
#include <stdint.h>
#include "lcd_atmega8.h"
void main(void)
{
unsigned int i;
LCD_Init();
LCD_Clr();
DDRB= (1<<PB0) | (1<<PB5);
PORTB=1;
for (i=0;i<=30000;i++) ;
PORTB|= (1<<5);
LCD_Str("irgendwas");
while (1);
return 0;
}
Hin und wieder kann man kurz das Wort auf dem LCD lesen, dann ists
wieder weg und irgenwann wieder da. Im gleichen Takt wechselt der
PortB-5 seinen Zustand. PortB-0 bleibt auf 5V.
Wenn ich die Schleife und die Port-Befehle rausmache, dann filmmert das
LCD (als obs ständig aktualisiert würde).
(Optimierungsstufe 0)
Trivial, hier ohne Belang und vom Compiler angezeigt: return in einer
void-Funktion.
Welche Schleife rausgemacht? Sind 2 drin. Ohne die zweite tät's mich
nicht wundern. Wenn sich jedoch während der while(1)-Schleife auf dem
LCD oder den Ports etwas tut, dann liegt das Problem in der Hardware,
nicht der Software. Mal vorausgesetzt, dass die LCD-Routinen keine
Interrupts verwenden.
Der Compiler optimiert nur Dinge weg, die aus seiner keine Wirkung
haben. Die while(1)-Schleife aber darf er nicht wegoptimieren, da sonst
der Code dahinter ausgeführt würde.
Nicht zu verwechseln mit Zählschleifen. Da kann's schon sein, dass aus
for (i=1;i!=1000;++i); am Ende ein einfaches i=1000 wird.
Konnte es noch weiter eingrenzen:
void main(void)
{
unsigned int i;
DDRB= (1<<PB0) | (1<<PB5);
PORTB=1;
for (i=0;i<=30000;i++) ;
PORTB|= (1<<5);
while (1) ;//asm volatile ("nop")
return 0;
}
So bleibt PortB auf 1 stehen (d.h. er macht ab der For-Schleife nicht
mehr das, was er soll. Wenn ich jedoch das "asm..." in der while
Schleife eintrage, dann gehts wunderbar. Aber wieso passiert das mit
der Optimierungsstufe 0? In der "lss"-Datei steht der Befehl (rjmp
-2) noch drin. In der Hex stimmt dann gar nix mehr überein!
Außerdem war dies auch nur ein kleines Beispiel meiner Probleme. Bei
größeren Projekten habe ich keine Chance mehr irgendwas zu
kontrollieren. Da optimiert er einfach Sachen weg, obwohl sie nötig
sind. Ich habe keine Ahnung mehr was ich da machen kann. Hat von euch
niemand solche Probleme?
"Da optimiert er einfach Sachen weg, obwohl sie nötig sind."
Da wäre ein konkretes Beispiel recht hilfreich - also der betreffende
C-Code und das falsche Resultat (.lst oder .lss). Im oben gezeigten
Code ist bis hin zum Hex-File alles ok.
"Hat von euch niemand solche Probleme?"
Ich selbst nicht und der allgemeinen Diskussionskultur hier nach zu
schliessen auch sonst niemand.
Anbei Disassembly vom Hex.
PORTB=1;
for (i=0;i<=30000;i++) ;
PORTB|= (1<<5);
"So bleibt PortB auf 1 stehen"
Ich sehe auch keinen Grund, warum der Mega8 das nicht so halten sollte.
Die erste Zeile setzt B5 auf 1, die dritte Zeile ändert B5 von 1 auf 1.
Wenn B5 da auf 0 gehen soll, dann mit
PORTB &= ~(1<<5);
@A.K. Genau, der PortB müsste 0x21 sein, ist er aber definitiv nicht.
Ich hab mal das Hex mit dem AVR-Studio debugged und siehe da, auch hier
ist nur PB0 gesetzt nicht aber PB5!
Das deutet doch daraufhin, dass hex und lss doch nicht übereinstimmen,
oder bin ich blind? Habt ihr das hex mal ausprobiert? Oder könnte
jemand von euch mal die obigen Zeilen kompilieren und das hex hier
reinstellen, dann könnte ich sehen obs vielleicht doch an meinen
Einstellung liegt.
Übrigens, nur nebenbei: das LSS-Listing ist ein Disassemblerlisting,
das von der Ausgabe her rückwärts generiert wird und dann anhand der
Debuginformationen mit den Codeschnipseln ,,annotiert'' wird. Das
muss ganz zwangsläufig mit der ELF-Date übereinstimmen, und sofern
nicht jemand das Extrahieren der HEX-Datei aus dem ELF verpfuscht hat,
dann auch mit dieser.