px-fwlib 0.10.0
Cross-platform embedded library and documentation for 8/16/32-bit microcontrollers generated with Doxygen 1.9.2
px_log.h : Debug log module

Description

Output human readable debug info to a serial console.

File(s):

An old school debugging technique which still works well is to add debug print statements in the source code to track program flow and check for coding mistakes during development. Afterwards the debug print statements are removed from the final release build to avoid the significant code and delay overhead.

This module allows one to easily add formatted debug print macros to the source code and enable them by defining PX_LOG=1 or remove them from the build by defining PX_LOG=0 in the Makefile. There is no need to manually edit the source code afterwards for the release build.

The following macros can be used:

PX_LOG_CFG_LEVEL is used to specify which log messages are compiled into the source code. For example if PX_LOG_CFG_LEVEL is set to PX_LOG_LEVEL_INFO then all ERROR, WARNING and INFO messages will be included in the code but VERBOSE and DEBUG message will not. It does not affect PX_LOG_TRACE() or PX_LOG_ASSERT() macros.

Set PX_LOG_CFG_COLOR to 1 to indicate log message level with color on an ANSI/VT100 terminal emulator (for example Tera Term).

Example usage:

PX_LOG_I("This word is " PX_LOG_FG_GREEN "green" PX_LOG_CR);
#define PX_LOG_I(format,...)
Macro to display a formatted INFO message.
Definition: px_log.h:399

Observe that the compiler will automatically concatenate adjacent strings.

The log messages will report the file / module name and line number as well as the user format string. To save code space, the name must be declared at the top of the C file using PX_LOG_NAME(). This is the correct way to declare the name:

#include "px_log.h"
PX_LOG_NAME("module / file name"); // Or PX_LOG_NAME(__FILE__);
#define PX_LOG_NAME(name)
Macro to declare a log name string once for each file to reduce code size.
Definition: px_log.h:349

If PX_LOG_NAME() is not used, then the compiler will output the following error when log output is enabled (PX_LOG=1):

error: '_px_log_name' undeclared (first use in this function)

The log output can be redirected by using the PX_LOG_CFG_PUTCHAR macro, for example to stderr stream, a different uart or to a log file on an SD card.

Example:

#include "px_defs.h"
#include "px_board.h"
#include "px_sysclk.h"
#include "px_uart.h"
#include "px_uart_stdio.h"
#include "px_log.h"
// Declare log name
PX_LOG_NAME("px_log_test");
// Declare UART handle structure
px_uart_handle_t px_uart_handle;
bool px_log_filter(px_log_level_t level, const char * name)
{
// Filter all logs with a higher verbosity than DEBUG level
if(level > PX_LOG_LEVEL_DEBUG)
{
return true;
}
// Does name start with "px"?
if(strncmp(name, "px", 2) != 0)
{
return true;
}
// Allow log
return false;
}
uint8_t calc(uint8_t val)
{
uint8_t answer;
// Report function call with parameter value
PX_LOG_D("calc(" PX_LOG_BG_YELLOW "val = %u" PX_LOG_CR ")", val);
// Is val equal to zero?
if(val == 0)
{
PX_LOG_E("val may not be equal to zero");
return 0;
}
// Calculate answer
answer = 100 / val;
// Report answer
PX_LOG_I("answer = " PX_LOG_FG_GREEN "%u" PX_LOG_CR, answer);
return answer;
}
int main(void)
{
uint8_t val;
uint8_t answer;
// Initialise modules
// Open UART1 @ 115200 BAUD, 8 data bits, no parity, 1 stop bit
px_uart_open2(&px_uart_handle,
PX_UART_NR_1,
115200,
PX_UART_DATA_BITS_8,
PX_UART_PARITY_NONE,
PX_UART_STOP_BITS_1);
// Direct stdio to UART0
px_uart_stdio_init(&px_uart_handle);
// Enable interrupts
px_interrupts_enable();
PX_LOG_V("Calculation started");
for(val = 0; val < 3; val++)
{
// Calculate answer
answer = calc(val);
}
PX_LOG_TRACE("Calculation finished. answer = %u\n", answer);
}
void main_log_timestamp(char * str)
{
uint8_t i;
uint8_t j;
char timestamp[9];
sprintf(timestamp, "%08lu", (uint32_t)px_sysclk_get_tick_count());
i = 0;
j = 0;
while(i < 5)
{
str[i++] = timestamp[j++];
}
// Insert decimal separator
str[i++] = '.';
while(i < 9)
{
str[i++] = timestamp[j++];
}
str[i++] = '\0';
}
void px_board_init(void)
Initialise the board hardware.
Definition: px_board.c:168
#define PX_LOG_D(format,...)
Macro to display a formatted DEBUG message.
Definition: px_log.h:410
#define PX_LOG_TRACE(format,...)
Macro to output a user format string if PX_LOG=1.
Definition: px_log.h:458
bool px_log_filter(px_log_level_t level, const char *name)
Run time log filter.
Definition: px_log.c:253
px_log_level_t
Log message level ordered in increasing verbosity.
Definition: px_log.h:186
#define PX_LOG_E(format,...)
Macro to display a formatted ERROR message.
Definition: px_log.h:377
#define PX_LOG_V(format,...)
Macro to display a formatted VERBOSE message.
Definition: px_log.h:421
@ PX_LOG_LEVEL_DEBUG
Extra info for debugging that's not required for normal use.
Definition: px_log.h:191
px_sysclk_ticks_t px_sysclk_get_tick_count(void)
Return number of ticks since system clock started.
Definition: px_sysclk.c:97
void px_sysclk_init(void)
Start system clock (one clock tick every 1/PX_SYSCLK_TICKS_PER_SEC seconds)
Definition: px_sysclk.c:79
void px_uart_stdio_init(px_uart_handle_t *handle)
Initialise stdio stream to use a UART driver.
Definition: px_uart_stdio.c:94
bool px_uart_open2(px_uart_handle_t *handle, px_uart_nr_t uart_nr, uint32_t baud, px_uart_data_bits_t data_bits, px_uart_parity_t parity, px_uart_stop_bits_t stop_bits)
Open UART peripheral using specified parameters.
Definition: px_uart.c:483
void px_uart_init(void)
Initialise UART driver.
Definition: px_uart.c:452
Define UART handle.
Definition: px_uart.h:141

The project wide PX_LOG_CFG_LEVEL setting in the Makefile or "px_log_cfg.h" can be overriden for a specific C file as follows:

// PX_LOG_CFG_LEVEL defined in Makefile?
#ifdef PX_LOG_CFG_LEVEL
#undef PX_LOG_CFG_LEVEL
#endif
// Set output level to DEBUG (ERROR, WARN, INFO and DEBUG messages)
#define PX_LOG_CFG_LEVEL PX_LOG_LEVEL_DEBUG
#include "px_log.h"
PX_LOG_NAME("buggy_module");

The PX_LOG_CFG_LEVEL can easily be tested with the the PX_LOG_LEVEL_IS_E(), PX_LOG_LEVEL_IS_W(), PX_LOG_LEVEL_IS_I(), PX_LOG_LEVEL_IS_V() or PX_LOG_LEVEL_IS_D() macro to conditionally add code, for example:

void tx_data(void * data, size_t nr_of_bytes)
{
// PX_LOG=1 and PX_LOG_CFG_LEVEL includes VERBOSE messages?
{
// Report content of buffer
PX_LOG_TRACE_HEXDUMP(data, nr_of_bytes);
}
// Rest of function...
}
#define PX_LOG_LEVEL_IS_V()
Verbose level enabled?
Definition: px_log.h:373
#define PX_LOG_TRACE_HEXDUMP(data, nr_of_bytes)
Macro to output the content of a buffer if PX_LOG=1.
Definition: px_log.h:487

A naming convention is used to start a function, variable or macro name with an underscore ('_') to indicate that it is used internally by this C module and should not be used directly, for example _px_log_log_error() or _px_log_name[].

Macros

#define PX_LOG   1
 Set flag to disable (PX_LOG=0) or enable (PX_LOG=1) log output. More...
 
#define PX_LOG_NAME(name)   PX_ATTR_UNUSED static const char _px_log_name[] PX_ATTR_PGM = name;
 Macro to declare a log name string once for each file to reduce code size. More...
 
#define PX_LOG_LEVEL_IS_E()   (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_ERROR)
 Error level enabled? More...
 
#define PX_LOG_LEVEL_IS_W()   (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_WARNING)
 Warning level enabled? More...
 
#define PX_LOG_LEVEL_IS_I()   (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_INFO)
 Info level enabled? More...
 
#define PX_LOG_LEVEL_IS_D()   (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_DEBUG)
 Debug level enabled? More...
 
#define PX_LOG_LEVEL_IS_V()   (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_VERBOSE)
 Verbose level enabled? More...
 
#define PX_LOG_E(format, ...)
 Macro to display a formatted ERROR message. More...
 
#define PX_LOG_W(format, ...)
 Macro to display a formatted WARNING message. More...
 
#define PX_LOG_I(format, ...)
 Macro to display a formatted INFO message. More...
 
#define PX_LOG_D(format, ...)
 Macro to display a formatted DEBUG message. More...
 
#define PX_LOG_V(format, ...)
 Macro to display a formatted VERBOSE message. More...
 
#define PX_LOG_ASSERT(expression)
 Macro that will test an expression, and block indefinitely if false. More...
 
#define PX_LOG_TRACE(format, ...)   _px_log_trace(PX_PGM_STR(format), ## __VA_ARGS__)
 Macro to output a user format string if PX_LOG=1. More...
 
#define PX_LOG_TRACE_CHAR(c)   _px_log_trace_char(c)
 Macro to output a char if PX_LOG=1. More...
 
#define PX_LOG_TRACE_DATA(data, nr_of_bytes)   _px_log_trace_data(data, nr_of_bytes)
 Macro to output the content of a buffer if PX_LOG=1. More...
 
#define PX_LOG_TRACE_HEXDUMP(data, nr_of_bytes)   _px_log_trace_hexdump(data, nr_of_bytes)
 Macro to output the content of a buffer if PX_LOG=1. More...
 
#define PX_LOG_CFG_LEVEL   PX_LOG_LEVEL_INFO
 Set COMPILE TIME log output level. More...
 
#define PX_LOG_CFG_FILTER   0
 Disable (0) or Enable (1) run time log filter. More...
 
#define PX_LOG_CFG_COLOR   1
 Disable (0) or Enable (1) VT100 terminal color output. More...
 
#define PX_LOG_CFG_BUF_SIZE   64
 Debug output string buffer size. More...
 

Enumerations

enum  px_log_level_t {
  PX_LOG_LEVEL_NONE = 0 , PX_LOG_LEVEL_ERROR = 1 , PX_LOG_LEVEL_WARNING = 2 , PX_LOG_LEVEL_DEBUG = 4 ,
  PX_LOG_LEVEL_VERBOSE = 5
}
 Log message level ordered in increasing verbosity. More...
 

Functions

bool px_log_filter (px_log_level_t level, const char *name)
 Run time log filter. More...
 
void _px_log_log_error (const char *name, uint16_t line, const char *format,...)
 Output error info: module name, line and variable argument user format string. More...
 
void _px_log_log_warning (const char *name, uint16_t line, const char *format,...)
 Output warning info: module name, line and variable argument user format string. More...
 
void _px_log_log_info (const char *name, uint16_t line, const char *format,...)
 Output info info: module name, line and variable argument user format string. More...
 
void _px_log_log_debug (const char *name, uint16_t line, const char *format,...)
 Output debug info: module name, line and variable argument user format string. More...
 
void _px_log_log_verbose (const char *name, uint16_t line, const char *format,...)
 Output verbose info: module name, line and variable argument user format string. More...
 
void _px_log_assert (const char *name, uint16_t line) PX_ATTR_NORETURN
 Report that an assertion has failed and block indefinitely. More...
 
void _px_log_trace (const char *format,...)
 Output a user format string. More...
 
void _px_log_trace_char (char c)
 Output a character. More...
 
void _px_log_trace_data (const void *data, size_t nr_of_bytes)
 Output the content of a buffer as an array of HEX values. More...
 
void _px_log_trace_hexdump (const void *data, size_t nr_of_bytes)
 Output the content of a buffer as a spaced table of HEX values and ASCII characters. More...
 

Macro Definition Documentation

◆ PX_LOG

#define PX_LOG   1

Set flag to disable (PX_LOG=0) or enable (PX_LOG=1) log output.

Definition at line 152 of file px_log.h.

◆ PX_LOG_NAME

#define PX_LOG_NAME (   name)    PX_ATTR_UNUSED static const char _px_log_name[] PX_ATTR_PGM = name;

Macro to declare a log name string once for each file to reduce code size.

Definition at line 349 of file px_log.h.

◆ PX_LOG_LEVEL_IS_E

#define PX_LOG_LEVEL_IS_E ( )    (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_ERROR)

Error level enabled?

Definition at line 365 of file px_log.h.

◆ PX_LOG_LEVEL_IS_W

#define PX_LOG_LEVEL_IS_W ( )    (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_WARNING)

Warning level enabled?

Definition at line 367 of file px_log.h.

◆ PX_LOG_LEVEL_IS_I

#define PX_LOG_LEVEL_IS_I ( )    (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_INFO)

Info level enabled?

Definition at line 369 of file px_log.h.

◆ PX_LOG_LEVEL_IS_D

#define PX_LOG_LEVEL_IS_D ( )    (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_DEBUG)

Debug level enabled?

Definition at line 371 of file px_log.h.

◆ PX_LOG_LEVEL_IS_V

#define PX_LOG_LEVEL_IS_V ( )    (PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_VERBOSE)

Verbose level enabled?

Definition at line 373 of file px_log.h.

◆ PX_LOG_E

#define PX_LOG_E (   format,
  ... 
)
Value:
do \
{ \
{ \
_px_log_log_error(_px_log_name, (uint16_t)__LINE__, PX_PGM_STR(format), ## __VA_ARGS__); \
} \
} \
while(0)
#define PX_LOG_CFG_LEVEL
Set COMPILE TIME log output level.
@ PX_LOG_LEVEL_ERROR
Critical errors.
Definition: px_log.h:188

Macro to display a formatted ERROR message.

Definition at line 377 of file px_log.h.

◆ PX_LOG_W

#define PX_LOG_W (   format,
  ... 
)
Value:
do \
{ \
{ \
_px_log_log_warning(_px_log_name, (uint16_t)__LINE__, PX_PGM_STR(format), ## __VA_ARGS__); \
} \
} \
while(0)
@ PX_LOG_LEVEL_WARNING
Warnings.
Definition: px_log.h:189

Macro to display a formatted WARNING message.

Definition at line 388 of file px_log.h.

◆ PX_LOG_I

#define PX_LOG_I (   format,
  ... 
)
Value:
do \
{ \
if(PX_LOG_CFG_LEVEL >= PX_LOG_LEVEL_INFO) \
{ \
_px_log_log_info(_px_log_name, (uint16_t)__LINE__, PX_PGM_STR(format), ## __VA_ARGS__); \
} \
} \
while(0)

Macro to display a formatted INFO message.

Definition at line 399 of file px_log.h.

◆ PX_LOG_D

#define PX_LOG_D (   format,
  ... 
)
Value:
do \
{ \
{ \
_px_log_log_debug(_px_log_name, (uint16_t)__LINE__, PX_PGM_STR(format), ## __VA_ARGS__); \
} \
} \
while(0)

Macro to display a formatted DEBUG message.

Definition at line 410 of file px_log.h.

◆ PX_LOG_V

#define PX_LOG_V (   format,
  ... 
)
Value:
do \
{ \
{ \
_px_log_log_verbose(_px_log_name, (uint16_t)__LINE__, PX_PGM_STR(format), ## __VA_ARGS__); \
} \
} \
while(0)
@ PX_LOG_LEVEL_VERBOSE
Extra details for debugging which can flood normal output.
Definition: px_log.h:192

Macro to display a formatted VERBOSE message.

Definition at line 421 of file px_log.h.

◆ PX_LOG_ASSERT

#define PX_LOG_ASSERT (   expression)
Value:
do \
{ \
if(!(expression)) \
{ \
_px_log_assert(_px_log_name, (uint16_t)__LINE__); \
} \
} while(0)

Macro that will test an expression, and block indefinitely if false.

This macro will perform the test and if false, will output the filename and line number. The macro will then block indefinitely.

Parameters
[in]expressionExpression that evaluates to a boolean value (true or false)

Definition at line 440 of file px_log.h.

◆ PX_LOG_TRACE

#define PX_LOG_TRACE (   format,
  ... 
)    _px_log_trace(PX_PGM_STR(format), ## __VA_ARGS__)

Macro to output a user format string if PX_LOG=1.

This macro does not append a new line character ('\n') so that multiple strings can be sent on the same line.

Parameters
[in]formatFormat string following by a variable list of arguments.

Definition at line 458 of file px_log.h.

◆ PX_LOG_TRACE_CHAR

#define PX_LOG_TRACE_CHAR (   c)    _px_log_trace_char(c)

Macro to output a char if PX_LOG=1.

Parameters
cCharacter to output

Definition at line 465 of file px_log.h.

◆ PX_LOG_TRACE_DATA

#define PX_LOG_TRACE_DATA (   data,
  nr_of_bytes 
)    _px_log_trace_data(data, nr_of_bytes)

Macro to output the content of a buffer if PX_LOG=1.

The data is displayed as an array of HEX values.

Parameters
dataPointer to buffer containing data to display
nr_of_bytesSize of buffer (in bytes)

Definition at line 476 of file px_log.h.

◆ PX_LOG_TRACE_HEXDUMP

#define PX_LOG_TRACE_HEXDUMP (   data,
  nr_of_bytes 
)    _px_log_trace_hexdump(data, nr_of_bytes)

Macro to output the content of a buffer if PX_LOG=1.

The data is displayed as a spaced table of HEX values and ASCII characters.

Parameters
dataPointer to buffer containing data to display
nr_of_bytesSize of buffer (in bytes)

Definition at line 487 of file px_log.h.

◆ PX_LOG_CFG_LEVEL

#define PX_LOG_CFG_LEVEL   PX_LOG_LEVEL_INFO

Set COMPILE TIME log output level.

The levels are sorted in increasing levels of verbosity. For example if PX_LOG_CFG_LEVEL is set to PX_LOG_LEVEL_INFO then all ERROR, WARNING and INFO messages will be included in the code but DEBUG and VERBOSE messages will not.

Definition at line 49 of file px_log_cfg_template.h.

◆ PX_LOG_CFG_FILTER

#define PX_LOG_CFG_FILTER   0

Disable (0) or Enable (1) run time log filter.

Definition at line 53 of file px_log_cfg_template.h.

◆ PX_LOG_CFG_COLOR

#define PX_LOG_CFG_COLOR   1

Disable (0) or Enable (1) VT100 terminal color output.

Definition at line 56 of file px_log_cfg_template.h.

◆ PX_LOG_CFG_BUF_SIZE

#define PX_LOG_CFG_BUF_SIZE   64

Debug output string buffer size.

Definition at line 59 of file px_log_cfg_template.h.

Enumeration Type Documentation

◆ px_log_level_t

Log message level ordered in increasing verbosity.

Enumerator
PX_LOG_LEVEL_NONE 

No log output.

PX_LOG_LEVEL_ERROR 

Critical errors.

PX_LOG_LEVEL_WARNING 

Warnings.

PX_LOG_LEVEL_DEBUG 

Extra info for debugging that's not required for normal use.

PX_LOG_LEVEL_VERBOSE 

Extra details for debugging which can flood normal output.

Definition at line 185 of file px_log.h.

Function Documentation

◆ px_log_filter()

bool px_log_filter ( px_log_level_t  level,
const char *  name 
)

Run time log filter.

A customised version of this function can be declared to filter log output based on the level and / or name. Define PX_LOG_CFG_FILTER=1 to enable.

A weak version is declared in px_log.c that always returns false meaning that all log output is allowed (none is filtered).

Parameters
levelLog level
nameModule / file name
Return values
trueLog must be filtered
falseLog must be outputted

Definition at line 253 of file px_log.c.

◆ _px_log_log_error()

void _px_log_log_error ( const char *  name,
uint16_t  line,
const char *  format,
  ... 
)

Output error info: module name, line and variable argument user format string.

The line is automatically appended with a new line character ('\n'), except if the format string ends with a tab character ('\t'). The tab character at the end of the string is discarded.

Parameters
nameModule / file name
lineLine number
formatUser format string
...Variable number of arguments

Definition at line 259 of file px_log.c.

◆ _px_log_log_warning()

void _px_log_log_warning ( const char *  name,
uint16_t  line,
const char *  format,
  ... 
)

Output warning info: module name, line and variable argument user format string.

The line is automatically appended with a new line character ('\n'), except if the format string ends with a tab character ('\t'). The tab character at the end of the string is discarded.

Parameters
nameModule / file name
lineLine number
formatUser format string
...Variable number of arguments

Definition at line 285 of file px_log.c.

◆ _px_log_log_info()

void _px_log_log_info ( const char *  name,
uint16_t  line,
const char *  format,
  ... 
)

Output info info: module name, line and variable argument user format string.

The line is automatically appended with a new line character ('\n'), except if the format string ends with a tab character ('\t'). The tab character at the end of the string is discarded.

Parameters
nameModule / file name
lineLine number
formatUser format string
...Variable number of arguments

Definition at line 310 of file px_log.c.

◆ _px_log_log_debug()

void _px_log_log_debug ( const char *  name,
uint16_t  line,
const char *  format,
  ... 
)

Output debug info: module name, line and variable argument user format string.

The line is automatically appended with a new line character ('\n'), except if the format string ends with a tab character ('\t'). The tab character at the end of the string is discarded.

Parameters
nameModule / file name
lineLine number
formatUser format string
...Variable number of arguments

Definition at line 336 of file px_log.c.

◆ _px_log_log_verbose()

void _px_log_log_verbose ( const char *  name,
uint16_t  line,
const char *  format,
  ... 
)

Output verbose info: module name, line and variable argument user format string.

The line is automatically appended with a new line character ('\n'), except if the format string ends with a tab character ('\t'). The tab character at the end of the string is discarded.

Parameters
nameModule / file name
lineLine number
formatUser format string
...Variable number of arguments

Definition at line 362 of file px_log.c.

◆ _px_log_assert()

void _px_log_assert ( const char *  name,
uint16_t  line 
)

Report that an assertion has failed and block indefinitely.

Parameters
nameModule / file name
lineLine number

Definition at line 388 of file px_log.c.

◆ _px_log_trace()

void _px_log_trace ( const char *  format,
  ... 
)

Output a user format string.

This function does not automatically append a new line character ('\n') so that multiple strings can be sent on the same line.

Parameters
formatUser format string
...Variable number of arguments

Definition at line 402 of file px_log.c.

◆ _px_log_trace_char()

void _px_log_trace_char ( char  c)

Output a character.

Parameters
cCharacter to output

Definition at line 416 of file px_log.c.

◆ _px_log_trace_data()

void _px_log_trace_data ( const void *  data,
size_t  nr_of_bytes 
)

Output the content of a buffer as an array of HEX values.

Parameters
dataPointer to buffer containing data to display
nr_of_bytesNumber of bytes in buffer to display

Definition at line 421 of file px_log.c.

◆ _px_log_trace_hexdump()

void _px_log_trace_hexdump ( const void *  data,
size_t  nr_of_bytes 
)

Output the content of a buffer as a spaced table of HEX values and ASCII characters.

Parameters
dataPointer to buffer containing data to display
nr_of_bytesNumber of bytes in buffer to display

Definition at line 433 of file px_log.c.