The lwIP socket API provides a BSD socket-style API to programs. This API provides an execution model that is a blocking, open-read-write-close paradigm.
Xilinx Adapter Requirements when using the Socket API
Applications using the Socket API with Xilinx adapters need to spawn a separate thread called xemacif_input_thread. This thread takes care of moving received packets from the interrupt handlers to the tcpip_thread of the lwIP. Application threads that use lwIP must be created using the lwIP sys_thread_new API. Internally, this function makes use of the appropriate thread or task creation routines provided by XilKernel or FreeRTOS.
Xilkernel/FreeRTOS scheduling policy when using the Socket API
lwIP in socket mode requires the use of the Xilkernel or FreeRTOS, which
provides two policies for thread scheduling: round-robin and
priority based. There are no special requirements when round-robin
scheduling policy is used because all threads or tasks with same
priority receive the same time quanta. This quanta is fixed by the
RTOS (Xilkernel or FreeRTOS) being used. With priority scheduling,
care must be taken to ensure that lwIP threads or tasks are not
starved. For Xilkernel, lwIP internally launches all threads at the
priority level specified in
socket_mode_thread_prio
. For FreeRTOS, lwIP
internally launches all tasks except the main TCP/IP task at the
priority specified in socket_mode_thread_prio
. The
TCP/IP task in FreeRTOS is launched with a higher priority (one more
than priority set in socket_mode_thread_prio
). In
addition, application threads must launch
xemacif_input_thread
. The priorities of
both xemacif_input_thread
, and the lwIP internal
threads (socket_mode_thread_prio
) must be high
enough in relation to the other application threads so that they are
not starved.
Socket API Example
main_thread()
is a thread specified to be
launched by XIlkernel, control reaches this first thread from
application main
after the Xilkernel schedule is
started. In main_thread
, one more thread
(network_thread) is created to initialize the MAC layer. For
FreeRTOS (Zynq 7000, Zynq UltraScale+ MPSoC, and Versal adatpive
SoC) based applications.- Once the control reaches application main routine, a task (can be termed as main_thread) with an entry point function as main_thread() is created before starting the scheduler.
- After the FreeRTOS scheduler starts, the control reaches main_thread(), where the lwIP internal initialization happens.
- The application then creates one more thread (network_thread) to initialize the MAC layer. The following pseudo-code illustrates a typical socket mode program structure.
void
network_thread(void
*p)
{
struct
netif *netif;
ip_addr_t ipaddr, netmask, gw;
unsigned
char
mac_ethernet_address[] =
{0x00, 0x0a, 0x35, 0x00, 0x01, 0x02};
netif = &server_netif;
IP4_ADDR(&ipaddr,192,168,1,10);
IP4_ADDR(&netmask,255,255,255,0);
IP4_ADDR(&gw,192,168,1,1);
if
(!xemac_add(netif, &ipaddr, &netmask,
&gw, mac_ethernet_address,
EMAC_BASEADDR)) {
printf(“Error adding N/W interface\n\r”);
return
;
}
netif_set_default(netif);
netif_set_up(netif);
sys_thread_new(“xemacif_input_thread”, xemacif_input_thread,
netif,
THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
sys_thread_new(“httpd” web_application_thread, 0,
THREAD_STACKSIZE DEFAULT_THREAD_PRIO);
}
int
main_thread()
{
lwip_init();
sys_thread_new(“network_thread” network_thread, NULL,
THREAD_STACKSIZE DEFAULT_THREAD_PRIO);
return
0;
}