最近从STM32换成NXP的S32K1平台做项目,从读手册调外设驱动开始,关于外设驱动是怎么调的,我用的软件是S32 Design Studio for ARM Version 2.2 在官网下载的,注册账号产品码会发到邮箱选择ONLINE验证,安装完成就可以调试驱动了。

回归主题!
这次想说的是嵌入式平台打印log的函数分析,打印log开源项目都有很多比如Zlog,easylogger等,这次分析一下easylogger中部分源码的作用。
我的C语言水平一般,看起来还挺吃力的

  #define elog_info(tag, ...) \elog_output(ELOG_LVL_INFO, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
//我们的主角elog_output#define elog_i(tag, ...)     elog_info(tag, __VA_ARGS__)#define log_i(...)       elog_i(LOG_TAG, __VA_ARGS__)//解释一下__VA_ARGS__:用于在宏替换部分中,表示可变参数列表;[我的参考] (https://blog.csdn.net/auccy/article/details/88833659)log_a("Hello EasyLogger!");log_e("Hello EasyLogger!");log_w("Hello EasyLogger!");log_i("Hello EasyLogger!");log_d("Hello EasyLogger!");log_v("Hello EasyLogger!");

分析一下elog_output,我不会的大家有想法的都可以留言一起进步!
他是一个变长参数函数前三个

void elog_output(uint8_t level, const char *tag, const char *file, const char *func,const long line, const char *format, ...) {extern const char *elog_port_get_time(void);extern const char *elog_port_get_p_info(void);extern const char *elog_port_get_t_info(void);
//elog提供了三个接口三个指针函数返回值用来获取当前时间、获取进程号、获取线程号
//因为本文中移植到裸机工程中,并且没有提供时间支持
//所以这三个接口都返回空字符串size_t tag_len = strlen(tag), log_len = 0, newline_len = strlen(ELOG_NEWLINE_SIGN);//获得tag的长度,初始化局部LOG的长度  //#define ELOG_NEWLINE_SIGN   "\n" 新一行标志的长度//输出行号最大长度//#define ELOG_LINE_NUM_MAX_LEN                    5//#define ELOG_FILTER_TAG_MAX_LEN                  30char line_num[ELOG_LINE_NUM_MAX_LEN + 1] = { 0 };char tag_sapce[ELOG_FILTER_TAG_MAX_LEN / 2 + 1] = { 0 };//va_list args;//首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针; //然后用VA_START宏初始化变量刚定义的VA_LIST变量; int fmt_result;//EasyLogger自带的断言,可以直接用户软件,在断言表达式不成立后会输出断言信息并保持while(1),//或者执行断言钩子方法,钩子方法的设定参考 elog_assert_set_hook/*关于断言对于断言,相信大家都不陌生,大多数编程语言也都有断言这一特性。简单地讲,断言就是对某种假设条件进行检查。在 C 语言中,断言被定义为宏的形式(assert(expression)),而不是函数,其原型定义在<assert.h>文件中。其中,assert 将通过检查表达式 expression 的值来决定是否需要终止执行程序。也就是说,如果表达式 expression 的值为假(即为 0),那么它将首先向标准错误流 stderr 打印一条出错信息,然后再通过调用 abort 函数终止程序运行;否则,assert 无任何作用。*/ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);//elog_init中初始化elog.output_enabled/* check output enabled */if (!elog.output_enabled) {return;}//过滤器等级 elog_set_filter_lvl(ELOG_LVL_VERBOSE);elog_init初始化/* level filter */if (level > elog.filter.level || level > elog_get_filter_tag_lvl(tag)) {return;} else if (!strstr(tag, elog.filter.tag)) { /* tag filter */return;}//获得并指向第一个参数/* args point to the first variable parameter */va_start(args, format);/* lock output 这里边实现是关中断可能是为了保证日志的正确性用关闭全局中断来加锁*/elog_output_lock();#ifdef ELOG_COLOR_ENABLE/* add CSI start sign and color info */if (elog.text_color_enabled) {log_len += elog_strcpy(log_len, log_buf + log_len, CSI_START);log_len += elog_strcpy(log_len, log_buf + log_len, color_output_info[level]);}
#endif
//elog_strcpy的实现参考strcpy实现
//即把从src地址开始的字符串复制到以dest开始的地址空间/* package level info */if (get_fmt_enabled(level, ELOG_FMT_LVL)) {log_len += elog_strcpy(log_len, log_buf + log_len, level_output_info[level]);}/* package tag info */if (get_fmt_enabled(level, ELOG_FMT_TAG)) {log_len += elog_strcpy(log_len, log_buf + log_len, tag);/* if the tag length is less than 50% ELOG_FILTER_TAG_MAX_LEN, then fill space */if (tag_len <= ELOG_FILTER_TAG_MAX_LEN / 2) {memset(tag_sapce, ' ', ELOG_FILTER_TAG_MAX_LEN / 2 - tag_len);log_len += elog_strcpy(log_len, log_buf + log_len, tag_sapce);}log_len += elog_strcpy(log_len, log_buf + log_len, " ");}/* package time, process and thread info */if (get_fmt_enabled(level, ELOG_FMT_TIME | ELOG_FMT_P_INFO | ELOG_FMT_T_INFO)) {log_len += elog_strcpy(log_len, log_buf + log_len, "[");/* package time info */if (get_fmt_enabled(level, ELOG_FMT_TIME)) {log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_time());if (get_fmt_enabled(level, ELOG_FMT_P_INFO | ELOG_FMT_T_INFO)) {log_len += elog_strcpy(log_len, log_buf + log_len, " ");}}/* package process info */if (get_fmt_enabled(level, ELOG_FMT_P_INFO)) {log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_p_info());if (get_fmt_enabled(level, ELOG_FMT_T_INFO)) {log_len += elog_strcpy(log_len, log_buf + log_len, " ");}}/* package thread info */if (get_fmt_enabled(level, ELOG_FMT_T_INFO)) {log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_t_info());}log_len += elog_strcpy(log_len, log_buf + log_len, "] ");}/* package file directory and name, function name and line number info */if (get_fmt_enabled(level, ELOG_FMT_DIR | ELOG_FMT_FUNC | ELOG_FMT_LINE)) {log_len += elog_strcpy(log_len, log_buf + log_len, "(");/* package file info */if (get_fmt_enabled(level, ELOG_FMT_DIR)) {log_len += elog_strcpy(log_len, log_buf + log_len, file);if (get_fmt_enabled(level, ELOG_FMT_FUNC)) {log_len += elog_strcpy(log_len, log_buf + log_len, ":");} else if (get_fmt_enabled(level, ELOG_FMT_LINE)) {log_len += elog_strcpy(log_len, log_buf + log_len, " ");}}/* package line info */if (get_fmt_enabled(level, ELOG_FMT_LINE)) {snprintf(line_num, ELOG_LINE_NUM_MAX_LEN, "%ld", line);log_len += elog_strcpy(log_len, log_buf + log_len, line_num);if (get_fmt_enabled(level, ELOG_FMT_FUNC)) {log_len += elog_strcpy(log_len, log_buf + log_len, " ");}}/* package func info */if (get_fmt_enabled(level, ELOG_FMT_FUNC)) {log_len += elog_strcpy(log_len, log_buf + log_len, func);}log_len += elog_strcpy(log_len, log_buf + log_len, ")");}/* package other log data to buffer. '\0' must be added in the end by vsnprintf. *///将可变参数格式化输出到一个字符数组//参数1 生成的格式化的字符串存放//参数2可接受的最大字符数//参数3 指定输出格式//返回值:执行成功,返回最终生成字符串的长度fmt_result = vsnprintf(log_buf + log_len, ELOG_LINE_BUF_SIZE - log_len, format, args);//用va_end宏结束可变参数的获取va_end(args);/* calculate log length */if ((log_len + fmt_result <= ELOG_LINE_BUF_SIZE) && (fmt_result > -1)) {log_len += fmt_result;} else {/* using max length */log_len = ELOG_LINE_BUF_SIZE;}/* overflow check and reserve some space for CSI end sign and newline sign */
#ifdef ELOG_COLOR_ENABLEif (log_len + (sizeof(CSI_END) - 1) + newline_len > ELOG_LINE_BUF_SIZE) {/* using max length */log_len = ELOG_LINE_BUF_SIZE;/* reserve some space for CSI end sign */log_len -= (sizeof(CSI_END) - 1);
#elseif (log_len + newline_len > ELOG_LINE_BUF_SIZE) {/* using max length */log_len = ELOG_LINE_BUF_SIZE;
#endif /* ELOG_COLOR_ENABLE *//* reserve some space for newline sign */log_len -= newline_len;}//关键字截取 符串里的log_buf含有keyword字符串的情况/* keyword filter */if (elog.filter.keyword[0] != '\0') {/* add string end sign */log_buf[log_len] = '\0';/* find the keyword */if (!strstr(log_buf, elog.filter.keyword)) {/* unlock output */elog_output_unlock();//取消关闭中断return;}}
//因为我是做汽车电子的项目这里临界区对于日志的保护是否有必要?
//各位可以畅所欲言
#ifdef ELOG_COLOR_ENABLE/* add CSI end sign */if (elog.text_color_enabled) {log_len += elog_strcpy(log_len, log_buf + log_len, CSI_END);}
#endif/* package newline sign */log_len += elog_strcpy(log_len, log_buf + log_len, ELOG_NEWLINE_SIGN);//加入换行标志\n/* output log */
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)extern void elog_async_output(uint8_t level, const char *log, size_t size);elog_async_output(level, log_buf, log_len);
#elif defined(ELOG_BUF_OUTPUT_ENABLE)extern void elog_buf_output(const char *log, size_t size);elog_buf_output(log_buf, log_len);
#elseelog_port_output(log_buf, log_len);
#endif
//输出接口/* unlock output */elog_output_unlock();
}

剩下的功能需要在移植之后跑一下来验证!

NXP S32K146 打印LOG函数分析相关推荐

  1. 【FFmpeg】打印日志函数分析(可以根据不同级别打印不同颜色的日志)

    FFmpeg的打印日志实现在FFmpeg-n4.2.1/libavutil/log.c中. 一.设置log等级 1.设置日志级别 日志默认级别是AV_LOG_INFO static int av_lo ...

  2. Linux内核出错的栈打印详解,linux内核中打印栈回溯信息 - dump_stack()函数分析

    简介 当内核出现比较严重的错误时,例如发生Oops错误或者内核认为系统运行状态异常,内核就会打印出当前进程的栈回溯信息,其中包含当前执行代码的位置以及相邻的指令.产生错误的原因.关键寄存器的值以及函数 ...

  3. php error log 函数,php日志函数error_log如何使用 php日志函数error_log用法介绍

    php日志函数error_log如何使用?这篇文章主要介绍了php日志函数error_log用法,结合实例形式分析了php日志函数error_log相关的配置文件设置.函数功能.用法与使用注意事项,需 ...

  4. Android中日志打印 Log的使用

    文章目录 Log等级划分 Log使用规范 Android Studio中log使用 Logcat中选择筛选条件 Log信息颜色设置 Log信息说明 写一份便于使用的Log辅助类 Log等级划分 Log ...

  5. android jni打印log信息

    今天,讲讲在jni中如何打印logxx,用来进行调试. 一.实现 1.修改Android.mk文件. 在这个配置文件中我们加入如下一行代码: LOCAL_LDLIBS += -llog 注意:这行代码 ...

  6. NXP S32K146 FLEXI2C底层驱动+IAM-20680(二)

    NXP S32K146 FLEXI2C底层驱动+IAM-20680(一) 在上一篇文章的基础上,写IAM-20680的接口层,与上一篇差不多,os任务中分为初始化与正常运行,下面根据IAM-30680 ...

  7. asm实现注解打印log

    前言 在Android开发中有时候调试问题要给方法加很多的log,很麻烦,所以结合asm用注解的方式来自动在方法中插入log,这样方便开发时候调试.当然通过asm插入的log应该需要包含方法的参数,方 ...

  8. log()函数(C++)

    文章目录 1.介绍 2.分析 3.使用 1.介绍  A. log()函数原型:  B. log10()函数原型:  C. 补充 exp()函数:求x的以e为底的指数函数,即e的x次方的大小  c++库 ...

  9. Keil串口打印log显示乱码

    Keil串口打印log显示乱码原因分析及解决方案 背景 出错原因及解决方案 1. 波特率不正确 2. 编码格式不正确 3. 外部晶振不一致 小结 背景 使用GD32F450IIH6作为MCU时,外部晶 ...

最新文章

  1. java jar 打包命令行_Java程序命令行打包Jar
  2. 如何配置一套优雅的Lua开发环境
  3. OpenResty请求参数处理
  4. python非贪婪匹配_Python中关于正则表达式非贪婪以及多行匹配功能详解
  5. 【Matplotlib】详解图像各个部分
  6. java微信内h5调起支付_java微信支付--------公众号内H5调起支付
  7. win7下安装tomcat
  8. 杀鸡儆猴!苹果撤销Facebook的iOS企业证书
  9. python中文视频教程-鱼C零基础入门 Python中文视频教程
  10. python 移动/剪切文件
  11. 万字长文讲述我是怎样保送清华的 | 寒门学子奋斗史(四)
  12. Android日期类组件学习
  13. 刚装好的mysql设置密码_第一次装好mysql后要设置密码
  14. 非对称算法之RSA的签名剖析
  15. 【Eclipse报错】Faceted Project Problem:Target runtime Apache Tomcat v8.0 is not defined.
  16. 计算机视觉项目-文档扫描OCR识别
  17. 解决 C2449在文件范围内找到 “{“(是否缺少函数头?), C2059 语法错误:“}“, C1075 “{“:未找到匹配令牌问题
  18. Python小游戏:BMI指数的计算
  19. access的否定形式_高中英语:否定形式表示肯定意义的句型总结
  20. 彭兰 新媒体进阶研究

热门文章

  1. 无痛减肥黑科技:拍照识热量
  2. 安徽电子信息计算机系教师,安徽电子信息职业技术学院网站网址
  3. 创客贴、即时设计、摹客RP的区别
  4. Java多个分隔符indexof,java split用多个标点符号拆分,并保留分隔符
  5. 实例讲解统计学基础知识(4):参数估计
  6. 华为鸿蒙北向应用开发DAY9——来自软通教育项目实训
  7. 2018中国公有云厂商排名第二:阿里云 213.4亿元
  8. 广州有免费学计算机网络的技校,读技校免学费广州免费的技校有哪些呢?
  9. CorelDRAW 9发生不可预期的错误解决方法
  10. 计算机病毒的常用方法,几种检测计算机病毒方法