/* * Lab-Project-coreMQTT-Agent 201215 * 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. * * http://www.FreeRTOS.org * http://aws.amazon.com/freertos * * 1 tab == 4 spaces! */ /*** * See https://www.FreeRTOS.org/mqtt/mqtt-agent-demo.html for configuration and usage * instructions. ***/ /* Standard includes. */ #include #include /* FreeRTOS includes. */ #include #include "task.h" /* TCP/IP stack includes. */ #include "FreeRTOS_IP.h" #include "FreeRTOS_Sockets.h" /* Demo Specific configs. */ #include "demo_config.h" /* * Prototypes for the demos that can be started from this project. Note the * MQTT demo is not actually started until the network is already, which is * indicated by vApplicationIPNetworkEventHook() executing - hence * prvStartMQTTAgentDemo() is called from inside vApplicationIPNetworkEventHook(). */ extern void vStartMQTTAgentDemo( void ); /* * 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 ); /* * Miscellaneous initialization 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 }; /* 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 ) { /*** * See https://www.FreeRTOS.org/mqtt and https://www.FreeRTOS.org/tcp for * configuration and usage instructions. ***/ /* Miscellaneous initialization including preparing the logging and seeding * the random number generator. */ prvMiscInitialisation(); /* Initialize 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 * 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 * really applicable to the Win32 simulator port). */ for( ; ; ) { } } /*-----------------------------------------------------------*/ /* Called by FreeRTOS+TCP when the network connects or disconnects. Disconnect * events are only received if implemented in the MAC driver. */ void vApplicationIPNetworkEventHook( eIPCallbackEvent_t 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 ) { /* Demos that use the network are created after the network is * up. */ LogInfo( ( "---------STARTING DEMO---------\r\n" ) ); vStartMQTTAgentDemo(); 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 ); LogInfo( ( "\r\n\r\nIP Address: %s\r\n", cBuffer ) ); FreeRTOS_inet_ntoa( ulNetMask, cBuffer ); LogInfo( ( "Subnet Mask: %s\r\n", cBuffer ) ); FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer ); LogInfo( ( "Gateway Address: %s\r\n", cBuffer ) ); FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer ); LogInfo( ( "DNS Server Address: %s\r\n\r\n\r\n", cBuffer ) ); } } /*-----------------------------------------------------------*/ void vAssertCalled( const char * pcFile, uint32_t ulLine ) { volatile uint32_t ulBlockVariable = 0UL; volatile char * pcFileName = ( volatile char * ) pcFile; volatile uint32_t ulLineNumber = ulLine; ( void ) pcFileName; ( void ) ulLineNumber; LogError( ( "vAssertCalled( %s, %u\n", pcFile, ( unsigned int ) ulLine ) ); /* Setting ulBlockVariable to a non-zero value in the debugger will allow * this function to be exited. */ taskDISABLE_INTERRUPTS(); { while( ulBlockVariable == 0UL ) { } } taskENABLE_INTERRUPTS(); } /*-----------------------------------------------------------*/ 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 ulNextRand; } /*-----------------------------------------------------------*/ static void prvSRand( UBaseType_t ulSeed ) { /* Utility function to seed the pseudo random number generator. */ ulNextRand = ulSeed; } /*-----------------------------------------------------------*/ static void prvMiscInitialisation( void ) { time_t xTimeNow; /* Perform any initialization that is specific to a build. This macro * can be defined in the build specific FreeRTOSConfig.h header file. */ #ifdef configBUILD_SPECIFIC_INITIALISATION { configBUILD_SPECIFIC_INITIALISATION(); } #endif vLoggingInit(); /* * Seed random number generator. * * !!!NOTE!!! * This is not a secure method of generating a random number. Production * devices should use a True Random Number Generator (TRNG). */ time( &xTimeNow ); LogDebug( ( "Seed for randomizer: %lu\n", xTimeNow ) ); prvSRand( ( uint32_t ) xTimeNow ); LogDebug( ( "Random numbers: %08X %08X %08X %08X\n", ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32() ) ); } /*-----------------------------------------------------------*/ /* * 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 ) { ( void ) ulSourceAddress; ( void ) usSourcePort; ( void ) ulDestinationAddress; ( void ) usDestinationPort; return uxRand(); } /*-----------------------------------------------------------*/ /* * Set *pulNumber to a random number, and return pdTRUE. When the random number * generator is broken, it shall return pdFALSE. * The macros ipconfigRAND32() and configRAND32() are not in use * anymore in FreeRTOS+TCP. * * 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; } /*-----------------------------------------------------------*/ /* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is * used by the Idle task. */ void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, uint32_t * pulIdleTaskStackSize ) { /* If the buffers to be provided to the Idle task are declared inside this * function then they must be declared static - otherwise they will be allocated on * the stack and so not exists after this function exits. */ static StaticTask_t xIdleTaskTCB; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; /* Pass out a pointer to the StaticTask_t structure in which the Idle task's * state will be stored. */ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; /* Pass out the array that will be used as the Idle task's stack. */ *ppxIdleTaskStackBuffer = uxIdleTaskStack; /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. * Note that, as the array is necessarily of type StackType_t, * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } /*-----------------------------------------------------------*/ /* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the * application must provide an implementation of vApplicationGetTimerTaskMemory() * to provide the memory that is used by the Timer service task. */ void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t * pulTimerTaskStackSize ) { /* If the buffers to be provided to the Timer task are declared inside this * function then they must be declared static - otherwise they will be allocated on * the stack and so not exists after this function exits. */ static StaticTask_t xTimerTaskTCB; static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; /* Pass out a pointer to the StaticTask_t structure in which the Timer * task's state will be stored. */ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; /* Pass out the array that will be used as the Timer task's stack. */ *ppxTimerTaskStackBuffer = uxTimerTaskStack; /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. * Note that, as the array is necessarily of type StackType_t, * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; } /*-----------------------------------------------------------*/ void vApplicationMallocFailedHook( void ) { LogDebug( ( "Malloc failed\n" ) ); } /*-----------------------------------------------------------*/ void vApplicationStackOverflowHook( TaskHandle_t xTask, char * pcTaskName ) { volatile uint32_t ulSetToZeroToStepOut = 1UL; LogDebug( ( "Stack overflow in %s\n", pcTaskName ) ); ( void ) xTask; ( void ) pcTaskName; /* Remove compiler warnings if LogDebug() is not defined. */ taskENTER_CRITICAL(); while( ulSetToZeroToStepOut != 0 ) { } taskEXIT_CRITICAL(); }