Rules for Debugging Logs in Embedded Development

Follow+Star Public Account, don’t miss out on exciting content
Rules for Debugging Logs in Embedded Development
Source | Embedded Miscellaneous

In our embedded development, printing logs is the most commonly used debugging method. Properly printing logs can help us quickly analyze problems.

This article summarizes some rules for logging in embedded systems.

1. When to Add Logs?

(1) Error Handling

For unrecoverable serious errors, the log content should be detailed enough to help locate the problem, but should not contain sensitive information. For example, use the Error level when memory allocation fails along with log information.

(2) Key Operations

For critical processes, logs should be printed for both normal and abnormal situations. For instance, there should be corresponding log information when WiFi is turned on.

(3) System Startup and Shutdown

Recording key steps during system startup and shutdown helps analyze whether the system initialization is correct or whether the system shuts down normally.

(4) Performance Monitoring

Logs can record key performance indicators of system operation, such as CPU and memory usage, IO operations, etc., for system performance analysis and optimization.

(5) Key Data

Some key data need to be printed, as many functional issues are directly linked to the data.

(6) Communication Logs

For embedded systems that need to communicate with external devices or networks, recording communication logs can help analyze and debug communication protocols or data exchange issues.

(7) Record User Behavior

When analyzing how users interact with embedded devices, logging user behavior can be very helpful.

(8) if, switch

In branch judgments, each execution branch needs to have corresponding log information added, which can help us accurately know the direction of program execution.

(9) Information During Program Crash

For example, the call stack information when an application process crashes under Linux.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>

void func0(void)
{
    printf("This is func0\n");
    int *p = NULL;
    *p = 1234;
}

void func1(void)
{
    printf("This is func1\n");
    func0();
}

void func2(void)
{
    printf("This is func2\n");
    func1();
}

void dump(int signo)
{
    void *array[100];
    size_t size;
    char **strings;

    size = backtrace(array, 100);
    strings = backtrace_symbols(array, size);

    printf("Obtained %zd stacks.\n", size);
    for(int i = 0; i < size; i++)
    {
        printf("%s\n", strings[i]);
    }
        
    free(strings);
    exit(0);
}

int main(int argc, char **argv)
{
    printf("==================segmentation fault test5==================\n");
    signal(SIGSEGV, &dump);
    func2();

    return 0;
}
Rules for Debugging Logs in Embedded Development

2. Module Tagging

In a project, multiple modules will definitely be divided, and a module tag string can be assigned to each module, included in the log entries. This way, we can filter logs for a specific module in the log file, improving our efficiency in locating problems.

For example:

// app_wifi.c
#define LOG_TAG    "[wifi_module]"
#define LOG_D(fmt, arg...) LOG_D_TAG(LOG_TAG, fmt, ##arg)
LOG_D("hello wifi module");

Output:

[wifi_module]hello wifi module

3. Module Log Switch

Setting a module log switch can conveniently narrow down the analysis range when debugging and analyzing problems. When our function design has multiple functional modules, if a problem occurs in a certain module, we only care about that module and can turn off the logging functionality of other modules while keeping the logs of the concerned module on.

For example:

// module1.c
#include "module1.h"

#if MODULE1_LOG_SWITCH
#define LOG_MODULE1(fmt, args...)   DBG_PRINTF(fmt, ##args)  
#else
#define LOG_MODULE1(fmt, args...) 
#endif

// module2.c
#include "module2.h"

#if MODULE2_LOG_SWITCH
#define LOG_MODULE2(fmt, args...)   DBG_PRINTF(fmt, ##args)  
#else
#define LOG_MODULE2(fmt, args...) 
#endif

// config.h
#define  MODULE1_LOG_SWITCH  0
#define  MODULE2_LOG_SWITCH  1

4. Timestamps

Logs should include timestamps, making it easy to view the execution time of a certain piece of code and determine when problems occur. The timestamp should ideally be accurate to microseconds/milliseconds.

5. Log Levels

Using different log levels can help filter and control the amount of information output.

Common log levels include:

  • Error: The program cannot run or there is a serious issue.
  • Warning: Potential issues, the program can continue running.
  • Info: Information about the program’s running status.
  • Debug: Detailed debugging information, including variable values and program flow.
  • Verbose: Very detailed information for in-depth debugging.

6. Unified Format

To make logs easy to read, all logs should maintain a consistent format.

Common fixed information in logs includes:

  • Filename
  • Line Number
  • Date/Time Timestamp
  • Function Name
  • Module Name
  • Process ID
  • Thread ID

These can be combined as needed. For example:

[2024-01-14 11:12:30.666][wifi_module][func:wifi_init]

7. Filtering Control

Using dynamic filtering control for logs can dynamically adjust the output of logs, provided that the logging component used in the project has such capability. For example, EasyLogger (https://github.com/armink/EasyLogger).

Rules for Debugging Logs in Embedded Development

8. Release/Debug Switch

Since log printing may consume considerable system resources, attention should be paid to its impact on performance. In the Release version, it may be necessary to reduce log output or remove some unnecessary logs, requiring a switch to toggle.

9. Encapsulating Log Interfaces

In embedded systems, logs are mostly output to serial terminals. However, there are scenarios where logs need to be output to screens, network devices, customized upper computers, etc. Corresponding interfaces should be reserved for flexible switching.

That concludes this sharing session. Feel free to save and forward!

———— END ————

Rules for Debugging Logs in Embedded Development

● Column “Embedded Tools”

● Column “Embedded Development”

● Column “Keil Tutorial”

● Selected Tutorials for Embedded Columns

Follow the public account Reply “Join Group” to join the technical exchange group according to the rules, reply “1024” to see more content.

Rules for Debugging Logs in Embedded Development

Rules for Debugging Logs in Embedded Development

Click “Read Original” for more shares.

Leave a Comment