This paper describes how to enable address allocation throught DHCP for applications developed with Xilinx Platform Studio using Xilinx's lwip library.
The lwip v2.00.a library provided by Xilinx (at least in EDK 9.1) does not
enable to use the in the lwip library included DHCP support by default. A little
'hack' is needed to make DHCP work - the lwip Makefile (Makefile_mb
for Microblaze and Makefile_ppc for PowerPC) in
$EDK/sw/ThirdParty/sw_services/lwip_v2_00_a/src has to be changed.
Add $(LWIPDIR)/core/dhcp.c to the file list defined under
COREFILES. For the MicroBlaze lwip Makefile version you can use the
Makefile in atachment 1.
There is no support for obtaining the DNS server within the DHCP session
by default. If you need to get the DNS server address, you can use the in the
atachment also included patched files dhcp.c, dhcp.h
and netif.h. Your netif structure will then include
an additional entry of the type struct ip_addr called
dns which will contain the DNS server IP address. The file
dhcp.c belongs to ($LWIPDIR)/lwip/src/core, the files
netif.h and dhcp.h to
($LWIPDIR)/lwip/src/include/lwip.
The second step is to make your application correctly use the lwip DHCP functions. The example below shows the essential code needed in an application that uses DHCP to configure its network interface:
#include <netif/xemacliteif.h> #include <xmk.h> #include <xparameters.h> #include <lwip/mem.h> #include <lwip/tcpip.h> #include <lwip/dhcp.h> #define DEBUG #ifdef DEBUG #define DEBUG_MSG(msg) xil_printf(msg); #else #define DEBUG_MSG(msg) #endif #define MAC_ADDR {0x01, 0x02, 0x03, 0x04, 0x05, 0x06} #define DHCP_TIMEOUT_MS 2000 extern XEmacLiteIf_Config XEmacLiteIf_ConfigTable[]; static struct netif *app_netif; void* netif_config_thread(void *arg) { unsigned char macaddr[6] = MAC_ADDR; struct ip_addr ipaddr, netmask, gateway; int mscnt = 0; XEmacLiteIf_Config *xemacif_ptr = &XEmacLiteIf_ConfigTable[0]; // Set up the MAC address for the ethernet MAC xemacliteif_setmac(0, (u8_t *)macaddr); // Clear the IP address, Subnet Mask, and Gateway ipaddr.addr = 0; netmask.addr = 0; gateway.addr = 0; // Set up the lwIP network interface // Allocate and configure the app's netif app_netif = (struct netif *) mem_malloc(sizeof(struct netif)); if(app_netif == NULL) { DEBUG_MSG("ERROR: Out of memory for default netif\r\n"); return; } app_netif = netif_add(app_netif, &ipaddr, &netmask, &gateway, &XEmacLiteIf_ConfigTable[0], xemacliteif_init, tcpip_input); netif_set_default(app_netif); // Register the XEMAC interrupt handler with the controller // and enable interrupts within XMK register_int_handler(XPAR_OPB_INTC_0_ETHERNET_MAC_IP2INTC_IRPT_INTR, (XInterruptHandler)XEmacLite_InterruptHandler, xemacif_ptr->instance_ptr); enable_interrupt(XPAR_OPB_INTC_0_ETHERNET_MAC_IP2INTC_IRPT_INTR); // Start the DHCP "Client Daemon" DEBUG_MSG("Starting DHCPCD...\r\n"); dhcp_start(app_netif); while (1) { sleep(DHCP_FINE_TIMER_MSECS); dhcp_fine_tmr(); mscnt += DHCP_FINE_TIMER_MSECS; if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) { dhcp_coarse_tmr(); mscnt = 0; } } } void* socket_thread(void* arg) { int mscnt = 0; // Initialize the lwIP library DEBUG_MSG("Initializing the lwIP library...\r\n"); lwip_init(); sleep(200); DEBUG_MSG("lwIP initialization done\r\n"); // Start network configuration (+DHCPCD) thread DEBUG_MSG("Configuring IP...\r\n"); sys_thread_new ((void (*)(void*))netif_config_thread, 0, 0); // Wait for DHCP IP configuration while (1) { sleep(DHCP_FINE_TIMER_MSECS); if (app_netif->ip_addr.addr) { DEBUG_MSG("DHCP request success\r\n"); break; } mscnt += DHCP_FINE_TIMER_MSECS; if (mscnt >= DHCP_TIMEOUT_MS) { DEBUG_MSG("ERROR: DHCP request timed out\r\n"); return; } } DEBUG_MSG("IP configuration done\r\n"); // START THE APPLICATION THREAD(S) // sys_thread_new ((void (*)(void*)) app_thread, 0, 1); // ... } int main() { // Launch XMK DEBUG_MSG("System initialization start\r\n"); xilkernel_main(); return 0; }
Fig. 1.: Simple application using DHCP network interface configuration
Note: The socket_thread thread must be defined in the Xilkernel
configuration to be started at Xilkernel start.
After initializing the interface, the function
dhcp_start(struct netif *netif) is called to configure the
interface. Then every DHCP_FINE_TIMER_MSECS miliseconds the
function dhcp_fine_tmr() and every
DHCP_COARSE_TIMER_SECS seconds the function
dhcp_coarse_tmr() has to be called.
More info can be found in the lwip dhcp.c source file and the
lwip wiki [1].
[1]
http://lwip.scribblewiki.com/DHCP
1. lwip_patch.zip
- DHCP patch archive
2. example.c
- Simple DHCP using application example