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, Zynq Ultrascale+,
and Versal processor systems) 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;
}