"weg-"optimierung while(funk(.))

Gast #1076138
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.
Gast #1076183
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....
#1077168
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.
Persönliche Seite #1077236
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.
Gast #1082375
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 !?
Gast #1082562
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 !!
Gast #1082823
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
Gast #1083250
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?
#1083266
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...
Gast #1083273
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?
#1083283
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;").
Gast #1083469
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 !!
#1083475
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.
Gast #1083704
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.
Gast #1083880
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren