嵌入式日志输出

  嵌入式开发进行调试或者查找BUG时,常见的两种方法是仿真和日志打印的。但是在编写嵌入式软件程序过程时,并不是所有的硬件都支持仿真或者方便仿真,所以大多数方法是加打印信息来进行查找问题的。打印的接口有很多种,比如串口,网络,显示等等。这里简单记录下日志打印方法。

一、日志打印的目的

  1)方便查找打印日志
  2)日志格式规范
  3)可以查看用户添加信息,文件信息,函数接口,以及文件所在行号
  4)支持format格式
  5)可以支持实时时间

二、日志打印的基本知识

  C语言中的__FILE__、LINE__和 __FUNCTION
  1、FILE 用于指示本行代码所在源文件的文件名;
  2、__LINE__用于指示本行代码所在源文件中的位置(行数);
  3、__FUNCTION__用于指示本行代码所在函数(函数名);
注:
  1)"FILE "、“LINE”、"FUNCTION"等均大小写敏感
  2)支持需要添加头文件#include<stdio.h>

三、源码

#define DEBUG_EN (1u)
 
#if (DEBUG_EN)
 
#define DEBUG_MAX_SIZE 512
extern char szBuf[DEBUG_MAX_SIZE];
 
#define DEBUG_INFO( format, ... ) do{\
    u16 unLen = 0;\
    unLen += snprintf(szBuf+unLen,DEBUG_MAX_SIZE, "[INFO][%s][@%s][#%d]:",__FILE__,__FUNCTION__,__LINE__);\
    unLen += snprintf(szBuf+unLen,DEBUG_MAX_SIZE-unLen, format, ## __VA_ARGS__ );\
    usart1_send_buf_with_txe((u8 *)szBuf,unLen);\
}while(0)
 
#define DEBUG_WARN( format, ... ) do{\
    u16 unLen = 0;\
    unLen += snprintf(szBuf+unLen,DEBUG_MAX_SIZE, "[WARN][%s][@%s][#%d]:",__FILE__,__FUNCTION__,__LINE__);\
    unLen += snprintf(szBuf+unLen,DEBUG_MAX_SIZE-unLen, format, ## __VA_ARGS__ );\
    usart1_send_buf_with_txe((u8 *)szBuf,unLen);\
}while(0)
 
#define DEBUG_ERR( format, ... ) do{\
    u16 unLen = 0;\
    unLen += snprintf(szBuf+unLen,DEBUG_MAX_SIZE, "[ERR][%s][@%s][#%d]:",__FILE__,__FUNCTION__,__LINE__);\
    unLen += snprintf(szBuf+unLen,DEBUG_MAX_SIZE-unLen, format, ## __VA_ARGS__ );\
    usart1_send_buf_with_txe((u8 *)szBuf,unLen);\
}while(0)
 
#elif 
 
#define DEBUG_INFO(...)
#define DEBUG_WARN(...)
#define DEBUG_ERR(...)
 
#endif

  源码主要使用宏定义的方式,为了支持文件、行号,函数等等,不能使用单独的函数进行定义。C文件目前只有一个数组定义char szBuf[DEBUG_MAX_SIZE]。为了兼容,INFO,WARN和ERR三个共用一个buf,声明全局变量更主要的一个原因是使用了串口的中断发送函数usart1_send_buf_with_txe,而不是循环发送完成再退出,这里传输是进行指针传递的,发送使用中断的好处就是高效率,不耽误其他程序跑。当然移植的时候完全可以根据自己的接口和实现方式进行更换。

四、打印log的原则

  1、异常分支或错误处理一定要打log
  2、重大操作时一定要打log,

五、log格式的原则

  1、时间戳必须有,最好能够精确到微秒。
  一般格式:

[20170109 121630.541]

  2、打log位置的文件名和代码行数。这个不用说,用于定位问题根源。
  一般格式:

[20170109 121630.541][network.c:541]

  3、有进程id。
  一般格式:

[20170109 121630.541][network.c:541][pid=15529]

  4、有线程id。在多线程程序,如果不加线程id,很难追溯程序的行为
  一般格式:

[20170109 121630.541][network.c:541][pid=15529][thread=0x12345]

  5、有日志的级别。日志是反映问题的,有不同紧急程序的问题,自然有不同的日志级别。一般采用Error,Warning,Info,Debug。定义不同级别,也可以方便在日志查找问题来源。
  一般格式:

[20170109 121630.541][network.c:541][pid=15529][thread=0x12345][Error]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值