TwinCAT static code analysis

Together with TwinCAT release 4022.0 Beckhoff released their product “TE1200 – TC3 PLC Static Analysis“. It’s a tool integrated in the development environment to help the developer increase the quality of the code. Other than being able to set your own naming conventions for the code, TE1200 can be used for various rule checks, for example:

  • non-assigned return values
  • usage of object-oriented features
  • unreachable code

There are over 100 different checks that can be enabled to either output a warning or an error. These are configurable by the user, and the configurations can be exported. This is particularly good when developing in teams, and having common code checks. On top of this, TE1200 includes something called “Metrics”, which analyses your software and gives the properties of the code in different type of indicators, which for instance can be how many percentage of your code consists of comments. In this post, I’m primarily going to focus on the naming conventions and rules, and share my initial thoughts about this product.

With the TwinCAT development environment, there is a “light” version of the static code analysis included, and includes a basic set of compiler checks. In version 4022.2, these are available under the project properties, and “Static Analysis”:

Static code analysis light

As you’ve noticed, these are of limited use and normally you want to have a more extensive code analysis. The TE1200 is an engineering license, which means you use it on your development environment and not on the target runtime itself. Thus it’s possible to analyse any code that you have produced, no matter if it is standard runtime project or a library project. The only requirement is that the code is analyzed in TwinCAT version 4022.0 or later, since it is from this version that the static code analysis is installed. Therefore static code analysis is not a separate installation, but it’s included in the XAE.

There is no trial version of TE1200, but a license must be bought. It can either be bought as a single license for your development machine, or you can have it pre-installed from Beckhoff on a USB license stick. As I wanted to move my license around different development computers, I went for the latter. After a couple of weeks, the USB license stick came with the license pre-installed.

C900-L100 license USB stick

If you insert this stick to a PC, it will not behave as an ordinary stick as a drive with files. This stick can only be handled by TwinCAT 3.1. So my assumption was that if I insert the USB-stick, TwinCAT would automatically detect the engineering license and allow me to do the static code analysis immediately, but this proved to be wrong. It’s necessary to first add the USB-stick as a device under the I/O-tree of the project, before being able to activate the license. As I wanted to do this on several projects, it felt strange that I needed to update the I/O of the target device for every project that I wanted to do this with. Beckhoff are planning to change this in a forthcoming release (possibly in the next one after 4022.2) of TwinCAT, so that this license will automatically be activated without it being necessary to add it in the I/O. However, to use it across several projects on a development machine it’s enough to active the license stick on just one project. So what I did was to:

  • Create a temporary TwinCAT-project (which I later removed), scanned the I/O on my computer so it detected the USB-stick in the I/O-list
  • Add a license dongle under SYSTEM/License
  • Search for the USB-dongle (which is now detected in the I/O tree

USB license stick in TwinCAT

From this point the TE1200 license was valid in TwinCAT, and now it is possible to use this license in any project (from 4022.0) that you open on your development machine.

Valid TE1200 license

So now we’re all set to go and start doing the actual code analysis. I thought a good first example and target for this would be a library project that includes some accompanying unit tests that are made to verify/test the library. As you can read in the documentation, there is a ton of settings that you can do. I initially setup the configuration with more or less the default settings, but applied some naming conventions which more or less, are according to Beckhoffs programming conventions.

TE1200 settings

As you can see, the increase of items in the “Static Analysis” page compared to what’s included without the license is quite dramatic! All the settings can exported/imported, so it’s easy to share the static analysis settings between different computers, projects and/or developers. Once the settings are saved, they follow the project which I think is neat. It’s also possible to setup whether the static code analysis should be automatically done every time the project is built, or only manually by the “Run static analysis”-command:

Run static analysis under “Build”

Running the static code analysis tool the first time revealed 110 errors. This is going to take some time… let’s get to work! I worked my way through them one by one. Once I started to dig deeper into some of the errors I saw a couple that seemed a little strange. Take this for example:

Static analysis result

First, many of the errors have no reference to any file, and it refers to line zero! Most likely a bug. It’s a new product, so I can live with that. But what does “SA0102 – Access to program/fb variable from the outside” actually mean? The documentation describes this as:

Determines external access to local variables of programs or function blocks

Yes, I agree that access to local variables from the outside is bad and is considered bad practice of object oriented programming. But I don’t access any local variables from the outside. Let’s take the above example where both bSuccess and bFinished are considered to be local variables accessed from the outside. These errors refer to a function block call that looks like this:

fbTest_DiagnosticMessageCodeParser(bSuccess => bSuccess_DiagnosticMessageCodeParser,
                                   bFinished => bFinished_DiagnosticMessageCodeParser);

where fbTest_DiagnosticMessageCodeParser is an instance of the function block FB_Test_DiagnosticMessageCodeParser. This relevant part of the header for this function block looks like this:

FUNCTION_BLOCK FB_Test_DiagnosticMessageCodeParser
VAR_OUTPUT
    bSuccess : BOOL;
    bFinished : BOOL;
END_VAR

I’m clearly not trying to access local variables. So again, most likely a bug in TE1200. I’m ignoring this for now and continue. Working off error by error I then come to these errors:

SA0033

Beckhoff documentation for SA0033 says:

Determines variables that are declared but not used within the compiled program code

Yes, unused variables are not necessary, I agree. But look at the code of where these are used:

VAR CONSTANT
// @TEST-FIXTURE EmergencyErrorCode
    cnDiagnosticCodeBufferByte1_EmergencyErrorCode : BYTE := 16#00; // 16#E800
    cnDiagnosticCodeBufferByte2_EmergencyErrorCode : BYTE := 16#E8;
    cnDiagnosticCodeBufferByte3_EmergencyErrorCode : BYTE := 16#30; // 16#7530
    cnDiagnosticCodeBufferByte4_EmergencyErrorCode : BYTE := 16#75;
    canDiagnosticCodeBuffer_EmergencyErrorCode : ARRAY[1..4] OF BYTE := [
                                                cnDiagnosticCodeBufferByte1_EmergencyErrorCode,
                                                cnDiagnosticCodeBufferByte2_EmergencyErrorCode,
                                                cnDiagnosticCodeBufferByte3_EmergencyErrorCode,
                                                cnDiagnosticCodeBufferByte4_EmergencyErrorCode];
END_VAR

All of those four constants that are declared by the static analysis tools are clearly used by the array below them. If I remove the constants, the compiler instead complains that it cannot find the constants that are needed for the instantiation of the array!

It seems like Beckhoff might have been in a hurry with this product, but then again this is a new product and early in it’s life so you normally expect some bugs in this early phase. Even with these bugs this product helped me identify many weak spots in my software, and most importantly I can now incorporate processes of how to use this in any forthcoming development of TwinCAT software. It’s after all not just about the technical perspective. For instance, if you work in a team of other software developers, you would normally want to incorporate these type of checks across the whole codebase. If you are not in any particular hurry, I’d at least wait until the release after 4022.2 (released in christmas 2017?) where Beckhoff hopefully have worked out these bugs. I will come back with more posts about this product for sure!

Test icon by Freepik from www.flaticon.com / CC 3.0 BY

Your email address will not be published. Required fields are marked *

*