W5500 KeepAlive功能调试经验
1. 问题W5500在实际项目应用时遇到Client可能会异常中断和板卡的连接。软件程序控制断开连接,实际上由于种种原因未断开,使得板卡进入某种临界状态,且无法恢复。根本原因是驱动库的接收函数为阻塞型,在没有报文接收时会阻塞在该函数内部,当外部Client进行某种异常断开后,Socket的状态得不到及时更新,认为当前依然在established状态,依旧阻塞。而Client恢复后无法再次连接该端口
1. 问题
W5500在实际项目应用时遇到Client可能会异常中断和板卡的连接。软件程序控制断开连接,实际上由于种种原因未断开,使得板卡进入某种临界状态,且无法恢复。根本原因是驱动库的接收函数为阻塞型,在没有报文接收时会阻塞在该函数内部,当外部Client进行某种异常断开后,Socket的状态得不到及时更新,认为当前依然在established状态,依旧阻塞。而Client恢复后无法再次连接该端口,造成死锁。
2. 解决
解决办法是在程序内增加keepalive帧,异常阻塞超过一定时间后让w5500自动关闭该socket,跳出该阻塞W5500,使能KeepAlive功能分两种方式:自动发送和手动发送
2.1 准备
使用这种方式前都需要设置一个timeout的时间参数,setRCR()和setRTR()
寄存器方式设置
- setRTR()为设置超时时间,单位为5s,一般默认即可
- setRCR()为设置超时次数,在检测到网络上无消息传送时发送keepalive报文,若无响应超过该次数则关闭socket,进而更新socket的状态
函数接口方式设置
直接调用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);
}
2.2 自动模式
初始化时对应的Socket 用setSn_KPALVTR(sn, 0x01); // 配置命令,可以放到系统初始化中
此处W5500芯片有自动处理机制,若在设定时间内有数据收发,则默认不发送keepalive帧。若设置的超时时间为5s,重试次数为2次,只要在connect成功后我们保持10S以上不发数据就可以通过wireshark检测到keepalive帧
2.2 手动模式
手动模式需要设置两处
- setSn_KPALVTR(sn, 0x00); // 在初始化代码中放置,第二个参数必须为0
- IINCHIP_WRITE(Sn_CR(sn),Sn_CR_SEND_KEEP); // 在主循环或定时任务中
这个是手动发送的,只要执行第二条指令就会发送出 keepalive帧,不管这个周期内有无数据
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)