From 95c7627f5f757427c1b78968e29106a036bf43cb Mon Sep 17 00:00:00 2001 From: rtel Date: Wed, 17 Jul 2019 20:50:15 +0000 Subject: [PATCH] Added simple UDP demo into the mqtt project to enable the network connectivity to be tested in a simple way prior to performing any MQTT operations. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2686 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../mqtt/DemoTasks/SimpleUDPClientAndServer.c | 14 + .../mqtt/FreeRTOSConfig.h | 2 +- .../mqtt/FreeRTOSIPConfig.h | 2 +- .../Demo/FreeRTOS_IoT_Libraries/mqtt/main.c | 247 +++++++++++++++--- .../FreeRTOS_IoT_Libraries/task_pool/main.c | 7 - 5 files changed, 224 insertions(+), 48 deletions(-) diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleUDPClientAndServer.c b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleUDPClientAndServer.c index 54143c367..32a9aec1f 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleUDPClientAndServer.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleUDPClientAndServer.c @@ -47,6 +47,10 @@ #include "FreeRTOS_IP.h" #include "FreeRTOS_Sockets.h" +#if( configASSERT_DEFINED == 0 ) + #error This demo uses configASSERT() to trap errors. configASSERT() must be defined in FreeRTOSConfig.h https://www.freertos.org/a00110.html#configASSERT +#endif + #define simpTINY_DELAY ( ( TickType_t ) 2 ) /* @@ -101,6 +105,8 @@ const TickType_t x150ms = 150UL / portTICK_PERIOD_MS; /* Remove compiler warning about unused parameters. */ ( void ) pvParameters; + FreeRTOS_printf( ( "Starting prvSimpleClientTask\r\n" ) ); + /* 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 @@ -161,6 +167,8 @@ Socket_t xListeningSocket; /* Just to prevent compiler warnings. */ ( void ) pvParameters; + FreeRTOS_printf( ( "Starting prvSimpleServerTask\r\n" ) ); + /* Attempt to open the socket. */ xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET ); @@ -191,6 +199,7 @@ Socket_t xListeningSocket; /* Error check. */ configASSERT( lBytes == ( BaseType_t ) strlen( ( const char * ) cReceivedString ) ); + FreeRTOS_printf( ( "prvSimpleServerTask() recieved %s\r\n", ( const char * ) cReceivedString ) ); } } /*-----------------------------------------------------------*/ @@ -211,6 +220,8 @@ const size_t xStringLength = strlen( pcStringToSend ) + 15; /* Remove compiler warning about unused parameters. */ ( void ) pvParameters; + FreeRTOS_printf( ( "Starting prvSimpleZeroCopyUDPClientTask\r\n" ) ); + /* 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 @@ -309,6 +320,8 @@ Socket_t xListeningSocket; /* Just to prevent compiler warnings. */ ( void ) pvParameters; + FreeRTOS_printf( ( "Starting prvSimpleZeroCopyServerTask\r\n" ) ); + /* Attempt to open the socket. */ xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET ); @@ -343,6 +356,7 @@ Socket_t xListeningSocket; /* It is expected to receive one more byte than the string length as the NULL terminator is also transmitted. */ configASSERT( lBytes == ( ( BaseType_t ) strlen( ( const char * ) pucUDPPayloadBuffer ) + 1 ) ); + FreeRTOS_printf( ( "prvSimpleZeroCopyServerTask() recieved %s\r\n", ( const char * ) pucUDPPayloadBuffer ) ); } if( lBytes >= 0 ) diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/FreeRTOSConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/FreeRTOSConfig.h index c60557dec..1ab0867f1 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/FreeRTOSConfig.h +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/FreeRTOSConfig.h @@ -136,7 +136,7 @@ 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 4L +#define configNETWORK_INTERFACE_TO_USE 3L /* The address of an echo server that will be used by the two demo echo client tasks. diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/FreeRTOSIPConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/FreeRTOSIPConfig.h index 7092fca6a..79ce6d429 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/FreeRTOSIPConfig.h +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/FreeRTOSIPConfig.h @@ -53,7 +53,7 @@ out the debugging messages. */ 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 0 +#define ipconfigHAS_PRINTF 1 #if( ipconfigHAS_PRINTF == 1 ) #define FreeRTOS_printf(X) vLoggingPrintf X #endif diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c index 6361b49b2..5b0f4e132 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c @@ -46,18 +46,80 @@ should an assert get hit. */ /* TCP/IP stack includes. */ #include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" + +/* Demo app includes. */ +#include "demo_logging.h" + +/* Set the following constants to 1 or 0 to define which tasks to include and +exclude: + +mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS: When set to 1 two UDP client tasks +and two UDP server tasks are created. The clients talk to the servers. One set +of tasks use the standard sockets interface, and the other the zero copy sockets +interface. These tasks are self checking and will trigger a configASSERT() if +they detect a difference in the data that is received from that which was sent. +As these tasks use UDP, and can therefore loose packets, they will cause +configASSERT() to be called when they are run in a less than perfect networking +environment. + +mainCREATE_SIMPLE_MQTT_EXAMPLE_TASKS: TBD +*/ +#define mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS 1 +#define mainCREATE_SIMPLE_MQTT_EXAMPLE_TASKS 0 + +/* Simple UDP client and server task parameters. */ +#define mainSIMPLE_UDP_CLIENT_SERVER_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define mainSIMPLE_UDP_CLIENT_SERVER_PORT ( 5005UL ) /* * Prototypes for the demos that can be started from this project. */ -extern void vStartSimpleTaskPoolDemo( void ); +extern void vStartSimpleMQTTDemo( void ); +extern void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulsPort, UBaseType_t uxPriority ); + +/* + * Just seeds the simple pseudo random number generator. + * + * !!! NOTE !!! + * This is not a secure method of generating random numbers and production + * devices should use a true random number generator (TRNG). + */ +static void prvSRand( UBaseType_t ulSeed ); -/* This example is the first in a sequence that adds IoT functionality into -an existing TCP/IP project. In this first project the TCP/IP stack is not -actually used, but it is still built, which requires this array to be -present. */ +/* + * Miscellaneous initialisation including preparing the logging and seeding the + * random number generator. + */ +static void prvMiscInitialisation( 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 }; + +/* 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; + +/* 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 }; +/* Use by the pseudo random number generator. */ +static UBaseType_t ulNextRand; /*-----------------------------------------------------------*/ int main( void ) @@ -67,14 +129,20 @@ int main( void ) * TBD */ - /* Create the example that demonstrates task pool functionality. Examples - that demonstrate networking connectivity will be added in future projects - and get started after the network has connected (from within the - vApplicationIPNetworkEventHook() function).*/ - vStartSimpleTaskPoolDemo(); + /* Miscellaneous initialisation including preparing the logging and seeding + the random number generator. */ + prvMiscInitialisation(); - /* Start the scheduler - if all is well from this point on only FreeRTOS - tasks will execute. */ + /* Initialise the network interface. + + ***NOTE*** Tasks that use the network are created in the network event hook + when the network is connected and ready for use (see the implementation of + vApplicationIPNetworkEventHook() below). 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 ); + + /* Start the RTOS scheduler. */ vTaskStartScheduler(); /* If all is well, the scheduler will now be running, and the following @@ -118,46 +186,147 @@ volatile uint32_t ulLineNumber = ulLine; events are only received if implemented in the MAC driver. */ void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ) { - /* This example is the first in a sequence that adds IoT functionality into - an existing TCP/IP project. In this first project the TCP/IP stack is not - actually used, but it is still built, which requires this function to be - present. For now this function does not need to do anything, so just ensure - the unused parameters don't cause compiler warnings and that calls to this - function are trapped by the debugger. */ - __debugbreak(); - ( void ) eNetworkEvent; +uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress; +char cBuffer[ 16 ]; +static BaseType_t xTasksAlreadyCreated = pdFALSE; + + /* If the network has just come up...*/ + 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 ) + { + vStartSimpleUDPClientServerTasks( configMINIMAL_STACK_SIZE, mainSIMPLE_UDP_CLIENT_SERVER_PORT, mainSIMPLE_UDP_CLIENT_SERVER_TASK_PRIORITY ); + } + #endif + + #if( mainCREATE_SIMPLE_MQTT_EXAMPLE_TASKS == 1 ) + { + vStartSimpleMQTTDemo(); + } + #endif + + xTasksAlreadyCreated = pdTRUE; + } + + /* Print out the network configuration, which may have come from a DHCP + server. */ + FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress ); + FreeRTOS_inet_ntoa( ulIPAddress, cBuffer ); + FreeRTOS_printf( ( "\r\n\r\nIP Address: %s\r\n", cBuffer ) );/*_RB_ Should use IoT libraries logging. */ + + FreeRTOS_inet_ntoa( ulNetMask, cBuffer ); + FreeRTOS_printf( ( "Subnet Mask: %s\r\n", cBuffer ) ); + + FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer ); + FreeRTOS_printf( ( "Gateway Address: %s\r\n", cBuffer ) ); + + FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer ); + FreeRTOS_printf( ( "DNS Server Address: %s\r\n\r\n\r\n", cBuffer ) ); + } +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxRand( void ) +{ +const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL; + + /* + * Utility function to generate a pseudo random number. + * + * !!!NOTE!!! + * This is not a secure method of generating a random number. Production + * devices should use a True Random Number Generator (TRNG). + */ + ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement; + return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL ); } /*-----------------------------------------------------------*/ +static void prvSRand( UBaseType_t ulSeed ) +{ + /* Utility function to seed the pseudo random number generator. */ + ulNextRand = ulSeed; +} +/*-----------------------------------------------------------*/ + +static void prvMiscInitialisation( void ) +{ +time_t xTimeNow; +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 ); + + /* Seed the random number generator. */ + time( &xTimeNow ); + FreeRTOS_debug_printf( ( "Seed for randomiser: %lu\n", xTimeNow ) ); + prvSRand( ( uint32_t ) xTimeNow ); + FreeRTOS_debug_printf( ( "Random numbers: %08X %08X %08X %08X\n", ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32() ) ); +} +/*-----------------------------------------------------------*/ + +#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 +/*-----------------------------------------------------------*/ + +/* + * Callback that provides the inputs necessary to generate a randomized TCP + * Initial Sequence Number per RFC 6528. THIS IS ONLY A DUMMY IMPLEMENTATION + * THAT RETURNS A PSEUDO RANDOM NUMBER SO IS NOT INTENDED FOR USE IN PRODUCTION + * SYSTEMS. + */ extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress, uint16_t usSourcePort, uint32_t ulDestinationAddress, uint16_t usDestinationPort ) { - /* This example is the first in a sequence that adds IoT functionality into - an existing TCP/IP project. In this first project the TCP/IP stack is not - actually used, but it is still built, which requires this function to be - present. For now this function does not need to do anything, so just ensure - the unused parameters don't cause compiler warnings and that calls to this - function are trapped by the debugger. */ ( void ) ulSourceAddress; ( void ) usSourcePort; ( void ) ulDestinationAddress; ( void ) usDestinationPort; - __debugbreak(); - return 0; -} -/*-----------------------------------------------------------*/ -UBaseType_t uxRand( void ) -{ - /* This example is the first in a sequence that adds IoT functionality into - an existing TCP/IP project. In this first project the TCP/IP stack is not - actually used, but it is still built, which requires this function to be - present. For now this function does not need to do anything, so just ensure - the calls to the function are trapped by the debugger. */ - __debugbreak(); - return 0; + return uxRand(); } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/task_pool/main.c b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/task_pool/main.c index 6361b49b2..7f42f9ab2 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/task_pool/main.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/task_pool/main.c @@ -25,13 +25,6 @@ * 1 tab == 4 spaces! */ -/* - * This project is a cut down version of the project described on the following - * link. Only the simple UDP client and server and the TCP echo clients are - * included in the build: - * http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html - */ - /* Standard includes. */ #include #include -- 2.39.5