当前位置: 首页 > news >正文

【LwIP源码学习2】调试输出相关宏

前言

本文对lwip中debug.h文件里的调试相关宏进行分析。

正文

debug.h中有3个重要的调试相关宏:
LWIP_ASSERT(message, assertion)
LWIP_ERROR(message, expression, handler)
LWIP_DEBUGF(debug, message)

断言

LWIP_ASSERT(message, assertion)
源代码为:

#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \LWIP_PLATFORM_ASSERT(message); }} while(0)

message为断言触发时输出的字符串,assertion为一个布尔值,展开后:

if (!(assertion))
{printf("Assertion \"%s\" failed at line %d in %s\n", message, __LINE__, __FILE__); fflush(NULL);  //更新文件系统abort();	   //程序中止运行
}

当判断条件不为真时,打印断言原因,输出断言所在文件名和文件中行数,更新文件系统 ,中止程序运行。
例子:

err_t
ethernetif_init(struct netif *netif)
{struct ethernetif *ethernetif;LWIP_ASSERT("netif != NULL", (netif != NULL));。。。。。。/* initialize the hardware */low_level_init(netif);return ERR_OK;
}

网卡初始化部分代码,当传入指针为空时,触发断言。

错误处理

LWIP_ERROR(message, expression, handler)
源码为:

#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \LWIP_PLATFORM_ERROR(message); handler;}} while(0)

message为一段错误发生时输出的字符串,expression为错误判断条件,handler为一段代码,展开如下:

if (!(expression)
{printf(message);handler;
}

当判断条件不为真后,输出错误原因,执行错误处理代码handler
例子:

err_t
netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
{API_MSG_VAR_DECLARE(msg);err_t err;LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);。。。。。。return err;
}

传入指针为空,打印错误原因,返回ERR_ARG错误码。

调试打印

LWIP_DEBUGF(debug, message)
源码为:

#define LWIP_DEBUGF(debug, message) do { \if ( \((debug) & LWIP_DBG_ON) && \((debug) & LWIP_DBG_TYPES_ON) && \((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \LWIP_PLATFORM_DIAG(message); \if ((debug) & LWIP_DBG_HALT) { \while(1); \} \} \} while(0)

debug包含了多个用于控制调试行为的位标志。message是要调试打印的字符串。
展开后:

if (((debug) & LWIP_DBG_ON) && ((debug) & LWIP_DBG_TYPES_ON)) && ((signed short)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL))
{printf(message);if ((debug) & LWIP_DBG_HALT){	while(1);}
}

其中:

#define LWIP_DBG_TYPES_ON               LWIP_DBG_ON
/** flag for LWIP_DEBUGF to enable that debug message */
#define LWIP_DBG_ON            0x80U
/** flag for LWIP_DEBUGF to disable that debug message */
#define LWIP_DBG_OFF           0x00U

可见LWIP_DBG_TYPES_ONLWIP_DBG_ON是一样的,都是0x80U
debug的第15位置1时,开启调试打印。

#define LWIP_DBG_MASK_LEVEL    0x03

表示debug的低两位是调式等级。

#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_ALL
/** Debug level: ALL messages*/
#define LWIP_DBG_LEVEL_ALL     0x00
/** Debug level: Warnings. bad checksums, dropped packets, ... */
#define LWIP_DBG_LEVEL_WARNING 0x01
/** Debug level: Serious. memory allocation failures, ... */
#define LWIP_DBG_LEVEL_SERIOUS 0x02
/** Debug level: Severe */
#define LWIP_DBG_LEVEL_SEVERE  0x03

表示有4个调试等级。
debug低两位表示的调式等级高于LWIP_DBG_MIN_LEVEL时,开启调试打印。

#define LWIP_DBG_HALT          0x08U

表示当debug的第3为置1时,打印调试信息后,进入while循环中止程序运行。

在opt.h文件中包含了lwip所有的调试标志,如下:

#define ETHARP_DEBUG                    LWIP_DBG_OFF
#define NETIF_DEBUG                     LWIP_DBG_OFF
#define PBUF_DEBUG                      LWIP_DBG_OFF
#define API_LIB_DEBUG                   LWIP_DBG_OFF
#define API_MSG_DEBUG                   LWIP_DBG_OFF
#define SOCKETS_DEBUG                   LWIP_DBG_OFF
。。。。。。

表示这些调试打印都关闭了,如果把LWIP_DBG_OFF换成LWIP_DBG_ON则开启对应的调试打印。

例子:

err_t
ethernetif_init(struct netif *netif)
{struct ethernetif *ethernetif;ethernetif = mem_malloc(sizeof(struct ethernetif));if (ethernetif == NULL){LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));return ERR_MEM;}。。。。。。return ERR_OK;
}

opt.h文件中NETIF_DEBUG宏定义为LWIP_DBG_ON时,则运行到这里时打印后面的字符串。

http://www.lryc.cn/news/459363.html

相关文章:

  • Python 列表专题:删除元素
  • Spring Boot 快速入门与核心原理详解
  • UniApp 与微信小程序详细对比
  • 【用大模型提示工程处理NLP任务】
  • 适配器模式、代理模式(C++)
  • unity 2d 近战攻击判定的三种方式以及精确获取碰撞点
  • 矩形函数的傅里叶变换——从一维到二维,从连续到离散
  • 潜水打捞系统助力,破解汽车打捞难题
  • 【深度学习】经典的深度学习模型-01 开山之作:CNN卷积神经网络LeNet-5
  • LeetCode 每日一题 2024/10/7-2024/10/13
  • ZYNQ使用XGPIO驱动外设模块(前半部分)
  • 【FastAdmin】全栈视角下的页面跳转实现:从原生html、javascrpt、php技术到jQuery、FastAdmin框架
  • 从零开始搭建一个node.js后端服务项目
  • 自定义注解和组件扫描在Spring Boot中动态注册Bean(一)
  • 如何在 IDEA 中导入 Java 项目的 Git 仓库并启动
  • BIO与NIO学习
  • 麒麟操作系统:解决umount命令卸载USB存储设备时报“device is busy”错误
  • Git客户端使用之TortoiseGit和Git
  • regionprops函数详解及应用
  • FPAG学习(5)-三种方法实现LED流水灯
  • 科迅网络阅卷系统存在存储型XSS漏洞
  • 【AAOS】Android Automotive 11模拟器源码下载及编译
  • 鹏哥C语言74---第12次作业:OJ题练习
  • Light灯光组件+组件的相关操作+游戏资源的加载
  • 离岗睡岗预警系统 值班室离岗识别系统Python 结合 OpenCV 库
  • 在Centos中安装、配置与使用atop监控工具
  • 前端框架对比与选择:详尽分析
  • FLINK SQL时区问题
  • LibreOffice SDK是LibreOffice软件的开发工具包
  • 第十五届蓝桥杯C/C++学B组(解)