Interrupt

Begonnen von picass, 07.04.2021, 11:59:40 CEST

Vorheriges Thema - Nächstes Thema

picassTopic starter

#20
Mein Lieblingskampf, der gegen Interrupts.... >:(  >:(  >:(

Aktuell führt das Prob auf wohl eine Eigenart des PIC18F25K22. Da versuche ich das Aufwachen aus der Sleep-Routine OHNE Interrupt. Und da gibts reichlich Probleme: mit dem Programm - siehe unten - will der PIC erst gar nicht einschlafen. Was erklärlich wäre, weil immer dasjenige INTCON Flag gesetzt ist, welches einen Port-on-Change-IRQ anzeigt, das Bit 1 mit dem Beinamen " RBIF". Das lässt sich auch im Simulator nicht löschen! Überhaupt spinnt der Simulator, wenn - aber auch nur dann - diese Wake-up-Routine implementiert ist. Wenn man dann im Sim den Einzelschrittmodus wählt, um den Zustand der Variablen (ZdV) zu verfolgen, dann reagiert dieses Teil-Prog für den ZdV immer erst nach zwei Schritten. Normal aktualisiert sich das immer sofort dann, wenn ein Schritt ausgeführt wurde und nicht erst nach zwei Schritten.

Ein und dasselbe Prog - natürlich am Anfang mit angepasster Initialisierung - funktioniert auf einem PIC18F14K22 prima. "Eigentlich" sollte zwischen den beiden PIC-Typen kein nennenswerter Unterschied sein. Es gibt zwar marginale, z.B. bei den Namen der INTCON Register, aber sonst....
Unangenehm könnten diverse Mehrfachbelegungen mit mehreren Funktionen auf ein und demselben Port beim 25-er sein. So ist der Port B5 mit Funktionen derart überfrachtet..., man sieht es, wenn man sich vom MPLAB die Initialisierung mit ihren Auswahlmöglichkeiten anschaut.

Was klemmt beim PIC18F25K22 da so, wenn das Prog bei seinem namentlich fast gleichen Bruder so prima funktioniert?!?
Grüße, picass
4x7anzeige.txt

picassTopic starter

#21
Drei gordische Knoten auf einen Streich !

ALLE meine Probleme der letzten Zeit mit Assembler-Programmieren sind gelöst und das in unerwarteter Weise. Vor 2 Tagen schwante es mir, dass die SSD einen Defekt haben könnte: häufiger wollte der Compi nach dem Einschalten nicht drauf zu greifen, beim Win-Runterfahren lief der PC minutenlang weiter, statt nach ca. 10 sec spätestens aus zu sein. Eine testweise andere, ähnliche SSD verhielt sich nicht so. Gestern dann der Gedanke, es vielleicht doch erst mal nur mit einer Win-Reparatur-Installation zu versuchen, bevor die HD im Müll landet. Also gleich die MPLAB X Version vorweg deinstalliert, damit alle evtl. Leichen weg waren, dann WIN neu und genervt die 5 Stunden dauernde Aktion abgewartet, der PC kroch mühsamst vor sich hin. Dann heute Mittag die alte MPLAB X v5.20 neu installiert. Aber.....
....aber vorher noch hatte ich mir heute morgen meinen guten, aber alten PC gekrallt und den durch gewurstet:
- den CPU-Lüfter demontiert und gucke da: trotz meiner Empfindung, dass die CPU-Kühlerpaste noch nicht so alt sein dürfte, war diese doch kurz davor, hart zu sein. Also die CPU neu beschmiert. Dann den Lüfter drüber endlich so montiert, dass er in die ,,richtige" Richtung blies. Der saß vorher anders rum. Was in dem Fall nahezu egal war, einmal, weil er so riesig ist, dass er auch alleine die Lufthoheit im Gehäuse hatte, dann aber auch, weil ich am großen Towergehäuse eh' die Seitenwand ab hatte, um immer Zugriff auf die Innereien zu haben. An Kühlung durch Luft war definitiv kein Mangel, aber die harte Paste verhinderte mit Sicherheit eine ausreichende Hitzeabfuhr.
- die Bios-Batterie war schlapp. ,,Eigentlich" soll ein PC auch ohne das starten können, aber die Häufung der Hänger gleich nach dem Einschalten, also noch vor dem Winstart, war wohl kein Zufall.
- die RAMs wurden kurz entnommen und gleich wieder in ihre Sockel gesteckt: Korrision an Kontakten ist eine böse, böse und fast nicht zu entdeckende Sache !
- alle Anschlüsse der HD-Datenkabel wurde zusätzlich nochmal mit Heißkleber gegen evtl. Wackeln gesichert;
- einzelne, noch irgendwie lose Kabel oder Käbelchen wurden auch noch mit Heißkleber fixiert, jetzt rührt sich selbst bei leichtem Erdbeben nichts mehr.
- der hintere Gehäuselüfter wurde entstaubt;
- der vordere GL schien bei genauer Betrachtung sauber zu sein. Aber man kann nie wissen, also doch die Arbeit der Abnahme der Vorderfront ausgeführt und Tusch: guckst du Bild !

Also den alten PC komplett auf Vordermann gebracht, dann die mit dem frischen Win10 versehene SSD installiert, die neue alte MPLAB Version von Microchip geladen, dann mutig die beiden Nagelproben gemacht:
- das Win läuft deutlich schneller und vor allem das Ausschalten ist wieder so fix wie üblich.
- das Elend mit dem Interrupt bei Wechsel vom PIC18F14K22 auf den PIC18F25K22 ist wie weg geblasen. Als hätte es das nie gegeben! Der PIC pennt ein, wie er soll, wacht auf, wenn die passende Taste gedrückt wird, tut, was er soll – was soll er? Doofe Frage: eine LED anzünden ! – und der Simulator wie auch der Hardware-Debugger waschen ihre Hände in jungfräulicher Unschuld: endlich reagiert der Sim/Debug nicht erst nach zwei Schritten auf die Anweisungen, sondern wie üblich sofort. Dann lassen sich die INTCON Flags löschen......... das hatte vorher Verzweiflung bis zur Gehirnwäsche hervor gerufen !

NEUER alter Compi, neues Win10, neues MPLAB und die PIC-Welt ist wieder in Ordnung. HEUREKA !
Grüße, picass
Staub-Ventilator.jpg
Staub-Ventilator.jpg

^Cobra


picassTopic starter

#23
Weil an so vielen Stellschrauben auf einmal gedreht wurde, ist es im Nachhinein nicht seriös, sich auf einen einzigen Punkt zum Festmachen der Schuld zu kaprizieren. Aber sicher ist, dass das Win-System ,,in den Wicken" war, wie man an der teils elend langen Verarbeitung einzelner Funktionen sehen konnte, so z.B. auch das ewig dauernde Runterfahren. Verwunderlich ist das aber irgendwie schon, denn auf dieser Hd wurde über Jahre quasi nur das MPLAB genutzt. Andere Programme waren erst gar nicht installiert oder wurden schon vor Langem deinstalliert. Ich gehe davon aus, dass die SSD – eine preiswerte Version – auch Speicherverluste hatte. Muss mal versuchen, ein spezielles Testprog auf die los zu lassen. Und – ach ja – nun rasch noch eine Sicherung in Form eines Images vorzunehmen.

Zum eigentlichen Fred-Thema – dem Interrupt – gibt es aber auch noch was, nachzutragen. Weiß nicht, wie ihr für ein neues Projekt eure Programm-Arbeit angeht. Ich neige dazu, mir ein Vorhandenes auszusuchen, bei dem schon allerlei passt oder ähnlich ist. Das wird dann umgestrickt, also angepasst und erweitert. Beim Thema Interrupt gehts genau so. Da hatte ich zunächst die ,,echten" Interrupt-Routinen bearbeitet, also die mit abrupter Unterbrechung des Progs, Sprung zum IRQ-Vektor, von dort zur IRQ-Bearbeitungs-Routine, von dort mit ,,return" wieder ins Prog zurück. Alles prima, nur hatte ich heuer nicht mehr auf dem Schirm, dass ein einfaches ,,wake-on-change" (WoC) schon ein wenig anders ist als die beiden normalen IRQ's. So hatte ich nicht beachtet, dass beim WoC im Gegensatz zum ,,Echten" bei jedem Status-Wechsel des avisierten Port-Pins eine Aufwach-Reaktion erfolgt. Beim "Echten" stellt man sehr genau ein, ob fallende oder ansteigende Flanke, beim ,,Falschen" gibt es solche Unterscheidung gar nicht.
Und – Tusch – hat man die aus der IRQ-Bearbeitungs-Routine sinnvolle und notwendige Abfrage, welcher Pin sich denn nun verändert hatte, mit in das neue Prog übernommen und wundert sich, dass es auf einmal völlig deplazierte Sprünge gibt. Naja, halt mangelnde Übung...., da vergisst der Mann schon mal was.... Seufz !
Grüße, picass

picassTopic starter

#24
Und nun das immer wieder gern genommene Thema: "Spaß an den Backen mit Interrupts" - die zehnte Auflage!
Heuer geht es um Bezeichungen, rsp. Namen, welche meine Aufmerksamkeit und mich gleich mit erregten. Ihr wisst ja, dass mein Lieblings-PIC der 18F14K22 ist. Und der hat einen größeren Bruder, den 18F25K22. Das ist quasi der gleiche µC, nur sind beim 14K nicht alle 8 Portpinne an PortA und PortB vorhanden, beim 25K aber schon. Sonst sollte alles perfekt gleich sein, insbesondere der Instruktion-Set enthält die gleiche Menge an Befehlen und im Vorspann der Datenblätter ist auch keine Abweichung ersichtlich. Aber.......
....aber....geifer.....gettz konkret zu meinem Lieblingskampf mit Interrupts.

Beim 14K und 25K sind in den INTCON und INTCON2-Registern abweichende Bezeichnung für ein- und dasselbe Bit vorhanden. Mal heißt es "RABIE" und mal "RBIE", und auch bei INTCON,0 und INTCON2,0 ist mal ein "A" integriert und mal nicht. Vielleicht hatte das auch - siehe oben - evtl. für Simulator-Trouble gesorgt.

Ach....., das macht einfach nur Spaß, das Interrupten! :)  Wenn man sich gerade nicht ärgert! >:(
Grüße, picass

vloki

Zitat von: picass in 15.09.2026, 11:59:34 CESTBeim 14K und 25K sind in den INTCON und INTCON2-Registern abweichende Bezeichnung für ein- und dasselbe Bit vorhanden

Na ja, so ganz das selbe ist es ja nicht.

1xer: RBIF: Port B Interrupt-On-Change (IOCx) Interrupt Flag bit
2xer: RABIF: RA and RB Port Change Interrupt Flag bit

Macht doch Sinn ;-)
Like Like x 1 View List
MPLABX  XC8  KiCad FreeCAD Qt

picassTopic starter

#26
Ja, macht Sinn! Hat mich nur eben überrascht, dass doch nicht Alles genau gleich war zwischen den vermeintlichen Brüderchen. Aber da wir gerade mal "zufällig" bei Thema "Interrupt" sind, kommen mir doch gleich Detailfragen in den Sinn. Beginne mal mit dieser:
In einem fiktiven Normalfall lümmelt der µC irgendwo im Programm umeinander und wird durch einen high-IRQ aus dieser Routine gerissen. Er hinterlegt auf dem 31-füßigen Stack die momentane Prog-Adresse, springt zum Anfang des Progs, findet in der high-IRQ-Adresse (0x08) eine Sprunganweisung wie "bra ruptus", springt dort rein und dann wird das IRQ-Flag gelöscht, irgendwas Kurzes ausgeführt - wie z.B. das Ablesen und Sichern des Status der Portpinne, um den Auslöser einer externen Quelle wie Taster dingfest machen zu können - ,gelangt standardmäßig zu dem Befehl "retfie", retourniert an die vorher verlassene Prog-Adresse und macht weiter wie vor, was man wörtlich nehmen muss, denn mit dem Befehl "retfie" wird das IRQ-Flag gleich wieder gesetzt: der nächste IRQ ist jederzeit wieder möglich.
Ist das so weit korrekt dargestellt?
Wenn dem so wäre, eröffnet sich für mich ein Prob, weil z.B. ein erneuter IRQ unerwünscht ist. Da aber z.B. ein willkürlicher Tastendruck den µC an vielen Positionen im Prog erwischen kann, kann man nicht überall im Prog Anweisungen für das Unterdrücken von IRQs unterbringen.
Entsprechend läge es nahe, die Standard-Anweisung "retfie" nicht zu nutzen, sondern.... ja was nun?
Von der 008-Position einen Call auf "ruptus" setzen und dort einen Return? Um dann an 008 einen gezielten Ansprung auf die letztendlich IRQ-Behandlungs-Routine (Welche Taste war es nun ?) zu setzen?
Was ist dann mit dem Stack...., der kann irgendwann überlaufen! Man kann ja in der Initialisierung so einstellen, dass der Überlauf keine Aktion auslöst. Aber wäre das so  wie beschrieben die passende Lösung?
Grüße, picass

pic18

ich verstehe dein Problem nicht ganz, es gibt für jede Interrupt Operation ein IE (Interrupt Enable) = Interrupt - Freigabe und ein IF ( Interrupt Flag). IF wird gesetzt wenn ein Interrupt ausgelöst wurde, unabhängig ob der Prozessor wirklich in den Interrupt gesprungen ist. ZB. wenn GIE nicht gesetzt. 
Meine Programme sind meistens komplexer. Ich frage im Interrupt IE und IF ab um zu erfahren was den Interrupt ausgelöst hat und springe in die entsprechende Unterprogramme. Wichtig ist, das Du das IF im Interrupt manuell löscht, sonst wird beim Verlassen des Interrupts ein neuer ausgelöst. Wenn Du den Interrupt und auch die Unterprogramme richtig mit RETFIE bzw. RETURN beendest, dann dürfte der 31 Stufige Programmstack nicht überlaufen. Sollte dieser überlaufen dann stürzt dein Programm ab. Ich weiß jetzt nicht ob man einen Programmneustart bei Stack-Überlauf erzwingen kann.
Bei RETFIE (Ausnahme GIEL) und bei RETURN würde ich immer "FAST" nehmen, da hier automatisch immer die geretten Register (W, STATUS, BSR) übernommen werden.

picassTopic starter

Zitat von: pic18 in 20.09.2026, 15:46:16 CESTWichtig ist, das Du das IF im Interrupt manuell löscht, sonst wird beim Verlassen des Interrupts ein neuer ausgelöst.
Da hatte ich mich nicht korrekt ausgedrückt, was aber an der Problematik nichts ändert: die Rücksprunganweisung "retfie" setzt das GIE/GIEH-bit (nicht wie geschrieben das Flag-bit) und schaltet damit die Interrupts wieder frei. Wie dies zu verhindern ist, das war meine Frage.
Grüße, picass


pic18

willst Du nur ein einziges Mal den Interrupt ausführen? Dann setze doch im Interrupt GIE auf 0, alternativ kannst Du auch IE auf 0 setzen

picassTopic starter

So die Theorie...., also die deinige! In der Praxis steht die klare Aussage des Datenblattes dagegen, in welcher es  heißt:
"The "return-from-interrupt"-instruction, RETFIE, exits the interrupt routine and sets the GIE/GIEH bit ...., which re-enables interrupts." Zitatende

Das zu beackernde Feld der Interrupts hält noch so manche Widersprüche bereit. Nur als kleines Beispiel: die weiter oben zweimal genannte Modifikation "retfie fast" ist im Datenblatt des PIC18F14K22 nicht dokumentiert. Entprechend gibt es diesen Befehl dann dort nicht.
Grüße, picass


pic18

#31
Zitat von: picass in 21.09.2026, 15:29:36 CEST"retfie fast" ist im Datenblatt des PIC18F14K22 nicht dokumentier

3.1.3 FAST REGISTER STACK

s Fast Call/Return mode select bit s = 0: do not update into/from shadow registers s = 1: certain registers loaded into/from shadow registers (Fast mode)

EXAMPLE 3-1:
RETURN, FAST ;RESTORE VALUES SAVED ;IN FAST REGISTER STACK

Zitat von: picass in 21.09.2026, 15:29:36 CESTexits the interrupt routine and sets the GIE/GIEH bit
ich glaube da hast du was falsch verstanden. JA GIE wird im Interrupt gesperrt und danach wieder freigegeben. Aber wenn du das GIE - Bit löscht, dann wird kein Interrupt mehr ausgeführt. So meine Meinung.

picassTopic starter

#32
Verstehen....hin, Meinung.....her! Die Gemengelage bleibt im günstigsten Falle unklar. Die Aussage im Datenblatt ist ja nicht misszuverstehen. Und sie macht ja auch nur Sinn, wenn vorher das globale IRQ-Bit, also z.B. GIEH gelöscht wurde. Denn ein ohnehin gesetztes GIEH-Bit braucht nicht erneut gesetzt zu werden. In hatten Fällen muss das mal praktisch überprüft werden. Dahinter steckt wohl das Standard-Verhalten, dass nach dem Auswerten, bzw. dem Abarbeiten der IRQ-Routine die Interrupt-Situation erhalten bleiben soll. Was in den meisten Fällen ja auch Sinn macht. Wenn man das jedoch nicht möchte, sondern nur einen einzigen IRQ und dann erst mal keinen mehr, dann ist es wohl erforderlich, nicht nur das GIEH-bit zu löschen und/oder das spezielle IRQ-Enable-bit wie z.B. RABIF, sondern zudem auch auf die Anweisung "RETFIE" zu verzichten.

Hinter all dem steckt vor allem die "gängige Sprachpraxis". In all den Beispielen für Interrupts, die ich bislang gelesen hatte, fanden sich immer diese Stereotypen "bra IRQ-Prog" und dort "retfie". Was anderes schien es nicht zu geben. Das hatte ich jetzt aber mal - anders - ausprobiert und siehe da, es klappte. In der IRQ-Routine lassen sich also auch die anderen, gewöhnlichen (Rück-) Sprung-Befehle verwenden. Darum ging es mir letztlich.
Grüße, picass

picassTopic starter

#33
Zitat von: pic18 in 20.09.2026, 18:13:41 CEST....willst Du nur ein einziges Mal den Interrupt ausführen? Dann setze doch im Interrupt GIE auf 0..........
Treibe meine Studien zu dem "weißen Fleck" namens Interrupt voran. Im Moment beschäftigte mich noch die Anweisung "RETFIE", von der es im Datenblatt ja heißt, dass sie das Setzen des GIE/GIEH-Bits beim Verlassen der irq-Routine bewirkt. Habe das an einem erschütternd einfachen Prog gerade getestet. In diesem Prog gibt es nur drei Routinen: main, ruptus und butak (mein Standardname für Zeitschleifen). In main werden zwei LEDs getoggelt mit kurzen Pausen, um das vernünftig beobachten zu können. In ruptus - ihr ahnt, wozu die gut sein soll - werden zwei andere LEDs getoggelt, wieder mit Pausen.
Das Prog läuft prima: die 2 LEDs außen blinken sich gegenseitig an und bei Tastendruck tun das dann die beiden anderen, wenn auch nur kurzfristig. So passt alles, insbesondere der IRQ. Wenn ich nun in der ruptus-routine das GIEH-Bit - also das für den high-irq - lösche, dann hat das null-komma-null Wirkung. Kaum ist der PIC aus dem IRQ raus und beschäftigt sich mit den beiden äußeren LEDs, ist ein IRQ sofort oder gleich oder auch später - also jederzeit - wieder möglich. Folglich kann man sich fürderhin dieses Löschen in der IRQ-Routine verkneifen, die RETFIE-Anweisung übersteuert es zuverlässig wieder.

Gänzlich davon unberührt ist das Löschen des IRQ-Flags. Das hat ja einen ganz anderen Job und dessen Löschen in der IRQ-Routine soll verhindern, dass derselbe IRQ, welcher das Verlassen des Progs und den Sprung in die ruptus-Routine bewirkte, gleich Mehrfach-Interrupts auslöst.

Macht voll Spass, dieses IRQ-Gefummel. Wenn ich mir so ansehe, wie viele Anweisungen im Prog nötig sind, um auch nur einen einzigen IRQ auszulösen, dann....... bin ich mindestens beeindruckt. Oder doch knurrig, allein wegen der vielen Arbeit für so'n ollen IRQ.
Grüße, picass

pic18

Zitat von: picass in 25.09.2026, 16:39:35 CESTdass sie das Setzen des GIE/GIEH-Bits beim Verlassen der irq-Routine bewirkt. 
hätte ich nicht gedacht. Hast Du mal das IE (RBIE) Bit im Interrupt gelöscht? Ich denke das wird nicht beim Austritt vom Interrupt gesetzt.
Like Like x 1 View List

picassTopic starter

Wie zu erwarten, verhindert das Löschen des Port-Change-Bits RABIE einen weiteren IRQ. Aber nun tritt ein neues, düsteres Phänomen auf: es gibt erst überhaupt keinen IRQ mehr, was nicht sein dürfte, weil dieses Löschen ja nur in der IRQ-Routine erfolgt, und die ja erst nach einem IRQ angesteuert werden düfte. Aber dazu kommt es jetzt erst gar nicht mehr. Voll der neue Horror...
Habe das Test-Prog unten angehängt. Da es quasi nur die erweiterte Luxus-Version von "hello world" enthält, dürfte eine Einarbeitung kein Prob sein.
Grüße, picass
irqtest02.7z

Ottmar

Hallo,
es sind beim Interrupt PORTA/PORTB Change ein paar Kleinigkeiten zu beachten.
Ich habe das Program von picass mit MPLAB 8.5 ohne Probleme zum Laufen gebracht, allerdings hat die ISR wie von ihm geschildert nicht funktioniert.
Es bedurfte einiger Überlegungen und einiger Lesearbeit bis ich es hinbekommen habe:
1. Es muss entschieden werden ob der IRQ mit steigender/fallender Flanke durchlaufen werden soll
2. Ich weiß nicht warum, habe es aber so gelesen, der betreffende Port muss "in sich selbst gelesen werden: movf  PORTA,f.

MAIN_PROG CODE                        ; let linker place main program
main:
   ;LED_TEST
   nop
   movlw    b'00001111'   ;RC3:0 ein
   movwf    LED_LAT
   call     butak

   call     butak
   call     butak
   call     butak
   clrf     LED_LAT
main_loop
   btg      LATC,RC0
   call     butak
   btg      LATC,RC1 
   call  butak
   bsf   IOCA,BTTN_ISR
   BRA   main_loop      ; loop program counter
;----------------------------------------------------------------
HIGH_ISR:
   btfsc PORTA,RA2      ;interrupt mit fallender Flankeausgelöst?   
   BRA   high_isr_clear ;nein
   ;
   btg   LATC,RC2
   call  butak
   call  butak
   btg   LATC,RC3
   call  butak
   call  butak
   bcf   LATC,RC2
   bcf   LATC,RC3 
   ;
high_isr_clear: 
   movf  PORTA,f        ;Liest PortB (in sich selbst)
                        ;behebt type-mismatch   
   bcf   INTCON,RABIF
high_isr_end:
   RETFIE  FAST

Zum Video:
Die obere linke Doppelgruppe steht für die LEDs in der main_loop. Mit dem Bleistift wird der Taster betätigt, welcher RA2 auf Low zieht und damit den Interrupt auslöst, der einmal durchlaufen wird (LED-Gruppe oben rechts). Anschließend blinken die LEDs in der main_loop wieder und die LEDs in der ISR bleiben dauerhaft aus, bis der Taster RA2 erneut betätigtwird

Grüße Ottmar

Ottmar

Nachtrag:
Das  obere Oszillogramm  (gelb) zeigt das Schalten einer LED in mainloop. Die Spur darunter zeigt das Schalten einer LED in der ISR, sobald der PORT-on-change-button RA2 gedrück wird. Die Dauer des Tasterdrucks spielt keine Rolle, der Interrupt wird nur einmal durchlaufen. Wegen der Dauer des Tastendrucks (2x Delay in der ISR) wird die Ausgabe in mainloop sichtbar unterbrochen.
In der Anlage  auch das GEÄNDERTE ASM-File von picass, in dem lediglich die Änderungen vorgenommen worden sind, um die ISR wie gewünscht auszuführen.

Schnellantwort

Name:
Verifizierung:
Bitte lassen Sie dieses Feld leer:
Geben Sie die Buchstaben aus dem Bild ein
Buchstaben anhören / Neues Bild laden

Geben Sie die Buchstaben aus dem Bild ein:

Tastenkürzel: Alt+S Beitrag schreiben oder Alt+P für Vorschau

🡱 🡳