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裏面的功能暫時還不怎麼會用!