LWIP的调试方式

LWIP提供了观察和调试协议栈内部的方法。LWIP关于调试的内容在debug.h和stats.h文件中可见。

9.1 调试接口重定向

为了实现重定向 printf()函数,我们需要重写 fputc() 这个 c 标准库函数,因为 printf()在 c 标准库函数中实质是一个宏,最终是调用了 fputc()这个函数的。重定向的这部分工作,由 usart.c 文件中的 fputc(int ch, FILE *f) 这个函数来完成。

9.2 ERROR

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

实际就是

LWIP_ERROR(message, expression, handler) 
{
if (!(expression)) 
{ 
        LWIP_PLATFORM_ASSERT(message); 
handler;
}
}

而LWIP_PLATFORM_ASSERT(message)在cc.h中定义

#define LWIP_PLATFORM_ASSERT(x) \
    do \
    {   printf("Assertion \"%s\" failed at line %d in %s\n",\ x, __LINE__, __FILE__); \
    } while(0)
#endif

当expression不成立,则输出出错位置的行号与文件。同时调用处理函数函数。在lwip中
handler一般为 return sth;

9.3 DEBUG

#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)
//---LWIP_DEBUGF(debug, message)为debug.h中实现的宏定义。
//---实际就是
LWIP_DEBUGF(debug, message)
{
    if (((debug) & LWIP_DBG_ON)  &&  ((debug) & LWIP_DBG_TYPES_ON)  &&  
  ((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) 
  { 
          LWIP_PLATFORM_DIAG(message); 
          if ((debug) & LWIP_DBG_HALT) 
  { 
             while(1);
         }
     } 
}

1)调试系统有三个开关
LWIP_DBG_ON 调试总开关
LWIP_DBG_TYPES_ON 调试类型开关
LWIP_DBG_MASK_LEVEL 调试水平
* - 0 all
* - 1 warning
* - 2 serious
* - 3 severe
2)LWIP_PLATFORM_DIAG(message)函数在cc.h定义

#define LWIP_PLATFORM_DIAG(x)  do {printf x;} while(0)

9.4 ASSERT

#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \
  LWIP_PLATFORM_ASSERT(message); } while(0)
  LWIP_PLATFORM_ASSERT(message)在cc.h文件由用户定义
#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \
  LWIP_PLATFORM_ASSERT(message); } while(0)

9.5 lwip提供的stat统计信息

在stat.c文件中定义了如下统计信息

struct stats_ {
#if LINK_STATS
  struct stats_proto link;
#endif
#if ETHARP_STATS
  struct stats_proto etharp;
#endif
#if IPFRAG_STATS
  struct stats_proto ip_frag;
#endif
#if IP_STATS
  struct stats_proto ip;
#endif
#if ICMP_STATS
  struct stats_proto icmp;
#endif
#if IGMP_STATS
  struct stats_igmp igmp;
#endif
#if UDP_STATS
  struct stats_proto udp;
#endif
#if TCP_STATS
  struct stats_proto tcp;
#endif
#if MEM_STATS
  struct stats_mem mem;
#endif
#if MEMP_STATS
  struct stats_mem memp[MEMP_MAX];
#endif
#if SYS_STATS
  struct stats_sys sys;
#endif
};

上述统计信息,除stats_sys,其余在相应宏开关打开后,统计信息由协议栈自动完成,而对于stats_sys统计信息的实现,可在sys_arch关于信号量和有限的申请释放函数中实现。
1、在stats.h 添加如下代码,/—add sun—/便是添加的代码

#if SYS_STATS
#define SYS_STATS_INC(x) STATS_INC(sys.x)
#define SYS_STATS_DEC(x) STATS_DEC(sys.x)
#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys)
/*---add sun---*/
#define SYS_STATS_SEM_AVAIL(t,x)            (lwip_stats.sys.sem.t=x)
#define SYS_STATS_MBOX_AVAIL(t,x)           (lwip_stats.sys.mbox.t=x)
#define SYS_STATS_INC_USED(t) do { ++lwip_stats.sys.t.used; \
                                    if (lwip_stats.sys.t.max < lwip_stats.sys.t.used) { \
                                        lwip_stats.sys.t.max = lwip_stats.sys.t.used; \
                                    } \
                                 } while(0)
/*---add sun---*/
#else
#define SYS_STATS_INC(x)
#define SYS_STATS_DEC(x)
#define SYS_STATS_DISPLAY()
/*---add sun---*/
#define SYS_STATS_INC_USED(t,x)
#define SYS_STATS_SEM_AVAIL(t,x)            
#define SYS_STATS_MBOX_AVAIL(t,x)   
/*---add sun---*/       
#endif

struct stats_syselem {      //---添加变量avail表示协议栈总共多少个信号量
  /*---add sun---*/
  STAT_COUNTER avail;
  /*---add sun---*/
  STAT_COUNTER used;
  STAT_COUNTER max;
  STAT_COUNTER err;
};

struct stats_syselem {      //---添加变量avail表示协议栈总共多少个邮箱
  /*---add sun---*/
  STAT_COUNTER avail;
  /*---add sun---*/
  STAT_COUNTER used;
  STAT_COUNTER max;
  STAT_COUNTER err;
};

2、在stats.c中stats_display_sys()添加如下代码,显示协议栈总共的邮箱和信号量个数。

LWIP_PLATFORM_DIAG(("sem.avail: %"U32_F"\n\t", (u32_t)sys->sem.avail)); 
LWIP_PLATFORM_DIAG(("mbox.avail: %"U32_F"\n\t", (u32_t)sys->mbox.avail));

3、在sys_arch.c
3.1 sys_init函数添加关于信号量和邮箱统计信息的初始化

SYS_STATS_MBOX_AVAIL(avail,OS_MAX_QS);
    SYS_STATS_MBOX_AVAIL(used,0);
    SYS_STATS_MBOX_AVAIL(max,0);
    SYS_STATS_MBOX_AVAIL(err,0);

    SYS_STATS_SEM_AVAIL(avail,OS_MAX_EVENTS-OS_MAX_FLAGS);
    SYS_STATS_SEM_AVAIL(used,0);
    SYS_STATS_SEM_AVAIL(max,0);
    SYS_STATS_SEM_AVAIL(err,0);

3.2 mbox分配与释放
在邮箱分配成功后添加:
SYS_STATS_INC_USED(mbox);
在邮箱释放成功后:
SYS_STATS_DEC(mbox.used);
3.3 sem分配与释放

在信号量分配成功后添加:
SYS_STATS_INC_USED(sem);
在信号量释放成功后:
SYS_STATS_DEC(sem.used);

4、在lwipopts.h打开相应宏开关,并在任务中调用相关stats_display()函数就可在串口调试中看到LWIP的统计信息了。
LWIP的调试方式_第1张图片

5、在LWIP的1.4版本中提供了shell.c代码
代码运行界面如图所示
LWIP的调试方式_第2张图片
其中的stat的命令也同样可查询lwip状态。
shell里面的功能暂时还不怎么会用!

你可能感兴趣的:(LWIP)