Debugging nRF9160 Zephyr Applications Using Ozone

Ozone is SEGGER’s free embedded software debugger. It is a powerful tool that allows you to gain deep insights into what is happening within embedded systems. It is particularly useful when debugging nRF9160 Zephyr applications. Organizing multiple threads and multi-image builds can be challenging, but this is the tool you want.

In our previous blog post, “Taking the Next Step: Debugging with SEGGER Ozone and SystemView on Zephyr” (blog link: https://blog.golioth.io/taking-the-next-step-debugging-with-segger-ozone-and-systemview-on-zephyr/), Chris Gammell wrote about how to set up a SEGGER Ozone project to debug Zephyr applications running on the i.MX RT1060 evaluation kit. This is a great introduction to debugging Zephyr applications in Ozone and analyzing RTOS runtime behavior.

When I tried to set up a similar Ozone project to debug the Nordic nRF9160 SIP development board, I encountered some difficulties along the way. Today, I will share what I learned.

In this article, I will cover how to:

• Configure the nRF9160 Zephyr application for thread-aware debugging.

• Create an Ozone project for the nRF9160 using the New Project Wizard.

• Modify the Ozone project to support debugging the nRF9160 multi-image build.

Hardware Configuration

Debugging nRF9160 Zephyr Applications Using Ozone

In the example below, I will use the Nordic nRF9160 DK board. This development kit from Nordic has a built-in SEGGER J-Link OB debugger on the board, so no external J-Link debugger is needed to follow along with the example (SEGGER Ozone requires J-Link support).

Debugging nRF9160 Zephyr Applications Using Ozone

Thread Awareness Support in Zephyr

Debugging nRF9160 Zephyr Applications Using Ozone

In a typical Zephyr application built using the Golioth Zephyr SDK, there will be multiple threads. For example, one for the main loop of the application, one for the Golioth system client, and others for UART shell, logging subsystems, network management, etc.

SEGGER provides a Zephyr RTOS plugin for Ozone that displays the status of each thread, but it requires the Zephyr firmware to support thread-aware debugging at build time. Zephyr provides a CONFIG_DEBUG_THREAD_INFO Kconfig symbol that instructs the kernel to maintain a list of all threads, making the thread names visible in Ozone.

While you can simply add CONFIG_DEBUG_THREAD_INFO=y to the application’s prj.conf file, you might want to enable this additional debug information only at build time. We can create an extra debug.conf Kconfig file that will only be merged when we pass the -DEXTRA_CONF_FILE=debug.conf parameter to the build system.

Since this article is about using Ozone for thread-aware debugging, we will use the zephyr/samples/basic/threads/ application from the nRF Connect SDK Zephyr repository as the example application for this article.

If this is your first time building one of the Zephyr example applications, make sure to complete the nRF Connect SDK installation first and ensure your development environment is set up correctly.

How to Enable Thread Awareness

Debugging nRF9160 Zephyr Applications Using Ozone

First, create a zephyr/samples/basic/threads/debug.conf file and add the following command lines:

zephyr/samples/basic/threads/debug.conf

CONFIG_DEBUG_THREAD_INFO=y# CONFIG_DEBUG_THREAD_INFO needs the heap memory pool to# be defined for this appCONFIG_HEAP_MEM_POOL_SIZE=256

Next, build the firmware, specifying the required debug.conf file to be merged into the build configuration:

cd <your ncs workspace>/west build -p -b nrf9160dk_nrf9160_ns zephyr/samples/basic/threads/ -- -DEXTRA_CONF_FILE="debug.conf"

If the build completes successfully, you will see the build/zephyr/zephyr.elf file needed to start a debug session in Ozone.

Creating an Ozone Project

Debugging nRF9160 Zephyr Applications Using Ozone

Now that we have built the firmware, we can launch Ozone and create an Ozone project using the New Project Wizard:

Debugging nRF9160 Zephyr Applications Using Ozone

Select the nRF9160_xxAA chip.

Debugging nRF9160 Zephyr Applications Using Ozone

Select to use the J-Link emulator.

Debugging nRF9160 Zephyr Applications Using Ozone

Select the build/zephyr/zephyr.elf file that was generated in the previous discussion.

Debugging nRF9160 Zephyr Applications Using Ozone

Leave the other selections as defaults.

Debugging nRF9160 Zephyr Applications Using Ozone

After clicking “Finish,” you will see the Ozone project window appear. In the “Console” window, run the following command to load the Zephyr RTOS plugin:

Project.SetOSPlugin("ZephyrPlugin.js");

Debugging nRF9160 Zephyr Applications Using Ozone

Now, you should see a new “Zephyr” window in the Ozone project (if not, click “View”→”Zephyr” to display the window):

Debugging nRF9160 Zephyr Applications Using Ozone

Finally, save the project file by clicking “File”→”Save Project as…”:

Debugging nRF9160 Zephyr Applications Using Ozone

Starting the Debug Session

Debugging nRF9160 Zephyr Applications Using Ozone

Now that we have configured the Ozone project, we can start the debug session.

Click “Debug”→”Start Debug Session”→”Download & Reset Pro”

Debugging nRF9160 Zephyr Applications Using Ozone

Strangely, when the firmware starts running, a pop-up window will indicate that the target has stopped in a HardFault exception state!

Debugging nRF9160 Zephyr Applications Using Ozone

At this point, you might be wondering what is happening here……

Here’s a hint: the answer relates to the multi-image build.

https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/config_and_build/multi_image.html

Missing Steps:

Burn the Merged File Image

Debugging nRF9160 Zephyr Applications Using Ozone

You may have noticed that we pass the board parameter (nrf9160dk_nrf9160_ns) to west build with a _ns suffix. This suffix indicates that the firmware will be built with Trusted Firmware-M (TF-M). This is the reference implementation of ARM’s IoT security framework called Platform Security Architecture (PSA).

TF-M uses the ARM TrustZone security features of the nRF9160’s Cortex-M33 MCU to partition the MCU into a Secure Processing Environment (SPE) and a Non-Secure Processing Environment (NSPE).

In short, the boot process works as follows:

1. When the MCU starts, it begins execution in the secure environment (SPE).

2. The boot process may choose to begin with a secure bootloader chain using NSIB and/or MCUboot.

3. If used, the bootloader will start TF-M, which will configure part of the MCU’s memory and peripherals as non-secure.

4. TF-M starts the Zephyr application running in the non-secure environment (NSPE).

When we build targeting _ns, the TF-M image is automatically built and linked with the Zephyr application. If you look at the build/zephyr/ output directory, you will see a file named merged.hex, which is a merged file containing the MCUboot bootloader (optional), TF-M secure image, and the non-secure Zephyr application.

Fixing the Ozone Project File

Debugging nRF9160 Zephyr Applications Using Ozone

We will make some changes directly in the Ozone project file, which can be opened in Ozone by clicking “File”→”Edit Project File”:

Debugging nRF9160 Zephyr Applications Using Ozone

Burning the Merged Image

Debugging nRF9160 Zephyr Applications Using Ozone

Navigate to the TargetDownload section of the Ozone project file and add the following content to configure Ozone to flash the merged image (change the path to match the merged image file in your project):

/*********************************************************************** TargetDownload** Function description* Replaces the default program download routine. Optional.************************************************************************/void TargetDownload(void){Exec.Download("$(ProjectDir)/build/zephyr/merged.hex");}

Fix the vector table and PC address

Navigate to the _SetupTarget section of the Ozone project file and make the following changes:

1. Set the vector table address to 0

2. Read the entry point program counter address from the vector table

/*********************************************************************** _SetupTarget** Function description* Setup the target.* Called by AfterTargetReset() and AfterTargetDownload().** Auto-generated function. May be overridden by Ozone.************************************************************************/void _SetupTarget(void) {unsigned int SP;unsigned int PC;unsigned int VectorTableAddr;VectorTableAddr = 0;//// Set up initial stack pointer//SP = Target.ReadU32(VectorTableAddr);if (SP != 0xFFFFFFFF) {Target.SetReg("SP", SP);}//// Set up entry point PC//PC = Target.ReadU32(VectorTableAddr + 4);if (PC != 0xFFFFFFFF) {Target.SetReg("PC", PC);} else {Util.Error("Project script error: failed to set up entry point PC", 1);}}

When you save the project file, you should see a prompt asking if you want to reload the project.

Select “Yes”:

Debugging nRF9160 Zephyr Applications Using Ozone

Starting the Debug Session

Debugging nRF9160 Zephyr Applications Using Ozone

After the image file is flashed onto the chip, you should see the debugger stop at the main location:

Debugging nRF9160 Zephyr Applications Using Ozone

Click “Debug”→”Continue”:

Debugging nRF9160 Zephyr Applications Using Ozone

This time, the firmware runs normally without any exceptions.

Conclusion

Debugging nRF9160 Zephyr Applications Using Ozone

I hope this helps you get started debugging the nRF9160 with Ozone. The nRF9160 has full support in Zephyr projects and the highest level of support in the Golioth IoT device management platform. With Golioth, you can connect and secure devices, send sensor data to the web, wirelessly update firmware, and expand your coverage using the IoT cloud.

Mictech Technology is the agent for SEGGER products in China, with over 20 years of market, service, and training experience in embedded real-time operating systems and tools. We have recorded many SEGGER video courses and written blog posts. For more product information, contact Mictech Technology [email protected].

Welcome to follow our WeChat public account 【Mictech Technology】, reply with “Join Group” to join the technical exchange group as prompted.

Product Consultation:

Beijing: 010-62975900

Shanghai: 021-62127690

Shenzhen: 0755-82977971

Leave a Comment