Profiling the Softdevice and FreeRTOS with Segger SystemView

In a previous blog post, RK has shown us how to use Segger SystemView to monitor a bare-metal application as well as the Softdevice. Based on his work, we will see how to go further and add FreeRTOS to SystemView in order to monitor the RTOS tasks and events.

Prerequisites :

The following steps are based on the Heart Rate application with FreeRTOS example located in the SDK (11.0 and 12,0) in examples\ble_peripheral\ble_app_hrs_freertos. To keep the example clean, I made a copy of it and named the copy ble_app_hrs_freertos_sysview, where I will work.



How to use SystemView with FreeRTOS


1. Getting the required files

In the ble_app_hrs_freertos_sysview project folder, create a systemview folder where you will place the following files :

From Instrumenting with Segger SystemView blog post :

From the SystemView installation folder in Src/Config :

  • Global.h
  • SEGGER_RTT_Conf.h
  • SEGGER_SYSVIEW_Conf.h

From the SystemView installation folder in Src/Sample/OS :

  • SEGGER_SYSVIEW_FreeRTOS.c
  • SEGGER_SYSVIEW_FreeRTOS.h

From the SystemView installation folder in Src/SEGGER :

  • SEGGER.h
  • SEGGER_SYSVIEW.h

From Instrumenting with Segger SystemView blog post, also download SYSVIEW_Softdevice.txt and keep it in a temporary folder, we'll use it later.

2. Adapting the build

In the Makefile, which is located in pca100xx\sxxx\armgcc conditionally add the following items to their respective variable depending on the value of USE_SYSVIEW :

Add to LIBS :

  • SysviewSoftdevice_S132V2.a

Add to SRC_FILES :

  • SEGGER_SYSVIEW_FreeRTOS.c

Add to INC_FOLDERS :

  • The systemview folder created in STEP 1

Add to CFLAGS :

  • -DNRF_LOG_USES_SYSVIEW=1

Example :

ifeq ($(USE_SYSVIEW),1) 
CFLAGS += -DNRF_LOG_USES_SYSVIEW=1 
endif

Note : I replaced the syntax for SRC_FILES, INC_FOLDERS and LIBS, it did use backslashes to put all on the same line, I prefer the += syntax which more easily allows to conditionally add sources. By example :

SRC_FILES = \
foo.c \
bar.c \

becomes :

SRC_FILES = foo.c
SRC_FILES += bar.c

3. Adapting the default build of RTT files when using SystemView

In the Makefile, replace these three lines as follow :

Old :

SRC_FILES +=  $(SDK_ROOT)/external/segger_rtt/RTT_Syscalls_GCC.c 
SRC_FILES +=  $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c 
SRC_FILES +=  $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c 

New :

ifeq ($(USE_SYSVIEW),)
SRC_FILES +=  $(SDK_ROOT)/external/segger_rtt/RTT_Syscalls_GCC.c 
SRC_FILES +=  $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c 
SRC_FILES +=  $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c 
endif

This way, the Segger RTT sources are not included when we use SystemView so they don't collide with the SystemView_Softdevice library.

4. Including SystemView files when using SystemView in main.c

Add these lines on top of main.c :

#ifdef NRF_LOG_USES_SYSVIEW
#if (NRF_LOG_USES_SYSVIEW == 1)
#include "SEGGER_SYSVIEW.h"
#include "sysview_softdevice.h"
#endif
#endif

It simply includes SystemView if NRF_LOG_USES_SYSVIEW was defined to 1, which is what we have done in STEP 2 when we modified CFLAGS.

5. Including SystemView files when using SystemView in FreeRTOSConfig.h

Here we will modify FreeRTOSConfig.h to include the SystemView output to FreeRTOS.

Warning : Modify the file located in ble_app_hrs_freertos_sysview\config\ble_app_hrs_freertos_pca100xx_sxxx, not the one in the external folder of the SDK.

Add these lines at the end of FreeRTOSConfig.h before the last #endif

#ifdef NRF_LOG_USES_SYSVIEW
#if (NRF_LOG_USES_SYSVIEW == 1)
#include "SEGGER_SYSVIEW_FreeRTOS.h"
#endif
#endif

6.Initializing SystemView in main()

Open main.c and add these initialization lines in main() before the infinite loop :

#ifdef NRF_LOG_USES_SYSVIEW
#if (NRF_LOG_USES_SYSVIEW == 1)
	sysview_all_irq_log( false );

	// log the radio, SWI2, our use of RTC1 and SVC calls
	sysview_irq_log( SWI2_IRQn, true );
	sysview_irq_log( RADIO_IRQn, true );
	sysview_irq_log( RTC1_IRQn, true );
	sysview_irq_log( SVCall_IRQn, true );

	// and enable it
	sysview_softdevice_enable( true, true );
#endif    
#endif

You can of course place them in a function to make the code cleaner.

7. Giving SystemView the SoftDevice configuration file

Add the previously downloaded file SYSVIEW_Softdevice.txt to the "description" folder in the SystemView installation directory.

8. Merging SoftDevice and FreeRTOS configuration files

In the description folder of the SystemView installation directory, copy-paste the content of SYSVIEW_FreeRTOS.txt at the end of SYSVIEW_Softdevice.txt, between the line that begin with 194 and the one that begin with 500. These lines represent the events received by SystemView from the target, they will allow SystemView to interpret what it receives and to display it correctly.

9. Give a new eventID to the FreeRTOS SystemView events

Add 200 to the number on the left of each line you copy-pasted in the previous step. Example :

33        vTaskAllocateMPURegions             xTask=%t pxRegions=%u

Becomes :

233        vTaskAllocateMPURegions             xTask=%t pxRegions=%u

Note : This can be done very quickly on all lines with Notepad++. Maintain ALT on your keyboard and select the beginning of each line with your mouse, then add/modify the first digit.

10. Adapt the eventID offset in SEGGER_SYSVIEW_FreeRTOS.h

Open SEGGER_SYSVIEW_FreeRTOS.h in the sysview folder created in STEP 1 and change this line :

Old :

#define apiID_OFFSET                              (32u)

New :

#define apiID_OFFSET                              (232u)

11. Build the application

Build with this command :

make USE_SYSVIEW=1 all

(Add -j4 or VERBOSE=1 if wanted).

12. Flash the application

Flash with this command :

make USE_SYSVIEW=1 flash


Well, that's it ! Now you should be able to see the tasks and events in Segger SYstemView. I really hope this will help some of you to use SystemView with FreeRTOS on the nRF family. Let me know if you have issues setting this up or if something was hard to understand and reproduce.

I wish Nordic will one day include a native way to use SystemView to monitor the Softdevice in the SDK.

Here is a very useful link if you are looking for more information on profiling FreeRTOS with SystemView : MCUOnEclipse - Segger SystemView: Realtime Analysis

Tips :

  • If you work on Eclipse, you can create two make targets that call make with some predefined parameters. Create a Build_With_Sysview and a Flash_with_Sysview targets that call make all and make flash with USE_SYSVIEW=1.
  • You can use SEGGER_SYSVIEW_Print() to send debug messages that will be displayed in SystemView directly, and you will see them in the Timeline ! This is a really great feature ;)

Known issues :

  • The FreeRTOS tasks should be displayed with their names. It happens quite often that the name is not correctly displayed. I have not found any fix yet.

  • The recording stops after some time, I don't know why and this time is different on different setups.

  • A "Buffer overflow" message appears at the beginning of a recording session. There is however not the possibility to enhance the buffer size since it's defined in the library given by RK on his blog post. Maybe one day Nordic will come with a native solution in the SDK which allows this level of configuration.

  • On SDK 11.0, calling make flash will relink the project, which by default does not include the SystemView library if you didn't write USE_SYSVIEW=1. This is why we need a custom flash command. This issue does not happen with SDK 12.0.

Thanks

  • RK for answering me on the Devzone, for writing his post and for his precious help
  • Erich Styger who publish a lot of useful posts on MCUOnEclipse, including a great guide on how to use SystemView with FreeRTOS.
  • Segger for this awesome free tool
  • And of course Nordic