From conventional user mode programming to real-time programming in TwinCAT
This article describes the conceptual differences between standard user mode programming in a programming language such as C++, C# or Java, and real-time programming in TwinCAT.
The article particularly focuses on real-time programming with TwinCAT C++, because this is where previous knowledge with C++ programming comes to the fore and the sequence characteristics of the TwinCAT real-time system have to be taken into account.
With conventional user mode programming, e.g. in C#, a program is created, which is then executed by an operating system.
The program is started by the operating system and can run independently, i.e. it has full control over its own execution, including aspects such as threading and memory management. In order to enable multitasking, the operating system interrupts such a program at any time and for any period. The program does not register such an interruption. The operating system must ensure that such interruptions remain unnoticed by the user. The data exchange between the program and its environment is event-driven, i.e. non-deterministic and often blocking.
The behavior is not adequate for execution under real-time conditions, because the application itself must be able to rely on the available resources in order to be able to ensure real-time characteristics (response guarantees).
The basic idea of PLC is therefore adopted for TwinCAT C++: the TwinCAT real-time system manages the real-time tasks, handles the scheduling and cyclically calls an entry point in the program code. The program execution must be completed within the available cycle length and return the control. The TwinCAT system makes the data from the I/O area available in the process images, so that consistent access can be guaranteed. This means that the program code itself cannot use mechanisms such as threading.
Concurrency
With conventional programming in user mode, concurrency is controlled by the program. This is where threads are started, which communicate with each other. All these mechanisms require resources, which have to be allocated and enabled, which can compromise the real-time capability. The communication between the threads is event-based, so that a calling thread has no control over the processing time in the called thread.
In TwinCAT, tasks are used for calling modules, which therefore represents concurrency. Tasks are assigned to a core; they have cycle times and priorities, with the result that a higher-priority task can interrupt a lower-priority task. If several cores are used, tasks are executed concurrently in practice.
Modules can communicate with each other, so that data consistency has to be ensured in concurrency mode.
Data exchange across task boundaries is enabled through mapping, for example. When direct data access via methods is used, it must be protected through Critical sections, for example.
Startup/shutdown behavior
The TwinCAT C++ code is executed in the so-called "kernel context" and the "TwinCAT real-time context", not as a user mode application.
During startup/shutdown of the modules, code for (de)initialization is initially executed in the kernel context; only the last phase and the cyclic calls are executed in the TwinCAT real-time context.
Details are described in chapter Module state machine.
Memory management
TwinCAT has its own memory management, which can also be used in the real-time context. This memory is obtained from what is referred to as the "non-paged pool", which is provided by the operating system. In this memory the TcCOM modules are instantiated with their memory requirement.
In addition, the so-called "router memory" is provided by TwinCAT in this memory area, from which the TcCOM modules can allocate memory dynamically in the real-time-context (e.g. with the New operator).
If possible, memory should generally be allocated in advance, not in the cyclic code. During each allocation a check is required to verify that the memory is actually available. For allocations in the cyclic code, the execution therefore depends on the memory availability.