socket.c sendto() ignores SOCK_IO_NONBLOCK flag?

I’m using the io6library for the W6100 is all working well so far except for the sendto() function in socket.c seems to block even though I have set SOCK_IO_NONBLOCK.

I’m running DHCPv4_run(), which works and gets an IP address, but it blocks in the function check_DHCPv4_leasedIP() when calling sendto().

I’ve tracked it down to this section near the end of sendto():

    while( 1 )
        tmp = getSn_IR( sn );
        if( tmp & Sn_IR_SENDOK )
            setSn_IRCLR( sn, Sn_IR_SENDOK );
        else if( tmp & Sn_IR_TIMEOUT )
            setSn_IRCLR( sn, Sn_IR_TIMEOUT );
            return SOCKERR_TIMEOUT;

It waits in this loop until the timeout occurs (about 1.5 seconds) and then returns SOCKERR_TIMEOUT. I have configured the socket using SOCK_IO_NONBLOCK, so why does it block?
I changed


Any help would be appreciated!


The code is correct from WIZnet chip workflow sequence, but you raised interesting issue. Under normal circumstances data sending is performed very quickly, here we have the issue with sending timing out. Can you please check what arguments you supply to send()? Because if send command does not complete using interrupts usually means misconfiguration (something wrong in registers, specific interrupts are disabled in Sn_IMR) or hardware issue.

Thanks for the quick response!
The sendto() call is from check_DHCPv4_leasedIP() in dhcpv4.c:

// IP conflict detection : ARP request - ARP reply
// Broadcasting ARP Request for check the IP conflict using UDP sendto() function
ret = sendto(DHCPV4_SOCKET, (uint8_t *)CHECK_IP_CONFLICT, 17, DHCPv4_allocated_ip, 5000, 4);

I’m guessing from the comments that it’s sending a packet to the DHCP server supplied IP address to check for an IP conflict. So in this case there should be no reply - hence the timeout? I can see how this is normal and required/expected behaviour.

I have a TCP client connection running too (partly copied from loopback_tcpc() in loopback.c), but I see that this uses send() rather than sendto(). This works fine it seems, but then my server application to receive the connection will always be available.

I’m not sure what you mean about interrupts. Should I be using hardware interrupts to a pin on my micro? And therefore I need some ISR to run and do something when the WizNet chip asserts its interrupt output pin?

I’m in the process of trying to split the sendto() function into two, so that I can call a first function to send the data, then repeatedly call a second function which will check the status of the send. Eventually this would return either the SOCKERR_TIMEOUT, or the length of data sent. Crucially though, it would not block, so I’ll probably return BUSY until either SENDOK or TIMEOUT occurs. I’ll see how far I get with this!

No. In the code you provided the chip (and software) is doing sending only. It is SEND command which is not being performed properly, there’s no receive involved.

The code you cited checks for two bits - Sn_IR_SENDOK and Sn_IR_TIMEOUT, and blocks until each of them gets set. Normally SENDOK is the first, informing software that data was sent. In your case it is TIMEOUT, and it means either sending is experiences the problems or Sn_IMR register for this socket has bit SENDOK reset (and therefore SENDOK interrupt does not happen, while SEND command is completed properly). Further research is needed on what value Sn_IMR (as well as IMR in common register block) are having when problem occurs.

No, no need for hardware changes, a least for this problem. No MCU IST needed, you have code which, for some reason, does not work as expected, and we must sort it out.

Normally the code you provided does NOT block, sending is performer relatively quickly. In your case something prohibits sending.