SOC-ESP32S3部分:5-IDF的日志管理
飞书文档https://x509p6c8to.feishu.cn/wiki/MUkSwSCw1ixhl2kvNL2cU708nHe
前面的代码中,我们一般直接使用printf进行日志打印,这在绝大多数情况下是没问题的。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"void app_main(void)
{int i = 0;while (1) {printf("[%d] Hello world!\n", i);i++;vTaskDelay(5000 / portTICK_PERIOD_MS);}
}
但是企业中开发项目,其实要求我们可以更好管理日志,例如调试的日志在发布时不打印,例如应为每个模块设置不同的日志级别。那应该如何实现呢?
1.1、使用日志组件
其实idf中就给我们提供了日志组件,我们可以直接使用,具体说明可以点击下方文档了解。
https://docs.espressif.com/projects/esp-idf/zh_CN/v5.4/esp32s3/api-reference/system/log.html
头文件
#include "esp_log.h"可使用下列宏来定义不同的日志级别:
ESP_LOGE - 错误
ESP_LOGW - 警告
ESP_LOGI - 普通
ESP_LOGD - 调试
ESP_LOGV - 冗余
函数说明
函数说明如下:
ESP_LOGE(const char *tag, const char *format, ...);
ESP_LOGW(const char *tag, const char *format, ...);
ESP_LOGI(const char *tag, const char *format, ...);
ESP_LOGD(const char *tag, const char *format, ...);
ESP_LOGV(const char *tag, const char *format, ...);参数说明:
const char *tag
含义:日志标签(Log Tag),是一个字符串指针,用于标识日志信息的来源。
const char *format, ...
含义:这是一个格式化字符串和可变参数列表。format 是一个字符串,用于指定输出日志的格式,类似于 printf 函数的格式化字符串;使用示例:
int temperature = 25;
const char *TAG = "SENSOR";
ESP_LOGD(TAG, "The current temperature is %d degrees Celsius", temperature);
如何使用idf的日志库呢?为了方便演示,我们新建工程03_log_project,然后执行idf.py fullclean
修改main.c代码如下
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"static const char* TAG = "MyModule"; //模块名称void app_main(void)
{ESP_LOGE(TAG, "this is esp log"); //错误日志,用于记录系统中发生的严重错误,这些错误通常会导致程序无法正常运行或产生严重的异常情况。ESP_LOGW(TAG, "this is esp log"); //警告日志,用于记录可能会影响程序正常运行,但不会导致程序崩溃的潜在问题或异常情况。ESP_LOGI(TAG, "this is esp log"); //信息日志,用于记录程序的正常运行状态和重要事件,帮助开发者了解程序的执行流程和关键操作的结果。ESP_LOGD(TAG, "this is esp log"); //调试日志,用于记录程序的详细执行过程和中间结果,主要用于开发和调试阶段,帮助开发者排查问题。ESP_LOGV(TAG, "this is esp log"); //详细日志,用于记录最详细的程序执行信息,输出的日志信息最多,会带来较大的系统开销,通常只在开发和调试阶段使用。while (1) {vTaskDelay(5000 / portTICK_PERIOD_MS);}
}
复制的工程需要编译前,需要执行idf.py fullclean清除之前编译的配置。
idf.py fullclean
idf.py set-target esp32s3
idf.py build
idf.py flash monitor //烧录,需要自行指定端口-p xxxx
此时我们可以看到打印的各种彩色日志
但细看我们会发现,日志只打印了E W I三条,还有D V的没有打印,这是因为什么呢?
1.2、设置打印日志级别
我们回到官网的文档部分:
https://docs.espressif.com/projects/esp-idf/zh_CN/v5.4/esp32s3/api-reference/system/log.html
我们可以回到文档中看到有这么一个描述:
也就是说我们可以配置CONFIG_LOG_DEFAULT_LEVEL这个宏来决定打印日志的类型,等于或小于这个宏值能打印,高的不能打印,在sdkconfig文件中可以看到CONFIG_LOG_DEFAULT_LEVEL默认为3,所以ESP_LOG_ERROR、ESP_LOG_WARN、ESP_LOG_INFO都可以打印。
typedef enum {ESP_LOG_NONE = 0, /*!< No log output */ESP_LOG_ERROR = 1, /*!< Critical errors, software module can not recover on its own */ESP_LOG_WARN = 2, /*!< Error conditions from which recovery measures have been taken */ESP_LOG_INFO = 3, /*!< Information messages which describe normal flow of events */ESP_LOG_DEBUG = 4, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ESP_LOG_VERBOSE = 5, /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */ESP_LOG_MAX = 6, /*!< Number of levels supported */
} esp_log_level_t;
那这个CONFIG_LOG_DEFAULT_LEVEL在哪里配置呢?答案就是上节课的menuconfig中
我们依次找Component config → Log → Log Level
| | |
然后就可以修改日志打印级别,我们修改为Verbose即可
| |
然后重复按ESC退出保存即可,保存成功后,我们可以在工程sdkconfig文件中看到
然后再次编译、烧录、运行
idf.py build
idf.py flash monitor //烧录,需要自行指定端口-p xxxx
到这里,我们就可以看到所有的日志都打印出来了。
1.3、更加快捷的menuconfig搜索
前面我们手动一个个设置寻找然后选择,效率还是太低了,那有没有直接搜索设置名称的方式呢?那当然也是有的,我们执行idf.py menuconfig
按/,搜索LOG_DEFAULT_LEVEL,注意,这里没有CONFIG
就可以看到日志级别的菜单,然后点击Enter回车,就可以直接进入到最终的设置页面
然后在这里直接修改即可,是不是方便多了呢?
到这里,我们就可以回答课程一开始提出的问题了,在调试阶段,我们可以设置CONFIG_LOG_DEFAULT_LEVEL=5,这时候所有日志都会打印,在产品发布时,我们可以设置CONFIG_LOG_DEFAULT_LEVEL=1,这时候只会打印关键日志,一些调试的信息别人就看不到了。