A peek inside Amazon FreeRTOS

Last fall, Amazon announced that they were getting involved in the embedded systems space with the release of Amazon FreeRTOS, an open source real-time operating system that makes connecting to Amazon Web Services easy for developers. Unfortunately, just like with many open source projects, the documentation for Amazon FreeRTOS doesn’t provide a clear picture on what is going on behind the scenes or how the demonstration software is supposed to execute. In this post, we will take a peek inside Amazon FreeRTOS to see what we can expect from this Amazon Web Services offering.

Now there are several ways that a developer could start to understand how the Amazon FreeRTOS demonstration software works. The first, and more time-consuming method, is to perform a complete code review. A code review is a great idea, but many developers will probably skip this step anyways. The second method is to trace the application and see how many tasks are created, how they interact with each other and analyze the applications run-time.

I set up Amazon FreeRTOS on a STM32 IoT Discovery Node which has a STM32L475 Arm microcontroller. In order to trace the application, I set up the default Amazon FreeRTOS example within Atollic TrueStudio and used a SEGGGER J-Link Ultra+ debugger to live stream trace data to Percepio Tracealyzer. The setup is a little bit different than the default setup from Amazon which uses an ST-Link and System Workbench for STM32. I was finding the System Workbench did not want to compile the imported project and that it also would only support the ST-Link which has far less bandwidth for trace data.

After getting everything set up, I took a three-minute trace which provided the result shown in Figure 1.

There are several useful pieces of information about the application that we can gain from this trace. First, there are seven tasks in the base application. These include, from highest to lowest priority:

Logging

TmrSVC

MQTT

TzCtrl (the trace task)

MQTTEcho

Echoing

Idle

At this point, we don’t know what all these tasks do but we at least know that they exist and can dig into the code to get that information.

Second, examining the trace reveals that the tasks don’t appear to all be created at the program's start. Instead, it looks like they are created from highest priority to lowest in a staggered fashion over the course of a little more than 30 seconds! If we were to examine the source code, we would in fact see that this is how the tasks are created (which also makes it more difficult to look through the code and figure out how it behaves).

Finally, we can see that once the MQTTEcho task starts executing, the Echoing task runs in sync with it and together they execute twelve times. At first this might seem like odd behavior, except that the application is designed to transmit a MQTT message to the cloud once every 5 seconds for 60 seconds. That’s twelve messages which correlate to the twelve executions. With this knowledge, we can see what the application is doing, and we can at least verify that it does what we expect it to.

Now we saw in the trace data that the tasks are created during the first 30 seconds. We can try to glean a little more information about what might be happening by zooming in on the first thirty seconds and examining the communication and RTOS events. What we would find is that the MQTT task runs nearly constantly during this entire time period. How constant? If we look at the CPU load graph, shown in Figure 2, then we can see that the CPU is loaded 100% for the first 37 seconds after starting the system.

From examining these two views, we not only see how the application is executing, but we also see that it would be wise for any developer to dig into the MQTT task and understand exactly what it is that it is doing. Does it really make sense for the CPU to be loaded at full capacity for 37 seconds? As a real-time developer, whenever I see long periods of CPU utilization like this I have to throw a red flag and question what is going on. Could this be poorly architected start-up code? Perhaps it’s just the easiest implementation for connecting to an access point and negotiating a secure connection with the cloud. At this point, we would need to dive into the code which I will leave as an exercise for the reader, for now.

Jacob Beningo is an embedded software consultant, advisor and educator who currently works with clients in more than a dozen countries to dramatically transform their software, systems and processes. Feel free to contact him at jacob@beningo.com, at his website www.beningo.com, and sign-up for his monthly Embedded Bytes Newsletter.