.. dass beim Interrupt der Stack gesichert und anschliessend zurück geschrieben werden muss .. erscheint mir etwas hoch ..
Hallo PICman - sorry, GeoMan.
Ich kenn mich mit den PICs nicht aus, ich programmiere Atmels in C. Aber vielleicht gibts bei PIC ähnliche Dinge. Ich bekomme z.B. mit dem Compilat noch ne so genannte LLS-Datei. In der ist eine Art Assemblerlisting mit Maschinencode, dazwischen eingefügtem C-Code und mit mancherlei organisatorischen Daten zum Compilat enthalten. Als Beispiel mal eine vollständige ISR zum USART-Empfang
Code:
ISR( USART0_RX_vect )
{
148: 1f 92 push r1
14a: 0f 92 push r0
14c: 0f b6 in r0, 0x3f ; 63
14e: 0f 92 push r0
150: 0b b6 in r0, 0x3b ; 59
152: 0f 92 push r0
154: 11 24 eor r1, r1
156: 8f 93 push r24
158: 9f 93 push r25
15a: ef 93 push r30
15c: ff 93 push r31
u8 i = rx_in;
15e: 90 91 20 0f lds r25, 0x0F20
ROLLOVER( i, RX0_SIZE );
162: 9f 5f subi r25, 0xFF ; 255
164: 97 fd sbrc r25, 7
166: 90 e0 ldi r25, 0x00 ; 0
if( i == rx_out ){ // buffer overflow
168: 80 91 21 0f lds r24, 0x0F21
16c: 98 17 cp r25, r24
16e: 31 f4 brne .+12 ; 0x17c <__vector_20+0x34>
URX0_IEN = 0; // disable RX interrupt
170: 80 91 c1 00 lds r24, 0x00C1
174: 8f 77 andi r24, 0x7F ; 127
176: 80 93 c1 00 sts 0x00C1, r24
17a: 0a c0 rjmp .+20 ; 0x190 <__vector_20+0x48>
return;
}
rx_buff[rx_in] = UDR0;
17c: e0 91 20 0f lds r30, 0x0F20
180: f0 e0 ldi r31, 0x00 ; 0
182: 80 91 c6 00 lds r24, 0x00C6
186: e0 56 subi r30, 0x60 ; 96
188: f1 4f sbci r31, 0xF1 ; 241
18a: 80 83 st Z, r24
rx_in = i;
18c: 90 93 20 0f sts 0x0F20, r25
}
190: ff 91 pop r31
192: ef 91 pop r30
194: 9f 91 pop r25
196: 8f 91 pop r24
198: 0f 90 pop r0
19a: 0b be out 0x3b, r0 ; 59
19c: 0f 90 pop r0
19e: 0f be out 0x3f, r0 ; 63
1a0: 0f 90 pop r0
1a2: 1f 90 pop r1
1a4: 18 95 reti
Hier siehst Du diesen gesamten Overhead an pushs und pops, zugehörigen Registerbewegungen und dem reti; der Jump nach "ISR( USART0.."
50:...0c 94 a4 00.....jmp.....0x148.....; 0x148 <__vector_20>
ist hier aber noch NICHT erfasst. Aus den entsprechenden Befehlen und dem Datenblatt des Controllers kann man nun (bei Atmel und GCC) den tatsächlichen Zeitbedarf in Einheiten der CPUclocks (siehe unten: #Clocks) genau ausrechnen:
Code:
DATA TRANSFER INSTRUCTIONS
Mnemonics Operands Description .............. Operation .. Flags .. #Clocks
...
PUSH .... Rr ..... Push Register on Stack ... STACK ← Rr . None .... 2
POP ..... Rd ..... Pop Register from Stack .. Rd ← STACK . None .... 2
RETI ..............Interrupt Return ......... PC ← STACK .. I ...... 4
Nachtrag:
Zitat von
Doku zu m328/p, Atmel-42735B
..
When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The
user software can write logic one to the I-bit to enable nested interrupts.
..
Man kann bei den Atmels in einer ISR das Interruptbit explizit auf "erlaube Interrupts" setzen. Ich habe hin und wieder zwar nested interrupts in meinen Quellen - aber die sind schon ein heisses Eisen.
Lesezeichen