I'm trying to get a Spartan3E FPGA to communicate with a PC. I'm using lwIP and Microblaze and have managed to get the FPGA to receive packets fine, but despite it appearing to bind and connect the socket for transmitting data, I don't receive any data. The code is below. Your help would be greatly appriciated.
Thanks, SC
/***************************** Include Files
*********************************//* Xilinx Includes */ #include "xstatus.h" // Required for status checks on peripheral functions #include "xgpio.h" // Required for GPIO peripherals #include "xmk.h"
/* C Library Includes */ #include "string.h" // Required for memset and strtok
/* lwIP Includes */ #include "netif/xemacif.h" #include "lwip/udp.h" #include "lwip/memp.h" #include "netif/etharp.h" #include "lwip/sys.h" #include "lwip/sockets.h"
// OPB Timer/Counter Device Driver #include "xtmrctr.h"
#include "Ethernet_10.h"
/************************** Variable Definitions
******************************/extern XEmacIf_Config XEmacIf_ConfigTable[];
int numConnections;
int incoming_buffer_len;
int incoming_sock, outgoing_sock;
struct sockaddr_in incoming_udp, outgoing_udp;
XTmrCtr udp_transmitter_timer;
/ ***************************************************************************** *- This is the UDP Transmitter Application Thread
- @param baseaddr_p is the Base Address of OPB_Timer_0
- @return None
- @note None
void udp_transmitter_int_handler (void* arg) {
char writeBuffer[6]; xil_printf("Sending Data\r\n"); writeBuffer[0] = 'a'; writeBuffer[1] = 'b'; writeBuffer[2] = 'c'; writeBuffer[3] = 'd'; writeBuffer[4] = 'e'; writeBuffer[5] = 'f';
// write(outgoing_sock, "writeBuffer", 11); //hanging here // udp_send(outgoing_sock, "a"); //hanging here
// Resets the UDP Transmitter Timer to a start mode XTmrCtr_Reset(&udp_transmitter_timer, 0); }
/ ***************************************************************************** *- This is the Network Listener Application Thread
- @param sd - Socket ID
- @return None
- @note None
void* processConnection(struct sockaddr_in input, int connections) { // char receiveBuffer[6];//RECV_BUFFER_LENGTH]; // int sd = *((int*) arg); // int bytesReceived;
// Read the request data
xil_printf("Data : %s \r\n", &incoming_udp);
// xil_printf("Data Recieved: "); // xil_printf(&input); // xil_printf("\n\r"); // xil_printf("Connections: ");
// close(&input); numConnections--; }
/ ***************************************************************************** *- This is the UDP Application Thread, it generates and listens to udp traffic
- @param sd - Socket ID
- @return None
- @note None
void* udpAppThread(void* arg) { int i; int leds_disp; int switches_value; int size; int status; unsigned char mac_address[6]; unsigned char ip_address[4]; unsigned char gateway_addr[4]; unsigned char subnet[4]; struct ip_addr ipaddr, netmask, gateway; struct netif *server_netif; XEmacIf_Config *xemacif_ptr = &XEmacIf_ConfigTable[0]; XStatus udp_transmitter_initialized; Xuint32 udp_transmitter_status; XStatus register_setup_status;
// MAC Address = 00-00-00-00-22-31 memset(mac_address, 0, 6); mac_address[0] = 0x00; mac_address[1] = 0x00; mac_address[2] = 0x00; mac_address[3] = 0x00; mac_address[4] = 0x22; mac_address[5] = 0x31; xemacif_setmac(0, (u8_t *)mac_address);
// Netmask = 255.255.255.0 netmask.addr = htonl(0xffffff00);
// Gateway = 10.1.2.1 gateway.addr = htonl(0x0a010201);
// IP Address = 10.1.2.101 ipaddr.addr = htonl(0x0a010265);
// Set up the lwIP network interface // Allocate and configure the server's netif server_netif = mem_malloc(sizeof(struct netif)); if(server_netif == NULL) { xil_printf("ERROR: netif_add(): Out of memory for default netif \n\r"); return; } server_netif = netif_add(server_netif, &ipaddr, &netmask, &gateway, &XEmacIf_ConfigTable[0], xemacif_init, ip_input); netif_set_default(server_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)XEmac_IntrHandlerFifo, xemacif_ptr->instance_ptr);
enable_interrupt(XPAR_OPB_INTC_0_ETHERNET_MAC_IP2INTC_IRPT_INTR);
// Create and bind the socket. Because the MicroBlaze and PowerPC processors // are big-endian architectures, the calls to htons(), htonl(), etc. aren't // necessary, but are included for completeness and portability incoming_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); incoming_udp.sin_family = AF_INET; incoming_udp.sin_port = htons(VMS_PORT); incoming_udp.sin_addr.s_addr = INADDR_ANY; bind(incoming_sock, (struct sockaddr*)&incoming_udp, sizeof(struct sockaddr));
outgoing_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); outgoing_udp.sin_family = AF_INET; outgoing_udp.sin_port = htons(90); outgoing_udp.sin_addr.s_addr = htonl(0x0a010264); status = bind(outgoing_sock, (struct sockaddr*)&outgoing_udp, sizeof(struct sockaddr)); xil_printf("%d bind\r\n",status); status = connect(outgoing_sock, (struct sockaddr*)&outgoing_udp, sizeof(struct sockaddr)); xil_printf("%d connect\r\n",status);
xil_printf("Server initialization complete.\r\n");
// Begin listening on the socket. For all new connections, spawn a new // thread, processConnection(), to deal with them listen(incoming_sock, 20); numConnections = 0;
// Initializes opb_timer_0 as udp_transmitter_timer udp_transmitter_initialized = XTmrCtr_Initialize(&udp_transmitter_timer, XPAR_OPB_TIMER_0_DEVICE_ID);
if (udp_transmitter_initialized == XST_SUCCESS) { xil_printf("-- UDP Transmitter was initialized --\r\n"); } else { if (udp_transmitter_initialized == XST_DEVICE_IS_STARTED) { xil_printf("-- UDP Transmitter was already initialized --\r \n"); } else { xil_printf("-- UDP Transmitter was not found --\r\n"); } }
//Sets options for udp transmitter timer XTmrCtr_SetOptions(&udp_transmitter_timer, 0, // set the 0 timer in opb_timer_0 XTC_DOWN_COUNT_OPTION | // See page 3 on OPB Timer/Counter v1.00b in regards to count down XTC_INT_MODE_OPTION | // Enables the timer counter interrupt output. XTC_AUTO_RELOAD_OPTION); // And reload the "reset" value and begin counting again
// set timer on 1 second interval XTmrCtr_SetResetValue(&udp_transmitter_timer, 0, 50000000);
// Sets the UDP Transmitter Timer to a stop mode XTmrCtr_Stop(&udp_transmitter_timer, 0);
// timer_int_handler process will execute on opb_timer_0 interrupt register_setup_status = register_int_handler(XPAR_OPB_INTC_0_OPB_TIMER_0_INTERRUPT_INTR, udp_transmitter_int_handler, NULL); enable_interrupt(XPAR_OPB_INTC_0_OPB_TIMER_0_INTERRUPT_INTR);
if (register_setup_status == XST_SUCCESS) { xil_printf("-- Interrupt Successfully Created --\r\n"); } else { xil_printf("Interrupt Error : "); putnum(register_setup_status); xil_printf("\r\n"); }
// Sets the UDP Transmitter Timer to a start mode XTmrCtr_Start(&udp_transmitter_timer, 0);
while(1) { // Will wait at the line below till code is recieved. incoming_buffer_len = read(incoming_sock, (struct sockaddr
*)&incoming_udp, sizeof(struct sockaddr));// Increases numConnections everyime new connection is read. // numConnections will decrease after connection is dropped numConnections++;
xil_printf("%d bytes of data \r\n", incoming_buffer_len); // Spawn a new thread to handle the data for the new connection sys_thread_new((void *)&processConnection, &incoming_sock, numConnections); } }
/ ***************************************************************************** *- This is the Top Level Application Thread. It will start all other
- Application Threads.
- @param None
- @return None
- @note None
void serverThread (void* arg) {
// Initialize the lwIP library xil_printf("Initializing the lwIP library...\r\n"); lwip_init(); //mem_init(); //memp_init(); //pbuf_init(); //netif_init(); //udp_init();
// Sleep to allow lwIP initialization status messages to display // without interruption sleep(100); xil_printf("lwIP initialization done\n\r");
// Spawn the UDP communication application thread sys_thread_new((void *)&udpAppThread, 0, 0); xil_printf("udpAppThread Started\n\r"); }
int main (void) { // Launch XMK xilkernel_main();
return 0; }