Logging User Guide#
This section describes the logging framework used to push important information on target logging interface in a compressed format.
The logging framework is designed to provide standard
printf() like experience to the developers without overloading the debug target(UART by default) with redundant information. The framework compresses the amount of log data that is pushed on to the target.
In order to achieve this compression,
SAPI and FW Logs follows strict Syntax rules.
A pre-build analyzer tool converts all static information(read-only component of SAPI and FW logs) in log description file placed in the build system.
A C framework embedded within SAPI and FW emits the dynamic components of logs along with an identifier and compressed timestamp(conditionally).
The compressed logs are processed offline by a decoder to regenerate the human readable log data.
Compression Numbers in different scenarios#
Number of bytes emitted
No Debug Arguments, first 32 Debug IDs
No Debug Arguments, 32-4096 Debug IDs
Cost of Timestamp
1 byte if temporal spacing between two consecutive logs is more than 1ms. 2 bytes if temporal spacing between two consecutive logs is more than 127ms
Cost of each fixed length argument
Number of bytes in argument
Cost of string
Length of string(Null terminated)
Enable/Disable SAPI Logs#
Compile time switch
SAPI_LOGGING_ENABLE should be enabled for SAPI logs to be active. If the compile switch
SAPI_LOGGING_ENABLE is not present, SAPI log instances are considered as void statements and shall not generate any code.
Syntax for SAPI Logging calls#
The calls to SAPI Logs should strictly follow below syntax.
SL_PRINTF(DEBUG_ELEMENT, COMPONENT, LOG_LEVEL, Format, <Arguments>);
DEBUG_ELEMENT is the unique identifier for a logging call. In order to add a new logging call, user is just required to mention a new DEBUG_ELEMENT in the fucntion call, user is not required to define this new DEBUG_ELEMENT. A pre-processing tool shall search for all occurences of
SL_PRINTF calls in the source files and prepare an enum with all unique
The component the module to which the debug log belongs to. Currently supported list of components is:
The level of active logs can be controlled through compile switch
CONFIG_DEBUG_LEVEL present in
rsi_user.h. The compile switch define can be initialized with one of four possible enum values:
As the enums suggest,
LOG_OFF turns off logging,
LOG_ERROR provides minimum logging and
LOG_INFO provides maximum logging.
e.g. Suppose the user configures
CONFIG_DEBUG_LEVEL to LOG_ERROR then only
SL_PRINTF calls having debug level as LOG_ERROR will be processed. Similarly, if the user configures
CONFIG_DEBUG_LEVEL to LOG_WARNING then
SL_PRINTF calls with LOG_ERROR and LOG_WARNING debug levels will be processed.
>Note! It is not intended to use LOG_OFF as a debug level in any SL_PRINTF call.
Format defines how additional arguments in the logging call should be treated. The format is parsed by the pre-processing tool and information is stored in build system. The format information is latter used to display the decoded logs.
Each argument defination should be separated by ','
Each Argument defination should comprise of a Display Name and properties, separated by ':'
The display name is what will be visible in decoded output log against each argument.
sign should be used only to identify debug argument property. Number of % signs denotes number of arguments that are being pased in the debug log.
b stands for 1 byte argument which should be displayed in decimal format.
w stands for 2 byte argument which should be displayed in decimal format.
d stands for 4 byte argument which should be displayed in decimal format.
s stands for a variable length string which should always be terminated by NULL character.
%1x stands for 1 byte argument which should be displayed in Hexadecimal format.
%2x stands for 2 byte argument which should be displayed in Hexadecimal format.
%4x stands for 4 byte argument which should be displayed in Hexadecimal format.
The format is also used by pre-processing tool to identify number of arguments in given debug call and define
SL_PRINTF call for given
DEBUG_ELEMENT accordingly. There is no limit to number of times logging call is made with same
DEBUG_ELEMENT but the format should remain the same for each of these calls. The pre-processor tool shall throw error if any descripancy is found in format.
For a fixed length argument, parameters shall be passed by value. For strings, parameters shall be passed by reference.
>Note! The format and arguments fields are optional.
SL_PRINTF call shall have only three mandatory arguments(
LOG_LEVEL) if an argument is not required in the call.
advanced_logs_generator.py is a pre-processing python script present at the path:
<SDK>\utilities\advanced_logging\app_logging. This tool is used to generate the
debug_auto_gen.h file at the path:
debug_auto_gen.h comprises all the enumerations of all
DEBUG_ELEMENTS and declarations required for the logging framework.
Whenever the user wants to add a new SAPI logging call, a new
debug_auto_gen.h needs to be generated using the
advanced_log_generator.py pre-processing tool.
>Note! The pre-processing tool should be invoked mandatorily if a new(unique) SAPI logging call is introduced. The autogenerated files are already updated as part of the release package for all existing SAPI logging calls.
Given below is an example of adding the new SAPI logging call and execution of the
e.g. Let's add a new SL_PRINTF call similar to an existing error case SL_PRINTF call present in the
Now let's execute the
advanced_log_generator.py to get the new SAPI logging elements and declarations in debug_auto_gen.h file
>Note! For successful execution of advanced_log_generator.py or sapi_log_decoder.py python scripts, it is recommended to use Python version 3.9 or higher.
Upon execution of the tool, changes like those shown below take place in the
There is another file named
manifest.json which is present in the same folder. This JSON file comprises metadata corresponding to all SAPI logging calls required at the time of decoding the logs.
Decoding SAPI Logs#
The decoder tool
sapi_log_decoder.py is a python tool present in the
utilities\advanced_logging\app_logging folder. The decoder tool takes the encoded logs as the input and searches for
#@$ in the start of line. The tool expects the rest of the line to have heaxdecimal numbers which are then decoded to generate human readable text file.
Given below is an example of the SAPI logs, before and after decoding.
Enable/Disable Firmware Logs#
Compile time switch
FW_LOGGING_ENABLE should be enabled for firmware logs to be active. If the compile switch
FW_LOGGING_ENABLE is not present, firmware log instances are considered as void statements and shall not generate any code.
Firmware Log Components#
The component to which the debug log belongs to. Current supported list of components is:
COMMON - common section among all protocols
CM_PM - Coex manager and power manager logs are used to debug issues involving multi protocols and power save.
WLAN_LMAC - LMAC logs are used to debug Transmit/Receive related issues
WLAN_UMAC - UMAC logs are used to debug Supplicant, SME, APME layers issues
WLAN_NETSTACK - Network stack logs are used to debug TCP/IP and application layers issues
BT_BLE_CTRL - Bluetooth and Bluetooth Low Power controller logs are used to debug issues in controller
BT_BLE_STACK - Bluetooth and Bluetooth Low Power controller logs are used to debug issues in stack
Firmware Logging Parameters#
Applications for which firmware logging has been enabled, contain parameters that can be configured according to the users requirements and constraints.
Component Log Levels#
The level of active logs of individual firmware components can be controlled through compile switches in application configuration files. The compile switch define can be initialized with one of five possible values:
Log Buffer Size#
Determines the size of log packet recieved from firmware. The log buffer size can vary from a minimum of 2048 bytes to a maximum of 4096 bytes. The size can be varied with increments of 512 bytes. Any size below the minimum size or more than maximum size will be replaced with corresponding limits.
Log Queue Size#
Determines the number of elements in the firmware log queue. The log queue ensures that debug logs arriving from firmware are not lost when previously received logs are being processed. For a larger queue size, more debug logs can be stored in the queue. It has a minimum value of 1.
Increasing the log queue size increases the memory required by the firmware logging framework, during application initialization.
Decoding Firmware Logs#
The decoder tool
fw_log_decoder.py is a python tool present in the
The decoder tool takes the encoded logs as the input and searches for
&^$ in the start of line. The tool expects the rest of the line to have heaxdecimal numbers which are then decoded to generate human readable text file. Given below is an example of the firmware logs, before and after decoding.