STM32 移植LwIP 之后,能正常联网通讯,但是发现2个问题,
1、上电初始化前,未插入网线,之后就无法获取到IP地址(DHCP)
2、正常通讯过程中,拔掉网线,然后插回去,不知道如何复位
先看一下LWIP初始化代码
/**
* LwIP initialization function
*/
int MX_LWIP_Init()
{
/* Initilialize the LwIP stack with RTOS */
tcpip_init( NULL, NULL );
/* IP addresses initialization with DHCP (IPv4) */
ipaddr.addr = 0;
netmask.addr = 0;
gw.addr = 0;
printf("netif add\r\n");
/* add the network interface (IPv4/IPv6) with RTOS */
netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
printf("check netif status\r\n");
/* Registers the default network interface */
netif_set_default(&gnetif);
if (netif_is_link_up(&gnetif))
{
printf("netif is link up\r\n");
/* When the netif is fully configured this function must be called 当netif完全配置时,必须调用此函数*/
netif_set_up(&gnetif);
}
else
{
printf("netif set down\r\n");
/* When the netif link is down this function must be called 当netif链接断开时,必须调用这个函数*/
netif_set_down(&gnetif);
}
/* Set the link callback function, this function is called on change of link status 设置链接回调函数,当链接状态改变时调用该函数*/
netif_set_link_callback(&gnetif, ethernetif_update_config);
/* create a binary semaphore used for informing ethernetif of frame reception 创建一个二进制信号量,用于通知ethernetif接收帧*/
Netif_LinkSemaphore = osSemaphoreNew(1, 1, NULL);
link_arg.netif = &gnetif;
link_arg.semaphore = Netif_LinkSemaphore;
/* Create the Ethernet link handler thread */
/* USER CODE BEGIN OS_THREAD_NEW_CMSIS_RTOS_V2 */
memset(&attributes, 0x0, sizeof(osThreadAttr_t));
attributes.name = "LinkThr";
attributes.stack_size = INTERFACE_THREAD_STACK_SIZE;
attributes.priority = osPriorityBelowNormal;
osThreadNew(ethernetif_set_link, &link_arg, &attributes);
/* USER CODE END OS_THREAD_NEW_CMSIS_RTOS_V2 */
dhcp_start(&gnetif);
/* USER CODE BEGIN 3 */
return 1;
/* USER CODE END 3 */
}
其中
netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
是添加了网卡,并调用了ethernetif_init初始化ETH
if (netif_is_link_up(&gnetif))
这个函数可以知道网线的插拔状态
netif_set_link_callback(&gnetif, ethernetif_update_config);
这个函数,设置了一个回调函数,在网线状态变化时会调用ethernetif_update_config
而ethernetif_update_config函数,最终会调用
__weak void ethernetif_notify_conn_changed(struct netif *netif)
我们在ethernetif_notify_conn_changed函数内加入以下内容,实现网线插拔的处理
__weak void ethernetif_notify_conn_changed(struct netif *netif)
{
/* NOTE : This is function could be implemented in user file
when the callback is needed,
*/
//以下自己添加的
printf("*** netif changed");
if (netif_is_link_up(netif))
{
printf("netif is link up\r\n");
/* When the netif is fully configured this function must be called 当netif完全配置时,必须调用此函数*/
netif_set_up(netif);
}
else
{
printf("netif set down\r\n");
/* When the netif link is down this function must be called 当netif链接断开时,必须调用这个函数*/
netif_set_down(netif);
}
}
上电若未插网线就执行DHCP,将无法获取到IP
dhcp_start(&gnetif);
我们要做的是,增加一个判断,将dhcp_start(&gnetif);改为:
while(1) //等待网线插上了再开始DHCP
{
if (netif_is_link_up(&gnetif))
{
dhcp_start(&gnetif);
break;
}
osDelay(1000);
printf("Wait for the cable to be plugged in...\r\n");
}
这样,网线插上后,才会执行dhcp_start(&gnetif),可以解决第一个问题。
解决第二个问题的方法是,创造2个状态的读取,让应用程序知道网线是否断开了,执行重连操作
//这个函数可以知道,目前IP是否已经获取到了
int IP_Get_Ok()
{
if(ip_addr_cmp(&(gnetif.ip_addr),&ipaddr))
{
return 0;
}
else
return 1;
}
//这个函数可以知道当前网线是否插着
int Cable_Is_Plugged_In()
{
if (netif_is_link_up(&gnetif))
{
return 1;
}
else
return 0;
}