Monday, May 1, 2017

FreeRTOS Tasks in Eclipse


I have been working with FreeRTOS for a while and finally decided to figure out how to properly get Eclipse to show the tasks as threads.  It is quite useful to know what other tasks are doing when you are debugging problems in your firmware.  This is a matter of enabling features within OpenOCD by changing configuration files for your target.  This post will center around configuring this for STMicroelectronics chips.  The first thing I would like to show is a working Eclipse/OpenOCD/GDB debug setup.

Non RTOS based Debug Setup Part 1
The above picture shows the normal setup I was using, a single configuration file for my target board.
The next picture shows the settings I used, to stop in main.

Non RTOS based Debug Setup Part 2

The contents of that file is below:

## This is the Test Rom Board
## Core429I Board
## STM32F429IGT6 ARM Cortex-M4
## Use the STLINK V2 Debug Probe
source [find interface/stlink-v2.cfg]

## This is setup with Serial Wire Debug
set WORKAREASIZE 0x20000
transport select hla_swd

## Use Generic STM32F4x chip setup support
source [find target/stm32f4x.cfg]

## Reset (software only reset)
reset_config srst_only srst_nogate

## Boost Adapter speed to 4 MHz
adapter_khz 4000

## Configure SWO/SWV
## System Core Clock 180 MHz
## Baud Rate 2 Mbaud/s
tpiu config internal debug.log uart off 180000000 2000000

The results of all of this configuration are shown below in the debugging screenshot:

Non RTOS Debugging Session

As you can see, there is a single thread.  This only allows me to see the exact spot in the code that I have currently stopped.  I would much rather be able to see what other tasks were running at the same time, and where they were in their execution at the exact moment the debugger halted everything.
In order for this to work, as the manual describes, we have to change the configuration file for the target to support using RTOS features.  Since I am using the STM32F4 series chips, I copied the stm32f4x.cfg file from /usr/share/openocd/scripts/target/stm32f4x.cfg to my utility directory in my code repository.  Once this file was copied I modified it to use the RTOS auto discovery, as shown below:

Modifying the stm32f4x.cfg file for RTOS debugging

I have highlighted the added text to enable auto discovery of RTOS usage.  The next thing I did was add a file called FreeRTOS_openocd.c to my project, the contents of this file are below:


/*
 * Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer
 * present in the kernel, so it has to be supplied by other means for
 * OpenOCD's threads awareness.
 *
 * Add this file to your project, and, if you're using --gc-sections,
 * ``--undefined=uxTopUsedPriority'' (or
 * ``-Wl,--undefined=uxTopUsedPriority'' when using gcc for final
 * linking) to your LDFLAGS; same with all the other symbols you need.
 */

#include "FreeRTOS.h"

#ifdef __GNUC__
#define USED __attribute__((used))
#else
#define USED
#endif

const int USED uxTopUsedPriority = (configMAX_PRIORITIES -1);

Next, I modified my makefile to include a new linker option, which allows OpenOCD to work correctly with the RTOS features.  The linker option I added was:

-Wl,--undefined=uxTopUsedPriority

I rebuilt the entire project (make distclean; make all -j16) to rebuild all the modules.  I usually only do this when I need to rebuild standard peripheral libraries, FreeRTOS etc.  Usually, I only have to rebuild the application code I am working in.  

I then tested this by using OpenOCD and GDB from the command line to ensure that this worked, the steps are below:
  1. run in a terminal: openocd -f interface/stlink-v2.cfg -f stm32f4x_RTOS.cfg
  2. run in a terminal: arm-none-eabi-gdb build/debug/core4x9i.elf
  3. execute the following commands inside the GDB session:
    1. target remote localhost:3333
    2. continue
    3. Control-C
    4. info threads
The first step is shown below

Running OpenOCD configured for RTOS debugging
The second step is shown in the following screenshot:

Connecting GDB to OpenOCD for RTOS debugging

The third step, which shows the threads feature working is below:

RTOS task info as threads in GDB

This is great, it's all working properly now.  Might as well set this up inside Eclipse so we can debug in an easier way.  

The first debug configuration page in Eclipse starts out with the proper files for starting OpenOCD as follows:

RTOS debug setup part 1

The second configuration page is below:

RTOS debug setup part 2

You may have noticed the change to the "Set breakpoint at" setting, this value has been changed to the first task that gets started: logger_task.  You need to do this, otherwise the debugger will become confused and not present you with the normal Eclipse debug experience.  This stems from the fact that it won't know about the tasks unless you allow them all to start, prior to hitting a break point.  I know, I know, there are times when you want to debug without the RTOS threads!  So keep two configurations, RTOS enabled and not.  This way you can debug start up as well as the RTOS tasks.
Either way, once you have this all completed and working, it should look like the debug session below:

RTOS debug session in Eclipse

Now, like me, you can have two debug configurations.  Have fun coding!