Skip to content

Robust Design Patterns - Part 2

Introduction

In this codelab, we address the problem of unresponsive applications. Unresponsive is referring to the situation a program installed on an MCU becomes unavailable due to various reasons (e.g. gobbler task, dead-lock, …). We take what we did in a previous codelab Robust Design Patterns - Part 1 a step further: we do this on a per task base.

What you’ll build

In this codelab, you will reuse the application used in previous codelabs (or that of the project) and add a watchdog to a specific task to make sure it complies to its expected timing - reacting should this not be the case.

What you’ll learn

  • The general concepts of thread watchdogs.
  • What main components are relevant to such concept.
  • The inner working of ARM Keil and how to add thread watchdogs to it.
  • Finally, making use of thread watchdogs 🙃

What you’ll need

Implementing a Thread Watchdog

As we have seen temporal isolation using Thread Watchdogs is very important. Each thread can have an independent watchdog that can be started using the osThreadFeedWatchdog(uint32_t ticks) method. The ticks parameter is the timeout value of the watchdog. Within the interval, the thread must call the function anew to refeed the watchdog timer. If the timer is not fed, the osWatchdogAlarm_Handler callback is triggered and can be used to recover the system or escalate up to the system shutdown. This method must be implemented by the user.

The watchdog timers operate in a similar way as user timers. At each SysTick interrupt, the method osRtxThreadWatchdogTick gets executed. It iterates over the list of sorted threads watchdog and call the watchdog handler for those who have expired, effectively calling osWatchdogAlarm_Handler. Temporal Isolation is important because applying a scheduling analysis does not ensure that threads will respect their deadlines under any circumstances. With the Rate Monotonic Analysis we ensure that if all threads behave correctly the tasks’ set is schedulable, temporal isolation is here to verify that the tasks’ set respects its temporal requirements.

So, go ahead and implement a thread watchdog for the task with the highest priority within your application.

First of all, you need to make sure you have activated the overall configuration. For that, one needs to have :

  1. Activated OS_SAFETY_FEATURES and
  2. Checked that OS_THREAD_WATCHDOG is set to 1

The following pseudo-code can be used as reference within your most important task:

// If thread watchdog enabled, refresh it
if (wdEnabled) {
    // Calculate new watchdog time based on current execution
    osStatus_t status = osThreadFeedWatchdog(watchdog_timeout);
    if (status != osOK) {
        app_error_handler(CANNOT_REFRESH_TASK_WATCHDOG);
    }
}

In order for you to realize whether the system does what it is supposed to, the first implementation of osWatchdogAlarm_Handler should be as simple as using :

vioSetSignal(vioLED0, vioLEDon);
app_error_handler(REFRESH_TASK_WATCHDOG_ELAPSED);

Note

Remember to remove the use of the vioLED0 from the osRtxIdleThread for the above to run correctly.

Questions

  1. What is a sensible value for refreshing the watchdog of a thread?
  2. Taking into consideration what seen during the Robust Patterns lectures ( lecture 1, lecture 2 ), what can you do with osWatchdogAlarm_Handler?
  3. Can you explain how Thread Watchdog are implemented? Most important files are rtx_kernel.c and rtx_thread.c.

Modifying an RTX kernel

Introduction to ARM Keil structure

Note

Even though the present section refers to CMSIS version 5.9.0, the information remains valid with other versions as well.

The “SDK” (SW Development Kit) we use in this course offers an easy way to integrate functionality through so-called packages. However, one may also want/need to modify a component for specific reasons (say, a given function is not available). However, prior to doing so, one will want to make sure to have made a backup of the component that is about to change. In this example the component changed is CMSIS - a set of tools, APIs, frameworks, and work flows that help to simplify software re-use, reduce the learning curve for microcontroller developers, speed-up project build and debug, and thus reduce the time to market for new applications. (note: this description is taken directly from the official documentation).
The intention is to modify the CMSIS version 5.9.0 we have installed on our pc with one that we modify.
So, locate on your hard drive where the CMSIS 5.9.0 has been installed. Normally, the location is usually C:\Users\username\AppData\Local\Arm\Packs\ARM. An example of this - for a user named virtu - can be seen below:

In the location C:\Users\username\AppData\Local\Arm\Packs.Download all downloaded packages can be found. Each installed package is then installed in the appropriate location - with each package version stored in its dedicated directory.

Once the package folder for version 5.9.0 identified, make a copy of the directory named CMSIS within it and name it CMSIS_original (or similar). The folder with the versions looks like : While the version 5.9.0 contains - after backup creation - the following :

Warning

Make sure you do a copy of the CMSIS folder of version 5.9.0 prior to continuing with the codelab. It may be challenging to rectify the installation without such a copy.

Note

The package folder contains 2 files : pdsc and sha1.

The former (pdsc) describes content and version of the package. The latter (sha1) ensures the expected files are contained in the package. Without it, files lose their “certified” mark in ARM Keil’s GUI (“Project” window - see below for a concrete example of certified file).

Modifying ARM Keil RTOS

First of all, clone the original CMSIS project located under : https://github.com/ARM-software/CMSIS_5

Secondly, make sure you checkout the correct version : 5.9.0. As there is a corresponding tag, it is a simple matter of issuing git checkout 5.9.0. Once done so, you can apply the required changes to your git project as desired.

Moving the new kernel into place

Now that you have created your kernel, you need to put it where CMSIS_original was. So,

  1. Close ARM Keil MDK
  2. Put the new kernel - in the form of the CMSIS folder - in place under C:\Users\username\AppData\Local\Arm\Packs\ARM\CMSIS\5.9.0 (or whatever location applies to you - see what you did before)
  3. Open ARM Keil anew and check that the changes are visible (so that you are sure you did all correctly 😉). You can do so, for instance, by checking the file(s) you modified

So, if you have been able to successfully do what described above, you are ready for the next step : using whatever function you wanted so badly to have!

Note

Make sure you close all files in ARM Keil in order to avoid caching issues while looking for symbols in ARM Keil.

Going beyond