Work has continued on this project since my previous post. With this additional work there has also been a shift in the primary repository from Bitbucket to Github. This has been so as to take greater advantage of code quality and continuous build tools that are available with the latter platform. More significant than this however is a new project name – echidna.
An echidna, sometimes known as spiny anteaters, is an egg-laying mammal (monotreme) which is native to Australia and New Guinea. The analogy of a robust animal – with many spines on which one could hurt themselves were they to mishandle an echidna – seemed somewhat appropriate for this project.
The new repository can be found at https://github.com/61131/echidna and includes significant code coverage and a continuous integration pipeline.
After a hiatus of some time, I have returned to development on this project. This development has focused on extending the capability of the virtual machine such that it more fully supports the IEC 61131-3 standard including configuration definitions. The work that is in progress can be found in the devel branch on bitbucket.
One new and very interesting element of the work carried out to date is the implementation of preemptive scheduling within the virtual machine run-time.
In non-preemptive scheduling, logic is executed only when the execution of a program organisation unit has been completed. That is, once a program organisation unit is started, it must be run to completion before the next highest priority program organisation unit can be started. With preemptive scheduling however, when a program organisation unit is scheduled, it can interrupt the execution of a lower priority task.
This behaviour can be demonstrated with the test application tests/runtime/loop.txt which has the same program organisation unit associated with two tasks which will schedule execution at the same time (every 100 ms). Where the same priority is associated with each of these tasks, the average latency between triggering and the execution of the program organisation unit (on a virtual Linux host system) is 0.01 ms. However where the priority of one of these tasks is lowered, the average latency for the associated program organisation unit will rise to 0.3 ms, as a result of having to await the completion of execution of the higher priority program organisation unit.
Well, I found it interesting.
Following on from my previous post regarding the implementation of a Linux kernel module for application level Modbus protocol filtering, I have scratched a further itch and implemented a similar Linux kernel module for DNP3. This new filter kernel module – and corresponding patch for iptables 1.6, required in order to allow the specification and manipulation of firewall rules using DNP3 protocol nomenclature – can be found at https://bitbucket.org/rob_au/dnp3fw
The implementation of this filter for DNP3 proved to be a more complex (and in turn, interesting) affair due to the complex, multi-layer structure of the DNP3 packet format and ability for DNP3 fragments to be transmitted across multiple TCP/IP packets. At this point in time, this filter permits the filtering of DNP3 messages based on station addresses (source and destination) and function codes (such as read, write, cold restart, etc) – This is intended to allow for the implementation of an application firewall rule-set, likely to meet the basic requirements of the majority of intended use-cases.
While my employment has drawn me away from development work and work in the industrial automation space, I have continued to work on a number of smaller projects related to the open source IEC 61131-3 Virtual Machine. One such project has been the development of a Modbus application protocol network filter for the Linux kernel.
While a Modbus filter for Linux has made available by Venkat Pothamsetty and Matthew Franz previously and provided for download from Sourceforge. The most recent version of this code dated from 2004 however was written for Linux kernel 2.6.16 and no longer compiles against recent Linux kernel versions. To this end, this new filter match module for Modbus has been written and includes Modbus frame matching features beyond that available in the previous work by Pothamsetty and Franz.
This new Modbus filter kernel module – and corresponding patch for iptables 1.6, required in order to allow the specification and manipulation of firewall rules using Modbus protocol nomenclature – can be found at https://bitbucket.org/rob_au/modbusfw/.
After having received some correspondence with questions about how elements of the IEC 61131-3 virtual machine operations, I have had the idea that there would be value in my spending some time to write some “how to” documents on the development and usage of the IEC 61131-3 virtual machine. I would envisage that such documents would aid other developers looking in their employ of the IEC 61131-3 virtual machine, providing a clear road-map for such development.
The question remains however, what topics to cover? At the outset I would envisage the following topics as having merit:
- Writing IEC 61131-3 virtual machine drivers;
- Interfacing I/O with IEC 61131-3 virtual machine drivers;
- Implementing communication protocols;
I wonder though what topics others would like to see me document in this manner?
I have just pushed a commit through to Bitbucket for this project which implements function block operations for the IEC 61131-3 virtual machine. While still undergoing testing and further development, the implementation of this functionality addresses a major omission of functionality within the IEC 61131-3 virtual machine to date.
Surprisingly, the major effort associated with this functionality was associated with the implementation of the C library interface, allowing for function blocks to be written in both IEC 61131-3 languages and C, rather than the implementation of function block operations per se. To date, only the edge detection function blocks (F_TRIG and R_TRIG) have been implemented in the external C library for execution by the IEC 61131-3 virtual machine run-time, but next immediate task will be to extend this implementation to cover all standard function blocks defined within the IEC 61131-3 standard such that these are all immediately available, in the most optimised manner, from within the run-time environment.
Nevertheless, the rudiments of this functionality is now in place and available to be pulled from the git repository on Bitbucket.
After a short diversion to work on the Modbus protocol interface, work has resumed on the IEC 61131-3 compiler and virtual machine. This development effort is primarily focused on the implementation of support for function blocks, the primary omission in the scope of IEC 61131-3 support within the project at this point.
Building upon the efforts undertaken to implement a primitive Modbus protocol interface for the IEC 61131-3 virtual machine environment, I have spent some time consolidating this development and have released an embedded Modbus slave protocol library. This protocol library implements support for the most common Modbus operations including:
- Read coils (function code 1);
- Read discrete inputs (function code 2);
- Read holding registers (function code 3);
- Read input registers (function code 4);
- Write single coil (function code 5);
- Write single register (function code 6);
- Write multiple coils (function code 15);
- Write multiple registers (function code 16);
- Write mask register (function code 22); and
- Read write multiple holding registers (function code 23).
In this initial implementation, this library primary supports Modbus TCP operations – aligned with the initial implementation of Modbus operations on the IEC 61131-3 virtual machine – but there is scope for both Modbus RTU and Modbus ASCII implementations within the code base. Additionally, this library has been implemented with a keen awareness of portability for different platforms and as such includes distinct APIs for database and target platform integration.
This embedded Modbus slave C library can be obtained from GIT at https://bitbucket.org/rob_au/modbus. Similar to the IEC 61131-3 virtual machine project, this library is licensed under CC BY-NC 4.0.
In order to improve accessibility of the IEC 61131-3 virtual machine for external developers, I have committed code which provides a basic Modbus TCP protocol interface for the IEC 61131-3 virtual machine. The protocol was originally published by Modicon (now Schneider Electric) in 1979 for use with its programmable logic controllers (PLCs). Since this time, this protocol has become the de facto standard for communication with a range of industrial devices including programmable logic controllers, data loggers and smart instrumentation. See http://www.modbus.org/ and http://en.wikipedia.org/wiki/Modbus.
While this interface is still under development, the basic interface that is in place now allows for 16-bit integer values to be read from the virtual machine environment by external data visualisation packages – The package that I have used for evaluation purposes above is from http://thesz.diecru.eu/content/medford.php. This interface in turn provides a greater level flexibility for the monitoring of byte code under evaluation within the IEC 61131-3 virtual machine environment.
Over the last few weeks I have committed some changes relating to the file structure generated by the IEC 61131-3 compiler and employed by the IEC 61131-3 virtual machine run-time. Up until this point, the file structure has consisted of the flat binary byte code, encoded using the Intel hexadecimal object file format – See http://microsym.com/editor/assets/intelhex.pdf. This flat byte code format however does not encapsulate sufficient flexibility required to implement of the range of features – such as and initial values and retained variables – mandated for this project.
To this end, I have implemented a simple but expandable file header data structure that allows for the specification of meta-data associated with the compiled byte code application file. This packed data structure takes the form:
With respect to each of the elements of this data structure:
- Header – This member of the data structure is intended to provide scope for the specification of magic values and version information associated with the file structure.
- Symbols – This member of the data structure is intended to specify a byte offset into the encoded file where initial values for variables (symbol table) are specified. These values are specified in a byte aligned nature such that these raw values can be directly copied into the (RAM) memory space employed for the symbol table by the virtual machine run-time.
- Retain – This member of the data structure – where specified – is intended to specify a byte offset into the encoded file where a set of byte masks are specified for variables within the symbol table whose values should be retained, on a cycle-by-cycle basis, on the target controller across virtual machine run-time invocations.
- ByteCode – This member of the data structure is intended to specify a byte offset into the encoded file where the application byte code is located. This byte code, the output of the IEC 61131-3 compiler, specifies operations of the virtual machine run-time.
- Functions – This member of the data structure contains a MD5 hash created from the library of C-based functions linked to the IEC 61131-3 compiler. This is matched against a similarly generated hash for the virtual machine run-time which provides a level of surety of equivalence (or compatibility) of these C-based functions between the IEC 61131-3 compiler and IEC 61131-3 virtual machine run-time.
This file structure may be expanded in the future – most notably to include source variable information (such as variable names, types, size and scope) that may be required for debugging and controller redundancy synchronisation operations – but the above data structure gives me the scope for further immediate development.