hi, ich habe eine avr applikation als frequenzzähler mit entsprechend zeitkritischem externen interrupt. bisher in assembler mit dem avr studio programmiert, dementsprechend war das interrupt-ansprech-verhalten determiniert und im datenblatt nachlesbar. bin jetzt auf avr-gcc umgestiegen um komfortabler die menüführung programmieren zu können. nun habe ich festgestellt, dass der compiler ernorm viele freiheiten hat und z.B. selbst dann noch, wenn ich meine interrupt-funktion in assembler schreibe die freiheit hat, vor der ausführung der funktion noch diverse register zu pushen und andere spässchen zu machen, sprich ich hab keine ahnung nach wieviel takten nach interruptauslösung im kompilierten programm meine interruptfunktion abgearbeitet wird. auf diese weise habe ich eine nicht einschätzbare zähler-ungenauigkeit. gibt es eine möglichkeit beim avr-gcc determiniertes interruptverhalten zu erzwingen? kann ich irgendwie bewirken, dass aus der interruptvektortabelle direkt und ohne zwischensprünge, ohne vorheriges gepushe oder sonstirgendwas mein assembler-code angesprungen wird? oder kann man irgendwie "invertiert" arbeiten und den programmkörper samt interruptvektortabelle wie gewohnt manuell in assembler programmieren und dann für bestimmte aufgaben c-funktionen einbinden? danke, dingens
Nun, das Verhalten des Compilers ist natürlich schon deterministisch. ;-) Aber das willst Du sicher gar nicht. Du willst ja wohl eigentlich eher eine ISR in Assembler. Dann tu's doch einfach. Die register usage conventions stehen in der avr-libc Doku drin (in der FAQ, genauer gesagt). Es gibt auch in Kapitelchen über reine Assemblerprogrammierung dort. Ganz davon abgesehen, ich habe auch schon Frequenzen mit dem AVR gezählt, aber je nach Lage der Meßfrequenz zur Referenzfrequenz finde ich dabei input capture oder einfaches Mitzählen der externen Frequenz deutlich praktikabler. Mit Deiner Methode dürftest Du ja keinen einzigen weiteren Interrupt in der Applikation haben um sicherzustellen, daß die ISR für den externen Interrupt wirklich immer dieselbe Bearbeitungszeit hat.
Weitere Interrupts darf es dabei eigentlich schon geben(nur die Dinger, die in GCC SIGNAL heissen, können nicht unterbrochen werden.). Allerdings hast du im Allgemeinen die Unsicherheit, dass ein mehrtaktiger Befehl(wie zum Beispiel, aber nicht nur das Anspringen einer ISR) erst zuende ausgeführt wird, bevor dein Interrupt dran ist. Unerwünschtes "Gesichere" kannst du natürlich auch nach dem Compilieren im Assembler wieder 'rauswerfen.
Wenn Du im gcc-Interrupt keine Funktion anspringst, sondern Deinen Code direkt (ohne Funktionsaufruf) reinschreibst, dann sichert gcc auch keine "überflüssigen" Register. Wenn Du dagegen eine externe Assembler-Funktion im IR aufrufst, dann hat gcc keine Kontrolle mehr und muss alles sichern. Stefan
Dann macht der das ja bis auf wenige Ausnahmen(z.B. wenn man ein Register für einen Interrupt reservieren und anderswo garnicht benutzen will) optimal. Ich nehme mal an, das mit den Funktionen bezieht sich auf externe Libraries(und nicht auf Bitschieben mit BV oder so)?
_BV() ist keine Funktion, sondern ein simpler Makro. Ja, die Aussage bezieht sich in der Tat auf weitere Funktionsaufrufe, nicht notwendig aber solche aus der Library. Auch bei Funktionen, die in der gleichen Quelldatei definiert werden, analysiert der Compiler nicht, welche Register diese Funktion tatsächlich benötigen würde, sondern geht von der pessimistischen Annahme aus, daß die gerufene Funktion alle Register, die sie per ABI verwerfen darf (call-used registers), auch ggf. benutzt. Er behandelt also eine Funktion aus der eigenen translation unit nicht anders als eine extern dazugelinkte.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.