1.平常我们都是用串口的方式通过rt-thread的finish来调试,但是在遇到串口不够用或者板子没有焊串口。我们就需要通过网络+finish的方式来调试板子。但是在调试板子的时候发现通过通过TCP连接方式调用list_if()的时候,网络出现挂掉。现像是ping不通。
2.原因分析:后面查看list_if()的代码发现有这么一个代码:
void list_if(void)
{
rt_ubase_t index;
struct netif * netif;
//rt_enter_critical();//进入临界断,调用锁
netif = netif_list;
while( netif != RT_NULL )
{
rt_kprintf("network interface: %c%c%s\n",
netif->name[0],
netif->name[1],
(netif == netif_default)?" (Default)":"");
rt_kprintf("MTU: %d\n", netif->mtu);
rt_kprintf("MAC: ");
for (index = 0; index < netif->hwaddr_len; index ++)
rt_kprintf("%02x ", netif->hwaddr[index]);
rt_kprintf("\nFLAGS:");
if (netif->flags & NETIF_FLAG_UP) rt_kprintf(" UP");
else rt_kprintf(" DOWN");
if (netif->flags & NETIF_FLAG_LINK_UP) rt_kprintf(" LINK_UP");
else rt_kprintf(" LINK_DOWN");
if (netif->flags & NETIF_FLAG_DHCP) rt_kprintf(" DHCP");
if (netif->flags & NETIF_FLAG_POINTTOPOINT) rt_kprintf(" PPP");
if (netif->flags & NETIF_FLAG_ETHARP) rt_kprintf(" ETHARP");
if (netif->flags & NETIF_FLAG_IGMP) rt_kprintf(" IGMP");
rt_kprintf("\n");
rt_kprintf("ip address: %s\n", ipaddr_ntoa(&(netif->ip_addr)));
rt_kprintf("gw address: %s\n", ipaddr_ntoa(&(netif->gw)));
rt_kprintf("net mask : %s\n", ipaddr_ntoa(&(netif->netmask)));
rt_kprintf("\r\n");
netif = netif->next;
}
#if LWIP_DNS
{
struct ip_addr ip_addr;
for(index=0; index<DNS_MAX_SERVERS; index++)
{
ip_addr = dns_getserver(index);
rt_kprintf("dns server #%d: %s\n", index, ipaddr_ntoa(&(ip_addr)));
}
}
#endif /**< #if LWIP_DNS */
//rt_exit_critical();//出临界段,解锁
}
从上面的代码,我们看到了有两处屏蔽的地方是进入临界段和出临界段被屏蔽了,如果打开这两处。当我们通过TCP连接的方式通过finish调用list_if()函数的时候,一进list_if()函数,则马上调用锁,这时候调度被锁住了。但是我们TCP是发送的需要接收的,这时候可能导致没有正确的跑到解锁的位置,没有成功解锁,从而导致被锁住,线程没有办法正常调度。这样就导致网络死掉。解决办法,把list_if()函数的锁与解锁两处屏蔽掉,就可以正常使用了。【
[RealTouch例程]TCP/IP网络组件Lwip之telnet远程命令行交互】在没有关闭代码上面两处,也可以正常的list_if(),不会出现网络死掉的情况。
但是上面这个方法会导致另外一个问题发生,就是没有这个锁”rt_enter_critical();“可能会导致netif这个链表可能在这个过程中加入新的,或者某个netif被删除了。
这个BUG已经提交到rt-thread上面,最终解决方案以他们为准,希望大家可以关注下rt-thread的更新。 |