Do not be put off by the apparent complexity of the topic. FreeRTOS+UDP takes care of the underlying protocols. FreeRTOS+UDP users only need to know the meaning of the configuration options, and how to use the standard Berkeley sockets "like" interface to send and receive data. Simple worked examples and an API reference are provided on this website.
FreeRTOS+UDP is designed specifically for small embedded systems. Such systems are normally, but by no means exclusively, connected via Ethernet.
On this page (topics best read in the order they appear):
FreeRTOS+UDP allows your embedded device to use the Internet Protocol (IP) to send data to, and receive data from, remote network nodes. The remote nodes can be on the same local network, or on remote networks that are accessible over the Internet.
User Datagram Protocol (UDP) data is sent in connectionless packets. That means the UDP and IP protocols do not guarantee delivery. Just like in RS232 or RS485 communications, the node sending data cannot assume the intended recipient received the data just because the data was sent onto the network. This is where TCP/IP differs from UDP/IP. The TCP protocol has a built in acknowledgement and re-transmission mechanism, UDP does not. Therefore, UDP packets that require acknowledgement of receipt must be manually acknowledged by the receiving application.
UDP is smaller, faster, and more suitable to fast embedded network communication than TCP.
Each single network node can run multiple applications that use the same network interface, and therefore use the same IP address. For example, a FreeRTOS application can run a TFTP server, an echo server and a Nabto client at the same time - all of which make use of the UDP/IP stack. Different applications running on the same network node, and therefore at the same IP address, are identified by their port number.
The source and destination address of each UDP packet is therefore a combination of an IP address and a port number.
The API function FreeRTOS_socket() is used to create a socket.
When a socket is created it assumes the IP address of the network node that created it. If a socket has an IP address but not a port number it is said to be 'unbound'. An unbound socket cannot receive data because it does not have a complete address.
When a socket has both an IP address and a port number it is said to be 'bound to a port', or 'bound to an address'. A bound socket can receive data because it has a complete address.
The process of allocating a port number to a socket is called 'binding'.
The API function FreeRTOS_bind() is used to bind a FreeRTOS+UDP socket to a port number.
If ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 in FreeRTOSIPConfig.h then FreeRTOS_bind() must be used to bind a socket to a port number before the socket can be used to either send or receive data. If ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 in FreeRTOSIPConfig.h then an unbound socket will be automatically bound to a port number the first time it attempts to send data, but can still only receive data after it has been bound.
Clients need to locate servers, and the simplest way to achieve this is by having the server bind to a pre-agreed address (other more complex methods also exist).
Servers do not need to know the client's address in advance, they just send their replies to the address from which the client's request originated. Therefore clients can (normally) bind to nearly any port number, although high port numbers in the range 0xC000 to 0xFFFF are reserved for use by FreeRTOS+UDP itself, and many low port numbers are (by convention only) reserved for common network services.
The standard echo service provides a convenient example, and is the subject of the worked FreeRTOS+UDP demo application available from this website. Echo servers simply echo back the data sent to them by clients. Echo servers use port 7 by convention. The sequence diagram below shows a socket being created and bound on both an echo client and an echo server, and then a single echo transaction between the client and the server (it should be noted that the sockets only need to be created and bound once, not for each transaction).
The FreeRTOS+UDP API function FreeRTOS_IPInit() takes a default IP address (among other addresses) as one of it's parameters. The default IP address is used as a static IP address if ipconfigUSE_DHCP is set to 0, or if ipconfigUSE_DHCP is set to 1 but a DHCP server cannot be contacted. See the description of DHCP below.
If ipconfigUSE_DHCP is set to 1 in FreeRTOSIPConfig.h then FreeRTOS+UDP will attempt to obtain its IP address from a DHCP server, and only revert to using a static IP address if a DHCP server cannot be contacted.
Like the IP address, the subnet mask can be configured either statically as a parameter to FreeRTOS_IPInit(), or dynamically from a DHCP server.
If a destination IP address bitwise ANDed with the subnet mask matches the local IP address bitwise ANDed with the subnet mask then the two IP addresses exist on the same network.
FreeRTOS+UDP determines whether a UDP packet can be sent directly, or if it needs to be routed through a gateway. FreeRTOS+UDP users only need to provide a gateway address. Like the IP address, the IP address of a gateway can be configured either statically as a parameter to FreeRTOS_IPInit(), or dynamically from a DHCP server.
If ipconfigUSE_DNS is set to 1 in FreeRTOSIPConfig.h then the FreeRTOS+UDP API function FreeRTOS_gethostbyname() can be used to resolve a text name to an IP address.
Like the IP address, the IP address of a domain name server can be configured either statically as a parameter to FreeRTOS_IPInit(), or dynamically from a DHCP server.
The Address Resolution Protocol (ARP) is used to obtain MAC address information. FreeRTOS+UDP (like most if not all IP stacks) stores IP address to MAC address mappings in an ARP table (sometimes called the ARP cache).
It is rare for the writer of a non connected application to need to concern themselves with how their target microcontroller stores data internally. If data is written to memory in little endian order, it will be read back from memory in little endian order - and so the value read back will match the value originally written.
It is more complicated when microcontrollers are connected, because there are no guarantees that all the microcontrollers on a connected network will have the same byte order. All the microcontrollers on the network have to agree the byte order used to send and receive data in advance. The byte order used for data in transit is called the network byte order.
In UDP/IP networks data is sent most significant byte first, making UDP/IP networks effectively big endian. Therefore, a little endian microcontroller sending to a UDP/IP network must swap the order in which bytes appear within multi byte values before the values are sent onto the network, and must swap the order in which bytes appear in multi byte values received from the network before the values are used. A big endian microcontrollers does not need to perform any byte swapping because the endian of the microcontroller (the host byte order) matches the agreed endian of the network (the network byte order).