Von der klassischen Usermode-Programmierung zur Echtzeit-Programmierung in TwinCAT

Dieser Artikel soll die Unterschiede der Programmierkonzepte beschreiben, die zwischen einer normalen Usermode-Programmierung in einer Programmiersprache wie C++, C# oder Java zu der Echtzeit-Programmierung in TwinCAT bestehen.

Dieser Artikel bezieht sich dabei insbesondere auf die TwinCAT-Echtzeit-Programmierung mit TwinCAT C++, da gerade hier auf der einen Seite wesentliche Vorkenntnisse der C++ Programmierung eingebracht werden können, auf der anderen Seite die Ablaufeigenschaften des TwinCAT Echtzeitsystems Berücksichtigung finden müssen.

Von der klassischen Usermode-Programmierung zur Echtzeit-Programmierung in TwinCAT 1:

Beim klassischen Usermode-Programmieren z.B. in C# wird ein Programm erstellt, welches von einem Betriebssystem ausgeführt wird.

Das Programm wird hierbei vom Betriebssystem gestartet und kann selbstständig ablaufen, d.h. auch es hat die volle Kontrolle auf seinen eigenen Ablauf wie Threading und Speicherverwaltung. Um Multitasking zu ermöglichen unterbricht das Betriebssystem ein solches Programm zu einem beliebigen Zeitpunkt und für eine beliebige Zeit. Das Programm bekommt eine solche Unterbrechung nicht mit. Es ist Aufgabe des Betriebssystems dafür zu sorgen, dass der Nutzer von diesen Unterbrechungen nichts mitbekommt. Der Datenaustausch des Programms mit der Umwelt erfolgt dabei Event-getrieben, d.h. nicht-deterministisch und häufig blockierend.

Für einen Ablauf unter Echtzeitanforderungen ist das Verhalten nicht hinreichend, denn die Anwendung selber muss sich auf die bereitstehenden Ressourcen verlassen können um Echtzeiteigenschaften (Antwortgarantien) zusichern zu können.

Von der klassischen Usermode-Programmierung zur Echtzeit-Programmierung in TwinCAT 2:

Für TwinCAT C++ wird deswegen der Grundgedanke aus der PLC aufgenommen: Das TwinCAT Echtzeitsystem verwaltet die Echtzeit Tasks, übernimmt das Scheduling und ruft einen Einstiegspunkt in dem Programmcode zyklisch auf. Das Programm muss innerhalb der bereitstehenden Zykluslänge abgearbeitet sein und die Kontrolle zurückliefern. Das TwinCAT System stellt dabei die Daten aus dem I/O Bereich in Prozessabbildern bereit, so dass ein konsistenter Zugriff garantiert werden kann. Hieraus ergibt sich, dass der Programmcode selber keine Mechanismen wie Threading verwenden kann.

Nebenläufigkeit

Von der klassischen Usermode-Programmierung zur Echtzeit-Programmierung in TwinCAT 3:

Bei der klassischen Programmierung im Usermode liegt die Kontrolle der Nebenläufigkeit im Bereich des Programms. Hier werden Threads gestartet und diese kommunizieren untereinander. All diese Mechanismen benötigen Ressourcen, die allokiert und freigegeben werden müssen, was die Echtzeit-fähigkeit gefährden kann. Die Kommunikation zwischen den Threads erfolgt Event-basiert, sodass ein aufrufender Thread keine Kontrolle über den Abarbeitungszeitpunkt im aufgerufenen Thread besitzt.

In TwinCAT werden Tasks genutzt, um Module aufzurufen, was somit eine Nebenläufigkeit darstellt. Tasks sind jeweils einem Core zugeordnet und haben Zykluszeiten sowie Prioritäten, was dazu führt, dass ein höher priorer Task einen niedriger prioren Task unterbrechen kann. Bei Verwendung von mehreren Cores werden Tasks tatsächlich nebenläufig ausgeführt.

Von der klassischen Usermode-Programmierung zur Echtzeit-Programmierung in TwinCAT 4:

Module können untereinander kommunizieren, sodass bei Nebenläufigkeit die Datenkonsistenz sichergestellt werden muss.
Einen Datenaustausch über die Task-Grenzen hinweg wird z.B. durch das Mapping ermöglicht. Bei direktem Zugriff mittels Methoden ist der Datenzugriff z.B. durch CriticalSections zu schützen.

Startup-/Shutdown-Verhalten

Der TwinCAT C++ Code wird im sogenannten „Kernel Kontext“ und „TwinCAT Echtzeit-Kontext“ und nicht als UserMode-Anwendung ausgeführt.

Beim Hoch-/Runterfahren der Module wird Code zur (De)Initialisierung zunächst im Kernel Kontext ausgeführt; erst die letzte Phase sowie die zyklischen Aufrufe werden im TwinCAT Echtzeit-Kontext ausgeführt.

Details sind im Kapitel Modul-Statemachine beschrieben.

Speichermanagement

TwinCAT bringt ein eigenes Speichermanagement mit, welches auch im Echtzeit Kontext verwendet werden kann. Dieser Speicher wird aus dem so genannten „Nonpaged Pool“, der durch das Betriebssystem bereitgestellt wird, bezogen. In diesem Speicher werden die TcCOM Module mit ihrem Speicherbedarf instanziiert.

Zusätzlich wird der sogenannte „Routerspeicher“ in diesem Speicherbereich durch TwinCAT bereitgestellt, aus dem im Echtzeit-Kontext dynamisch von den TcCOM Modulen Speicher allokiert werden kann (z.B. mit Operator new).

Von der klassischen Usermode-Programmierung zur Echtzeit-Programmierung in TwinCAT 5:

Generell sollte Speicher möglichst vorab allokiert werden und nicht im zyklischen Code. Bei jeder Allokation muss geprüft werden, ob der Speicher auch wirklich zur Verfügung steht. Bei Allokationen im zyklischen Code hängt der Ablauf dann also von der Verfügbarkeit des Speichers ab.