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


von hubi (Gast)


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:
1
while ( !ReadExtDevice(A) ) 
2
{
3
  ; // wait until dev. ready  
4
}
5
// 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.

von Dummdödel (Gast)


Lesenswert?

nen volatile-Dummy reinschmeisen?

von Wolfgang Mües (Gast)


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....

von Re T. (toobatch)


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.

von Johann L. (gjlayde) Benutzerseite


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.

von hubi (Gast)


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 !?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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

von hubi (Gast)


Lesenswert?

es ist echt so ...

hab jetzt mal die  UART- initialisierung  ausgegeben :
Teil aus UART_Init
1
 // Set ModeRegisters
2
  PtrOffBUart1[D_SCC_MR1A] = 0x13; // 8 bit, no parity
3
  PtrOffBUart1[D_SCC_MR2A] = 0x07; // standard operation, 1 stop bit
4
    //Readout ModeRegister values 
5
  PtrOffBUart1[D_SCC_CRA]  = 0x1A;   // resets MR-Pointer to MR1
6
  VolDummy++; VolDummy++; VolDummy++;VolDummy++;
7
  testOut[0] = PtrOffBUart1[D_SCC_MR1A];
8
  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 !!

von hubi (Gast)


Lesenswert?

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

von Johann L. (gjlayde) Benutzerseite


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...

von hubi (Gast)


Lesenswert?

D_SCC_MR1A  =  D_SCC_MR2A , jo

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

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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).

von hubi (Gast)


Lesenswert?

jo .. es geht .. :))

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

von Auweia (Gast)


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
1
char a;
eine Variable anlege, dann würde mit
1
volatile char a;
eine mögliche Veränderung des Inhaltes berücksichtigt.

Wenn ich aber
1
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?

von Auweia (Gast)


Lesenswert?

Anders gefragt, was ist denn der Unterschied zwischen
1
volatile char a;
und
1
volatile char * b;

?

von (prx) A. K. (prx)


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;

von Johannes M. (johnny-m)


Lesenswert?

Auweia wrote:
> Wenn ich aber
>
1
> volatile char * b;
2
>
> 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
1
volatile char *volatile b;
heißen.

EDIT:
Wieder zu langsam...

von Auweia (Gast)


Lesenswert?

Danke Johannes.

D.h. also, der Unterschied zwischen
1
volatile char a;
und
1
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?

von (prx) A. K. (prx)


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;").

von Auweia (Gast)


Lesenswert?

Ist klar. Danke euch allen.

von hut und helm (Gast)


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 !!

von (prx) A. K. (prx)


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.

von Auweia (Gast)


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.

von Oliver (Gast)


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

von (prx) A. K. (prx)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.