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.
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.
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 :
From the SystemView installation folder in Src/Sample/OS :
From the SystemView installation folder in Src/SEGGER :
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 :
Add to SRC_FILES :
Add to INC_FOLDERS :
Add to CFLAGS :
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 \
SRC_FILES = foo.c SRC_FILES += bar.c
In the Makefile, replace these three lines as follow :
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
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.
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.
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
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.
Add the previously downloaded file SYSVIEW_Softdevice.txt to the "description" folder in the SystemView installation directory.
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.
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
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.
Open SEGGER_SYSVIEW_FreeRTOS.h in the sysview folder created in STEP 1 and change this line :
#define apiID_OFFSET (32u)
#define apiID_OFFSET (232u)
Build with this command :
make USE_SYSVIEW=1 all
(Add -j4 or VERBOSE=1 if wanted).
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
Known issues :
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.