Socket API - 2021.1 English

Xilinx Standalone Library Documentation OS and Libraries Document Collection (UG643)

Document ID
UG643
Release Date
2021-06-16
Version
2021.1 English

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

XilKernel-based applications in socket mode can specify a static list of threads that Xilkernel spawns on startup in the Xilkernel Software Platform Settings dialog box. Assuming that 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;
}