Code Monkey home page Code Monkey logo

wiznet's Introduction

WIZnet

中文页 | English

1. Introduction

The WIZnet software package is a porting implementation of RT-Thread based on the WIZnet official website ioLibrary_Driver code base, and currently only supports W5500 devices. On the basis of the original code library function, this software package docks with the RT-Thread SAL socket abstraction layer, realizes the support for standard BSD Socket APIs, is perfectly compatible with a variety of software packages and network functions, and improves the compatibility of WIZnet devices.

1.1 Directory structure

The WIZnet software package directory structure is as follows:

wiznet
├───inc           // RT_Thread transplant header file
├───iolibrary     // WIZnet official library file
│ └───Ethernet    // WIZnet official Socket APIs and WIZCHIP driver
│ │ └───W5500     // WIZCHIP driver
│ │ wizchip_conf.c // Socket configuration file
│ │ wizchip_socket.c // Socket APIs file
│ └───Internet // WIZnet official network function realization
│ │ └───DHCP // DHCP function implementation
│ └───────DNS // DNS function realization
├───src // RT_Thread transplant source code file
│ └───wiz_af_inet.c // WIZnet BSD Socket registered to SAL
│ │ wiz_device.c // WIZnet device initialization
│ │ wiz_ping.c // WIZnet device Ping command realization
│ │ wiz_socket.c // WIZnet BSD Socket APIs implementation
│ └───wiz.c // WIZnet initialization (device initialization, network initialization)
│ LICENSE // package license
│ README.md // Software package instructions
└───SConscript // RT-Thread default build script

1.2 License

The WIZnet software package complies with the Apache-2.0 license, see the LICENSE file for details.

1.3 Dependency

  • RT-Thread 4.0.1+
  • SAL component
  • netdev component
  • SPI driver: WIZnet devices use SPI for data communication, which requires the support of the system SPI driver framework;
  • PIN driver: used to handle device reset and interrupt pins;

2. Get the software package

To use the WIZnet software package, you need to select it in the RT-Thread package management. The specific path is as follows:

WIZnet: WIZnet TCP/IP chips SAL framework implement
        WIZnet device type (W5500) --->
        WIZnet device configure --->
            (spi30) SPI device name
            (10) Reset PIN number
            (11) IRQ PIN number
  [] Enable alloc IP address through DHCP
            WIZnet network configure --->
                (192.168.1.10) IPv4: IP address
                (192.168.1.1) IPv4: Gateway address
                (255.255.255.0) IPv4: Mask address
  [] Enable Ping utility
  [] Enable debug log output
        Version (latest) --->

WIZnet device type: Configure the supported device type (currently only supports W5500 devices)

WIZnet device configure: configure the parameters of the device used

  • SPI device name: Configure the name of the device using SPI (note that it needs to be set to non-SPI bus device)

  • Reset PIN number: Configure the reset pin number connected to the device (modified according to the actual pin number used)

  • IRQ PIN number: Configure the interrupt pin number of the device connection (same as above)

Enable alloc IP address through DHCP: Configure whether to use DHCP to allocate IP addresses (enabled by default)

WIZnet network configure: If you do not enable the DHCP function, you need to configure the statically connected IP address, gateway and subnet mask

Enable Ping utility: Configure to enable Ping command (enabled by default)

Enable debug log output: Configure to enable debug log display

Version: software package version selection

3. Use the software package

The initialization function of WIZnet software package is as follows:

int wiz_init(void);

This function supports component initialization. If the automatic component initialization function is enabled, the application layer does not need to call this function. The main functions of the function are:

  • Set the default MAC address;
  • Device configuration and initialization (configure SPI device, configure reset and interrupt pins);
  • Network configuration and initialization (DHCP allocation of IP address, configuration of socket parameters);
  • Register the implemented BSD Socket APIs to the SAL socket abstraction layer to complete WIZnet device adaptation;

Each WIZnet device needs a unique MAC address. The user can call the following function in the application layer program to set the MAC address of the WIZnet device. If this function is not called, the device will use the default MAC address. The default MAC address is 00-E0-81 -DC-53-1A (Note: If there are devices with the same MAC address in the same LAN, it may cause the device network to be abnormal).

int wiz_set_mac(const char *mac);

After the device is powered on and initialized, the device's MAC address is successfully set, and then you can enter the command wiz_ifconfig in FinSH to view the device's IP address, MAC address and other network information, as shown below:

msh />ifconfig
network interface device: W5500 (Default)    ## Device name
MTU: 1472                                    ## Network maximum transmission unit
MAC: 00 e0 81 dc 53 1a                       ## Device MAC address
FLAGS: UP LINK_UP INTERNET_UP                ## Device flag
ip address: 192.168.12.26                    ## Device IP address
gw address: 192.168.10.1                     ## Device gateway address
net mask: 255.255.0.0                        ## Device subnet mask
dns server #0: 192.168.10.1                  ## DNS server address 0
dns server #1: 0.0.0.0                       ## DNS server address 1

After obtaining the IP address successfully, if the Ping command function is enabled, you can enter the command ping + domain name address in FinSH to test the network connection status, as shown below:

msh />wiz_ping baidu.com
32 bytes from 220.181.57.216 icmp_seq=0 ttl=128 time=31 ticks
32 bytes from 220.181.57.216 icmp_seq=1 ttl=128 time=31 ticks
32 bytes from 220.181.57.216 icmp_seq=2 ttl=128 time=32 ticks
32 bytes from 220.181.57.216 icmp_seq=3 ttl=128 time=32 ticks

The normal test of the ping command indicates that the WIZnet device is successfully connected to the network, and then you can use the standard BSD Socket APIs abstracted by SAL (Socket Abstraction Layer) for network development (MQTT, HTTP, MbedTLS, NTP, Iperf, etc.), WIZnet software package The supported protocol cluster types are: the primary protocol cluster is AF_WIZ, and the secondary protocol cluster is AF_INET (for specific differences and usage, please refer to SAL Programming Guide ).

4. Common problems

  • Assertion problem during SPI device initialization

    (wiz_device->parent.type == RT_Device_Class_SPIDevice) assertion failed at function:wiz_spi_init, line number:126

    The above assertion problem occurs. The possible reason is that the name of the SPI device used by WIZnet in ENV is incorrectly filled. Please distinguish the relationship between SPI DEVICE and SPI BUS. If there is no SPI device or only SPI bus device in the BSP project, you need to manually mount the SPI device to the SPI bus in the driver and correctly configure the SPI device name used in the WIZnet software package.

  • The latest version of WIZnet software package has been supported as a server server mode (not supported before V1.1.0).

  • WIZNet software package initialization error [E/wiz.dev] You should attach [wiznet] into SPI bus firstly. error is caused by not mounting the winzet device to the SPI bus; please refer to the wiz_init function Note to solve the problem of package initialization failure.

  • When using the previous code in the RT-Thread repository, please compare [components/net/sal_socket/src/sal_socket.c], especially about the content of PR, pay attention to the content of sal_closesocket . When you always fail to apply for socket(-1), please make sure that the RT-Thread code you are using is the same as the [PR](RT-Thread/rt-thread#3534 /files).

  • When applying for a socket, the error is 0x22. Note that the development branch of wiznet is in the master version or a version greater than V1.1.0. Please pay attention to the execution order of wiz_socket_init(), because the sal_check_netdev_internet_up networking detection function will actively apply for a socket to determine whether the w5500 has network capabilities, and network status changes will cause sal_check_netdev_internet_up was called, causing 0x22 error.

5. Matters needing attention

  • When obtaining the software package, you need to pay attention to the correct configuration of the SPI device name, reset pin number and interrupt pin number used;
  • After the initialization is complete, it is recommended to use the wiz_set_mac() function to set the device MAC address to prevent conflicts with the default MAC address;

6. Contact & Thanks

wiznet's People

Contributors

ackleys avatar aingsu avatar armink avatar balancetwk avatar guozhanxin avatar heyuanjie87 avatar hubertxie avatar k4kkk avatar lawlieta avatar mysterywolf avatar shineroyal avatar shishirong avatar warfalcon-spunky avatar wendal avatar wwl19890302 avatar xiangxistu avatar yangjie11 avatar zhkag avatar zhouchuanfu avatar zhouscd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wiznet's Issues

W5500前端没有路由器直接接网关会创建socket失败

系统都是静态IP方式:
1.1 如果接到路由器上或者路由器带的交换机上系统没有问题,wiz_socket.c中的wiz_socket函数中的socket_state = getSn_SR(sock->socket)正常为0;
1.2但如果直接接交换机上则创建socket会失败,跟踪发现socket_state =0x22,所以会-1返回,查手册ox22是socket_udp,此时按udp放行可以发送udp信息;但是tcp因0x22会一直失败。
在不接路由只接交换机的情况下:
2.1 如果按照:拔掉网线->上电->插入网线,则系统先失败后自动恢复正常;
2.2 如果按照:插入网线->上电->拔掉网线->再插入网线,则系统始终失败
万一中间断电,我总不能一根根去按1来操作吧?请问这个问题怎么解决,急急急

编译错误,EAGAIN找不到定义

编译器:keil mdk default compiler version 5
报错信息:
packages\wiznet-latest\src\wiz_socket.c(1136): error: #20: identifier "EAGAIN" is undefined
见下图:
image

引脚中断回调没有被执行

在执行ping指令后,从启动到send都正常,只有在recv的时候,因为收不到中断回调,导致获取信号量失败,超时退出。这个你们有遇到过吗,怎么解决呢

W5500+libmodbus系统不稳定,运行一段时间后断开就再也无法连接上了

1 RTT的SAL说明里面“目前 SAL 组件支持的协议栈或网络实现类型有:lwIP 协议栈、AT Socket 协议栈、WIZnet 硬件 TCP/IP 协议栈。”,但是关于怎么具体对接没有说明。
2 经过自己一些痛苦摸索,程序可以进行mdobusTCP采集,但过一段时间就出现无法再连接上。各种方法都试了还不行,和libmodbus作者也沟通了,人家说人家的系统已经跑了几个月了没任何问题。
3 那么这块究竟是什么问题?希望wiznet软件包作者看到能沟通一下,不然这个项目真要黄了,项目进入小批,发现这个大一个bug,真不知道该咋弄了,看到请联系我,谢谢18100336192或2730122869

packages/wiznet-latest/src/wiz_af_inet.c:16:25: fatal error: sal_low_lvl.h: No such file or directory

使用了最新的RT-thread 4.1.0系统,总是报错如上。请教两个问题:

1.不清楚最新的wiznet2.0.0的代码中修改的头文件部分

#ifdef RT_USING_SAL
#include <sal_netdb.h>
#include <sal_low_lvl.h>
#endif /* RT_USING_SAL */

增加的sal_low_lvl.h文件在哪里?在rt-thread studio软件中添加软件包后无法自动下载下来,且wiznet2.0.0的代码中也么有这个。

2.咱们更新记录中说的适配5.0.0,是指适配什么组件的5.0.0?

wiz_socket函数封装有问题

wiz_socket函数中,调用
if (wizchip_socket(sock->socket, sock->type, wiz_port++, Sn_MR_ND) != sock->socket)
该函数生成W5500实际可用的socket,如果作为TCP服务器,accept的时候会又分配一个W5500实际可用的socket,这两个socket就冲突了。

执行Ping命令的程序跑飞

我在配置好wiznet组件后,使用命令行测试ping命令时发现ping命令ping完一次就卡住,命令行也无响应,debug后发现报NMI_Handle
Snipaste_2021-06-10_16-11-45.png
研究下报错的地方发现是wiz_do_event_changes中的sock没有正常初始化
image.png
导致后续rt_wqueue_wakeup调用的时候程序跑飞
我在所有调用了wiz_do_event_changes添加了调试信息,输出如下:
image.png
大概可以判断,wiz_do_event_changes被调用之前socket被关闭了,sock变量也被置零,在调用wiz_do_event_changes之前的wiz_recv_notice_cb函数里,有个释放信号量的地方:
image.png
rt在执行rt_sem_release的时候会调用rt_schedule重新进行进程调度,而我的shell进程优先级比wiznet接收进程的优先级高:
image.png
这导致shell执行的ping命令会抢占,而ping命令执行后会有wiz_closesocket关闭socket,执行完后再回到wiznet的接收线程里执行wiz_do_event_changes就报错,wiz_do_event_changes没有预防socket被关闭的操作,也就容易导致程序跑飞
我参考AT_Socket的方法,在wiz_closesocket加以延时:
image.png
让wiz_do_event_changes在socket没被关闭前执行完,再执行ping命令就不报错了,算是简单解决了这个问题,但总感觉指标不治本

这个问题应该只会在shell进程优先级或者其他会执行closesocket的进程优先级大于wiz接收进程优先级的时候发生

read收数据时会导致线程一直执行

问题:
TCP通信,当使用单独的线程去收数据时,并且线程里只使用read函数,不使用select函数配合,代码如下:

 while (1)
     {
         ret = read(sock, buf, 64);
         if (ret <= 0)
         {
             break;
         }

         rt_ringbuffer_put(rx_ring_buf, buf, ret);
     }

如果此时对方只发了一次数据,那么线程会一直执行,不会阻塞,导致低优先级线程无法调度。

原因是wiz_recvfrom函数里面有这样一段代码,

        uint16_t recvsize = getSn_RX_RSR(socket);
        /* receive last transmission of remaining data */
        if (recvsize > 0)
        {
            rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
            recv_len = wizchip_recv(socket, mem, len);
            if (recv_len > 0)
            {
                rt_mutex_release(sock->recv_lock);
                goto __exit;
            }
            rt_mutex_release(sock->recv_lock);
        }

        if (socket_state == SOCK_CLOSED)
        {
            return 0;
        }
        else if (socket_state != SOCK_ESTABLISHED)
        {
            LOG_E("WIZnet receive failed, get socket(%d) register state(%d) error.", socket, socket_state);
            result = -1;
            goto __exit;
        }

        while (1)
        {
            /* wait the receive semaphore */
            if (rt_sem_take(sock->recv_notice, timeout) < 0)
            {
                result = -1;
                /* blocking mode will prints an error and non-blocking mode exits directly */
                if ((flags & MSG_DONTWAIT) == 0)
                {
                    LOG_E("WIZnet socket (%d) receive timeout (%d)!", socket, timeout);
                    errno = EAGAIN;
                }
                goto __exit;
            }
            else
            {
                if (sock->state == SOCK_ESTABLISHED)
                {
                    /* get receive buffer to receiver ring buffer */
                    rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
                    recv_len = wizchip_recv(socket, mem, len);
                    if (recv_len < 0)
                    {
                        LOG_E("WIZnet socket(%d) receive data failed(%d).", socket, recv_len);
                        rt_mutex_release(sock->recv_lock);
                        result = -1;
                        goto __exit;
                    }
                    rt_mutex_release(sock->recv_lock);
                }
                else if (sock->state == SOCK_CLOSED)
                {
                    result = 0;
                    goto __exit;
                }
                break;
            }
        }
        break;
    }

这段代码先通过getSn_RX_RSR判断是否有数据,有的话就返回,这就导致第二次read时,getSn_RX_RSR判断到无数据,就到下面的 if (rt_sem_take(sock->recv_notice, timeout) < 0)这,因为这里信号量已经在中断里面释放过了,所以这里是不会阻塞的,从而进入到wizchip_recv函数,而这个函数里面就一直在判断getSn_RX_RSR是否有数,因为对端只发了一次,第一次已经读走了,因此getSn_RX_RSR一直返回0,从而形成无阻赛的死循环。

所以wiz_recvfrom函数应该改进,通过注释(/* receive last transmission of remaining data */)可以看出,是否防止数据读不干净,而这样做的。那么为啥不在wizchip_recv执行完后,再去判断getSn_RX_RSR是否有数,如果有,再释放一次信号量即可

环境:
RT-Thread Studio 2.1.2
wiznet latest

socket创建必须要物理link up

问题:
当在创建socket时,wiz_socket函数会去调用WIZ_INIT_STATUS_CHECK来检查物理上是否link up,并且accept函数里面也是,这就导致我不插网线时,无法创建socket。这种做法不符合通用的使用方法。

环境:
RT-Thread Studio 2.1.2
wiznet latest

当发送数据超过发送缓存 应分包发送保证所有数据发送出去

if (len > freesize) len = freesize; // check size not to exceed MAX size.

建议写成循环分包发送 比如用户要发送5k数据 那么分三包发送 2K 2K 1K 这样顶层api调用才不会出问题,WEBNET顶层发送数据缓存4k 调用该wiznet 数据发送API时永远发送不成功 浏览器等待后续的数据导致卡死
freesize = getSn_TxMAX(sn);
if (len > freesize) len = freesize; // check size not to exceed MAX size. 超过了缓存大小就分包发送

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.