Runtime, Queries und Native Worker
Aufbau der STM32-Runtime, Query-Pfade 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.