PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Compiler ignoriert volatile ?



Siro
21.10.2010, 16:14
Mehr "volatile" geht wohl kaum und trotzdem "KLAUT" mir der Compiler meinen Code. Wo muss das "volatile" denn hin, damit der compiler meinen Code NICHT rausschmeisst ?????
Die Funktion "ShiftOut() " welche ich vom Hauptprogramm aufrufe, wird rausgeschmissen, (wegoptimiert)
wie kann das denn sein ?????
Wichtig: ANSI-C tauglich



typedef volatile union
{
struct
{
int data : 16;
int reserved0 : 16;
} bits;
U32 value;
} SSP1DR_TypeDef;
#define LPC_SSP1DR (* (SSP1DR_TypeDef *)(0x40030008))


typedef volatile union
{
volatile struct
{
volatile int TFE : 1;
volatile int TFN : 1;
volatile int RNE : 1;
volatile int RFF : 1;
volatile int BSY : 1;
volatile int reserved0 : 27;
} bits;
volatile U32 value;
} SSP1SR_TypeDef;
#define LPC_SSP1SR (* (volatile SSP1SR_TypeDef *)(0x4003000C))


unsigned char data;

void ShiftOut()
{
while (LPC_SSP1SR.bits.BSY) ; /* wait until BSY becomes zero */
LPC_SSP1DR.value = data; /* shift out the data byte */
}


int main(void)
{
while (1)
{
data = 0xAA;
ShiftOut();
}
}



Compiler: IAR Embedded Workbench 5.4

fassungslos...
Siro

Jaecko
21.10.2010, 17:07
Wo in dem Code ist die TestFunc()?
Da die Funktion nicht aufgerufen wird, kanns sein, dass der Linker die einfach nicht linkt. (Im Stil von "Warum was reinpacken, was eh nicht gebraucht wird?")

Siro
21.10.2010, 18:25
Upps, entschuldigt, die funktion heisst natürlich "ShiftOut()" nicht TestFunc
ich hatte sie testweise umbenannt.
Ja, das wäre okay, wenn ich die funktion nicht aufrufen würde, dürfte er diese auch entfernen.
Versuche ergaben, wenn ich dieser funktion einen parameter übergebe, dann lässt der Compiler sie auch drin, mit dem gesamten code.

so zum Beispiel:

void ShiftOut(char data)
{
while (LPC_SSP1SR.bits.BSY) ; /* wait until BSY becomes zero */
LPC_SSP1DR.value = data; /* shift out the data byte */
}

wenn aber data eine lokale variable ist und nicht übergeben wird, schmeisst der Compiler den gesamten Code raus.
Wenn ich aber auch die variable data als volatile definieren, dann gehts wieder. Er dürfte doch nichts wegoptimieren, da der Zugriff auf das
Bit "BSY" sich in einer volatile Strukture befindet. Damit muss er dieses doch erst lesen und darf keine Vorentscheidungen treffen und code wegoptimieren. Ich denke mal ich hab irgendwas falsch definiert in meiner Struktur.

Siro

Jaecko
21.10.2010, 18:29
Mach mal void ShiftOut() zu void ShiftOut(void), ob ers dann drin lässt

Siro
21.10.2010, 19:21
mit dem ShiftOut(void) habe ich eben versucht, aber das ändert auch nichts.

Ich habe aber völlig neue Erkenntnisse gewonnen: P R O B L E M G E L Ö S T
Ich habe mal die Optimierungen des Compilers verändert und siehe da:

bei Optimize "Balanced" geht es.
bei Optimize "Size" geht es.
bei Optimize "Speed" geht es nicht.

Aber geht nicht, stimmt hier nicht so ganz.
Er hat tatsächlich die Funktion ShiftOut rausgeschmissen, aber ....
Er hat den Code ohne Funktionsaufruf in die main schleife gepackt.
Das sieht man aber nicht im Source-Code-Fenster. Man wundert sich nur, warum die funktion niemals
aufgerufen wird und man dort auch keinen Breakpoint setzen kann.
Wenn man aber im Fenster des Assemblercodes schrittweise simuliert bzw. sich den Code ansieht,
wird man feststellen, daß dort der Code direkt eingefügt wurde.
Jetzt leuchtet es mir auch ein, da er auf "Speed" optimieren sollte, kann er natürlich den
Unterprogrammaufruf sparen, wenn er den Code gleich in die Main Schleife reinpackt.

Da muss man erstmal drauf kommen. Absolut verwirrend. Zumal man sich nicht dauernd den
Assemblercode ansieht, welchen der Compiler erzeugt. Zudem habe ich immer nach dem
Label ShiftOut gesucht, den gibts aber dann garnicht mehr im Assemblercode.
Das Problem ist also gelöst...
Ich danke Dir Jaecko, daß Du mich ermutigt hast da nochmal reinzuschauen,
obwohl ich hätt eh nicht aufgegeben...

Fazit: wenn man im C-Source-Code plötzlich keine Breakpoints mehr setzen kann,
bzw. in der Simulation bestimmte Unterprogramme "scheinbar" nicht mehr aufgerufen werden,
dann hat der Compiler sicher was "umgebaut" an der Ablaufstruktur.
Dies sieht man aber nicht im Sorce-Code sondern höchstens im Assembler-Code.

Mein Code hätte also funktioniert, ich hatte es aber garnicht erst ausprobiert, da mir die Softwaresimulation klarmachen wollte, daß meine funktion nie aufgerufen wird. Warum sollte ich also diese Software downloaden :-)

Schwere Geburt,
Siro

Jaecko
21.10.2010, 19:33
Ok... stimmt... jetzt wo man's liest, wirds klar. Der Compiler darf natürlich Funktionen als "inline" an die Stelle einfügen, wenn es Sinn macht und die eigentliche Funktion nicht verändert. Ein "volatile" ändert daran nichts.
Beim gcc gibts aber z.B. das Attribut "noinline" für Funktionen, dann wird dem Compiler hier diese Art der Optimierung verboten.

In diesem Fall war's anscheinend insgesamt schneller, den Funktionsinhalt direkt aufzurufen, als erst mal in die Funktion und danach wieder zurück zu springen.

Mit Optimierung Debuggen haut eh nur selten hin; also wenn Breakpoints nicht da oder ganz woanders sind, ist das "normal".

Siro
22.10.2010, 12:54
Danke für den Hinweis mit dem noinline.
Ja, Du hast recht, damit kann man diese Optimierung tatsächlich abschalten.
Mein Compiler von IAR hat dafür das Attribut --no_inline.
Habe mir das grad mal duchgelesen. Da wird sogar darauf hingewiesen,
daß es sehr schwierig mit dem Debuggen werden kann.

Hier der Ausschnitt aus der Hilfe:
This optimization, which is performed at optimization level High, normally reduces execution time and increases code size. The resulting code might also be difficult to debug.

Na da bin ich doch wieder ein ganzes Stück weiter gekommen...
ein schönes Wochenende allseits.
Siro