externer interrupt

#4996791
Lesenswert?

Hi

0,063µs / Takt -> ~20 Takte

Sprung zur ISR 2/3 Takte
Setzen des IO ebenfalls um den Dreh

Bis auf dem PC-Int reagiert wird, vergehen auch 1/2 Takte im Simulator

Wie viele Takte hattest Du erwartet?
Was spricht der Simulator, wie viele Takte es sein sollten?
Womit hast Du die 1,25µs ermittelt?
Reproduzierbar?

MfG
Gast #4996834
Lesenswert?

Hier als Anhang die Oszi-Aufnahme und der Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 16000000UL
4
#include <util/delay.h>
5

6
int main(void)
7
{
8

9
  DDRB = 0xff;                        
10
  DDRC = 0xff; 
11
  PORTD = 0xff;                      
12
  GICR |= (1 << INT1);               
13
  MCUCR |= (1 << ISC10)|(1<<ISC11);              
14
  sei();  
15
                            
16
  while(1){  
17
  PORTC=0xff;
18
  _delay_ms(1);
19
  PORTC=0x00;
20
  _delay_ms(1);
21

22
}                                                    
23
}
24

25
ISR(INT1_vect)
26
{
27
  PORTB=0xff;
28
  PORTB=0x00;
29
}

Ein Signal des PortC wird dabei zum Test auf den INT1/PD3 gegeben.
Zum Oszibild: blau PortC und gelb PortB
Angehängte Dateien:
Gast #4996894
Lesenswert?

fixi schrieb:

> An meinem atmega8 löse ich einen externen interrupt aus. In der ISR wird
> lediglich ein Ausgang auf high gesetzt (1 Zeile Code). Die Reaktionszeit
> beträgt bei 16MHz ca 1,25 Mikrosekunden. Woran liegt das?

Schlechte Programmierung, falsche Sprache.

> Gibt es eine
> Möglichkeit das Ganze etwas zu beschleunigen?

Klar: Assembler. Damit ist bei Interruptsteuerung ein progagation delay 
für eine einzelne Flanke von 6 Takten möglich, bei einer Endlosschleife 
sind's sogar nur 4.

Sprich, bei 16MHz: 375 bzw. 250ns.
#4996966
Lesenswert?

fixi schrieb:
> Ich habe so an die 5-6 Takte erwartet, sprich ca 400ns. Ist das
> realistisch?

Absolut nein.
Der AVR ist ein RISC, da sind 50 Takte nichts.
Schon der nackte Interrupteinsprung + Return kostet 10 Takte. Dann noch 
Prolog, Epilog (Register retten).
Auch muß man damit rechnen, daß ja gerade eine anderer Interrupt in 
Arbeit sein könnte. Assembler ist daher nur selten zielführend.
Kalkuliere nen Interrupthandler mit ~200 Takten, das reicht für die 
meisten kleineren Sachen.
Gast #4997014
Lesenswert?

Peter D. schrieb:
> m.n. schrieb:
>> Sofern keine anderen Interrupts aktiv
>> sind

und weiter zitiert: ... oder diese passend programmiert werden.
Wenn man hohe Interruptlast im System hat, muß man sich auch ein paar 
Gedanken über die Prioritäten machen.
Nur sehe ich diese Probleme beim TO überhaupt nicht.

Wilhelm M. schrieb:
> Auf den Prolog und Epilog kannst Du durch das Attribute ISR_NAKED
> verzichten.
> Dann werden r0, r1 und SREG (und evtl. andere Register) nicht gesichert.

Das ist selbst schon bei dieser einfachen ISR tödlich!
Transparente und schnelle ISRs programmiert man in Assembler, wo nur die 
Register gerettet werden, die unbedingt gebraucht werden mit SREG an 
allererster Stelle.

Aber gut, dazu ist schon an anderen Stellen bis zum Abwinken diskutiert 
worden.
Gast #4997078
Lesenswert?

Wie so oft:

Vielleicht ist es auch an der Zeit zu erörtern was eigentlich
das Ziel des ganzen Unternehmens sein soll, denn die schnelle
ISR zu schreiben soll ja wohl keinen reinen Selbstzweck
erfüllen.

Sonst werden hier ja nur reihenweise die Pferde scheu gemacht
für nix und wieder nix ....
#4997093
Lesenswert?

m.n. schrieb:

> Das ist selbst schon bei dieser einfachen ISR tödlich!

Nö. Aus
1
ISR(TIMER0_COMPA_vect, ISR_NAKED) {
2
    PORTB = 0xff;
3
    reti();
4
}

wird
1
.global __vector_14
2
        .type   __vector_14, @function
3
__vector_14:
4
/* prologue: naked */
5
/* frame size = 0 */
6
/* stack size = 0 */
7
.L__stack_usage = 0
8
        ldi r24,lo8(-1)  ;  tmp43,
9
        out 0x5,r24      ;  MEM[(volatile uint8_t *)37B], tmp43
10
        reti
11
/* epilogue start */
12
/* #NOAPP */
13
        .size   __vector_14, .-__vector_14
Gast #4997172
Lesenswert?

Peter D. schrieb:
> Und falls doch, dann ist ein ATmega8 mit 8kB Flash für ein <100Byte
> Progrämmchen leicht oversized.

Wenn es um den eigentlichen Sinn der Übung geht (es soll ja
keine Übung sein?) wird es sehr schnell sehr ruhig.

Eine oft gemachte Erfahrung hier ....

fixi schrieb:
> Kann jemand meinen Code so umschreiben, dass die Reaktionszeit besser
> wird?
#4997189
Lesenswert?

Arduinoquäler schrieb:
> Wie so oft:
>
> Vielleicht ist es auch an der Zeit zu erörtern was eigentlich
> das Ziel des ganzen Unternehmens sein soll, denn die schnelle
> ISR zu schreiben soll ja wohl keinen reinen Selbstzweck
> erfüllen.
>
> Sonst werden hier ja nur reihenweise die Pferde scheu gemacht
> für nix und wieder nix ....

Finde ich nicht! Es ist ein MCVE, das ausreicht. Und ein klare Frage.
Gast #4997327
Lesenswert?

Wilhelm M. schrieb:
> Wohl kaum! Schon mal gegoogelt: MCVE code -> erster Eintrag.

Zu deiner eigenen Welt gehört dazu dass du es dem Suchenden
überlässt wie er sucht.

Also:  MCVE --> Malaysia Commercial Vehicle Expo

Zu deiner eigenen Welt gehört auch dazu dass du ohne Not
irgedwelche Abkürzungen verwendest die kein Schwein kennt.
#4997330
Lesenswert?

m.n. schrieb:
> Wilhelm M. schrieb:
>> Nö.
>
> Und Du meinst, man könne R24 mal eben so zerschießen?

In diesem, sehr speziellen Fall ist das aber kein Problem! Schau Dir 
hast Listing genau an:
1
  .file  "bm99a.c"
2
__SP_H__ = 0x3e
3
__SP_L__ = 0x3d
4
__SREG__ = 0x3f
5
__tmp_reg__ = 0
6
__zero_reg__ = 1
7
  .section  .text.startup,"ax",@progbits
8
.global  main
9
  .type  main, @function
10
main:
11
/* prologue: function */
12
/* frame size = 0 */
13
/* stack size = 0 */
14
.L__stack_usage = 0
15
  ldi r24,lo8(-1)
16
  out 0x4,r24
17
  out 0x7,r24
18
  out 0xb,r24
19
  in r24,0x35
20
  ori r24,lo8(12)
21
  out 0x35,r24
22
/* #APP */
23
 ;  32 "/home/lmeier/Projekte/wmucpp/doc/bmcpp99/bm99a.c" 1
24
  sei
25
 ;  0 "" 2
26
/* #NOAPP */
27
  ldi r24,lo8(-1)
28
.L2:
29
  out 0x8,r24
30
  ldi r30,lo8(3999)
31
  ldi r31,hi8(3999)
32
1:  sbiw r30,1
33
  brne 1b
34
  rjmp .
35
  nop
36
  out 0x8,__zero_reg__
37
  ldi r30,lo8(3999)
38
  ldi r31,hi8(3999)
39
1:  sbiw r30,1
40
  brne 1b
41
  rjmp .
42
  nop
43
  rjmp .L2
44
  .size  main, .-main
45
  .text
46
.global  __vector_2
47
  .type  __vector_2, @function
48
__vector_2:
49
/* prologue: naked */
50
/* frame size = 0 */
51
/* stack size = 0 */
52
.L__stack_usage = 0
53
  ldi r24,lo8(-1)
54
  out 0x5,r24
55
  out 0x5,__zero_reg__
56
/* epilogue start */
57
  .size  __vector_2, .-__vector_2
58
  .ident  "GCC: (GNU) 8.0.0 20170502 (experimental)"

... also r24 wird mit demselben Wert überschieben ;-) Aber Du hast 
natürlich recht: ich hatte die Schleife in main() nicht beachtet ...
#4997331
Lesenswert?

Arduinoquäler schrieb:
> Wilhelm M. schrieb:
>> Wohl kaum! Schon mal gegoogelt: MCVE code -> erster Eintrag.
>
> Zu deiner eigenen Welt gehört dazu dass du es dem Suchenden
> überlässt wie er sucht.
>
> Also:  MCVE --> Malaysia Commercial Vehicle Expo
>
> Zu deiner eigenen Welt gehört auch dazu dass du ohne Not
> irgedwelche Abkürzungen verwendest die kein Schwein kennt.

Schon mal was von StackOverflow gehört ... (wer ist das Schwein?)
#4997340
Lesenswert?

Wilhelm M. schrieb:
> Es ist ein MCVE, das ausreicht. Und ein klare Frage.

MCVE nimmt man für Bugreports.
Hier handelt es sich aber um keinen Bug, sondern um falsche Erwartungen 
bezüglich der Ausführungszeit.

Und zur Klarheit fehlen noch sämtliche wichtigen Randbedingungen (wie 
oft, welche anderen Tasks usw.).

Unter speziellen Bedingungen kann man auf eine externe Flanke innerhalb 
2..3 Takten einen Pin setzen:
Timer als Zähler, Auswahl der Flanke, Signal an den Timereingang, Set 
Output-Pin on Compare, Comparewert auf Timer+1.
#4997350
Lesenswert?

Peter D. schrieb:
> Wilhelm M. schrieb:
>> Es ist ein MCVE, das ausreicht. Und ein klare Frage.
>
> MCVE nimmt man für Bugreports.

Nope, generell überall für jede Art von Frage, die mit einem bestimmten 
Codeverhalten (bug oder auch nicht) zu tun hat:

FYI: https://stackoverflow.com/help/mcve

FYI: for your interest

HTH

HTH: Hope that helps

AFAIK, hat das aber alles nichts mit der Frage zu tun...

http://www.catb.org/jargon/html
#4997370
Lesenswert?

Meiner Meinung nach baut man sich mit ISR_NAKED eine Zeitbombe in den 
Code. Da nicht definiert ist, welche Register der Compiler für die 
folgenden Befehle benutzt, ist eine manuelle Sichtung des Outputs 
eigentlich unumgänglich. Spätestens bei einer Änderung der 
Compilereinstellungen oder einem Compilerupdate können ganz andere 
Register zu sichern sein.

Und ich finde es auch nicht wirklich sinnvoll. Wenn man nicht gerade 
Funktionen im ISR aufruft, die nicht im gleichen C-File implementiert 
sind, dann sichert der gcc die Register sehr sparsam. Meiner Erinnerung 
sind es ein, höchstens 2 Register, die man händisch einsparen könnte.

Falls man tatsächlich einen derart zeitkritischen Code hat, dann sollte 
man auf eingebetteten Asm-Code innerhalb von ISR_NAKED ausweichen.

Gruß, Stefan
#4997378
Lesenswert?

Stefan K. schrieb:
> Meiner Meinung nach baut man sich mit ISR_NAKED eine Zeitbombe in den
> Code.

Sehe ich genauso. Aber die Frage war nach den Möglichkeiten ...

> Und ich finde es auch nicht wirklich sinnvoll. Wenn man nicht gerade
> Funktionen im ISR aufruft, die nicht im gleichen C-File implementiert
> sind, dann sichert der gcc die Register sehr sparsam.

Oder er macht ein inlining der Funktion. Wenn man Templates (C++) 
verwendet sogar (fast) immer (da es dieselbe TU, ups, 
Übersetzungseinheit ist).
Gast #4997452
Lesenswert?

1
ISR(TIMER0_COMPA_vect, ISR_NAKED) {
2
  asm volatile (        
3
    "push r16"      "\n\t"
4
    "ldi r16, 0xFF" "\n\t"
5
    "out %0, r16"   "\n\t"
6
    "pop r16"       "\n\t"
7
    :
8
    : "M" (_SFR_IO_ADDR (PORTB))
9
  );
10
  asm volatile ( "reti" );
11
}
Gast #4997464
Lesenswert?

oh, ich überlas, es ging um den INT1-Interrupt...
dann eben so...
1
ISR(INT1_vect, ISR_NAKED) {
2
  asm volatile (        
3
    "push r16"      "\n\t"
4
    "ldi r16, 0xFF" "\n\t"
5
    "out %0, r16"   "\n\t"
6
    "pop r16"       "\n\t"
7
    :
8
    : "M" (_SFR_IO_ADDR (PORTB))
9
  );
10
  asm volatile ( "reti" );
11
}
Asche über mein Haupt.
Gast #4997586
Lesenswert?

Der Ablauf ist eigentlich recht einfach:
1. Es dauert ein bisschen, bis eine Unterbrechung erkannt wird
   (1 bis 2 Takte). Üblicherweise sind die ja auch asynchron.
   Siehe Handbuch.
2. Nicht jeder Befehl kann unmittelbar unterbrochen werden, manche
   müssen halt beendet werden (1 bis 2 Takte).
3. Die Rücksprungadresse muss auf dem Stapel abgelegt werden
   (2 Bytes Push).
4. Die neue "Arbeitsadresse" muss in den Programmzähler geholt werden.
5. Arbeitest Du nicht im Assembler, so wird hier praktisch immer noch
   das Statusregister gesichert.

6. MACH DEIN DING. Zusätzlich fast immer 1 X Push und 1 X Pop.

7. Ein Compiler wird hier das Statusregister restaurieren.
8. Interrupt beenden meist mittel IRET. Also mindestens 2 X Pop.

Also: Auch wenn Du in Assembler programmierst, gibt es einige Sachen, 
die unumgänglich sind. Die Meisten sind mit etwas Nachdenken einfach 
nachzuvollziehen.

Natürlich fällt, bei den heutigen Compilern, kein "alle Register 
sichern" und kein "alle Register restaurieren" am Ende der Routine mehr 
an.

Habe bestimmt den einen oder anderen Takt vergessen.
Gast #4997987
Lesenswert?

Klar ist der Code etwas primitiv. Es geht aber erstmal nur darum die 
Reaktionszeit zu testen, bevor es ans eigentliche Projekt geht. Dafür 
sollte dieses Beispiel ausreichend sein. Wie es aber scheint, gibt es 
(noch) keine Lösung für ein schnelleres ansprechen :(
Später soll das Programm doch etwas umfangreicher werden.


Dorftrottel schrieb:
> oh, ich überlas, es ging um den INT1-Interrupt...
> dann eben so...ISR(INT1_vect, ISR_NAKED) {
>   asm volatile (
>     "push r16"      "\n\t"
>     "ldi r16, 0xFF" "\n\t"
>     "out %0, r16"   "\n\t"
>     "pop r16"       "\n\t"
>     :
>     : "M" (_SFR_IO_ADDR (PORTB))
>   );
>   asm volatile ( "reti" );
> }
> Asche über mein Haupt.

das funktioniert so leider nicht ganz - PORTB ist dauerhaft auf high.
#4998007
Lesenswert?

Hi

Wie sieht es aus, die scheinbar nicht auszumerzenden Takte durch 
brachiale Prozessor-Geschwindigkeit anszutricksen?

Wenn bei Deiner aktuellen Geschwindigkeit 40 Takte vergehen, wo Du mit 
maximal 4 Takten leben kannst - Tiger in den Tank und Quarz x10 in den 
Slot - die Wartetakte hast Du zwar immer noch, sind aber viel schneller 
vorbei.

MfG

PS:
fixi schrieb:
> das funktioniert so leider nicht ganz - PORTB ist dauerhaft auf high.

Dann ersetze versuchshalber
"ldi r16, 0xFF" "\n\t"

durch

"ldi r16, 0x00" "\n\t"
Gast #4998013
Lesenswert?

1
ISR(INT1_vect, ISR_NAKED) {
2
  PORTB = 0xff;
3
  PORTB = 0x00;
4
  reti();
5
}

Damit beträgt die Reaktionszeit nur noch 600ns. Leider immernoch etwas 
zu langsam...
Aber wie ich den Reaktionen entnehmen kann, sollte ich lieber die Finger 
von diesem Ansatz lassen?
#4998032
Lesenswert?

Hi

Darauf wollte ich hinaus - wenn im ISR steht, daß der Port bei JEDEM 
Abarbeiten komplett auf HIGH oder LOW gesetzt wird, wird der Port wohl 
so gesetzt.
Sofern das Hauptprogramm da Nichts dran ändert.

Da Das das einzige Register war, was eine Information enthielt und hier 
wohl PortB beschrieben wurde, ging ich davon aus, daß das Port nun 
'anders herum' bleibt.

Wenn Du nur ein Toggel pro ISR möchtest, kannst Du PinB mit 0xFF 
beschreiben - Das sollte Dir alle PortB-Bits 'umdrehen'.
(zumindest beim ATtiny ... vll. reicht der Verwandtschaftsgrad ja bis 
hier hin)

MfG
Gast #4998050
Lesenswert?

fixi schrieb:
> Wie es aber scheint, gibt es
> (noch) keine Lösung für ein schnelleres ansprechen :(

Doch, gibt es. Ein STM32F4xx schafft es schneller.
Mit der richtigen Hardware geht es noch viel schneller ;-)

> Später soll das Programm doch etwas umfangreicher werden.

Dann sag besser schon jetzt, was später sein soll. Ein ATmega8 ist 
heutzutage ja nicht mehr der absolute Renner - in jeder Beziehung.
#4998186
Lesenswert?

fixi schrieb:
> Später soll das Programm doch etwas umfangreicher werden.

Dann ist Dein Test vollkommen nutzlos.
Du hast nur eine CPU und die muß auch im worst-case alles in der 
geplanten Zeit ausführen können.

Die oben genannten ~200 Zyklen je Interrupthandler sind eine brauchbare 
Praxisabschätzung. Anfänger können auch deutlich mehr brauchen.
Gast #4998642
Lesenswert?

fixi schrieb:
> ISR(INT1_vect, ISR_NAKED) {
>   PORTB = 0xff;
>   PORTB = 0x00;
>   reti();
> }

willst Du sowas?
1
ISR(INT1_vect, ISR_NAKED) {
2
  asm volatile (        
3
    "push r16"      "\n\t"
4
    "ldi r16, 0xFF" "\n\t"
5
    "out %0, r16"   "\n\t"
6
    :
7
    : "M" (_SFR_IO_ADDR (PORTB))
8
  );
9
  asm volatile (        
10
    "ldi r16, 0x00" "\n\t"
11
    "out %0, r16"   "\n\t"
12
    "pop r16"       "\n\t"
13
    :
14
    : "M" (_SFR_IO_ADDR (PORTB))
15
  );
16
  asm volatile ( "reti" );
17
}
wird zu:
1
PUSH      R16            Push register on stack
2
SER       R16            Set Register
3
OUT       0x18,R16       Out to I/O location
4
LDI       R16,0x00       Load immediate
5
OUT       0x18,R16       Out to I/O location
6
POP       R16            Pop register from stack
7
RETI                     Interrupt return
Gast #4998933
Lesenswert?

Danke für die zahlreichen Vorschläge. Ich komme mit dem testen noch 
nicht ganz hinterher. Das werde ich aber demnächst ausführlich machen.

Eine Altnernative wäre den Atmega88a einzusetzen. Dieser kann laut 
Datenblatt 20MHz. Gibt es abgesehen von der höheren Frequenz evtl 
weitere Auswirkungen auf die Reaktionszeit?
Gast #4998959
Lesenswert?

Oliver S. schrieb:
> Je nun, was anderes macht der Compiler auch nicht...

Stimmt, der macht sogar noch viel mehr ;-)

ISR(INT1_vect)
{
     5f0:  1f 92         push  r1
     5f2:  0f 92         push  r0
     5f4:  0f b6         in  r0, 0x3f  ; 63
     5f6:  0f 92         push  r0
     5f8:  11 24         eor  r1, r1
     5fa:  8f 93         push  r24
  PORTB=0xff;
     5fc:  8f ef         ldi  r24, 0xFF  ; 255
     5fe:  85 b9         out  0x05, r24  ; 5
  PORTB=0x00;
     600:  15 b8         out  0x05, r1  ; 5
}
     602:  8f 91         pop  r24
     604:  0f 90         pop  r0
     606:  0f be         out  0x3f, r0  ; 63
     608:  0f 90         pop  r0
     60a:  1f 90         pop  r1
     60c:  18 95         reti
Gast #4999001
Lesenswert?

Oliver S. schrieb:

> Je nun, was anderes macht der Compiler auch nicht...

Doch, das tut er durchaus, es sei denn, es ist ein "guter" UND man ist 
sehr mit seinen Eigenheiten vertraut und benutzt sie auch kompetent.

Aber selbst wenn die Kenntnisse da sind und der Compiler zumindest 
potentiell wirklich alle wesentlichen Tricks ermöglicht, die in Asm 
möglich sind, stellt sich am Ende des Tages immer noch die Frage: warum 
zum Teufel muss man das nun unbedingt in C programmieren?

Bilanz:
1.
Der Einsatz von C bringt in einem solchen "engen" Szenario keinerlei 
Vorteile, weil's entweder garnicht geht oder zumindest die 
"Portabilität" als einziger nennenswerter Vorteil von C gegenüber Asm 
praktisch vollständig entfällt.
2.
Es macht mehr Arbeit, weil man neben der allfälligen Kenntnis der 
Zielarchitektur und seiner Assemblersprache auch noch die konkreten 
Features des Compilers perfekt beherrschen muss (weit jenseits der 
C-Sprachstandards).

Fazit:
Wer in solchen Szenarien trotzdem C benutzt, hat einfach irgendwie nicht 
alle Latten am Zaun. Das kann nur ein eingefleischter C-Wanker sein, der 
nix anderes will (und nix anderes kann)...
#4999204
Lesenswert?

@ m.n.

Es ist natürlich ein sehr seltener Sonderfall, aber die Sequenz:

>PUSH      R16            Push register on stack
>SER       R16            Set Register
>OUT       0x18,R16       Out to I/O location
>LDI       R16,0x00       Load immediate
>OUT       0x18,R16       Out to I/O location
>POP       R16            Pop register from stack
>RETI                     Interrupt return

lässt das Statusregister in Ruhe.

Deshalb gilt:

>Nein, nicht einmal das. Es sollte nur unbemerkt das SREG zerschiessen.

nicht.
Gast #5008117
Lesenswert?

fixi schrieb:
> Ist die Reaktion beim aktiven Warten durch polling auf ein High signal
> am Pin schneller als bei einem externen Interrupt?

Wie wäre es denn wenn du so einen einfachen Sachverhalt einfach
schnell selbst duch Eigeninitiative in der Praxis klärst. Die
Voraussetzungen dazu hast du ja offensichtlich:

fixi schrieb:
> An meinem atmega8 löse ich einen externen interrupt aus. In der ISR wird
> lediglich ein Ausgang auf high gesetzt (1 Zeile Code). Die Reaktionszeit
> beträgt bei 16MHz ca 1,25 Mikrosekunden.

Andererseit drängst sich bei solchen Fragen und Handlungs-
zusammenhängen deinerseits der Verdacht auf dass hier im Thread
etwas gefaked wird, oder getrollt.
Gast #5008213
Lesenswert?

Arduinoquäler schrieb:
> Andererseit drängst sich bei solchen Fragen und Handlungs-
> zusammenhängen deinerseits der Verdacht auf dass hier im Thread
> etwas gefaked wird, oder getrollt.

Ich hab ja sonst nichts zu tun...

Es ist doch ganz einfach. Ich habe kaum Zeit um das auszutesten und will 
einfach nur wissen wie die Erfolgsaussichten sind, bevor ich damit 
anfange. Darum wende ich mich hier an das Forum. Und genau das ist doch 
Sinn und Zweck eines Forums. Es ist doch eine ganz einfach Frage. 
Entweder man weiß die Antwort und hilft, oder man lässt es eben sein. 
Aussagen wie "such doch selbst" oder "teste es doch" sind hier das 
eigentliche rumgetrolle.
Gast #5008220
Lesenswert?

fixi schrieb:
> Es ist doch ganz einfach. Ich habe kaum Zeit um das auszutesten und will
> einfach nur wissen wie die Erfolgsaussichten sind, bevor ich damit
> anfange.

Verstehe.

Bei solch einem aufwendigen, umfangreichen Test muss man sich
schon gut überlegen ob, wie und wann man diesen Aufwand treibt.

Ich veranschlage mal ca vier Wochen Arbeit a 50 Stunden für das
Schreiben von 10 Zeilen Code, das Hochladen auf den Controller
und das Anschliessen eines Oszilloskops. Betrachten und
Analysieren des Ergebnisses noch nicht einbezogen.

Alternativ dazu drei Wochen Arbeit für das Schreiben von 10
Zeilen Code und das analysieren des compilierten C-Codes auf
Assembler-Ebene.
Gast #5008250
Lesenswert?

Grundsätzlich würde ich erst mal auf:

ISR(INT1_vect, ISR_NAKED) {
  PORTB = ~PORTB;
  reti();
}

Umsteigen.

Wie bereits gesagt natürlich nur, wenn Deine Reaktionszeit unter der 
eines Oszilloskops liegt;-)

Wie es mit den minimal möglichen Zeiten aussieht wurde bereits gesagt:

"Unterbrechung erkennen"      Automatisch, abhängig vom Zeitpunkt
                              und gerade aktuellem Befehl    Variabel
PUSH PC                       Automatisch                    Fixzeit
Load Interruptvector -> PC    Automatisch                    Fixzeit
PUSH Work                     Dein Ding PUSH                 Fixzeit
MOV                           Dein Ding Hole Status          Fixzeit
PUSH Status                   Dein Ding PUSH                 Fixzeit
„Hau rein“                    Dein Ding akt. Status holen 1) Fixzeit
                              Dein Ding invertieren und   2) Fixzeit
                              Dein Ding zurückschreiben   3) Fixzeit
POP Status                    Dein Ding POP                  Fixzeit
MOV Status                    Dein Ding                      Fixzeit
POP Work                      Dein Ding POP                  Fixzeit
POP PC                        Dein Ding Indirekt durch IRET  Fixzeit

In diesem Falle muss auch das Statusregister gesichert werden, da der 
Befehl: COM wahrscheinlich den Status ändert.

Besondere Wünsche sehen weder der Compiler noch die Befehlsliste vor.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren