Du machst eine naked Funktion, siehe auch das Beispiel bei GCC im Abschnitt Interrupts.
GCC macht daraus:Code:#include <avr/io.h> uint8_t register G_cLastData asm ("r2"); void __attribute__ ((naked)) SIG_INTERRUPT0 (void) { // Port D __asm__ __volatile ( "in r2, %0" "\n\t" "reti" : : "M" (_SFR_IO_ADDR (PORTD)) ); }Code:.global __vector_1 .type __vector_1, @function __vector_1: in r2, 24 reti
Wichtig ist, daß in ALLEN deinen Modulen R2 so als Register deklariert ist, damit GCC nicht auf die Idee kommt, nach R2 Werte zu allokieren. Das gilt auch für Module, die G_cLastData nicht verwenden!
Oder du must anfangen, zu sichern mit push/pop:
Das führt zuCode:#include <avr/io.h> uint8_t volatile G_cLastData; void __attribute__ ((naked)) SIG_INTERRUPT0 (void) { // Port D __asm__ __volatile ( "push r2" "\n\t" "in r2, %1" "\n\t" "sts %2, r2" "\n\t" "pop r2" "\n\t" "reti" : : "M" (_SFR_IO_ADDR (PORTD)) : "i" (&G_cLastData) ); }
Wichtig ist, daß dabei keine Instruktion den Status ändert (SREG). Daß R2 verwendet wird, braucht GCC nicht zu interessieren. Falls man GCC die Register-Allokierung überlässt, weiß man nicht, wofür er sich entscheidet. Und da GCC kein Epilog machen soll (naked), geht das auch gar nicht, weil das Register nicht wieder hergestellt werden könnte. Daher wird auch das Speichern in die Variable im Asm gemacht.Code:.global __vector_1 .type __vector_1, @function __vector_1: push r2 in r2, 18 sts G_cLastData, r2 pop r2 reti
Zu den Zeiten der ISR-Befehlen muss noch die Interrupt-Respond-Zeit hinzugezählt werden (IRQ-Latenz) und die Zeit für den Sprung aus der Vektor-Tabelle, sie ist also davon abhängig, welche IRQs sonst noch aktiv sind und wie deren ISRs aussehen.






Zitieren

Lesezeichen