Document ID: /fineweb-2-swissfilter-quality_10-filterrobots/filtered/03415.jsonl.gz/768

Initialisierung und Startup
Die Runtime erlaubt die volle Kontrolle über die Initialisierung und Start der Zielhardware. Dazu werden verschiedene Callback Methoden aufgerufen.
Zuerst wird eine Methode für die Hardware Initialisierung aufgerufen. In dieser kann z.B. die Click Frequenz, Interrupt Prioritäten oder Pin Muxing konfiguriert werden.
Anschliessend wird bei jedem Active Part die Initialize() Methode aufgerufen um den Zustand zu initialisieren.
Nach abgeschlossener Initialisierung, wird bei jedem active part die Start() Methode aufgerufen. Dies erlaubt es, bereits bei Start der Firmware Timer zu starten oder Nachrichten zu verschicken. Zuletzt werden alle Interrupts der Zielhardware aktiviert und die Runtime gestartet. Diese führt nun getrieben durch den System Tick Interrupt den Message Loop aus bis die Hardware ausgeschaltet wird (siege auch Idle Verhalten).
Idle Verhalten
Wenn die Runtime keine Timer oder Nachrichten zu Verarbeiten hat, wird die OnIdle() Callback Funktion aufgerufen. Dies erlaubt es dem Entwickler, genau zu definieren, wie sich die Hardware in diesem Fall verhalten soll. Es ist z.B. Möglich in einen Stromsparmodus zu wechseln. Die Runtime wird automatisch durch den nächsten Hardware Interrupt aufgeweckt (z.B. SysTick).
Kommunikation
Die Runtime übernimmt die Kommunikation zwischen den Active Parts. Dazu wird ein Event Buffer im Arbeitsspeicher verwendet. Wenn ein Active Part eine Nachricht verschickt, kopiert die Runtime diese in den Buffer. Nun wird jeder Empfänger der Nachricht anhand der Priorität (siehe unten) aufgerufen. Die Nachricht verbleibt im Buffer und kann von den Active Parts gelesenes aber nicht verändert werden. Nach Abschluss der Verarbeitung wird der Slot im Event Buffer wieder für eine neue Nachricht freigegeben.
Prioritäten
Um die Reihenfolge der Verarbeitung bei gleichzeitig versendeten Nachrichten zu definieren, kann jedem Active Part eine Priorität von 1 bis 32 vergeben werden. Die Runtime wird immer zuerst Nachrichten an Active Parts mit höherer Priorität verarbeiten. Grundsätzlich wird eine Nachricht vollständig abgearbeitet (Coorporative Multitasking) und darf daher nicht blockieren. Wird eine Nachricht an ein höher priorisiertes Active Part verschickt (auch aus einem Interrupt), wird die Runtime dieses zuerst abhandeln und anschliessend die Verarbeitung des Senders fortsetzen (Preemtive Scheduling).
Software Timer
Software Timer können von jedem Active Part gestartet und gestoppt werden. Wenn ein Timer ausläuft, wird das entsprechende Active Part über einen Methodenaufruf benachrichtig, genau wie wenn es eine Nachricht erhalten hat.
Hardware Interrupts
Hardware Interrupts werden mittels ISR Methoden (Interrupt Service Routine) implementiert. Diese Methoden sind in der Interrupt Tabelle (Interrupt Vector Table)hinterlegt und werden von Mikroprozessor angesprungen, wenn der entsprechende Interrupt aufgerufen wird. Innerhalb der ISR wird die Runtime über das Betreten und Verlassen des ISR informiert. Alle innerhalb des ISR verschickten Nachrichten werden nach verlassen des ISR umgehend verarbeitet. (Siehe Kommunikation und Prioritäten).
Bei verschachtelten Interrupts (Interrupt wird durch höher priorisierten Interrupt unterbrochen: Nested IRQ) wird die Runtime die Nachrichten verarbeiteten, sobald der letzte Interrupt verlassen wurde. Welche Interrupts andere Interrupts unterbrechen können wird durch die Hardware Konfiguration des NVIC (Nested Vector Interrupt Controllers) des ARM Cores festgelegt.
Nebenläufigkeit
Die Runtime übernimmt die Handhabung der Nebenläufigkeit. Dazu wird sie in für kritische nicht atomare Operationen (z.B. Lesen, Verändern, Schreiben) der Runtime die Hardware Interrupts kurzzeitig ausschaltet. Das stellt sicher, das keine Konflikte beim Zugriff auf Message Buffer etc. entstehen. Der Code innerhalb von Active Parts muss sich daher nicht um Nebenläufigkeit kümmern und kann geschrieben werden als ob die Methode ganz alleine auf dem System laufen würde. Wichtig hierbei ist, das der Zugriff auf Hardware Ressourcen (z.B. Peripherien wie GPIO Pins, USART, ..) nur durch jeweils ein einziges Active Part erfolgen darf. Falls mehrere Active Part die selbe Ressource verwenden müssen, sollte ein Active Part dien Zugriff kapseln und von den Anderen durch Nachrichten angesprochen werden.
Ausnahmen
Die DATAFLOW Runtime erlaubt es auch, das Verhalten bei Ausnahmen zu definieren. Dazu werden 3 Arten von Assertions verwendet:
- Compiler
- Debug
- Ex
AssertCompiler: Wird beim Kompilieren der Applikation ausgelöst. Kann verwendet werden um statische Annahmen zu überprüfen. z.B Grösse von Buffern oder Typen.
AsstertDebug: Wird zur Laufzeit ausgelöst. Kann verwendet werden um Fehler im Code zu entdecken wenn z.B. ungültige Parameter übergeben werden.
AssertEx: Wird verwendet um kritische Fehler zu behandeln, die ein normales Ausführen der Applikation verunmöglichen.
Das Verhalten bei AssertDebug und AssertEx kann über Callback Funktionen definiert werden. Dies erlaubt je nach Anwendung, das verhalten anzupassen und z.B. einen Neustart auszulösen, die Applikation anzuhalten oder andere Vorkehrungen zu treffen.
Logging Framework
Als Option bietet die Runtime ein Logging Framework an. Dieses erlaubt das registrieren eines Active Parts als Logger. Über eine Runtime Funktion kann anschliessend jederzeit eine Log Nachricht an dieses Active Part gesendet werden, ohne das dazu Channels und Ports definiert werden müssen. Das Format der Log Nachricht ist ebenfalls frei definierbar, genauso wie die Priorität des Loggers.
Runtime Statistik
Die DATAFLOW Runtime bringt eine Laufzeit Statistik Funktion mit. Diese muss beim kompilieren der Runtime aktiviert werden, da zusätzliche Aufrufe im Code eingebaut werden müssten, um die Daten zu erfassen. Im Binary Packages (siehe unten) gibt es eine Bibliothek mit aktivierter Statistik. Wann die Statistik aktiviert wurde, werden folgende Daten erfasst und als statische Variablen im Debugger ausgelesen werden:
- Auslastung Event Buffer
- Auslastung Timer Buffer
- Verweildauer der Aufrufe in den einzelnen Active Parts
- CPU Load (Benötigt einen Hardware Timer für akkurate Ergebnisse).