Logging via SWO

Hi,

I am trying to configure SWO logging in a sample project based on zephyr/samples/hello_world (source and config at the end).

I run this application on two targets: nRF54L15-DK and nRF52-DK.

On nRF54L15-DK: I cannot see any logs when using SEGGER J-Link SWO Viewer but I can see the logs via cortex-debug extension for vscode.

On nRF52-DK: I can see logs when using SEGGER J-Link SWO Viewer but I cannot see any logs via cortex-debug extension for vscode.

Do you know why it works that way?

Another question is about the SWO frequency. In case of nRF54L15-DK and vscode I need to configure the SWO receiver to half of the frequency configured in the application. In case of nRF52-DK and SEGGER J-Link SWO Viewer I can choose whatever frequency I want.

How to properly set the SWO frequency for nRF54L15?

Application code:

 

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>

int main(void)
{
	while (1) {
		printk("Hello World! %s\n", CONFIG_BOARD_TARGET);
		k_msleep(1000);
	}

	return 0;
}

prj.conf file:

CONFIG_LOG=y
CONFIG_LOG_MODE_MINIMAL=n
CONFIG_LOG_MODE_IMMEDIATE=y
CONFIG_LOG_BACKEND_SWO=y
CONFIG_LOG_BACKEND_SWO_FREQ_HZ=2000000

launch.json file for vscode:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "hello nrf54",
            "cwd": "${workspaceFolder}",
            "executable": "${workspaceFolder}/build/merged.hex",
            "symbolFiles": [
                "${workspaceFolder}/build/hello_world/zephyr/zephyr.elf",
            ],
            "request": "launch",
            "type": "cortex-debug",
            "runToEntryPoint": "main",
            "servertype": "jlink",
            "device": "NRF54L15_M33",
            "interface": "swd",
            "showDevDebugOutput": "raw",
            "swoConfig": {
                "enabled": true,
                "source": "probe",
                "swoFrequency": 1000000,
                "cpuFrequency": 128000000,
                "decoders": [
                    {
                        "port": 0,
                        "type": "console",
                        "label": "hello",
                        "encoding":"ascii"
                    }
                ]
            },
            "ipAddress": "192.168.100.20:19020",
        },
        {
            "name": "hello nrf52",
            "cwd": "${workspaceFolder}",
            "executable": "${workspaceFolder}/build/merged.hex",
            "symbolFiles": [
                "${workspaceFolder}/build/hello_world/zephyr/zephyr.elf",
            ],
            "request": "launch",
            "type": "cortex-debug",
            "runToEntryPoint": "main",
            "servertype": "jlink",
            "device": "NRF52832_xxAA",
            "interface": "swd",
            "showDevDebugOutput": "raw",
            "swoConfig": {
                "enabled": true,
                "source": "probe",
                "swoFrequency": 1000000,
                "cpuFrequency": 64000000,
                "decoders": [
                    {
                        "port": 0,
                        "type": "console",
                        "label": "hello",
                        "encoding":"ascii"
                    }
                ]
            },
            "ipAddress": "192.168.100.20:19020",
        },
    ]
}

Cheers,
Damian

Parents Reply Children
  • Hi Marte,

    Unfortunately, the version of my DK is 0.9.1.

    Do you know how to enable SWO on a custom board with nRF54L10 SoC? I am asking about nRF54L10 since in our project we use our custom board with this SoC and we have exactly the same issue with SWO as described above for nRF54L15-DK.

    Best Regards,

    Damian

  • Hi Damian,

    The board configurator tool configures the board controller (interface MCU) on the DK itself, it does not configure the nRF54L chip. This means what you want to replicate in firmware is the trace port enablement on the nRF54L chip itself, not the DK board controller configuration.

    For the nRF54L, the following sequence is required to enable SWO support:

    /* Trace configuration */
    #define TRACE_PORT                  NRF_P2_S
    #define TRACE_TRACECLK_PIN          (6ul)
    #define TRACE_TRACEDATA0_PIN        (7ul)
    #define TRACE_TRACEDATA1_PIN        (8ul)
    #define TRACE_TRACEDATA2_PIN        (9ul)
    #define TRACE_TRACEDATA3_PIN        (10ul)
    #define TRACE_PIN_CONFIG            ((GPIO_PIN_CNF_DRIVE0_E0 << GPIO_PIN_CNF_DRIVE0_Pos) \
    | (GPIO_PIN_CNF_DRIVE1_E1 << GPIO_PIN_CNF_DRIVE1_Pos) \
    | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos))
    
    #define TRACE_PIN_CLEAR             (~(GPIO_PIN_CNF_CTRLSEL_Msk | GPIO_PIN_CNF_DRIVE0_Msk | GPIO_PIN_CNF_DRIVE1_Msk | GPIO_PIN_CNF_DIR_Msk))
    /* End Trace configuration */
    
    
    // Enable trace and debug
    NRF_TAD_S->ENABLE = TAD_ENABLE_ENABLE_Msk;
    
    // Configure trace port pads
    TRACE_PORT->PIN_CNF[TRACE_TRACECLK_PIN] &= TRACE_PIN_CLEAR;
    TRACE_PORT->PIN_CNF[TRACE_TRACEDATA0_PIN] &= TRACE_PIN_CLEAR;
    
    TRACE_PORT->PIN_CNF[TRACE_TRACECLK_PIN] |= TRACE_PIN_CONFIG;
    TRACE_PORT->PIN_CNF[TRACE_TRACEDATA0_PIN] |= TRACE_PIN_CONFIG;
    
    // Configure trace port speed
    NRF_TAD_S->TRACEPORTSPEED = TAD_TRACEPORTSPEED_TRACEPORTSPEED_DIV2;

    However, this should automatically be set when you have SWO enabled with CONFIG_LOG=y and CONFIG_LOG_BACKEND_SWO=y as you can see from these files:

    https://github.com/nrfconnect/sdk-zephyr/blob/main/modules/hal_nordic/nrfx/CMakeLists.txt#L116

    https://github.com/nordicsemi/nrfx/blob/master/bsp/stable/mdk/system_nrf54l.c#L260-L278

    Since this is not working in your case, can you try manually enabling SWO using the code above? If this does not work, please let me know.

    Best regards,
    Marte

  • Hi Marte,

    Thanks for clarifying how the board configurator works and what it does.

    I have added the above code snippet but it did not help. I still cannot see the logs in SEGGER J-Link SWO Viewer.

    Best Regards,

    Damian

  • Hi Damian,

    What debugger are you using? The debugger must be SWO capable to work.

    Is there a specific reason for using SWO instead of RTT?

    Best regards,
    Marte

  • Hi Marte,

    The debugger I use is SEGGER J-Link Base.

    The reason behind using SWO is that in our project we would like to have two builds: release and test. Release one uses SWO log backend but the application does not enable SWO. It can be enabled and set up by the attached debugger when needed.
    Test build which is used for measuring power consumption. Here the enables SWO by itself. No debugger is attached, only one wire to the SWO pin to gather the logs.


    I have an update regarding the logs in SEGGER J-Link SWO Viewer, I can get the logs, I just had to power cycle the target device. So after the reboot the logs are received. Setting `CONFIG_LOG_BACKEND_SWO=y` was enough. My apologies, it was my mistake.

    Nevertheless, the logs look corrupted. When running the simple application (from the code snippet above) every couple of lines of logs the ending of the line is incorrect.

    *** Booting nRF Connect SDK v3.2.1-d8887f6f32df ***
    
    *** Using Zephyr OS v4.2.99-ec78104f1569 ***
    
    Hello World! hcm200/nrf54l10/app
    
    Hello World! hcm200/nrf54l10/cpuapp
    
    Hello World! hcm200/nrf54l10/app
    
    Hello World! hcm200/nrf54l10/p
    
    Hello World! hcm200/nrf54l10/cuapp
    
    Hello World! hcm200/nrf54l10/uapp
    
    Hello World! hcm200/nrf54l10/puapp
     

    The correct ending should be `cpuapp`.

    I have attached a logic analyzer to SWO pin to see what really is happening on the wire. It occurs, there is unexpected data sent via SWO. Here are the waveforms:

    hello_world_sleep.sal

    I modified the application so that it does not use `k_msleep` function but a spin wait instead, like this:

    static void spin_wait_ms(int64_t duration_ms)
    {
        const int64_t start_ms = k_uptime_get();
    
        while ((k_uptime_get() - start_ms) < duration_ms) {}
    }

    After that the logs look correctly. The waveforms:

    hello_world_spin.sal

    It has been run on a custom board with nRF54L10 SoC on it.


    I have the following questions:

    1. Do you know why the logs are corrupted when using a sleep function in the code?
    2. Is there a way to use SWO log backend in Zephyr/NCS but not enabling SWO? Only the debugger would enable it when attached. It would save some power when the debugger is not attached.

    Best Regards,
    Damian

Related