Zum Inhalt

Dokumentation

Runtime, Queries und Native Worker

Aufbau der STM32-Runtime, Query-Pfade und Native Worker.

Runtime, Queries und Native Worker

Die Standard-Runtime

Die Runtime stellt bis zu 16 Instanz-Slots bereit. Die Standardkonfiguration verwendet drei getrennte Funktionspfade.

Master-Pfad – LIN1

Host
 ↓
Slot 0   master_tx_query
 ↓
Slot 2   master_native
 ↓
LIN1
 ↓
Slot 1   master_rx_query
 ↓
Host

master_native führt die eigentlichen LIN-Operationen auf LIN1 aus.

Slave-Pfad – LIN2

Host
 ↓
Slot 3   slave_tx_query
 ↓
Slot 5   slave_native
 ↓
LIN2
 ↓
Slot 4   slave_rx_query
 ↓
Host

slave_native verwendet denselben generischen LIN-Worker wie der Master-Pfad, jedoch mit LIN2 als physischem Kanal.

Logging-Pfad

Host
 ↓
Slot 6   logging_tx_query
 ↓
Slot 8   logging_native
 ↓
Slot 7   logging_rx_query
 ↓
Host

Die Slots 9 bis 15 sind in der Standardkonfiguration frei und können für eigene Runtime-Anwendungen verwendet werden.

Welche Datei gehört zu welcher Schicht?

Die Runtime-Struktur lässt sich direkt auf das Repository abbilden.

Linux-Anwendung
  |
  |  host/beiis_lin/client.py
  v
beiis-lind
  |
  |  host/beiis_lin/daemon.py
  |  host/beiis_lin/socket_protocol.py
  v
I²C + GPIO6
  |
  |  host/beiis_lin/i2c_transport.py
  |  host/beiis_lin/gpio_irq.py
  v
Runtime-Dispatcher
  |
  |  stm32/boards/BEIIS_LIN_HAT/frozen/beiis_runtime.py
  v
Query
  |
  |  stm32/micropython/apps/query.py
  v
Native Worker
  |
  |  stm32/micropython/apps/lin_native.py
  v
MicroPython-Binding
  |
  |  stm32/micropython/modules/lin/modlin.c
  v
native LIN-Funktionen
  |
  |  stm32/lib/lin/lin.c
  |  stm32/lib/lin/lin.h
  v
boardspezifische Hardware-Anbindung
  |
  |  stm32/boards/BEIIS_LIN_HAT/board_init.c
  v
LIN1 / LIN2

Damit ist auch klar, auf welcher Ebene eine Erweiterung erfolgen sollte:

neue Linux-Anwendung         -> host/ oder eigene Anwendung
neue Query-/App-Logik        -> stm32/micropython/apps/
neue MicroPython-Funktion    -> stm32/micropython/modules/
neue zeitkritische LIN-Funktion -> stm32/lib/lin/
neue Hardware-Anbindung      -> board_init.c

Was macht eine Query?

Eine Query ist ein kleiner, wiederverwendbarer Transportbaustein.

TX-Query   Host -> Worker
RX-Query   Worker -> Host

Die Query kennt das eigentliche LIN-Protokoll nicht. Sie transportiert Payload und Channel zum konfigurierten Worker beziehungsweise zurück zum Host.

Dadurch können dieselben Query-Bausteine für unterschiedliche Anwendungen verwendet werden.

Was macht der Native Worker?

master_native und slave_native verwenden beide lin_native.py.

Der Worker übersetzt Runtime-Nachrichten in Aufrufe des nativen LIN-Moduls.

Die Operationen sind nach Aufgabe gruppiert:

Verbindung und Konfiguration

0x00  PING     Worker prüfen
0x01  INIT     LIN-Baudrate setzen

Master

0x02  SEND       vollständiges Master-Frame senden
0x03  REQUEST    Slave-Antwort anfordern

Slave

0x04  SLAVE_SET       Slave-Antwort konfigurieren
0x05  SLAVE_CLEAR     Slave-Antwort löschen
0x08  SLAVE_RX_SET    Slave-Empfang konfigurieren
0x09  SLAVE_RX_RECV   empfangene Daten abholen

Diagnose

0x06  LEDS_GET
0x07  LEDS_SET

Request und Reply

Request:

Byte 0      Operation
Byte 1..    operationsspezifische Daten

Reply:

Byte 0      Operation
Byte 1      Status
Byte 2..    Ergebnis oder Fehlertext

Status:

0  OK
1  ungültiger Request
2  LIN-/Native-Fehler
3  interner Worker-Fehler

Höhere Anwendungsschichten mit eigenen Workern

Die Standard-Worker sind absichtlich generisch. Sie bilden einzelne LIN-Operationen ab.

Ein eigener Worker kann dagegen eine komplette Anwendungsschicht übernehmen.

Beispiel:

C- oder Python-Anwendung
          |
          | "Setze Sensorwert auf 42"
          v
      TX-Query
          |
          v
 eigener Sensor-Worker
          |
          | erzeugt selbst die nötigen LIN-Frames
          | verwaltet Zustände
          | reagiert auf Busereignisse
          v
      RX-Query
          |
          | "Sensorwert übernommen"
          v
C- oder Python-Anwendung

In diesem Fall muss die Host-Anwendung nicht mehr jeden einzelnen SEND- oder REQUEST-Befehl selbst auslösen.

Interrupt zum Raspberry Pi

Der Interrupt ist keine Eigenschaft der Query selbst.

Der Mikrocontroller besitzt eine allgemeine Host-Interruptleitung über PC6 zur Raspberry-Pi-GPIO6.

Sie wird verwendet, wenn hostseitig relevante Daten bereitstehen. beiis-lind wartet auf diesen Interrupt und liest danach die Daten über I²C.

Damit können auch höhere Runtime-Schichten Ereignisse an eine C- oder Python-Anwendung melden, ohne dass die Anwendung selbst GPIO oder I²C pollen muss.

Kommunikation zwischen Instanzen

Runtime-Anwendungen erhalten einen Context ctx.

source, channel, payload = await ctx.recv()

await ctx.send_host(channel, payload)
ctx.send_to("other_instance", payload, channel)
ctx.publish(channel, payload)

Damit können mehrere Worker lokal auf dem Mikrocontroller zusammenarbeiten.

Ressourcen

Eine Instanz kann Hardware-Ressourcen beanspruchen, beispielsweise:

lin1
lin2

Die Runtime verhindert, dass zwei laufende Instanzen gleichzeitig dieselbe deklarierte Ressource besitzen.

Einfache und erweiterte Nutzung

Die Runtime ist so aufgebaut, dass beide Wege möglich bleiben:

Direkte LIN-Steuerung

Host -> Query -> lin_native -> LIN

Eigene Anwendungsschicht

Host -> Query -> eigener Worker -> native Funktionen -> LIN

Damit bleibt der einfache Zugriff erhalten, während komplexere Protokolle schrittweise auf den Mikrocontroller verlagert werden können.