嵌入式技术论坛
直播中

熊本熊

8年用户 1399经验值
擅长:处理器/DSP
私信 关注
[问答]

W5500有时无法联网是何原因

现在的代码里面使用了EC20和w5500两种网卡驱动。
开机之后判断哪一个可以上网,就用哪一个.
但是现在出现拔掉ec20只使用w5500,W5500的状态一直是INTERNET_DOWN(虽然一直在探测ec20)。

msh />ifconfig
msh />mqtt_offline[127]
network interface device: W5500 (Default)
MTU: 1472
MAC: 00 e3 81 94 8d 89
FLAGS: UP LINK_UP INTERNET_DOWN DHCP_ENABLE
ip address: 172.16.9.166
gw address: 172.16.9.1
net mask : 255.255.255.0
dns server #0: 172.16.13.9
dns server #1: 0.0.0.0
network interface device: e0
MTU: 1500
IMEI: 000000000000000
FLAGS: UP LINK_DOWN INTERNET_DOWN DHCP_DISABLE
ip address: 0.0.0.0
gw address: 0.0.0.0
net mask : 0.0.0.0
dns server #0: 0.0.0.0
dns server #1: 0.0.0.0
ping baidu.com
msh />mqtt_offline[128]
ping: unknown host baidu.com
32 bytes from 220.181.38.148 icmp_seq=1 ttl=128 time=4 ms
mqtt_offline[129]
ping: unknown host baidu.com
32 bytes from 220.181.38.148 icmp_seq=3 ttl=128 time=4 ms
msh />mqtt_offline[130]

回帖(2)

刘秀英

2022-9-15 14:15:38
internet down 状态,是在网络状态的标志位;该位的显示,是由 check_netdev_internet_up_work 处理的;通常哪个 netdev 设备连接状态发生变化就会去检测该 netdev 的状态。可能是这中间哪一步出现问题,导致 w5500 的网络状态标识错误了;
如果你一定要用 internet up 状态去选择网卡,sal_check_netdev_internet_up 一定要维护这个函数的添加工作队列的功能。不然,这个网络状态在错误状态时,并不会频繁更新<不准确>。
你的 RT-Thread 版本是多少,master 版本下应该不会有这个问题。
举报

最强海贼王

2022-9-15 14:16:04
这看起来是link.rt-thread.org服务器不稳定导致的。一旦中间出现socket异常,整个网卡就一直处于INTERNET_DOWN状态。而且,开机出现的概率很大。

/* check SAL network interface device internet status */
static void check_netdev_internet_up_work(struct rt_work *work, void *work_data)
{
#define SAL_INTERNET_VERSION   0x00
#define SAL_INTERNET_BUFF_LEN  12
#define SAL_INTERNET_TIMEOUT   (2)
#define SAL_INTERNET_HOST      "link.rt-thread.org"
#define SAL_INTERNET_PORT      8101
#define SAL_INTERNET_MONTH_LEN 4
#define SAL_INTERNET_DATE_LEN  16
    int index, sockfd = -1, result = 0;
    struct sockaddr_in server_addr;
    struct hostent *host;
    struct timeval timeout;
    struct netdev *netdev = (struct netdev *)work_data;
    socklen_t addr_len = sizeof(struct sockaddr_in);
    char send_data[SAL_INTERNET_BUFF_LEN], recv_data = 0;
    struct rt_delayed_work *delay_work = (struct rt_delayed_work *)work;
    const char month[][SAL_INTERNET_MONTH_LEN] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
    char date[SAL_INTERNET_DATE_LEN];
    int moth_num = 0;
    struct sal_proto_family *pf = (struct sal_proto_family *) netdev->sal_user_data;
    const struct sal_socket_ops *skt_ops;
    if (work)
    {
        rt_free(delay_work);
    }
    /* get network interface socket operations */
    if (pf == RT_NULL || pf->skt_ops == RT_NULL)
    {
        result = -RT_ERROR;
        goto __exit;
    }
    host = (struct hostent *) pf->netdb_ops->gethostbyname(SAL_INTERNET_HOST);
    if (host == RT_NULL)
    {
        result = -RT_ERROR;
        goto __exit;
    }
    skt_ops = pf->skt_ops;
    if ((sockfd = skt_ops->socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        result = -RT_ERROR;
        goto __exit;
    }
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SAL_INTERNET_PORT);
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
    timeout.tv_sec = SAL_INTERNET_TIMEOUT;
    timeout.tv_usec = 0;
    /* set receive and send timeout */
    skt_ops->setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (void *) &timeout, sizeof(timeout));
    skt_ops->setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (void *) &timeout, sizeof(timeout));
    /* get build moth value*/
    rt_memset(date, 0x00, SAL_INTERNET_DATE_LEN);
    rt_snprintf(date, SAL_INTERNET_DATE_LEN, "%s", __DATE__);
    for (index = 0; index < sizeof(month) / SAL_INTERNET_MONTH_LEN; index++)
    {
        if (rt_memcmp(date, month[index], SAL_INTERNET_MONTH_LEN - 1) == 0)
        {
            moth_num = index + 1;
            break;
        }
    }
    /* not find build month */
    if (moth_num == 0 || moth_num > sizeof(month) / SAL_INTERNET_MONTH_LEN)
    {
        result = -RT_ERROR;
        goto __exit;
    }
    rt_memset(send_data, 0x00, SAL_INTERNET_BUFF_LEN);
    send_data[0] = SAL_INTERNET_VERSION;
    for (index = 0; index < netdev->hwaddr_len; index++)
    {
        send_data[index + 1] = netdev->hwaddr[index] + moth_num;
    }
    send_data[9] = RT_VERSION;
    send_data[10] = RT_SUBVERSION;
    send_data[11] = RT_REVISION;
    skt_ops->sendto(sockfd, send_data, SAL_INTERNET_BUFF_LEN, 0,
                    (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
    result = skt_ops->recvfrom(sockfd, &recv_data, sizeof(recv_data), 0, (struct sockaddr *)&server_addr, &addr_len);
    if (result < 0)
    {
        goto __exit;
    }
    if (recv_data == RT_FALSE)
    {
        result = -RT_ERROR;
        goto __exit;
    }
__exit:
    if (result > 0)
    {
        LOG_D("Set network interface device(%s) internet status up.", netdev->name);
        netdev->flags |= NETDEV_FLAG_INTERNET_UP;
    }
    else
    {
        LOG_D("Set network interface device(%s) internet status down.", netdev->name);
        netdev->flags &= ~NETDEV_FLAG_INTERNET_UP;
    }
    if (sockfd >= 0)
    {
        skt_ops->closesocket(sockfd);
    }
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分