nRF54H20 logging

To read logs on the nRF54H20 DK, you can use the following methods:

  • A direct UART connection to a specific core.

  • Local domain logging with System Trace Macrocell (STM). STM has two modes:

    • Standalone logging

    • Assisted multicore logging

For general information on how logging works in the nRF Connect SDK, consult the Logging in nRF Connect SDK and Logging documentation pages.

nRF54H20 logging using a direct UART connection

Similarly to other SoCs from Nordic Semiconductor, to use a UART connection for reading logs, follow the UART logging guide in the application development section.

nRF54H20 logging using System Trace Macrocell (STM)

nRF54H20 domains contain ARM Coresight System Trace Macrocell (STM) hardware devices for collecting trace data from multiple domains, using either standalone logging or assisted multicore logging. The STM uses memory-mapped registers to write trace data generated by the domains in the system. It multiplexes the data as trace protocol data, formatted according to the MIPI System Trace Protocol (STP) v2, and synchronizes the data on a single output, such as a single UART. This approach has a minimal cost on performance and code size, allowing for a non-intrusive collection of system debug-and-trace information.

The STM implements a frontend of the Zephyr logging subsystem, allowing you to use the standard Zephyr logging API.

Note

Currently, only the Multicore Hello World application sample supports STM logging.

Embedded Trace Router (ETR)

The Embedded Trace Router (ETR) is a hardware feature that provides a circular buffer in RAM for trace data. It can trigger interrupts when the buffer is half-full or full, allowing the CPU to be woken up in time to handle the data. The ETR buffer size is limited to 4 Kb, and it requires additional formatting with 16-byte frames.

When using ETR, one of the cores is designated as a proxy to manage the trace data.

Note

Currently, the Secure Domain is the only core that can be designated as proxy.

The proxy core is responsible for handling the data from the ETR and outputting it through the desired transport mechanism (like UART or USB). The proxy core approach allows for on-chip data processing, offering more flexibility than the Trace Port Interface Unit (TPIU). However, due to the limited size of the ETR buffer, there is a risk of data loss if not handled promptly.

Standalone logging

The current implementation for the standalone logging mode with STM works as follows:

  1. All domains write the raw encoded log data to their own STM peripheral called the STM Extended Stimulus Port (STMESP).

  2. The STMESP generates a data stream based on the register writes.

  3. The STM multiplexes the data stream with streams from other domains, and it places them in the single memory buffer provided by the ETR.

  4. The Secure Domain Firmware (SDFW), acting as the ETR-designated proxy, reads the buffer and decodes the raw encoded log data.

  5. The SDFW outputs the logging data in a human-readable format over UART.

Standalone logging leverages the frontend API of the Zephyr logging subsystem to select the stimulus ports and writes log messages directly to memory-mapped registers. This method bypasses the need for string formatting functions and peripheral drivers, as the core writes directly to the STM port.

Configuration

To show the logs for a given domain in the UART output, you must enable the STM for that domain.

To enable the STM for a domain, set the CONFIG_LOG_STM Kconfig option for that domain’s image to y. The STM will be enabled by the build system in the configuration of the SDFW.

Reading the logs

To read the STM log output on the UART, consult the following documentation pages:

Note

To use UART in your application, the UART’s node must be described in devicetree. For more details, see Introduction to devicetree.

The following is an example log output:

[00:00:00.154,790] <inf> app/spsc_pbuf: alloc in 0x2f0df800
[00:00:00.163,319] <inf> app/spsc_pbuf: alloc 0x2f0df800 wr_idx:20
[00:00:00.181,112] <inf> app/spsc_pbuf: commit in 0x2f0df800
[00:00:00.189,090] <inf> app/spsc_pbuf: commit 0x2f0df800, len:20 wr_idx: 44
[00:00:00.202,577] <inf> rad/icmsg: mbox_callback
[00:00:00.214,750] <inf> rad/spsc_pbuf: claim 0x2f0df800 rd_idx:20
[00:00:00.235,823] <inf> rad/spsc_pbuf: free 0x2f0df800 len:20 rd_idx: 44
[00:00:00.244,507] <inf> rad/spsc_pbuf: read done 0x2f0df800 len:20
[00:00:00.272,444] <inf> rad/host: ep recv 0x330021f0, len:20
[00:00:00.283,939] <inf> rad/host: rx:00 exp:00
[00:00:00.292,200] <inf> rad/icmsg: read 0
[00:00:05.077,026] <inf> rad/spsc_pbuf: alloc in 0x2f0df000
[00:00:05.077,068] <inf> rad/spsc_pbuf: alloc 0x2f0df000 wr_idx:44
[00:00:05.077,098] <inf> rad/spsc_pbuf: commit in 0x2f0df000
[00:00:05.077,134] <inf> rad/spsc_pbuf: commit 0x2f0df000, len:20 wr_idx

Each log line contains a domain-related or core-related prefix between the log level and the module name, indicating the core that generated the log entry. The following are the prefixes used to indicate the cores:

nRF54H20 log prefixes

Core

Prefix

Secure Domain

sec

Application core

app

Radio core

rad

System Controller (SysCtrl)

sys

Fast Lightweight Processor (FLPR)

flpr

Peripheral Processor (PPR)

ppr

Assisted multicore logging

Assisted multicore logging uses dictionary-based logging to send messages without redundant strings to STM, and is based on the Dictionary-based Logging feature of the logging API provided by Zephyr. Instead of including the format strings in the log messages, it logs the addresses (message IDs) where the strings are stored, which reduces the size of the logging subsystem. If the data goes to the ETR buffer, the proxy core’s responsibility is to dump this data. The host PC, equipped with a decoder tool, translates these addresses back into human-readable text using a JSON database generated during the build process.

When using logs, this method has the following advantages:

  • It reduces the size of the binary, as the strings used in the log messages are not stored in the binary itself.

  • It reduces the amount of data that needs to be sent to and processed by the application core, as the string formatting is offloaded to the host side.

Configuration

To enable the assisted multicore logging for a domain, set the CONFIG_LOG_STM_DICT Kconfig option for that domain’s image to y.

After building your application, a dictionary database file named log_database.json will be generated in the build/zephyr directory. This file is crucial for decoding the logs and is updated with every build.

Reading the logs

To read the dictionary-based STM log output, do the following:

  1. Set up the log capture.

    Use the nrfutil trace stm command to start capturing logs from the device, specifying the database configuration for each domain ID, as well as the serial port, the baud rate, and the output file name:

    nrfutil trace stm --database-config 33:build/secdom/src/secdombuild/zephyr/log_dictionary.json,34:build/zephyr/log_dictionary.json --input-serialport /dev/ttyACM1 --baudrate 115200 --output-ascii out.txt
    
  2. Capture and decode the logs.

    nrfutil will capture the log data from the specified UART port and use the provided dictionary databases to decode the logs into a human-readable format. The decoded logs will be saved in the specified output file (the out.txt file in the previous example).

  3. Open the output file to review the decoded log messages.

    The file will contain timestamps and the log messages in a format that is human-readable.

If the log capture fails to find a sync, rerun the capture process.

Note

Decoding artifacts or incorrect timestamps might occur when rerunning the process.

Each log line contains a domain-related or core-related prefix between the log level and the module name, indicating the core that generated the log entry. The following are the prefixes used to indicate the cores:

nRF54H20 log prefixes

Core

Prefix

ID

Secure Domain

sec

0x21

Application core

app

0x22

Radio core

rad

0x23

System Controller (SysCtrl)

sys

0x2c

Fast Lightweight Processor (FLPR)

flpr

0x2d

Peripheral Processor (PPR)

ppr

0x2e

mod

0x24

Additional considerations

When using assisted multicore logging, consider the following:

  • Use optimized log macros (having up to 2 word size numeric arguments, like LOG_INF("%d %c", (int)x, (char)y)) to improve the size and speed of logging.

  • For memory constrained applications (for example, when running on the PPR or FLPR cores), disable the printk() function by setting both the CONFIG_PRINTK and CONFIG_BOOT_BANNER Kconfig options to n in your project configuration.

  • When working with multiple domains, such as the Secure Domain and Application core, ensure that each database is prefixed with the correct domain ID.

  • Some log messages might be dropped due to the limited size of the RAM buffer that stores STM logs.