[LINUX] Ich möchte Interrupts auf dem Raspberry Pi deaktivieren (≒ DI / EI)

Hintergrund

Auf Raspberry Pi, das unter Linux verwendet werden soll, läuft das Benutzerprogramm natürlich unter dem OS-Scheduler. Daher ist es sehr schwierig, ein zeitstriktes Programm zu schreiben. Einfach gesagt, ich bin nicht gut darin, etwas in regelmäßigen Abständen genau zu verarbeiten. In einem solchen Fall handelt es sich um einen Timer-Interrupt oder eine Taktabfrage, aber ich denke, dass es viele Fälle gibt, in denen Sie Letzteres verwenden möchten, wenn Sie den geringen Overhead und die Einfachheit des Kontexts berücksichtigen. Zu diesem Zeitpunkt stören verschiedene Unterbrechungen. Ich dachte, es wäre schön, wenn ich einige einfache vorübergehende Unterbrechungen verbieten könnte, und ich habe verschiedene Dinge ausprobiert, also habe ich einen Artikel geschrieben. Es ist der DI / EI von Z80, der dem alten Mann vertraut ist.

Was du tun kannst

Ich habe ein Programm geschrieben (später beschrieben), das gettimeofday () abfragt und in einem Zyklus von 100 us arbeitet. Hier sind die Ergebnisse (gemessener Zyklus) für den Standardfall und wenn Interrupts deaktiviert sind. rpiint.png

Wie ist das? Es ist auf einen Blick offensichtlich. Wenn Sie Interrupts deaktivieren, können Sie verschiedene Timings steuern. Zum Beispiel Infrarot-Fernbedienung. (Hinweis: Das Deaktivieren von Interrupts hat natürlich viele Nebenwirkungen. Minimieren Sie die Deaktivierungszeit.)

Übersicht, wie es geht

Laut dem Handbuch von SoC BCM2835 / 2837 von Raspberry Pi scheint es "Interrupt Disable Register" und "Interrupt Enable Register" zu geben, also schlagen Sie sie direkt. Das ist das bekannte "/ dev / mem" in GPIO zu "mmap ()".

  1. mmap (), damit Sie die physikalische Adresse direkt treffen können.
  2. Lesen Sie das Register und speichern Sie die aktuellen Einstellungsinformationen.
  3. Schreiben Sie alle Einsen, um das Deaktivierungsregister zu unterbrechen und alle Interrupts zu deaktivieren.
  4. Führen Sie die erforderliche Verarbeitung durch, die zeitaufwändig ist.
  5. Schreiben Sie den in 2. gespeicherten Wert in das Interrupt-Aktivierungsregister und bringen Sie ihn in den Ausgangszustand zurück.

Und das ist alles. In Bezug auf Z80 ist 2-3 "DI" und 5 ist "EI".

Codebeispiel

Dies ist der Code, mit dem die Daten für das obige Diagramm erstellt werden. Bitte ändern Sie den Teil von #define PERI_BASE PI? _PERI_BASE entsprechend Ihrem Raspberry Pi.

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/time.h>

#define BLOCK_SIZE (4 * 1024)
#define PI2_PERI_BASE 0x3f000000
#define PI1_PERI_BASE 0x20000000
#define PERI_BASE PI1_PERI_BASE // Raspberry 0/1 or 2/3

//Angegebene Zeit(us)Warten Sie durch Abfragen
inline static void waitUs(struct timeval tv_zero, int until_us) {
  struct timeval tv;
  int us;

  while (1) {
    gettimeofday(&tv, NULL);
    us = (tv.tv_sec - tv_zero.tv_sec) * 1000000 + (tv.tv_usec - tv_zero.tv_usec);
    if (us >= until_us) break;
  }
}


int main() {
  int mem_fd;
  char *map;
  int i;
  int us_next;
  struct timeval tv0, tv1;
  int dt[10000];
  int irq1, irq2, irq3;   //Speichern wir die Interrupt-Informationen(Zum Schluss schreibe zurück an irqen)

  volatile unsigned int *irqen1;
  volatile unsigned int *irqen2;
  volatile unsigned int *irqen3;
  volatile unsigned int *irqdi1;
  volatile unsigned int *irqdi2;
  volatile unsigned int *irqdi3;

  if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0) return -1;
  map = (char*) mmap(NULL,
		     BLOCK_SIZE,
		     PROT_READ | PROT_WRITE,
		     MAP_SHARED,
		     mem_fd,
		     PERI_BASE + 0xb000
		     );
  if (map == MAP_FAILED)  return -1;
  irqen1 = (volatile unsigned int *) (map + 0x210);
  irqen2 = (volatile unsigned int *) (map + 0x214);
  irqen3 = (volatile unsigned int *) (map + 0x218);
  irqdi1 = (volatile unsigned int *) (map + 0x21c);
  irqdi2 = (volatile unsigned int *) (map + 0x220);
  irqdi3 = (volatile unsigned int *) (map + 0x224);

  gettimeofday(&tv0, NULL);
  irq1 = *irqen1;
  irq2 = *irqen2;
  irq3 = *irqen3;
  //Deaktivieren Sie alle Interrupts in den folgenden 3 Zeilen
  *irqdi1 = 0xffffffff;
  *irqdi2 = 0xffffffff;
  *irqdi3 = 0xffffffff;
  
  for (i = 0, us_next = 100; i < 10000; i++, us_next += 100) {
    waitUs(tv0, us_next);
    gettimeofday(&tv1, NULL);
    dt[i] = (tv1.tv_usec - tv0.tv_usec) + (tv1.tv_sec - tv0.tv_sec) * 1000000;
  }
  //Stellen Sie das Interrupt-Berechtigungsflag in den folgenden drei Zeilen wieder her.
  *irqen1 = irq1;
  *irqen2 = irq2;
  *irqen3 = irq3;
  //Ergebnisanzeige
  for (i = 1; i < 10000; i++) {
    printf("%d\n", dt[i] - dt[i - 1]);
  }
  return 0;
}


Recommended Posts

Ich möchte Interrupts auf dem Raspberry Pi deaktivieren (≒ DI / EI)
Ich möchte Python GUI ausführen, wenn Raspberry Pi startet
Ich möchte Linux auf dem Mac verwenden
So installieren Sie NumPy auf Raspeye
Ich möchte Android-Apps auf Android entwickeln
Hinweis: Ich möchte die Heimautomation mit Home Assistant + Raspberry Pi + Sensor Nr. 1 durchführen
Ich möchte pyenv + pipenv auch unter Windows machen
Ich möchte die Eingabe / Ausgabe von Dateien unter Linux protokollieren
Stellen Sie mit Python auf Raspberry Pi eine Verbindung zu MySQL her
Ich habe eine Frage. Protokollpuffer für Himbeer-Pi-3-Modell B können nicht erstellt werden.
Pigpio auf Himbeer-Pi
Cython auf Raspberry Pi
Ich möchte Android-Apps auf Android entwickeln (Debug)
Ich möchte ein beliebtes Paket auf PyPi finden
Ich möchte Lambda mit Python auf Mac AWS!
Ich möchte OpenJDK 11 mit Ubuntu Linux 18.04 LTS / 18.10 verwenden
Ausgabe auf "7 Segment LED" mit Python mit Raspberry Pi 3!
Ich möchte Wake On LAN vollautomatisch ausführen
Ich möchte über die Verbindungsumgebung benachrichtigt werden, wenn RaspberryPi eine Verbindung zum Netzwerk herstellt
Einführung von PyMySQL in Himbeer-Pi3
Ich möchte SUDOKU lösen
Ich möchte meine Abschlussarbeit über IPython Notebook ankündigen
Ich habe versucht, [eine bestimmte Aufgabe] mit einem Raspeltorte zu automatisieren
Pyenv auf Raspberry Pi eingeführt
Verwenden Sie NeoPixel mit Himbeerkuchen
Installieren Sie OpenCV4 auf Raspberry Pi 3
Installieren Sie TensorFlow 1.15.0 auf Raspberry Pi
Ich habe die Daten von Raspberry Pi an GCP gesendet (kostenlos)
Über den Fehler, den ich beim Versuch, Adafruit_DHT von Python auf Raspberry Pi zu verwenden, festgestellt habe
Ich möchte Shortcut-Übersetzungen wie die DeepL-App auch unter Linux verwenden
Ich habe versucht, die Bewässerung des Pflanzgefäßes mit Raspberry Pi zu automatisieren
Ich habe mit Razpai einen Webserver erstellt, um Anime zu schauen
Verwenden Sie Python auf Raspberry Pi 3, um die LED zu beleuchten (Hello World)
So spielen Sie Musikdateien (WAV / MP3) auf Raspberry Pi Python ab
Führen Sie Polyglot auf Raspberry Pi aus, um eine morphologische Analyse auf Englisch durchzuführen
Port FreeRTOS auf Raspberry Pi 4B
Testen der Kommunikation mit Raspberry Pi
MQTT auf Raspberry Pi und Mac
Himbeer Pi 4 Centos7 auf Docker installieren
Installieren Sie ghoto2 auf Raspberry Pi (Hinweis)
Ausgabe von Raspberry Pi an Line
Versuchen Sie es mit ArUco mit Raspberry Pi
OpenCV-Installationsverfahren auf Raspberry Pi
Ich möchte Bilder kratzen und trainieren
Ich möchte ○○ mit Pandas machen
Ein- / Ausschalten von Raspberry Pi mit Arduino
Erkennen Sie den Schalterstatus mit Raspberry Pi 3
Ich möchte Yolos Anmerkung kopieren
Installieren Sie OpenMedia Vault 5 auf Raspberry Pi 4
Ich möchte mit Python debuggen
L Chika mit Himbeer-Pi C #
[Raspberry Pi] Python wurde standardmäßig in Python3 geändert
Erstellen Sie wxPython unter Ubuntu 20.04 auf Himbeer-Pi 4
Ich möchte Twitter mit Python twittern, bin aber süchtig danach
Verwenden Sie Python auf Raspberry Pi 3, um die LED mit Schaltersteuerung zu beleuchten!
Ich möchte ein Bild auf Jupyter Notebook mit OpenCV (Mac) anzeigen.
Ich habe versucht, mit Raspeye 4 (Python Edition) ein signalähnliches Signal zu erzeugen.