Real-time trace of RTOS execution

Modern microcontrollers have much more processing power and memory than those of a few years ago. This has opened the opportunity to create more complex behaviors in the products we design. Managing this complexity requires the use of more sophisticated architectures to break the design into manageable components. An RTOS allows you to break your design into smaller chucks which are more manageable.

Each thread running in an RTOS is independent. It can generally execute its behaviors without regard to the other executing threads. When a thread has nothing to do it can yield execution to allow other threads to run. If its behavior is critical it can be assigned a higher priority assuring it runs as soon as it has work to do.

Because the RTOS is selecting which thread will run based on the current system state, it can be difficult to troubleshoot these systems, especially real-time systems which don’t tolerate setting a break point and stopping the execution.

One approach to tracking execution is to use a output port and pulse it each time the thread runs. This allows you to see if the thread runs and how often. Additional output ports can be added to trace more complex relationships. However, this solution is addhock and provides only minimal information.

Five Wire provides a more useful solution using the Logic Analyzer tool and the value nibble decoder. Four output pins must be assigned to make up a nibble that is captured by the Logic Analyzer. A small set of C functions are called within your thread to encode ‘marks’ or ‘variables’ which send short nibble packets to the Logic Analyzer. Once captured, the nibble packets are decoded into human readable values and displayed in the Logic Analyzer trace.

Here is an example capturing a span of time from an ST32F429 running 5 threads in FreeRTOS. Each of the spikes is a mark or variable being exported using the nibble decoder.

Zooming in on one of the spikes reveals three variables being exported and one mark indicating the monitor task is running. By calling the void nibMark(uint8_t n) function in your thread, a mark packet is sent to the Logic Analyzer. Up to 7 unique marks can be set. You can define your own label to reflect the purpose of each mark in the decoder definition file. For example, you could set a mark in each thread if the thread runs. This way you can see the sequence of thread execution, measure the time between executions, or compare the execution time with other external external signals captured on Logic Analyzer channels.

Even more powerful are the variable outputs. You can send up to 16 different variable values by calling void nibVar8(uint8_t n), void nibVar16(uint16_t n), or void nibVar32(uint32_t n). You can also customize the decoder to label each variable value. The variable nibble packets do take more time to send but usually less than a few microseconds.

Here we zoom in on the exported 32 bit tick timer to measure the time taken for the nibble export.

Here we zoom in on a mark to measure its export time.

Using this tool, you can trace the execution of your threads. You can also verify their reaction time to external logic signals by capturing additional signals on other Logic Analyzer channels. You can watch the values of variables as they change in reaction the external stimulus or track a control variable a state machine.

Here is a nibble capture on the same system but also capturing and decoding an RS232 input and the monThread RS232 response output.

The Five Wire Logic Analyzer with the nibble decoder provides a powerful tool to see whats going on in your multi-tasking environment.