Zephyr log系统

Creative Commons
本作品采用知识共享署名

本文说明如何使用zephyr log系统。

简述

zephyr log系统提供一个通用的接口用于输出调试信息,主要有以下特性:

  • 异步显示,不占用当前上下文时间
  • 最多9个显示后端
  • 编译时module filter level筛选
  • 运行时后端filter level设置
  • 运行时module filter level设置
  • 同模块下多实例(instances)
  • 可用户设置时间戳格式
  • 提供dump raw data API
  • Panic支持
  • printk支持(printk重定位到log)

基本概念

Frontend : 前端,需要显示log的模块
Backend : 终端,log显示终端
Level : log等级,Frontend可以指定自己在指定Backend上的显示log的等级
Frontend呼叫LOG显示API将信息显示到Backend,可以有多个Frontend和Backend,每个Frontend都可以指定自己的信息在Backend的level。
例如:有2个Frontend:a1,a2,2个backend: uart,net,那么可以指定

  • a1的wrn以上信息在uart显示
  • a1的inf以上信息在net显示
  • a2的信息不在uart显示
  • a1的所有信息在net显示

使用实例

使用log系统很简单:

  1. conf中进行log配置
  2. 代码中注册log frontend
  3. 在代码中使用log API进行message显示
  4. 启动系统后通过shell的log命令控制

代码

配置文件prj.conf中配置使用log系统,开启了net backend,同时开启了shell,因此会有两个backend:net backend & shell uart backend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CONFIG_TEST_RANDOM_GENERATOR=y

# 网络配置,启动net backend需要网络配置
CONFIG_NETWORKING=y
CONFIG_NET_UDP=y

CONFIG_NET_IPV6=n
CONFIG_NET_IPV4=y
CONFIG_NET_DHCPV4=n
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_NEED_IPV6=n
CONFIG_NET_CONFIG_NEED_IPV4=y
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2"

#使用Shell,会开启shell uart backend
CONFIG_SHELL=y

#使用log系统
CONFIG_LOG=y
#使用和配置net backend
CONFIG_LOG_BACKEND_NET=y
CONFIG_LOG_BACKEND_NET_SERVER="192.0.2.2:514"

下面代码在一个thread调用LOG相关API显示log,注释log相关代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <zephyr.h>
#include <shell/shell.h>
#include <logging/log.h>

#define STACKSIZE 1024
//注册一个名为main的log frontend, build-in level为LOG_LEVEL_DBG
LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);

static K_THREAD_STACK_DEFINE(stack, STACKSIZE);
static struct k_thread main_thread;

static void log_thread_fun(void *p1, void *p2, void *p3)
{
int i = 0;
while(1){
LOG_ERR("main err %d", i++); //ERR Level log
LOG_WRN("main wrn"); //WRN Level log
LOG_INF("main info"); //INFO Level log
LOG_DBG("main dbg"); //DBG Level log
k_sleep(1000);
}
}

void main(void)
{
k_thread_create(&main_thread, stack, STACKSIZE, log_thread_fun, NULL, NULL,
NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);

}

操作

上面代码运行后可以在shell中进行log的控制,并在shell uart和net syslog(配置方法参见[如何接收UDP-Syslog[https://lgl88911.gitee.io/2019/02/03/%E5%A6%82%E4%BD%95%E6%8E%A5%E6%94%B6UDP-Syslog/]])中看到如下情况:
LOG

使用详解

配置

基本上将CONFIG_SHELL和CONFIG_LOG配置好就可用log系统,其它配置这里不展开说明了可以看官方文档

Level

log系统支援4种等级,严重程度为:err>wrn>inf>dbg
当前显示log level必须大于等于系统设置的level,例如当设置为显示wrn level,那么就只有err和wrn会被显示。

module&输出

不同的module用不同的module注册,显示时会显示module名称,log控制时也已module控制。
下面的示例注册module名称为main, build-in level为LOG_LEVEL_DBG

1
LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG)

build-in level是在编译的时候指定了该module的level,在运行设置的level只能比build-in的大,否则无效,例如build-in level是wrn,如果运行时设置level为dbg,实际显示还是只会显示level大于等于wrn的log。
一个module只能在一个文件中注册,但可以跨文件使用,只用在其它文件中使用LOG_MODULE_DECLARE声明即可,例如下面几个文件都属于led module:

1
2
3
led_main.c      LOG_MODULE_REGISTER(main, LOG_LEVEL_INF)
led_control.c LOG_MODULE_DECLARE(main)
lec_check.c LOG_MODULE_DECLARE(main)

log显示使用下面的宏:

  • 格式化字符串显示的宏:LOG_ERR,LOG_WRN, LOG_INF, LOG_DBG
  • raw hex显示的宏:LOG_HEXDUMP_ERR,LOG_HEXDUMP_ERR, LOG_HEXDUMP_INF, LOG_HEXDUMP_DBG
    例如
    1
    2
    LOG_ERR("This is err");
    LOG_HEXDUMP_ERR(buffer, 16, "Raw:");

命令控制

shell的log命令共有下面几条

  • backend : 控制backend
  • list_backends : 显示所有backend
  • disable : 关闭shell uart backend
  • enable : 设置/启动 shell uart backend
  • go : 恢复shell uart backend
  • halt : 停止shell uart backend
  • status : 查看shell uart backend中不同module的level

例如设置main module显示wrn及以上log信息:
log enable wrn main
对于backend命令可以对指定的backend执行子命令disable,enable,go,halt,status
例如设置net backend在main module显示inf及以上log信息:
log backend log_backend_net enable inf main

参考

https://docs.zephyrproject.org/latest/reference/logging/index.html