Logging is instrumental in preventing dropped connections in connection-based products, which occur when using breakpoint. This example introduces a simple implementation of logging on EFR32 based devices. The key point of the example code is to introduce a way to classify the log into different levels, where each level of log has its own identifier.
The example code supports both SEGGER's Real Time Transfer (RTT) and Serial Terminal via UART (VCOM).
By default, each logging piece contains the information below.
- Time - it is the relative time for device boots. If it is fed by the wall clock information, it will become absolute time.
- Location - the file and line information where the logging function is called.
- Level - it supports 7 logging levels, which are color-coded. See the information in the table below and the image below.
|Fatal (highest level)||Backgroud Red||Non-maskable, configurable if to assert or not when called|
|Important Information||Backgroud Magenta||Maskable|
|Debug Highlight||Backgroud Magenta||Maskable|
|Verbose (lowest level)||White||Maskable|
You can set a threshold at run time. Messages with level higher or equal to the threshold will be sent to the logging interface. Messages with level lower than the threshold will be ignored and discarded. For example, if the threshold is set to Important Information, then logging messages with Fatal, Error, Warning and Important Information levels will be sent to the logging interface, the others will be ignored.
Currently, it supports full featured and lightweight modes.
In full featured mode, logging.c is necessary to be built and a dedicated buffer for storing the logging message will be allocated statically at compiling time.
For lightweight mode, no source file will be built and all the functionalities are mostly provided as macros in the header file, there is no memory needs to be allocated and logging message is passed to the underlying functions directly. The way to store the message depends on the implementation of the underlying functions.
From the functionality perspective, the only difference between these 2 modes is that the lightweight mode doesn't support runtime threshold configuration, which can only be hardcoded at compiling time.
Integrated with GSDK 2.7
Create a new SoC-Empty example project in Simplicity Studio.
Download the logging project into your SoC-Empty project space.
Open the logging_config.h and modify below settings if needed.
- LOGGING_CONFIG - see Memory Usage
- TIME_ON - if you need to add time information to the log, set to 1. Because it utilizes the sl_sleep_timer service, you need to set macro - SL_SLEEPTIMER_WALLCLOCK_CONFIG to 1 in sl_sleeptimer_config.h file.
- LOGGING_BUF_LENGTH - size of the dedicated buffer for the full featured mode.
- LOGGING_INTERFACE - decide which interface or both the logging will be sent to.
- FATAL_ABORT - if assert the program when a fatal logging is called.
- LOGGING_LEVEL - set the threshold for logging levels in the lightweight mode.
Add _INIT_LOG(0xff);_ to the initialization code place and include "logging/logging.h" to the file you want to use the logging functionality.
Add your own logging to the project.
Build and flash the image to your board, connect your board with the proper interface to view the log.
Integrated with GSDK 3.0
If using the RTT as the logging interface, follow the same instruction as above - Integrated to GSDK 2.7.
If using serial port as the logging interface, add 2 steps between step 3 and 4 of Integrated to GSDK 2.7.
Open the \$.slcp file and install the _IO Stream: USART and and IO Stream: Retarget STDIO components.
Set the SL_BOARD_ENABLE_VCOM to 1 in sl_board_control_config.h
The logging project is in Github.