W5500在实际项目应用时遇到Client可能会异常中断和板卡的连接。软件程序控制断开连接,实际上由于种种原因未断开,使得板卡进入某种临界状态,且无法恢复。根本原因是驱动库的接收函数为阻塞型,在没有报文接收时会阻塞在该函数内部,当外部Client进行某种异常断开后,Socket的状态得不到及时更新,认为当前依然在established状态,依旧阻塞。而Client恢复后无法再次连接该端口,造成死锁。
解决办法是在程序内增加keepalive帧,异常阻塞超过一定时间后让w5500自动关闭该socket,跳出该阻塞W5500,使能KeepAlive功能分两种方式:自动发送和手动发送
使用这种方式前都需要设置一个timeout的时间参数,setRCR()和setRTR()
直接调用ctlnetwork(CN_SET_TIMEOUT, (void *)&gWIZNetTimeout);这个函数,其中第二个参数为配置值,用户需指定。
位置:wizchip.c文件中 void network_init(void) line243 wiz_nettimeout.retry_cnt = 5; //1->5 wiz_nettimeout.time_100us = 30000; //200-> 20000 3s ctlnetwork(CN_SET_TIMEOUT, (void*)&wiz_nettimeout); -> wizchip_settimeout((wiz_NetTimeout*)arg); -> void wizchip_settimeout(wiz_NetTimeout* nettime) { setRCR(nettime->retry_cnt); setRTR(nettime->time_100us); }初始化时对应的Socket 用setSn_KPALVTR(sn, 0x01); // 配置命令,可以放到系统初始化中
此处W5500芯片有自动处理机制,若在设定时间内有数据收发,则默认不发送keepalive帧。若设置的超时时间为5s,重试次数为2次,只要在connect成功后我们保持10S以上不发数据就可以通过wireshark检测到keepalive帧
手动模式需要设置两处
setSn_KPALVTR(sn, 0x00); // 在初始化代码中放置,第二个参数必须为0IINCHIP_WRITE(Sn_CR(sn),Sn_CR_SEND_KEEP); // 在主循环或定时任务中这个是手动发送的,只要执行第二条指令就会发送出 keepalive帧,不管这个周期内有无数据
