Reset/re-initialize the external WiFi IC & UDP socket issues

@mdma, I wanted to start a quick discussion here about some UDP issues I’ve seen and ask if there’s a way to ‘reset’ the Broadcom/WICED system to a fresh state.

First, I’m encountering UDP stability issues where a socket won’t stay open for very long. Situation :

  • UDP.begin returns success
  • UDP.beginpacket, UDP.endpacket return a success
  • Next call to UDP.beginpacket/UDP.endpacket returns INVALID_SOCKET wiced error and the socket seems to close faster than the target can reply to the message that was sent out.
  • Next socket that’s opened will behave the same way.

Another way I found to break UDP is to create sockets until it refuses to create any more ( leaving socket garbage collection up to the user ).

UDP my_sock ;
my_sock.begin(5000) ; 
my_sock.begin(5001) ; // nothing closes socket on port 5000 ... it remains in existence
...
my_sock.begin(5021) ; // eventually begin will return an error because too many sockets have been opened

Ideally these issues can be resolved at the cause, but in the interim is there a way to ‘reset’ the WICED system to a fresh state. I’m hoping that can be a bandage to keep uptime to a maximum.

EDIT: oops posted prematurely

Internally, the system will close all sockets when entering listening mode, so that might provide some kind of stop-gap solution, but it doesn’t feel like a good solution, just one that works!

Is there any reason why the firmware app cannot clean up the sockets it creates?

Ideally, yes the FW closes the sockets it creates, just wanted to point out that it doesn’t take much bad code to break the current implementation.

I’m more concerned with the first issue I described as I’m not sure where to begin to try to reproduce the conditions or where to probe around with the debugger. It would be nice to have a way to do a reset of the wiced side to clear any funky states.

It might be unrelated to the network - e.g. insufficient memory, so you might want to investigate there.

If you can make a standalone app that I can run that reproduces the issue, I’d be happy to look into this.

Thanks. I’ll look into the memory.
I’ll share test code or create an issue if I can manage to reproduce it reliably.

Guys,

Sorry for my own ignorance but in this code how do I ‘close’ a socket then - using UDP ???.

My code uses a single socket to transmit to a couple of destinations, and never expects a response - so is never receiving anything.

I create a UDP object at the top of the file and then use this socket elsewhere. I never destroy this object.

Are you saying then that creating a UDP class object is what you class as ‘creating or opening’ a socket ???. So to ‘close’ the socket I have to destroy the class object ???. To me - the UDP object is more than simply a ‘socket’…and there are no open/close methods available.

Sorry but I am more used to other compilers (or code) (C# or Windows C++ - or PIC C) where creating an object and then opening/closing the socket are separate operations :open_mouth: - these don’t seem to be available on the Photon ???.

Is there an explicit ‘destroy’ I should be calling ???. Again - sorry - I historically have used C (or assembler :wink: for embedded programming, so embedded C++ is new to me since starting with the Photon.

I also suspect Memory issues but as the ‘FreeMemory’ call is simply a high (or low) watermark - it is pretty useless in this respect ??. I do however report it to the serial port and it DOES change when losing network etc. :-O.

Thanks

BR

Graham

Hi @GrahamS

To close a UDP socket, you call the stop() method on the UDP object. You don’t have to destroy the object (and it is usually a good idea not to destroy it).

It is the begin(port) call that creates the socket.

I would consider calling UDP.begin(5000) opening a socket on port 5000.
When you call that it does dynamically allocate some resources that are freed by calling UDP.stop( ), conversely I would call that closing a socket. However the system may close a socket on it’s own, I believe it occurs when the WiFi connection is lost.

I plan on digging into the memory issue myself. I’ll update if I find anything on that front.

Hi,

Thanks for the swift replies…

So I can ONLY have one UDP socket at any time (as stop() does not require a port) ???.

That’s not an issue for me at the moment, but is limiting if I need to receive on multiple sockets - isn’t it ???. OR send and receive on different sockets ???.

Thanks

Graham

Also…

So - what is the overhead of opening a socket, sending then closing in the same function ???. Does the System not need time to perform the send - or it it totally synchronous - even when using System_Threading ???.

Performance speed is not really a problem but Its better to understand what is going on ;-)).

I would normally not create a new socket for every transmission - as (on most systems) this is pretty wasteful of resource in my view.

Graham

You can have multiple sockets open, there is a limit ( I encountered about 6-8 open sockets ) before calling UDP.begin returns errors.

UDP is connectionless. So you can have just one UDP socket open sending messages to different targets, that’s totally valid.

1 Like

You can have several UDP objects (bound to different ports) and you'll be calling the stop() method of each respective object.

1 Like

Hi @GrahamS

You can have more than one UDP object and therefore more than one socket, but any single UDP object can only ever be associated with one socket. It is very normal in network communications for sockets to have a fairly long lifetime (minutes to hours); conversely it is a bit unusual and wasteful to have a socket only live for one packet.

A socket has two ports associated with it, a receive port specified in the begin(port) method and transmit port specified in the beginPacket(ip,port) method and they can differ. If IP addresses are like phone numbers, then ports are your extension number for your particular office phone. You can change transmiit IP address and port on every packet you send.

When @jakeypoo says that UDP is connectionless, that is correct but it has a very precise technical meaning. It does not mean (as new folks sometimes think) that you can try to send UDP packets to hosts that don’t exist. UDP (if you don’t use broadcast or multicast) is still a point-to-point protocol from one IP address to another IP address. If you want something other than that, investigate broadcast and multicast UDP. As I said above, you can change which IP address and port you are sending to for each packet that you send.

I would not call stop() directly after endPacket() since you are creating a race condition, but I don’t know in WICED how to know that your packet has definitely been transmitted. It is an interesting question, but does not come up much due the socket lifetime discussion above. You could wait a smallish amount time and have high confidence that it was sent.

The WICED WiFi chip (and the TI CC3000 before it) have a limited number of total sockets available. If you are using the cloud connection, that consumes one socket. Each UDP or TCPClient object consumes one socket. A TCPServer object is slightly different and can consume one, two or more sockets over time as clients connect. The total number on the core was 7 sockets but I think it is larger on Photon.

Doesn’t seem to be a memory issue.
free heap reports ~53KB for a freshly rebooted P1, ~52KB for a P1 that has been running for several days and is experiencing the issue.