Zitat Zitat von s.frings
Es hat sich inzwischen herausgestellt, dass die Verwendung von Register Variablen bei Verwendung der AVR libc unerwartete Seiteneffekte bewirkt hat.
Nö, unerwartet ist das überhaupt nicht.

Zitat Zitat von s.frings
Das Problem ist, dass ich in "meinen" Sourcen zwar ein Register reserviert habe, aber die AVR libc weiss davon nichts. Spätestens wenn man nun z.B. mit printf etwas ausgibt, passieren seltsame Dinge.

In meinem Fall kam erschwerend dazu, dass ich das Register in einer Interrupt-Routine beschrieben habe. Sobald irgendeine Library das Register anderweitig verwendet (was sehr wahrscheinlich ist), kommt es zu Fehlfunktionen.
Es ist ohne weiteres möglich globale Registervariablen zu verwenden.

Das Problem in deinem Code ist, daß das von dir definierte Register nicht global ist. Damit ein Register global ist, müssen
  • in allen Module, die die Registervariable verwenden, diese bekannt gemacht werden. Dazu schreibt man die Register-Definition zweckmässigerweise in einen Header
  • alle Module, auch die, welche die Variable nicht verwenden, werden mit -ffixed-* übersetzt (gcc). Für eine 16-Bit Registervariable in R2/R3 also -ffixed-2 -ffixed-3. Beachte, daß Bibliotheken nicht mit diesen Schaltern übersetzt wurden. GCC kann alle Register > 2 explizit verwenden, und die Register 0 und 1 verwendet er implizit. Daher kann innerhalb einer Lib-Routine diese Register verwenden.


Um globle Register, die in ISRs verwendet werden, sicher zu verwenden, gibt es also mehrere möglichkeiten:
  • Keine Lib-Funktionen verwenden, d.h. keine explizit in die Quelle schreiben.
  • Alle explizit aufgerufenen Lib-Funktionen mit SEI/CLI atomar machen
  • Eigene Variante der Libs übersetzen mit -ffixed-* wie benötigt
  • Verwendung von prologue-saves, epilogue-restores anpassen (libgcc.S anpassen)
  • Libs verwenden und sich mit einem grep o.ö. versichern, daß keine der verwendeten Lib-Funktionen auf die Register zugreift.
  • Implizit verwendete Lib-Funktionen sollten unkritisch sein. Ausnahme: prologue_saves, epilogue_restores und evtl das setjmp/longjmp-Zeug


Immerhin hast du durch den "Fehler" ein bisschen mehr über die Arbeitsweise eines Compilers gelernt

Übrigens ist es garnicht sooo viel Arbeit, ein eigenes printf zu schreiben.