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.
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:
All domains write the raw encoded log data to their own STM peripheral called the STM Extended Stimulus Port (STMESP).
The STMESP generates a data stream based on the register writes.
The STM multiplexes the data stream with streams from other domains, and it places them in the single memory buffer provided by the ETR.
The Secure Domain Firmware (SDFW), acting as the ETR-designated proxy, reads the buffer and decodes the raw encoded log data.
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:
If you want to use the nRF Serial Terminal from the nRF Connect for VS Code extension, see the nRF Terminal documentation on the nRF Connect for Visual Studio Code documentation site.
If you want to use PuTTY, see Testing and optimization.
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:
Core |
Prefix |
---|---|
Secure Domain |
|
Application core |
|
Radio core |
|
System Controller (SysCtrl) |
|
Fast Lightweight Processor (FLPR) |
|
Peripheral Processor (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:
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
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).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:
Core |
Prefix |
ID |
---|---|---|
Secure Domain |
|
0x21 |
Application core |
|
0x22 |
Radio core |
|
0x23 |
System Controller (SysCtrl) |
|
0x2c |
Fast Lightweight Processor (FLPR) |
|
0x2d |
Peripheral Processor (PPR) |
|
0x2e |
|
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 theCONFIG_PRINTK
andCONFIG_BOOT_BANNER
Kconfig options ton
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.