From 9a452918d16082251eab1c52c9558b221508931d Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed, 2 Dec 2020 14:30:50 -0800 Subject: [PATCH] Add UDP demo running FreeRTOS+TCP (#425) * Add FreeRTOS+TCP UDP only demo. * Update folder name and remove old one * Update the network interface to be used. * Update headers * Update header * Header update and folder name correction * Remove WinPCap folder --- .../DemoTasks/CLI-commands.c | 630 ++++++++++++++++++ .../DemoTasks/SimpleClientAndServer.c | 352 ++++++++++ .../DemoTasks/TwoEchoClients.c | 397 +++++++++++ .../DemoTasks/UDPCommandServer.c | 207 ++++++ .../DemoTasks/include/SimpleClientAndServer.h | 32 + .../DemoTasks/include/TwoEchoClients.h | 37 + .../DemoTasks/include/UDPCommandInterpreter.h | 32 + .../FreeRTOSConfig.h | 217 ++++++ .../FreeRTOSIPConfig.h | 306 +++++++++ .../FreeRTOS_Plus_UDP_with_CLI.sln | 20 + .../FreeRTOS_Plus_UDP_with_CLI.suo | Bin 0 -> 195584 bytes .../README_FIRST.txt | 11 + .../Run-time-stats-utils.c | 89 +++ .../WIN32.vcxproj | 195 ++++++ .../WIN32.vcxproj.filters | 212 ++++++ .../WIN32.vcxproj.user | 3 + .../main.c | 365 ++++++++++ .../ReadMe.txt | 4 - .../See also FreeRTOS+TCP.url | 5 - 19 files changed, 3105 insertions(+), 9 deletions(-) create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/CLI-commands.c create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/SimpleClientAndServer.c create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/TwoEchoClients.c create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/UDPCommandServer.c create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/SimpleClientAndServer.h create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/TwoEchoClients.h create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/UDPCommandInterpreter.h create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOSConfig.h create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOSIPConfig.h create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOS_Plus_UDP_with_CLI.sln create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOS_Plus_UDP_with_CLI.suo create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/README_FIRST.txt create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/Run-time-stats-utils.c create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj.filters create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj.user create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/main.c delete mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/ReadMe.txt delete mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/See also FreeRTOS+TCP.url diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/CLI-commands.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/CLI-commands.c new file mode 100644 index 0000000000..8ab0a91413 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/CLI-commands.c @@ -0,0 +1,630 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + /****************************************************************************** + * + * See the following URL for information on the commands defined in this file: + * http://localhost/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Ethernet_Related_CLI_Commands.shtml + * + ******************************************************************************/ + + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Standard includes. */ +#include +#include +#include + +/* FreeRTOS+CLI includes. */ +#include "FreeRTOS_CLI.h" + +/* FreeRTOS+UDP includes, just to make the stats available to the CLI +commands. */ +#include "FreeRTOS_UDP_IP.h" +#include "FreeRTOS_Sockets.h" + +#ifndef configINCLUDE_TRACE_RELATED_CLI_COMMANDS + #define configINCLUDE_TRACE_RELATED_CLI_COMMANDS 0 +#endif + + +/* + * Implements the run-time-stats command. + */ +static portBASE_TYPE prvTaskStatsCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ); + +/* + * Implements the task-stats command. + */ +static portBASE_TYPE prvRunTimeStatsCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ); + +/* + * Implements the echo-three-parameters command. + */ +static portBASE_TYPE prvThreeParameterEchoCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ); + +/* + * Implements the echo-parameters command. + */ +static portBASE_TYPE prvParameterEchoCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ); + +/* + * Defines a command that prints out IP address information. + */ +static portBASE_TYPE prvDisplayIPConfig( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ); + +/* + * Defines a command that prints out the gathered demo debug stats. + */ +static portBASE_TYPE prvDisplayIPDebugStats( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ); + +/* + * Defines a command that sends an ICMP ping request to an IP address. + */ +static portBASE_TYPE prvPingCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ); + +/* + * Implements the "trace start" and "trace stop" commands; + */ +#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 + static portBASE_TYPE prvStartStopTraceCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ); +#endif + +/* Structure that defines the "ip-config" command line command. */ +static const CLI_Command_Definition_t xIPConfig = +{ + ( const int8_t * const ) "ip-config", + ( const int8_t * const ) "ip-config:\r\n Displays IP address configuration\r\n\r\n", + prvDisplayIPConfig, + 0 +}; + +#if configINCLUDE_DEMO_DEBUG_STATS != 0 + /* Structure that defines the "ip-debug-stats" command line command. */ + static const CLI_Command_Definition_t xIPDebugStats = + { + ( const int8_t * const ) "ip-debug-stats", /* The command string to type. */ + ( const int8_t * const ) "ip-debug-stats:\r\n Shows some IP stack stats useful for debug - an example only.\r\n\r\n", + prvDisplayIPDebugStats, /* The function to run. */ + 0 /* No parameters are expected. */ + }; +#endif /* configINCLUDE_DEMO_DEBUG_STATS */ + +/* Structure that defines the "run-time-stats" command line command. This +generates a table that shows how much run time each task has */ +static const CLI_Command_Definition_t xRunTimeStats = +{ + ( const int8_t * const ) "run-time-stats", /* The command string to type. */ + ( const int8_t * const ) "run-time-stats:\r\n Displays a table showing how much processing time each FreeRTOS task has used\r\n\r\n", + prvRunTimeStatsCommand, /* The function to run. */ + 0 /* No parameters are expected. */ +}; + +/* Structure that defines the "task-stats" command line command. This generates +a table that gives information on each task in the system. */ +static const CLI_Command_Definition_t xTaskStats = +{ + ( const int8_t * const ) "task-stats", /* The command string to type. */ + ( const int8_t * const ) "task-stats:\r\n Displays a table showing the state of each FreeRTOS task\r\n\r\n", + prvTaskStatsCommand, /* The function to run. */ + 0 /* No parameters are expected. */ +}; + +/* Structure that defines the "echo_3_parameters" command line command. This +takes exactly three parameters that the command simply echos back one at a +time. */ +static const CLI_Command_Definition_t xThreeParameterEcho = +{ + ( const int8_t * const ) "echo-3-parameters", + ( const int8_t * const ) "echo-3-parameters :\r\n Expects three parameters, echos each in turn\r\n\r\n", + prvThreeParameterEchoCommand, /* The function to run. */ + 3 /* Three parameters are expected, which can take any value. */ +}; + +/* Structure that defines the "echo_parameters" command line command. This +takes a variable number of parameters that the command simply echos back one at +a time. */ +static const CLI_Command_Definition_t xParameterEcho = +{ + ( const int8_t * const ) "echo-parameters", + ( const int8_t * const ) "echo-parameters <...>:\r\n Take variable number of parameters, echos each in turn\r\n\r\n", + prvParameterEchoCommand, /* The function to run. */ + -1 /* The user can enter any number of commands. */ +}; + +#if ipconfigSUPPORT_OUTGOING_PINGS == 1 + + /* Structure that defines the "ping" command line command. This takes an IP + address or host name and (optionally) the number of bytes to ping as + parameters. */ + static const CLI_Command_Definition_t xPing = + { + ( const int8_t * const ) "ping", + ( const int8_t * const ) "ping :\r\n for example, ping 192.168.0.3 8, or ping www.example.com\r\n\r\n", + prvPingCommand, /* The function to run. */ + -1 /* Ping can take either one or two parameter, so the number of parameters has to be determined by the ping command implementation. */ + }; + +#endif /* ipconfigSUPPORT_OUTGOING_PINGS */ + +#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 + /* Structure that defines the "trace" command line command. This takes a single + parameter, which can be either "start" or "stop". */ + static const CLI_Command_Definition_t xStartStopTrace = + { + ( const int8_t * const ) "trace", + ( const int8_t * const ) "trace [start | stop]:\r\n Starts or stops a trace recording for viewing in FreeRTOS+Trace\r\n\r\n", + prvStartStopTraceCommand, /* The function to run. */ + 1 /* One parameter is expected. Valid values are "start" and "stop". */ + }; +#endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */ + +/*-----------------------------------------------------------*/ + +void vRegisterCLICommands( void ) +{ + /* Register all the command line commands defined immediately above. */ + FreeRTOS_CLIRegisterCommand( &xTaskStats ); + FreeRTOS_CLIRegisterCommand( &xRunTimeStats ); + FreeRTOS_CLIRegisterCommand( &xThreeParameterEcho ); + FreeRTOS_CLIRegisterCommand( &xParameterEcho ); + FreeRTOS_CLIRegisterCommand( &xIPConfig ); + + #if ipconfigSUPPORT_OUTGOING_PINGS == 1 + { + FreeRTOS_CLIRegisterCommand( &xPing ); + } + #endif /* ipconfigSUPPORT_OUTGOING_PINGS */ + + #if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 + FreeRTOS_CLIRegisterCommand( & xStartStopTrace ); + #endif +} +/*-----------------------------------------------------------*/ + +static portBASE_TYPE prvTaskStatsCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ) +{ +const int8_t *const pcHeader = ( int8_t * ) "Task State Priority Stack #\r\n************************************************\r\n"; + + /* 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 ); + + /* Generate a table of task stats. */ + strcpy( ( char * ) pcWriteBuffer, ( char * ) pcHeader ); + vTaskList( pcWriteBuffer + strlen( ( char * ) pcHeader ) ); + + /* There is no more data to return after this single string, so return + pdFALSE. */ + return pdFALSE; +} +/*-----------------------------------------------------------*/ + +static portBASE_TYPE prvRunTimeStatsCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ) +{ +const int8_t * const pcHeader = ( int8_t * ) "Task Abs Time % Time\r\n****************************************\r\n"; + + /* 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 ); + + /* Generate a table of task stats. */ + strcpy( ( char * ) pcWriteBuffer, ( char * ) pcHeader ); + + #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + vTaskGetRunTimeStats( pcWriteBuffer + strlen( ( char * ) pcHeader ) ); + #endif + + /* There is no more data to return after this single string, so return + pdFALSE. */ + return pdFALSE; +} +/*-----------------------------------------------------------*/ + +static portBASE_TYPE prvThreeParameterEchoCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ) +{ +int8_t *pcParameter; +portBASE_TYPE xParameterStringLength, xReturn; +static portBASE_TYPE lParameterNumber = 0; + + /* 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 ); + + if( lParameterNumber == 0 ) + { + /* The first time the function is called after the command has been + entered just a header string is returned. */ + sprintf( ( char * ) pcWriteBuffer, "The three parameters were:\r\n" ); + + /* Next time the function is called the first parameter will be echoed + back. */ + lParameterNumber = 1L; + + /* There is more data to be returned as no parameters have been echoed + back yet. */ + xReturn = pdPASS; + } + else + { + /* Obtain the parameter string. */ + pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter + ( + pcCommandString, /* The command string itself. */ + lParameterNumber, /* Return the next parameter. */ + &xParameterStringLength /* Store the parameter string length. */ + ); + + /* Sanity check something was returned. */ + configASSERT( pcParameter ); + + /* Return the parameter string. */ + memset( pcWriteBuffer, 0x00, xWriteBufferLen ); + sprintf( ( char * ) pcWriteBuffer, "%d: ", ( int ) lParameterNumber ); + strncat( ( char * ) pcWriteBuffer, ( const char * ) pcParameter, xParameterStringLength ); + strncat( ( char * ) pcWriteBuffer, "\r\n", strlen( "\r\n" ) ); + + /* If this is the last of the three parameters then there are no more + strings to return after this one. */ + if( lParameterNumber == 3L ) + { + /* If this is the last of the three parameters then there are no more + strings to return after this one. */ + xReturn = pdFALSE; + lParameterNumber = 0L; + } + else + { + /* There are more parameters to return after this one. */ + xReturn = pdTRUE; + lParameterNumber++; + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static portBASE_TYPE prvParameterEchoCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ) +{ +int8_t *pcParameter; +portBASE_TYPE xParameterStringLength, xReturn; +static portBASE_TYPE lParameterNumber = 0; + + /* 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 ); + + if( lParameterNumber == 0 ) + { + /* The first time the function is called after the command has been + entered just a header string is returned. */ + sprintf( ( char * ) pcWriteBuffer, "The parameters were:\r\n" ); + + /* Next time the function is called the first parameter will be echoed + back. */ + lParameterNumber = 1L; + + /* There is more data to be returned as no parameters have been echoed + back yet. */ + xReturn = pdPASS; + } + else + { + /* Obtain the parameter string. */ + pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter + ( + pcCommandString, /* The command string itself. */ + lParameterNumber, /* Return the next parameter. */ + &xParameterStringLength /* Store the parameter string length. */ + ); + + if( pcParameter != NULL ) + { + /* Return the parameter string. */ + memset( pcWriteBuffer, 0x00, xWriteBufferLen ); + sprintf( ( char * ) pcWriteBuffer, "%d: ", ( int ) lParameterNumber ); + strncat( ( char * ) pcWriteBuffer, ( const char * ) pcParameter, xParameterStringLength ); + strncat( ( char * ) pcWriteBuffer, "\r\n", strlen( "\r\n" ) ); + + /* There might be more parameters to return after this one. */ + xReturn = pdTRUE; + lParameterNumber++; + } + else + { + /* No more parameters were found. Make sure the write buffer does + not contain a valid string. */ + pcWriteBuffer[ 0 ] = 0x00; + + /* No more data to return. */ + xReturn = pdFALSE; + + /* Start over the next time this command is executed. */ + lParameterNumber = 0; + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ipconfigSUPPORT_OUTGOING_PINGS == 1 + + static portBASE_TYPE prvPingCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ) + { + int8_t * pcParameter; + portBASE_TYPE lParameterStringLength, xReturn; + uint32_t ulIPAddress, ulBytesToPing; + const uint32_t ulDefaultBytesToPing = 8UL; + int8_t cBuffer[ 16 ]; + + /* 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 ); + + /* Start with an empty string. */ + pcWriteBuffer[ 0 ] = 0x00; + + /* Obtain the number of bytes to ping. */ + pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter + ( + pcCommandString, /* The command string itself. */ + 2, /* Return the second parameter. */ + &lParameterStringLength /* Store the parameter string length. */ + ); + + if( pcParameter == NULL ) + { + /* The number of bytes was not specified, so default it. */ + ulBytesToPing = ulDefaultBytesToPing; + } + else + { + ulBytesToPing = atol( ( const char * ) pcParameter ); + } + + /* Obtain the IP address string. */ + pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter + ( + pcCommandString, /* The command string itself. */ + 1, /* Return the first parameter. */ + &lParameterStringLength /* Store the parameter string length. */ + ); + + /* Sanity check something was returned. */ + configASSERT( pcParameter ); + + /* Attempt to obtain the IP address. If the first character is not a + digit, assume the host name has been passed in. */ + if( ( *pcParameter >= '0' ) && ( *pcParameter <= '9' ) ) + { + ulIPAddress = FreeRTOS_inet_addr( ( const uint8_t * ) pcParameter ); + } + else + { + /* Terminate the host name. */ + pcParameter[ lParameterStringLength ] = 0x00; + + /* Attempt to resolve host. */ + ulIPAddress = FreeRTOS_gethostbyname( ( uint8_t * ) pcParameter ); + } + + /* Convert IP address, which may have come from a DNS lookup, to string. */ + FreeRTOS_inet_ntoa( ulIPAddress, ( char * ) cBuffer ); + + if( ulIPAddress != 0 ) + { + xReturn = FreeRTOS_SendPingRequest( ulIPAddress, ( uint16_t ) ulBytesToPing, portMAX_DELAY ); + } + else + { + xReturn = pdFALSE; + } + + if( xReturn == pdFALSE ) + { + sprintf( ( char * ) pcWriteBuffer, "%s", "Could not send ping request\r\n" ); + } + else + { + sprintf( ( char * ) pcWriteBuffer, "Ping sent to %s with identifier %d\r\n", cBuffer, xReturn ); + } + + return pdFALSE; + } + /*-----------------------------------------------------------*/ + +#endif /* ipconfigSUPPORT_OUTGOING_PINGS */ + +#if configINCLUDE_DEMO_DEBUG_STATS != 0 + + static portBASE_TYPE prvDisplayIPDebugStats( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ) + { + static portBASE_TYPE xIndex = -1; + extern xExampleDebugStatEntry_t xIPTraceValues[]; + portBASE_TYPE xReturn; + + /* 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 ); + + xIndex++; + + if( xIndex < xExampleDebugStatEntries() ) + { + sprintf( ( char * ) pcWriteBuffer, "%s %d\r\n", ( char * ) xIPTraceValues[ xIndex ].pucDescription, ( int ) xIPTraceValues[ xIndex ].ulData ); + xReturn = pdPASS; + } + else + { + /* Reset the index for the next time it is called. */ + xIndex = -1; + + /* Ensure nothing remains in the write buffer. */ + pcWriteBuffer[ 0 ] = 0x00; + xReturn = pdFALSE; + } + + return xReturn; + } + /*-----------------------------------------------------------*/ + +#endif /* configINCLUDE_DEMO_DEBUG_STATS */ + +static portBASE_TYPE prvDisplayIPConfig( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ) +{ +static portBASE_TYPE xIndex = 0; +portBASE_TYPE 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( ( char * ) pcWriteBuffer, "\r\nIP address " ); + xReturn = pdTRUE; + xIndex++; + break; + + case 1 : + FreeRTOS_GetAddressConfiguration( NULL, &ulAddress, NULL, NULL ); + sprintf( ( char * ) pcWriteBuffer, "\r\nNet mask " ); + xReturn = pdTRUE; + xIndex++; + break; + + case 2 : + FreeRTOS_GetAddressConfiguration( NULL, NULL, &ulAddress, NULL ); + sprintf( ( char * ) pcWriteBuffer, "\r\nGateway address " ); + xReturn = pdTRUE; + xIndex++; + break; + + case 3 : + FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulAddress ); + sprintf( ( char * ) pcWriteBuffer, "\r\nDNS server address " ); + xReturn = pdTRUE; + xIndex++; + break; + + default : + ulAddress = 0; + sprintf( ( char * ) pcWriteBuffer, "\r\n\r\n" ); + xReturn = pdFALSE; + xIndex = 0; + break; + } + + if( ulAddress != 0 ) + { + FreeRTOS_inet_ntoa( ulAddress, ( ( char * ) &( pcWriteBuffer[ strlen( ( char * ) pcWriteBuffer ) ] ) ) ); + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 + + static portBASE_TYPE prvStartStopTraceCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ) + { + int8_t *pcParameter; + portBASE_TYPE lParameterStringLength; + + /* 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 ); + + /* Obtain the parameter string. */ + pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter + ( + pcCommandString, /* The command string itself. */ + 1, /* Return the first parameter. */ + &lParameterStringLength /* Store the parameter string length. */ + ); + + /* Sanity check something was returned. */ + configASSERT( pcParameter ); + + /* There are only two valid parameter values. */ + if( strncmp( ( const char * ) pcParameter, "start", strlen( "start" ) ) == 0 ) + { + /* Start or restart the trace. */ + vTraceStop(); + vTraceClear(); + vTraceStart(); + + sprintf( ( char * ) pcWriteBuffer, "Trace recording (re)started.\r\n" ); + } + else if( strncmp( ( const char * ) pcParameter, "stop", strlen( "stop" ) ) == 0 ) + { + /* End the trace, if one is running. */ + vTraceStop(); + sprintf( ( char * ) pcWriteBuffer, "Stopping trace recording.\r\n" ); + } + else + { + sprintf( ( char * ) pcWriteBuffer, "Valid parameters are 'start' and 'stop'.\r\n" ); + } + + /* There is no more data to return after this single string, so return + pdFALSE. */ + return pdFALSE; + } + +#endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/SimpleClientAndServer.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/SimpleClientAndServer.c new file mode 100644 index 0000000000..c8d2abdc7d --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/SimpleClientAndServer.c @@ -0,0 +1,352 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* Standard includes. */ +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* FreeRTOS+UDP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" + +#define simpTINY_DELAY ( ( portTickType ) 2 ) + +/* + * Uses a socket to send data without using the zero copy option. + * prvSimpleServerTask() will receive the data. + */ +static void prvSimpleClientTask( void *pvParameters ); + +/* + * Uses a socket to receive the data sent by the prvSimpleClientTask() task. + * Does not use the zero copy option. + */ +static void prvSimpleServerTask( void *pvParameters ); + +/* + * Uses a socket to send data using the zero copy option. + * prvSimpleZeroCopyServerTask() will receive the data. + */ +static void prvSimpleZeroCopyUDPClientTask( void *pvParameters ); + +/* + * Uses a socket to receive the data sent by the prvSimpleZeroCopyUDPClientTask() + * task. Uses the zero copy option. + */ +static void prvSimpleZeroCopyServerTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulPort, unsigned portBASE_TYPE uxPriority ) +{ + /* Create the client and server tasks that do not use the zero copy + interface. */ + xTaskCreate( prvSimpleClientTask, "SimpCpyClnt", usStackSize, ( void * ) ulPort, uxPriority, NULL ); + xTaskCreate( prvSimpleServerTask, "SimpCpySrv", usStackSize, ( void * ) ulPort, uxPriority + 1, NULL ); + + /* Create the client and server tasks that do use the zero copy interface. */ + xTaskCreate( prvSimpleZeroCopyUDPClientTask, "SimpZCpyClnt", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority, NULL ); + xTaskCreate( prvSimpleZeroCopyServerTask, "SimpZCpySrv", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority + 1, NULL ); +} +/*-----------------------------------------------------------*/ + +static void prvSimpleClientTask( void *pvParameters ) +{ +Socket_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 prvSimpleServerTask( void *pvParameters ) +{ +long lBytes; +uint8_t cReceivedString[ 60 ]; +struct freertos_sockaddr xClient, xBindAddress; +uint32_t xClientLength = sizeof( xClient ); +Socket_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. 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. */ + 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( ;; ) + { + /* Zero out the receive array so there is NULL at the end of the string + when it is printed out. */ + memset( cReceivedString, 0x00, sizeof( cReceivedString ) ); + + /* Receive data on the socket. ulFlags is zero, so the zero copy option + is not set and the received data is copied into the buffer pointed to by + cReceivedString. By default the block time is portMAX_DELAY. + xClientLength is not actually used by FreeRTOS_recvfrom(), but is set + appropriately in case future versions do use it. */ + lBytes = FreeRTOS_recvfrom( xListeningSocket, cReceivedString, sizeof( cReceivedString ), 0, &xClient, &xClientLength ); + + /* Print the received characters. */ + if( lBytes > 0 ) + { + FreeRTOS_debug_printf( ( ( char * ) cReceivedString ) ); + } + + /* Error check. */ + configASSERT( lBytes == ( portBASE_TYPE ) strlen( ( const char * ) cReceivedString ) ); + } +} +/*-----------------------------------------------------------*/ + +static void prvSimpleZeroCopyUDPClientTask( void *pvParameters ) +{ +Socket_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 ); + } +} +/*-----------------------------------------------------------*/ + +static void prvSimpleZeroCopyServerTask( void *pvParameters ) +{ +int32_t lBytes; +uint8_t *pucUDPPayloadBuffer; +struct freertos_sockaddr xClient, xBindAddress; +uint32_t xClientLength = sizeof( xClient ), ulIPAddress; +Socket_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 ) + { + FreeRTOS_debug_printf( ( ( char * ) pucUDPPayloadBuffer ) ); + } + + if( lBytes >= 0 ) + { + /* The buffer *must* be freed once it is no longer needed. */ + FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer ); + } + } +} + diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/TwoEchoClients.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/TwoEchoClients.c new file mode 100644 index 0000000000..401f411e87 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/TwoEchoClients.c @@ -0,0 +1,397 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +/****************************************************************************** + * + * See the following web page for essential TwoEchoClient.c usage and + * configuration details: + * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Common_Echo_Clients.shtml + * + ******************************************************************************/ + + +/* Standard includes. */ +#include +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* FreeRTOS+UDP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" + +/* Small delay used between attempts to obtain a zero copy buffer. */ +#define echoTINY_DELAY ( ( portTickType ) 2 ) + +/* The echo tasks create a socket, send out a number of echo requests +(listening for each echo reply), then close the socket again before +starting over. This delay is used between each iteration to ensure the +network does not get too congested. The delay is shorter when the Windows +simulator is used because simulated time is slower than real time. */ +#ifdef _WINDOWS_ + #define echoLOOP_DELAY ( ( portTickType ) 10 / portTICK_RATE_MS ) +#else + #define echoLOOP_DELAY ( ( portTickType ) 150 / portTICK_RATE_MS ) +#endif /* _WINDOWS_ */ + +#if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 + /* When the trace recorder code is included user events are generated to + mark the sending and receiving of the echoed data (only in the zero copy + task. */ + #define echoMARK_SEND_IN_TRACE_BUFFER( x ) vTraceUserEvent( x ) + traceLabel xZeroCopySendEvent, xZeroCopyReceiveEvent; + +#else + /* When the trace recorder code is not included just #define away the call + to post the user event. */ + #define echoMARK_SEND_IN_TRACE_BUFFER( x ) + #define xZeroCopySendEvent 0 + #define xZeroCopyReceiveEvent 0 +#endif + +/* The echo server is assumed to be on port 7, which is the standard echo +protocol port. */ +#define echoECHO_PORT ( 8080 ) + +/* + * Uses a socket to send data to, then receive data from, the standard echo + * port number 7. prvEchoClientTask() uses the standard interface. + * prvZeroCopyEchoClientTask() uses the zero copy interface. + */ +static void prvEchoClientTask( void *pvParameters ); +static void prvZeroCopyEchoClientTask( void *pvParameters ); + +/* The receive timeout is set shorter when the windows simulator is used +because simulated time is slower than real time. */ +#ifdef _WINDOWS_ + const portTickType xReceiveTimeOut = 500 / portTICK_RATE_MS; +#else + const portTickType xReceiveTimeOut = 1000 / portTICK_RATE_MS; +#endif + +/*-----------------------------------------------------------*/ + +void vStartEchoClientTasks( uint16_t usTaskStackSize, unsigned portBASE_TYPE uxTaskPriority ) +{ + /* Create the echo client task that does not use the zero copy interface. */ + xTaskCreate( prvEchoClientTask, /* The function that implements the task. */ + ( const signed char * const ) "Echo0", /* Just a text name for the task to aid debugging. */ + usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ + NULL, /* The task parameter, not used in this case. */ + uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ + NULL ); /* The task handle is not used. */ + + /* Create the echo client task that does use the zero copy interface. */ + xTaskCreate( prvZeroCopyEchoClientTask, /* The function that implements the task. */ + ( const signed char * const ) "Echo1", /* Just a text name for the task to aid debugging. */ + usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ + NULL, /* The task parameter, not used in this case. */ + uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ + NULL ); /* The task handle is not used. */ +} +/*-----------------------------------------------------------*/ + +static void prvEchoClientTask( void *pvParameters ) +{ +Socket_t xSocket; +struct freertos_sockaddr xEchoServerAddress; +int8_t cTxString[ 25 ], cRxString[ 25 ]; /* Make sure the stack is large enough to hold these. Turn on stack overflow checking during debug to be sure. */ +int32_t lLoopCount = 0UL; +int32_t lReturned; +const int32_t lMaxLoopCount = 50; +volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL; +uint32_t xAddressLength = sizeof( xEchoServerAddress ); + + /* Remove compiler warning about unused parameters. */ + ( void ) pvParameters; + + /* Echo requests are sent to the echo server. The address of the echo + server is configured by the constants configECHO_SERVER_ADDR0 to + configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */ + xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT ); + xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, + configECHO_SERVER_ADDR1, + configECHO_SERVER_ADDR2, + configECHO_SERVER_ADDR3 ); + + for( ;; ) + { + /* Create a socket. */ + xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); + configASSERT( xSocket != FREERTOS_INVALID_SOCKET ); + + /* Set a time out so a missing reply does not cause the task to block + indefinitely. */ + FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); + + /* Send a number of echo requests. */ + for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ ) + { + /* Create the string that is sent to the echo server. */ + sprintf( ( char * ) cTxString, "Message number %u\r\n", ulTxCount ); + + /* Send the string to the socket. ulFlags is set to 0, so the zero + copy interface is not used. That means the data from cTxString is + copied into a network buffer inside FreeRTOS_sendto(), and cTxString + can be reused as soon as FreeRTOS_sendto() has returned. 1 is added + to ensure the NULL string terminator is sent as part of the message. */ + lReturned = FreeRTOS_sendto( xSocket, /* The socket being sent to. */ + ( void * ) cTxString, /* The data being sent. */ + strlen( ( const char * ) cTxString ) + 1, /* The length of the data being sent. */ + 0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */ + &xEchoServerAddress, /* The destination address. */ + sizeof( xEchoServerAddress ) ); + + if( lReturned == 0 ) + { + /* The send operation failed. */ + } + else + { + /* The send was successful. */ + FreeRTOS_debug_printf( ( "[Echo Client] Data sent... \r\n" ) ); + } + + /* Keep a count of how many echo requests have been transmitted so + it can be compared to the number of echo replies received. It would + be expected to loose at least one to an ARP message the first time + the connection is created. */ + ulTxCount++; + + /* Receive data echoed back to the socket. ulFlags is zero, so the + zero copy option is not being used and the received data will be + copied into the buffer pointed to by cRxString. xAddressLength is + not actually used (at the time of writing this comment, anyway) by + FreeRTOS_recvfrom(), but is set appropriately in case future + versions do use it. */ + + memset( ( void * ) cRxString, 0x00, sizeof( cRxString ) ); + lReturned = FreeRTOS_recvfrom( xSocket, /* The socket being received from. */ + cRxString, /* The buffer into which the received data will be written. */ + sizeof( cRxString ), /* The size of the buffer provided to receive the data. */ + 0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */ + &xEchoServerAddress, /* The address from where the data was sent (the source address). */ + &xAddressLength ); + + if( lReturned > 0 ) + { + /* Compare the transmitted string to the received string. */ + if( strcmp( ( char * ) cRxString, ( char * ) cTxString ) == 0 ) + { + /* The echo reply was received without error. */ + ulRxCount++; + FreeRTOS_debug_printf( ( "[Echo Client] Data was received correctly.\r\n" ) ); + } + else + { + FreeRTOS_debug_printf( ( "[Echo Client] Data received was erreneous.\r\n" ) ); + } + } + else + { + FreeRTOS_debug_printf( ( "[Echo Client] Data was not received\r\n" ) ); + } + } + + /* Pause for a short while to ensure the network is not too + congested. */ + vTaskDelay( echoLOOP_DELAY ); + + /* Close this socket before looping back to create another. */ + FreeRTOS_closesocket( xSocket ); + } +} +/*-----------------------------------------------------------*/ + +static void prvZeroCopyEchoClientTask( void *pvParameters ) +{ +Socket_t xSocket; +struct freertos_sockaddr xEchoServerAddress; +static int8_t cTxString[ 40 ]; +int32_t lLoopCount = 0UL; +volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL; +uint32_t xAddressLength = sizeof( xEchoServerAddress ); +int32_t lReturned; +uint8_t *pucUDPPayloadBuffer; + +const int32_t lMaxLoopCount = 50; +const uint8_t * const pucStringToSend = ( const uint8_t * const ) "Zero copy message number"; +/* The buffer is large enough to hold the string, a number, and the string terminator. */ +const size_t xBufferLength = strlen( ( char * ) pucStringToSend ) + 15; + + #if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 + { + /* When the trace recorder code is included user events are generated to + mark the sending and receiving of the echoed data (only in the zero copy + task). */ + xZeroCopySendEvent = xTraceOpenLabel( "ZeroCopyTx" ); + xZeroCopyReceiveEvent = xTraceOpenLabel( "ZeroCopyRx" ); + } + #endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS */ + + /* Remove compiler warning about unused parameters. */ + ( void ) pvParameters; + + /* Delay for a little while to ensure the task is out of synch with the + other echo task implemented above. */ + vTaskDelay( echoLOOP_DELAY >> 1 ); + + /* Echo requests are sent to the echo server. The address of the echo + server is configured by the constants configECHO_SERVER_ADDR0 to + configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */ + xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT ); + xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, + configECHO_SERVER_ADDR1, + configECHO_SERVER_ADDR2, + configECHO_SERVER_ADDR3 ); + + for( ;; ) + { + /* Create a socket. */ + xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); + configASSERT( xSocket != FREERTOS_INVALID_SOCKET ); + + /* Set a time out so a missing reply does not cause the task to block + indefinitely. */ + FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); + + /* Send a number of echo requests. */ + for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ ) + { + /* 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 by reference into the FreeRTOS_sendto() function. First + obtain a buffer of adequate size from the IP stack. Although a max + delay is used, the actual delay will be capped to + ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence the test to ensure a buffer + was actually obtained. */ + pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xBufferLength, portMAX_DELAY ); + + if( pucUDPPayloadBuffer != NULL ) + { + /* A buffer was successfully obtained. Create the string that is + sent to the echo server. Note the string is written directly + into the buffer obtained from the IP stack. */ + sprintf( ( char * ) pucUDPPayloadBuffer, "%s %u\r\n", ( const char * ) "Zero copy message number", ulTxCount ); + + /* Also copy the string into a local buffer so it can be compared + with the string that is later received back from the echo server. */ + strcpy( ( char * ) cTxString, ( char * ) pucUDPPayloadBuffer ); + + /* 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. */ + echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopySendEvent ); + lReturned = FreeRTOS_sendto( xSocket, /* The socket being sent to. */ + ( void * ) pucUDPPayloadBuffer, /* The buffer being passed into the IP stack. */ + strlen( ( const char * ) cTxString ) + 1, /* The length of the data being sent. Plus 1 to ensure the null terminator is part of the data. */ + FREERTOS_ZERO_COPY, /* ulFlags with the zero copy bit is set. */ + &xEchoServerAddress, /* Where the data is being sent. */ + sizeof( xEchoServerAddress ) ); + + 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 to receive from the socket below once the + buffer has been returned to the stack. */ + 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 to receive from + the socket below. */ + FreeRTOS_debug_printf( ( "[Zero Copy] Data sent... \r\n" ) ); + } + + /* Keep a count of how many echo requests have been transmitted + so it can be compared to the number of echo replies received. + It would be expected to loose at least one to an ARP message the + first time the connection is created. */ + ulTxCount++; + + /* 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 receive block time is + portMAX_DELAY. */ + echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopyReceiveEvent ); + lReturned = FreeRTOS_recvfrom( xSocket, /* The socket to receive from. */ + ( void * ) &pucUDPPayloadBuffer, /* pucUDPPayloadBuffer will be set to point to the buffer that already contains the received data. */ + 0, /* Ignored because the zero copy interface is being used. */ + FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */ + &xEchoServerAddress, /* The address from which the data was sent. */ + &xAddressLength ); + + if( lReturned > 0 ) + { + /* Compare the string sent to the echo server with the string + received back from the echo server. */ + if( strcmp( ( char * ) pucUDPPayloadBuffer, ( char * ) cTxString ) == 0 ) + { + /* The strings matched. */ + ulRxCount++; + FreeRTOS_debug_printf( ( "[Zero Copy] Data was received correctly.\r\n" ) ); + } + else + { + FreeRTOS_debug_printf( ( "[Zero Copy] Data received was erreneous.\r\n" ) ); + } + + /* The buffer that contains the data passed out of the stack + *must* be returned to the stack. */ + FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer ); + } + else + { + FreeRTOS_debug_printf( ( "[Zero Copy] Data was not received\r\n" ) ); + } + } + } + + /* Pause for a short while to ensure the network is not too + congested. */ + vTaskDelay( echoLOOP_DELAY ); + + /* Close this socket before looping back to create another. */ + FreeRTOS_closesocket( xSocket ); + } +} +/*-----------------------------------------------------------*/ + diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/UDPCommandServer.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/UDPCommandServer.c new file mode 100644 index 0000000000..fc353dfdad --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/UDPCommandServer.c @@ -0,0 +1,207 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* Standard includes. */ +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* FreeRTOS+CLI includes. */ +#include "FreeRTOS_CLI.h" + +/* FreeRTOS+UDP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" + +/* Demo app includes. */ +#include "UDPCommandInterpreter.h" + +/* Dimensions the buffer into which input characters are placed. */ +#define cmdMAX_INPUT_SIZE 60 + +/* Dimensions the buffer into which string outputs can be placed. */ +#define cmdMAX_OUTPUT_SIZE 1024 + +/* Dimensions the buffer passed to the recvfrom() call. */ +#define cmdSOCKET_INPUT_BUFFER_SIZE 60 + +/* + * The task that runs FreeRTOS+CLI. + */ +void vUDPCommandInterpreterTask( void *pvParameters ); + +/* + * Open and configure the UDP socket. + */ +static Socket_t prvOpenUDPServerSocket( uint16_t usPort ); + +/*-----------------------------------------------------------*/ + +void vStartUDPCommandInterpreterTask( uint16_t usStackSize, uint32_t ulPort, unsigned portBASE_TYPE uxPriority ) +{ + xTaskCreate( vUDPCommandInterpreterTask, ( signed char * ) "CLI", usStackSize, ( void * ) ulPort, uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +/* + * Task that provides the input and output for the FreeRTOS+CLI command + * interpreter. In this case a UDP port is used. See the URL in the comments + * within main.c for the location of the online documentation. + */ +void vUDPCommandInterpreterTask( void *pvParameters ) +{ +long lBytes, lByte; +signed char cInChar, cInputIndex = 0; +static signed char cInputString[ cmdMAX_INPUT_SIZE ], cOutputString[ cmdMAX_OUTPUT_SIZE ], cLocalBuffer[ cmdSOCKET_INPUT_BUFFER_SIZE ]; +portBASE_TYPE xMoreDataToFollow; +struct freertos_sockaddr xClient; +socklen_t xClientAddressLength = 0; /* This is required as a parameter to maintain the sendto() Berkeley sockets API - but it is not actually used so can take any value. */ +Socket_t xSocket; +extern const uint8_t ucIPAddress[ 4 ]; +extern const uint8_t ucMACAddress[ 6 ]; + + /* Just to prevent compiler warnings. */ + ( void ) pvParameters; + + /* Attempt to open the socket. The port number is passed in the task + parameter. The strange casting is to remove compiler warnings on 32-bit + machines. */ + xSocket = prvOpenUDPServerSocket( ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL ); + + if( xSocket != FREERTOS_INVALID_SOCKET ) + { + for( ;; ) + { + /* Wait for incoming data on the opened socket. */ + lBytes = FreeRTOS_recvfrom( xSocket, ( void * ) cLocalBuffer, sizeof( cLocalBuffer ), 0, &xClient, &xClientAddressLength ); + + if( lBytes != FREERTOS_SOCKET_ERROR ) + { + /* Process each received byte in turn. */ + lByte = 0; + while( lByte < lBytes ) + { + /* The next character in the input buffer. */ + cInChar = cLocalBuffer[ lByte ]; + lByte++; + + /* Newline characters are taken as the end of the command + string. */ + if( cInChar == '\n' ) + { + /* Process the input string received prior to the + newline. */ + do + { + /* Pass the string to FreeRTOS+CLI. */ + xMoreDataToFollow = FreeRTOS_CLIProcessCommand( cInputString, cOutputString, cmdMAX_OUTPUT_SIZE ); + + /* Send the output generated by the command's + implementation. */ + FreeRTOS_sendto( xSocket, cOutputString, strlen( ( const char * ) cOutputString ), 0, &xClient, xClientAddressLength ); + + } while( xMoreDataToFollow != pdFALSE ); /* Until the command does not generate any more output. */ + + /* All the strings generated by the command processing + have been sent. Clear the input string ready to receive + the next command. */ + cInputIndex = 0; + memset( cInputString, 0x00, cmdMAX_INPUT_SIZE ); + + /* Transmit a spacer, just to make the command console + easier to read. */ + FreeRTOS_sendto( xSocket, "\r\n", strlen( "\r\n" ), 0, &xClient, xClientAddressLength ); + } + else + { + if( cInChar == '\r' ) + { + /* Ignore the character. Newlines are used to + detect the end of the input string. */ + } + else if( cInChar == '\b' ) + { + /* Backspace was pressed. Erase the last character + in the string - if any. */ + if( cInputIndex > 0 ) + { + cInputIndex--; + cInputString[ cInputIndex ] = '\0'; + } + } + else + { + /* A character was entered. Add it to the string + entered so far. When a \n is entered the complete + string will be passed to the command interpreter. */ + if( cInputIndex < cmdMAX_INPUT_SIZE ) + { + cInputString[ cInputIndex ] = cInChar; + cInputIndex++; + } + } + } + } + } + } + } + else + { + /* The socket could not be opened. */ + vTaskDelete( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static Socket_t prvOpenUDPServerSocket( uint16_t usPort ) +{ +struct freertos_sockaddr xServer; +Socket_t xSocket = FREERTOS_INVALID_SOCKET; + + xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); + if( xSocket != FREERTOS_INVALID_SOCKET) + { + /* Zero out the server structure. */ + memset( ( void * ) &xServer, 0x00, sizeof( xServer ) ); + + /* Set family and port. */ + xServer.sin_port = FreeRTOS_htons( usPort ); + + /* Bind the address to the socket. */ + if( FreeRTOS_bind( xSocket, &xServer, sizeof( xServer ) ) == -1 ) + { + FreeRTOS_closesocket( xSocket ); + xSocket = FREERTOS_INVALID_SOCKET; + } + } + + return xSocket; +} + + diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/SimpleClientAndServer.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/SimpleClientAndServer.h new file mode 100644 index 0000000000..ca7b8589c5 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/SimpleClientAndServer.h @@ -0,0 +1,32 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef SIMPLE_CLIENT_AND_SERVER_H +#define SIMPLE_CLIENT_AND_SERVER_H + +void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulsPort, unsigned portBASE_TYPE uxPriority ); + +#endif /* SIMPLE_CLIENT_AND_SERVER_H */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/TwoEchoClients.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/TwoEchoClients.h new file mode 100644 index 0000000000..de785cf54f --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/TwoEchoClients.h @@ -0,0 +1,37 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef TWO_ECHO_CLIENTS_H +#define TWO_ECHO_CLIENTS_H + +/* + * Create the two UDP echo client tasks. One task uses the standard interface + * to send to and receive from an echo server. The other task uses the zero + * copy interface to send to and receive from an echo server. + */ +void vStartEchoClientTasks( uint16_t usTaskStackSize, unsigned portBASE_TYPE uxTaskPriority ); + +#endif /* TWO_ECHO_CLIENTS_H */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/UDPCommandInterpreter.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/UDPCommandInterpreter.h new file mode 100644 index 0000000000..9da47e3da1 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/DemoTasks/include/UDPCommandInterpreter.h @@ -0,0 +1,32 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef UDP_COMMAND_INTERPRETER_H +#define UDP_COMMAND_INTERPRETER_H + +void vStartUDPCommandInterpreterTask( uint16_t usStackSize, uint32_t ulPort, unsigned portBASE_TYPE uxPriority ); + +#endif /* UDP_COMMAND_INTERPRETER_H */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOSConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOSConfig.h new file mode 100644 index 0000000000..5275a3a202 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOSConfig.h @@ -0,0 +1,217 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + + /*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * http://www.freertos.org/a00110.html + * + * The bottom of this file contains some constants specific to running the UDP + * stack in this demo. Constants specific to FreeRTOS+TCP itself (rather than + * the demo) are contained in FreeRTOSIPConfig.h. + *----------------------------------------------------------*/ +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configMAX_PRIORITIES ( 7 ) +#define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 60 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the Win32 thread. */ +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 2048U * 1024U ) ) +#define configMAX_TASK_NAME_LEN ( 15 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_CO_ROUTINES 0 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 3 /* FreeRTOS+FAT requires 2 pointers if a CWD is supported. */ + + /* Hook function related definitions. */ +#define configUSE_TICK_HOOK 0 +#define configUSE_IDLE_HOOK 1 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 /* Not applicable to the Win32 port. */ + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +/* Event group related definitions. */ +#define configUSE_EVENT_GROUPS 1 + +/* Run time stats gathering definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerTaskHandle 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xQueueGetMutexHolder 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xEventGroupSetBitsFromISR 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_pcTaskGetTaskName 1 + +/* This demo makes use of one or more example stats formatting functions. These +format the raw data provided by the uxTaskGetSystemState() function in to human +readable ASCII form. See the notes in the implementation of vTaskList() within +FreeRTOS/Source/tasks.c for limitations. configUSE_STATS_FORMATTING_FUNCTIONS +is set to 2 so the formatting functions are included without the stdio.h being +included in tasks.c. That is because this project defines its own sprintf() +functions. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Assert call defined for debug builds. */ +#ifdef _DEBUG +extern void vAssertCalled(const char* pcFile, uint32_t ulLine); +#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ) +#endif /* _DEBUG */ + + + +/* Application specific definitions follow. **********************************/ + +/* If configINCLUDE_DEMO_DEBUG_STATS is set to one, then a few basic IP trace +macros are defined to gather some UDP stack statistics that can then be viewed +through the CLI interface. */ +#define configINCLUDE_DEMO_DEBUG_STATS 0 + +/* The size of the global output buffer that is available for use when there +are multiple command interpreters running at once (for example, one on a UART +and one on TCP/IP). This is done to prevent an output buffer being defined by +each implementation - which would waste RAM. In this case, there is only one +command interpreter running, and it has its own local output buffer, so the +global buffer is just set to be one byte long as it is not used and should not +take up unnecessary RAM. */ +#define configCOMMAND_INT_MAX_OUTPUT_SIZE 1 + +/* Only used when running in the FreeRTOS Windows simulator. Defines the +priority of the task used to simulate Ethernet interrupts. */ +#define configMAC_ISR_SIMULATOR_PRIORITY ( configMAX_PRIORITIES - 1 ) + +/* This demo creates a virtual network connection by accessing the raw Ethernet +or WiFi data to and from a real network connection. Many computers have more +than one real network port, and configNETWORK_INTERFACE_TO_USE is used to tell +the demo which real port should be used to create the virtual port. The ports +available are displayed on the console when the application is executed. For +example, on my development laptop setting configNETWORK_INTERFACE_TO_USE to 4 +results in the wired network being used, while setting +configNETWORK_INTERFACE_TO_USE to 2 results in the wireless network being +used. */ +#define configNETWORK_INTERFACE_TO_USE ( 0L ) + +/* The address of an echo server that will be used by the two demo echo client +tasks. +http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Echo_Clients.html +http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/UDP_Echo_Clients.html */ +#define configECHO_SERVER_ADDR0 192 +#define configECHO_SERVER_ADDR1 168 +#define configECHO_SERVER_ADDR2 0 +#define configECHO_SERVER_ADDR3 17 + +/* Default MAC address configuration. The demo creates a virtual network +connection that uses this MAC address by accessing the raw Ethernet/WiFi data +to and from a real network connection on the host PC. See the +configNETWORK_INTERFACE_TO_USE definition above for information on how to +configure the real network connection to use. */ +#define configMAC_ADDR0 0x00 +#define configMAC_ADDR1 0x11 +#define configMAC_ADDR2 0x22 +#define configMAC_ADDR3 0x33 +#define configMAC_ADDR4 0x44 +#define configMAC_ADDR5 0x41 + +/* Default IP address configuration. Used in ipconfigUSE_DNS is set to 0, or +ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */ +#define configIP_ADDR0 192 +#define configIP_ADDR1 168 +#define configIP_ADDR2 0 +#define configIP_ADDR3 20 + +/* Default gateway IP address configuration. Used in ipconfigUSE_DNS is set to +0, or ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */ +#define configGATEWAY_ADDR0 10 +#define configGATEWAY_ADDR1 10 +#define configGATEWAY_ADDR2 10 +#define configGATEWAY_ADDR3 1 + +/* Default DNS server configuration. OpenDNS addresses are 208.67.222.222 and +208.67.220.220. Used if ipconfigUSE_DNS is set to 0, or ipconfigUSE_DNS is set +to 1 but a DNS server cannot be contacted.*/ +#define configDNS_SERVER_ADDR0 208 +#define configDNS_SERVER_ADDR1 67 +#define configDNS_SERVER_ADDR2 222 +#define configDNS_SERVER_ADDR3 222 + +/* Default netmask configuration. Used in ipconfigUSE_DNS is set to 0, or +ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */ +#define configNET_MASK0 255 +#define configNET_MASK1 0 +#define configNET_MASK2 0 +#define configNET_MASK3 0 + +/* The UDP port to which print messages are sent. */ +#define configPRINT_PORT ( 15000 ) + +#if( defined( _MSC_VER ) && ( _MSC_VER <= 1600 ) && !defined( snprintf ) ) + /* Map to Windows names. */ +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#endif + +/* Visual studio does not have an implementation of strcasecmp(). */ +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define strcmpi _strcmpi + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOSIPConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOSIPConfig.h new file mode 100644 index 0000000000..e8740194fe --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOSIPConfig.h @@ -0,0 +1,306 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + + /***************************************************************************** + * + * See the following URL for configuration information. + * http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html + * + *****************************************************************************/ + +#ifndef FREERTOS_IP_CONFIG_H +#define FREERTOS_IP_CONFIG_H + + /* Prototype for the function used to print out. In this case it prints to the + console before the network is connected then a UDP port after the network has + connected. */ +extern void vLoggingPrintf(const char* pcFormatString, ...); + +/* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to +1 then FreeRTOS_debug_printf should be defined to the function used to print +out the debugging messages. */ +#define ipconfigHAS_DEBUG_PRINTF 1 +#if( ipconfigHAS_DEBUG_PRINTF == 1 ) +#define FreeRTOS_debug_printf(X) vLoggingPrintf X +#endif + +/* Set to 1 to print out non debugging messages, for example the output of the +FreeRTOS_netstat() command, and ping replies. If ipconfigHAS_PRINTF is set to 1 +then FreeRTOS_printf should be set to the function used to print out the +messages. */ +#define ipconfigHAS_PRINTF 1 +#if( ipconfigHAS_PRINTF == 1 ) +#define FreeRTOS_printf(X) vLoggingPrintf X +#endif + +/* Define the byte order of the target MCU (the MCU FreeRTOS+TCP is executing +on). Valid options are pdFREERTOS_BIG_ENDIAN and pdFREERTOS_LITTLE_ENDIAN. */ +#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN + +/* If the network card/driver includes checksum offloading (IP/TCP/UDP checksums) +then set ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM to 1 to prevent the software +stack repeating the checksum calculations. */ +#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1 + +/* Several API's will block until the result is known, or the action has been +performed, for example FreeRTOS_send() and FreeRTOS_recv(). The timeouts can be +set per socket, using setsockopt(). If not set, the times below will be +used as defaults. */ +#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME ( 5000 ) +#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME ( 5000 ) + +/* Include support for LLMNR: Link-local Multicast Name Resolution +(non-Microsoft) */ +#define ipconfigUSE_LLMNR ( 1 ) + +/* Include support for NBNS: NetBIOS Name Service (Microsoft) */ +#define ipconfigUSE_NBNS ( 1 ) + +/* Include support for DNS caching. For TCP, having a small DNS cache is very +useful. When a cache is present, ipconfigDNS_REQUEST_ATTEMPTS can be kept low +and also DNS may use small timeouts. If a DNS reply comes in after the DNS +socket has been destroyed, the result will be stored into the cache. The next +call to FreeRTOS_gethostbyname() will return immediately, without even creating +a socket. */ +#define ipconfigUSE_DNS_CACHE ( 1 ) +#define ipconfigDNS_CACHE_NAME_LENGTH ( 16 ) +#define ipconfigDNS_CACHE_ENTRIES ( 4 ) +#define ipconfigDNS_REQUEST_ATTEMPTS ( 2 ) + +/* The IP stack executes it its own task (although any application task can make +use of its services through the published sockets API). ipconfigUDP_TASK_PRIORITY +sets the priority of the task that executes the IP stack. The priority is a +standard FreeRTOS task priority so can take any value from 0 (the lowest +priority) to (configMAX_PRIORITIES - 1) (the highest priority). +configMAX_PRIORITIES is a standard FreeRTOS configuration parameter defined in +FreeRTOSConfig.h, not FreeRTOSIPConfig.h. Consideration needs to be given as to +the priority assigned to the task executing the IP stack relative to the +priority assigned to tasks that use the IP stack. */ +#define ipconfigIP_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) + +/* The size, in words (not bytes), of the stack allocated to the FreeRTOS+TCP +task. This setting is less important when the FreeRTOS Win32 simulator is used +as the Win32 simulator only stores a fixed amount of information on the task +stack. FreeRTOS includes optional stack overflow detection, see: +http://www.freertos.org/Stacks-and-stack-overflow-checking.html */ +#define ipconfigIP_TASK_STACK_SIZE_WORDS ( configMINIMAL_STACK_SIZE * 5 ) + +/* ipconfigRAND32() is called by the IP stack to generate random numbers for +things such as a DHCP transaction number or initial sequence number. Random +number generation is performed via this macro to allow applications to use their +own random number generation method. For example, it might be possible to +generate a random number by sampling noise on an analogue input. */ +extern UBaseType_t uxRand(); +#define ipconfigRAND32() uxRand() + +/* If ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 then FreeRTOS+TCP will call the +network event hook at the appropriate times. If ipconfigUSE_NETWORK_EVENT_HOOK +is not set to 1 then the network event hook will never be called. See +http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/vApplicationIPNetworkEventHook.shtml +*/ +#define ipconfigUSE_NETWORK_EVENT_HOOK 1 + +/* Sockets have a send block time attribute. If FreeRTOS_sendto() is called but +a network buffer cannot be obtained then the calling task is held in the Blocked +state (so other tasks can continue to executed) until either a network buffer +becomes available or the send block time expires. If the send block time expires +then the send operation is aborted. The maximum allowable send block time is +capped to the value set by ipconfigMAX_SEND_BLOCK_TIME_TICKS. Capping the +maximum allowable send block time prevents prevents a deadlock occurring when +all the network buffers are in use and the tasks that process (and subsequently +free) the network buffers are themselves blocked waiting for a network buffer. +ipconfigMAX_SEND_BLOCK_TIME_TICKS is specified in RTOS ticks. A time in +milliseconds can be converted to a time in ticks by dividing the time in +milliseconds by portTICK_PERIOD_MS. */ +#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( 5000U / portTICK_PERIOD_MS ) + +/* If ipconfigUSE_DHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP +address, netmask, DNS server address and gateway address from a DHCP server. If +ipconfigUSE_DHCP is 0 then FreeRTOS+TCP will use a static IP address. The +stack will revert to using the static IP address even when ipconfigUSE_DHCP is +set to 1 if a valid configuration cannot be obtained from a DHCP server for any +reason. The static configuration used is that passed into the stack by the +FreeRTOS_IPInit() function call. */ +#define ipconfigUSE_DHCP 1 + +/* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at +increasing time intervals until either a reply is received from a DHCP server +and accepted, or the interval between transmissions reaches +ipconfigMAXIMUM_DISCOVER_TX_PERIOD. The IP stack will revert to using the +static IP address passed as a parameter to FreeRTOS_IPInit() if the +re-transmission time interval reaches ipconfigMAXIMUM_DISCOVER_TX_PERIOD without +a DHCP reply being received. */ +#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( 120000U / portTICK_PERIOD_MS ) + +/* The ARP cache is a table that maps IP addresses to MAC addresses. The IP +stack can only send a UDP message to a remove IP address if it knowns the MAC +address associated with the IP address, or the MAC address of the router used to +contact the remote IP address. When a UDP message is received from a remote IP +address the MAC address and IP address are added to the ARP cache. When a UDP +message is sent to a remote IP address that does not already appear in the ARP +cache then the UDP message is replaced by a ARP message that solicits the +required MAC address information. ipconfigARP_CACHE_ENTRIES defines the maximum +number of entries that can exist in the ARP table at any one time. */ +#define ipconfigARP_CACHE_ENTRIES 6 + +/* ARP requests that do not result in an ARP response will be re-transmitted a +maximum of ipconfigMAX_ARP_RETRANSMISSIONS times before the ARP request is +aborted. */ +#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 ) + +/* ipconfigMAX_ARP_AGE defines the maximum time between an entry in the ARP +table being created or refreshed and the entry being removed because it is stale. +New ARP requests are sent for ARP cache entries that are nearing their maximum +age. ipconfigMAX_ARP_AGE is specified in tens of seconds, so a value of 150 is +equal to 1500 seconds (or 25 minutes). */ +#define ipconfigMAX_ARP_AGE 150 + +/* Implementing FreeRTOS_inet_addr() necessitates the use of string handling +routines, which are relatively large. To save code space the full +FreeRTOS_inet_addr() implementation is made optional, and a smaller and faster +alternative called FreeRTOS_inet_addr_quick() is provided. FreeRTOS_inet_addr() +takes an IP in decimal dot format (for example, "192.168.0.1") as its parameter. +FreeRTOS_inet_addr_quick() takes an IP address as four separate numerical octets +(for example, 192, 168, 0, 1) as its parameters. If +ipconfigINCLUDE_FULL_INET_ADDR is set to 1 then both FreeRTOS_inet_addr() and +FreeRTOS_indet_addr_quick() are available. If ipconfigINCLUDE_FULL_INET_ADDR is +not set to 1 then only FreeRTOS_indet_addr_quick() is available. */ +#define ipconfigINCLUDE_FULL_INET_ADDR 1 + +/* ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS defines the total number of network buffer that +are available to the IP stack. The total number of network buffers is limited +to ensure the total amount of RAM that can be consumed by the IP stack is capped +to a pre-determinable value. */ +#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 60 + +/* A FreeRTOS queue is used to send events from application tasks to the IP +stack. ipconfigEVENT_QUEUE_LENGTH sets the maximum number of events that can +be queued for processing at any one time. The event queue must be a minimum of +5 greater than the total number of network buffers. */ +#define ipconfigEVENT_QUEUE_LENGTH ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 ) + +/* The address of a socket is the combination of its IP address and its port +number. FreeRTOS_bind() is used to manually allocate a port number to a socket +(to 'bind' the socket to a port), but manual binding is not normally necessary +for client sockets (those sockets that initiate outgoing connections rather than +wait for incoming connections on a known port number). If +ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 then calling +FreeRTOS_sendto() on a socket that has not yet been bound will result in the IP +stack automatically binding the socket to a port number from the range +socketAUTO_PORT_ALLOCATION_START_NUMBER to 0xffff. If +ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 then calling FreeRTOS_sendto() +on a socket that has not yet been bound will result in the send operation being +aborted. */ +#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1 + +/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */ +#define ipconfigUDP_TIME_TO_LIVE 128 +#define ipconfigTCP_TIME_TO_LIVE 128 /* also defined in FreeRTOSIPConfigDefaults.h */ + +/* USE_TCP: Use TCP and all its features */ +#define ipconfigUSE_TCP ( 0 ) + +/* USE_WIN: Let TCP use windowing mechanism. */ +#define ipconfigUSE_TCP_WIN ( 0 ) + +/* The MTU is the maximum number of bytes the payload of a network frame can +contain. For normal Ethernet V2 frames the maximum MTU is 1500. Setting a +lower value can save RAM, depending on the buffer management scheme used. If +ipconfigCAN_FRAGMENT_OUTGOING_PACKETS is 1 then (ipconfigNETWORK_MTU - 28) must +be divisible by 8. */ +#define ipconfigNETWORK_MTU 1200U + +/* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver. DNS is used +through the FreeRTOS_gethostbyname() API function. */ +#define ipconfigUSE_DNS 1 + +/* If ipconfigREPLY_TO_INCOMING_PINGS is set to 1 then the IP stack will +generate replies to incoming ICMP echo (ping) requests. */ +#define ipconfigREPLY_TO_INCOMING_PINGS 1 + +/* If ipconfigSUPPORT_OUTGOING_PINGS is set to 1 then the +FreeRTOS_SendPingRequest() API function is available. */ +#define ipconfigSUPPORT_OUTGOING_PINGS 0 + +/* If ipconfigSUPPORT_SELECT_FUNCTION is set to 1 then the FreeRTOS_select() +(and associated) API function is available. */ +#define ipconfigSUPPORT_SELECT_FUNCTION 1 + +/* If ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is set to 1 then Ethernet frames +that are not in Ethernet II format will be dropped. This option is included for +potential future IP stack developments. */ +#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1 + +/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1 then it is the +responsibility of the Ethernet interface to filter out packets that are of no +interest. If the Ethernet interface does not implement this functionality, then +set ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES to 0 to have the IP stack +perform the filtering instead (it is much less efficient for the stack to do it +because the packet will already have been passed into the stack). If the +Ethernet driver does all the necessary filtering in hardware then software +filtering can be removed by using a value other than 1 or 0. */ +#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 + +/* The windows simulator cannot really simulate MAC interrupts, and needs to +block occasionally to allow other tasks to run. */ +#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ( 20 / portTICK_PERIOD_MS ) + +/* Advanced only: in order to access 32-bit fields in the IP packets with +32-bit memory instructions, all packets will be stored 32-bit-aligned, plus 16-bits. +This has to do with the contents of the IP-packets: all 32-bit fields are +32-bit-aligned, plus 16-bit(!) */ +#define ipconfigPACKET_FILLER_SIZE 2U + +/* Define the size of the pool of TCP window descriptors. On the average, each +TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6 +outstanding packets (for Rx and Tx). When using up to 10 TP sockets +simultaneously, one could define TCP_WIN_SEG_COUNT as 120. */ +#define ipconfigTCP_WIN_SEG_COUNT 240 + +/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed +maximum size. Define the size of Rx buffer for TCP sockets. */ +#define ipconfigTCP_RX_BUFFER_LENGTH ( 1000 ) + +/* Define the size of Tx buffer for TCP sockets. */ +#define ipconfigTCP_TX_BUFFER_LENGTH ( 1000 ) + +/* When using call-back handlers, the driver may check if the handler points to +real program memory (RAM or flash) or just has a random non-zero value. */ +#define ipconfigIS_VALID_PROG_ADDRESS(x) ( (x) != NULL ) + +/* Include support for TCP hang protection. All sockets in a connecting or +disconnecting stage will timeout after a period of non-activity. */ +#define ipconfigTCP_HANG_PROTECTION ( 1 ) +#define ipconfigTCP_HANG_PROTECTION_TIME ( 30 ) + +/* Include support for TCP keep-alive messages. */ +#define ipconfigTCP_KEEP_ALIVE ( 1 ) +#define ipconfigTCP_KEEP_ALIVE_INTERVAL ( 20 ) /* in seconds */ + +#define portINLINE __inline + +#endif /* FREERTOS_IP_CONFIG_H */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOS_Plus_UDP_with_CLI.sln b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOS_Plus_UDP_with_CLI.sln new file mode 100644 index 0000000000..6504706481 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOS_Plus_UDP_with_CLI.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WIN32", "WIN32.vcxproj", "{C686325E-3261-42F7-AEB1-DDE5280E1CEB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|Win32.ActiveCfg = Debug|Win32 + {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|Win32.Build.0 = Debug|Win32 + {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|Win32.ActiveCfg = Release|Win32 + {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOS_Plus_UDP_with_CLI.suo b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/FreeRTOS_Plus_UDP_with_CLI.suo new file mode 100644 index 0000000000000000000000000000000000000000..640eae6baafb5fe2991806dfe6c12e8e0a6b4bc8 GIT binary patch literal 195584 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�~-K7--2+X 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

vz6rfsgh3ta!LrY~8rq&4uy8+GrTF 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 + +/* Variables used in the creation of the run time stats time base. Run time +stats record how much time each task spends in the Running state. */ +static long long llInitialRunTimeCounterValue = 0LL, llTicksPerHundedthMillisecond = 0LL; + +/*-----------------------------------------------------------*/ + +void vConfigureTimerForRunTimeStats( void ) +{ +LARGE_INTEGER liPerformanceCounterFrequency, liInitialRunTimeValue; + + /* Initialise the variables used to create the run time stats time base. + Run time stats record how much time each task spends in the Running + state. */ + + if( QueryPerformanceFrequency( &liPerformanceCounterFrequency ) == 0 ) + { + llTicksPerHundedthMillisecond = 1; + } + else + { + /* How many times does the performance counter increment in 1/100th + millisecond. */ + llTicksPerHundedthMillisecond = liPerformanceCounterFrequency.QuadPart / 100000LL; + + /* What is the performance counter value now, this will be subtracted + from readings taken at run time. */ + QueryPerformanceCounter( &liInitialRunTimeValue ); + llInitialRunTimeCounterValue = liInitialRunTimeValue.QuadPart; + } +} +/*-----------------------------------------------------------*/ + +unsigned long ulGetRunTimeCounterValue( void ) +{ +LARGE_INTEGER liCurrentCount; +unsigned long ulReturn; + + /* What is the performance counter value now? */ + QueryPerformanceCounter( &liCurrentCount ); + + /* Subtract the performance counter value reading taken when the + application started to get a count from that reference point, then + scale to (simulated) 1/100ths of a millisecond. */ + ulReturn = ( unsigned long ) ( ( liCurrentCount.QuadPart - llInitialRunTimeCounterValue ) / llTicksPerHundedthMillisecond ); + + return ulReturn; +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj new file mode 100644 index 0000000000..3972419560 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj @@ -0,0 +1,195 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {C686325E-3261-42F7-AEB1-DDE5280E1CEB} + RTOSDemo + + + + Application + false + MultiByte + v142 + + + Application + false + MultiByte + v142 + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + .\Debug/WIN32.tlb + + + + + Disabled + ..\..\Source\Utilities\logging;..\..\..\FreeRTOS\Source\include;..\..\..\FreeRTOS\Source\portable\MSVC-MingW;..\..\Source\FreeRTOS-Plus-TCP\portable\BufferManagement;..\..\Source\FreeRTOS-Plus-TCP\portable\Compiler\MSVC;..\..\Source\FreeRTOS-Plus-TCP\include;.\DemoTasks\include;..\Common\WinPCap;..\..\Source\FreeRTOS-Plus-CLI;.;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0500;WINVER=0x400;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + .\Debug/WIN32.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level4 + true + false + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + .\Debug/RTOSDemo.exe + true + true + .\Debug/WIN32.pdb + Console + MachineX86 + wpcap.lib;%(AdditionalDependencies) + ..\Common\WinPCap + + + true + .\Debug/WIN32.bsc + + + + + .\Release/WIN32.tlb + + + + + MaxSpeed + OnlyExplicitInline + _WINSOCKAPI_;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreaded + true + .\Release/WIN32.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + ..\Common\Utils;..\Common\ethernet\lwip-1.4.0\ports\win32\WinPCap;..\Common\ethernet\lwip-1.4.0\src\include\ipv4;..\Common\ethernet\lwip-1.4.0\src\include;..\..\Source\include;..\..\Source\portable\MSVC-MingW;..\Common\ethernet\lwip-1.4.0\ports\win32\include;..\Common\Include;.\lwIP_Apps;.;%(AdditionalIncludeDirectories) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + .\Release/RTOSDemo.exe + true + .\Release/WIN32.pdb + Console + MachineX86 + ..\Common\ethernet\lwip-1.4.0\ports\win32\WinPCap + wpcap.lib;%(AdditionalDependencies) + + + true + .\Release/WIN32.bsc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj.filters b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj.filters new file mode 100644 index 0000000000..48f1ce979d --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj.filters @@ -0,0 +1,212 @@ + + + + + {34567deb-d5ab-4a56-8640-0aaec609521a} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {af3445a1-4908-4170-89ed-39345d90d30c} + + + {e5ad4ec7-23dc-4295-8add-2acaee488f5a} + + + {fd43c0ed-fdbc-437f-a5a3-c50399690bd7} + + + {b71e974a-9f28-4815-972b-d930ba8a34d0} + + + {19ff1a34-36de-4c48-9d10-3fb1fa0d1fa4} + h;hpp;hxx;hm;inl + + + {8672fa26-b119-481f-8b8d-086419c01a3e} + + + {5d93ed51-023a-41ad-9243-8d230165d34b} + + + {efdc091e-3412-4dbe-a7c3-f660d1cf75e8} + + + {822b2cba-7de8-4a4b-9b44-c819647cdeb7} + + + {cb5941d0-6158-48ca-b76e-a922c037fe93} + + + {60d4e26e-d730-4d65-b64c-347fee222b9a} + + + {c86a0d3c-216d-4259-b770-21678dd82ea2} + + + {e2273fad-c964-49fb-ba24-046e2095064c} + + + + + Demo App Source + + + Demo App Source + + + Demo App Source\DemoTasks + + + Demo App Source\DemoTasks + + + FreeRTOS+\FreeRTOS+CLI + + + FreeRTOS+\FreeRTOS+TCP + + + FreeRTOS+\FreeRTOS+TCP + + + FreeRTOS+\FreeRTOS+TCP + + + FreeRTOS+\FreeRTOS+TCP + + + FreeRTOS+\FreeRTOS+TCP + + + FreeRTOS+\FreeRTOS+TCP + + + FreeRTOS+\FreeRTOS+TCP + + + FreeRTOS+\FreeRTOS+TCP + + + FreeRTOS+\FreeRTOS+TCP + + + FreeRTOS + + + FreeRTOS + + + FreeRTOS + + + FreeRTOS + + + FreeRTOS + + + FreeRTOS + + + FreeRTOS + + + FreeRTOS\portable + + + FreeRTOS\portable + + + FreeRTOS+\FreeRTOS+TCP\portable\NetworkInterface + + + FreeRTOS+\FreeRTOS+TCP\portable\BufferManagement + + + Demo App Source + + + Demo App Source\DemoTasks + + + Demo App Source + + + + + Demo App Source\Configuration Files + + + Demo App Source\Configuration Files + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS+\FreeRTOS+TCP\include + + + FreeRTOS\include + + + FreeRTOS\include + + + FreeRTOS\include + + + FreeRTOS\include + + + FreeRTOS\include + + + FreeRTOS\portable + + + FreeRTOS+\FreeRTOS+TCP\portable\Compiler + + + FreeRTOS+\FreeRTOS+TCP\portable\Compiler + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj.user b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj.user new file mode 100644 index 0000000000..ace9a86acb --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/WIN32.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/main.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/main.c new file mode 100644 index 0000000000..45f5dbcba0 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/main.c @@ -0,0 +1,365 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* Standard includes. */ +#include +#include + +/* FreeRTOS includes. */ +#include +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo application includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" +#include "SimpleClientAndServer.h" +#include "TwoEchoClients.h" +#include "UDPCommandInterpreter.h" +#include "logging.h" + +/* UDP command server task parameters. */ +#define mainUDP_CLI_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define mainUDP_CLI_PORT_NUMBER ( 5001UL ) +#define mainUDP_CLI_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE ) + +/* Simple UDP client and server task parameters. */ +#define mainSIMPLE_CLIENT_SERVER_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define mainSIMPLE_CLIENT_SERVER_PORT ( 5005UL ) +#define mainSIMPLE_CLIENT_SERVER_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE ) + +/* Echo client task parameters. */ +#define mainECHO_CLIENT_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) +#define mainECHO_CLIENT_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) + +/* Set the following constants to 1 or 0 to define which tasks to include and +exclude. */ +#define mainCREATE_UDP_CLI_TASKS 1 +#define mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS 0 +#define mainCREATE_UDP_ECHO_TASKS 1 + +/*-----------------------------------------------------------*/ + +/* + * Register commands that can be used with FreeRTOS+CLI through the UDP socket. + * The commands are defined in CLI-commands.c. + */ +extern void vRegisterCLICommands( void ); + +/* The default IP and MAC address used by the demo. The address configuration +defined here will be used if ipconfigUSE_DHCP is 0, or if ipconfigUSE_DHCP is +1 but a DHCP server could not be contacted. See the online documentation for +more information. */ +static const uint8_t ucIPAddress[ 4 ] = { configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 }; +static const uint8_t ucNetMask[ 4 ] = { configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 }; +static const uint8_t ucGatewayAddress[ 4 ] = { configGATEWAY_ADDR0, configGATEWAY_ADDR1, configGATEWAY_ADDR2, configGATEWAY_ADDR3 }; +static const uint8_t ucDNSServerAddress[ 4 ] = { configDNS_SERVER_ADDR0, configDNS_SERVER_ADDR1, configDNS_SERVER_ADDR2, configDNS_SERVER_ADDR3 }; + +/* Default MAC address configuration. The demo creates a virtual network +connection that uses this MAC address by accessing the raw Ethernet data +to and from a real network connection on the host PC. See the +configNETWORK_INTERFACE_TO_USE definition for information on how to configure +the real network connection to use. */ +const uint8_t ucMACAddress[ 6 ] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 }; + +/* Used to guard prints to the console. */ +static xSemaphoreHandle xConsoleMutex = NULL; + +/* Set the following constant to pdTRUE to log using the method indicated by the + * name of the constant, or pdFALSE to not log using the method indicated by the + * name of the constant. Options include to standard out (xLogToStdout), to a disk + * file (xLogToFile), and to a UDP port (xLogToUDP). If xLogToUDP is set to pdTRUE + * then UDP messages are sent to the IP address configured as the echo server + * address (see the configECHO_SERVER_ADDR0 definitions in FreeRTOSConfig.h) and + * the port number set by configPRINT_PORT in FreeRTOSConfig.h. */ +const BaseType_t xLogToStdout = pdTRUE, xLogToFile = pdFALSE, xLogToUDP = pdFALSE; + +/*-----------------------------------------------------------*/ + +/* Define a name that will be used for LLMNR and NBNS searches. */ +#define mainHOST_NAME "RTOSDemo" +#define mainDEVICE_NICK_NAME "windows_demo" + +/* Used by the pseudo random number generator. */ +static UBaseType_t ulNextRand; + +/****************************************************************************** + * + * See the following web page for information on using this demo. + * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/RTOS_UDP_CLI_Windows_Simulator.shtml + * + ******************************************************************************/ + + +int main( void ) +{ +const uint32_t ulLongTime_ms = 250UL; + + /* Create a mutex that is used to guard against the console being accessed + by more than one task simultaniously. */ + xConsoleMutex = xSemaphoreCreateMutex(); + + /* Initialise the network interface. Tasks that use the network are + created in the network event hook when the network is connected and ready + for use. The address values passed in here are used if ipconfigUSE_DHCP is + set to 0, or if ipconfigUSE_DHCP is set to 1 but a DHCP server cannot be + contacted. */ + FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress ); + + /* Initialise the logging. */ + uint32_t ulLoggingIPAddress; + + ulLoggingIPAddress = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, + configECHO_SERVER_ADDR1, + configECHO_SERVER_ADDR2, + configECHO_SERVER_ADDR3 ); + vLoggingInit( xLogToStdout, xLogToFile, xLogToUDP, ulLoggingIPAddress, configPRINT_PORT ); + + + /* Register commands with the FreeRTOS+CLI command interpreter. */ + vRegisterCLICommands(); + + /* Start the RTOS scheduler. */ + 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 insufficient FreeRTOS heap memory available for the idle and/or + timer tasks to be created. See the memory management section on the + FreeRTOS web site for more details (this is standard text that is not not + really applicable to the Win32 simulator port). */ + for( ;; ) + { + Sleep( ulLongTime_ms ); + } +} +/*-----------------------------------------------------------*/ + +void vApplicationIdleHook( void ) +{ +const unsigned long ulMSToSleep = 5; + + /* This function is called on each cycle of the idle task if + configUSE_IDLE_HOOK is set to 1 in FreeRTOSConfig.h. Sleep to reduce CPU + load. */ + Sleep( ulMSToSleep ); +} +/*-----------------------------------------------------------*/ + +void vAssertCalled( void ) +{ +const unsigned long ulLongSleep = 1000UL; +volatile uint32_t ulBlockVariable = 0UL; + + /* Setting ulBlockVariable to a non-zero value in the debugger will allow + this function to be exited. */ + taskDISABLE_INTERRUPTS(); + { + while( ulBlockVariable == 0UL ) + { + Sleep( ulLongSleep ); + } + } + taskENABLE_INTERRUPTS(); +} +/*-----------------------------------------------------------*/ + +/* Called by FreeRTOS+TCP when the network connects. */ +void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ) +{ +uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress; +int8_t cBuffer[ 16 ]; +static BaseType_t 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_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 ); + FreeRTOS_debug_printf( ( "IP Address: " ) ); + FreeRTOS_inet_ntoa( ulIPAddress, cBuffer ); + FreeRTOS_debug_printf( ( ( char * ) cBuffer ) ); + FreeRTOS_debug_printf( ( "\r\nSubnet Mask: " ) ); + FreeRTOS_inet_ntoa( ulNetMask, cBuffer ); + FreeRTOS_debug_printf( ( ( char * ) cBuffer ) ); + FreeRTOS_debug_printf( ( "\r\nGateway Address: " ) ); + FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer ); + FreeRTOS_debug_printf( ( ( char * ) cBuffer ) ); + FreeRTOS_debug_printf( ( "\r\nDNS Server Address: " ) ); + FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer ); + FreeRTOS_debug_printf( ( ( char * ) cBuffer ) ); + FreeRTOS_debug_printf( ( "\r\n\r\n" ) ); + } +} +/*-----------------------------------------------------------*/ + +/* Called automatically when a reply to an outgoing ping is received. */ +void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier ) +{ +static const uint8_t *pcSuccess = ( uint8_t * ) "Ping reply received - "; +static const uint8_t *pcInvalidChecksum = ( uint8_t * ) "Ping reply received with invalid checksum - "; +static const uint8_t *pcInvalidData = ( uint8_t * ) "Ping reply received with invalid data - "; +static uint8_t cMessage[ 50 ]; + + + switch( eStatus ) + { + case eSuccess : + FreeRTOS_debug_printf( ( ( char * ) pcSuccess ) ); + break; + + case eInvalidChecksum : + FreeRTOS_debug_printf( ( ( char * ) pcInvalidChecksum ) ); + break; + + case eInvalidData : + FreeRTOS_debug_printf( ( ( char * ) pcInvalidData ) ); + break; + + default : + /* It is not possible to get here as all enums have their own + case. */ + break; + } + + sprintf( ( char * ) cMessage, "identifier %d\r\n", ( int ) usIdentifier ); + FreeRTOS_debug_printf( ( ( char * ) cMessage ) ); +} +/*-----------------------------------------------------------*/ + +void vApplicationMallocFailedHook( void ) +{ + /* vApplicationMallocFailedHook() will only be called if + configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook + function that will get called if a call to pvPortMalloc() fails. + pvPortMalloc() is called internally by the kernel whenever a task, queue, + timer or semaphore is created. It is also called by various parts of the + demo application. If heap_1.c, heap_2.c or heap_4.c are used, then the + size of the heap available to pvPortMalloc() is defined by + configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize() + API function can be used to query the size of free heap space that remains + (although it does not provide information on how the remaining heap might + be fragmented). */ + taskDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) || ( ipconfigDHCP_REGISTER_HOSTNAME == 1 ) + + const char * pcApplicationHostnameHook( void ) + { + /* Assign the name "FreeRTOS" to this network node. This function will + * be called during the DHCP: the machine will be registered with an IP + * address plus this name. */ + return mainHOST_NAME; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) + + BaseType_t xApplicationDNSQueryHook( const char * pcName ) + { + BaseType_t xReturn; + + /* Determine if a name lookup is for this node. Two names are given + * to this node: that returned by pcApplicationHostnameHook() and that set + * by mainDEVICE_NICK_NAME. */ + if( _stricmp( pcName, pcApplicationHostnameHook() ) == 0 ) + { + xReturn = pdPASS; + } + else if( _stricmp( pcName, mainDEVICE_NICK_NAME ) == 0 ) + { + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) */ +/*-----------------------------------------------------------*/ + +UBaseType_t uxRand( void ) +{ + const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL; + + /* Utility function to generate a pseudo random number. */ + + ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement; + return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL ); +} + + +/* + * Supply a random number to FreeRTOS+TCP stack. + * THIS IS ONLY A DUMMY IMPLEMENTATION THAT RETURNS A PSEUDO RANDOM NUMBER + * SO IS NOT INTENDED FOR USE IN PRODUCTION SYSTEMS. + */ +BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber ) +{ + *( pulNumber ) = uxRand(); + return pdTRUE; +} diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/ReadMe.txt b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/ReadMe.txt deleted file mode 100644 index 24bb5461e9..0000000000 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/ReadMe.txt +++ /dev/null @@ -1,4 +0,0 @@ -FreeRTOS+UDP was removed in FreeRTOS V10.1.0 as it was replaced by FreeRTOS+TCP, -which was brought into the main download in FreeRTOS V10.0.0. FreeRTOS+TCP can -be configured as a UDP only stack, and FreeRTOS+UDP does not contain the patches -applied to FreeRTOS+TCP. \ No newline at end of file diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/See also FreeRTOS+TCP.url b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/See also FreeRTOS+TCP.url deleted file mode 100644 index 2da199cac9..0000000000 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/See also FreeRTOS+TCP.url +++ /dev/null @@ -1,5 +0,0 @@ -[{000214A0-0000-0000-C000-000000000046}] -Prop3=19,2 -[InternetShortcut] -URL=http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/index.html -IDList=