Forum: Compiler & IDEs GCC: Aufruf mehrerer Inline-Funktionen schießt den AVR ins Nirvana


von brechbunkt (Gast)


Lesenswert?

Hallo,

ich verwende das AVR-Studio-5 von Atmel und dessen Bibliothek um per 
lokal-bus auf die GPIOs zuzugreifen. Die CPU ist der UC3.
In Atmels lib sind diese Funktionen als Inline-Funktionen beschrieben. 
Dessen Aufruf um z.B. den Eingang zu lesen sieht dann z.B. so aus:
1
#if (defined __GNUC__)
2
__attribute__((__always_inline__))
3
#endif
4
static inline int gpio_local_get_pin_value(uint32_t pin)
5
{
6
  return (AVR32_GPIO_LOCAL.port[pin >> 5].pvr >> (pin & 0x1F)) & 1;
7
}


Wie vorgeschrieben ist mein clock für den Port genauso groß wie der 
CPU-Takt. Rufe ich nun ein paar mal diese Funktionen zum Setzen, Löschen 
und Einlesen einiger Pins auf, funktioniert alles wunderbar und ich kann 
auch im Debug-Modus sehen die CPU an die richtige Stelle springt.

Füge ich nun ein paar mehr von diesen Aufrufen auf (unter anderem in 
Schleifen), macht die CPU plötzlich gar nichts mehr. Im Debug-Modus kann 
ich sehen, wie die Verbindung plötzlich bei simplen Befehlen (ein paar 
Zeilen vor den Inlinebefehlen) abreißt und die JTAG-Leitung neu 
connectet werden muss.

Ersetze ich nun diese Befehle durch die Befehle aus der Lib, läuft alles 
gut. Also so hier:
1
// das hier:
2
//gpio_local_clr_gpio_pin(CLK_PIN);
3
//wird ersetzt durch:
4
AVR32_GPIO_LOCAL.port[CLK_PIN >> 5].ovrc = 1 << (CLK_PIN & 0x1F);

Es funktioniert nun zwar, aber kann mir irgend jemand erklären warum die 
normalen Aufrufe fehl schlagen?

: Verschoben durch Moderator
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Einmal wird .pvr verwendet, dann .ovrc.

von brechbunkt (Gast)


Lesenswert?

Johann L. schrieb:
> Einmal wird .pvr verwendet, dann .ovrc.

Die beiden Beispiele sollten nur als Beispiel dienen. Verwenden tuhe ich 
.pvr, .ovrc und ovrs.

von brechbunkt (Gast)


Lesenswert?

Ich denke, dass das ganze eher weniger mit den Befehlen zu tun hat, die 
"in" der Inline-Funktion stecken. Sondern eher mit der Tatsache, dass 
der Kompiler nicht mit den Inline-Funktionen selbst zurecht kommt (also 
selbst, wenn diese gar nichts tun würden). Erklären kann ich mir es aber 
trotzdem nicht.

von Peter D. (peda)


Lesenswert?

brechbunkt schrieb:
> Es funktioniert nun zwar, aber kann mir irgend jemand erklären warum die
> normalen Aufrufe fehl schlagen?

Beide Codefragmente machen völlig verschiedene Sachen.
Das erste liest ein Register, das 2. schreibt ein (anderes) Register.

Es ist normal, daß verschiedener Code verschiedene Sachen macht. Sonst 
könnte man ja nicht programmieren.

Du müßtest schon einen compilierbaren funktionierenden und nicht 
funktionierenden Code zeigen, die beide Deiner Erwartung nach exakt das 
gleiche machen sollten.


Peter

von brechbunkt (Gast)


Lesenswert?

Ok, sorry. Ich habe mich anscheinen nicht richtig ausgedrückt.

Also für den Fall, in dem ich den Pin auf Null setzen möchte, würde ich 
die Funktion gpio_local_clr_gpio_pin() aufrufen, welche in der Lib so 
hier beschrieben ist:
1
#if (defined __GNUC__)
2
__attribute__((__always_inline__))
3
#endif
4
static inline void gpio_local_clr_gpio_pin(uint32_t pin)
5
{
6
  AVR32_GPIO_LOCAL.port[pin >> 5].ovrc = 1 << (pin & 0x1F);
7
}

Wenn ich diese Inline-Funktion mehrfach aufrufe, "hängt" sich die CPU 
wie beschrieben auf und ich kann nur noch neu connecten.

Rufe ich statt dessen den Befehl selber auf, läuft wieder alles. Ein 
Aufruf würde dann also so aussehen:
1
AVR32_GPIO_LOCAL.port[CLK_PIN >> 5].ovrc = 1 << (CLK_PIN & 0x1F);

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Na dann schau dir den erzeugten Code an — wahlweise die 
Assembler-Ausgabe des Compiler, ein vom Assembler erstelltes 
Disassamebly oder ein von objdump erstelltes Disassembly — und dir geht 
vielleicht ein Licht auf.

Von dem, was du bisher geschrieben hast, wird hier niemand den Fehler 
finden können.  Zuman deine Prosa-Beispiele wie das ursprüngliche noch 
verwiddend sind weil komplett anderer Code.

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.