mikrocontroller.net

Forum: Compiler & IDEs "weg-"optimierung while(funk(.))


Autor: hubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab vergessen die optimierung nach fehlersuche wieder anzuschalten und 
so weiter programmiert.. nun läuft das prog. nicht mehr bei aktiver 
Optim.

folgender code:

while ( !ReadExtDevice(A) ) 
{
  ; // wait until dev. ready  
}
// now dev. ready

quasi  eine "warteschleife" die funktion ReadExtDevice liest nur  von 
einem   beliebigen  Baustein  einen wert.

wird soetwas rausoptimiert / verändert ?

für den compiler müsste ja  das return der funktion konstant  bzw. auch 
das dort  in der funktion gelesene konstant sein- oder ? "er" weiß ja 
nicht das
 "jemand" externes da was dran ändert.

Autor: Dummdödel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nen volatile-Dummy reinschmeisen?

Autor: Wolfgang Mües (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo ist denn die Funktion ReadExtDevice definiert?

Wenn der Compiler an der Stelle, wo die Funktion gebraucht wird, den 
Sourcecode für die Funktion kennt, kann er den Code auch inline 
einsetzen.

Und wenn Du dann IN der Funktion einen Fehler hast, z.B. wenn 
ReadExtDevice aus einer Speicherstelle liest, die NICHT volatile 
deklariert ist, dann hast Du die Schleife wegoptimiert....

Autor: Re To (toobatch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmm .. ReadExtDevice ist in einem anderen src-file definiert . aber im 
aktuellen file bekannt (prototyp).

mein problem ist, dass ich ziehmlich viel code zusammengeschrieben 
(+getestet)  hab mit deaktivierter Optimierung.

also u.U. hängt es an mehreren  stellen - da muss ich jetzt durch und 
nochmal alles angucken.

müsste  überprüfen ob Variablen die in ISRn benutzt werden volatile sind
und ob While-Schleifen vorhanden  sind die intern nix machen.

wär das  ca. richtig zusammengefasst ??
>> muss ja nun nach irgendwas suchen ..
evtl. jemand noch andere Idee auf was ich acht geben sollte // auf was 
die Optimierung irgendwie einfluss nimmt.

was ist wenn ISR wiederum funktionen aufrufen - die dort geänderten 
variablen müssten dann auch volatile sein oder ?

hab gerade was gelesen das u.U. auch nicht-volatile variablen o. auch 
schleifen wegoptimiert werden können wenn die variablen oder in den 
schleifen benutzen variablen verändert werden, aber diese nie geprüft 
werden.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Prinzipiell kann ein Compiler alles wegoptimieren, was nicht benutzt 
wird oder von dem er ausgeht, daß es überflüssig ist.

C hat keine Vorstellung von Interrupts. Ein Compiler kann also immer 
davon ausgehen, daß eine Variable den Wert hat den er innerhalb des 
Progammflusses hineingeschrieben hat.

Wenn sich also von Geisterhand irgendwelche Werte ändern können (zB 
durch eine ISR, die bekanntlich nicht im momentanen Programmfluss 
dargestellt ist) dann muss man das kennzeichnen.

D.h. entsprechende Objekte/Zugriffe müssen volatile sein, oder man baut 
eine Barrier ein, über die zB gcc keine Speicherinhalte wegoptimieren 
kann.

Autor: hubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi ..

merkwürdiges problem gefunden !



also .. bin immernoch beim suchen der Fehlerquellen -  das mein prog. 
mit eingeschalteter optimierung funktioniert.

das Prog. bedient u.A. eine externe UART ( RS232) .

so nun hab ich mir mal ausgeben lassen ( direkt in der ISR) was die denn 
so empfängt:

bei ausgeschalteter Opt.  :   alles OK
bei eingeschalteter Opt.  :   die zeichen nach der ersten Position immer 
fehlerhaft

Errors:   framing Error + parity Error
senden geht in beiden Modi!


nun kann es ja nur sein das bei der optimierung irgendetwas in der 
UART_initalisierung  schief läuft. ( wie gesagt  bei ausgeschalteter 
Opt.  funktionier ja alles) .

kann mir nicht mehr weiterhelfen ..

@ johann du sagtest was von bereichen wo der Compiler nicht optimiert: 
wie geb ich sowas an?

in der init. wird ja nix weiter gemacht als über pointer diverse werte 
in Register der UART geschrieben ( Über externes Memory Interface)

normalerweise wird doch da nix wegoptimiert !?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne was vom Code zu sehen, ohne Compilerschalter oder -version zu 
kennen, ist's Rumraterei.

Autor: hubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es ist echt so ...

hab jetzt mal die  UART- initialisierung  ausgegeben :
Teil aus UART_Init
 // Set ModeRegisters
  PtrOffBUart1[D_SCC_MR1A] = 0x13; // 8 bit, no parity
  PtrOffBUart1[D_SCC_MR2A] = 0x07; // standard operation, 1 stop bit
    //Readout ModeRegister values 
  PtrOffBUart1[D_SCC_CRA]  = 0x1A;   // resets MR-Pointer to MR1
  VolDummy++; VolDummy++; VolDummy++;VolDummy++;
  testOut[0] = PtrOffBUart1[D_SCC_MR1A];
  testOut[1] = PtrOffBUart1[D_SCC_MR2A];

ERLÄUTERUNG: PtrOffBUart1[D_SCC_CRA]  = 0x1A; >>  setzt nur den UART 
internen Pointer auf das erste Register zurück, MR1A und MR2A sind unter 
der gleichen BUS-Adresse erreichbar.

ist quatsch jetzt hier den ganzen code zu posten..

also nur mal beispiel

bei deaktivierter Opt. bekomme ich die richtigen Werte ( 0x13, 0x07 ) 
zurück.
bei aktivierter   Opt. kommt  0x07, 0x07  zurück.

wie gesagt liegt das UART_device am ext. Memoryinterface eines 
ATMEGA2561 --  die zugriffszeit  hab ich auf maximal gestellt - daran 
kann es doch nicht liegen/ interessiert die Opt. ja nicht !

muss ich evtl. die Pointer zu den Registern der Externen Devices  auch 
auf volatile stellen  ???   ich  mein der Compiler könnte ja  auch 
denken - dort werden   einmalig werte geschrieben  die nie geprüft 
werden ...

ich komm hier langsam nicht mehr klar ...  bitte helft mir !!

Autor: hubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
compileroptionen :
-Wall -g2 -gstabs -O3 -funsigned-char -funsigned-bitfields -mmcu=atmega2561 -DF_CPU=14745600UL
-avr-gcc version:
 4.1.1 (WinAVR 20070122)

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich seh immer noch nicht was abgeht...

Ist D_SCC_MR1A ein Makro? Auf was? Eine globale Variable? Wie 
deklariert?
Wenn die Busadresse gleich ist, dann ist also D_SCC_MR1A=D_SCC_MR2A?
In letzterem Falle kann gcc optimieren, falls PtrOffBUart1[] nicht 
volatile ist, was aber auch nicht ersichtlich ist...

Autor: hubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D_SCC_MR1A  =  D_SCC_MR2A , jo

ist ein  define :
#define D_SCC_MR1A 0  // erstes Register des UART ICs
....
//lokal in Init-Fuktion
char  *PtrOffBUart1;
...
PtrOffBUart1 = 0xC000; // physik. (Start)Adresse des UartICs 

also mal den pointer PtrOffBUart1 volatile definieren ?
ok mach ich morgen gleich mal .
danke

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hubi wrote:

> muss ich evtl. die Pointer zu den Registern der Externen Devices  auch
> auf volatile stellen  ?

Selbstverständlich!  Geräteregister sind der klassische Fall für
volatile (und die ganzen IO-Register des AVR selbst sind ja letztlich
auch nichts anderes als irgendwelche Adressen im Speicherbereich).

Autor: hubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jo .. es geht .. :))

ja sowas weiß ich nicht ..  das der optimierer  sowas wegschmeißt!

Autor: Auweia (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir ist nicht klar, warum der Zeiger auf die UART-Register im externen 
RAM volatile sein soll, im Gegensatz zu den Inhalten der dadurch 
adressierten Speicherstellen.

Ich meine, die Adresse ändert sich ja nicht, sondern der Inhalt.

Mir scheint, wenn ich z.B. mit
char a;
eine Variable anlege, dann würde mit
volatile char a;
eine mögliche Veränderung des Inhaltes berücksichtigt.

Wenn ich aber
volatile char * b;
schreibe, dann bezieht sich das doch auf den Zeiger und nicht auf den 
Inhalt.

Mir scheint, als wenn ich eher den Variablen (im Linker- bzw. Makefile) 
feste (im ext. RAM) gelegene Adressen zuweisen würde und sie im Code als 
volatile bezeichnen sollte.

Könntet Ihr das bitte mal erläutern?

Autor: Auweia (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anders gefragt, was ist denn der Unterschied zwischen
volatile char a;
und
volatile char * b;

?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auweia wrote:

> dann bezieht sich das doch auf den Zeiger und nicht auf den
> Inhalt.

Nein. Das wäre der Fall bei
  char * volatile b.
oder
  typedef char * char_ptr;
  volatile char_ptr b;

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auweia wrote:
> Wenn ich aber
>
> volatile char * b;
> 
> schreibe, dann bezieht sich das doch auf den Zeiger und nicht auf den
> Inhalt.
Nein. Die Deklaration legt einen Zeiger mit dem Namen b auf ein Objekt 
vom Typ volatile char an. Der Zeiger selbst ist nicht volatile! Wenn 
der Zeiger auch volatile sein soll, dann müsste es
volatile char *volatile b;
heißen.

EDIT:
Wieder zu langsam...

Autor: Auweia (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Johannes.

D.h. also, der Unterschied zwischen
volatile char a;
und
volatile char * b;
ist, das b eben ein Zeiger ist und a nicht, aber bzgl. der volatile 
Eigenschaft sind beide gleich, oder, anders ausgedrück:
Beiden ist gemeinsam, das sie sich auf volatile Daten a bzw. *b 
beziehen.
Korrekt?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kleiner Tip zum Verständnis von C Deklarationen: Nicht einfach von links 
nach rechts lesen, sondern ausgehend vom Variablennamen von innen nach 
aussen entsprechende der Prioritäten auflösen.

So löst sich auch zwanglos die bei Anfängern beliebte Verwirrung um
  char *a[]; //= array of ptr to char
  char (*a)[]; //= ptr to array of char

Und hier eben:
  char *volatile p;
als
  p
  *volatile
  char
lesen, demgegenüber
  volatile char *p;
als
  p
  *
  volatile char

Das sieht insbesondere deshalb so scheusslich aus, weil "const" und 
"volatile" erst später hinzugeführt wurden, aber sich syntaktisch nicht 
mehr elegant einfügen liessen (zur Übung die exquisite Scheusslichkeit 
"char volatile * const a[] const;").

Autor: Auweia (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist klar. Danke euch allen.

Autor: hut und helm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so UARTs  gehen alle ..

jetzt bei dem code für ethernetInterface  da gehts  teilweise mit -O2 
und mit -03 garnicht.


gibts nicht irgendwo ne liste / manual   zum  (avr-)gcc wo  drinn steht 
was der so alles anfässt bei den verschieden Optimierungsstufen ???

das man ein paar anhaltspunkte hat wo man aufpassen  muss .
sowas wär echt klasse !!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hut und helm wrote:

> gibts nicht irgendwo ne liste / manual   zum  (avr-)gcc wo  drinn steht
> was der so alles anfässt bei den verschieden Optimierungsstufen ???

Steht merkwürdigerweise im Manual vom GCC drin. Also welcher -O Level 
welche Optimierungsoptionen impliziert, und dort dann jeweils was die 
bewirken.

> das man ein paar anhaltspunkte hat wo man aufpassen  muss .
> sowas wär echt klasse !!

Falscher Ansatz. Besser wär's, sich nach der Sprache C zu richten, und 
nicht nach dem was der verwendete Compiler je nach Optimierungsgrad an 
Programmierfehlern noch durchgehen lässt.

Autor: Auweia (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Falscher Ansatz.

Das meine ich auch. Allerdings wäre es für Dich, Hubi, vielleicht 
hilfreich mal ein paar Tips zu kriegen woran es denn liegen könnte. Denn 
aus den Optimierungen zu schliessen was denn am Code falsch ist, kann um 
einiges schwieriger sein als richtigen Code zu schreiben. ;-)

Dafür empfiehlt sich dann Lint.
Z.B.
# Splint — an open source evolved version of Lint (C language).

Gibt natürlich noch kommerzielle Lösungen wie PCLint.


Und hilfreich könnte auch
# Cppcheck — a tool that can find memory leaks, buffer overruns and many 
other common errors.

sein.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob aber Lint oder seine Varianten ein fehlendes volatile erkennen?

Für den vorliegenden Fall "Programm läuft nur ohne Optimierung" gibt es 
doch beim avr-gcc gar nicht so viele mögliche Ursachen. Ein fehlendes 
"volatile" dürfte zu 99,99999% die Ursache sein. Früher (so zu Zeiten 
von Turbo-C o.ä.) gab es noch den Effekt, daß (lokale?) Variablen ohne 
Optimierung mit Null vorbelegt, mit aber undefiniert waren. Das ist aber 
Geschichte.

Fällt jemandem sonst noch was ein?

Und die Kenntnis darüber, was der gcc genau bei den einzelnen 
Optimierungsstufen anstellt, braucht man nur, wenn es um extrem 
kritische timings oder um das letzte freie Byte im Flash geht.

Oliver

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicht ganz so viele Neuner. Compiler-Fehler waren auch schon dabei. Die 
Frühjahrs-Version von WinAVR hatte in dieser Hinsicht einen recht 
holprigen Start und die Linux-Fraktion ist bis heute etwas gekniffen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.