/* Scheduler include files. */ #include "FreeRTOS.h" #include "task.h" #include "semphr.h" /********************************************************************************************************************** * Type definitions **********************************************************************************************************************/ typedef struct { uint8_t ucIpAdr4[4]; uint8_t ucIpSubNetMask4[4]; uint8_t ucIpStdGateway4[4]; }ip_config_t; /********************************************************************************************************************** * UPORT Instance Definitions **********************************************************************************************************************/ uport_ctrl_t uportFirstTcpCtrlBlock = {}; uport_instance_t uportFirstTcpInst = { .p_api = &uport_api_ethernet, .p_ctrl = &uportFirstTcpCtrlBlock }; uport_ctrl_t uportSecondTcpCtrlBlock = {}; uport_instance_t uportSecondTcpInst = { .p_api = &uport_api_ethernet, .p_ctrl = &uportSecondTcpCtrlBlock }; //Entry point int main( void ) { /* Configure the hardware ready to run the demo. */ prvSetupHardware(); /* Retrieve MAC */ getMACAddress(); /* Create Main Task */ xTaskCreate( prvMainTask, "Main Task", 4096, NULL, mainTASK_PRIORITY, NULL ); /* Start the tasks and timer running. */ vTaskStartScheduler(); /* If all is well, the scheduler will now be running, and the following line will never be reached. If the following line does execute, then there was either insufficient FreeRTOS heap memory available for the idle and/or timer tasks to be created, or vTaskStartScheduler() was called from User mode. See the memory management section on the FreeRTOS web site for more details on the FreeRTOS heap http://www.freertos.org/a00111.html. The mode from which main() is called is set in the C start up code and must be a privileged mode (not user mode). */ for( ;; ); } //Appliaction Task static void prvMainTask( void *pvParameters ) { TickType_t xNextWakeTime; /* Remove compiler warning about unused parameter. */ (void) pvParameters; /* Initialise xNextWakeTime - this only needs to be done once. */ xNextWakeTime = xTaskGetTickCount(); //Return value of API ret_val_e retVal = RET_ERR_DEF; //Create Event Bits to tell the tasks when the TCP/IP stack is ready to create a socket os_syncEvents = xEventGroupCreateStatic(&os_syncEvents_memory); configASSERT(os_syncEvents); /* Initialize the network interface *************************************************************** * _____ * | | * |_____| * _________|_________ * __|__ __|__ * | | | | * |_____| |_____| * * Use IP Config that has been retrieved from EEPROM */ const ip_config_t ipConfig = { .ucIpAdr4 = {192, 168, 168, 230}, .ucIpStdGateway4 = {192, 168, 168, 10}, .ucIpSubNetMask4 = {255, 255, 255, 0} }; EventBits_t osFlagSync = xEventGroupGetBits(os_syncEvents); //Only initialize IP stack if it has not already been done if(!(osFlagSync & (1 << OS_FLAG_SYNC_TCP_STACK_READY_POS))) { FreeRTOS_IPInit( ipConfig.ucIpAdr4, ipConfig.ucIpSubNetMask4, ipConfig.ucIpStdGateway4, ucDNSServerAddress, ucMACAddress ); //Wait for TCP/IP stack to be initialized osFlagSync = xEventGroupWaitBits( os_syncEvents, (1 << OS_FLAG_SYNC_TCP_STACK_READY_POS), FALSE, //Clear on exit TRUE, //Wait for all bits OS_WAIT_FOREVER); if(osFlagSync & (1 << OS_FLAG_SYNC_TCP_STACK_READY_POS)) { xil_printf("TCP/IP stack ready.\n"); } } /* Initialize the TCP-servers, implemented by the User Port(s) (UPORT) ***********************************************************************************************/ // Setup & start-up first TCP Instance // ------------------------------------ uport_cfg_t uportTcpCfg = { .role = UPORT_ROLE_SERVER, .managingTskPriority = mainTASK_PRIORITY, .port = 10000, .ucId = "1st Uport Perf", }; //Init the first instance of the UPORT uportFirstTcpInst.p_cfg = &uportTcpCfg; //Fire it up retVal = uportFirstTcpInst.p_api->open(uportFirstTcpInst.p_ctrl, uportFirstTcpInst.p_cfg); // Setup & start-up second TCP Instance // -------------------------------------- uportTcpCfg.port = 20000; uportTcpCfg.ucId = "2nd Uport Perf"; uportSecondTcpInst.p_cfg = &uportTcpCfg; //Fire the second one up retVal = uportSecondTcpInst.p_api->open(uportSecondTcpInst.p_ctrl, uportSecondTcpInst.p_cfg); /* Setup the data structure **************************************************************************************************/ typedef struct __attribute__((packed)) { char frameStart[3]; uint32_t serialNum; uint8_t dummy[16]; }ipstack_perf_payload_t; ipstack_perf_payload_t payloadFirstUport = {}; memcpy(payloadFirstUport.frameStart, "sta", 3); //Create a human readable string at the beginning of each message ipstack_perf_payload_t payloadSecondUport = {}; memcpy(payloadSecondUport.frameStart, "xyz", 3); uint32_t writtenBytes = 0; //Read out console stdin uport_instance_t * pCurrentlyActiveUport = (uport_instance_t *) errReporterInst.p_ctrl->pUportInstance; uint8_t consoleReadBuf[20] = {}; uint32_t bytesRead = 0; // Handshake payload size const uint32_t payloadSize = sizeof(ipstack_perf_payload_t); bool bSendHandshakeFirst = true; bool bSendHandshakeSecond = true; while(1) { xNextWakeTime = xTaskGetTickCount(); /* HANDLE FIRST TCP INSTANCE: Send handshake, which is size of payload as first message after a connection is established ***************************************************************************************************************************/ if(bSendHandshakeFirst) { retVal = uportFirstTcpInst.p_api->write(uportFirstTcpInst.p_ctrl, (uint8_t*) &payloadSize, sizeof(payloadSize), &writtenBytes, pdMS_TO_MIN_TICKS(1000)); }else { //Send a predefined message that is mostly empty but an upcounting serial num, which reflects a cont. DS retVal = uportFirstTcpInst.p_api->write(uportFirstTcpInst.p_ctrl, (uint8_t*) &payloadFirstUport, sizeof(payloadFirstUport), &writtenBytes, pdMS_TO_MIN_TICKS(1000)); if(retVal == RET_OK) { payloadFirstUport.serialNum++; } } if(retVal == RET_OK) { bSendHandshakeFirst = false; }else if(retVal == RET_ERR_UPORT_IPSTACK_NO_CLIENT) { bSendHandshakeFirst = true; payloadFirstUport.serialNum = 0; } else { HRF_CONSOLE_RETVAL(retVal, "", "Uport 1st write failed") } /* HANDLE SECOND TCP INSTANCE: Send handshake, which is size of payload as first message after a connection is established ***************************************************************************************************************************/ if(bSendHandshakeSecond) { retVal = uportSecondTcpInst.p_api->write(uportSecondTcpInst.p_ctrl, (uint8_t*) &payloadSize, sizeof(payloadSize), &writtenBytes, pdMS_TO_MIN_TICKS(1000)); }else { //Send a predefined message that is mostly empty but an upcounting serial num, which reflects a cont. DS retVal = uportSecondTcpInst.p_api->write(uportSecondTcpInst.p_ctrl, (uint8_t*) &payloadSecondUport, sizeof(payloadSecondUport), &writtenBytes, pdMS_TO_MIN_TICKS(1000)); if(retVal == RET_OK) { payloadSecondUport.serialNum++; } } if(retVal == RET_OK) { bSendHandshakeSecond = false; }else if(retVal == RET_ERR_UPORT_IPSTACK_NO_CLIENT) { bSendHandshakeSecond = true; payloadSecondUport.serialNum = 0; } else { HRF_CONSOLE_RETVAL(retVal, "", "Uport 2nd write failed") } vTaskDelayUntil( &xNextWakeTime, pdMS_TO_MIN_TICKS(*pParams->pTskPeriod) ); }