Interrupt über Software starten

Hallo
Kann mir jemand von euch helfen.
Wie kann ich einen Interrup, nicht über Hardware mit einem Taster, sondern über Software starten.
Mein Problem : Ich möchte beim Master, über einen Taster, Programm beenden auslösen.
Gleichzeitig soll beim Slave, über den I2C Bus, auch ein Programm mit Interrup beendet werden.
Danke im Voraus
Jürgen

Du bist verwirrt!
(zumindest sieht das für mich so aus)

Software Interrupts machen Sinn, wenn der Prozessor mehrere Schutzebenen kennt.

Die üblichen µC kennen sowas nicht.

Also:
Du buddelst auf der falschen Baustelle.

und was passiert, wenn das Programm beendet wurde?
und warum Interrupt?

@combie : beim Atmega kannst du den PCI auslösen, wenn du mit den Pins wackelst. Wenn man dann noch eine LED dranbastelt hast du fast so ein schönes Erlebnis wie auf der PDP11 :slight_smile:

@combie : beim Atmega kannst du den PCI auslösen,

Man kann auch mit der Stirn versuchen, einen Nagel in die Wand zu kloppen.

Der Begriff Softwareinterrupt ist relativ klar belegt.
PCI ist ganz klar ein Hardwareinterrupt.

Nu, der TO möchte keinen Softwareinterrupt, sondern einen Interrupt über Software triggern - wie auch immer. Dass das keinen großen Sinn macht ist eh klar :slight_smile:

Dass das keinen großen Sinn macht ist eh klar :slight_smile:

Eben....
Wozu dann der Holzweg?
Die Nebelkerze?

Merksatz:

Wer in die falsche Richtung läuft,
braucht sich nicht zu beeilen.

Hallo,

Dein Ansatz "Interrupt" ist völlig falsch. Für den Master fragst Du ganz normal den Eingang ab und wertest das mit z.B If... aus. Ebenfalls muss die Information des Tasters in den Daten an den Slave enthalten sein. Dann kann der Slave das ebenfalls auf die geiche Weise auswerten.

Heinz

Naja...
Der Slave Callback läuft sowieso im Interrupt Kontext.

Alleine das ist schon ein Grund zu sagen, dass Softwareinterrupts hier fehl am Platze sind.

Hallo

dass man einen Interrupt nicht mit Software starten kann, hat mir mein Bauchgefühl auch gesagt.
War mir als Anfänger aber nicht sicher.

Jetzt ist mir klar wie es nicht geht, aber kann mir einer von euch auch erklären wie ich das lösen kann.
Bitte mit leicht verständlichen Sätze, da meine Programmier Fähigkeiten nicht die besten sind.

Nochmals Danke im Voraus
Jürgen

Bitte mit leicht verständlichen Sätze, da meine Programmier Fähigkeiten nicht die besten sind.

Das merken wir auch so!
Oder hältst du uns für so ****?

Wenn du bitte in leicht verständlichen Sätzen beschreiben würdest, was dein Problem ist, vielleicht...

Meine Modellbahn Anlage besteht bis jetzt aus drei Modulen.
Im Mittelmodul kann ich die Beleuchtung und noch ein paar Bewegungsabläufe mit Taster ein- und ausschalten.
Die Signale gehen von einem Modul zum nächsten Modul über den I2C Bus.
Alles funktioniert einwandfrei, nur die Beleuchtung in meinem Kurhotel lässt sich nicht mehr ausschalten,
da sie sich in einer Endlosschleife befindet. Daher auch meine Idee mit dem Interrupt.

Ich glaube auch daß Du dich da in etwas verzettelst was nicht so funktionieren kann.

Ein interrupt ist ein Teil des Programms das bei einem gewissen Ereignis abgearbeitet wird, unabhängig von dem was der Rest des Programms macht. EIn Interrupt ist nicht dazu da etws zu beenden.

Das "Bitte Müll raustragen" Deiner Frau kommt ja auch unerwartet und im falschesten Moment. Da muß man das Bier und den Fußball stehen lassen und kann danach dort weitermachen wo man aufgehört hat.

Fragen an die C-besser-Könner als ich einer bin. Die Interrupt-Funktion kann wohl auch wie jede andere Funktion via Programm aufgerufen werden?

Grüße Uwe

Auf einem einfachen µC kann man Programme oder Programmteile nicht beenden, ohne den ganzen Controller anzuhalten. Was man machen kann ist ein Flag setzen, das anzeigt, ob ein Programmteil in loop() ausgeführt werden soll oder nicht.

bool runThis = false; //globales Flag
void loop() {
...
if (runThis) { DasHierNurBeiBedarfLaufenLassen; }

Dieses Flag kann man auch in einem Interrupt setzen, aber wenn man dazu den (Software-) Interrupt erst auslösen müßte, dann kann man stattdessen ganz einfach das Flag auch ohne Umweg setzen.

Fragen an die C-besser-Könner als ich einer bin. Die Interrupt-Funktion kann wohl auch wie jede andere Funktion via Programm aufgerufen werden?

Ja und nein!

Normale Funktionen werden mit dem ASM Statement RET beendet.
Interrupt Routinen werden mit RETI beendet.
Das muss man beachten!

5.88 RET – Return from Subroutine
5.88.1 Description
Returns from the subroutine. The return address is loaded from the STACK. The Stack Pointer uses a pre-increment
scheme during RET

5.89 RETI – Return from Interrupt
5.89.1 Description
Returns from the interrupt. The return address is loaded from the STACK, and the Global Interrupt Enable bit is set.
Note that the Status Register is not automatically stored when entering an interrupt routine, and it is not restored
when returning from an interrupt routine. This must be handled by the application program. The Stack Pointer uses a
pre-increment scheme during RETI.

AVR® Instruction Set Manual

Ja und nein!

Immerhin programmierst du in C++, und da gibt es diesen Unterschied nicht.
void myHandler (); deklariert eine normale Funktion, die jeder der sie kennt verwenden kann. Was in die Interrupt- Verarbeitung eingehängt wird, wird also nochmal einen Rahmen drumrum machen.

Immerhin programmierst du in C++, und da gibt es diesen Unterschied nicht.

:o :o :o
Natürlich endet die ISR mit "reti"
Und eine normale Funktion mit ret.
Mit den bekannten Folgen.

Zudem muss eine solche Prototype Deklaration so aussehen:

extern "C" void TIMER0_COMPA_vect();

Und was ist mit

void myHandler() {return;}

void setup() {
  attachInterrupt(0, myHandler, CHANGE);
  myHandler();
}
void loop(){
    myHandler();
}

Irgendwelche Probleme?
myHandler ist eine normale Funktion, die evtl. auch von einer ISR aufgerufen wird, wenn du da einen Unterschied deutlich machen willst.

Wenn sie als/in ISR läuft, sind natürlich viele Sachen tabu.

Einverstanden?

Einer der größten Fehler im Arduino-Design ist die Existenz von attachInterrupt. Dadurch wird es zu einfach, schwere Fehler zu machen.

Einverstanden?

Ach sicher.... teileweise

Einer der größten Fehler im Arduino-Design ist die Existenz von attachInterrupt. Dadurch wird es zu einfach, schwere Fehler zu machen.

z.B. damit.

Albtraumartige Push Pop Kaskaden kommen noch dazu.

Und was ist mit
....
attachInterrupt(0, myHandler, CHANGE);

Natürlich ist myHandler eine stinknormale Callback Funktion.
Keine ISR.
Läuft aber im ISR Kontext, weil sie von einer aufgerufen wird.

Wenn z.B. attachInterrupt im Code vorkommt, dann werden die ISR für ALLE Pin Hardwareinterrupts erzeugt.
Total teures Verfahren!

Aber hier dreht es sich ja darum eine Interrupt Routine aus C++ heraus aufzurufen.

Habe dein Beispiel, mal mit meinem zusammengegossen

void myHandler() {return;}
extern "C" void TIMER0_COMPA_vect();

int main() 
{
  detachInterrupt(0);
  DDRB = _BV(PB5);
  TIMER0_COMPA_vect();
  TIMER0_COMPA_vect();
  //attachInterrupt(0, myHandler, CHANGE);
}

ISR(TIMER0_COMPA_vect)
{
  PINB = _BV(PB5); // toggle Pin 13 UNO
}

Der erzeugte Asmcode:

E:\temp\Arduino/sketch_jan15f.ino.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
   0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
   4: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__vector_1>
   8: 0c 94 78 00 jmp 0xf0 ; 0xf0 <__vector_2>
   c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  10: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  14: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  18: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  1c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  20: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  24: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  28: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  2c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  30: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  34: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  38: 0c 94 4c 00 jmp 0x98 ; 0x98 <__vector_14>
  3c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  40: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  44: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  48: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  4c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  50: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  54: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  58: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  5c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  60: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
  64: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>

00000068 <__ctors_end>:
  68: 11 24       eor r1, r1
  6a: 1f be       out 0x3f, r1 ; 63
  6c: cf ef       ldi r28, 0xFF ; 255
  6e: d8 e0       ldi r29, 0x08 ; 8
  70: de bf       out 0x3e, r29 ; 62
  72: cd bf       out 0x3d, r28 ; 61

00000074 <__do_copy_data>:
  74: 11 e0       ldi r17, 0x01 ; 1
  76: a0 e0       ldi r26, 0x00 ; 0
  78: b1 e0       ldi r27, 0x01 ; 1
  7a: e2 e6       ldi r30, 0x62 ; 98
  7c: f1 e0       ldi r31, 0x01 ; 1
  7e: 02 c0       rjmp .+4       ; 0x84 <__do_copy_data+0x10>
  80: 05 90       lpm r0, Z+
  82: 0d 92       st X+, r0
  84: a4 30       cpi r26, 0x04 ; 4
  86: b1 07       cpc r27, r17
  88: d9 f7       brne .-10     ; 0x80 <__do_copy_data+0xc>
  8a: 0e 94 9f 00 call 0x13e ; 0x13e <main>
  8e: 0c 94 af 00 jmp 0x15e ; 0x15e <_exit>

00000092 <__bad_interrupt>:
  92: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>

00000096 <nothing>:
#include <stdio.h>

#include "wiring_private.h"

static void nothing(void) {
}
  96: 08 95       ret

00000098 <__vector_14>:
  TIMER0_COMPA_vect();
  //attachInterrupt(0, myHandler, CHANGE);
}

ISR(TIMER0_COMPA_vect)
{
  98: 8f 93       push r24
  PINB = _BV(PB5); // toggle Pin 13 UNO
  9a: 80 e2       ldi r24, 0x20 ; 32
  9c: 83 b9       out 0x03, r24 ; 3
}
  9e: 8f 91       pop r24
  a0: 18 95       reti

000000a2 <__vector_1>:
IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_6)
IMPLEMENT_ISR(INT7_vect, EXTERNAL_INT_7)

#else

IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
  a2: 1f 92       push r1
  a4: 0f 92       push r0
  a6: 0f b6       in r0, 0x3f ; 63
  a8: 0f 92       push r0
  aa: 11 24       eor r1, r1
  ac: 2f 93       push r18
  ae: 3f 93       push r19
  b0: 4f 93       push r20
  b2: 5f 93       push r21
  b4: 6f 93       push r22
  b6: 7f 93       push r23
  b8: 8f 93       push r24
  ba: 9f 93       push r25
  bc: af 93       push r26
  be: bf 93       push r27
  c0: ef 93       push r30
  c2: ff 93       push r31
  c4: e0 91 00 01 lds r30, 0x0100 ; 0x800100 <intFunc>
  c8: f0 91 01 01 lds r31, 0x0101 ; 0x800101 <intFunc+0x1>
  cc: 09 95       icall
  ce: ff 91       pop r31
  d0: ef 91       pop r30
  d2: bf 91       pop r27
  d4: af 91       pop r26
  d6: 9f 91       pop r25
  d8: 8f 91       pop r24
  da: 7f 91       pop r23
  dc: 6f 91       pop r22
  de: 5f 91       pop r21
  e0: 4f 91       pop r20
  e2: 3f 91       pop r19
  e4: 2f 91       pop r18
  e6: 0f 90       pop r0
  e8: 0f be       out 0x3f, r0 ; 63
  ea: 0f 90       pop r0
  ec: 1f 90       pop r1
  ee: 18 95       reti

000000f0 <__vector_2>:
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
  f0: 1f 92       push r1
  f2: 0f 92       push r0
  f4: 0f b6       in r0, 0x3f ; 63
  f6: 0f 92       push r0
  f8: 11 24       eor r1, r1
  fa: 2f 93       push r18
  fc: 3f 93       push r19
  fe: 4f 93       push r20
 100: 5f 93       push r21
 102: 6f 93       push r22
 104: 7f 93       push r23
 106: 8f 93       push r24
 108: 9f 93       push r25
 10a: af 93       push r26
 10c: bf 93       push r27
 10e: ef 93       push r30
 110: ff 93       push r31
 112: e0 91 02 01 lds r30, 0x0102 ; 0x800102 <intFunc+0x2>
 116: f0 91 03 01 lds r31, 0x0103 ; 0x800103 <intFunc+0x3>
 11a: 09 95       icall
 11c: ff 91       pop r31
 11e: ef 91       pop r30
 120: bf 91       pop r27
 122: af 91       pop r26
 124: 9f 91       pop r25
 126: 8f 91       pop r24
 128: 7f 91       pop r23
 12a: 6f 91       pop r22
 12c: 5f 91       pop r21
 12e: 4f 91       pop r20
 130: 3f 91       pop r19
 132: 2f 91       pop r18
 134: 0f 90       pop r0
 136: 0f be       out 0x3f, r0 ; 63
 138: 0f 90       pop r0
 13a: 1f 90       pop r1
 13c: 18 95       reti

0000013e <main>:
      EIMSK &= ~(1 << INT0);
 13e: e8 98       cbi 0x1d, 0 ; 29
    intFunc[interruptNum] = nothing;
 140: 8b e4       ldi r24, 0x4B ; 75
 142: 90 e0       ldi r25, 0x00 ; 0
 144: 90 93 01 01 sts 0x0101, r25 ; 0x800101 <intFunc+0x1>
 148: 80 93 00 01 sts 0x0100, r24 ; 0x800100 <intFunc>
  DDRB = _BV(PB5);
 14c: 80 e2       ldi r24, 0x20 ; 32
 14e: 84 b9       out 0x04, r24 ; 4
  TIMER0_COMPA_vect();
 150: 0e 94 4c 00 call 0x98 ; 0x98 <__vector_14>
  TIMER0_COMPA_vect();
 154: 0e 94 4c 00 call 0x98 ; 0x98 <__vector_14>
}
 158: 90 e0       ldi r25, 0x00 ; 0
 15a: 80 e0       ldi r24, 0x00 ; 0
 15c: 08 95       ret

0000015e <_exit>:
 15e: f8 94       cli

00000160 <__stop_program>:
 160: ff cf       rjmp .-2       ; 0x160 <__stop_program>

Hallo,

dass der Ansatz "Interrupt" völlig falsch war, ist mir jetzt auch klar.

Ich bin gerade dabei einen anderen Weg zu gehen.
Wollte euch bei Eurer Diskussion nicht stören.

Werde mich auf jeden Fall wieder melden, vermutlich weil ich es nicht hin bekomme.
Nochmals Danke für Eure Hilfe.

Warum ist das Einloggen jetzt so umständlich. Früher war ich ruck zuck in dem Forum drinnen.
Jetzt ist es jedes Mal ein Glückspiel.

Gruß Jürgen

Wollte euch bei Eurer Diskussion nicht stören.

Danke. Sehr nett von dir, dass du für uns diesen Thread gestartet hast. :slight_smile: