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的統計信息了。
這裏寫圖片描述

5、在LWIP的1.4版本中提供了shell.c代碼
代碼運行界面如圖所示
這裏寫圖片描述
其中的stat的命令也同樣可查詢lwip狀態。
shell裏面的功能暫時還不怎麼會用!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章