static BaseType_t prvDisplayIPConfig( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) { static BaseType_t xIndex = 0; BaseType_t xReturn; uint32_t ulAddress; /* Remove compile time warnings about unused parameters, and check the write buffer is not NULL. NOTE - for simplicity, this example assumes the write buffer length is adequate, so does not check for buffer overflows. */ ( void ) pcCommandString; ( void ) xWriteBufferLen; configASSERT( pcWriteBuffer ); switch( xIndex ) { case 0 : FreeRTOS_GetAddressConfiguration( &ulAddress, NULL, NULL, NULL ); sprintf( pcWriteBuffer, "\r\nIP address " ); xReturn = pdTRUE; xIndex++; break; case 1 : FreeRTOS_GetAddressConfiguration( NULL, &ulAddress, NULL, NULL ); sprintf( pcWriteBuffer, "\r\nNet mask " ); xReturn = pdTRUE; xIndex++; break; case 2 : FreeRTOS_GetAddressConfiguration( NULL, NULL, &ulAddress, NULL ); sprintf( pcWriteBuffer, "\r\nGateway address " ); xReturn = pdTRUE; xIndex++; break; case 3 : FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulAddress ); sprintf( pcWriteBuffer, "\r\nDNS server address " ); xReturn = pdTRUE; xIndex++; break; default : ulAddress = 0; sprintf( pcWriteBuffer, "\r\n\r\n" ); xReturn = pdFALSE; xIndex = 0; break; } if( ulAddress != 0 ) { FreeRTOS_inet_ntoa( ulAddress, ( &( pcWriteBuffer[ strlen( pcWriteBuffer ) ] ) ) ); } return xReturn; }
static void prvSimpleClientTask( void *pvParameters ) { xSocket_t xClientSocket; struct freertos_sockaddr xDestinationAddress; uint8_t cString[ 50 ]; portBASE_TYPE lReturned; uint32_t ulCount = 0UL, ulIPAddress; const uint32_t ulLoopsPerSocket = 10UL; const portTickType x150ms = 150UL / portTICK_RATE_MS; /* Remove compiler warning about unused parameters. */ ( void ) pvParameters; /* It is assumed that this task is not created until the network is up, so the IP address can be obtained immediately. store the IP address being used in ulIPAddress. This is done so the socket can send to a different port on the same IP address. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); /* This test sends to itself, so data sent from here is received by a server socket on the same IP address. Setup the freertos_sockaddr structure with this nodes IP address, and the port number being sent to. The strange casting is to try and remove compiler warnings on 32 bit machines. */ xDestinationAddress.sin_addr = ulIPAddress; xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL; xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port ); for( ;; ) { /* Create the socket. */ xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET ); /* The count is used to differentiate between different messages sent to the server, and to break out of the do while loop below. */ ulCount = 0UL; do { /* Create the string that is sent to the server. */ sprintf( ( char * ) cString, "Server received (not zero copy): Message number %lu\r\n", ulCount ); /* Send the string to the socket. ulFlags is set to 0, so the zero copy option is not selected. That means the data from cString[] is copied into a network buffer inside FreeRTOS_sendto(), and cString[] can be reused as soon as FreeRTOS_sendto() has returned. */ lReturned = FreeRTOS_sendto( xClientSocket, ( void * ) cString, strlen( ( const char * ) cString ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) ); ulCount++; } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) ); FreeRTOS_closesocket( xClientSocket ); /* A short delay to prevent the messages printed by the server task scrolling off the screen too quickly, and to prevent reduce the network loading. */ vTaskDelay( x150ms ); } }
static void prvMultipleSocketTxTask( void *pvParameters ) { uint32_t ulTxValue = 0; struct freertos_sockaddr xDestinationAddress; uint32_t ulIPAddress, ulFirstDestinationPortNumber, xPortNumber; xSocket_t xTxSocket; const TickType_t xShortDelay = 100 / portTICK_RATE_MS, xSendBlockTime = 500 / portTICK_RATE_MS; srand( ( unsigned int ) &xPortNumber ); /* The first destination port number is passed in as the task parameter. Other destination port numbers used are consecutive from this. */ ulFirstDestinationPortNumber = ( uint32_t ) pvParameters; /* Create the socket used to send to the sockets created by the Rx task. Let the IP stack select a port to bind to. */ xTxSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); FreeRTOS_bind( xTxSocket, NULL, sizeof( struct freertos_sockaddr ) ); /* The Rx and Tx tasks execute at the same priority so it is possible that the Tx task will fill up the send queue - set a Tx block time to ensure flow control is managed if this happens. */ FreeRTOS_setsockopt( xTxSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendBlockTime, sizeof( xSendBlockTime ) ); /* It is assumed that this task is not created until the network is up, so the IP address can be obtained immediately. Store the IP address being used in ulIPAddress. This is done so the socket can send to a different port on the same IP address. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); /* This test sends to itself, so data sent from here is received by a server socket on the same IP address. Setup the freertos_sockaddr structure with this nodes IP address. */ xDestinationAddress.sin_addr = ulIPAddress; /* Block for a short time to ensure the task implemented by the prvMultipleSocketRxTask() function has finished creating the Rx sockets. */ vTaskDelay( xShortDelay ); for( ;; ) { /* Pseudo randomly select the destination port number from the range of valid destination port numbers. */ xPortNumber = rand() % selNUMBER_OF_SOCKETS; xDestinationAddress.sin_port = ( uint16_t ) ( ulFirstDestinationPortNumber + xPortNumber ); xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port ); /* Send an incrementing value. */ FreeRTOS_sendto( xTxSocket, &ulTxValue, sizeof( ulTxValue ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) ); ulTxValue++; /* Delay here because in the Windows simulator the MAC interrupt simulator delays, so network trafic cannot be received any faster than this. */ vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ); } }
/* Defined by the application code, but called by FreeRTOS+UDP when the network connects/disconnects (if ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 in FreeRTOSIPConfig.h). */ void vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent) { uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress; static BaseType_t xTasksAlreadyCreated = pdFALSE; int8_t cBuffer[16]; char bufor[100]; /* Check this was a network up event, as opposed to a network down event. */ if (eNetworkEvent == eNetworkUp) { /* Create the tasks that use the IP stack if they have not already been created. */ if (xTasksAlreadyCreated == pdFALSE) { //if(xTaskCreate(vUDPTransmitCANFramesTask,"Tx CAN/UDP",UDPD_CAN_TX_SIZE,NULL,UDP_CAN_TX_PRIO,NULL)==pdPASS) print_console("Creating UDP/CAN Tx task -- > OK\r\n"); // else print_console("Creating UDP/CAN Tx -- > failed\r\n"); SNTP_init(); //daj znac taskowi do obslugi http/ftp,ze moze utworzyc sockety #if ipconfigUSE_HTTP==1 || ipconfigUSE_FTP==1 xTaskNotifyGive(xServerWorkTaskHandle); #endif xTasksAlreadyCreated = pdTRUE; } /* The network is up and configured. Print out the configuration, which may have been obtained from a DHCP server. */ FreeRTOS_GetAddressConfiguration(&ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress); print_console("\r\n-----------------------\r\n\r\n"); /* Convert the IP address to a string then print it out. */ FreeRTOS_inet_ntoa(ulIPAddress, cBuffer); sprintf(bufor, "IP Address: %s\r\n", cBuffer); print_console(bufor); gdb.sys.ipaddress = ulIPAddress; /* Convert the net mask to a string then print it out. */ FreeRTOS_inet_ntoa(ulNetMask, cBuffer); sprintf(bufor, "Subnet Mask: %s\r\n", cBuffer); print_console(bufor); gdb.sys.maskaddress = ulNetMask; /* Convert the IP address of the gateway to a string then print it out. */ FreeRTOS_inet_ntoa(ulGatewayAddress, cBuffer); sprintf(bufor, "Gateway IP Address: %s\r\n", cBuffer); print_console(bufor); gdb.sys.gwaddress = ulGatewayAddress; /* Convert the IP address of the DNS server to a string then print it out. */ FreeRTOS_inet_ntoa(ulDNSServerAddress, cBuffer); sprintf(bufor, "DNS server IP Address: %s\r\n", cBuffer); print_console(bufor); gdb.sys.dnsaddress = ulDNSServerAddress; } }
static void prvSimpleZeroCopyServerTask( void *pvParameters ) { int32_t lBytes; uint8_t *pucUDPPayloadBuffer; struct freertos_sockaddr xClient, xBindAddress; uint32_t xClientLength = sizeof( xClient ), ulIPAddress; xSocket_t xListeningSocket; /* Just to prevent compiler warnings. */ ( void ) pvParameters; /* Attempt to open the socket. */ xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET ); /* This test receives data sent from a different port on the same IP address. Obtain the nodes IP address. Configure the freertos_sockaddr structure with the address being bound to. The strange casting is to try and remove compiler warnings on 32 bit machines. Note that this task is only created after the network is up, so the IP address is valid here. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); xBindAddress.sin_addr = ulIPAddress; xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL; xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port ); /* Bind the socket to the port that the client task will send to. */ FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) ); for( ;; ) { /* Receive data on the socket. ulFlags has the zero copy bit set (FREERTOS_ZERO_COPY) indicating to the stack that a reference to the received data should be passed out to this task using the second parameter to the FreeRTOS_recvfrom() call. When this is done the IP stack is no longer responsible for releasing the buffer, and the task *must* return the buffer to the stack when it is no longer needed. By default the block time is portMAX_DELAY. */ lBytes = FreeRTOS_recvfrom( xListeningSocket, ( void * ) &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength ); /* It is expected to receive one more byte than the string length as the NULL terminator is also transmitted. */ configASSERT( lBytes == ( ( portBASE_TYPE ) strlen( ( const char * ) pucUDPPayloadBuffer ) + 1 ) ); /* Print the received characters. */ if( lBytes > 0 ) { vOutputString( ( char * ) pucUDPPayloadBuffer ); } if( lBytes >= 0 ) { /* The buffer *must* be freed once it is no longer needed. */ FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer ); } } }
/* Called by FreeRTOS+UDP when the network connects. */ void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ) { uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress; int8_t cBuffer[ 16 ]; static portBASE_TYPE xTasksAlreadyCreated = pdFALSE; if( eNetworkEvent == eNetworkUp ) { /* Create the tasks that use the IP stack if they have not already been created. */ if( xTasksAlreadyCreated == pdFALSE ) { #if( mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS == 1 ) { /* Create tasks that demonstrate sending and receiving in both standard and zero copy mode. */ vStartSimpleUDPClientServerTasks( mainSIMPLE_CLIENT_SERVER_TASK_STACK_SIZE, mainSIMPLE_CLIENT_SERVER_PORT, mainSIMPLE_CLIENT_SERVER_TASK_PRIORITY ); } #endif /* mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS */ #if( mainCREATE_SELECT_UDP_SERVER_TASKS == 1 ) { /* Create tasks that demonstrate sending and receiving in both standard and zero copy mode. */ vStartSelectUDPServerTasks( mainSELECT_SERVER_TASK_STACK_SIZE, mainSELECT_SERVER_PORT, mainSELECT_SERVER_TASK_PRIORITY ); } #endif /* mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS */ #if( mainCREATE_UDP_ECHO_TASKS == 1 ) { /* Create the tasks that transmit to and receive from a standard echo server (see the web documentation for this port) in both standard and zero copy mode. */ vStartEchoClientTasks( mainECHO_CLIENT_TASK_STACK_SIZE, mainECHO_CLIENT_TASK_PRIORITY ); } #endif /* mainCREATE_UDP_ECHO_TASKS */ #if( mainCREATE_UDP_CLI_TASKS == 1 ) { /* Create the task that handles the CLI on a UDP port. The port number is set using the configUDP_CLI_PORT_NUMBER setting in FreeRTOSConfig.h. */ vStartUDPCommandInterpreterTask( mainUDP_CLI_TASK_STACK_SIZE, mainUDP_CLI_PORT_NUMBER, mainUDP_CLI_TASK_PRIORITY ); } #endif /* mainCREATE_UDP_CLI_TASKS */ xTasksAlreadyCreated = pdTRUE; } /* Print out the network configuration, which may have come from a DHCP server. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress ); vOutputString( "IP Address: " ); FreeRTOS_inet_ntoa( ulIPAddress, cBuffer ); vOutputString( ( char * ) cBuffer ); vOutputString( "\r\nSubnet Mask: " ); FreeRTOS_inet_ntoa( ulNetMask, cBuffer ); vOutputString( ( char * ) cBuffer ); vOutputString( "\r\nGateway Address: " ); FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer ); vOutputString( ( char * ) cBuffer ); vOutputString( "\r\nDNS Server Address: " ); FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer ); vOutputString( ( char * ) cBuffer ); vOutputString( "\r\n\r\n" ); } }
static void prvSimpleZeroCopyUDPClientTask( void *pvParameters ) { xSocket_t xClientSocket; uint8_t *pucUDPPayloadBuffer; struct freertos_sockaddr xDestinationAddress; portBASE_TYPE lReturned; uint32_t ulCount = 0UL, ulIPAddress; const uint32_t ulLoopsPerSocket = 10UL; const uint8_t *pucStringToSend = ( const uint8_t * ) "Server received (using zero copy): Message number "; const portTickType x150ms = 150UL / portTICK_RATE_MS; /* 15 is added to ensure the number, \r\n and terminating zero fit. */ const size_t xStringLength = strlen( ( char * ) pucStringToSend ) + 15; /* Remove compiler warning about unused parameters. */ ( void ) pvParameters; /* It is assumed that this task is not created until the network is up, so the IP address can be obtained immediately. store the IP address being used in ulIPAddress. This is done so the socket can send to a different port on the same IP address. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); /* This test sends to itself, so data sent from here is received by a server socket on the same IP address. Setup the freertos_sockaddr structure with this nodes IP address, and the port number being sent to. The strange casting is to try and remove compiler warnings on 32 bit machines. */ xDestinationAddress.sin_addr = ulIPAddress; xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL; xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port ); for( ;; ) { /* Create the socket. */ xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET ); /* The count is used to differentiate between different messages sent to the server, and to break out of the do while loop below. */ ulCount = 0UL; do { /* This task is going to send using the zero copy interface. The data being sent is therefore written directly into a buffer that is passed into, rather than copied into, the FreeRTOS_sendto() function. First obtain a buffer of adequate length from the IP stack into which the string will be written. Although a max delay is used, the actual delay will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence the do while loop is used to ensure a buffer is obtained. */ do { } while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xStringLength, portMAX_DELAY ) ) == NULL ); /* A buffer was successfully obtained. Create the string that is sent to the server. First the string is filled with zeros as this will effectively be the null terminator when the string is received at the other end. Note that the string is being written directly into the buffer obtained from the IP stack above. */ memset( ( void * ) pucUDPPayloadBuffer, 0x00, xStringLength ); sprintf( ( char * ) pucUDPPayloadBuffer, "%s%lu\r\n", ( char * ) pucStringToSend, ulCount ); /* Pass the buffer into the send function. ulFlags has the FREERTOS_ZERO_COPY bit set so the IP stack will take control of the buffer rather than copy data out of the buffer. */ lReturned = FreeRTOS_sendto( xClientSocket, /* The socket being sent to. */ ( void * ) pucUDPPayloadBuffer, /* A pointer to the the data being sent. */ strlen( ( const char * ) pucUDPPayloadBuffer ) + 1, /* The length of the data being sent - including the string's null terminator. */ FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */ &xDestinationAddress, /* Where the data is being sent. */ sizeof( xDestinationAddress ) ); if( lReturned == 0 ) { /* The send operation failed, so this task is still responsible for the buffer obtained from the IP stack. To ensure the buffer is not lost it must either be used again, or, as in this case, returned to the IP stack using FreeRTOS_ReleaseUDPPayloadBuffer(). pucUDPPayloadBuffer can be safely re-used after this call. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); } else { /* The send was successful so the IP stack is now managing the buffer pointed to by pucUDPPayloadBuffer, and the IP stack will return the buffer once it has been sent. pucUDPPayloadBuffer can be safely re-used. */ } ulCount++; } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) ); FreeRTOS_closesocket( xClientSocket ); /* A short delay to prevent the messages scrolling off the screen too quickly. */ vTaskDelay( x150ms ); } }
DWORD WINAPI prvSimpleWinsockTCPClientTask( void *pvParameters ) { char *pcTransmittedString, *pcReceivedString; BaseType_t lReceived, lTransmitted = 0, lStringLength, lReturned = 0, lInstance; uint32_t ulCount = 0UL, ulMaxCount, ulIPAddress; const uint32_t ulMaxLoopsPerSocket = 100UL; struct sockaddr_in xConnection; SOCKET xClientSocket; int iReturned; TickType_t xTimeOnShutdown; /* Multiple instances of this task are created. The instance is passed in as the parameter. */ lInstance = ( BaseType_t ) pvParameters; /* Locate the buffers for this instance of this task. */ pcTransmittedString = &( cTxBuffers[ lInstance ][ 0 ] ); pcReceivedString = &( cRxBuffers[ lInstance ][ 0 ] ); /* It is assumed that this task is not created until the network is up, so the IP address of the server (which is the FreeRTOS+TCP side of the connection) can be obtained immediately. Store the IP address being used in ulIPAddress. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); /* Set family and port for client socket. */ memset( ( void * ) &xConnection, 0x00, sizeof( struct sockaddr_in ) ); xConnection.sin_family = AF_INET; xConnection.sin_addr.s_addr = ulIPAddress; xConnection.sin_port = htons( tcpechoPORT_NUMBER ); for( ;; ) { /* Create the socket then connect it to the FreeRTOS+TCP server. */ xClientSocket = socket( AF_INET, SOCK_STREAM, 0 ); configASSERT( xClientSocket != INVALID_SOCKET ); do { iReturned = connect( xClientSocket, (const struct sockaddr*) &xConnection, sizeof( xConnection ) ); } while( iReturned != 0 ); ulMaxCount = ipconfigRAND32() % ulMaxLoopsPerSocket; for( ulCount = 0; ulCount < ulMaxCount; ulCount++ ) { /* Create a string then send it to the server. */ lStringLength = prvCreateTxData( pcTransmittedString, tcpechoBUFFER_SIZE ); lTransmitted = send( xClientSocket, pcTransmittedString, lStringLength, 0 ); configASSERT( lTransmitted != SOCKET_ERROR ); configASSERT( lTransmitted == lStringLength ); if( lTransmitted == lStringLength ) { memset( ( void * ) pcReceivedString, 0x00, tcpechoBUFFER_SIZE ); lReceived = 0; /* Wait for the echoed string. */ while( lReceived < lTransmitted ) { lReturned = recv( xClientSocket, ( char * ) &( pcReceivedString[ lReceived ] ), lTransmitted - lReceived, 0 ); if( lReturned >= 0 ) { /* Data was received. */ lReceived += lReturned; } else { /* Error was returned. */ ulClientReceiveErrors++; break; } } /* If the socket was not closed, check the number of bytes received. */ if( lReceived == lTransmitted ) { /* Were the expected characters received? */ configASSERT( memcmp( pcTransmittedString, pcReceivedString, lTransmitted ) == 0x00 ); if( memcmp( pcTransmittedString, pcReceivedString, lReceived ) != 0x00 ) { ulIncorrectDataReceived++; break; } else { /* Received expected string, increment the count of successful cycles. */ ulClientCycles++; } } else { /* Socket is being closed or an error occurred. Don't try using the same socket again. */ break; } } else { ulClientTransmitErrors++; break; } } shutdown( xClientSocket, SD_BOTH ); xTimeOnShutdown = xTaskGetTickCount(); do { Sleep( tcpechoWINSOCK_SHUTDOWN_DELAY ); lReturned = recv( xClientSocket, pcReceivedString, lTransmitted, 0 ); if( lReturned < 0 ) { break; } } while( ( xTaskGetTickCount() - xTimeOnShutdown ) < tcpechoSHUTDOWN_DELAY ); configASSERT( closesocket( xClientSocket ) == 0 ); Sleep( tcpechoLOOP_DELAY ); } }
/* Called by FreeRTOS+UDP when the network connects. */ void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ) { static long lTasksAlreadyCreated = pdFALSE; const unsigned long ulXCoord = 3, ulYCoord = 3, ulIPAddressOffset = 45; unsigned long ulIPAddress; char cIPAddress[ 20 ]; /* Note: If the application is started without the network cable plugged in then ipconfigUDP_TASK_PRIORITY should be set to 0 in FreeRTOSIPConfig.h to ensure the IP task is created at the idle priority. This is because the Atmel ASF GMAC driver polls the GMAC looking for a connection, and doing so will prevent any lower priority tasks from executing. In this demo the IP task is started at the idle priority, then set to configMAX_PRIORITIES - 2 in the network event hook only after a connection has been established (when the event passed into the network event hook is eNetworkUp). */ if( eNetworkEvent == eNetworkUp ) { /* Ensure tasks are only created once. */ if( lTasksAlreadyCreated == pdFALSE ) { /* Create the task that handles the CLI on a UDP port. The port number is set using the configUDP_CLI_PORT_NUMBER setting in FreeRTOSConfig.h. */ vStartUDPCommandInterpreterTask( mainUDP_CLI_TASK_STACK_SIZE, mainUDP_CLI_PORT_NUMBER, mainUDP_CLI_TASK_PRIORITY ); #if( mainINCLUDE_ECHO_CLIENT_TASKS == 1 ) { /* Create the UDP echo tasks. The UDP echo tasks require the IP address of the echo server to be defined using the configECHO_SERVER_ADDR0 to configECHO_SERVER_ADDR3 constants in FreeRTOSConfig.h. */ vStartEchoClientTasks( mainECHO_CLIENT_STACK_SIZE, tskIDLE_PRIORITY ); } #endif } /* Obtain the IP address, convert it to a string, then display it on the LCD. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); FreeRTOS_inet_ntoa( ulIPAddress, cIPAddress ); ili93xx_draw_string( ulXCoord, ulYCoord, ( uint8_t * ) "IP: " ); ili93xx_draw_string( ulXCoord + ulIPAddressOffset, ulYCoord, ( uint8_t * ) cIPAddress ); /* Set the priority of the IP task up to the desired priority now it has connected. */ vTaskPrioritySet( NULL, mainCONNECTED_IP_TASK_PRIORITY ); } /* NOTE: At the time of writing the Ethernet driver does not report the cable being unplugged - so the following if() condition will never be met. It is included for possible future updates to the driver. */ if( eNetworkEvent == eNetworkDown ) { /* Ensure the Atmel GMAC drivers don't hog all the CPU time as they look for a new connection by lowering the priority of the IP task to that of the Idle task. */ vTaskPrioritySet( NULL, tskIDLE_PRIORITY ); /* Disconnected - so no IP address. */ ili93xx_draw_string( ulXCoord, ulYCoord, ( uint8_t * ) "IP: " ); } }
static uint32_t prvGetHostByName( const char *pcHostName, TickType_t xIdentifier, TickType_t xReadTimeOut_ms ) { struct freertos_sockaddr xAddress; Socket_t xDNSSocket; uint32_t ulIPAddress = 0UL; uint8_t *pucUDPPayloadBuffer; static uint32_t ulAddressLength; BaseType_t xAttempt; int32_t lBytes; size_t xPayloadLength, xExpectedPayloadLength; TickType_t xWriteTimeOut_ms = 100U; #if( ipconfigUSE_LLMNR == 1 ) BaseType_t bHasDot = pdFALSE; #endif /* ipconfigUSE_LLMNR == 1 */ /* If LLMNR is being used then determine if the host name includes a '.' - if not then LLMNR can be used as the lookup method. */ #if( ipconfigUSE_LLMNR == 1 ) { const char *pucPtr; for( pucPtr = pcHostName; *pucPtr; pucPtr++ ) { if( *pucPtr == '.' ) { bHasDot = pdTRUE; break; } } } #endif /* ipconfigUSE_LLMNR == 1 */ /* Two is added at the end for the count of characters in the first subdomain part and the string end byte. */ xExpectedPayloadLength = sizeof( DNSMessage_t ) + strlen( pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2u; xDNSSocket = prvCreateDNSSocket(); if( xDNSSocket != NULL ) { FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xWriteTimeOut_ms, sizeof( TickType_t ) ); FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xReadTimeOut_ms, sizeof( TickType_t ) ); for( xAttempt = 0; xAttempt < ipconfigDNS_REQUEST_ATTEMPTS; xAttempt++ ) { /* Get a buffer. This uses a maximum delay, but the delay will be capped to ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS so the return value still needs to be tested. */ pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xExpectedPayloadLength, portMAX_DELAY ); if( pucUDPPayloadBuffer != NULL ) { /* Create the message in the obtained buffer. */ xPayloadLength = prvCreateDNSMessage( pucUDPPayloadBuffer, pcHostName, xIdentifier ); iptraceSENDING_DNS_REQUEST(); /* Obtain the DNS server address. */ FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulIPAddress ); /* Send the DNS message. */ #if( ipconfigUSE_LLMNR == 1 ) if( bHasDot == pdFALSE ) { /* Use LLMNR addressing. */ ( ( DNSMessage_t * ) pucUDPPayloadBuffer) -> usFlags = 0; xAddress.sin_addr = ipLLMNR_IP_ADDR; /* Is in network byte order. */ xAddress.sin_port = FreeRTOS_ntohs( ipLLMNR_PORT ); } else #endif { /* Use DNS server. */ xAddress.sin_addr = ulIPAddress; xAddress.sin_port = dnsDNS_PORT; } ulIPAddress = 0UL; if( FreeRTOS_sendto( xDNSSocket, pucUDPPayloadBuffer, xPayloadLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) != 0 ) { /* Wait for the reply. */ lBytes = FreeRTOS_recvfrom( xDNSSocket, &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xAddress, &ulAddressLength ); if( lBytes > 0 ) { /* The reply was received. Process it. */ ulIPAddress = prvParseDNSReply( pucUDPPayloadBuffer, xIdentifier ); /* Finished with the buffer. The zero copy interface is being used, so the buffer must be freed by the task. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); if( ulIPAddress != 0UL ) { /* All done. */ break; } } } else { /* The message was not sent so the stack will not be releasing the zero copy - it must be released here. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); } } } /* Finished with the socket. */ FreeRTOS_closesocket( xDNSSocket ); } return ulIPAddress; }
static void prvMultipleSocketTxTask( void *pvParameters ) { uint32_t ulTxValue = 0; struct freertos_sockaddr xDestinationAddress; uint32_t ulIPAddress, ulFirstDestinationPortNumber, xPortNumber; xSocket_t xTxSocket; uint32_t ulSendCount[ selNUMBER_OF_SOCKETS ]; memset( ulSendCount, '\0', sizeof( ulSendCount ) ); /* The first destination port number is passed in as the task parameter. Other destination port numbers used are consecutive from this. */ ulFirstDestinationPortNumber = ( uint32_t ) pvParameters; /* Create the socket used to send to the sockets created by the Rx task. Let the IP stack select a port to bind to. */ xTxSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); FreeRTOS_bind( xTxSocket, NULL, sizeof( struct freertos_sockaddr ) ); /* The Rx and Tx tasks execute at the same priority so it is possible that the Tx task will fill up the send queue - set a Tx block time to ensure flow control is managed if this happens. */ FreeRTOS_setsockopt( xTxSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendBlockTime, sizeof( xSendBlockTime ) ); /* It is assumed that this task is not created until the network is up, so the IP address can be obtained immediately. Store the IP address being used in ulIPAddress. This is done so the socket can send to a different port on the same IP address. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); /* This test sends to itself, so data sent from here is received by a server socket on the same IP address. Setup the freertos_sockaddr structure with this nodes IP address. */ xDestinationAddress.sin_addr = ulIPAddress; /* Block for a short time to ensure the task implemented by the prvMultipleSocketRxTask() function has finished creating the Rx sockets. */ while( eTaskGetState( xRxTaskHandle ) != eSuspended ) { vTaskDelay( xSendBlockTime ); } vTaskResume( xRxTaskHandle ); for( ;; ) { /* Pseudo randomly select the destination port number from the range of valid destination port numbers. */ xPortNumber = ipconfigRAND32() % selNUMBER_OF_SOCKETS; ulSendCount[ xPortNumber ]++; xDestinationAddress.sin_port = ( uint16_t ) ( ulFirstDestinationPortNumber + xPortNumber ); xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port ); /* Send an incrementing value to the pseudo randomly selected port. */ FreeRTOS_sendto( xTxSocket, &ulTxValue, sizeof( ulTxValue ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) ); ulTxValue++; if( ulTxValue >= selMAX_TX_VALUE ) { /* Start over. */ ulTxValue = 0; /* As a sanity check that this demo is valid, ensure each socket has been used at least once. */ for( xPortNumber = 0; xPortNumber < selNUMBER_OF_SOCKETS; xPortNumber++ ) { if( ulSendCount[ xPortNumber ] == 0 ) { ulErrorOccurred = pdTRUE; } ulSendCount[ xPortNumber ] = 0; } /* Allow the Rx task to check it has received all the values. */ while( eTaskGetState( xRxTaskHandle ) != eSuspended ) { vTaskDelay( xSendBlockTime ); } vTaskResume( xRxTaskHandle ); /* Increment to show this task is still executing. */ ulTxCycles++; } /* Delay here because in the Windows simulator the MAC interrupt simulator delays, so network traffic cannot be received any faster than this. */ vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY << 2 ); } }
uint32_t FreeRTOS_gethostbyname( const uint8_t *pcHostName ) { static uint16_t usIdentifier = 0; struct freertos_sockaddr xAddress; static xSocket_t xDNSSocket = NULL; uint32_t ulIPAddress = 0UL; uint8_t *pucUDPPayloadBuffer; static uint32_t ulAddressLength; portBASE_TYPE xAttempt; int32_t lBytes; size_t xPayloadLength; const size_t xExpectedPayloadLength = sizeof( xDNSMessage_t ) + strlen( ( const char * const ) pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2; /* Two for the count of characters in the first subdomain part, and the string end byte */ if( xDNSSocket == NULL ) { xDNSSocket = prvCreateDNSSocket(); } if( xDNSSocket != NULL ) { /* Generate a unique identifier for this query. */ usIdentifier++; for( xAttempt = 0; xAttempt < dnsMAX_REQUEST_ATTEMPTS; xAttempt++ ) { /* Get a buffer. This uses a maximum delay, but the delay will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS so the return value still needs to be tested. */ pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xExpectedPayloadLength, portMAX_DELAY ); if( pucUDPPayloadBuffer != NULL ) { /* Create the message in the obtained buffer. */ xPayloadLength = prvCreateDNSMessage( pucUDPPayloadBuffer, pcHostName, usIdentifier ); iptraceSENDING_DNS_REQUEST(); /* Obtain the DNS server address. */ FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulIPAddress ); /* Send the DNS message. */ xAddress.sin_addr = ulIPAddress; xAddress.sin_port = dnsDNS_PORT; ulIPAddress = 0; if( FreeRTOS_sendto( xDNSSocket, pucUDPPayloadBuffer, xPayloadLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) != 0 ) { /* Wait for the reply. */ lBytes = FreeRTOS_recvfrom( xDNSSocket, &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xAddress, &ulAddressLength ); if( lBytes > 0 ) { /* The reply was received. Process it. */ ulIPAddress = prvParseDNSReply( pucUDPPayloadBuffer, usIdentifier ); /* Finished with the buffer. The zero copy interface is being used, so the buffer must be freed by the task. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); if( ulIPAddress != 0 ) { /* All done. */ break; } } } else { /* The message was not sent so the stack will not be releasing the zero copy - it must be released here. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); } } } } return ulIPAddress; }