Forum: Mikrocontroller und Digitale Elektronik Interrupt aus main aufrufen AVR


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von Justus Jonas (Gast)


Lesenswert?

Moin,
ich würde gerne eine Interrupt Routine auf meinem ATmega2560 per Hand 
aufrufen. Konkret geht es um den Transmit Complete interrupt, welchen 
ich gerne einmal per Hand auslösen würde.

Gruß
Justus

von Falk B. (falk)


Lesenswert?

Justus Jonas schrieb:
> ich würde gerne eine Interrupt Routine auf meinem ATmega2560 per Hand
> aufrufen. Konkret geht es um den Transmit Complete interrupt, welchen
> ich gerne einmal per Hand auslösen würde.

Das ist wenig sinnvoll. Wenn, dann musst du die Funktion im Interruopt 
in eine normale Funktion packen, die man dann aus der ISR oder dem 
normalen Programm heraus aufrufen kann. Das hat in der ISR den kleinen 
Nachteill, daß dort realtiv viele Register gesichert werden müssen, so 
um die 10. Das macht die ISR etwas langsamer. Wenn man das vermeiden 
will, muss man die Funktionalität der ISR und der normalen Funktion 
kopieren, sprich, doppelter Code an zwei Stellen im Quelltext. Nicht 
schön, aber OK.

von Wolfgang (Gast)


Lesenswert?

Justus Jonas schrieb:
> Konkret geht es um den Transmit Complete interrupt, welchen
> ich gerne einmal per Hand auslösen würde.

Such mal nach "Software Interrupt"

von c-hater (Gast)


Lesenswert?

Justus Jonas schrieb:

> ich würde gerne eine Interrupt Routine auf meinem ATmega2560 per Hand
> aufrufen.

cli
rcall <symbolischer Name des Vectors, z.B.: UTXC0addr>

Das ruft natürlich wirklich nur die ISR auf, ändert nichts am Status der 
Hardware.

von Hugo H. (hugo_hu)


Lesenswert?

Justus Jonas schrieb:
> Konkret geht es um den Transmit Complete interrupt, welchen
> ich gerne einmal per Hand auslösen würde.

Warum setzt Du nicht das entsprechende Interrupt-Flag?

von Falk B. (falk)


Lesenswert?

Hugo H. schrieb:
>> Konkret geht es um den Transmit Complete interrupt, welchen
>> ich gerne einmal per Hand auslösen würde.
>
> Warum setzt Du nicht das entsprechende Interrupt-Flag?

Weil die nur die Hardware setzen kann. Die CPU kann sie nur löschen!

"Bit 6 – TXCn: USART Transmit Complete
This flag bit is set when the entire frame in the Transmit Shift 
Register has been shifted out and there are no new data currently 
present in the transmit buffer (UDRn). The TXCn Flag bit is 
automatically cleared when a transmit complete interrupt is executed, or 
it can be cleared by writing a one to its bit location. The TXCn Flag 
can generate a Transmit Complete interrupt (see description of the 
TXCIEn bit)."

von Hugo H. (hugo_hu)


Lesenswert?

Falk B. schrieb:
> Weil die nur die Hardware setzen kann. Die CPU kann sie nur löschen!

Dann erkläre bitte mal, warum das bei einem Bit gehen soll und beim 
anderen Bit nicht:

• Bit 7 – RXCn: USART Receive Complete
This flag bit is set when there are unread data in the receive buffer 
and cleared when the receive buffer is empty
(that is, does not contain any unread data). If the Receiver is 
disabled, the receive buffer will be flushed and consequently
the RXCn bit will become zero.

The RXCn Flag can be used to generate a Receive Complete interrupt 
(see
description of the RXCIEn bit).

• Bit 6 – TXCn: USART Transmit Complete
This flag bit is set when the entire frame in the Transmit Shift 
Register has been shifted out and there are no new
data currently present in the transmit buffer (UDRn). The TXCn Flag bit 
is automatically cleared when a transmit
complete interrupt is executed, or it can be cleared by writing a one to 
its bit location.

The TXCn Flag can generate a Transmit Complete interrupt (see 
description of the TXCIEn bit).

Soll das nur am "Sprachgefüge" liegen? Wenn ich Spaß dran habe probiere 
ich es mal aus :-)

: Bearbeitet durch User
von Maxe (Gast)


Lesenswert?

Hugo H. schrieb:
> The RXCn Flag can be used to generate a Receive Complete interrupt
> (see
> description of the RXCIEn bit).

> Soll das nur am "Sprachgefüge" liegen?

Can be used heisst, dass das Bit intern mit der Interrupt-Einrichtung 
verkabelt ist und es 'can' ein Interrupt-Enable-Bit gesetzt werden, 
sodass jenes Bit den Interrupt ausloest.

von Stefan F. (Gast)


Lesenswert?

Bei 8 Bit AVR macht der RETI Befehl genau das gleiche, wie RET. Deswegen 
kann man theoretisch Interrupthandler wie ganz normale Funktionen 
aufrufen. Ich habe allerdings nicht herausgefunden, wie man das in C 
anstellt.

von Falk B. (falk)


Lesenswert?

Stefan F. schrieb:
> Bei 8 Bit AVR macht der RETI Befehl genau das gleiche, wie RET.

Falsch. RETI setzt das I-Bit und ermöglicht weitere Interrupts. RET tut 
das nicht.

von S. Landolt (Gast)


Lesenswert?

> Bei 8 Bit AVR macht der RETI Befehl genau das gleiche, wie RET.

?

RETI behaves differently in AVRe, AVRxm, and AVRxt devices. In the AVRe 
series of devices, the Global Interrupt Enable bit is cleared by 
hardware once an interrupt occurs, and this bit is set when RETI is 
executed. In the AVRxm and AVRxt devices, RETI will not modify the 
Global Interrupt Enable bit in SREG since it is not cleared by hardware 
while entering ISR. This bit should be modified using SEI and CLI 
instructions when needed.

von Falk B. (falk)


Lesenswert?

Hugo H. schrieb:
>> Weil die nur die Hardware setzen kann. Die CPU kann sie nur löschen!
>
> Dann erkläre bitte mal, warum das bei einem Bit gehen soll und beim
> anderen Bit nicht:

Erklär mal, wie du das Bit setzen willst, wenn es heißt

"The TXCn Flag bit is automatically cleared when a transmit complete 
interrupt is executed, or it can be cleared by writing a one to its bit 
location."

von S. Landolt (Gast)


Lesenswert?

Hugo Hurtig schrieb:
> Wenn ich Spaß dran habe probiere ich es mal aus

Wäre nicht das umgekehrte Vorgehen angebracht - wenn man sich unsicher 
ist, erst ausprobieren, und danach sich hier äußern?

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

S. Landolt schrieb:
> ?
> RETI behaves differently in AVRe, AVRxm, and AVRxt devices.

Da hast du jetzt ein paar spezielle AVR Serien genannt, die ich dabei 
nicht im Sinn hatte. Ehrlich gesagt sagen mir diese drei Abkürzungen 
nichts. Wo hast du die her, dass ich da mal nachlesen kann?

Ob durch den Funktionsaufruf das globale I Flag gesetzt wird, spielt bei 
dem angefragten Anwendungsfall keine Rolle. Denn es war vorher an und 
soll auch nachher an sein (nehme ich an).

Die Screenshots stammen aus 
https://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

> ein paar spezielle AVR Serien

?

AVRe sind die 'normalen von früher', AVRxt die 'neuen' - was ist an 
denen "speziell"?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Stefan F. schrieb:
> Ich habe allerdings nicht herausgefunden, wie man das in C
> anstellt.

Ganz einfach:
1
  cli();
2
  USART0_TX_vect();

Der Funktionsname ist derselbe, der auch in der Definition der ISR an
das ISR-Makro übergeben wird.

Vor dem Aufruf sperrt man sinnvollerweise die Interrupts, wie dies auch
beim Auslösen eines echten Interrupts automatisch getan wird. Durch den
RETI am Ende der ISR werden die Interrupts wieder freigeschaltet, was
hier vermutlich auch gewünscht wird.

von EAF (Gast)


Lesenswert?

Justus Jonas schrieb:
> ich würde gerne eine Interrupt Routine auf meinem ATmega2560 per Hand
> aufrufen.
AVRs kennen keine Software Interrupts!

Justus Jonas schrieb:
> Konkret geht es um den Transmit Complete interrupt, welchen
> ich gerne einmal per Hand auslösen würde.
Auf ein kaputtes Konzept, einen solchen Flicken setzen zu wollen, ist 
99.999% der Fälle eine dumme Idee.


Mein Rat:
Mindestens 2 Schritte zurück gehen und neu nachdenken.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Yalu X. schrieb:
>   USART0_TX_vect();

Das habe ich probiert, aber zumindest im Simulator klappt das nicht. 
Dann habe ich zum ATmega328p gewechselt, aber auch damit klappte es 
nicht. Siehe Screenshot. Wenn ich dort noch einen schritt weiter 
debugge, beginnt das Programm wieder am Anfang von main().

Offenbar springt er an die falsche Adresse. Man sieht das auch im *.lss:
1
00000080 <ISR>:
2
#include <avr/io.h>
3
4
ISR(USART_TX_vect) // ISR(USART_TX_vect) 
5
{
6
    PORTB |= 1; // PB0 auf HIGH
7
  80:  e5 e2         ldi  r30, 0x25  ; 37
8
  82:  f0 e0         ldi  r31, 0x00  ; 0
9
  84:  80 81         ld  r24, Z
10
  86:  81 60         ori  r24, 0x01  ; 1
11
  88:  80 83         st  Z, r24
12
}
13
  8a:  08 95         ret
14
15
0000008c <main>:
16
17
18
int main() 
19
{
20
    DDRB |= 3;  // PB0 und PB1: Ausgang
21
  8c:  e4 e2         ldi  r30, 0x24  ; 36
22
  8e:  f0 e0         ldi  r31, 0x00  ; 0
23
  90:  80 81         ld  r24, Z
24
  92:  83 60         ori  r24, 0x03  ; 3
25
  94:  80 83         st  Z, r24
26
    USART_TX_vect();
27
  96:  0e 94 3e 00   call  0x7c  ; 0x7c <__bad_interrupt>
28
  PORTB |= 2; // PB1 auf HIGH
29
  9a:  e5 e2         ldi  r30, 0x25  ; 37
30
  9c:  f0 e0         ldi  r31, 0x00  ; 0
31
  9e:  80 81         ld  r24, Z
32
  a0:  82 60         ori  r24, 0x02  ; 2
33
  a2:  80 83         st  Z, r24
34
}
35
  a4:  80 e0         ldi  r24, 0x00  ; 0
36
  a6:  90 e0         ldi  r25, 0x00  ; 0
37
  a8:  08 95         ret
38
39
000000aa <_exit>:
40
  aa:  f8 94         cli
41
42
000000ac <__stop_program>:
43
  ac:  ff cf         rjmp  .-2        ; 0xac <__stop_program>


Anstatt "call 0x7c" würde ich hier "call 0x80" erwarten. Ich habe mit 
-O1 compiliert.

von Falk B. (falk)


Lesenswert?

Yalu X. schrieb:
> Ganz einfach:
>   cli();
>   USART0_TX_vect();

Das mag der Compiler nicht 8-0
1
#define F_CPU 8000000UL
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
7
int main(void)
8
9
{
10
    DDRB |= (1<<DDB1);  //PORTB=0x00;
11
12
    USART_TX_vect();
13
14
    while (1) 
15
    {
16
        PORTB |= (1<<PORTB1);
17
        _delay_ms(50);
18
        PORTB &= ~ (1<<PORTB1);
19
        _delay_ms(50);
20
    }
21
}
22
23
ISR(USART_TX_vect) {
24
    PORTB ^= (1<<PORTB1);
25
}
1
../test_simulation.c: In function 'main':
2
../test_simulation.c:12: warning: implicit declaration of function '__vector_20'
3
../test_simulation.c: At top level:
4
../test_simulation.c:23: warning: conflicting types for '__vector_20'
5
../test_simulation.c:12: warning: previous implicit declaration of '__vector_20' was here

von Stefan F. (Gast)


Lesenswert?

Du musst die ISR vor main() platzieren.

von Sebastian (Gast)


Lesenswert?

Stefan F. schrieb:
> Anstatt "call 0x7c" würde ich hier "call 0x80" erwarten.

Auf die Auflösung dieses Rätsels bin ich gespannt.

LG, Sebastian

von S. Landolt (Gast)


Lesenswert?

> ... falsche Adresse. Man sieht das auch im *.lss

Also bei mir stimmt es im .lss-File.
  Zu meiner C-Umgebung kann ich aber leider nichts sagen, die ist 
irgendwie zusammengestoppelt.

von Stefan F. (Gast)


Lesenswert?

Ich habe unter Linux den gleichen Fehler:
1
stefan@stefanspc:~/Downloads$ cat > test.c
2
#include <avr/io.h>
3
4
ISR(USART_TX_vect) // ISR(USART_TX_vect) 
5
{
6
    PORTB |= 1; // PB0 auf HIGH
7
}
8
9
10
int main() 
11
{
12
    DDRB |= 3;  // PB0 und PB1: Ausgang
13
    USART_TX_vect();
14
  PORTB |= 2; // PB1 auf HIGH
15
}
16
17
stefan@stefanspc:~/Downloads$ avr-gcc -Wall -gdwarf-2 -std=gnu99 -O1 -mmcu=atmega328p test.c
18
test.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
19
 ISR(USART_TX_vect) // ISR(USART_TX_vect) 
20
 ^
21
test.c: In function ‘ISR’:
22
test.c:3:1: warning: type of ‘__vector_20’ defaults to ‘int’ [-Wimplicit-int]
23
test.c:6:1: warning: control reaches end of non-void function [-Wreturn-type]
24
 }
25
 ^
26
stefan@stefanspc:~/Downloads$ avr-objdump -h -S a.out
27
28
a.out:     file format elf32-avr
29
30
...
31
32
0000007c <__bad_interrupt>:
33
  7c:  0c 94 00 00   jmp  0  ; 0x0 <__vectors>
34
35
00000080 <ISR>:
36
#include <avr/io.h>
37
38
ISR(USART_TX_vect) // ISR(USART_TX_vect) 
39
{
40
    PORTB |= 1; // PB0 auf HIGH
41
  80:  28 9a         sbi  0x05, 0  ; 5
42
}
43
  82:  08 95         ret
44
45
00000084 <main>:
46
47
48
int main() 
49
{
50
    DDRB |= 3;  // PB0 und PB1: Ausgang
51
  84:  84 b1         in  r24, 0x04  ; 4
52
  86:  83 60         ori  r24, 0x03  ; 3
53
  88:  84 b9         out  0x04, r24  ; 4
54
    USART_TX_vect();
55
  8a:  0e 94 3e 00   call  0x7c  ; 0x7c <__bad_interrupt>
56
  PORTB |= 2; // PB1 auf HIGH
57
  8e:  29 9a         sbi  0x05, 1  ; 5
58
}
59
  90:  80 e0         ldi  r24, 0x00  ; 0
60
  92:  90 e0         ldi  r25, 0x00  ; 0
61
  94:  08 95         ret
62
63
00000096 <_exit>:
64
  96:  f8 94         cli
65
66
00000098 <__stop_program>:
67
  98:  ff cf         rjmp  .-2        ; 0x98 <__stop_program>
68
69
stefan@stefanspc:~/Downloads$ avr-gcc --version
70
avr-gcc (GCC) 5.4.0
71
Copyright (C) 2015 Free Software Foundation, Inc.
72
This is free software; see the source for copying conditions.  There is NO
73
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

von Falk B. (falk)


Lesenswert?

Stefan F. schrieb:
> Du musst die ISR vor main() platzieren.

Ahhhh! Manchmal ist es so einfach!
1
00000000 <__vectors>:
2
   0:  0c 94 34 00   jmp  0x68  ; 0x68 <__ctors_end>
3
   4:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
4
   8:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
5
   c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
6
  10:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
7
  14:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
8
  18:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
9
  1c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
10
  20:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
11
  24:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
12
  28:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
13
  2c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
14
  30:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
15
  34:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
16
  38:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
17
  3c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
18
  40:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
19
  44:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
20
  48:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
21
  4c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
22
  50:  0c 94 40 00   jmp  0x80  ; 0x80 <__vector_20>
23
  54:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
24
  58:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
25
  5c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
26
  60:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
27
  64:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
28
29
00000068 <__ctors_end>:
30
  68:  11 24         eor  r1, r1
31
  6a:  1f be         out  0x3f, r1  ; 63
32
  6c:  cf ef         ldi  r28, 0xFF  ; 255
33
  6e:  d8 e0         ldi  r29, 0x08  ; 8
34
  70:  de bf         out  0x3e, r29  ; 62
35
  72:  cd bf         out  0x3d, r28  ; 61
36
  74:  0e 94 52 00   call  0xa4  ; 0xa4 <main>
37
  78:  0c 94 68 00   jmp  0xd0  ; 0xd0 <_exit>
38
39
0000007c <__bad_interrupt>:
40
  7c:  0c 94 00 00   jmp  0  ; 0x0 <__vectors>
41
42
00000080 <__vector_20>:
43
ISR(USART_TX_vect) {
44
  80:  1f 92         push  r1
45
  82:  0f 92         push  r0
46
  84:  0f b6         in  r0, 0x3f  ; 63
47
  86:  0f 92         push  r0
48
  88:  11 24         eor  r1, r1
49
  8a:  8f 93         push  r24
50
  8c:  9f 93         push  r25
51
    PORTB ^= (1<<PORTB1);
52
  8e:  85 b1         in  r24, 0x05  ; 5
53
  90:  92 e0         ldi  r25, 0x02  ; 2
54
  92:  89 27         eor  r24, r25
55
  94:  85 b9         out  0x05, r24  ; 5
56
}
57
  96:  9f 91         pop  r25
58
  98:  8f 91         pop  r24
59
  9a:  0f 90         pop  r0
60
  9c:  0f be         out  0x3f, r0  ; 63
61
  9e:  0f 90         pop  r0
62
  a0:  1f 90         pop  r1
63
  a2:  18 95         reti
64
65
000000a4 <main>:
66
67
68
int main(void)
69
70
{
71
    DDRB |= (1<<DDB1);  //PORTB=0x00;
72
  a4:  21 9a         sbi  0x04, 1  ; 4
73
74
    USART_TX_vect();
75
  a6:  0e 94 40 00   call  0x80  ; 0x80 <__vector_20>
76
    milliseconds can be achieved.
77
 */

Passt. Die ISR liegt auf Adresse 0x80, und der rcall ruft sie auf. Ganz 
normal. Es wird NICHT der Interruptvektor __vector_20 auf Adresse 0x50 
aufgerufen! In ASM kann man das machen, bringt aber auch nix extra.

von Hugo H. (hugo_hu)


Lesenswert?

S. Landolt schrieb:
> Wäre nicht das umgekehrte Vorgehen angebracht - wenn man sich unsicher
> ist, erst ausprobieren, und danach sich hier äußern?

Ja - hätte ich mal besser gemacht. Ich gelobe Besserung :-)

von Stefan F. (Gast)


Lesenswert?

Falk B. schrieb:
> Passt. Die ISR liegt auf Adresse 0x80, und der rcall ruft sie auf. Ganz
> normal.

Warum zum Teufel geht das bei dir, und bei mir nicht?

von S. Landolt (Gast)


Lesenswert?

> Passt.

Genau - funktioniert hier realiter.

von Falk B. (falk)


Lesenswert?

Stefan F. schrieb:
> Ich habe unter Linux den gleichen Fehler:

Da fehlt das #include "avr/interrupt.h"

von Stefan F. (Gast)


Lesenswert?

Falk B. schrieb:
> Da fehlt das #include "avr/interrupt.h"

Oh Mann, ja genau das war bei mir der Fehler.

Also halten wir fest: ISR kann man einfach wie normale Funktionen 
aufrufen.

von S. Landolt (Gast)


Lesenswert?

Stefan Frings schrieb:
> Oh Mann, ja genau das war bei mir der Fehler.

Merkwürdig: bei mir hier bringt der Compiler drei Warnungen, wenn ich 
das '#include <avr/interrupt.h>' weglasse - bei Ihnen nicht?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Warum nicht einfach "normalen" Code schreiben?
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
void machwas (void);
5
6
ISR (USART_TX_vect, ISR_FLATTEN)
7
{
8
    machwas();
9
}
10
11
int main (void)
12
{
13
    machwas();
14
}
15
16
void machwas (void)
17
{
18
    __asm ("nop");
19
    // ...
20
}

Falls "machwas" in der ISR nicht geinlinet werden soll, dann einfach 
flatten weglassen.

von Stefan F. (Gast)


Lesenswert?

S. Landolt schrieb:
> Merkwürdig: bei mir hier bringt der Compiler drei Warnungen, wenn ich
> das '#include <avr/interrupt.h>' weglasse - bei Ihnen nicht?

Siehe

Stefan F. schrieb:
Ausgaben des Compilers

Ich habe die Warnungen schon gesehen, aber nicht erkannt, was deren 
Ursache ist.

von S. Landolt (Gast)


Lesenswert?

> Siehe ...

Da ich ausschließlich unter Windows arbeite, hatte ich mir Ihre 
Linux-Version gar nicht erst angeschaut.

von W.S. (Gast)


Lesenswert?

Stefan F. schrieb:
> Also halten wir fest: ISR kann man einfach wie normale Funktionen
> aufrufen.

Man kann auch im 10.Stock aus dem Fenster springen. Ratsam ist beides 
nicht.

Mal ganz deutlich gesagt: Interrupt-Services sind NICHT dafür gemacht, 
im Programm von irgendwo her aufgerufen zu werden - auch wenn es formal 
gehen sollte. Und wer da meint, daß er es dennoch braucht, der hat an 
anderer Stelle etwas ganz verkehrt gemacht.

W.S.

von c-hater (Gast)


Lesenswert?

Stefan F. schrieb:

> Also halten wir fest: ISR kann man einfach wie normale Funktionen
> aufrufen.

Ja. Sinnvoll ist das aber praktisch nie. I.d.R. hantieren ISRs ja 
irgendwie mit der Hardware, die den Interrupt ausgelöst hat. Und deren 
Status passt halt nicht. D.h.: es ist relativ wahrscheinlich, dass die 
ISR "anders" läuft, als im echten Interruptfall.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Früher (TM)  hätte man eine Rücksprungadresse auf den Stack gelegt und 
dann einen Sprung auf die Interrupt-Routine gemacht. Aber das waren noch 
6502-Tricksereien.

von Stefan F. (Gast)


Lesenswert?

Christoph db1uq K. schrieb:
> Früher (TM)  hätte man eine Rücksprungadresse auf den Stack gelegt und
> dann einen Sprung auf die Interrupt-Routine gemacht. Aber das waren noch
> 6502-Tricksereien.

Nichts anderes passiert beim direkten Aufruf in C.

von Peter D. (peda)


Lesenswert?

Justus Jonas schrieb:
> Konkret geht es um den Transmit Complete interrupt, welchen
> ich gerne einmal per Hand auslösen würde.

Die Frage ist, warum man sowas überhaupt machen sollte.
Er wird doch nur benötigt, um bei RS-485 die Richtung des Transceivers 
umzuschalten. Initial läßt man den Transceiver erstmal auf Empfang.
Für das Senden selber nimmt man ja den USART Data Register Empty 
Interrupt.

von c-hater (Gast)


Lesenswert?

Peter D. schrieb:

[TXC-Interrupt]
> Er wird doch nur benötigt, um bei RS-485 die Richtung des Transceivers
> umzuschalten.

Das mag die einzige nützliche Anwendung sein, die DU kennst, aber es 
gibt noch etliche mehr...

von W.S. (Gast)


Lesenswert?

Stefan F. schrieb:
> Nichts anderes passiert beim direkten Aufruf in C.

Sei froh, daß es sich hier um einen AVR handelt. Bei anderen 
Architekturen sieht sowas völlig anders aus, da wird ggf. auch der Stack 
gewechselt, der Programmlevel von User auf System oder Supervisor 
gewechselt, beim ARM7 ggf. auch Code (Arm/Thumb) und einige Register 
(Schattenregister) gewechselt usw.

Von wegen nichts ...
Eben genau deshalb gibt es eine Reihe von Randbedingungen bei der 
Verwendung von C, die eine saubere Trennung zwischen dem Grundprogramm 
und den ISR erfordern. Und bei kleineren Plattformen (PIC, 8051 usw.) 
hat man oftmals keine reentranten Funktionen, weil lokale Variablen eben 
NICHT auf dem Stack stehen und RAM nur sehr begrenzt vorhanden ist, da 
sollte man sowas auch besser bleiben lassen.

Und Leute, die offenbar mit den AVR aufgewachsen sind, haben sich dann 
solche schlechten Manieren angewöhnt. Ja auch das ubiquitäre Verwenden 
von DI/EI gehört dazu.

W.S.

von Stefan F. (Gast)


Lesenswert?

W.S. schrieb:
> Sei froh, daß es sich hier um einen AVR handelt. Bei anderen
> Architekturen sieht sowas völlig anders aus

Ich weiss. Deswegen hatte ich das (siehe oben) extra nochmal 
ausprobiert, bevor ich hier Blödsinn verzapfe.

Manche Dinge sind eben Hardware spezifisch. Man kann nicht alles völlig 
generisch programmieren.

von c-hater (Gast)


Lesenswert?

Stefan F. schrieb:

> Manche Dinge sind eben Hardware spezifisch. Man kann nicht alles völlig
> generisch programmieren.

Das allerdings ist, was die nixwissenden C-Apologeten immer wieder 
versprechen, also inbesondere die, die nie nahe an der Hardware 
programmieren...

Die richtigen C-Programmierer wissen natürlich sehr wohl, dass es da 
eine Grenze gibt, die sich auch in C nicht wirklich überwinden läßt. Es 
läuft dann halt auf die allseits beliebten #ifdef-Orgien hinaus, wenn 
man nahe an der Hardware irgendwas "portabel" programmieren will.

Ich halte diese Art der "Portabilität" allerdings sowieso für einen 
ziemlichen Euphemismus. Wie wohl jeder, der beim Kompilieren solchen 
Codes in den #else-Zweig dieser #ifdef-Orgien gelangt...

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.