743|0

504

帖子

4

TA的资源

纯净的硅(高级)

楼主
 

【ST多款开发板返场测评】STM32F767 Nucleo-144 灵活可配的LOG日志输出实现 [复制链接]

前言

磨刀不误砍柴工,前面的非阻塞串口打印,shell命令行交互都是为了方便后面USB开发的调试。现在开始正是开始砍柴了。第一步我们就是实现比较灵活的LOG输出。主要考虑以下几点需求

  1. 非阻塞,前面已经实现了相关的接口
  2. 可配置日志输出等级,因为调试输出可能很多,所以根据等级过滤会方便查看
  3. 可配置日子类型,结合上述等级可控制,进一步能控制不同类型(TAG)的日志的不同等级的使能,这样可以更精确的分类输出。
  4. 可动态命令行配置,基于前面的shell可以动态修改不同TAG的不同等级的日志的使能控制。
  5. 可以根据不同等级显示不通的颜色,方便屠户显示错误。

 

过程

添加debug.c和debug.h

 

使能配置如下,一个数组记录每个TAG的当前使能等级

static uint8_t debug_level_enabled[DEBUG_TAG_MAX] = {



};



void debug_toggle_level(debug_level_t tag)

{

if (tag >= DEBUG_TAG_MAX)

return;

debug_level_enabled[tag] ^= 0x80;

}





void debug_set_level(debug_tag_t tag, debug_level_t level)

{

if (level >= DEBUG_LEVEL_MAX)

return;

if (tag >= DEBUG_TAG_MAX)

return;

if(level == DEBUG_LEVEL_OFF)

  {

debug_level_enabled[tag] = 0;

}

else

  {

debug_level_enabled[tag] = level | 0x80;

}

}



debug_level_t debug_get_level(debug_tag_t tag)

{

if (tag >= DEBUG_TAG_MAX)

return DEBUG_LEVEL_OFF;

return debug_level_enabled[tag];

}

 

根据不同等级打印不同颜色

void debug_set_color(debug_color_t color) {



unsigned int color_code, modifier_code;

switch (color & COLOR_MASK_COLOR) {

case COLOR_BLACK:

color_code = 30; break;

case COLOR_RED:

color_code = 31; break;

case COLOR_GREEN:

color_code = 32; break;

case COLOR_YELLOW:

color_code = 33; break;

case COLOR_BLUE:

color_code = 34; break;

case COLOR_MAGENTA:

color_code = 35; break;

case COLOR_CYAN:

color_code = 36; break;

case COLOR_WHITE:

color_code = 37; break;

case COLOR_RESET:

default:

color_code = 0; break;

}



switch (color & COLOR_MASK_MODIFIER) {

case COLOR_BOLD:

modifier_code = 1; break;

case COLOR_UNDERLINE:

modifier_code = 2; break;

case COLOR_BLINK:

modifier_code = 3; break;

case COLOR_HIDE:

modifier_code = 4; break;

case COLOR_NORMAL:

default:

modifier_code = 0; break;

}



printf("\033[%u;%um", modifier_code, color_code);

}

 

 

打印接口

void do_debug(debug_tag_t tag, debug_level_t level, const char *format, ...)

{

int color = COLOR_RESET;

va_list args;

/* Don't print anything if log level is disabled */

if(((debug_level_enabled[tag] & 0x80) == 0) || ((debug_level_enabled[tag] & 0x7F) > level))

return;



switch(level) {

case DEBUG_LEVEL_INFO:

color = COLOR_GREEN | COLOR_BOLD;

break;

case DEBUG_LEVEL_ERROR:

color = COLOR_RED | COLOR_BOLD;

break;

case DEBUG_LEVEL_WARN:

color = COLOR_YELLOW | COLOR_BOLD;

break;

default:

return;

}

va_start(args, format);

/* If csp_debug_hook symbol is defined, pass on the message.

 * Otherwise, just print with pretty colors ... */

if (debug_hook_func) {

debug_set_color((debug_color_t)color);

debug_hook_func((debug_color_t)color, format, args);

      debug_set_color(COLOR_RESET);

} else {

debug_set_color((debug_color_t)color);

vprintf(format, args);

printf("\r\n");

debug_set_color(COLOR_RESET);

}



va_end(args);

}

添加命令行

shell_func.c中#include "debug.h"

 

shell_cmd_list添加一行

  { (const uint8_t*)"debug",        DebugFun,         "debug tag level"},

 

添加实现函数

void DebugFun(unsigned char* param)

{

int tag;

int level;

if(2 == sscanf((const char*)param, "%*s %d %d", &tag, &tag))

  {

debug_set_level(tag, level);

}

}

 

shell_func.c中

void DebugFun(unsigned char* param);

 

可以看到添加的命令

 

 

 

 

 

 

 

测试

Main.c中

#include "debug.h"

 

 

 

 

使能颜色主题

 

输入

debug 0 1

debug 1 1

debug 2 1

使能所有TAG的所有等级输出

 

 

输入

debug 0 3

debug 1 3

debug 2 3

使能所有TAG的ERROR等级输出

则只输出ERROR

 

 

debug 0 0

关闭TAG0输出则只剩下如下两个TAG输出

 

 

代码

Debug.c

#include <stdio.h>
#include "debug.h"

/* Custom debug function */
debug_hook_func_t debug_hook_func = NULL;

/* Debug levels */
static uint8_t debug_level_enabled[DEBUG_TAG_MAX] = {

};

/* Some compilers do not support weak symbols, so this function
 * can be used instead to set a custom debug hook */
void csp_debug_hook_set(debug_hook_func_t f)
{
	debug_hook_func = f;
}

void debug_set_color(debug_color_t color) {

	unsigned int color_code, modifier_code;
	switch (color & COLOR_MASK_COLOR) {
		case COLOR_BLACK:
			color_code = 30; break;
		case COLOR_RED:
			color_code = 31; break;
		case COLOR_GREEN:
			color_code = 32; break;
		case COLOR_YELLOW:
			color_code = 33; break;
		case COLOR_BLUE:
			color_code = 34; break;
		case COLOR_MAGENTA:
			color_code = 35; break;
		case COLOR_CYAN:
			color_code = 36; break;
		case COLOR_WHITE:
			color_code = 37; break;
		case COLOR_RESET:
		default:
			color_code = 0; break;
	}
	
	switch (color & COLOR_MASK_MODIFIER) {
		case COLOR_BOLD:
			modifier_code = 1; break;
		case COLOR_UNDERLINE:
			modifier_code = 2; break;
		case COLOR_BLINK:
			modifier_code = 3; break;
		case COLOR_HIDE:
			modifier_code = 4; break;
		case COLOR_NORMAL:
		default:
			modifier_code = 0; break;
	}

	printf("\033[%u;%um", modifier_code, color_code);
}

void do_debug(debug_tag_t tag, debug_level_t level, const char *format, ...)
{
	int color = COLOR_RESET;
	va_list args;
	/* Don't print anything if log level is disabled */
	if(((debug_level_enabled[tag] & 0x80) == 0) || ((debug_level_enabled[tag] & 0x7F) > level))
		return;

	switch(level) {
	case DEBUG_LEVEL_INFO:
		color = COLOR_GREEN | COLOR_BOLD;
		break;
	case DEBUG_LEVEL_ERROR:
		color = COLOR_RED | COLOR_BOLD;
		break;
	case DEBUG_LEVEL_WARN:
		color = COLOR_YELLOW | COLOR_BOLD;
		break;
	default:
		return;
	}
	va_start(args, format);
	/* If csp_debug_hook symbol is defined, pass on the message.
	 * Otherwise, just print with pretty colors ... */
	if (debug_hook_func) {
			debug_set_color((debug_color_t)color);
			debug_hook_func((debug_color_t)color, format, args);
      debug_set_color(COLOR_RESET);
	} else {
		debug_set_color((debug_color_t)color);
		vprintf(format, args);
		printf("\r\n");
		debug_set_color(COLOR_RESET);
	}

	va_end(args);
}


void debug_toggle_level(debug_level_t tag)
{
	if (tag >= DEBUG_TAG_MAX)
		return;
	debug_level_enabled[tag] ^= 0x80;
}


void debug_set_level(debug_tag_t tag, debug_level_t level)
{
	if (level >= DEBUG_LEVEL_MAX)
		return;
	if (tag >= DEBUG_TAG_MAX)
		return;
	if(level == DEBUG_LEVEL_OFF)
  {
		debug_level_enabled[tag] = 0;
	}
	else
  {
		debug_level_enabled[tag] = level | 0x80;
	}
}

debug_level_t debug_get_level(debug_tag_t tag)
{
	if (tag >= DEBUG_TAG_MAX)
		return DEBUG_LEVEL_OFF;
	return debug_level_enabled[tag];
}

Debug.h

#ifndef DEBUG_H
#define DEBUG_H

#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdarg.h>

#ifdef __cplusplus
extern "C" {
#endif

/** Debug levels */
typedef enum {
	DEBUG_LEVEL_OFF	= 0,
	DEBUG_LEVEL_INFO	= 1,
	DEBUG_LEVEL_WARN	= 2,
	DEBUG_LEVEL_ERROR	= 3,
	DEBUG_LEVEL_MAX	= 4,
} debug_level_t;

/** Debug tags */
typedef enum {
	DEBUG_TAG_SETUP	= 0,
	DEBUG_TAG_INT	= 1,
	DEBUG_TAG_STATE	= 2,
	DEBUG_TAG_MAX	= 3,
} debug_tag_t;

#define COLOR_MASK_COLOR 	0x0F
#define COLOR_MASK_MODIFIER	0xF0

typedef enum {
	/* Colors */
	COLOR_RESET		= 0xF0,
	COLOR_BLACK		= 0x01,
	COLOR_RED		= 0x02,
	COLOR_GREEN		= 0x03,
	COLOR_YELLOW	= 0x04,
	COLOR_BLUE		= 0x05,
	COLOR_MAGENTA	= 0x06,
	COLOR_CYAN		= 0x07,
	COLOR_WHITE		= 0x08,
	/* Modifiers */
	COLOR_NORMAL	= 0x0F,
	COLOR_BOLD		= 0x10,
	COLOR_UNDERLINE	= 0x20,
	COLOR_BLINK		= 0x30,
	COLOR_HIDE		= 0x40,
} debug_color_t;

typedef void (*debug_hook_func_t)(debug_color_t color, const char *format, va_list args);

void csp_debug_hook_set(debug_hook_func_t f);

/* Extract filename component from path */
#define BASENAME(_file) ((strrchr(_file, '/') ? : (strrchr(_file, '\\') ? : _file)) + 1)

#ifndef NDEBUG
	#define debug_assert(exp)										\
	do {												\
		if (!(exp)) {										\
			char *assertion = #exp;								\
			const char *file = BASENAME(__FILE__);						\
			int line = __LINE__;								\
			printf("\E[1;31m Assertion \'%s\' failed in %s:%d\E[0m\r\n",	\
			       assertion, file, line);}											\
	} while (0)
#else
	#define debug_assert(...) do {} while (0)
#endif


#ifdef DEBUG
	#define debug(tag, level, format, ...) do { do_debug(tag, level, CONSTSTR(format), ##__VA_ARGS__); } while(0)
#else
	#define debug(...) do {} while (0)
#endif


/**
 * This function should not be used directly, use log_<level>() macro instead
 * @param tag
 * @param level
 * @param format
 */
void do_debug(debug_tag_t tag, debug_level_t level, const char *format, ...);

/**
 * Toggle debug level on/off
 * @param tag Tag to toggle
 */
void debug_toggle_level(debug_level_t tag);

/**
 * Set debug level
 * @param tag Tag value to get
 * @param level Level to set
 */
void debug_set_level(debug_tag_t tag, debug_level_t level);

/**
 * Get current debug level value
 * @param tag Tag value to get
 * [url=home.php?mod=space&uid=784970]@return[/url] Level value
 */
debug_level_t debug_get_level(debug_tag_t tag);

#ifdef __cplusplus
} /* extern "C" */
#endif


#endif

 

 

总结

以上实现了比较灵活可配置的LOG输出,可配置TAG和指定TAG的输出等级,

方便后面USB调试动态修改条数输出。

此帖出自stm32/stm8论坛
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表