From dddefe062e4e56e864b269fcb4779e831ae98fe2 Mon Sep 17 00:00:00 2001 From: yuhzheng Date: Fri, 31 Jan 2020 19:21:15 +0000 Subject: [PATCH] Sync FreeRTOS-Labs -CLI -TCP -Trace with the version in FreeRTOS-Plus. Projects under FreeRTOS-Labs directory are in beta, developers updating projects please make sure you are using the correct version of -CLI -TCP -Trace. If you must edit -CLI -TCP and -Trace, please ensure the copies are synced. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2815 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.c | 74 +- .../Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.h | 51 +- .../Source/FreeRTOS-Plus-CLI/History.txt | 5 + .../FreeRTOS-Plus-CLI/LICENSE_INFORMATION.txt | 20 +- .../Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c | 28 +- .../Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c | 50 +- .../Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c | 704 +++-- .../Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c | 55 +- .../FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c | 116 +- .../FreeRTOS_Stream_Buffer.c | 4 +- .../FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c | 400 +-- .../FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c | 54 +- .../FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c | 49 +- .../Source/FreeRTOS-Plus-TCP/History.txt | 18 +- .../include/FreeRTOSIPConfigDefaults.h | 37 +- .../FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h | 8 +- .../FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h | 4 +- .../FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h | 12 +- .../FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h | 13 +- .../include/FreeRTOS_IP_Private.h | 70 +- .../include/FreeRTOS_Sockets.h | 31 +- .../include/FreeRTOS_Stream_Buffer.h | 29 +- .../include/FreeRTOS_TCP_IP.h | 4 +- .../include/FreeRTOS_TCP_WIN.h | 4 +- .../include/FreeRTOS_UDP_IP.h | 4 +- .../include/FreeRTOS_errno_TCP.h | 4 +- .../include/IPTraceMacroDefaults.h | 4 +- .../include/NetworkBufferManagement.h | 6 +- .../include/NetworkInterface.h | 4 +- .../BufferManagement/BufferAllocation_1.c | 12 - .../BufferManagement/BufferAllocation_2.c | 4 +- .../portable/Compiler/Keil/pack_struct_end.h | 33 + .../Compiler/Keil/pack_struct_start.h | 48 + .../ATSAM4E/NetworkInterface.c | 118 +- .../portable/NetworkInterface/ATSAM4E/gmac.c | 3 +- .../NetworkInterface/Common/phyHandling.c | 109 +- .../NetworkInterface/M487/NetworkInterface.c | 331 +++ .../portable/NetworkInterface/M487/m480_eth.c | 448 +++ .../portable/NetworkInterface/M487/m480_eth.h | 164 ++ .../NetworkInterface/RX/NetworkInterface.c | 629 ++++ .../NetworkInterface/RX/ether_callback.c | 177 ++ .../STM32F7xx/NetworkInterface.c | 4 +- .../STM32Fxx/NetworkInterface.c | 534 ++-- .../NetworkInterface/STM32Fxx/readme.txt | 40 + .../STM32Fxx/stm32fxx_hal_eth.c | 456 +-- .../STM32Fxx/stm32fxx_hal_eth.h | 93 +- .../NetworkInterface/WinPCap/FaultInjection.c | 6 +- .../NetworkInterface/Zynq/NetworkInterface.c | 100 +- .../NetworkInterface/Zynq/x_emacpsif.h | 1 + .../NetworkInterface/Zynq/x_emacpsif_dma.c | 157 +- .../NetworkInterface/Zynq/x_emacpsif_hw.c | 12 +- .../Zynq/x_emacpsif_physpeed.c | 70 +- .../board_family/NetworkInterface.c | 63 + .../NetworkInterface/board_family/ReadMe.txt | 1 + .../NetworkInterface/esp32/NetworkInterface.c | 193 ++ .../NetworkInterface/include/phyHandling.h | 40 +- .../mw300_rd/NetworkInterface.c | 217 ++ ...Port - Copy with task notification array.h | 2565 ----------------- 58 files changed, 4102 insertions(+), 4388 deletions(-) create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_end.h create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_start.h create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.c create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.h create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/NetworkInterface.c create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/ether_callback.c create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/ReadMe.txt create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/esp32/NetworkInterface.c create mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c delete mode 100644 FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort - Copy with task notification array.h diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.c index 6629892a7..a9770159c 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.c @@ -1,43 +1,28 @@ /* - * FreeRTOS+CLI V1.0.3 (C) 2014 Real Time Engineers ltd. All rights reserved. + * FreeRTOS+CLI V1.0.4 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * This file is part of the FreeRTOS+CLI distribution. The FreeRTOS+CLI license - * terms are different to the FreeRTOS license terms. + * 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: * - * FreeRTOS+CLI uses a dual license model that allows the software to be used - * under a standard GPL open source license, or a commercial license. The - * standard GPL license (unlike the modified GPL license under which FreeRTOS - * itself is distributed) requires that all software statically linked with - * FreeRTOS+CLI is also distributed under the same GPL V2 license terms. - * Details of both license options follow: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * - * - Open source licensing - - * FreeRTOS+CLI is a free download and may be used, modified, evaluated and - * distributed without charge provided the user adheres to version two of the - * GNU General Public License (GPL) and does not remove the copyright notice or - * this text. The GPL V2 text is available on the gnu.org web site, and on the - * following URL: http://www.FreeRTOS.org/gpl-2.0.txt. - * - * - Commercial licensing - - * Businesses and individuals that for commercial or other reasons cannot comply - * with the terms of the GPL V2 license must obtain a low cost commercial - * license before incorporating FreeRTOS+CLI into proprietary software for - * distribution in any form. Commercial licenses can be purchased from - * http://shop.freertos.org/cli and do not require any source files to be - * changed. - * - * FreeRTOS+CLI is distributed in the hope that it will be useful. You cannot - * use FreeRTOS+CLI unless you agree that you use the software 'as is'. - * FreeRTOS+CLI is provided WITHOUT ANY WARRANTY; without even the implied - * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they - * implied, expressed, or statutory. - * - * 1 tab == 4 spaces! + * 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://www.FreeRTOS.org/FreeRTOS-Plus + * http://aws.amazon.com/freertos * + * 1 tab == 4 spaces! */ /* Standard includes. */ @@ -51,6 +36,16 @@ /* Utils includes. */ #include "FreeRTOS_CLI.h" +/* If the application writer needs to place the buffer used by the CLI at a +fixed address then set configAPPLICATION_PROVIDES_cOutputBuffer to 1 in +FreeRTOSConfig.h, then declare an array with the following name and size in +one of the application files: + char cOutputBuffer[ configCOMMAND_INT_MAX_OUTPUT_SIZE ]; +*/ +#ifndef configAPPLICATION_PROVIDES_cOutputBuffer + #define configAPPLICATION_PROVIDES_cOutputBuffer 0 +#endif + typedef struct xCOMMAND_INPUT_LIST { const CLI_Command_Definition_t *pxCommandLineDefinition; @@ -93,8 +88,17 @@ command interpreter by UART and by Ethernet. Sharing a buffer is done purely to save RAM. Note, however, that the command console itself is not re-entrant, so only one command interpreter interface can be used at any one time. For that reason, no attempt at providing mutual exclusion to the cOutputBuffer array is -attempted. */ -static char cOutputBuffer[ configCOMMAND_INT_MAX_OUTPUT_SIZE ]; +attempted. + +configAPPLICATION_PROVIDES_cOutputBuffer is provided to allow the application +writer to provide their own cOutputBuffer declaration in cases where the +buffer needs to be placed at a fixed address (rather than by the linker). */ +#if( configAPPLICATION_PROVIDES_cOutputBuffer == 0 ) + static char cOutputBuffer[ configCOMMAND_INT_MAX_OUTPUT_SIZE ]; +#else + extern char cOutputBuffer[ configCOMMAND_INT_MAX_OUTPUT_SIZE ]; +#endif + /*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.h index 5820bff2f..12fdd7062 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/FreeRTOS_CLI.h @@ -1,43 +1,28 @@ /* - * FreeRTOS+CLI V1.0.3 (C) 2014 Real Time Engineers ltd. All rights reserved. + * FreeRTOS+CLI V1.0.4 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * This file is part of the FreeRTOS+CLI distribution. The FreeRTOS+CLI license - * terms are different to the FreeRTOS license terms. + * 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: * - * FreeRTOS+CLI uses a dual license model that allows the software to be used - * under a standard GPL open source license, or a commercial license. The - * standard GPL license (unlike the modified GPL license under which FreeRTOS - * itself is distributed) requires that all software statically linked with - * FreeRTOS+CLI is also distributed under the same GPL V2 license terms. - * Details of both license options follow: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * - * - Open source licensing - - * FreeRTOS+CLI is a free download and may be used, modified, evaluated and - * distributed without charge provided the user adheres to version two of the - * GNU General Public License (GPL) and does not remove the copyright notice or - * this text. The GPL V2 text is available on the gnu.org web site, and on the - * following URL: http://www.FreeRTOS.org/gpl-2.0.txt. - * - * - Commercial licensing - - * Businesses and individuals that for commercial or other reasons cannot comply - * with the terms of the GPL V2 license must obtain a low cost commercial - * license before incorporating FreeRTOS+CLI into proprietary software for - * distribution in any form. Commercial licenses can be purchased from - * http://shop.freertos.org/cli and do not require any source files to be - * changed. - * - * FreeRTOS+CLI is distributed in the hope that it will be useful. You cannot - * use FreeRTOS+CLI unless you agree that you use the software 'as is'. - * FreeRTOS+CLI is provided WITHOUT ANY WARRANTY; without even the implied - * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they - * implied, expressed, or statutory. - * - * 1 tab == 4 spaces! + * 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://www.FreeRTOS.org/FreeRTOS-Plus + * http://aws.amazon.com/freertos * + * 1 tab == 4 spaces! */ #ifndef COMMAND_INTERPRETER_H diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/History.txt b/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/History.txt index 39b4668b2..8c62cf90b 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/History.txt +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/History.txt @@ -1,3 +1,8 @@ +Changes between V1.0.3 and V1.0.4 released + + + Update to use stdint and the FreeRTOS specific typedefs that were + introduced in FreeRTOS V8.0.0. + Changes between V1.0.2 and V1.0.3 released + Previously, and in line with good software engineering practice, the diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/LICENSE_INFORMATION.txt b/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/LICENSE_INFORMATION.txt index f9e7dff51..6812e2716 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/LICENSE_INFORMATION.txt +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-CLI/LICENSE_INFORMATION.txt @@ -1,7 +1,19 @@ -Note the FreeRTOS+CLI license terms are different to the FreeRTOS license terms. +FreeRTOS+CLI is released under the following MIT license. -FreeRTOS+CLI is dual licensed. The files are provided here under an unmodified -open source GNU GPL license. Commercial licenses are also available, and are -provided free for some hardware platforms. See http://www.FreeRTOS.org/cli +Copyright (C) 2017 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. diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c index fb8a3b4f2..c98a7e870 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -580,8 +580,24 @@ NetworkBufferDescriptor_t *pxNetworkBuffer; } } #endif + if( xIsCallingFromIPTask() != 0 ) + { + /* Only the IP-task is allowed to call this function directly. */ + xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE ); + } + else + { + IPStackEvent_t xSendEvent; - xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE ); + /* Send a message to the IP-task to send this ARP packet. */ + xSendEvent.eEventType = eNetworkTxEvent; + xSendEvent.pvData = ( void * ) pxNetworkBuffer; + if( xSendEventStructToIPTask( &xSendEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL ) + { + /* Failed to send the message, so release the network buffer. */ + vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + } + } } } @@ -589,6 +605,12 @@ void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffe { ARPPacket_t *pxARPPacket; + /* Buffer allocation ensures that buffers always have space + for an ARP packet. See buffer allocation implementations 1 + and 2 under portable/BufferManagement. */ + configASSERT( pxNetworkBuffer ); + configASSERT( pxNetworkBuffer->xDataLength >= sizeof(ARPPacket_t) ); + pxARPPacket = ( ARPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; /* memcpy the const part of the header information into the correct diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c index ea4629b14..9180426df 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -84,9 +84,9 @@ /* Offsets into the transmitted DHCP options fields at which various parameters are located. */ -#define dhcpCLIENT_IDENTIFIER_OFFSET ( 5 ) -#define dhcpREQUESTED_IP_ADDRESS_OFFSET ( 13 ) -#define dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ( 19 ) +#define dhcpCLIENT_IDENTIFIER_OFFSET ( 6 ) +#define dhcpREQUESTED_IP_ADDRESS_OFFSET ( 14 ) +#define dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ( 20 ) /* Values used in the DHCP packets. */ #define dhcpREQUEST_OPCODE ( 1 ) @@ -354,9 +354,7 @@ BaseType_t xGivingUp = pdFALSE; if( xDHCPData.xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD ) { - xDHCPData.ulTransactionId = ipconfigRAND32( ); - - if( 0 != xDHCPData.ulTransactionId ) + if( xApplicationGetRandomNumber( &( xDHCPData.ulTransactionId ) ) != pdFALSE ) { xDHCPData.xDHCPTxTime = xTaskGetTickCount( ); xDHCPData.xUseBroadcast = !xDHCPData.xUseBroadcast; @@ -589,10 +587,9 @@ static void prvInitialiseDHCP( void ) /* Initialise the parameters that will be set by the DHCP process. Per https://www.ietf.org/rfc/rfc2131.txt, Transaction ID should be a random value chosen by the client. */ - xDHCPData.ulTransactionId = ipconfigRAND32(); /* Check for random number generator API failure. */ - if( 0 != xDHCPData.ulTransactionId ) + if( xApplicationGetRandomNumber( &( xDHCPData.ulTransactionId ) ) != pdFALSE ) { xDHCPData.xUseBroadcast = 0; xDHCPData.ulOfferedIPAddress = 0UL; @@ -604,6 +601,10 @@ static void prvInitialiseDHCP( void ) FreeRTOS_debug_printf( ( "prvInitialiseDHCP: start after %lu ticks\n", dhcpINITIAL_TIMER_PERIOD ) ); vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD ); } + else + { + /* There was a problem with the randomiser. */ + } } /*-----------------------------------------------------------*/ @@ -642,8 +643,8 @@ const uint32_t ulMandatoryOptions = 2ul; /* DHCP server address, and the correct /* Walk through the options until the dhcpOPTION_END_BYTE byte is found, taking care not to walk off the end of the options. */ pucByte = &( pxDHCPMessage->ucFirstOptionByte ); - /* Maintain a pointer to the last valid byte (i.e. not the first - invalid byte). */ + /* Maintain a pointer to the last valid byte (i.e. not the first + invalid byte). */ pucLastByte = pucUDPPayload + lBytes - 1; while( pucByte <= pucLastByte ) @@ -665,7 +666,7 @@ const uint32_t ulMandatoryOptions = 2ul; /* DHCP server address, and the correct /* Stop if the response is malformed. */ if( pucByte < pucLastByte ) { - /* There are at least two bytes left. */ + /* There are at least two bytes left. */ ucLength = pucByte[ 1 ]; pucByte += 2; @@ -904,7 +905,7 @@ static const uint8_t ucDHCPRequestOptions[] = dhcpCLIENT_IDENTIFIER_OFFSET, dhcpREQUESTED_IP_ADDRESS_OFFSET and dhcpDHCP_SERVER_IP_ADDRESS_OFFSET. */ dhcpMESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_REQUEST, /* Message type option. */ - dhcpCLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0, /* Client identifier. */ + dhcpCLIENT_IDENTIFIER_OPTION_CODE, 7, 1, 0, 0, 0, 0, 0, 0, /* Client identifier. */ dhcpREQUEST_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address being requested. */ dhcpSERVER_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address of the DHCP server. */ dhcpOPTION_END_BYTE @@ -942,7 +943,7 @@ static const uint8_t ucDHCPDiscoverOptions[] = { /* Do not change the ordering without also changing dhcpCLIENT_IDENTIFIER_OFFSET. */ dhcpMESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_DISCOVER, /* Message type option. */ - dhcpCLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0, /* Client identifier. */ + dhcpCLIENT_IDENTIFIER_OPTION_CODE, 7, 1, 0, 0, 0, 0, 0, 0, /* Client identifier. */ dhcpPARAMETER_REQUEST_OPTION_CODE, 3, dhcpSUBNET_MASK_OPTION_CODE, dhcpGATEWAY_OPTION_CODE, dhcpDNS_SERVER_OPTIONS_CODE, /* Parameter request option. */ dhcpOPTION_END_BYTE }; @@ -968,13 +969,16 @@ size_t xOptionsLength = sizeof( ucDHCPDiscoverOptions ); static void prvPrepareLinkLayerIPLookUp( void ) { uint8_t ucLinkLayerIPAddress[ 2 ]; + uint32_t ulNumbers[ 2 ]; /* After DHCP has failed to answer, prepare everything to start trying-out LinkLayer IP-addresses, using the random method. */ xDHCPData.xDHCPTxTime = xTaskGetTickCount(); - ucLinkLayerIPAddress[ 0 ] = ( uint8_t )1 + ( uint8_t )( ipconfigRAND32() % 0xFDu ); /* get value 1..254 for IP-address 3rd byte of IP address to try. */ - ucLinkLayerIPAddress[ 1 ] = ( uint8_t )1 + ( uint8_t )( ipconfigRAND32() % 0xFDu ); /* get value 1..254 for IP-address 4th byte of IP address to try. */ + xApplicationGetRandomNumber( &( ulNumbers[ 0 ] ) ); + xApplicationGetRandomNumber( &( ulNumbers[ 1 ] ) ); + ucLinkLayerIPAddress[ 0 ] = ( uint8_t )1 + ( uint8_t )( ulNumbers[ 0 ] % 0xFDu ); /* get value 1..254 for IP-address 3rd byte of IP address to try. */ + ucLinkLayerIPAddress[ 1 ] = ( uint8_t )1 + ( uint8_t )( ulNumbers[ 1 ] % 0xFDu ); /* get value 1..254 for IP-address 4th byte of IP address to try. */ xNetworkAddressing.ulGatewayAddress = FreeRTOS_htonl( 0xA9FE0203 ); @@ -995,9 +999,15 @@ size_t xOptionsLength = sizeof( ucDHCPDiscoverOptions ); xNetworkAddressing.ulBroadcastAddress = ( xDHCPData.ulOfferedIPAddress & xNetworkAddressing.ulNetMask ) | ~xNetworkAddressing.ulNetMask; /* Close socket to ensure packets don't queue on it. not needed anymore as DHCP failed. but still need timer for ARP testing. */ - vSocketClose( xDHCPData.xDHCPSocket ); - xDHCPData.xDHCPSocket = NULL; - xDHCPData.xDHCPTxPeriod = pdMS_TO_TICKS( 3000ul + ( ipconfigRAND32() & 0x3fful ) ); /* do ARP test every (3 + 0-1024mS) seconds. */ + if( xDHCPData.xDHCPSocket != NULL ) + { + /* Close socket to ensure packets don't queue on it. */ + vSocketClose( xDHCPData.xDHCPSocket ); + xDHCPData.xDHCPSocket = NULL; + } + + xApplicationGetRandomNumber( &( ulNumbers[ 0 ] ) ); + xDHCPData.xDHCPTxPeriod = pdMS_TO_TICKS( 3000ul + ( ulNumbers[ 0 ] & 0x3ffuL ) ); /* do ARP test every (3 + 0-1024mS) seconds. */ xARPHadIPClash = pdFALSE; /* reset flag that shows if have ARP clash. */ vARPSendGratuitous(); diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c index de53b3eb8..43b246d26 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -47,58 +47,58 @@ #if( ipconfigUSE_DNS != 0 ) #if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) - #define dnsDNS_PORT 0x3500 - #define dnsONE_QUESTION 0x0100 - #define dnsOUTGOING_FLAGS 0x0001 /* Standard query. */ - #define dnsRX_FLAGS_MASK 0x0f80 /* The bits of interest in the flags field of incoming DNS messages. */ - #define dnsEXPECTED_RX_FLAGS 0x0080 /* Should be a response, without any errors. */ + #define dnsDNS_PORT 0x3500u + #define dnsONE_QUESTION 0x0100u + #define dnsOUTGOING_FLAGS 0x0001u /* Standard query. */ + #define dnsRX_FLAGS_MASK 0x0f80u /* The bits of interest in the flags field of incoming DNS messages. */ + #define dnsEXPECTED_RX_FLAGS 0x0080u /* Should be a response, without any errors. */ #else - #define dnsDNS_PORT 0x0035 - #define dnsONE_QUESTION 0x0001 - #define dnsOUTGOING_FLAGS 0x0100 /* Standard query. */ - #define dnsRX_FLAGS_MASK 0x800f /* The bits of interest in the flags field of incoming DNS messages. */ - #define dnsEXPECTED_RX_FLAGS 0x8000 /* Should be a response, without any errors. */ + #define dnsDNS_PORT 0x0035u + #define dnsONE_QUESTION 0x0001u + #define dnsOUTGOING_FLAGS 0x0100u /* Standard query. */ + #define dnsRX_FLAGS_MASK 0x800fu /* The bits of interest in the flags field of incoming DNS messages. */ + #define dnsEXPECTED_RX_FLAGS 0x8000u /* Should be a response, without any errors. */ #endif /* ipconfigBYTE_ORDER */ /* The maximum number of times a DNS request should be sent out if a response is not received, before giving up. */ #ifndef ipconfigDNS_REQUEST_ATTEMPTS - #define ipconfigDNS_REQUEST_ATTEMPTS 5 + #define ipconfigDNS_REQUEST_ATTEMPTS 5 #endif /* If the top two bits in the first character of a name field are set then the name field is an offset to the string, rather than the string itself. */ -#define dnsNAME_IS_OFFSET ( ( uint8_t ) 0xc0 ) +#define dnsNAME_IS_OFFSET ( ( uint8_t ) 0xc0 ) /* NBNS flags. */ -#define dnsNBNS_FLAGS_RESPONSE 0x8000 -#define dnsNBNS_FLAGS_OPCODE_MASK 0x7800 -#define dnsNBNS_FLAGS_OPCODE_QUERY 0x0000 -#define dnsNBNS_FLAGS_OPCODE_REGISTRATION 0x2800 +#define dnsNBNS_FLAGS_RESPONSE 0x8000u +#define dnsNBNS_FLAGS_OPCODE_MASK 0x7800u +#define dnsNBNS_FLAGS_OPCODE_QUERY 0x0000u +#define dnsNBNS_FLAGS_OPCODE_REGISTRATION 0x2800u /* Host types. */ -#define dnsTYPE_A_HOST 0x01 -#define dnsCLASS_IN 0x01 +#define dnsTYPE_A_HOST 0x01u +#define dnsCLASS_IN 0x01u /* LLMNR constants. */ -#define dnsLLMNR_TTL_VALUE 300000 -#define dnsLLMNR_FLAGS_IS_REPONSE 0x8000 +#define dnsLLMNR_TTL_VALUE 300000uL +#define dnsLLMNR_FLAGS_IS_REPONSE 0x8000u /* NBNS constants. */ -#define dnsNBNS_TTL_VALUE 3600 /* 1 hour valid */ -#define dnsNBNS_TYPE_NET_BIOS 0x0020 -#define dnsNBNS_CLASS_IN 0x01 -#define dnsNBNS_NAME_FLAGS 0x6000 -#define dnsNBNS_ENCODED_NAME_LENGTH 32 +#define dnsNBNS_TTL_VALUE 3600uL /* 1 hour valid */ +#define dnsNBNS_TYPE_NET_BIOS 0x0020u +#define dnsNBNS_CLASS_IN 0x01u +#define dnsNBNS_NAME_FLAGS 0x6000u +#define dnsNBNS_ENCODED_NAME_LENGTH 32 /* If the queried NBNS name matches with the device's name, the query will be responded to with these flags: */ -#define dnsNBNS_QUERY_RESPONSE_FLAGS ( 0x8500 ) +#define dnsNBNS_QUERY_RESPONSE_FLAGS ( 0x8500u ) /* Flag DNS parsing errors in situations where an IPv4 address is the return type. */ -#define dnsPARSE_ERROR 0UL +#define dnsPARSE_ERROR 0uL /* * Create a socket and bind it to the standard DNS port number. Return the @@ -109,44 +109,66 @@ static Socket_t prvCreateDNSSocket( void ); /* * Create the DNS message in the zero copy buffer passed in the first parameter. */ -static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer, const char *pcHostName, TickType_t xIdentifier ); +static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer, + const char *pcHostName, + TickType_t uxIdentifier ); /* * Simple routine that jumps over the NAME field of a resource record. */ -static uint8_t *prvSkipNameField( uint8_t *pucByte, size_t xSourceLen ); +static uint8_t * prvSkipNameField( uint8_t *pucByte, + size_t uxSourceLen ); /* * Process a response packet from a DNS server. + * The parameter 'xExpected' indicates whether the identifier in the reply + * was expected, and thus if the DNS cache may be updated with the reply. */ -static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, size_t xBufferLength, TickType_t xIdentifier ); +static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, + size_t uxBufferLength, + BaseType_t xExpected ); /* - * Prepare and send a message to a DNS server. 'xReadTimeOut_ms' will be passed as + * Prepare and send a message to a DNS server. 'uxReadTimeOut_ticks' will be passed as * zero, in case the user has supplied a call-back function. */ -static uint32_t prvGetHostByName( const char *pcHostName, TickType_t xIdentifier, TickType_t xReadTimeOut_ms ); +static uint32_t prvGetHostByName( const char *pcHostName, + TickType_t uxIdentifier, + TickType_t uxReadTimeOut_ticks ); /* * The NBNS and the LLMNR protocol share this reply function. */ #if( ( ipconfigUSE_NBNS == 1 ) || ( ipconfigUSE_LLMNR == 1 ) ) - static void prvReplyDNSMessage( NetworkBufferDescriptor_t *pxNetworkBuffer, BaseType_t lNetLength ); + static void prvReplyDNSMessage( NetworkBufferDescriptor_t *pxNetworkBuffer, + BaseType_t lNetLength ); #endif #if( ipconfigUSE_NBNS == 1 ) - static portINLINE void prvTreatNBNS( uint8_t *pucUDPPayloadBuffer, size_t xBufferLength, uint32_t ulIPAddress ); + static portINLINE void prvTreatNBNS( uint8_t *pucUDPPayloadBuffer, + size_t uxBufferLength, + uint32_t ulIPAddress ); #endif /* ipconfigUSE_NBNS */ + +#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 ) + static uint8_t * prvReadNameField( uint8_t *pucByte, + size_t uxSourceLen, + char *pcName, + size_t uxLen ); +#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */ + #if( ipconfigUSE_DNS_CACHE == 1 ) - static uint8_t *prvReadNameField( uint8_t *pucByte, size_t xSourceLen, char *pcName, size_t xLen ); - static void prvProcessDNSCache( const char *pcName, uint32_t *pulIP, uint32_t ulTTL, BaseType_t xLookUp ); + static void prvProcessDNSCache( const char *pcName, + uint32_t *pulIP, + uint32_t ulTTL, + BaseType_t xLookUp ); typedef struct xDNS_CACHE_TABLE_ROW { - uint32_t ulIPAddress; /* The IP address of an ARP cache entry. */ - char pcName[ ipconfigDNS_CACHE_NAME_LENGTH ]; /* The name of the host */ - uint32_t ulTTL; /* Time-to-Live (in seconds) from the DNS server. */ + uint32_t ulIPAddress; /* The IP address of an ARP cache entry. */ + char pcName[ ipconfigDNS_CACHE_NAME_LENGTH ]; /* The name of the host */ + uint32_t ulTTL; /* Time-to-Live (in seconds) from the DNS server. */ uint32_t ulTimeWhenAddedInSeconds; } DNSCacheRow_t; @@ -160,7 +182,7 @@ static uint32_t prvGetHostByName( const char *pcHostName, TickType_t xIdentifier #if( ipconfigUSE_LLMNR == 1 ) const MACAddress_t xLLMNR_MacAdress = { { 0x01, 0x00, 0x5e, 0x00, 0x00, 0xfc } }; -#endif /* ipconfigUSE_LLMNR == 1 */ +#endif /* ipconfigUSE_LLMNR == 1 */ /*-----------------------------------------------------------*/ @@ -208,7 +230,7 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t; struct xLLMNRAnswer { uint8_t ucNameCode; - uint8_t ucNameOffset; /* The name is not repeated in the answer, only the offset is given with "0xc0 " */ + uint8_t ucNameOffset; /* The name is not repeated in the answer, only the offset is given with "0xc0 " */ uint16_t usType; uint16_t usClass; uint32_t ulTTL; @@ -247,32 +269,34 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t; uint16_t usClass; uint32_t ulTTL; uint16_t usDataLength; - uint16_t usNbFlags; /* NetBIOS flags 0x6000 : IP-address, big-endian */ + uint16_t usNbFlags; /* NetBIOS flags 0x6000 : IP-address, big-endian */ uint32_t ulIPAddress; } #include "pack_struct_end.h" typedef struct xNBNSAnswer NBNSAnswer_t; -#endif /* ipconfigUSE_NBNS == 1 */ + #endif /* ipconfigUSE_NBNS == 1 */ /*-----------------------------------------------------------*/ #if( ipconfigUSE_DNS_CACHE == 1 ) uint32_t FreeRTOS_dnslookup( const char *pcHostName ) { - uint32_t ulIPAddress = 0UL; + uint32_t ulIPAddress = 0uL; + prvProcessDNSCache( pcHostName, &ulIPAddress, 0, pdTRUE ); return ulIPAddress; } #endif /* ipconfigUSE_DNS_CACHE == 1 */ /*-----------------------------------------------------------*/ -#if( ipconfigDNS_USE_CALLBACKS != 0 ) +#if( ipconfigDNS_USE_CALLBACKS == 1 ) - typedef struct xDNS_Callback { - TickType_t xRemaningTime; /* Timeout in ms */ + typedef struct xDNS_Callback + { + TickType_t uxRemaningTime; /* Timeout in ms */ FOnDNSEvent pCallbackFunction; /* Function to be called when the address has been found or when a timeout has beeen reached */ - TimeOut_t xTimeoutState; + TimeOut_t uxTimeoutState; void *pvSearchID; struct xLIST_ITEM xListItem; char pcName[ 1 ]; @@ -283,7 +307,7 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t; /* Define FreeRTOS_gethostbyname() as a normal blocking call. */ uint32_t FreeRTOS_gethostbyname( const char *pcHostName ) { - return FreeRTOS_gethostbyname_a( pcHostName, ( FOnDNSEvent ) NULL, ( void* )NULL, 0 ); + return FreeRTOS_gethostbyname_a( pcHostName, ( FOnDNSEvent ) NULL, ( void * ) NULL, 0 ); } /*-----------------------------------------------------------*/ @@ -304,23 +328,25 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t; void vDNSCheckCallBack( void *pvSearchID ) { const ListItem_t *pxIterator; - const MiniListItem_t* xEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xCallbackList ); + const MiniListItem_t * xEnd = ( const MiniListItem_t * ) listGET_END_MARKER( &xCallbackList ); vTaskSuspendAll(); { for( pxIterator = ( const ListItem_t * ) listGET_NEXT( xEnd ); pxIterator != ( const ListItem_t * ) xEnd; - ) + ) { - DNSCallback_t *pxCallback = ( DNSCallback_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); + DNSCallback_t *pxCallback = ( DNSCallback_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); + /* Move to the next item because we might remove this item */ - pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ); + pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ); + if( ( pvSearchID != NULL ) && ( pvSearchID == pxCallback->pvSearchID ) ) { uxListRemove( &pxCallback->xListItem ); vPortFree( pxCallback ); } - else if( xTaskCheckForTimeOut( &pxCallback->xTimeoutState, &pxCallback->xRemaningTime ) != pdFALSE ) + else if( xTaskCheckForTimeOut( &pxCallback->uxTimeoutState, &pxCallback->uxRemaningTime ) != pdFALSE ) { pxCallback->pCallbackFunction( pxCallback->pcName, pxCallback->pvSearchID, 0 ); uxListRemove( &pxCallback->xListItem ); @@ -346,28 +372,38 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t; /* FreeRTOS_gethostbyname_a() was called along with callback parameters. Store them in a list for later reference. */ - static void vDNSSetCallBack( const char *pcHostName, void *pvSearchID, FOnDNSEvent pCallbackFunction, TickType_t xTimeout, TickType_t xIdentifier ); - static void vDNSSetCallBack( const char *pcHostName, void *pvSearchID, FOnDNSEvent pCallbackFunction, TickType_t xTimeout, TickType_t xIdentifier ) + static void vDNSSetCallBack( const char *pcHostName, + void *pvSearchID, + FOnDNSEvent pCallbackFunction, + TickType_t uxTimeout, + TickType_t uxIdentifier ); + static void vDNSSetCallBack( const char *pcHostName, + void *pvSearchID, + FOnDNSEvent pCallbackFunction, + TickType_t uxTimeout, + TickType_t uxIdentifier ) { - size_t lLength = strlen( pcHostName ); - DNSCallback_t *pxCallback = ( DNSCallback_t * )pvPortMalloc( sizeof( *pxCallback ) + lLength ); + size_t lLength = strlen( pcHostName ); + DNSCallback_t *pxCallback = ( DNSCallback_t * ) pvPortMalloc( sizeof( *pxCallback ) + lLength ); /* Translate from ms to number of clock ticks. */ - xTimeout /= portTICK_PERIOD_MS; + uxTimeout /= portTICK_PERIOD_MS; + if( pxCallback != NULL ) { if( listLIST_IS_EMPTY( &xCallbackList ) ) { /* This is the first one, start the DNS timer to check for timeouts */ - vIPReloadDNSTimer( FreeRTOS_min_uint32( 1000U, xTimeout ) ); + vIPReloadDNSTimer( FreeRTOS_min_uint32( 1000U, uxTimeout ) ); } + strcpy( pxCallback->pcName, pcHostName ); pxCallback->pCallbackFunction = pCallbackFunction; pxCallback->pvSearchID = pvSearchID; - pxCallback->xRemaningTime = xTimeout; - vTaskSetTimeOutState( &pxCallback->xTimeoutState ); - listSET_LIST_ITEM_OWNER( &( pxCallback->xListItem ), ( void* ) pxCallback ); - listSET_LIST_ITEM_VALUE( &( pxCallback->xListItem ), xIdentifier ); + pxCallback->uxRemaningTime = uxTimeout; + vTaskSetTimeOutState( &pxCallback->uxTimeoutState ); + listSET_LIST_ITEM_OWNER( &( pxCallback->xListItem ), ( void * ) pxCallback ); + listSET_LIST_ITEM_VALUE( &( pxCallback->xListItem ), uxIdentifier ); vTaskSuspendAll(); { vListInsertEnd( &xCallbackList, &pxCallback->xListItem ); @@ -378,12 +414,17 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t; /*-----------------------------------------------------------*/ /* A DNS reply was received, see if there is any matching entry and - call the handler. */ - static void vDNSDoCallback( TickType_t xIdentifier, const char *pcName, uint32_t ulIPAddress ); - static void vDNSDoCallback( TickType_t xIdentifier, const char *pcName, uint32_t ulIPAddress ) + call the handler. Returns pdTRUE if uxIdentifier was recognised. */ + static BaseType_t xDNSDoCallback( TickType_t uxIdentifier, + const char *pcName, + uint32_t ulIPAddress ); + static BaseType_t xDNSDoCallback( TickType_t uxIdentifier, + const char *pcName, + uint32_t ulIPAddress ) { - const ListItem_t *pxIterator; - const MiniListItem_t* xEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xCallbackList ); + BaseType_t xResult = pdFALSE; + const ListItem_t *pxIterator; + const MiniListItem_t * xEnd = ( const MiniListItem_t * ) listGET_END_MARKER( &xCallbackList ); vTaskSuspendAll(); { @@ -391,111 +432,132 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t; pxIterator != ( const ListItem_t * ) xEnd; pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) ) { - if( listGET_LIST_ITEM_VALUE( pxIterator ) == xIdentifier ) + /* The cast will take away the 'configLIST_VOLATILE' */ + if( uxIdentifier == ( TickType_t ) listGET_LIST_ITEM_VALUE( pxIterator ) ) { - DNSCallback_t *pxCallback = ( DNSCallback_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); + DNSCallback_t *pxCallback = ( DNSCallback_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); + pxCallback->pCallbackFunction( pcName, pxCallback->pvSearchID, ulIPAddress ); uxListRemove( &pxCallback->xListItem ); vPortFree( pxCallback ); + if( listLIST_IS_EMPTY( &xCallbackList ) ) { + /* The list of outstanding requests is empty. No need for periodic polling. */ vIPSetDnsTimerEnableState( pdFALSE ); } + + xResult = pdTRUE; break; } } } xTaskResumeAll(); + return xResult; } -#endif /* ipconfigDNS_USE_CALLBACKS != 0 */ +#endif /* ipconfigDNS_USE_CALLBACKS == 1 */ /*-----------------------------------------------------------*/ #if( ipconfigDNS_USE_CALLBACKS == 0 ) -uint32_t FreeRTOS_gethostbyname( const char *pcHostName ) + uint32_t FreeRTOS_gethostbyname( const char *pcHostName ) #else -uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, FOnDNSEvent pCallback, void *pvSearchID, TickType_t xTimeout ) + uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, + FOnDNSEvent pCallback, + void *pvSearchID, + TickType_t uxTimeout ) #endif { -uint32_t ulIPAddress = 0UL; -TickType_t xReadTimeOut_ms = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME; -TickType_t xIdentifier = 0; +uint32_t ulIPAddress = 0uL; +TickType_t uxReadTimeOut_ticks = ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS; +TickType_t uxIdentifier = 0u; +BaseType_t xHasRandom = pdFALSE; - /* If the supplied hostname is IP address, convert it to uint32_t - and return. */ - #if( ipconfigINCLUDE_FULL_INET_ADDR == 1 ) + if( pcHostName != NULL ) { - ulIPAddress = FreeRTOS_inet_addr( pcHostName ); - } - #endif /* ipconfigINCLUDE_FULL_INET_ADDR == 1 */ + /* If the supplied hostname is IP address, convert it to uint32_t + and return. */ + #if( ipconfigINCLUDE_FULL_INET_ADDR == 1 ) + { + ulIPAddress = FreeRTOS_inet_addr( pcHostName ); + } + #endif /* ipconfigINCLUDE_FULL_INET_ADDR == 1 */ - /* If a DNS cache is used then check the cache before issuing another DNS - request. */ - #if( ipconfigUSE_DNS_CACHE == 1 ) - { - if( ulIPAddress == 0UL ) + /* If a DNS cache is used then check the cache before issuing another DNS + request. */ + #if( ipconfigUSE_DNS_CACHE == 1 ) { - ulIPAddress = FreeRTOS_dnslookup( pcHostName ); - if( ulIPAddress != 0 ) + if( ulIPAddress == 0uL ) { - FreeRTOS_debug_printf( ( "FreeRTOS_gethostbyname: found '%s' in cache: %lxip\n", pcHostName, ulIPAddress ) ); - } - else - { - /* prvGetHostByName will be called to start a DNS lookup */ + ulIPAddress = FreeRTOS_dnslookup( pcHostName ); + + if( ulIPAddress != 0 ) + { + FreeRTOS_debug_printf( ( "FreeRTOS_gethostbyname: found '%s' in cache: %lxip\n", pcHostName, ulIPAddress ) ); + } + else + { + /* prvGetHostByName will be called to start a DNS lookup. */ + } } } - } - #endif /* ipconfigUSE_DNS_CACHE == 1 */ + #endif /* ipconfigUSE_DNS_CACHE == 1 */ - /* Generate a unique identifier. */ - if( 0 == ulIPAddress ) - { - xIdentifier = ( TickType_t )ipconfigRAND32( ); - } + /* Generate a unique identifier. */ + if( ulIPAddress == 0uL ) + { + uint32_t ulNumber; - #if( ipconfigDNS_USE_CALLBACKS != 0 ) - { - if( pCallback != NULL ) + xHasRandom = xApplicationGetRandomNumber( &( ulNumber ) ); + /* DNS identifiers are 16-bit. */ + uxIdentifier = ( TickType_t ) ( ulNumber & 0xffffu ); + /* ipconfigRAND32() may not return a non-zero value. */ + } + + #if( ipconfigDNS_USE_CALLBACKS == 1 ) { - if( ulIPAddress == 0UL ) + if( pCallback != NULL ) { - /* The user has provided a callback function, so do not block on recvfrom() */ - if( 0 != xIdentifier ) + if( ulIPAddress == 0uL ) { - xReadTimeOut_ms = 0; - vDNSSetCallBack( pcHostName, pvSearchID, pCallback, xTimeout, ( TickType_t )xIdentifier ); + /* The user has provided a callback function, so do not block on recvfrom() */ + if( xHasRandom != pdFALSE ) + { + uxReadTimeOut_ticks = 0u; + vDNSSetCallBack( pcHostName, pvSearchID, pCallback, uxTimeout, uxIdentifier ); + } + } + else + { + /* The IP address is known, do the call-back now. */ + pCallback( pcHostName, pvSearchID, ulIPAddress ); } - } - else - { - /* The IP address is known, do the call-back now. */ - pCallback( pcHostName, pvSearchID, ulIPAddress ); } } - } - #endif + #endif /* if ( ipconfigDNS_USE_CALLBACKS == 1 ) */ - if( ( ulIPAddress == 0UL ) && ( 0 != xIdentifier ) ) - { - ulIPAddress = prvGetHostByName( pcHostName, xIdentifier, xReadTimeOut_ms ); + if( ( ulIPAddress == 0uL ) && ( xHasRandom != pdFALSE ) ) + { + ulIPAddress = prvGetHostByName( pcHostName, uxIdentifier, uxReadTimeOut_ticks ); + } } - return ulIPAddress; } /*-----------------------------------------------------------*/ -static uint32_t prvGetHostByName( const char *pcHostName, TickType_t xIdentifier, TickType_t xReadTimeOut_ms ) +static uint32_t prvGetHostByName( const char *pcHostName, + TickType_t uxIdentifier, + TickType_t uxReadTimeOut_ticks ) { struct freertos_sockaddr xAddress; Socket_t xDNSSocket; -uint32_t ulIPAddress = 0UL; +uint32_t ulIPAddress = 0uL; uint8_t *pucUDPPayloadBuffer; uint32_t ulAddressLength = sizeof( struct freertos_sockaddr ); BaseType_t xAttempt; int32_t lBytes; -size_t xPayloadLength, xExpectedPayloadLength; -TickType_t xWriteTimeOut_ms = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME; +size_t uxPayloadLength, uxExpectedPayloadLength; +TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS; #if( ipconfigUSE_LLMNR == 1 ) BaseType_t bHasDot = pdFALSE; @@ -505,7 +567,8 @@ TickType_t xWriteTimeOut_ms = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME; if not then LLMNR can be used as the lookup method. */ #if( ipconfigUSE_LLMNR == 1 ) { - const char *pucPtr; + const char *pucPtr; + for( pucPtr = pcHostName; *pucPtr; pucPtr++ ) { if( *pucPtr == '.' ) @@ -519,26 +582,26 @@ TickType_t xWriteTimeOut_ms = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME; /* Two is added at the end for the count of characters in the first subdomain part and the string end byte. */ - xExpectedPayloadLength = sizeof( DNSMessage_t ) + strlen( pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2u; + uxExpectedPayloadLength = sizeof( DNSMessage_t ) + strlen( pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2u; xDNSSocket = prvCreateDNSSocket(); if( xDNSSocket != NULL ) { - FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xWriteTimeOut_ms, sizeof( TickType_t ) ); - FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xReadTimeOut_ms, sizeof( TickType_t ) ); + FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &uxWriteTimeOut_ticks, sizeof( TickType_t ) ); + FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &uxReadTimeOut_ticks, sizeof( TickType_t ) ); for( xAttempt = 0; xAttempt < ipconfigDNS_REQUEST_ATTEMPTS; xAttempt++ ) { /* Get a buffer. This uses a maximum delay, but the delay will be capped to ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS so the return value still needs to be tested. */ - pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xExpectedPayloadLength, portMAX_DELAY ); + pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( uxExpectedPayloadLength, portMAX_DELAY ); if( pucUDPPayloadBuffer != NULL ) { /* Create the message in the obtained buffer. */ - xPayloadLength = prvCreateDNSMessage( pucUDPPayloadBuffer, pcHostName, xIdentifier ); + uxPayloadLength = prvCreateDNSMessage( pucUDPPayloadBuffer, pcHostName, uxIdentifier ); iptraceSENDING_DNS_REQUEST(); @@ -550,8 +613,8 @@ TickType_t xWriteTimeOut_ms = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME; if( bHasDot == pdFALSE ) { /* Use LLMNR addressing. */ - ( ( DNSMessage_t * ) pucUDPPayloadBuffer) -> usFlags = 0; - xAddress.sin_addr = ipLLMNR_IP_ADDR; /* Is in network byte order. */ + ( ( DNSMessage_t * ) pucUDPPayloadBuffer )->usFlags = 0; + xAddress.sin_addr = ipLLMNR_IP_ADDR; /* Is in network byte order. */ xAddress.sin_port = FreeRTOS_ntohs( ipLLMNR_PORT ); } else @@ -562,24 +625,45 @@ TickType_t xWriteTimeOut_ms = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME; xAddress.sin_port = dnsDNS_PORT; } - ulIPAddress = 0UL; + ulIPAddress = 0uL; - if( FreeRTOS_sendto( xDNSSocket, pucUDPPayloadBuffer, xPayloadLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) != 0 ) + if( FreeRTOS_sendto( xDNSSocket, pucUDPPayloadBuffer, uxPayloadLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) != 0 ) { /* Wait for the reply. */ lBytes = FreeRTOS_recvfrom( xDNSSocket, &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xAddress, &ulAddressLength ); if( lBytes > 0 ) { + BaseType_t xExpected; + DNSMessage_t *pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer; + + /* See if the identifiers match. */ + if( uxIdentifier == ( TickType_t ) pxDNSMessageHeader->usIdentifier ) + { + xExpected = pdTRUE; + } + else + { + /* The reply was not expected. */ + xExpected = pdFALSE; + } + /* The reply was received. Process it. */ - ulIPAddress = prvParseDNSReply( pucUDPPayloadBuffer, lBytes, xIdentifier ); + #if( ipconfigDNS_USE_CALLBACKS == 0 ) + /* It is useless to analyse the unexpected reply + unless asynchronous look-ups are enabled. */ + if( xExpected != pdFALSE ) + #endif /* ipconfigDNS_USE_CALLBACKS == 0 */ + { + ulIPAddress = prvParseDNSReply( pucUDPPayloadBuffer, ( size_t ) lBytes, xExpected ); + } /* Finished with the buffer. The zero copy interface is being used, so the buffer must be freed by the task. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); - if( ulIPAddress != 0UL ) + if( ulIPAddress != 0uL ) { /* All done. */ break; @@ -593,6 +677,13 @@ TickType_t xWriteTimeOut_ms = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME; FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); } } + + if( uxReadTimeOut_ticks == 0u ) + { + /* This DNS lookup is asynchronous, using a call-back: + send the request only once. */ + break; + } } /* Finished with the socket. */ @@ -603,19 +694,21 @@ TickType_t xWriteTimeOut_ms = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME; } /*-----------------------------------------------------------*/ -static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer, const char *pcHostName, TickType_t xIdentifier ) +static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer, + const char *pcHostName, + TickType_t uxIdentifier ) { DNSMessage_t *pxDNSMessageHeader; uint8_t *pucStart, *pucByte; DNSTail_t *pxTail; static const DNSMessage_t xDefaultPartDNSHeader = { - 0, /* The identifier will be overwritten. */ - dnsOUTGOING_FLAGS, /* Flags set for standard query. */ - dnsONE_QUESTION, /* One question is being asked. */ - 0, /* No replies are included. */ - 0, /* No authorities. */ - 0 /* No additional authorities. */ + 0, /* The identifier will be overwritten. */ + dnsOUTGOING_FLAGS, /* Flags set for standard query. */ + dnsONE_QUESTION, /* One question is being asked. */ + 0, /* No replies are included. */ + 0, /* No authorities. */ + 0 /* No additional authorities. */ }; /* Copy in the const part of the header. */ @@ -623,7 +716,7 @@ static const DNSMessage_t xDefaultPartDNSHeader = /* Write in a unique identifier. */ pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer; - pxDNSMessageHeader->usIdentifier = ( uint16_t ) xIdentifier; + pxDNSMessageHeader->usIdentifier = ( uint16_t ) uxIdentifier; /* Create the resource record at the end of the header. First find the end of the header. */ @@ -659,15 +752,14 @@ static const DNSMessage_t xDefaultPartDNSHeader = ( *pucStart )--; pucStart = pucByte; - } while( *pucByte != 0x00 ); /* Finish off the record. */ - pxTail = (DNSTail_t *)( pucByte + 1 ); + pxTail = ( DNSTail_t * ) ( pucByte + 1 ); - vSetField16( pxTail, DNSTail_t, usType, dnsTYPE_A_HOST ); /* Type A: host */ - vSetField16( pxTail, DNSTail_t, usClass, dnsCLASS_IN ); /* 1: Class IN */ + vSetField16( pxTail, DNSTail_t, usType, dnsTYPE_A_HOST ); /* Type A: host */ + vSetField16( pxTail, DNSTail_t, usClass, dnsCLASS_IN ); /* 1: Class IN */ /* Return the total size of the generated message, which is the space from the last written byte to the beginning of the buffer. */ @@ -675,14 +767,17 @@ static const DNSMessage_t xDefaultPartDNSHeader = } /*-----------------------------------------------------------*/ -#if( ipconfigUSE_DNS_CACHE == 1 ) +#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 ) - static uint8_t *prvReadNameField( uint8_t *pucByte, size_t xSourceLen, char *pcName, size_t xDestLen ) + static uint8_t * prvReadNameField( uint8_t *pucByte, + size_t uxSourceLen, + char *pcName, + size_t uxDestLen ) { - size_t xNameLen = 0; + size_t uxNameLen = 0; BaseType_t xCount; - if( 0 == xSourceLen ) + if( 0 == uxSourceLen ) { return NULL; } @@ -692,7 +787,7 @@ static const DNSMessage_t xDefaultPartDNSHeader = if( ( *pucByte & dnsNAME_IS_OFFSET ) == dnsNAME_IS_OFFSET ) { /* Jump over the two byte offset. */ - if( xSourceLen > sizeof( uint16_t ) ) + if( uxSourceLen > sizeof( uint16_t ) ) { pucByte += sizeof( uint16_t ); } @@ -704,23 +799,23 @@ static const DNSMessage_t xDefaultPartDNSHeader = else { /* pucByte points to the full name. Walk over the string. */ - while( ( NULL != pucByte ) && ( *pucByte != 0x00 ) && ( xSourceLen > 1 ) ) + while( ( NULL != pucByte ) && ( *pucByte != 0x00u ) && ( uxSourceLen > 1u ) ) { /* If this is not the first time through the loop, then add a separator in the output. */ - if( ( xNameLen > 0 ) && ( xNameLen < ( xDestLen - 1 ) ) ) + if( ( uxNameLen > 0 ) && ( uxNameLen < ( uxDestLen - 1u ) ) ) { - pcName[ xNameLen++ ] = '.'; + pcName[ uxNameLen++ ] = '.'; } /* Process the first/next sub-string. */ - for( xCount = *(pucByte++), xSourceLen--; - xCount-- && xSourceLen > 1; - pucByte++, xSourceLen-- ) + for( xCount = *( pucByte++ ), uxSourceLen--; + xCount-- && uxSourceLen > 1u; + pucByte++, uxSourceLen-- ) { - if( xNameLen < xDestLen - 1 ) + if( uxNameLen < uxDestLen - 1u ) { - pcName[ xNameLen++ ] = *( ( char * )pucByte ); + pcName[ uxNameLen++ ] = *( ( char * ) pucByte ); } else { @@ -737,8 +832,8 @@ static const DNSMessage_t xDefaultPartDNSHeader = if( 0x00 == *pucByte ) { pucByte++; - xSourceLen--; - pcName[ xNameLen++ ] = '\0'; + uxSourceLen--; + pcName[ uxNameLen++ ] = '\0'; } else { @@ -749,14 +844,15 @@ static const DNSMessage_t xDefaultPartDNSHeader = return pucByte; } -#endif /* ipconfigUSE_DNS_CACHE == 1 */ +#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */ /*-----------------------------------------------------------*/ -static uint8_t *prvSkipNameField( uint8_t *pucByte, size_t xSourceLen ) +static uint8_t * prvSkipNameField( uint8_t *pucByte, + size_t uxSourceLen ) { - size_t xChunkLength; +size_t uxChunkLength; - if( 0 == xSourceLen ) + if( 0u == uxSourceLen ) { return NULL; } @@ -766,7 +862,7 @@ static uint8_t *prvSkipNameField( uint8_t *pucByte, size_t xSourceLen ) if( ( *pucByte & dnsNAME_IS_OFFSET ) == dnsNAME_IS_OFFSET ) { /* Jump over the two byte offset. */ - if( xSourceLen > sizeof( uint16_t ) ) + if( uxSourceLen > sizeof( uint16_t ) ) { pucByte += sizeof( uint16_t ); } @@ -778,14 +874,14 @@ static uint8_t *prvSkipNameField( uint8_t *pucByte, size_t xSourceLen ) else { /* pucByte points to the full name. Walk over the string. */ - while( ( *pucByte != 0x00 ) && ( xSourceLen > 1 ) ) + while( ( *pucByte != 0x00u ) && ( uxSourceLen > 1u ) ) { - xChunkLength = *pucByte + 1; + uxChunkLength = *pucByte + 1u; - if( xSourceLen > xChunkLength ) + if( uxSourceLen > uxChunkLength ) { - xSourceLen -= xChunkLength; - pucByte += xChunkLength; + uxSourceLen -= uxChunkLength; + pucByte += uxChunkLength; } else { @@ -797,7 +893,7 @@ static uint8_t *prvSkipNameField( uint8_t *pucByte, size_t xSourceLen ) /* Confirm that a fully formed name was found. */ if( NULL != pucByte ) { - if( 0x00 == *pucByte ) + if( 0x00u == *pucByte ) { pucByte++; } @@ -812,19 +908,33 @@ static uint8_t *prvSkipNameField( uint8_t *pucByte, size_t xSourceLen ) } /*-----------------------------------------------------------*/ +/* The function below will only be called : +when ipconfigDNS_USE_CALLBACKS == 1 +when ipconfigUSE_LLMNR == 1 +for testing purposes, by the module iot_test_freertos_tcp.c +*/ uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer ) { DNSMessage_t *pxDNSMessageHeader; - - if( pxNetworkBuffer->xDataLength >= sizeof( DNSMessage_t ) ) - { - pxDNSMessageHeader = - ( DNSMessage_t * )( pxNetworkBuffer->pucEthernetBuffer + sizeof( UDPPacket_t ) ); - - prvParseDNSReply( ( uint8_t * )pxDNSMessageHeader, - pxNetworkBuffer->xDataLength, - ( uint32_t )pxDNSMessageHeader->usIdentifier ); - } +size_t uxPayloadSize; + + /* Only proceed if the payload length indicated in the header + appears to be valid. */ + if( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) ) + { + uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ); + + if( uxPayloadSize >= sizeof( DNSMessage_t ) ) + { + pxDNSMessageHeader = + ( DNSMessage_t * ) ( pxNetworkBuffer->pucEthernetBuffer + sizeof( UDPPacket_t ) ); + + /* The parameter pdFALSE indicates that the reply was not expected. */ + prvParseDNSReply( ( uint8_t * ) pxDNSMessageHeader, + uxPayloadSize, + pdFALSE ); + } + } /* The packet was not consumed. */ return pdFAIL; @@ -833,15 +943,16 @@ DNSMessage_t *pxDNSMessageHeader; #if( ipconfigUSE_NBNS == 1 ) - uint32_t ulNBNSHandlePacket (NetworkBufferDescriptor_t *pxNetworkBuffer ) + uint32_t ulNBNSHandlePacket( NetworkBufferDescriptor_t * pxNetworkBuffer ) { UDPPacket_t *pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; uint8_t *pucUDPPayloadBuffer = pxNetworkBuffer->pucEthernetBuffer + sizeof( UDPPacket_t ); + size_t uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ); - /* The network buffer data length has already been set to the + /* The network buffer data length has already been set to the length of the UDP payload. */ prvTreatNBNS( pucUDPPayloadBuffer, - pxNetworkBuffer->xDataLength, + uxPayloadSize, pxUDPPacket->xIPHeader.ulSourceIPAddress ); /* The packet was not consumed. */ @@ -851,45 +962,48 @@ DNSMessage_t *pxDNSMessageHeader; #endif /* ipconfigUSE_NBNS */ /*-----------------------------------------------------------*/ -static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, size_t xBufferLength, TickType_t xIdentifier ) +static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, + size_t uxBufferLength, + BaseType_t xExpected ) { DNSMessage_t *pxDNSMessageHeader; DNSAnswerRecord_t *pxDNSAnswerRecord; -uint32_t ulIPAddress = 0UL; +uint32_t ulIPAddress = 0uL; #if( ipconfigUSE_LLMNR == 1 ) char *pcRequestedName = NULL; #endif uint8_t *pucByte; -size_t xSourceBytesRemaining; +size_t uxSourceBytesRemaining; uint16_t x, usDataLength, usQuestions; +BaseType_t xDoStore = xExpected; #if( ipconfigUSE_LLMNR == 1 ) uint16_t usType = 0, usClass = 0; #endif -#if( ipconfigUSE_DNS_CACHE == 1 ) +#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 ) char pcName[ ipconfigDNS_CACHE_NAME_LENGTH ] = ""; #endif /* Ensure that the buffer is of at least minimal DNS message length. */ - if( xBufferLength < sizeof( DNSMessage_t ) ) + if( uxBufferLength < sizeof( DNSMessage_t ) ) { return dnsPARSE_ERROR; } - else - { - xSourceBytesRemaining = xBufferLength; - } + + uxSourceBytesRemaining = uxBufferLength; /* Parse the DNS message header. */ pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer; - if( pxDNSMessageHeader->usIdentifier == ( uint16_t ) xIdentifier ) + /* Introduce a do {} while (0) to allow the use of breaks. */ + do { /* Start at the first byte after the header. */ pucByte = pucUDPPayloadBuffer + sizeof( DNSMessage_t ); - xSourceBytesRemaining -= sizeof( DNSMessage_t ); + uxSourceBytesRemaining -= sizeof( DNSMessage_t ); /* Skip any question records. */ usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions ); + for( x = 0; x < usQuestions; x++ ) { #if( ipconfigUSE_LLMNR == 1 ) @@ -901,11 +1015,11 @@ uint16_t x, usDataLength, usQuestions; } #endif -#if( ipconfigUSE_DNS_CACHE == 1 ) +#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 ) if( x == 0 ) { pucByte = prvReadNameField( pucByte, - xSourceBytesRemaining, + uxSourceBytesRemaining, pcName, sizeof( pcName ) ); @@ -914,35 +1028,32 @@ uint16_t x, usDataLength, usQuestions; { return dnsPARSE_ERROR; } - else - { - xSourceBytesRemaining = ( pucUDPPayloadBuffer + xBufferLength ) - pucByte; - } + + uxSourceBytesRemaining = ( pucUDPPayloadBuffer + uxBufferLength ) - pucByte; } else -#endif /* ipconfigUSE_DNS_CACHE */ +#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */ { /* Skip the variable length pcName field. */ pucByte = prvSkipNameField( pucByte, - xSourceBytesRemaining ); + uxSourceBytesRemaining ); /* Check for a malformed response. */ if( NULL == pucByte ) { return dnsPARSE_ERROR; } - else - { - xSourceBytesRemaining = pucUDPPayloadBuffer + xBufferLength - pucByte; - } + + uxSourceBytesRemaining = ( size_t ) + ( pucUDPPayloadBuffer + uxBufferLength - pucByte ); } /* Check the remaining buffer size. */ - if( xSourceBytesRemaining >= sizeof( uint32_t ) ) + if( uxSourceBytesRemaining >= sizeof( uint32_t ) ) { #if( ipconfigUSE_LLMNR == 1 ) { - /* usChar2u16 returns value in host endianness */ + /* usChar2u16 returns value in host endianness. */ usType = usChar2u16( pucByte ); usClass = usChar2u16( pucByte + 2 ); } @@ -950,7 +1061,7 @@ uint16_t x, usDataLength, usQuestions; /* Skip the type and class fields. */ pucByte += sizeof( uint32_t ); - xSourceBytesRemaining -= sizeof( uint32_t ); + uxSourceBytesRemaining -= sizeof( uint32_t ); } else { @@ -967,25 +1078,24 @@ uint16_t x, usDataLength, usQuestions; for( x = 0; x < pxDNSMessageHeader->usAnswers; x++ ) { pucByte = prvSkipNameField( pucByte, - xSourceBytesRemaining ); + uxSourceBytesRemaining ); /* Check for a malformed response. */ if( NULL == pucByte ) { return dnsPARSE_ERROR; } - else - { - xSourceBytesRemaining = pucUDPPayloadBuffer + xBufferLength - pucByte; - } + + uxSourceBytesRemaining = ( size_t ) + ( pucUDPPayloadBuffer + uxBufferLength - pucByte ); /* Is there enough data for an IPv4 A record answer and, if so, is this an A record? */ - if( xSourceBytesRemaining >= sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) && - usChar2u16( pucByte ) == dnsTYPE_A_HOST ) + if( ( uxSourceBytesRemaining >= ( sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) ) ) && + ( usChar2u16( pucByte ) == dnsTYPE_A_HOST ) ) { /* This is the required record type and is of sufficient size. */ - pxDNSAnswerRecord = ( DNSAnswerRecord_t * )pucByte; + pxDNSAnswerRecord = ( DNSAnswerRecord_t * ) pucByte; /* Sanity check the data length of an IPv4 answer. */ if( FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength ) == sizeof( uint32_t ) ) @@ -995,39 +1105,56 @@ uint16_t x, usDataLength, usQuestions; pucByte + sizeof( DNSAnswerRecord_t ), sizeof( uint32_t ) ); - #if( ipconfigUSE_DNS_CACHE == 1 ) + #if( ipconfigDNS_USE_CALLBACKS == 1 ) { - prvProcessDNSCache( pcName, &ulIPAddress, pxDNSAnswerRecord->ulTTL, pdFALSE ); + /* See if any asynchronous call was made to FreeRTOS_gethostbyname_a() */ + if( xDNSDoCallback( ( TickType_t ) pxDNSMessageHeader->usIdentifier, pcName, ulIPAddress ) != pdFALSE ) + { + /* This device has requested this DNS look-up. + The result may be stored in the DNS cache. */ + xDoStore = pdTRUE; + } } - #endif /* ipconfigUSE_DNS_CACHE */ - #if( ipconfigDNS_USE_CALLBACKS != 0 ) + #endif /* ipconfigDNS_USE_CALLBACKS == 1 */ + #if( ipconfigUSE_DNS_CACHE == 1 ) { - /* See if any asynchronous call was made to FreeRTOS_gethostbyname_a() */ - vDNSDoCallback( ( TickType_t ) pxDNSMessageHeader->usIdentifier, pcName, ulIPAddress ); + /* The reply will only be stored in the DNS cache when the + request was issued by this device. */ + if( xDoStore != pdFALSE ) + { + prvProcessDNSCache( pcName, &ulIPAddress, pxDNSAnswerRecord->ulTTL, pdFALSE ); + } + + /* Show what has happened. */ + FreeRTOS_printf( ( "DNS[0x%04X]: The answer to '%s' (%xip) will%s be stored\n", + ( unsigned ) pxDNSMessageHeader->usIdentifier, + pcName, + ( unsigned ) FreeRTOS_ntohl( ulIPAddress ), + ( xDoStore != 0 ) ? "" : " NOT" ) ); } - #endif /* ipconfigDNS_USE_CALLBACKS != 0 */ + #endif /* ipconfigUSE_DNS_CACHE */ } pucByte += sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ); - xSourceBytesRemaining -= ( sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) ); + uxSourceBytesRemaining -= ( sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) ); break; } - else if( xSourceBytesRemaining >= sizeof( DNSAnswerRecord_t ) ) + else if( uxSourceBytesRemaining >= sizeof( DNSAnswerRecord_t ) ) { /* It's not an A record, so skip it. Get the header location and then jump over the header. */ - pxDNSAnswerRecord = ( DNSAnswerRecord_t * )pucByte; + pxDNSAnswerRecord = ( DNSAnswerRecord_t * ) pucByte; pucByte += sizeof( DNSAnswerRecord_t ); - xSourceBytesRemaining -= sizeof( DNSAnswerRecord_t ); + uxSourceBytesRemaining -= sizeof( DNSAnswerRecord_t ); /* Determine the length of the answer data from the header. */ usDataLength = FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength ); /* Jump over the answer. */ - if( xSourceBytesRemaining >= usDataLength ) + if( uxSourceBytesRemaining >= usDataLength ) { pucByte += usDataLength; - xSourceBytesRemaining -= usDataLength; + uxSourceBytesRemaining -= usDataLength; } else { @@ -1037,12 +1164,13 @@ uint16_t x, usDataLength, usQuestions; } } } + #if( ipconfigUSE_LLMNR == 1 ) else if( usQuestions && ( usType == dnsTYPE_A_HOST ) && ( usClass == dnsCLASS_IN ) ) { /* If this is not a reply to our DNS request, it might an LLMNR request. */ - if( xApplicationDNSQueryHook ( ( pcRequestedName + 1 ) ) ) + if( xApplicationDNSQueryHook( ( pcRequestedName + 1 ) ) ) { int16_t usLength; NetworkBufferDescriptor_t *pxNewBuffer = NULL; @@ -1051,13 +1179,12 @@ uint16_t x, usDataLength, usQuestions; if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) ) { - BaseType_t xDataLength = xBufferLength + sizeof( UDPHeader_t ) + sizeof( EthernetHeader_t ) + sizeof( IPHeader_t ); + BaseType_t xDataLength = uxBufferLength + sizeof( UDPHeader_t ) + sizeof( EthernetHeader_t ) + sizeof( IPHeader_t ); - /* The field xDataLength was set to the length of the UDP payload. - The answer (reply) will be longer than the request, so the packet - must be duplicaed into a bigger buffer */ + /* Set the size of the outgoing packet. */ pxNetworkBuffer->xDataLength = xDataLength; - pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, xDataLength + 16 ); + pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, xDataLength + sizeof( LLMNRAnswer_t ) ); + if( pxNewBuffer != NULL ) { BaseType_t xOffset1, xOffset2; @@ -1071,7 +1198,6 @@ uint16_t x, usDataLength, usQuestions; pucByte = pucUDPPayloadBuffer + xOffset1; pcRequestedName = ( char * ) ( pucUDPPayloadBuffer + xOffset2 ); pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer; - } else { @@ -1079,21 +1205,22 @@ uint16_t x, usDataLength, usQuestions; pxNetworkBuffer = NULL; } } + if( pxNetworkBuffer != NULL ) { - pxAnswer = (LLMNRAnswer_t *)pucByte; + pxAnswer = ( LLMNRAnswer_t * ) pucByte; /* We leave 'usIdentifier' and 'usQuestions' untouched */ - vSetField16( pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_REPONSE ); /* Set the response flag */ - vSetField16( pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */ - vSetField16( pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */ - vSetField16( pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */ + vSetField16( pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_REPONSE ); /* Set the response flag */ + vSetField16( pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */ + vSetField16( pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */ + vSetField16( pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */ pxAnswer->ucNameCode = dnsNAME_IS_OFFSET; - pxAnswer->ucNameOffset = ( uint8_t )( pcRequestedName - ( char * ) pucUDPPayloadBuffer ); + pxAnswer->ucNameOffset = ( uint8_t ) ( pcRequestedName - ( char * ) pucUDPPayloadBuffer ); - vSetField16( pxAnswer, LLMNRAnswer_t, usType, dnsTYPE_A_HOST ); /* Type A: host */ - vSetField16( pxAnswer, LLMNRAnswer_t, usClass, dnsCLASS_IN ); /* 1: Class IN */ + vSetField16( pxAnswer, LLMNRAnswer_t, usType, dnsTYPE_A_HOST ); /* Type A: host */ + vSetField16( pxAnswer, LLMNRAnswer_t, usClass, dnsCLASS_IN ); /* 1: Class IN */ vSetField32( pxAnswer, LLMNRAnswer_t, ulTTL, dnsLLMNR_TTL_VALUE ); vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, 4 ); vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) ); @@ -1110,6 +1237,12 @@ uint16_t x, usDataLength, usQuestions; } } #endif /* ipconfigUSE_LLMNR == 1 */ + } while( 0 ); + + if( xExpected == pdFALSE ) + { + /* Do not return a valid IP-address in case the reply was not expected. */ + ulIPAddress = 0uL; } return ulIPAddress; @@ -1118,15 +1251,17 @@ uint16_t x, usDataLength, usQuestions; #if( ipconfigUSE_NBNS == 1 ) - static void prvTreatNBNS( uint8_t *pucUDPPayloadBuffer, size_t xBufferLength, uint32_t ulIPAddress ) + static void prvTreatNBNS( uint8_t *pucUDPPayloadBuffer, + size_t uxBufferLength, + uint32_t ulIPAddress ) { - uint16_t usFlags, usType, usClass; - uint8_t *pucSource, *pucTarget; - uint8_t ucByte; - uint8_t ucNBNSName[ 17 ]; + uint16_t usFlags, usType, usClass; + uint8_t *pucSource, *pucTarget; + uint8_t ucByte; + uint8_t ucNBNSName[ 17 ]; /* Check for minimum buffer size. */ - if( xBufferLength < sizeof( NBNSRequest_t ) ) + if( uxBufferLength < sizeof( NBNSRequest_t ) ) { return; } @@ -1140,10 +1275,11 @@ uint16_t x, usDataLength, usQuestions; usClass = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usClass ) ); /* Not used for now */ - ( void )usClass; + ( void ) usClass; + /* For NBNS a name is 16 bytes long, written with capitals only. Make sure that the copy is terminated with a zero. */ - pucTarget = ucNBNSName + sizeof(ucNBNSName ) - 2; + pucTarget = ucNBNSName + sizeof( ucNBNSName ) - 2; pucTarget[ 1 ] = '\0'; /* Start with decoding the last 2 bytes. */ @@ -1201,14 +1337,11 @@ uint16_t x, usDataLength, usQuestions; if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) ) { NetworkBufferDescriptor_t *pxNewBuffer; - BaseType_t xDataLength = pxNetworkBuffer->xDataLength + sizeof( UDPHeader_t ) + - sizeof( EthernetHeader_t ) + sizeof( IPHeader_t ); - /* The field xDataLength was set to the length of the UDP payload. - The answer (reply) will be longer than the request, so the packet - must be duplicated into a bigger buffer */ - pxNetworkBuffer->xDataLength = xDataLength; - pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, xDataLength + 16 ); + /* The field xDataLength was set to the total length of the UDP packet, + i.e. the payload size plus sizeof( UDPPacket_t ). */ + pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, pxNetworkBuffer->xDataLength + sizeof( NBNSAnswer_t ) ); + if( pxNewBuffer != NULL ) { pucUDPPayloadBuffer = pxNewBuffer->pucEthernetBuffer + sizeof( UDPPacket_t ); @@ -1224,7 +1357,7 @@ uint16_t x, usDataLength, usQuestions; /* Should not occur: pucUDPPayloadBuffer is part of a xNetworkBufferDescriptor */ if( pxNetworkBuffer != NULL ) { - pxMessage = (DNSMessage_t *)pucUDPPayloadBuffer; + pxMessage = ( DNSMessage_t * ) pucUDPPayloadBuffer; /* As the fields in the structures are not word-aligned, we have to copy the values byte-by-byte using macro's vSetField16() and vSetField32() */ @@ -1234,12 +1367,12 @@ uint16_t x, usDataLength, usQuestions; vSetField16( pxMessage, DNSMessage_t, usAuthorityRRs, 0 ); vSetField16( pxMessage, DNSMessage_t, usAdditionalRRs, 0 ); - pxAnswer = (NBNSAnswer_t *)( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usType ) ); + pxAnswer = ( NBNSAnswer_t * ) ( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usType ) ); - vSetField16( pxAnswer, NBNSAnswer_t, usType, usType ); /* Type */ - vSetField16( pxAnswer, NBNSAnswer_t, usClass, dnsNBNS_CLASS_IN ); /* Class */ + vSetField16( pxAnswer, NBNSAnswer_t, usType, usType ); /* Type */ + vSetField16( pxAnswer, NBNSAnswer_t, usClass, dnsNBNS_CLASS_IN ); /* Class */ vSetField32( pxAnswer, NBNSAnswer_t, ulTTL, dnsNBNS_TTL_VALUE ); - vSetField16( pxAnswer, NBNSAnswer_t, usDataLength, 6 ); /* 6 bytes including the length field */ + vSetField16( pxAnswer, NBNSAnswer_t, usDataLength, 6 ); /* 6 bytes including the length field */ vSetField16( pxAnswer, NBNSAnswer_t, usNbFlags, dnsNBNS_NAME_FLAGS ); vSetField32( pxAnswer, NBNSAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) ); @@ -1251,7 +1384,7 @@ uint16_t x, usDataLength, usQuestions; } } -#endif /* ipconfigUSE_NBNS */ +#endif /* ipconfigUSE_NBNS */ /*-----------------------------------------------------------*/ static Socket_t prvCreateDNSSocket( void ) @@ -1259,7 +1392,6 @@ static Socket_t prvCreateDNSSocket( void ) Socket_t xSocket = NULL; struct freertos_sockaddr xAddress; BaseType_t xReturn; -TickType_t xTimeoutTime = pdMS_TO_TICKS( 200 ); /* This must be the first time this function has been called. Create the socket. */ @@ -1277,9 +1409,7 @@ TickType_t xTimeoutTime = pdMS_TO_TICKS( 200 ); } else { - /* Set the send and receive timeouts. */ - FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) ); - FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) ); + /* The send and receive timeouts will be set later on. */ } return xSocket; @@ -1288,13 +1418,14 @@ TickType_t xTimeoutTime = pdMS_TO_TICKS( 200 ); #if( ( ipconfigUSE_NBNS == 1 ) || ( ipconfigUSE_LLMNR == 1 ) ) - static void prvReplyDNSMessage( NetworkBufferDescriptor_t *pxNetworkBuffer, BaseType_t lNetLength ) + static void prvReplyDNSMessage( NetworkBufferDescriptor_t *pxNetworkBuffer, + BaseType_t lNetLength ) { UDPPacket_t *pxUDPPacket; IPHeader_t *pxIPHeader; UDPHeader_t *pxUDPHeader; - pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer; + pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; pxIPHeader = &pxUDPPacket->xIPHeader; pxUDPHeader = &pxUDPPacket->xUDPHeader; /* HT: started using defines like 'ipSIZE_OF_xxx' */ @@ -1314,9 +1445,9 @@ TickType_t xTimeoutTime = pdMS_TO_TICKS( 200 ); #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) { /* calculate the IP header checksum */ - pxIPHeader->usHeaderChecksum = 0x00; - pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER ); - pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum ); + pxIPHeader->usHeaderChecksum = 0x00; + pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0uL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER ); + pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum ); /* calculate the UDP checksum for outgoing package */ usGenerateProtocolChecksum( ( uint8_t* ) pxUDPPacket, pxNetworkBuffer->xDataLength, pdTRUE ); @@ -1332,14 +1463,16 @@ TickType_t xTimeoutTime = pdMS_TO_TICKS( 200 ); #if( ipconfigUSE_DNS_CACHE == 1 ) - static void prvProcessDNSCache( const char *pcName, uint32_t *pulIP, uint32_t ulTTL, BaseType_t xLookUp ) + static void prvProcessDNSCache( const char *pcName, + uint32_t *pulIP, + uint32_t ulTTL, + BaseType_t xLookUp ) { BaseType_t x; BaseType_t xFound = pdFALSE; uint32_t ulCurrentTimeSeconds = ( xTaskGetTickCount() / portTICK_PERIOD_MS ) / 1000; static BaseType_t xFreeEntry = 0; - configASSERT(pcName); - + configASSERT(pcName); /* For each entry in the DNS cache table. */ for( x = 0; x < ipconfigDNS_CACHE_ENTRIES; x++ ) @@ -1395,6 +1528,7 @@ TickType_t xTimeoutTime = pdMS_TO_TICKS( 200 ); xDNSCache[ xFreeEntry ].ulTimeWhenAddedInSeconds = ulCurrentTimeSeconds; xFreeEntry++; + if( xFreeEntry == ipconfigDNS_CACHE_ENTRIES ) { xFreeEntry = 0; diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c index d6c36f31c..c94f55dd7 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -65,7 +65,9 @@ a constant. */ /* Time delay between repeated attempts to initialise the network hardware. */ -#define ipINITIALISATION_RETRY_DELAY ( pdMS_TO_TICKS( 3000 ) ) +#ifndef ipINITIALISATION_RETRY_DELAY + #define ipINITIALISATION_RETRY_DELAY ( pdMS_TO_TICKS( 3000 ) ) +#endif /* Defines how often the ARP timer callback function is executed. The time is shorted in the Windows simulator as simulated time is not real time. */ @@ -394,6 +396,12 @@ struct freertos_sockaddr xAddress; prvHandleEthernetPacket( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ) ); break; + case eNetworkTxEvent: + /* Send a network packet. The ownership will be transferred to + the driver, which will release it after delivery. */ + xNetworkInterfaceOutput( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ), pdTRUE ); + break; + case eARPTimerEvent : /* The ARP timer has expired, process the ARP cache. */ vARPAgeCache(); @@ -820,20 +828,20 @@ void *pvReturn; /*-----------------------------------------------------------*/ NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer, - BaseType_t xNewLength ) + size_t uxNewLength ) { NetworkBufferDescriptor_t * pxNewBuffer; /* This function is only used when 'ipconfigZERO_COPY_TX_DRIVER' is set to 1. The transmit routine wants to have ownership of the network buffer descriptor, because it will pass the buffer straight to DMA. */ - pxNewBuffer = pxGetNetworkBufferWithDescriptor( ( size_t ) xNewLength, ( TickType_t ) 0 ); + pxNewBuffer = pxGetNetworkBufferWithDescriptor( uxNewLength, ( TickType_t ) 0 ); if( pxNewBuffer != NULL ) { /* Set the actual packet size in case a bigger buffer than requested was returned. */ - pxNewBuffer->xDataLength = xNewLength; + pxNewBuffer->xDataLength = uxNewLength; /* Copy the original packet information. */ pxNewBuffer->ulIPAddress = pxNetworkBuffer->ulIPAddress; @@ -986,7 +994,10 @@ BaseType_t xReturn = pdFALSE; /* Added to prevent ARP flood to gateway. Ensure the gateway is on the same subnet as the IP address. */ - configASSERT( ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) == ( xNetworkAddressing.ulGatewayAddress & xNetworkAddressing.ulNetMask ) ); + if( xNetworkAddressing.ulGatewayAddress != 0ul ) + { + configASSERT( ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) == ( xNetworkAddressing.ulGatewayAddress & xNetworkAddressing.ulNetMask ) ); + } } #endif /* ipconfigUSE_DHCP == 1 */ @@ -1111,7 +1122,8 @@ void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint3 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = FREERTOS_SO_UDPCKSUM_OUT; pxNetworkBuffer->ulIPAddress = ulIPAddress; pxNetworkBuffer->usPort = ipPACKET_CONTAINS_ICMP_DATA; - pxNetworkBuffer->xDataLength = xNumberOfBytesToSend + sizeof( ICMPHeader_t ); + /* xDataLength is the size of the total packet, including the Ethernet header. */ + pxNetworkBuffer->xDataLength = xNumberOfBytesToSend + sizeof( ICMPPacket_t ); /* Send to the stack. */ xStackTxEvent.pvData = pxNetworkBuffer; @@ -1600,23 +1612,24 @@ uint8_t ucProtocol; /* Only proceed if the payload length indicated in the header appears to be valid. */ - if ( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) ) + if ( ( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) ) && ( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) >= sizeof( UDPHeader_t ) ) ) { - /* Ensure that downstream UDP packet handling has the lesser - * of: the actual network buffer Ethernet frame length, or - * the sender's UDP packet header payload length, minus the - * size of the UDP header. - * - * The size of the UDP packet structure in this implementation - * includes the size of the Ethernet header, the size of - * the IP header, and the size of the UDP header. + size_t uxPayloadSize_1, uxPayloadSize_2; + /* The UDP payload size can be calculated by subtracting the + * header size from `xDataLength`. + * However, the `xDataLength` may be longer that expected, + * e.g. when a small packet is padded with zero's. + * The UDP header contains a field `usLength` reflecting + * the payload size plus the UDP header ( 8 bytes ). + * Set `xDataLength` to the size of the headers, + * plus the lower of the two calculated payload sizes. */ - pxNetworkBuffer->xDataLength -= sizeof( UDPPacket_t ); - if( ( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) - sizeof( UDPHeader_t ) ) < - pxNetworkBuffer->xDataLength ) + uxPayloadSize_1 = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ); + uxPayloadSize_2 = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) - sizeof( UDPHeader_t ); + if( uxPayloadSize_1 > uxPayloadSize_2 ) { - pxNetworkBuffer->xDataLength = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) - sizeof( UDPHeader_t ); + pxNetworkBuffer->xDataLength = uxPayloadSize_2 + sizeof( UDPPacket_t ); } /* Fields in pxNetworkBuffer (usPort, ulIPAddress) are network order. */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c index 13feb832a..e15834849 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -385,7 +385,7 @@ Socket_t xReturn; } } - return ( SocketSet_t * ) pxSocketSet; + return ( SocketSet_t ) pxSocketSet; } #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */ @@ -702,9 +702,11 @@ EventBits_t xEventBits = ( EventBits_t ) 0; } taskEXIT_CRITICAL(); - /* The returned value is the data length, which may have been capped to - the receive buffer size. */ - lReturn = ( int32_t ) pxNetworkBuffer->xDataLength; + /* The returned value is the length of the payload data, which is + calculated at the total packet size minus the headers. + The validity of `xDataLength` prvProcessIPPacket has been confirmed + in 'prvProcessIPPacket()'. */ + lReturn = ( int32_t ) ( pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ) ); if( pxSourceAddress != NULL ) { @@ -833,7 +835,8 @@ FreeRTOS_Socket_t *pxSocket; if( pxNetworkBuffer != NULL ) { - pxNetworkBuffer->xDataLength = xTotalDataLength; + /* xDataLength is the size of the total packet, including the Ethernet header. */ + pxNetworkBuffer->xDataLength = xTotalDataLength + sizeof( UDPPacket_t ); pxNetworkBuffer->usPort = pxDestinationAddress->sin_port; pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket ); pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr; @@ -854,7 +857,7 @@ FreeRTOS_Socket_t *pxSocket; { if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) ) { - pxSocket->u.xUDP.pxHandleSent( (Socket_t *)pxSocket, xTotalDataLength ); + pxSocket->u.xUDP.pxHandleSent( ( Socket_t )pxSocket, xTotalDataLength ); } } #endif /* ipconfigUSE_CALLBACKS */ @@ -1421,7 +1424,7 @@ FreeRTOS_Socket_t *pxSocket; break; #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */ - #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 ) || ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT != 0 ) + #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 ) case FREERTOS_SO_WAKEUP_CALLBACK: { /* Each socket can have a callback function that is executed @@ -1433,16 +1436,6 @@ FreeRTOS_Socket_t *pxSocket; break; #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */ - #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT != 0 ) - case FREERTOS_SO_WAKE_CALLBACK_CONTEXT: - { - /* Each socket wake callback may be passed a user context. */ - pxSocket->pvUserWakeCallbackContext = ( void * ) pvOptionValue; - xReturn = 0; - } - break; - #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT */ - case FREERTOS_SO_SET_LOW_HIGH_WATER: { LowHighWater_t *pxLowHighWater = ( LowHighWater_t * ) pvOptionValue; @@ -1664,7 +1657,6 @@ const uint16_t usEphemeralPortCount = uint16_t usIterations = usEphemeralPortCount; uint32_t ulRandomSeed = 0; uint16_t usResult = 0; -BaseType_t xGotZeroOnce = pdFALSE; const List_t *pxList; #if ipconfigUSE_TCP == 1 @@ -1685,21 +1677,10 @@ const List_t *pxList; point. */ do { - /* Generate a random seed. */ - ulRandomSeed = ipconfigRAND32( ); - /* Only proceed if the random number generator succeeded. */ - if( 0 == ulRandomSeed ) + if( xApplicationGetRandomNumber( &( ulRandomSeed ) ) == pdFALSE ) { - if( pdFALSE == xGotZeroOnce ) - { - xGotZeroOnce = pdTRUE; - continue; - } - else - { - break; - } + break; } /* Map the random to a candidate port. */ @@ -1904,16 +1885,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket ) pxSocket->pxUserWakeCallback( pxSocket ); } } - #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */ - - #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT == 1 ) - { - if( pxSocket->pxUserWakeCallback != NULL ) - { - pxSocket->pxUserWakeCallback( pxSocket, pxSocket->pvUserWakeCallbackContext ); - } - } - #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT */ + #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */ #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) { @@ -2432,8 +2404,8 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket ) xResult = -pdFREERTOS_ERRNO_ENOMEM; } else if( pxSocket->u.xTCP.ucTCPState == eCLOSED || - pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT || - pxSocket->u.xTCP.ucTCPState == eCLOSING ) + pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT || + pxSocket->u.xTCP.ucTCPState == eCLOSING ) { xResult = -pdFREERTOS_ERRNO_ENOTCONN; } @@ -2472,25 +2444,25 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket ) '*pxLength' will contain the number of bytes that may be written. */ uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength ) { - uint8_t *pucReturn = NULL; + uint8_t *pucReturn = NULL; FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket; StreamBuffer_t *pxBuffer = NULL; - *pxLength = 0; + *pxLength = 0; - /* Confirm that this is a TCP socket before dereferencing structure - member pointers. */ - if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE ) - { - pxBuffer = pxSocket->u.xTCP.txStream; - if( pxBuffer != NULL ) - { - BaseType_t xSpace = ( BaseType_t )uxStreamBufferGetSpace( pxBuffer ); - BaseType_t xRemain = ( BaseType_t )( pxBuffer->LENGTH - pxBuffer->uxHead ); + /* Confirm that this is a TCP socket before dereferencing structure + member pointers. */ + if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE ) + { + pxBuffer = pxSocket->u.xTCP.txStream; + if( pxBuffer != NULL ) + { + BaseType_t xSpace = ( BaseType_t )uxStreamBufferGetSpace( pxBuffer ); + BaseType_t xRemain = ( BaseType_t )( pxBuffer->LENGTH - pxBuffer->uxHead ); - *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain ); - pucReturn = pxBuffer->ucArray + pxBuffer->uxHead; - } + *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain ); + pucReturn = pxBuffer->ucArray + pxBuffer->uxHead; + } } return pucReturn; @@ -2923,20 +2895,20 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket ) #if( ipconfigUSE_TCP == 1 ) - const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket ) - { - FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket; - struct xSTREAM_BUFFER *pxReturn = NULL; + const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket ) + { + FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket; + struct xSTREAM_BUFFER *pxReturn = NULL; - /* Confirm that this is a TCP socket before dereferencing structure - member pointers. */ - if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE ) - { - pxReturn = pxSocket->u.xTCP.rxStream; - } + /* Confirm that this is a TCP socket before dereferencing structure + member pointers. */ + if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE ) + { + pxReturn = pxSocket->u.xTCP.rxStream; + } - return pxReturn; - } + return pxReturn; + } #endif /* ipconfigUSE_TCP */ /*-----------------------------------------------------------*/ @@ -3100,7 +3072,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket ) break; } - pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount ); + pxSocket->u.xTCP.pxHandleReceive( ( Socket_t )pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount ); uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE ); } } else diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c index 994da7384..53a5c69c6 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c index 3b1c5a1e5..d26756589 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -227,6 +227,19 @@ static BaseType_t prvTCPPrepareConnect( FreeRTOS_Socket_t *pxSocket ); */ static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer ); +/* + * Identify and deal with a single TCP header option, advancing the pointer to + * the header. This function returns pdTRUE or pdFALSE depending on whether the + * caller should continue to parse more header options or break the loop. + */ +static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow); + +/* + * Skip past TCP header options when doing Selective ACK, until there are no + * more options left. + */ +static void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const ppucLen ); + /* * Set the initial properties in the options fields, like the preferred * value of MSS and whether SACK allowed. Will be transmitted in the state @@ -312,7 +325,7 @@ static BaseType_t prvTCPHandleState( FreeRTOS_Socket_t *pxSocket, NetworkBufferD * payload, just flags). */ static BaseType_t prvTCPSendSpecialPacketHelper( NetworkBufferDescriptor_t *pxNetworkBuffer, - uint8_t ucTCPFlags ); + uint8_t ucTCPFlags ); /* * A "challenge ACK" is as per https://tools.ietf.org/html/rfc5961#section-3.2, @@ -1151,7 +1164,7 @@ TCPHeader_t * pxTCPHeader; const unsigned char *pucPtr; const unsigned char *pucLast; TCPWindow_t *pxTCPWindow; -UBaseType_t uxNewMSS; +BaseType_t xShouldContinueLoop; pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer ); pxTCPHeader = &pxTCPPacket->xTCPHeader; @@ -1169,162 +1182,184 @@ UBaseType_t uxNewMSS; /* The comparison with pucLast is only necessary in case the option data are corrupted, we don't like to run into invalid memory and crash. */ - while( pucPtr < pucLast ) + xShouldContinueLoop = pdTRUE; + while( ( pucPtr < pucLast ) && ( xShouldContinueLoop == pdTRUE ) ) { - UBaseType_t xRemainingOptionsBytes = pucLast - pucPtr; + xShouldContinueLoop = prvSingleStepTCPHeaderOptions( &pucPtr, &pucLast, &pxSocket, &pxTCPWindow ); + } +} - if( pucPtr[ 0 ] == TCP_OPT_END ) - { - /* End of options. */ - break; - } - if( pucPtr[ 0 ] == TCP_OPT_NOOP) +/*-----------------------------------------------------------*/ + +static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow) +{ + UBaseType_t uxNewMSS; + UBaseType_t xRemainingOptionsBytes = ( *ppucLast ) - ( *ppucPtr ); + unsigned char ucLen; + + if( ( *ppucPtr )[ 0 ] == TCP_OPT_END ) + { + /* End of options. */ + return pdFALSE; + } + if( ( *ppucPtr )[ 0 ] == TCP_OPT_NOOP) + { + /* NOP option, inserted to make the length a multiple of 4. */ + ( *ppucPtr )++; + return pdTRUE; + } + + /* Any other well-formed option must be at least two bytes: the option + type byte followed by a length byte. */ + if( xRemainingOptionsBytes < 2 ) + { + return pdFALSE; + } +#if( ipconfigUSE_TCP_WIN != 0 ) + else if( ( *ppucPtr )[ 0 ] == TCP_OPT_WSOPT ) + { + /* Confirm that the option fits in the remaining buffer space. */ + if( ( xRemainingOptionsBytes < TCP_OPT_WSOPT_LEN ) || ( ( *ppucPtr )[ 1 ] != TCP_OPT_WSOPT_LEN ) ) { - /* NOP option, inserted to make the length a multiple of 4. */ - pucPtr++; - continue; + return pdFALSE; } - /* Any other well-formed option must be at least two bytes: the option - type byte followed by a length byte. */ - if( xRemainingOptionsBytes < 2 ) + ( *ppxSocket )->u.xTCP.ucPeerWinScaleFactor = ( *ppucPtr )[ 2 ]; + ( *ppxSocket )->u.xTCP.bits.bWinScaling = pdTRUE_UNSIGNED; + ( *ppucPtr ) += TCP_OPT_WSOPT_LEN; + } +#endif /* ipconfigUSE_TCP_WIN */ + else if( ( *ppucPtr )[ 0 ] == TCP_OPT_MSS ) + { + /* Confirm that the option fits in the remaining buffer space. */ + if( ( xRemainingOptionsBytes < TCP_OPT_MSS_LEN )|| ( ( *ppucPtr )[ 1 ] != TCP_OPT_MSS_LEN ) ) { - break; + return pdFALSE; } -#if( ipconfigUSE_TCP_WIN != 0 ) - else if( pucPtr[ 0 ] == TCP_OPT_WSOPT ) + + /* An MSS option with the correct option length. FreeRTOS_htons() + is not needed here because usChar2u16() already returns a host + endian number. */ + uxNewMSS = usChar2u16( ( *ppucPtr ) + 2 ); + + if( ( *ppxSocket )->u.xTCP.usInitMSS != uxNewMSS ) { - /* Confirm that the option fits in the remaining buffer space. */ - if( ( xRemainingOptionsBytes < TCP_OPT_WSOPT_LEN ) || ( pucPtr[ 1 ] != TCP_OPT_WSOPT_LEN ) ) + /* Perform a basic check on the the new MSS. */ + if( uxNewMSS == 0 ) { - break; + return pdFALSE; } - pxSocket->u.xTCP.ucPeerWinScaleFactor = pucPtr[ 2 ]; - pxSocket->u.xTCP.bits.bWinScaling = pdTRUE_UNSIGNED; - pucPtr += TCP_OPT_WSOPT_LEN; + FreeRTOS_debug_printf( ( "MSS change %u -> %lu\n", ( *ppxSocket )->u.xTCP.usInitMSS, uxNewMSS ) ); } -#endif /* ipconfigUSE_TCP_WIN */ - else if( pucPtr[ 0 ] == TCP_OPT_MSS ) + + if( ( *ppxSocket )->u.xTCP.usInitMSS > uxNewMSS ) { - /* Confirm that the option fits in the remaining buffer space. */ - if( ( xRemainingOptionsBytes < TCP_OPT_MSS_LEN )|| ( pucPtr[ 1 ] != TCP_OPT_MSS_LEN ) ) + /* our MSS was bigger than the MSS of the other party: adapt it. */ + ( *ppxSocket )->u.xTCP.bits.bMssChange = pdTRUE_UNSIGNED; + if( ( ( *ppxTCPWindow ) != NULL ) && ( ( *ppxSocket )->u.xTCP.usCurMSS > uxNewMSS ) ) { - break; + /* The peer advertises a smaller MSS than this socket was + using. Use that as well. */ + FreeRTOS_debug_printf( ( "Change mss %d => %lu\n", ( *ppxSocket )->u.xTCP.usCurMSS, uxNewMSS ) ); + ( *ppxSocket )->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS; } + ( *ppxTCPWindow )->xSize.ulRxWindowLength = ( ( uint32_t ) uxNewMSS ) * ( ( *ppxTCPWindow )->xSize.ulRxWindowLength / ( ( uint32_t ) uxNewMSS ) ); + ( *ppxTCPWindow )->usMSSInit = ( uint16_t ) uxNewMSS; + ( *ppxTCPWindow )->usMSS = ( uint16_t ) uxNewMSS; + ( *ppxSocket )->u.xTCP.usInitMSS = ( uint16_t ) uxNewMSS; + ( *ppxSocket )->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS; + } - /* An MSS option with the correct option length. FreeRTOS_htons() - is not needed here because usChar2u16() already returns a host - endian number. */ - uxNewMSS = usChar2u16( pucPtr + 2 ); + #if( ipconfigUSE_TCP_WIN != 1 ) + /* Without scaled windows, MSS is the only interesting option. */ + return pdFALSE; + #else + /* Or else we continue to check another option: selective ACK. */ + ( *ppucPtr ) += TCP_OPT_MSS_LEN; + #endif /* ipconfigUSE_TCP_WIN != 1 */ + } + else + { + /* All other options have a length field, so that we easily + can skip past them. */ + ucLen = ( *ppucPtr )[ 1 ]; + if( ( ucLen < 2 ) || ( ucLen > xRemainingOptionsBytes ) ) + { + /* If the length field is too small or too big, the options are + * malformed, don't process them further. + */ + return pdFALSE; + } - if( pxSocket->u.xTCP.usInitMSS != uxNewMSS ) + #if( ipconfigUSE_TCP_WIN == 1 ) + { + /* Selective ACK: the peer has received a packet but it is missing + * earlier packets. At least this packet does not need retransmission + * anymore. ulTCPWindowTxSack( ) takes care of this administration. + */ + if( ( *ppucPtr )[0] == TCP_OPT_SACK_A ) { - /* Perform a basic check on the the new MSS. */ - if( uxNewMSS == 0 ) - { - break; - } - - FreeRTOS_debug_printf( ( "MSS change %u -> %lu\n", pxSocket->u.xTCP.usInitMSS, uxNewMSS ) ); - } + ucLen -= 2; + ( *ppucPtr ) += 2; - if( pxSocket->u.xTCP.usInitMSS > uxNewMSS ) - { - /* our MSS was bigger than the MSS of the other party: adapt it. */ - pxSocket->u.xTCP.bits.bMssChange = pdTRUE_UNSIGNED; - if( ( pxTCPWindow != NULL ) && ( pxSocket->u.xTCP.usCurMSS > uxNewMSS ) ) + while( ucLen >= 8 ) { - /* The peer advertises a smaller MSS than this socket was - using. Use that as well. */ - FreeRTOS_debug_printf( ( "Change mss %d => %lu\n", pxSocket->u.xTCP.usCurMSS, uxNewMSS ) ); - pxSocket->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS; + prvSkipPastRemainingOptions( ppucPtr, ppxSocket, &ucLen ); } - pxTCPWindow->xSize.ulRxWindowLength = ( ( uint32_t ) uxNewMSS ) * ( pxTCPWindow->xSize.ulRxWindowLength / ( ( uint32_t ) uxNewMSS ) ); - pxTCPWindow->usMSSInit = ( uint16_t ) uxNewMSS; - pxTCPWindow->usMSS = ( uint16_t ) uxNewMSS; - pxSocket->u.xTCP.usInitMSS = ( uint16_t ) uxNewMSS; - pxSocket->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS; + /* ucLen should be 0 by now. */ } - - #if( ipconfigUSE_TCP_WIN != 1 ) - /* Without scaled windows, MSS is the only interesting option. */ - break; - #else - /* Or else we continue to check another option: selective ACK. */ - pucPtr += TCP_OPT_MSS_LEN; - #endif /* ipconfigUSE_TCP_WIN != 1 */ } - else + #endif /* ipconfigUSE_TCP_WIN == 1 */ + + ( *ppucPtr ) += ucLen; + } + return pdTRUE; +} + +/*-----------------------------------------------------------*/ + +static void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const pucLen ) +{ +uint32_t ulFirst = ulChar2u32( ( *ppucPtr ) ); +uint32_t ulLast = ulChar2u32( ( *ppucPtr ) + 4 ); +uint32_t ulCount = ulTCPWindowTxSack( &( *ppxSocket )->u.xTCP.xTCPWindow, ulFirst, ulLast ); + /* ulTCPWindowTxSack( ) returns the number of bytes which have been acked + * starting from the head position. Advance the tail pointer in txStream. + */ + if( ( ( *ppxSocket )->u.xTCP.txStream != NULL ) && ( ulCount > 0 ) ) + { + /* Just advancing the tail index, 'ulCount' bytes have been confirmed. */ + uxStreamBufferGet( ( *ppxSocket )->u.xTCP.txStream, 0, NULL, ( size_t ) ulCount, pdFALSE ); + ( *ppxSocket )->xEventBits |= eSOCKET_SEND; + + #if ipconfigSUPPORT_SELECT_FUNCTION == 1 { - /* All other options have a length field, so that we easily - can skip past them. */ - unsigned char len = pucPtr[ 1 ]; - if( ( len < 2 ) || ( len > xRemainingOptionsBytes ) ) + if( ( *ppxSocket )->xSelectBits & eSELECT_WRITE ) { - /* If the length field is too small or too big, the options are malformed. - Don't process them further. */ - break; + /* The field 'xEventBits' is used to store regular socket events + * (at most 8), as well as 'select events', which will be left-shifted. + */ + ( *ppxSocket )->xEventBits |= ( eSELECT_WRITE << SOCKET_EVENT_BIT_COUNT ); } + } + #endif - #if( ipconfigUSE_TCP_WIN == 1 ) + /* In case the socket owner has installed an OnSent handler, call it now. + */ + #if( ipconfigUSE_CALLBACKS == 1 ) + { + if( ipconfigIS_VALID_PROG_ADDRESS( ( *ppxSocket )->u.xTCP.pxHandleSent ) ) { - /* Selective ACK: the peer has received a packet but it is missing earlier - packets. At least this packet does not need retransmission anymore - ulTCPWindowTxSack( ) takes care of this administration. */ - if( pucPtr[0] == TCP_OPT_SACK_A ) - { - len -= 2; - pucPtr += 2; - - while( len >= 8 ) - { - uint32_t ulFirst = ulChar2u32( pucPtr ); - uint32_t ulLast = ulChar2u32( pucPtr + 4 ); - uint32_t ulCount = ulTCPWindowTxSack( &pxSocket->u.xTCP.xTCPWindow, ulFirst, ulLast ); - /* ulTCPWindowTxSack( ) returns the number of bytes which have been acked - starting from the head position. - Advance the tail pointer in txStream. */ - if( ( pxSocket->u.xTCP.txStream != NULL ) && ( ulCount > 0 ) ) - { - /* Just advancing the tail index, 'ulCount' bytes have been confirmed. */ - uxStreamBufferGet( pxSocket->u.xTCP.txStream, 0, NULL, ( size_t ) ulCount, pdFALSE ); - pxSocket->xEventBits |= eSOCKET_SEND; - - #if ipconfigSUPPORT_SELECT_FUNCTION == 1 - { - if( pxSocket->xSelectBits & eSELECT_WRITE ) - { - /* The field 'xEventBits' is used to store regular socket events (at most 8), - as well as 'select events', which will be left-shifted */ - pxSocket->xEventBits |= ( eSELECT_WRITE << SOCKET_EVENT_BIT_COUNT ); - } - } - #endif - - /* In case the socket owner has installed an OnSent handler, - call it now. */ - #if( ipconfigUSE_CALLBACKS == 1 ) - { - if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleSent ) ) - { - pxSocket->u.xTCP.pxHandleSent( (Socket_t *)pxSocket, ulCount ); - } - } - #endif /* ipconfigUSE_CALLBACKS == 1 */ - } - pucPtr += 8; - len -= 8; - } - /* len should be 0 by now. */ - } + ( *ppxSocket )->u.xTCP.pxHandleSent( (Socket_t )( *ppxSocket ), ulCount ); } - #endif /* ipconfigUSE_TCP_WIN == 1 */ - - pucPtr += len; } + #endif /* ipconfigUSE_CALLBACKS == 1 */ } + ( *ppucPtr ) += 8; + ( *pucLen ) -= 8; } + /*-----------------------------------------------------------*/ #if( ipconfigUSE_TCP_WIN != 0 ) @@ -1599,7 +1634,7 @@ BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it co if( xConnected != NULL ) { /* The 'connected' state has changed, call the OnConnect handler of the parent. */ - xConnected->u.xTCP.pxHandleConnected( ( Socket_t * ) xConnected, bAfter ); + xConnected->u.xTCP.pxHandleConnected( ( Socket_t ) xConnected, bAfter ); } } #endif @@ -2416,7 +2451,7 @@ int32_t lDistance, lSendResult; { if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleSent ) ) { - pxSocket->u.xTCP.pxHandleSent( (Socket_t *)pxSocket, ulCount ); + pxSocket->u.xTCP.pxHandleSent( ( Socket_t )pxSocket, ulCount ); } } #endif /* ipconfigUSE_CALLBACKS == 1 */ @@ -2836,41 +2871,41 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow ); } /*-----------------------------------------------------------*/ -static BaseType_t prvTCPSendSpecialPacketHelper( NetworkBufferDescriptor_t *pxNetworkBuffer, - uint8_t ucTCPFlags ) +static BaseType_t prvTCPSendSpecialPacketHelper( NetworkBufferDescriptor_t *pxNetworkBuffer, + uint8_t ucTCPFlags ) { #if( ipconfigIGNORE_UNKNOWN_PACKETS == 0 ) - { - TCPPacket_t *pxTCPPacket = ( TCPPacket_t * )( pxNetworkBuffer->pucEthernetBuffer ); - const BaseType_t xSendLength = ( BaseType_t ) - ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + 0u ); /* Plus 0 options. */ + { + TCPPacket_t *pxTCPPacket = ( TCPPacket_t * )( pxNetworkBuffer->pucEthernetBuffer ); + const BaseType_t xSendLength = ( BaseType_t ) + ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + 0u ); /* Plus 0 options. */ - pxTCPPacket->xTCPHeader.ucTCPFlags = ucTCPFlags; - pxTCPPacket->xTCPHeader.ucTCPOffset = ( ipSIZE_OF_TCP_HEADER + 0u ) << 2; + pxTCPPacket->xTCPHeader.ucTCPFlags = ucTCPFlags; + pxTCPPacket->xTCPHeader.ucTCPOffset = ( ipSIZE_OF_TCP_HEADER + 0u ) << 2; - prvTCPReturnPacket( NULL, pxNetworkBuffer, ( uint32_t )xSendLength, pdFALSE ); - } + prvTCPReturnPacket( NULL, pxNetworkBuffer, ( uint32_t )xSendLength, pdFALSE ); + } #endif /* !ipconfigIGNORE_UNKNOWN_PACKETS */ - /* Remove compiler warnings if ipconfigIGNORE_UNKNOWN_PACKETS == 1. */ - ( void )pxNetworkBuffer; - ( void )ucTCPFlags; + /* Remove compiler warnings if ipconfigIGNORE_UNKNOWN_PACKETS == 1. */ + ( void )pxNetworkBuffer; + ( void )ucTCPFlags; - /* The packet was not consumed. */ - return pdFAIL; + /* The packet was not consumed. */ + return pdFAIL; } /*-----------------------------------------------------------*/ static BaseType_t prvTCPSendChallengeAck( NetworkBufferDescriptor_t *pxNetworkBuffer ) { - return prvTCPSendSpecialPacketHelper( pxNetworkBuffer, ipTCP_FLAG_ACK ); + return prvTCPSendSpecialPacketHelper( pxNetworkBuffer, ipTCP_FLAG_ACK ); } /*-----------------------------------------------------------*/ static BaseType_t prvTCPSendReset( NetworkBufferDescriptor_t *pxNetworkBuffer ) { - return prvTCPSendSpecialPacketHelper( pxNetworkBuffer, - ipTCP_FLAG_ACK | ipTCP_FLAG_RST ); + return prvTCPSendSpecialPacketHelper( pxNetworkBuffer, + ipTCP_FLAG_ACK | ipTCP_FLAG_RST ); } /*-----------------------------------------------------------*/ @@ -2914,9 +2949,8 @@ uint16_t xRemotePort; uint32_t ulSequenceNumber; uint32_t ulAckNumber; BaseType_t xResult = pdPASS; - - configASSERT( pxNetworkBuffer ); - configASSERT( pxNetworkBuffer->pucEthernetBuffer ); +configASSERT(pxNetworkBuffer); +configASSERT(pxNetworkBuffer->pucEthernetBuffer); /* Check for a minimum packet size. */ if( pxNetworkBuffer->xDataLength >= ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) ) @@ -2926,8 +2960,8 @@ BaseType_t xResult = pdPASS; xLocalPort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usDestinationPort ); ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress ); xRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort ); - ulSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber ); - ulAckNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulAckNr ); + ulSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber ); + ulAckNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulAckNr ); /* Find the destination socket, and if not found: return a socket listing to the destination PORT. */ @@ -3007,36 +3041,36 @@ BaseType_t xResult = pdPASS; flag. */ if( ( ucTCPFlags & ipTCP_FLAG_RST ) != 0u ) { - FreeRTOS_debug_printf( ( "TCP: RST received from %lxip:%u for %u\n", ulRemoteIP, xRemotePort, xLocalPort ) ); - - /* Implement https://tools.ietf.org/html/rfc5961#section-3.2. */ - if( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN ) - { - /* Per the above RFC, "In the SYN-SENT state ... the RST is - acceptable if the ACK field acknowledges the SYN." */ - if( ulAckNumber == pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber + 1 ) - { - vTCPStateChange( pxSocket, eCLOSED ); - } - } - else - { - /* Check whether the packet matches the next expected sequence number. */ - if( ulSequenceNumber == pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber ) - { - vTCPStateChange( pxSocket, eCLOSED ); - } - /* Otherwise, check whether the packet is within the receive window. */ - else if( ulSequenceNumber > pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber && - ulSequenceNumber < ( pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber + - pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength ) ) - { - /* Send a challenge ACK. */ - prvTCPSendChallengeAck( pxNetworkBuffer ); - } - } - - /* Otherwise, do nothing. In any case, the packet cannot be handled. */ + FreeRTOS_debug_printf( ( "TCP: RST received from %lxip:%u for %u\n", ulRemoteIP, xRemotePort, xLocalPort ) ); + + /* Implement https://tools.ietf.org/html/rfc5961#section-3.2. */ + if( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN ) + { + /* Per the above RFC, "In the SYN-SENT state ... the RST is + acceptable if the ACK field acknowledges the SYN." */ + if( ulAckNumber == pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber + 1 ) + { + vTCPStateChange( pxSocket, eCLOSED ); + } + } + else + { + /* Check whether the packet matches the next expected sequence number. */ + if( ulSequenceNumber == pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber ) + { + vTCPStateChange( pxSocket, eCLOSED ); + } + /* Otherwise, check whether the packet is within the receive window. */ + else if( ulSequenceNumber > pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber && + ulSequenceNumber < ( pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber + + pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength ) ) + { + /* Send a challenge ACK. */ + prvTCPSendChallengeAck( pxNetworkBuffer ); + } + } + + /* Otherwise, do nothing. In any case, the packet cannot be handled. */ xResult = pdFAIL; } else if( ( ( ucTCPFlags & ipTCP_FLAG_CTRL ) == ipTCP_FLAG_SYN ) && ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) ) diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c index f94b181f7..cda8acd1c 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -675,17 +675,17 @@ const int32_t l500ms = 500; #if( ipconfigUSE_TCP_WIN == 1 ) - void vTCPSegmentCleanup( void ) - { - /* Free and clear the TCP segments pointer. This function should only be called - * once FreeRTOS+TCP will no longer be used. No thread-safety is provided for this - * function. */ - if( xTCPSegments != NULL ) - { - vPortFreeLarge( xTCPSegments ); - xTCPSegments = NULL; - } - } + void vTCPSegmentCleanup( void ) + { + /* Free and clear the TCP segments pointer. This function should only be called + * once FreeRTOS+TCP will no longer be used. No thread-safety is provided for this + * function. */ + if( xTCPSegments != NULL ) + { + vPortFreeLarge( xTCPSegments ); + xTCPSegments = NULL; + } + } #endif /* ipconfgiUSE_TCP_WIN == 1 */ /*-----------------------------------------------------------*/ @@ -805,20 +805,20 @@ const int32_t l500ms = 500; { ulSavedSequenceNumber = ulCurrentSequenceNumber; - /* Clean up all sequence received between ulSequenceNumber and ulSequenceNumber + ulLength since they are duplicated. - If the server is forced to retransmit packets several time in a row it might send a batch of concatenated packet for speed. - So we cannot rely on the packets between ulSequenceNumber and ulSequenceNumber + ulLength to be sequential and it is better to just - clean them out. */ - do - { - pxFound = xTCPWindowRxConfirm( pxWindow, ulSequenceNumber, ulLength ); - - if ( pxFound != NULL ) - { - /* Remove it because it will be passed to user directly. */ - vTCPWindowFree( pxFound ); - } - } while ( pxFound ); + /* Clean up all sequence received between ulSequenceNumber and ulSequenceNumber + ulLength since they are duplicated. + If the server is forced to retransmit packets several time in a row it might send a batch of concatenated packet for speed. + So we cannot rely on the packets between ulSequenceNumber and ulSequenceNumber + ulLength to be sequential and it is better to just + clean them out. */ + do + { + pxFound = xTCPWindowRxConfirm( pxWindow, ulSequenceNumber, ulLength ); + + if ( pxFound != NULL ) + { + /* Remove it because it will be passed to user directly. */ + vTCPWindowFree( pxFound ); + } + } while ( pxFound ); /* Check for following segments that are already in the queue and increment ulCurrentSequenceNumber. */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c index 09733a020..c8de69790 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -78,10 +78,22 @@ UDPPacket_t *pxUDPPacket; IPHeader_t *pxIPHeader; eARPLookupResult_t eReturned; uint32_t ulIPAddress = pxNetworkBuffer->ulIPAddress; +size_t uxPayloadSize; /* Map the UDP packet onto the start of the frame. */ pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; +#if ipconfigSUPPORT_OUTGOING_PINGS == 1 + if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA ) + { + uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( ICMPPacket_t ); + } + else +#endif + { + uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ); + } + /* Determine the ARP cache status for the requested IP address. */ eReturned = eARPGetCacheEntry( &( ulIPAddress ), &( pxUDPPacket->xEthernetHeader.xDestinationAddress ) ); @@ -109,7 +121,7 @@ uint32_t ulIPAddress = pxNetworkBuffer->ulIPAddress; pxUDPHeader->usDestinationPort = pxNetworkBuffer->usPort; pxUDPHeader->usSourcePort = pxNetworkBuffer->usBoundPort; - pxUDPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( UDPHeader_t ) ); + pxUDPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( UDPHeader_t ) ); pxUDPHeader->usLength = FreeRTOS_htons( pxUDPHeader->usLength ); pxUDPHeader->usChecksum = 0u; } @@ -143,16 +155,14 @@ uint32_t ulIPAddress = pxNetworkBuffer->ulIPAddress; if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA ) { pxIPHeader->ucProtocol = ipPROTOCOL_ICMP; - pxIPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( IPHeader_t ) ); + pxIPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( IPHeader_t ) + sizeof( ICMPHeader_t ) ); } else #endif /* ipconfigSUPPORT_OUTGOING_PINGS */ { - pxIPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( IPHeader_t ) + sizeof( UDPHeader_t ) ); + pxIPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( IPHeader_t ) + sizeof( UDPHeader_t ) ); } - /* The total transmit size adds on the Ethernet header. */ - pxNetworkBuffer->xDataLength = pxIPHeader->usLength + sizeof( EthernetHeader_t ); pxIPHeader->usLength = FreeRTOS_htons( pxIPHeader->usLength ); /* HT:endian: changed back to network endian */ pxIPHeader->ulDestinationIPAddress = pxNetworkBuffer->ulIPAddress; @@ -240,13 +250,12 @@ BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer { BaseType_t xReturn = pdPASS; FreeRTOS_Socket_t *pxSocket; -UDPPacket_t *pxUDPPacket; +configASSERT(pxNetworkBuffer); +configASSERT(pxNetworkBuffer->pucEthernetBuffer); - configASSERT( pxNetworkBuffer ); - configASSERT( pxNetworkBuffer->pucEthernetBuffer ); - pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; - +UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer; + /* Caller must check for minimum packet size. */ pxSocket = pxUDPSocketLookup( usPort ); @@ -271,7 +280,8 @@ UDPPacket_t *pxUDPPacket; destinationAddress.sin_port = usPort; destinationAddress.sin_addr = pxUDPPacket->xIPHeader.ulDestinationIPAddress; - if( xHandler( ( Socket_t * ) pxSocket, ( void* ) pcData, ( size_t ) pxNetworkBuffer->xDataLength, + /* The value of 'xDataLength' was proven to be at least the size of a UDP packet in prvProcessIPPacket(). */ + if( xHandler( ( Socket_t ) pxSocket, ( void* ) pcData, ( size_t ) ( pxNetworkBuffer->xDataLength - ipUDP_PAYLOAD_OFFSET_IPv4 ), &xSourceAddress, &destinationAddress ) ) { xReturn = pdFAIL; /* FAIL means that we did not consume or release the buffer */ @@ -351,6 +361,19 @@ UDPPacket_t *pxUDPPacket; /* There is no socket listening to the target port, but still it might be for this node. */ + #if( ipconfigUSE_DNS == 1 ) && ( ipconfigDNS_USE_CALLBACKS == 1 ) + /* A DNS reply, check for the source port. Although the DNS client + does open a UDP socket to send a messages, this socket will be + closed after a short timeout. Messages that come late (after the + socket is closed) will be treated here. */ + if( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usSourcePort ) == ipDNS_PORT ) + { + vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress ); + xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer ); + } + else + #endif + #if( ipconfigUSE_LLMNR == 1 ) /* a LLMNR request, check for the destination port. */ if( ( usPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) || diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/History.txt b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/History.txt index 07ad698a2..52565cc86 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/History.txt +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/History.txt @@ -1,7 +1,3 @@ -Changes in V2.0.11 - - + Updates some drivers in the portable layer. - Changes between 160919 and 180821 releases: + Multiple security improvements and fixes in packet parsing routines, DNS @@ -9,17 +5,7 @@ Changes between 160919 and 180821 releases: + Disable NBNS and LLMNR by default. + Add TCP hang protection by default. - We thank Ori Karliner of Zimperium zLabs Team for reporting these issues. - - + Update FreeRTOS_gethostbyname() to allow an IP address to be passed in - - in which case it is just returned as a uint32_t. - + Introduce ipconfigSOCKET_HAS_USER_WAKE_CALLBACK to FreeRTOS_Sockets.c to - allow a user supposed callback function to be executed when socket events - occur in the same way that the socket semaphore is currently used. - + Update xNetworkBuffersInitialise() to ensure the semaphore created by the - function is not accessed until after the NULL check. - + Improve print messages output by the Win32 port layer version of - prvPrintAvailableNetworkInterfaces(). +We thank Ori Karliner of Zimperium zLabs Team for reporting these issues. Changes between 160908 and 160919 releases: @@ -188,4 +174,4 @@ Changes between 141019 and 150825 + Fix: Previously if a listening socket was reused, and a connection failed, the TCP/IP stack closed the socket, now the socket is correctly left unclosed as it is owned by the application. - + Various other formatting and minor fix alterations. \ No newline at end of file + + Various other formatting and minor fix alterations. diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h index 96f4f53fb..20cdf739f 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -169,6 +169,14 @@ from the FreeRTOSIPConfig.h configuration header file. */ #define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME portMAX_DELAY #endif + +#ifndef ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS + #define ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS pdMS_TO_TICKS( 500u ) +#endif + +#ifndef ipconfigDNS_SEND_BLOCK_TIME_TICKS + #define ipconfigDNS_SEND_BLOCK_TIME_TICKS pdMS_TO_TICKS( 500u ) +#endif /* * FreeRTOS debug logging routine (proposal) * The macro will be called in the printf() style. Users can define @@ -375,6 +383,14 @@ from the FreeRTOSIPConfig.h configuration header file. */ #endif /* _WINDOWS_ */ #endif /* ipconfigMAXIMUM_DISCOVER_TX_PERIOD */ +#if( ipconfigUSE_DNS == 0 ) + /* The DNS module will not be included. */ + #if( ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) ) + /* LLMNR and NBNS depend on DNS because those protocols share a lot of code. */ + #error When either LLMNR or NBNS is used, ipconfigUSE_DNS must be defined + #endif +#endif + #ifndef ipconfigUSE_DNS #define ipconfigUSE_DNS 1 #endif @@ -408,13 +424,6 @@ from the FreeRTOSIPConfig.h configuration header file. */ #define ipconfigUSE_LLMNR ( 0 ) #endif -#if( !defined( ipconfigUSE_DNS ) ) - #if( ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) ) - /* LLMNR and NBNS depend on DNS because those protocols share a lot of code. */ - #error When either LLMNR or NBNS is used, ipconfigUSE_DNS must be defined - #endif -#endif - #ifndef ipconfigREPLY_TO_INCOMING_PINGS #define ipconfigREPLY_TO_INCOMING_PINGS 1 #endif @@ -507,14 +516,6 @@ from the FreeRTOSIPConfig.h configuration header file. */ #define ipconfigSOCKET_HAS_USER_WAKE_CALLBACK 0 #endif -#ifndef ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT - #define ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT 0 -#endif - -#if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 ) && ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT != 0 ) - #error ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT cannot be used with ipconfigSOCKET_HAS_USER_WAKE_CALLBACK - undefine one of them -#endif - #ifndef ipconfigSUPPORT_SELECT_FUNCTION #define ipconfigSUPPORT_SELECT_FUNCTION 0 #endif @@ -535,7 +536,7 @@ from the FreeRTOSIPConfig.h configuration header file. */ #define ipconfigUSE_NBNS 0 #endif -/* As an attack surface reduction for ports that listen for inbound +/* As an attack surface reduction for ports that listen for inbound connections, hang protection can help reduce the impact of SYN floods. */ #ifndef ipconfigTCP_HANG_PROTECTION #define ipconfigTCP_HANG_PROTECTION 1 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h index 13ba82089..166bf3a97 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -42,9 +42,9 @@ extern "C" { typedef struct xARP_CACHE_TABLE_ROW { uint32_t ulIPAddress; /* The IP address of an ARP cache entry. */ - MACAddress_t xMACAddress; /* The MAC address of an ARP cache entry. */ + MACAddress_t xMACAddress; /* The MAC address of an ARP cache entry. */ uint8_t ucAge; /* A value that is periodically decremented but can also be refreshed by active communication. The ARP cache entry is removed if the value reaches zero. */ - uint8_t ucValid; /* pdTRUE: xMACAddress is valid, pdFALSE: waiting for ARP reply */ + uint8_t ucValid; /* pdTRUE: xMACAddress is valid, pdFALSE: waiting for ARP reply */ } ARPCacheRow_t; typedef enum diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h index ab998ed05..6a6d372b6 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h index c52f3d3b4..449fa514f 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -84,12 +84,12 @@ uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer ); #if( ipconfigUSE_DNS_CACHE != 0 ) - /* Look for the indicated host name in the DNS cache. Returns the IPv4 - address if present, or 0x0 otherwise. */ + /* Look for the indicated host name in the DNS cache. Returns the IPv4 + address if present, or 0x0 otherwise. */ uint32_t FreeRTOS_dnslookup( const char *pcHostName ); - /* Remove all entries from the DNS cache. */ - void FreeRTOS_dnsclear(); + /* Remove all entries from the DNS cache. */ + void FreeRTOS_dnsclear(); #endif /* ipconfigUSE_DNS_CACHE != 0 */ #if( ipconfigDNS_USE_CALLBACKS != 0 ) diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h index f8019a779..6bfb4ad42 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -275,6 +275,15 @@ void FreeRTOS_ClearARP( void ); #endif /* ipconfigDHCP_REGISTER_HOSTNAME */ +/* This xApplicationGetRandomNumber() will set *pulNumber to a random number, +and return pdTRUE. When the random number generator is broken, it shall return +pdFALSE. +The function is defined in 'iot_secure_sockets.c'. +If that module is not included in the project, the application must provide an +implementation of it. +The macro's ipconfigRAND32() and configRAND32() are not in use anymore. */ +BaseType_t xApplicationGetRandomNumber( uint32_t *pulNumber ); + /* For backward compatibility define old structure names to the newer equivalent structure name. */ #ifndef ipconfigENABLE_BACKWARD_COMPATIBILITY diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h index 2563d010a..8604abed0 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -41,10 +41,6 @@ extern "C" { #include "FreeRTOS_TCP_IP.h" #endif -#if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 ) - #include "semphr.h" -#endif - #include "event_groups.h" typedef struct xNetworkAddressingParameters @@ -248,16 +244,17 @@ typedef enum eNoEvent = -1, eNetworkDownEvent, /* 0: The network interface has been lost and/or needs [re]connecting. */ eNetworkRxEvent, /* 1: The network interface has queued a received Ethernet frame. */ - eARPTimerEvent, /* 2: The ARP timer expired. */ - eStackTxEvent, /* 3: The software stack has queued a packet to transmit. */ - eDHCPEvent, /* 4: Process the DHCP state machine. */ - eTCPTimerEvent, /* 5: See if any TCP socket needs attention. */ - eTCPAcceptEvent, /* 6: Client API FreeRTOS_accept() waiting for client connections. */ - eTCPNetStat, /* 7: IP-task is asked to produce a netstat listing. */ - eSocketBindEvent, /* 8: Send a message to the IP-task to bind a socket to a port. */ - eSocketCloseEvent, /* 9: Send a message to the IP-task to close a socket. */ - eSocketSelectEvent, /*10: Send a message to the IP-task for select(). */ - eSocketSignalEvent, /*11: A socket must be signalled. */ + eNetworkTxEvent, /* 2: Let the IP-task send a network packet. */ + eARPTimerEvent, /* 3: The ARP timer expired. */ + eStackTxEvent, /* 4: The software stack has queued a packet to transmit. */ + eDHCPEvent, /* 5: Process the DHCP state machine. */ + eTCPTimerEvent, /* 6: See if any TCP socket needs attention. */ + eTCPAcceptEvent, /* 7: Client API FreeRTOS_accept() waiting for client connections. */ + eTCPNetStat, /* 8: IP-task is asked to produce a netstat listing. */ + eSocketBindEvent, /* 9: Send a message to the IP-task to bind a socket to a port. */ + eSocketCloseEvent, /*10: Send a message to the IP-task to close a socket. */ + eSocketSelectEvent, /*11: Send a message to the IP-task for select(). */ + eSocketSignalEvent, /*12: A socket must be signalled. */ } eIPEvent_t; typedef struct IP_TASK_COMMANDS @@ -441,15 +438,15 @@ uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t /* Socket related private functions. */ -/* - * The caller must ensure that pxNetworkBuffer->xDataLength is the UDP packet - * payload size (excluding packet headers) and that the packet in pucEthernetBuffer - * is at least the size of UDPPacket_t. +/* + * The caller must ensure that pxNetworkBuffer->xDataLength is the UDP packet + * payload size (excluding packet headers) and that the packet in pucEthernetBuffer + * is at least the size of UDPPacket_t. */ BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort ); /* - * Initialize the socket list data structures for TCP and UDP. + * Initialize the socket list data structures for TCP and UDP. */ BaseType_t vNetworkSocketsInit( void ); @@ -460,13 +457,8 @@ BaseType_t vNetworkSocketsInit( void ); BaseType_t xIPIsNetworkTaskReady( void ); #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 ) - struct XSOCKET; - typedef void (*SocketWakeupCallback_t)( struct XSOCKET * pxSocket ); -#endif - -#if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT == 1 ) - struct XSOCKET; - typedef void( *SocketWakeupCallback_t )( struct XSOCKET * pxSocket, void * pvContext ); + struct xSOCKET; + typedef void (*SocketWakeupCallback_t)( struct xSOCKET * pxSocket ); #endif #if( ipconfigUSE_TCP == 1 ) @@ -553,7 +545,7 @@ BaseType_t xIPIsNetworkTaskReady( void ); * This counter is separate from the xmitCount in the * TCP win segments */ uint8_t ucTCPState; /* TCP state: see eTCP_STATE */ - struct XSOCKET *pxPeerSocket; /* for server socket: child, for child socket: parent */ + struct xSOCKET *pxPeerSocket; /* for server socket: child, for child socket: parent */ #if( ipconfigTCP_KEEP_ALIVE == 1 ) uint8_t ucKeepRepCount; TickType_t xLastAliveTime; @@ -620,7 +612,7 @@ typedef enum eSOCKET_EVENT { eSOCKET_ALL = 0x007F, } eSocketEvent_t; -typedef struct XSOCKET +typedef struct xSOCKET { EventBits_t xEventBits; EventGroupHandle_t xEventGroup; @@ -635,12 +627,9 @@ typedef struct XSOCKET #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 ) SemaphoreHandle_t pxUserSemaphore; #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */ - #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 ) || ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT == 1 ) + #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 ) SocketWakeupCallback_t pxUserWakeCallback; #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */ - #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT == 1 ) - void * pvUserWakeCallbackContext; - #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT */ #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) struct xSOCKET_SET *pxSocketSet; @@ -823,3 +812,16 @@ void vIPNetworkUpCalls( void ); #endif #endif /* FREERTOS_IP_PRIVATE_H */ + + + + + + + + + + + + + diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h index 69caa0481..88d3bba65 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -55,7 +55,7 @@ extern "C" { /* Assigned to an Socket_t variable when the socket is not valid, probably because it could not be created. */ -#define FREERTOS_INVALID_SOCKET ( ( void * ) ~0U ) +#define FREERTOS_INVALID_SOCKET ( ( Socket_t ) ~0U ) /* API function error values. As errno is supported, the FreeRTOS sockets functions return error codes rather than just a pass or fail indication. */ @@ -126,16 +126,12 @@ FreeRTOS_setsockopt(). */ #define FREERTOS_SO_UDP_MAX_RX_PACKETS ( 16 ) /* This option helps to limit the maximum number of packets a UDP socket will buffer */ #endif -#if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 ) || ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT == 1 ) +#if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 ) #define FREERTOS_SO_WAKEUP_CALLBACK ( 17 ) #endif #define FREERTOS_SO_SET_LOW_HIGH_WATER ( 18 ) -#if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT == 1 ) - #define FREERTOS_SO_WAKE_CALLBACK_CONTEXT ( 19 ) -#endif - #define FREERTOS_NOT_LAST_IN_FRAGMENTED_PACKET ( 0x80 ) /* For internal use only, but also part of an 8-bit bitwise value. */ #define FREERTOS_FRAGMENTED_PACKET ( 0x40 ) /* For internal use only, but also part of an 8-bit bitwise value. */ @@ -217,11 +213,13 @@ struct freertos_sockaddr #endif /* ipconfigBYTE_ORDER */ /* The socket type itself. */ -typedef void *Socket_t; +struct xSOCKET; +typedef struct xSOCKET *Socket_t; /* The SocketSet_t type is the equivalent to the fd_set type used by the Berkeley API. */ -typedef void *SocketSet_t; +struct xSOCKET_SET; +typedef struct xSOCKET_SET *SocketSet_t; /** * FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE @@ -389,3 +387,16 @@ void FreeRTOS_netstat( void ); #endif #endif /* FREERTOS_SOCKETS_H */ + + + + + + + + + + + + + diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h index 43d1a9745..95bbbdf0a 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -157,31 +157,6 @@ size_t uxSize = uxStreamBufferMidSpace( pxBuffer ); } } /*-----------------------------------------------------------*/ -static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer ); -static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer ) -{ -BaseType_t xReturn; - - /* True if no item is available */ - if( pxBuffer->uxHead == pxBuffer->uxTail ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - return xReturn; -} -/*-----------------------------------------------------------*/ - -static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer ); -static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer ) -{ - /* True if the available space equals zero. */ - return ( BaseType_t ) ( uxStreamBufferGetSpace( pxBuffer ) == 0u ); -} -/*-----------------------------------------------------------*/ static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight ); static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight ) diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h index 4a94d2d83..76738c460 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h index f1823febc..9532fd159 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h index 0ae5fb5a4..a7463fcee 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h index 60708a04b..534f5261d 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h index d17299d6e..316e18f56 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h index 9543ef447..0fcde3439 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 @@ -47,7 +47,7 @@ UBaseType_t uxGetMinimumFreeNetworkBuffers( void ); /* Copy a network buffer into a bigger buffer. */ NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer, - BaseType_t xNewLength); + size_t uxNewLength); /* Increase the size of a Network Buffer. In case BufferAllocation_2.c is used, the new space must be allocated. */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h index 4e26f7e58..c3d3fb4bc 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.2.0 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c index 3540b15c2..fa3f4333f 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c @@ -280,13 +280,6 @@ UBaseType_t uxCount; pxReturn->pxNextBuffer = NULL; } #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ - - if( xTCPWindowLoggingLevel > 3 ) - { - FreeRTOS_debug_printf( ( "BUF_GET[%ld]: %p (%p)\n", - bIsValidNetworkDescriptor( pxReturn ), - pxReturn, pxReturn->pucEthernetBuffer ) ); - } } iptraceNETWORK_BUFFER_OBTAINED( pxReturn ); } @@ -390,11 +383,6 @@ BaseType_t xListItemAlreadyInFreeList; { xSemaphoreGive( xNetworkBufferSemaphore ); prvShowWarnings(); - if( xTCPWindowLoggingLevel > 3 ) - FreeRTOS_debug_printf( ( "BUF_PUT[%ld]: %p (%p) (now %lu)\n", - bIsValidNetworkDescriptor( pxNetworkBuffer ), - pxNetworkBuffer, pxNetworkBuffer->pucEthernetBuffer, - uxGetNumberOfFreeNetworkBuffers( ) ) ); } iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); } diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c index d6780b511..e008da07a 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c @@ -1,6 +1,6 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.0.11 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_end.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_end.h new file mode 100644 index 000000000..816b0b3b6 --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_end.h @@ -0,0 +1,33 @@ +/* +FreeRTOS+TCP V2.0.11 +Copyright (C) 2017 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://aws.amazon.com/freertos + http://www.FreeRTOS.org +*/ + +/***************************************************************************** + * + * See the following URL for an explanation of this file: + * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html + * + *****************************************************************************/ +; +#pragma pack(pop) diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_start.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_start.h new file mode 100644 index 000000000..29ea9ae3e --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_start.h @@ -0,0 +1,48 @@ +/* +FreeRTOS+TCP V2.0.11 +Copyright (C) 2017 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://aws.amazon.com/freertos + http://www.FreeRTOS.org +*/ + +/***************************************************************************** + * + * See the following URL for an explanation of this file: + * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html + * + *****************************************************************************/ + +#pragma pack(push,1) + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c index b869ccc85..83c96a07c 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c @@ -1,28 +1,27 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 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://aws.amazon.com/freertos - * http://www.FreeRTOS.org - */ - +FreeRTOS+TCP V2.0.11 +Copyright (C) 2017 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://aws.amazon.com/freertos + http://www.FreeRTOS.org +*/ /* Standard includes. */ #include @@ -83,10 +82,6 @@ expansion. */ #error Please define GMAC_USES_TX_CALLBACK as 1 #endif -#if( ipconfigZERO_COPY_RX_DRIVER != 0 ) - #warning The EMAC of SAM4E has fixed-size RX buffers so ZERO_COPY_RX is not possible -#endif - /* Default the size of the stack used by the EMAC deferred handler task to 4x the size of the stack used by the idle task - but allow this to be overridden in FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */ @@ -239,7 +234,7 @@ const TickType_t x5_Seconds = 5000UL; configASSERT( xTXDescriptorSemaphore ); } /* When returning non-zero, the stack will become active and - start DHCP (in configured) */ + start DHCP (in configured) */ return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0; } /*-----------------------------------------------------------*/ @@ -418,11 +413,11 @@ const TickType_t xShortTime = pdMS_TO_TICKS( 100UL ); if ( xProtPacket->xTCPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) { - IPHeader_t *pxIPHeader = &( xProtPacket->xTCPPacket.xIPHeader ); + IPHeader_t *pxIPHeader = &(xProtPacket->xTCPPacket.xIPHeader); /* Calculate the IP header checksum. */ pxIPHeader->usHeaderChecksum = 0x00; - pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0u, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER ); + pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER ); pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum ); /* Calculate the TCP checksum for an outgoing packet. */ @@ -504,43 +499,15 @@ static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; } /*-----------------------------------------------------------*/ -void vCheckBuffersAndQueue( void ) -{ -static UBaseType_t uxLastMinBufferCount = 0; -#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) - static UBaseType_t uxLastMinQueueSpace; -#endif -static UBaseType_t uxCurrentCount; - - #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) - { - uxCurrentCount = uxGetMinimumIPQueueSpace(); - if( uxLastMinQueueSpace != uxCurrentCount ) - { - /* The logging produced below may be helpful - while tuning +TCP: see how many buffers are in use. */ - uxLastMinQueueSpace = uxCurrentCount; - FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) ); - } - } - #endif /* ipconfigCHECK_IP_QUEUE_SPACE */ - uxCurrentCount = uxGetMinimumFreeNetworkBuffers(); - if( uxLastMinBufferCount != uxCurrentCount ) - { - /* The logging produced below may be helpful - while tuning +TCP: see how many buffers are in use. */ - uxLastMinBufferCount = uxCurrentCount; - FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", - uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) ); - } - -} - static void prvEMACHandlerTask( void *pvParameters ) { TimeOut_t xPhyTime; TickType_t xPhyRemTime; -UBaseType_t uxCount; +UBaseType_t uxLastMinBufferCount = 0, uxCount; +UBaseType_t uxCurrentCount; +#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) + UBaseType_t uxLastMinQueueSpace; +#endif #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) NetworkBufferDescriptor_t *pxBuffer; #endif @@ -559,7 +526,28 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS ); for( ;; ) { - vCheckBuffersAndQueue(); + uxCurrentCount = uxGetMinimumFreeNetworkBuffers(); + if( uxLastMinBufferCount != uxCurrentCount ) + { + /* The logging produced below may be helpful + while tuning +TCP: see how many buffers are in use. */ + uxLastMinBufferCount = uxCurrentCount; + FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", + uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) ); + } + + #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) + { + uxCurrentCount = uxGetMinimumIPQueueSpace(); + if( uxLastMinQueueSpace != uxCurrentCount ) + { + /* The logging produced below may be helpful + while tuning +TCP: see how many buffers are in use. */ + uxLastMinQueueSpace = uxCurrentCount; + FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) ); + } + } + #endif /* ipconfigCHECK_IP_QUEUE_SPACE */ if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 ) { diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c index fe73a73ac..948f9a661 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c @@ -429,7 +429,6 @@ void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev, * GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable. * Note: tha SAM4E does have RX checksum offloading * but TX checksum offloading has NOT been implemented. - * http://community.atmel.com/forum/sam4e-gmac-transmit-checksum-offload-enablesolved */ gmac_set_dma(p_gmac, @@ -658,7 +657,7 @@ uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer, } #else { - /* Or memcopy... */ + /* Or Memcopy... */ memcpy((void *)p_tx_td->addr, p_buffer, ul_size); } #endif /* ipconfigZERO_COPY_TX_DRIVER */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c index 47757e3bd..fa7695942 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c @@ -1,28 +1,3 @@ -/* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 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://aws.amazon.com/freertos - * http://www.FreeRTOS.org - */ - /* * Handling of Ethernet PHY's * PHY's communicate with an EMAC either through @@ -57,14 +32,29 @@ #endif #ifndef ipconfigPHY_LS_HIGH_CHECK_TIME_MS - /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not + /* Check if the LinkStatus in the PHY is still high after 15 seconds of not receiving packets. */ - #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000 + #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000uL #endif #ifndef ipconfigPHY_LS_LOW_CHECK_TIME_MS - /* Check if the LinkSStatus in the PHY is still low every second. */ - #define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000 + /* Check if the LinkStatus in the PHY is still low every second. */ + #define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000uL +#endif + +/* As the following 3 macro's are OK in most situations, and so they're not +included in 'FreeRTOSIPConfigDefaults.h'. +Users can change their values in the project's 'FreeRTOSIPConfig.h'. */ +#ifndef phyPHY_MAX_RESET_TIME_MS + #define phyPHY_MAX_RESET_TIME_MS 1000uL +#endif + +#ifndef phyPHY_MAX_NEGOTIATE_TIME_MS + #define phyPHY_MAX_NEGOTIATE_TIME_MS 3000uL +#endif + +#ifndef phySHORT_DELAY_MS + #define phySHORT_DELAY_MS 50uL #endif /* Naming and numbering of basic PHY registers. */ @@ -113,16 +103,18 @@ * Description of all capabilities that can be advertised to * the peer (usually a switch or router). */ -#define phyADVERTISE_CSMA 0x0001u /* Only selector supported. */ + +#define phyADVERTISE_CSMA 0x0001u /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */ #define phyADVERTISE_10HALF 0x0020u /* Try for 10mbps half-duplex. */ #define phyADVERTISE_10FULL 0x0040u /* Try for 10mbps full-duplex. */ #define phyADVERTISE_100HALF 0x0080u /* Try for 100mbps half-duplex. */ #define phyADVERTISE_100FULL 0x0100u /* Try for 100mbps full-duplex. */ #define phyADVERTISE_ALL ( phyADVERTISE_10HALF | phyADVERTISE_10FULL | \ - phyADVERTISE_100HALF | phyADVERTISE_100FULL ) + phyADVERTISE_100HALF | phyADVERTISE_100FULL | \ + phyADVERTISE_CSMA ) -/* Send a reset commando to a set of PHY-ports. */ +/* Send a reset command to a set of PHY-ports. */ static uint32_t xPhyReset( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask ); static BaseType_t xHas_1F_PHYSPCS( uint32_t ulPhyID ) @@ -224,7 +216,7 @@ BaseType_t xPhyAddress; } /*-----------------------------------------------------------*/ -/* Send a reset commando to a set of PHY-ports. */ +/* Send a reset command to a set of PHY-ports. */ static uint32_t xPhyReset( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask ) { uint32_t ulDoneMask, ulConfig; @@ -232,7 +224,7 @@ TickType_t xRemainingTime; TimeOut_t xTimer; BaseType_t xPhyIndex; - /* A bit-mask ofPHY ports that are ready. */ + /* A bit-mask of PHY ports that are ready. */ ulDoneMask = 0ul; /* Set the RESET bits high. */ @@ -245,7 +237,7 @@ BaseType_t xPhyIndex; pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig | phyBMCR_RESET ); } - xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( 1000UL ); + xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_RESET_TIME_MS ); vTaskSetTimeOutState( &xTimer ); /* The reset should last less than a second. */ @@ -272,19 +264,23 @@ BaseType_t xPhyIndex; break; } /* Block for a while */ - vTaskDelay( pdMS_TO_TICKS( 50ul ) ); + vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) ); } /* Clear the reset bits. */ for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) { - BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; + if( ( ulDoneMask & ( 1ul << xPhyIndex ) ) == 0uL ) + { + BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; - pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig ); - pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig & ~phyBMCR_RESET ); + /* The reset operation timed out, clear the bit manually. */ + pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig ); + pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig & ~phyBMCR_RESET ); + } } - vTaskDelay( pdMS_TO_TICKS( 50ul ) ); + vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) ); return ulDoneMask; } @@ -297,7 +293,7 @@ BaseType_t xPhyIndex; if( pxPhyObject->xPortCount < 1 ) { - FreeRTOS_printf( ( "xPhyResetAll: No PHY's detected.\n" ) ); + FreeRTOS_printf( ( "xPhyConfigure: No PHY's detected.\n" ) ); return -1; } @@ -308,11 +304,12 @@ BaseType_t xPhyIndex; /* Set advertise register. */ if( ( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO ) && ( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO ) ) { - ulAdvertise = phyADVERTISE_CSMA | phyADVERTISE_ALL; + ulAdvertise = phyADVERTISE_ALL; /* Reset auto-negotiation capability. */ } else { + /* Always select protocol 802.3u. */ ulAdvertise = phyADVERTISE_CSMA; if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO ) @@ -361,7 +358,7 @@ BaseType_t xPhyIndex; } } - /* Send a reset commando to a set of PHY-ports. */ + /* Send a reset command to a set of PHY-ports. */ xPhyReset( pxPhyObject, xPhyGetMask( pxPhyObject ) ); for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) @@ -450,6 +447,10 @@ BaseType_t xPhyIndex; } /*-----------------------------------------------------------*/ +/* xPhyFixedValue(): this function is called in case auto-negotiation is disabled. +The caller has set the values in 'xPhyPreferences' (ucDuplex and ucSpeed). +The PHY register phyREG_00_BMCR will be set for every connected PHY that matches +with ulPhyMask. */ BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask ) { BaseType_t xPhyIndex; @@ -480,6 +481,9 @@ uint32_t ulValue, ulBitMask = ( uint32_t )1u; } /*-----------------------------------------------------------*/ +/* xPhyStartAutoNegotiation() is the alternative xPhyFixedValue(): +It sets the BMCR_AN_RESTART bit and waits for the auto-negotiation completion +( phyBMSR_AN_COMPLETE ). */ BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask ) { uint32_t xPhyIndex, ulDoneMask, ulBitMask; @@ -491,7 +495,7 @@ TimeOut_t xTimer; { return 0; } - for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) + for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++ ) { if( ( ulPhyMask & ( 1lu << xPhyIndex ) ) != 0lu ) { @@ -502,14 +506,14 @@ TimeOut_t xTimer; pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue | phyBMCR_AN_RESTART ); } } - xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( 3000UL ); + xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_NEGOTIATE_TIME_MS ); vTaskSetTimeOutState( &xTimer ); ulDoneMask = 0; /* Wait until the auto-negotiation will be completed */ for( ;; ) { ulBitMask = ( uint32_t )1u; - for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) + for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) { if( ( ulPhyMask & ulBitMask ) != 0lu ) { @@ -531,17 +535,17 @@ TimeOut_t xTimer; } if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE ) { - FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) ); + FreeRTOS_printf( ( "xPhyStartAutoNegotiation: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) ); break; } - vTaskDelay( pdMS_TO_TICKS( 50 ) ); + vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) ); } if( ulDoneMask != ( uint32_t)0u ) { ulBitMask = ( uint32_t )1u; pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask ); - for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) + for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ]; @@ -623,7 +627,7 @@ TimeOut_t xTimer; pxPhyObject->fnPhyRead( xPhyAddress, PHYREG_10_PHYSTS, &ulRegValue); } - FreeRTOS_printf( ( ">> Autonego ready: %08lx: %s duplex %u mbit %s status\n", + FreeRTOS_printf( ( "Autonego ready: %08lx: %s duplex %u mbit %s status\n", ulRegValue, ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half", ( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100, @@ -676,6 +680,9 @@ BaseType_t xNeedCheck = pdFALSE; } else if( xTaskCheckForTimeOut( &( pxPhyObject->xLinkStatusTimer ), &( pxPhyObject->xLinkStatusRemaining ) ) != pdFALSE ) { + /* Frequent checking the PHY Link Status can affect for the performance of Ethernet controller. + As long as packets are received, no polling is needed. + Otherwise, polling will be done when the 'xLinkStatusTimer' expires. */ for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; @@ -700,10 +707,12 @@ BaseType_t xNeedCheck = pdFALSE; vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) ); if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 ) { + /* The link status is high, so don't poll the PHY too often. */ pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS ); } else { + /* The link status is low, polling may be done more frequently. */ pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS ); } } diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c new file mode 100644 index 000000000..e759141cc --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c @@ -0,0 +1,331 @@ +/* +FreeRTOS+TCP V2.0.11 +Copyright (C) 2018 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://aws.amazon.com/freertos + http://www.FreeRTOS.org +*/ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "list.h" +#include "queue.h" +#include "semphr.h" +#include "task.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" +#include "FreeRTOS_IP_Private.h" +#include "NetworkBufferManagement.h" +#include "NetworkInterface.h" + + +#include "m480_eth.h" + +/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet +driver will filter incoming packets and only pass the stack those packets it +considers need processing. */ +#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) +#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer +#else +#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) +#endif + +/* Default the size of the stack used by the EMAC deferred handler task to twice +the size of the stack used by the idle task - but allow this to be overridden in +FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */ +#ifndef configEMAC_TASK_STACK_SIZE + #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE ) +#endif + + +static SemaphoreHandle_t xTXMutex = NULL; + +/* The handle of the task that processes Rx packets. The handle is required so +the task can be notified when new packets arrive. */ +static TaskHandle_t xRxHanderTask = NULL; +static TimerHandle_t xPhyHandlerTask = NULL; +/* + * A task that processes received frames. + */ +static void prvEMACHandlerTask( void *pvParameters ); +static void prvPhyTmrCallback( TimerHandle_t xTimer ); + +/* The size of each buffer when BufferAllocation_1 is used: +http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */ + +#define niBUFFER_1_PACKET_SIZE 1536 +#ifdef __ICCARM__ +#pragma data_alignment=4 +static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] +#else +static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4))); +#endif + +BaseType_t xNetworkInterfaceInitialise( void ) +{ + uint8_t hwaddr[6]; + BaseType_t xReturn = pdPASS; + + /* Init ETH */ + numaker_mac_address(hwaddr); + FreeRTOS_UpdateMACAddress(hwaddr); + FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) ); + /* Enable clock & set EMAC configuration */ + /* Enable MAC and DMA transmission and reception */ + if( numaker_eth_init(hwaddr) < 0) + { + xReturn = pdFAIL; + } else { + xReturn = pdPASS; + /* Guard against the task being created more than once and the + descriptors being initialized more than once. */ + /* Timer task to monitor PHY Link status */ + if( xPhyHandlerTask == NULL ) + { + xPhyHandlerTask = xTimerCreate( "TimerPhy", pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback ); + configASSERT(xPhyHandlerTask); + xReturn = xTimerStart( xPhyHandlerTask, 0 ) ; + configASSERT( xReturn ); + } + /* Rx task */ + if( xRxHanderTask == NULL ) + { + xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask ); + configASSERT( xReturn ); + } + + if( xTXMutex == NULL ) + { + xTXMutex = xSemaphoreCreateMutex(); + configASSERT( xTXMutex ); + } + } + + NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY ); + NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY ); + + numaker_eth_enable_interrupts(); + + FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) ); + + return xReturn; +} + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) +{ + uint8_t *buffer=NULL; +// FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength)); + if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE ) + { + FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE)); + return pdFALSE; + } + + buffer = numaker_eth_get_tx_buf(); + if( buffer == NULL ) + { + NU_DEBUGF(("Eth TX slots are busy\n")); + return pdFALSE; + } + + /* Get exclusive access */ + xSemaphoreTake(xTXMutex, portMAX_DELAY); + NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer)); + //SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength + memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength); + numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL); + /* Call the standard trace macro to log the send event. */ + iptraceNETWORK_INTERFACE_TRANSMIT(); + + if( xReleaseAfterSend != pdFALSE ) + { + /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet + buffer. The Ethernet buffer is therefore no longer needed, and must be + freed for re-use. */ + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + } + + xSemaphoreGive(xTXMutex); + + return pdTRUE; +} + + +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ + + uint8_t *ucRAMBuffer = ucNetworkPackets; + uint32_t ul; + + for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) + { + pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING; + *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) ); + ucRAMBuffer += niBUFFER_1_PACKET_SIZE; + } +} + + +BaseType_t xGetPhyLinkStatus( void ) +{ + BaseType_t xReturn; + + if( numaker_eth_link_ok() ) + { + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; +} + +static void prvPhyTmrCallback( TimerHandle_t xTimer ) +{ + IPStackEvent_t xRxEvent; + static BaseType_t lastLink = pdFAIL; + BaseType_t currLink = xGetPhyLinkStatus(); + if( currLink != lastLink ) + { + FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down")); + if( !currLink ) + { + xRxEvent.eEventType = eNetworkDownEvent; + xSendEventStructToIPTask( &xRxEvent, 0 ); + } + lastLink = currLink; + } + +} + + +static void prvEMACHandlerTask( void *pvParameters ) +{ + TimeOut_t xPhyTime; + TickType_t xPhyRemTime; + UBaseType_t uxLastMinBufferCount = 0; + UBaseType_t uxCurrentCount; + BaseType_t xResult = 0; + uint32_t ulStatus; + uint16_t dataLength = 0; + uint8_t *buffer = NULL; + NetworkBufferDescriptor_t *pxBufferDescriptor = NULL; + IPStackEvent_t xRxEvent; + const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul ); + + /* Remove compiler warnings about unused parameters. */ + ( void ) pvParameters; + /* A possibility to set some additional task properties. */ + + for( ;; ) + { + uxCurrentCount = uxGetMinimumFreeNetworkBuffers(); + if( uxLastMinBufferCount != uxCurrentCount ) + { + /* The logging produced below may be helpful + while tuning +TCP: see how many buffers are in use. */ + uxLastMinBufferCount = uxCurrentCount; + FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", + uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) ); + } + + /* No events to process now, wait for the next. */ + ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); + while(1) + { + /* get received frame */ + if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) { + /* The event was lost because a network buffer was not available. + Call the standard trace macro to log the occurrence. */ + iptraceETHERNET_RX_EVENT_LOST(); + break; + } + + /* Allocate a network buffer descriptor that points to a buffer + large enough to hold the received frame. As this is the simple + rather than efficient example the received data will just be copied + into this buffer. */ + + pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( PACKET_BUFFER_SIZE, 0 ); + + if( pxBufferDescriptor != NULL ) + { + memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength ); +// FreeRTOS_printf(("--> dataLength=%d\n",dataLength)); + pxBufferDescriptor->xDataLength = dataLength; + } else { + numaker_eth_rx_next(); + iptraceETHERNET_RX_EVENT_LOST(); + break; + } + /* The event about to be sent to the TCP/IP is an Rx event. */ + xRxEvent.eEventType = eNetworkRxEvent; + + /* pvData is used to point to the network buffer descriptor that + now references the received data. */ + xRxEvent.pvData = ( void * ) pxBufferDescriptor; + + /* Send the data to the TCP/IP stack. */ + if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE ) + { + /* The buffer could not be sent to the IP task so the buffer + must be released. */ + vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor ); + + /* Make a call to the standard trace macro to log the + occurrence. */ + + iptraceETHERNET_RX_EVENT_LOST(); + } else + { + /* The message was successfully sent to the TCP/IP stack. + Call the standard trace macro to log the occurrence. */ + iptraceNETWORK_INTERFACE_RECEIVE(); + } + numaker_eth_rx_next(); + } + numaker_eth_trigger_rx(); + } +} + +void xNetworkCallback(char event) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + switch (event) + { + case 'R': //For RX event + /* Wakeup the prvEMACHandlerTask. */ + if( xRxHanderTask != NULL ) + { + vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } + break; + case 'T': //For TX event + // ack of tx done, no-op in this stage + break; + default: + break; + } +} diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.c new file mode 100644 index 000000000..2d45661d0 --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.c @@ -0,0 +1,448 @@ +/**************************************************************************//** + * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ +#include "FreeRTOS.h" +#include "list.h" +#include "FreeRTOS_IP.h" + +#include "m480_eth.h" + +#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0) +#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0) +#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0) +#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0) +#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0) +#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0) + + +struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4))); +struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4))); +#ifdef __ICCARM__ +#pragma data_alignment=4 +struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM]; +struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM]; +uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; +uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; +#else +struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4))); +struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4))); +uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4))); +uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4))); +#endif +struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr; + + +// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns +// Assume we want to set each tick to 100ns. +// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7 +// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz +// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600 + + + +static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val) +{ + + EMAC->MIIMDAT = val; + EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk; + + while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); + +} + + +static uint16_t mdio_read(uint8_t addr, uint8_t reg) +{ + EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk; + while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); + + return(EMAC->MIIMDAT); +} + +static int reset_phy(void) +{ + + uint16_t reg; + uint32_t delayCnt; + + + mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET); + + delayCnt = 2000; + while(delayCnt-- > 0) { + if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0) + break; + + } + + if(delayCnt == 0) { + NU_DEBUGF(("Reset phy failed\n")); + return(-1); + } + + mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA | + ADVERTISE_10HALF | + ADVERTISE_10FULL | + ADVERTISE_100HALF | + ADVERTISE_100FULL); + + reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR); + mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART); + + delayCnt = 200000; + while(delayCnt-- > 0) { + if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) + == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) + break; + } + + if(delayCnt == 0) { + NU_DEBUGF(("AN failed. Set to 100 FULL\n")); + EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + return(-1); + } else { + reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA); + + if(reg & ADVERTISE_100FULL) { + NU_DEBUGF(("100 full\n")); + EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } else if(reg & ADVERTISE_100HALF) { + NU_DEBUGF(("100 half\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; + } else if(reg & ADVERTISE_10FULL) { + NU_DEBUGF(("10 full\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; + } else { + NU_DEBUGF(("10 half\n")); + EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } + } + FreeRTOS_printf(("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1))); + FreeRTOS_printf(("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2))); + + return(0); +} + + +static void init_tx_desc(void) +{ + uint32_t i; + + + cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0]; + + for(i = 0; i < TX_DESCRIPTOR_NUM; i++) { + tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN; + tx_desc[i].buf = &tx_buf[i][0]; + tx_desc[i].status2 = 0; + tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM]; + + } + EMAC->TXDSA = (unsigned int)&tx_desc[0]; + return; +} + +static void init_rx_desc(void) +{ + uint32_t i; + + + cur_rx_desc_ptr = &rx_desc[0]; + + for(i = 0; i < RX_DESCRIPTOR_NUM; i++) { + rx_desc[i].status1 = OWNERSHIP_EMAC; + rx_desc[i].buf = &rx_buf[i][0]; + rx_desc[i].status2 = 0; + rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM]; + } + EMAC->RXDSA = (unsigned int)&rx_desc[0]; + return; +} + +void numaker_set_mac_addr(uint8_t *addr) +{ + + EMAC->CAM0M = (addr[0] << 24) | + (addr[1] << 16) | + (addr[2] << 8) | + addr[3]; + + EMAC->CAM0L = (addr[4] << 24) | + (addr[5] << 16); + + +} + +static void __eth_clk_pin_init() +{ + /* Unlock protected registers */ + SYS_UnlockReg(); + + /* Enable IP clock */ + CLK_EnableModuleClock(EMAC_MODULE); + + // Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH + CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127)); + + /* Update System Core Clock */ + SystemCoreClockUpdate(); + + /*---------------------------------------------------------------------------------------------------------*/ + /* Init I/O Multi-function */ + /*---------------------------------------------------------------------------------------------------------*/ + // Configure RMII pins + SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk); + SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV; + SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk); + SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0; + SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk; + SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK; + SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk | + SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk); + SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC | + SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO | + SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 | + SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 | + SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN; + + // Enable high slew rate on all RMII TX output pins + PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) | + (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) | + (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos); + + + /* Lock protected registers */ + SYS_LockReg(); + + +} + +int numaker_eth_init(uint8_t *mac_addr) +{ + int ret = 0; + // init CLK & pins + __eth_clk_pin_init(); + + // Reset MAC + EMAC->CTL = EMAC_CTL_RST_Msk; + while(EMAC->CTL & EMAC_CTL_RST_Msk) {} + + init_tx_desc(); + init_rx_desc(); + + numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc... + + + /* Configure the MAC interrupt enable register. */ + EMAC->INTEN = EMAC_INTEN_RXIEN_Msk | + EMAC_INTEN_TXIEN_Msk | + EMAC_INTEN_RXGDIEN_Msk | + EMAC_INTEN_TXCPIEN_Msk | + EMAC_INTEN_RXBEIEN_Msk | + EMAC_INTEN_TXBEIEN_Msk | + EMAC_INTEN_RDUIEN_Msk | + EMAC_INTEN_TSALMIEN_Msk | + EMAC_INTEN_WOLIEN_Msk; + + /* Configure the MAC control register. */ + EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk; + + /* Accept packets for us and all broadcast and multicast packets */ + EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | + EMAC_CAMCTL_AMP_Msk | + EMAC_CAMCTL_ABP_Msk; + EMAC->CAMEN = 1; // Enable CAM entry 0 + + ret= reset_phy(); + + EMAC_ENABLE_RX(); + EMAC_ENABLE_TX(); + return ret; +} + + + +void ETH_halt(void) +{ + + EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk); +} + +unsigned int m_status; + +void EMAC_RX_IRQHandler(void) +{ +// NU_DEBUGF(("%s ... \r\n", __FUNCTION__)); + m_status = EMAC->INTSTS & 0xFFFF; + EMAC->INTSTS = m_status; + if (m_status & EMAC_INTSTS_RXBEIF_Msk) { + // Shouldn't goes here, unless descriptor corrupted + NU_DEBUGF(("RX descriptor corrupted \r\n")); + //return; + } + // FIX ME: for rx-event, to ack rx_isr into event queue + xNetworkCallback('R'); +} + + +void numaker_eth_trigger_rx(void) +{ + ETH_TRIGGER_RX(); +} + +int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf) +{ + unsigned int cur_entry, status; + + cur_entry = EMAC->CRXDSA; + if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures + return -1; + status = cur_rx_desc_ptr->status1; + + if(status & OWNERSHIP_EMAC) + return -1; + + if (status & RXFD_RXGD) { + *buf = cur_rx_desc_ptr->buf; + *len = status & 0xFFFF; + } + return 0; +} + +void numaker_eth_rx_next(void) +{ + cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC; + cur_rx_desc_ptr = cur_rx_desc_ptr->next; +} + +void EMAC_TX_IRQHandler(void) +{ + unsigned int cur_entry, status; + + status = EMAC->INTSTS & 0xFFFF0000; + EMAC->INTSTS = status; + if(status & EMAC_INTSTS_TXBEIF_Msk) { + // Shouldn't goes here, unless descriptor corrupted + return; + } + + cur_entry = EMAC->CTXDSA; + + while (cur_entry != (uint32_t)fin_tx_desc_ptr) { + + fin_tx_desc_ptr = fin_tx_desc_ptr->next; + } + // FIX ME: for tx-event, no-op at this stage + xNetworkCallback('T'); +} + +uint8_t *numaker_eth_get_tx_buf(void) +{ + if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC) + return(NULL); + else + return(cur_tx_desc_ptr->buf); +} + +void numaker_eth_trigger_tx(uint16_t length, void *p) +{ + struct eth_descriptor volatile *desc; + cur_tx_desc_ptr->status2 = (unsigned int)length; + desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr + cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC; + cur_tx_desc_ptr = desc; + + ETH_TRIGGER_TX(); + +} + +int numaker_eth_link_ok(void) +{ + /* first, a dummy read to latch */ + mdio_read(CONFIG_PHY_ADDR, MII_BMSR); + if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS) + return 1; + return 0; +} + +//void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData) +//{ +// nu_eth_txrx_cb = eth_cb; +// nu_userData = userData; +//} + +// Provide ethernet devices with a semi-unique MAC address +void numaker_mac_address(uint8_t *mac) +{ + uint32_t uID1; + // Fetch word 0 + uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800 + // Fetch word 1 + // we only want bottom 16 bits of word1 (MAC bits 32-47) + // and bit 9 forced to 1, bit 8 forced to 0 + // Locally administered MAC, reduced conflicts + // http://en.wikipedia.org/wiki/MAC_address + uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800 + + if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash + { + // with a semi-unique MAC address from the UUID + /* Enable FMC ISP function */ + SYS_UnlockReg(); + FMC_Open(); + // = FMC_ReadUID(0); + uID1 = FMC_ReadUID(1); + word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8; + word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF); + /* Disable FMC ISP function */ + FMC_Close(); + /* Lock protected registers */ + SYS_LockReg(); + } + + word1 |= 0x00000200; + word1 &= 0x0000FEFF; + + mac[0] = (word1 & 0x0000ff00) >> 8; + mac[1] = (word1 & 0x000000ff); + mac[2] = (word0 & 0xff000000) >> 24; + mac[3] = (word0 & 0x00ff0000) >> 16; + mac[4] = (word0 & 0x0000ff00) >> 8; + mac[5] = (word0 & 0x000000ff); + + NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5])); +} + +void numaker_eth_enable_interrupts(void) { + EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk | + EMAC_INTEN_TXIEN_Msk ; + NVIC_EnableIRQ(EMAC_RX_IRQn); + NVIC_EnableIRQ(EMAC_TX_IRQn); +} + +void numaker_eth_disable_interrupts(void) { + NVIC_DisableIRQ(EMAC_RX_IRQn); + NVIC_DisableIRQ(EMAC_TX_IRQn); +} diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.h new file mode 100644 index 000000000..4e4d98d6d --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.h @@ -0,0 +1,164 @@ +/**************************************************************************//** + * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ +#include "M480.h" +#ifndef _M480_ETH_ +#define _M480_ETH_ + +/* Generic MII registers. */ + +#define MII_BMCR 0x00 /* Basic mode control register */ +#define MII_BMSR 0x01 /* Basic mode status register */ +#define MII_PHYSID1 0x02 /* PHYS ID 1 */ +#define MII_PHYSID2 0x03 /* PHYS ID 2 */ +#define MII_ADVERTISE 0x04 /* Advertisement control reg */ +#define MII_LPA 0x05 /* Link partner ability reg */ +#define MII_EXPANSION 0x06 /* Expansion register */ +#define MII_DCOUNTER 0x12 /* Disconnect counter */ +#define MII_FCSCOUNTER 0x13 /* False carrier counter */ +#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ +#define MII_RERRCOUNTER 0x15 /* Receive error counter */ +#define MII_SREVISION 0x16 /* Silicon revision */ +#define MII_RESV1 0x17 /* Reserved... */ +#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ +#define MII_PHYADDR 0x19 /* PHY address */ +#define MII_RESV2 0x1a /* Reserved... */ +#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ +#define MII_NCONFIG 0x1c /* Network interface config */ + +/* Basic mode control register. */ +#define BMCR_RESV 0x007f /* Unused... */ +#define BMCR_CTST 0x0080 /* Collision test */ +#define BMCR_FULLDPLX 0x0100 /* Full duplex */ +#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ +#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */ +#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */ +#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ +#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ +#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ +#define BMCR_RESET 0x8000 /* Reset the DP83840 */ + +/* Basic mode status register. */ +#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ +#define BMSR_JCD 0x0002 /* Jabber detected */ +#define BMSR_LSTATUS 0x0004 /* Link status */ +#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ +#define BMSR_RFAULT 0x0010 /* Remote fault detected */ +#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ +#define BMSR_RESV 0x07c0 /* Unused... */ +#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ +#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ +#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ +#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ +#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */ + +/* Advertisement control register. */ +#define ADVERTISE_SLCT 0x001f /* Selector bits */ +#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ +#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ +#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ +#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ +#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ +#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ +#define ADVERTISE_RESV 0x1c00 /* Unused... */ +#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ +#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ +#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ + +#define RX_DESCRIPTOR_NUM 4 //8 // Max Number of Rx Frame Descriptors +#define TX_DESCRIPTOR_NUM 2 //4 // Max number of Tx Frame Descriptors + +#define PACKET_BUFFER_SIZE 1520 + +#define CONFIG_PHY_ADDR 1 + + +// Frame Descriptor's Owner bit +#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC +//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU + + + +// Rx Frame Descriptor Status +#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received +#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available + + +// Tx Frame Descriptor's Control bits +#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable +#define TXFD_INTEN 0x04 // Interrupt Enable +#define TXFD_CRCAPP 0x02 // Append CRC +#define TXFD_PADEN 0x01 // Padding Enable + +// Tx Frame Descriptor Status +#define TXFD_TXCP 0x00080000 // Transmission Completion +#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available + +// Tx/Rx buffer descriptor structure +struct eth_descriptor; +struct eth_descriptor { + uint32_t status1; + uint8_t *buf; + uint32_t status2; + struct eth_descriptor *next; +#ifdef TIME_STAMPING + uint32_t backup1; + uint32_t backup2; + uint32_t reserved1; + uint32_t reserved2; +#endif +}; + +#ifdef TIME_STAMPING + +#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0) +#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0) +s32_t ETH_settime(u32_t sec, u32_t nsec); +s32_t ETH_gettime(u32_t *sec, u32_t *nsec); +s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec); +s32_t ETH_adjtimex(int ppm); +void ETH_setinc(void); + +#endif + +#ifdef NU_TRACE +#define NU_DEBUGF(x) { printf x; } +#else +#define NU_DEBUGF(x) +#endif + +void numaker_set_mac_addr(uint8_t *addr); +int numaker_eth_init(uint8_t *mac_addr); +uint8_t *numaker_eth_get_tx_buf(void); +void numaker_eth_trigger_tx(uint16_t length, void *p); +int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf); +void numaker_eth_rx_next(void); +void numaker_eth_trigger_rx(void); +int numaker_eth_link_ok(void); +void numaker_mac_address(uint8_t *mac); +void numaker_eth_enable_interrupts(void); +void numaker_eth_disable_interrupts(void); + +#endif /* _M480_ETH_ */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/NetworkInterface.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/NetworkInterface.c new file mode 100644 index 000000000..5a605af9b --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/NetworkInterface.c @@ -0,0 +1,629 @@ +/*********************************************************************************************************************** +* DISCLAIMER +* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No +* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all +* applicable laws, including copyright laws. +* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING +* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM +* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES +* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS +* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of +* this software. By using this software, you agree to the additional terms and conditions found by accessing the +* following link: +* http://www.renesas.com/disclaimer +* +* Copyright (C) 2018 Renesas Electronics Corporation. All rights reserved. +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +* File Name : NetworkInterface.c +* Device(s) : RX +* Description : Interfaces FreeRTOS TCP/IP stack to RX Ethernet driver. +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +* History : DD.MM.YYYY Version Description +* : 07.03.2018 0.1 Development +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +* Includes , "Project Includes" +***********************************************************************************************************************/ +#include +#include +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "FreeRTOS_IP.h" +#include "FreeRTOS_IP_Private.h" +/*#include "FreeRTOS_DNS.h" */ +#include "NetworkBufferManagement.h" +#include "NetworkInterface.h" + +#include "r_ether_rx_if.h" +#include "r_pinset.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ +#define ETHER_BUFSIZE_MIN 60 + +#if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) + #if ETHER_CFG_MODE_SEL == 0 + #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC0_MII() + #elif ETHER_CFG_MODE_SEL == 1 + #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC0_RMII() + #endif +#elif defined( BSP_MCU_RX63N ) + #if ETHER_CFG_MODE_SEL == 0 + #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC_MII() + #elif ETHER_CFG_MODE_SEL == 1 + #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC_RMII() + #endif +#endif /* if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) */ + +#ifndef PHY_LS_HIGH_CHECK_TIME_MS + +/* Check if the LinkSStatus in the PHY is still high after 2 seconds of not + * receiving packets. */ + #define PHY_LS_HIGH_CHECK_TIME_MS 2000 +#endif + +#ifndef PHY_LS_LOW_CHECK_TIME_MS + /* Check if the LinkSStatus in the PHY is still low every second. */ + #define PHY_LS_LOW_CHECK_TIME_MS 1000 +#endif + +/*********************************************************************************************************************** + * Private global variables and functions + **********************************************************************************************************************/ +typedef enum +{ + eMACInit, /* Must initialise MAC. */ + eMACPass, /* Initialisation was successful. */ + eMACFailed, /* Initialisation failed. */ +} eMAC_INIT_STATUS_TYPE; + +static TaskHandle_t ether_receive_check_task_handle = 0; +static TaskHandle_t ether_link_check_task_handle = 0; +static TaskHandle_t xTaskToNotify = NULL; +static BaseType_t xPHYLinkStatus; +static BaseType_t xReportedStatus; +static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit; + +static int16_t SendData( uint8_t * pucBuffer, + size_t length ); +static int InitializeNetwork( void ); +static void prvEMACDeferredInterruptHandlerTask( void * pvParameters ); +static void clear_all_ether_rx_discriptors( uint32_t event ); + +int32_t callback_ether_regist( void ); +void EINT_Trig_isr( void * ); +void get_random_number( uint8_t * data, + uint32_t len ); + +void prvLinkStatusChange( BaseType_t xStatus ); +#if ( ipconfigHAS_PRINTF != 0 ) + static void prvMonitorResources( void ); +#endif + +/*********************************************************************************************************************** + * Function Name: xNetworkInterfaceInitialise () + * Description : Initialization of Ethernet driver. + * Arguments : none + * Return Value : pdPASS, pdFAIL + **********************************************************************************************************************/ +BaseType_t xNetworkInterfaceInitialise( void ) +{ + BaseType_t xReturn; + + if( xMacInitStatus == eMACInit ) + { + /* + * Perform the hardware specific network initialization here using the Ethernet driver library to initialize the + * Ethernet hardware, initialize DMA descriptors, and perform a PHY auto-negotiation to obtain a network link. + * + * InitialiseNetwork() uses Ethernet peripheral driver library function, and returns 0 if the initialization fails. + */ + if( InitializeNetwork() == pdFALSE ) + { + xMacInitStatus = eMACFailed; + } + else + { + /* Indicate that the MAC initialisation succeeded. */ + xMacInitStatus = eMACPass; + } + + FreeRTOS_printf( ( "InitializeNetwork returns %s\n", ( xMacInitStatus == eMACPass ) ? "OK" : " Fail" ) ); + } + + if( xMacInitStatus == eMACPass ) + { + xReturn = xPHYLinkStatus; + } + else + { + xReturn = pdFAIL; + } + + FreeRTOS_printf( ( "xNetworkInterfaceInitialise returns %d\n", xReturn ) ); + + return xReturn; +} /* End of function xNetworkInterfaceInitialise() */ + + +/*********************************************************************************************************************** + * Function Name: xNetworkInterfaceOutput () + * Description : Simple network output interface. + * Arguments : pxDescriptor, xReleaseAfterSend + * Return Value : pdTRUE, pdFALSE + **********************************************************************************************************************/ +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, + BaseType_t xReleaseAfterSend ) +{ + BaseType_t xReturn = pdFALSE; + + /* Simple network interfaces (as opposed to more efficient zero copy network + * interfaces) just use Ethernet peripheral driver library functions to copy + * data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer. + * This example assumes SendData() is a peripheral driver library function that + * takes a pointer to the start of the data to be sent and the length of the + * data to be sent as two separate parameters. The start of the data is located + * by pxDescriptor->pucEthernetBuffer. The length of the data is located + * by pxDescriptor->xDataLength. */ + if( xPHYLinkStatus != 0 ) + { + if( SendData( pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ) >= 0 ) + { + xReturn = pdTRUE; + /* Call the standard trace macro to log the send event. */ + iptraceNETWORK_INTERFACE_TRANSMIT(); + } + } + else + { + /* As the PHY Link Status is low, it makes no sense trying to deliver a packet. */ + } + + if( xReleaseAfterSend != pdFALSE ) + { + /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet + * buffer. The Ethernet buffer is therefore no longer needed, and must be + * freed for re-use. */ + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + } + + return xReturn; +} /* End of function xNetworkInterfaceOutput() */ + + +#if ( ipconfigHAS_PRINTF != 0 ) + static void prvMonitorResources() + { + static UBaseType_t uxLastMinBufferCount = 0u; + static UBaseType_t uxCurrentBufferCount = 0u; + static size_t uxMinLastSize = 0uL; + static size_t uxCurLastSize = 0uL; + size_t uxMinSize; + size_t uxCurSize; + + uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers(); + + if( uxLastMinBufferCount != uxCurrentBufferCount ) + { + /* The logging produced below may be helpful + * while tuning +TCP: see how many buffers are in use. */ + uxLastMinBufferCount = uxCurrentBufferCount; + FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", + uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) ); + } + + uxMinSize = xPortGetMinimumEverFreeHeapSize(); + uxCurSize = xPortGetFreeHeapSize(); + + if( uxMinLastSize != uxMinSize ) + { + uxCurLastSize = uxCurSize; + uxMinLastSize = uxMinSize; + FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", uxCurSize, uxMinSize ) ); + } + + #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) + { + static UBaseType_t uxLastMinQueueSpace = 0; + UBaseType_t uxCurrentCount = 0u; + + uxCurrentCount = uxGetMinimumIPQueueSpace(); + + if( uxLastMinQueueSpace != uxCurrentCount ) + { + /* The logging produced below may be helpful + * while tuning +TCP: see how many buffers are in use. */ + uxLastMinQueueSpace = uxCurrentCount; + FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) ); + } + } + #endif /* ipconfigCHECK_IP_QUEUE_SPACE */ + } +#endif /* ( ipconfigHAS_PRINTF != 0 ) */ + +/*********************************************************************************************************************** + * Function Name: prvEMACDeferredInterruptHandlerTask () + * Description : The deferred interrupt handler is a standard RTOS task. + * Arguments : pvParameters + * Return Value : none + **********************************************************************************************************************/ +static void prvEMACDeferredInterruptHandlerTask( void * pvParameters ) +{ + NetworkBufferDescriptor_t * pxBufferDescriptor; + int32_t xBytesReceived = 0; + + /* Avoid compiler warning about unreferenced parameter. */ + ( void ) pvParameters; + + /* Used to indicate that xSendEventStructToIPTask() is being called because + * of an Ethernet receive event. */ + IPStackEvent_t xRxEvent; + + uint8_t * buffer_pointer; + + /* Some variables related to monitoring the PHY. */ + TimeOut_t xPhyTime; + TickType_t xPhyRemTime; + const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL ); + + vTaskSetTimeOutState( &xPhyTime ); + xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); + + FreeRTOS_printf( ( "Deferred Interrupt Handler Task started\n" ) ); + xTaskToNotify = ether_receive_check_task_handle; + + for( ; ; ) + { + #if ( ipconfigHAS_PRINTF != 0 ) + { + prvMonitorResources(); + } + #endif /* ipconfigHAS_PRINTF != 0 ) */ + + /* Wait for the Ethernet MAC interrupt to indicate that another packet + * has been received. */ + if( xBytesReceived <= 0 ) + { + ulTaskNotifyTake( pdFALSE, ulMaxBlockTime ); + } + + /* See how much data was received. */ + xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer ); + + if( xBytesReceived < 0 ) + { + /* This is an error. Logged. */ + if( xBytesReceived == ETHER_ERR_LINK ) + { + /* Auto-negotiation is not completed, and transmission/ + reception is not enabled. Will be logged elsewhere. */ + } + else + { + FreeRTOS_printf( ( "R_ETHER_Read_ZC2: rc = %d not %d\n", xBytesReceived, ETHER_ERR_LINK ) ); + } + } + else if( xBytesReceived > 0 ) + { + /* Allocate a network buffer descriptor that points to a buffer + * large enough to hold the received frame. As this is the simple + * rather than efficient example the received data will just be copied + * into this buffer. */ + pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ( size_t ) xBytesReceived, 0 ); + + if( pxBufferDescriptor != NULL ) + { + /* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet + * buffer large enough to hold the received data. Copy the + * received data into pcNetworkBuffer->pucEthernetBuffer. Here it + * is assumed ReceiveData() is a peripheral driver function that + * copies the received data into a buffer passed in as the function's + * parameter. Remember! While is is a simple robust technique - + * it is not efficient. An example that uses a zero copy technique + * is provided further down this page. */ + memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer_pointer, ( size_t ) xBytesReceived ); + /*ReceiveData( pxBufferDescriptor->pucEthernetBuffer ); */ + + /* Set the actual packet length, in case a larger buffer was returned. */ + pxBufferDescriptor->xDataLength = ( size_t ) xBytesReceived; + + R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 ); + + /* See if the data contained in the received Ethernet frame needs + * to be processed. NOTE! It is preferable to do this in + * the interrupt service routine itself, which would remove the need + * to unblock this task for packets that don't need processing. */ + if( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer ) == eProcessBuffer ) + { + /* The event about to be sent to the TCP/IP is an Rx event. */ + xRxEvent.eEventType = eNetworkRxEvent; + + /* pvData is used to point to the network buffer descriptor that + * now references the received data. */ + xRxEvent.pvData = ( void * ) pxBufferDescriptor; + + /* Send the data to the TCP/IP stack. */ + if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE ) + { + /* The buffer could not be sent to the IP task so the buffer must be released. */ + vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor ); + + /* Make a call to the standard trace macro to log the occurrence. */ + iptraceETHERNET_RX_EVENT_LOST(); + clear_all_ether_rx_discriptors( 0 ); + } + else + { + /* The message was successfully sent to the TCP/IP stack. + * Call the standard trace macro to log the occurrence. */ + iptraceNETWORK_INTERFACE_RECEIVE(); + R_NOP(); + } + } + else + { + /* The Ethernet frame can be dropped, but the Ethernet buffer must be released. */ + vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor ); + } + } + else + { + /* The event was lost because a network buffer was not available. + * Call the standard trace macro to log the occurrence. */ + iptraceETHERNET_RX_EVENT_LOST(); + clear_all_ether_rx_discriptors( 1 ); + FreeRTOS_printf( ( "R_ETHER_Read_ZC2: Cleared descriptors\n" ) ); + } + } + + if( xBytesReceived > 0 ) + { + /* A packet was received. No need to check for the PHY status now, + * but set a timer to check it later on. */ + vTaskSetTimeOutState( &xPhyTime ); + xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); + + /* Indicate that the Link Status is high, so that + * xNetworkInterfaceOutput() can send packets. */ + if( xPHYLinkStatus == 0 ) + { + xPHYLinkStatus = 1; + FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS assume %d\n", xPHYLinkStatus ) ); + } + } + else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) || ( FreeRTOS_IsNetworkUp() == pdFALSE ) ) + { + R_ETHER_LinkProcess( 0 ); + + if( xPHYLinkStatus != xReportedStatus ) + { + xPHYLinkStatus = xReportedStatus; + FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", xPHYLinkStatus ) ); + } + + vTaskSetTimeOutState( &xPhyTime ); + + if( xPHYLinkStatus != 0 ) + { + xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); + } + else + { + xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); + } + } + } +} /* End of function prvEMACDeferredInterruptHandlerTask() */ + + +/*********************************************************************************************************************** + * Function Name: vNetworkInterfaceAllocateRAMToBuffers () + * Description : . + * Arguments : pxNetworkBuffers + * Return Value : none + **********************************************************************************************************************/ +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ + uint32_t ul; + uint8_t * buffer_address; + + R_EXTERN_SEC( B_ETHERNET_BUFFERS_1 ) + + buffer_address = R_SECTOP( B_ETHERNET_BUFFERS_1 ); + + for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) + { + pxNetworkBuffers[ ul ].pucEthernetBuffer = ( buffer_address + ( ETHER_CFG_BUFSIZE * ul ) ); + } +} /* End of function vNetworkInterfaceAllocateRAMToBuffers() */ + + +/*********************************************************************************************************************** + * Function Name: prvLinkStatusChange () + * Description : Function will be called when the Link Status of the phy has changed ( see ether_callback.c ) + * Arguments : xStatus : true when statyus has become high + * Return Value : void + **********************************************************************************************************************/ +void prvLinkStatusChange( BaseType_t xStatus ) +{ + if( xReportedStatus != xStatus ) + { + xReportedStatus = xStatus; + } +} + +/*********************************************************************************************************************** + * Function Name: InitializeNetwork () + * Description : + * Arguments : none + * Return Value : pdTRUE, pdFALSE + **********************************************************************************************************************/ +static int InitializeNetwork( void ) +{ + ether_return_t eth_ret; + BaseType_t return_code = pdFALSE; + ether_param_t param; + uint8_t myethaddr[ 6 ] = + { + configMAC_ADDR0, + configMAC_ADDR1, + configMAC_ADDR2, + configMAC_ADDR3, + configMAC_ADDR4, + configMAC_ADDR5 + }; /*XXX Fix me */ + + R_ETHER_PinSet_CHANNEL_0(); + R_ETHER_Initial(); + callback_ether_regist(); + + param.channel = ETHER_CHANNEL_0; + eth_ret = R_ETHER_Control( CONTROL_POWER_ON, param ); /* PHY mode settings, module stop cancellation */ + + if( ETHER_SUCCESS != eth_ret ) + { + return pdFALSE; + } + + eth_ret = R_ETHER_Open_ZC2( ETHER_CHANNEL_0, myethaddr, ETHER_FLAG_OFF ); + + if( ETHER_SUCCESS != eth_ret ) + { + return pdFALSE; + } + + return_code = xTaskCreate( prvEMACDeferredInterruptHandlerTask, + "ETHER_RECEIVE_CHECK_TASK", + 512u, + 0, + configMAX_PRIORITIES - 1, + ðer_receive_check_task_handle ); + + if( pdFALSE == return_code ) + { + return pdFALSE; + } + + return pdTRUE; +} /* End of function InitializeNetwork() */ + + +/*********************************************************************************************************************** + * Function Name: SendData () + * Description : + * Arguments : pucBuffer, length + * Return Value : 0 success, negative fail + **********************************************************************************************************************/ +static int16_t SendData( uint8_t * pucBuffer, + size_t length ) /*TODO complete stub function */ +{ + ether_return_t ret; + uint8_t * pwrite_buffer; + uint16_t write_buf_size; + + /* (1) Retrieve the transmit buffer location controlled by the descriptor. */ + ret = R_ETHER_Write_ZC2_GetBuf( ETHER_CHANNEL_0, ( void ** ) &pwrite_buffer, &write_buf_size ); + + if( ETHER_SUCCESS == ret ) + { + if( write_buf_size >= length ) + { + memcpy( pwrite_buffer, pucBuffer, length ); + } + + if( length < ETHER_BUFSIZE_MIN ) /*under minimum*/ + { + memset( ( pwrite_buffer + length ), 0, ( ETHER_BUFSIZE_MIN - length ) ); /*padding*/ + length = ETHER_BUFSIZE_MIN; /*resize*/ + } + + ret = R_ETHER_Write_ZC2_SetBuf( ETHER_CHANNEL_0, ( uint16_t ) length ); + ret = R_ETHER_CheckWrite( ETHER_CHANNEL_0 ); + } + + if( ETHER_SUCCESS != ret ) + { + return -5; /* XXX return meaningful value */ + } + else + { + return 0; + } +} /* End of function SendData() */ + + +/*********************************************************************************************************************** +* Function Name: EINT_Trig_isr +* Description : Standard frame received interrupt handler +* Arguments : ectrl - EDMAC and ETHERC control structure +* Return Value : None +* Note : This callback function is executed when EINT0 interrupt occurred. +***********************************************************************************************************************/ +void EINT_Trig_isr( void * ectrl ) +{ + ether_cb_arg_t * pdecode; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + pdecode = ( ether_cb_arg_t * ) ectrl; + + if( pdecode->status_eesr & 0x00040000 ) /* EDMAC FR (Frame Receive Event) interrupt */ + { + if( xTaskToNotify != NULL ) + { + vTaskNotifyGiveFromISR( ether_receive_check_task_handle, &xHigherPriorityTaskWoken ); + } + + /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch + * should be performed to ensure the interrupt returns directly to the highest + * priority task. The macro used for this purpose is dependent on the port in + * use and may be called portEND_SWITCHING_ISR(). */ + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + /*TODO complete interrupt handler for other events. */ + } +} /* End of function EINT_Trig_isr() */ + + +static void clear_all_ether_rx_discriptors( uint32_t event ) +{ + int32_t xBytesReceived; + uint8_t * buffer_pointer; + + /* Avoid compiler warning about unreferenced parameter. */ + ( void ) event; + + while( 1 ) + { + /* See how much data was received. */ + xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer ); + + if( 0 > xBytesReceived ) + { + /* This is an error. Ignored. */ + } + else if( 0 < xBytesReceived ) + { + R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 ); + iptraceETHERNET_RX_EVENT_LOST(); + } + else + { + break; + } + } +} + +/*********************************************************************************************************************** + * End of file "NetworkInterface.c" + **********************************************************************************************************************/ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/ether_callback.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/ether_callback.c new file mode 100644 index 000000000..c42d8a20b --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/ether_callback.c @@ -0,0 +1,177 @@ +/*********************************************************************************************************************** +* DISCLAIMER +* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No +* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all +* applicable laws, including copyright laws. +* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING +* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM +* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES +* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS +* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of +* this software. By using this software, you agree to the additional terms and conditions found by accessing the +* following link: +* http://www.renesas.com/disclaimer +* +* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved. +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* File Name : ether_callback.c +* Version : ---- +* Description : This module solves all the world's problems +***********************************************************************************************************************/ +/********************************************************************************************************************** +* History : DD.MM.YYYY Version Description +* : 05.01.2015 ---- Clean up source code. +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +Includes , "Project Includes" +***********************************************************************************************************************/ +#include "r_ether_rx_if.h" + +/*********************************************************************************************************************** +Private global variables and functions +***********************************************************************************************************************/ +int32_t callback_ether_regist(void); +void callback_ether(void * pparam); +static void callback_wakeon_lan(uint32_t channel); +static void callback_link_on(uint32_t channel); +static void callback_link_off(uint32_t channel); + +volatile uint8_t pause_enable = ETHER_FLAG_OFF; +volatile uint8_t magic_packet_detect[ETHER_CHANNEL_MAX]; +volatile uint8_t link_detect[ETHER_CHANNEL_MAX]; + +void EINT_Trig_isr(void *); + +/* + * When that Link Status changes, the following function will be called: + */ +void prvLinkStatusChange( BaseType_t xStatus ); + +/*********************************************************************************************************************** +* Function Name: callback_ether +* Description : Regist of callback function +* Arguments : - +* Return Value : 0: success, -1:failed +***********************************************************************************************************************/ +int32_t callback_ether_regist(void) +{ + ether_param_t param; + ether_cb_t cb_func; + + int32_t ret; + + /* Set the callback function (LAN cable connect/disconnect event) */ + cb_func.pcb_func = &callback_ether; + param.ether_callback = cb_func; + ret = R_ETHER_Control(CONTROL_SET_CALLBACK, param); + if (ETHER_SUCCESS != ret) + { + return -1; + } + + /* Set the callback function (Ether interrupt event) */ + cb_func.pcb_int_hnd = &EINT_Trig_isr; + param.ether_callback = cb_func; + ret = R_ETHER_Control(CONTROL_SET_INT_HANDLER, param); + if (ETHER_SUCCESS != ret) + { + return -1; + } + return 0; +} /* End of function callback_ether_regist() */ + +/*********************************************************************************************************************** +* Function Name: callback_ether +* Description : Sample of the callback function +* Arguments : pparam - +* +* Return Value : none +***********************************************************************************************************************/ +void callback_ether(void * pparam) +{ + ether_cb_arg_t * pdecode; + uint32_t channel; + + pdecode = (ether_cb_arg_t *)pparam; + channel = pdecode->channel; /* Get Ethernet channel number */ + + switch (pdecode->event_id) + { + /* Callback function that notifies user to have detected magic packet. */ + case ETHER_CB_EVENT_ID_WAKEON_LAN: + callback_wakeon_lan(channel); + break; + + /* Callback function that notifies user to have become Link up. */ + case ETHER_CB_EVENT_ID_LINK_ON: + callback_link_on(channel); + break; + + /* Callback function that notifies user to have become Link down. */ + case ETHER_CB_EVENT_ID_LINK_OFF: + callback_link_off(channel); + break; + + default: + break; + } +} /* End of function callback_ether() */ + +/*********************************************************************************************************************** +* Function Name: callback_wakeon_lan +* Description : +* Arguments : channel - +* Ethernet channel number +* Return Value : none +***********************************************************************************************************************/ +static void callback_wakeon_lan(uint32_t channel) +{ + if (ETHER_CHANNEL_MAX > channel) + { + magic_packet_detect[channel] = 1; + + /* Please add necessary processing when magic packet is detected. */ + } +} /* End of function callback_wakeon_lan() */ + +/*********************************************************************************************************************** +* Function Name: callback_link_on +* Description : +* Arguments : channel - +* Ethernet channel number +* Return Value : none +***********************************************************************************************************************/ +static void callback_link_on(uint32_t channel) +{ + if (ETHER_CHANNEL_MAX > channel) + { + link_detect[channel] = ETHER_FLAG_ON_LINK_ON; + + /* Please add necessary processing when becoming Link up. */ + prvLinkStatusChange( 1 ); + } +} /* End of function callback_link_on() */ + +/*********************************************************************************************************************** +* Function Name: callback_link_off +* Description : +* Arguments : channel - +* Ethernet channel number +* Return Value : none +***********************************************************************************************************************/ +static void callback_link_off(uint32_t channel) +{ + if (ETHER_CHANNEL_MAX > channel) + { + link_detect[channel] = ETHER_FLAG_ON_LINK_OFF; + + /* Please add necessary processing when becoming Link down. */ + prvLinkStatusChange( 0 ); + } +} /* End of function ether_cb_link_off() */ + +/* End of File */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32F7xx/NetworkInterface.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32F7xx/NetworkInterface.c index ec58eb36e..7de2902f8 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32F7xx/NetworkInterface.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32F7xx/NetworkInterface.c @@ -4,8 +4,8 @@ */ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS+TCP V2.0.11 + * Copyright (C) 2017 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 diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c index 7b98a93ee..6fad9216e 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c @@ -4,28 +4,28 @@ */ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 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://aws.amazon.com/freertos - * http://www.FreeRTOS.org +FreeRTOS+TCP V2.0.11 +Copyright (C) 2017 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://aws.amazon.com/freertos + http://www.FreeRTOS.org */ /* Standard includes. */ @@ -44,12 +44,11 @@ #include "FreeRTOS_Sockets.h" #include "FreeRTOS_IP_Private.h" #include "FreeRTOS_DNS.h" +#include "FreeRTOS_ARP.h" #include "NetworkBufferManagement.h" #include "NetworkInterface.h" #include "phyHandling.h" -#define __STM32_HAL_LEGACY 1 - /* ST includes. */ #if defined( STM32F7xx ) #include "stm32f7xx_hal.h" @@ -57,7 +56,7 @@ #include "stm32f4xx_hal.h" #elif defined( STM32F2xx ) #include "stm32f2xx_hal.h" -#else +#elif !defined( _lint ) /* Lint does not like an #error */ #error What part? #endif @@ -82,6 +81,14 @@ expansion. */ #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */ +#if( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) ) + #warning Consider enabling checksum offloading +#endif + +#ifndef niDESCRIPTOR_WAIT_TIME_MS + #define niDESCRIPTOR_WAIT_TIME_MS 250uL +#endif + /* * Most users will want a PHY that negotiates about * the connection properties: speed, dmix and duplex. @@ -139,6 +146,15 @@ and the index of the PHY in use ( between 0 and 31 ). */ #warning Using MII, make sure if this is correct #endif +typedef enum +{ + eMACInit, /* Must initialise MAC. */ + eMACPass, /* Initialisation was successful. */ + eMACFailed, /* Initialisation failed. */ +} eMAC_INIT_STATUS_TYPE; + +static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit; + /*-----------------------------------------------------------*/ /* @@ -179,9 +195,9 @@ static void prvDMATxDescListInit( void ); */ static void prvDMARxDescListInit( void ); - /* After packets have been sent, the network - buffers will be released. */ - static void vClearTXBuffers( void ); +/* After packets have been sent, the network +buffers will be released. */ +static void vClearTXBuffers( void ); /*-----------------------------------------------------------*/ @@ -199,10 +215,10 @@ static EthernetPhy_t xPhyObject; /* Ethernet handle. */ static ETH_HandleTypeDef xETH; - /* xTXDescriptorSemaphore is a counting semaphore with - a maximum count of ETH_TXBUFNB, which is the number of - DMA TX descriptors. */ - static SemaphoreHandle_t xTXDescriptorSemaphore = NULL; +/* xTXDescriptorSemaphore is a counting semaphore with +a maximum count of ETH_TXBUFNB, which is the number of +DMA TX descriptors. */ +static SemaphoreHandle_t xTXDescriptorSemaphore = NULL; /* * Note: it is adviced to define both @@ -242,11 +258,9 @@ __attribute__ ((section(".first_data"))) __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END; #endif -#if( ipconfigZERO_COPY_TX_DRIVER != 0 ) - /* DMATxDescToClear points to the next TX DMA descriptor - that must be cleared by vClearTXBuffers(). */ - static __IO ETH_DMADescTypeDef *DMATxDescToClear; -#endif +/* DMATxDescToClear points to the next TX DMA descriptor +that must be cleared by vClearTXBuffers(). */ +static __IO ETH_DMADescTypeDef *DMATxDescToClear; /* Holds the handle of the task used as a deferred interrupt processor. The handle is used so direct notifications can be sent to the task for all EMAC/DMA @@ -267,9 +281,9 @@ const PhyProperties_t xPHYProperties = #endif #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 ) - .duplex = PHY_DUPLEX_FULL, + .ucDuplex = PHY_DUPLEX_FULL, #else - .duplex = PHY_DUPLEX_HALF, + .ucDuplex = PHY_DUPLEX_HALF, #endif #endif @@ -288,6 +302,8 @@ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth ) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; + ( void ) heth; + /* Ethernet RX-Complete callback function, elsewhere declared as weak. */ ulISREvents |= EMAC_IF_RX_EVENT; /* Wakeup the prvEMACHandlerTask. */ @@ -299,43 +315,44 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE; } /*-----------------------------------------------------------*/ - void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth ) - { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - - /* This call-back is only useful in case packets are being sent - zero-copy. Once they're sent, the buffers will be released - by the function vClearTXBuffers(). */ - ulISREvents |= EMAC_IF_TX_EVENT; - /* Wakeup the prvEMACHandlerTask. */ - if( xEMACTaskHandle != NULL ) - { - vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - } +void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth ) +{ +BaseType_t xHigherPriorityTaskWoken = pdFALSE; + ( void ) heth; + + /* This call-back is only useful in case packets are being sent + zero-copy. Once they're sent, the buffers will be released + by the function vClearTXBuffers(). */ + ulISREvents |= EMAC_IF_TX_EVENT; + /* Wakeup the prvEMACHandlerTask. */ + if( xEMACTaskHandle != NULL ) + { + vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } +} /*-----------------------------------------------------------*/ - static void vClearTXBuffers() - { - __IO ETH_DMADescTypeDef *txLastDescriptor = xETH.TxDesc; +static void vClearTXBuffers() +{ +__IO ETH_DMADescTypeDef *txLastDescriptor = xETH.TxDesc; size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore ); #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) NetworkBufferDescriptor_t *pxNetworkBuffer; uint8_t *ucPayLoad; #endif - /* This function is called after a TX-completion interrupt. - It will release each Network Buffer used in xNetworkInterfaceOutput(). - 'uxCount' represents the number of descriptors given to DMA for transmission. - After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */ - while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) ) + /* This function is called after a TX-completion interrupt. + It will release each Network Buffer used in xNetworkInterfaceOutput(). + 'uxCount' represents the number of descriptors given to DMA for transmission. + After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */ + while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) ) + { + if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) ) { - if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) ) - { - break; - } + break; + } #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) { ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr; @@ -352,13 +369,13 @@ size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescr } #endif /* ipconfigZERO_COPY_TX_DRIVER */ - DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr ); + DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr ); - uxCount--; - /* Tell the counting semaphore that one more TX descriptor is available. */ - xSemaphoreGive( xTXDescriptorSemaphore ); - } + uxCount--; + /* Tell the counting semaphore that one more TX descriptor is available. */ + xSemaphoreGive( xTXDescriptorSemaphore ); } +} /*-----------------------------------------------------------*/ BaseType_t xNetworkInterfaceInitialise( void ) @@ -366,91 +383,117 @@ BaseType_t xNetworkInterfaceInitialise( void ) HAL_StatusTypeDef hal_eth_init_status; BaseType_t xResult; - if( xEMACTaskHandle == NULL ) + if( xMacInitStatus == eMACInit ) { - if( xTXDescriptorSemaphore == NULL ) - { - xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB ); - configASSERT( xTXDescriptorSemaphore ); - } - - /* Initialise ETH */ + xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB ); + if( xTXDescriptorSemaphore == NULL ) + { + xMacInitStatus = eMACFailed; + } + else + { + /* Initialise ETH */ - xETH.Instance = ETH; - xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; - xETH.Init.Speed = ETH_SPEED_100M; - xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX; - /* Value of PhyAddress doesn't matter, will be probed for. */ - xETH.Init.PhyAddress = 0; + xETH.Instance = ETH; + xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; + xETH.Init.Speed = ETH_SPEED_100M; + xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX; + /* Value of PhyAddress doesn't matter, will be probed for. */ + xETH.Init.PhyAddress = 0; - xETH.Init.MACAddr = ( uint8_t *)FreeRTOS_GetMACAddress(); - xETH.Init.RxMode = ETH_RXINTERRUPT_MODE; + xETH.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress(); + xETH.Init.RxMode = ETH_RXINTERRUPT_MODE; - /* using the ETH_CHECKSUM_BY_HARDWARE option: - both the IP and the protocol checksums will be calculated - by the peripheral. */ - xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; + #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) + { + /* using the ETH_CHECKSUM_BY_HARDWARE option: + both the IP and the protocol checksums will be calculated + by the peripheral. */ + xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; + } + #else + { + xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE; + } + #endif - #if( ipconfigUSE_RMII != 0 ) - { - xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; - } - #else - { - xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; - } - #endif /* ipconfigUSE_RMII */ + #if( ipconfigUSE_RMII != 0 ) + { + xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; + } + #else + { + xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; + } + #endif /* ipconfigUSE_RMII */ - hal_eth_init_status = HAL_ETH_Init( &xETH ); + hal_eth_init_status = HAL_ETH_Init( &xETH ); - /* Only for inspection by debugger. */ - ( void ) hal_eth_init_status; + /* Only for inspection by debugger. */ + ( void ) hal_eth_init_status; - /* Set the TxDesc and RxDesc pointers. */ - xETH.TxDesc = DMATxDscrTab; - xETH.RxDesc = DMARxDscrTab; + /* Set the TxDesc and RxDesc pointers. */ + xETH.TxDesc = DMATxDscrTab; + xETH.RxDesc = DMARxDscrTab; - /* Make sure that all unused fields are cleared. */ - memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) ); - memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) ); + /* Make sure that all unused fields are cleared. */ + memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) ); + memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) ); /* Initialize Tx Descriptors list: Chain Mode */ DMATxDescToClear = DMATxDscrTab; - /* Initialise TX-descriptors. */ - prvDMATxDescListInit(); + /* Initialise TX-descriptors. */ + prvDMATxDescListInit(); - /* Initialise RX-descriptors. */ - prvDMARxDescListInit(); + /* Initialise RX-descriptors. */ + prvDMARxDescListInit(); - #if( ipconfigUSE_LLMNR != 0 ) - { - /* Program the LLMNR address at index 1. */ - prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress ); - } - #endif + #if( ipconfigUSE_LLMNR != 0 ) + { + /* Program the LLMNR address at index 1. */ + prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress ); + } + #endif - /* Force a negotiation with the Switch or Router and wait for LS. */ - prvEthernetUpdateConfig( pdTRUE ); + /* Force a negotiation with the Switch or Router and wait for LS. */ + prvEthernetUpdateConfig( pdTRUE ); - /* The deferred interrupt handler task is created at the highest - possible priority to ensure the interrupt handler can return directly - to it. The task's handle is stored in xEMACTaskHandle so interrupts can - notify the task when there is something to process. */ - xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ); + /* The deferred interrupt handler task is created at the highest + possible priority to ensure the interrupt handler can return directly + to it. The task's handle is stored in xEMACTaskHandle so interrupts can + notify the task when there is something to process. */ + if( xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ) == pdPASS ) + { + /* The xTXDescriptorSemaphore and the task are created successfully. */ + xMacInitStatus = eMACPass; + } + else + { + xMacInitStatus = eMACFailed; + } + } } /* if( xEMACTaskHandle == NULL ) */ - if( xPhyObject.ulLinkStatusMask != 0 ) + if( xMacInitStatus != eMACPass ) { - xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS; - xResult = pdPASS; - FreeRTOS_printf( ( "Link Status is high\n" ) ) ; + /* EMAC initialisation failed, return pdFAIL. */ + xResult = pdFAIL; } else { - /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running - and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */ - xResult = pdFAIL; + if( xPhyObject.ulLinkStatusMask != 0uL ) + { + xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS; + xResult = pdPASS; + FreeRTOS_printf( ( "Link Status is high\n" ) ) ; + } + else + { + /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running + and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */ + xResult = pdFAIL; + } } /* When returning non-zero, the stack will become active and start DHCP (in configured) */ @@ -484,6 +527,10 @@ BaseType_t xIndex; /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */ pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL; } + else + { + pxDMADescriptor->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL ); + } /* Initialize the next descriptor with the Next Descriptor Polling Enable */ if( xIndex < ETH_TXBUFNB - 1 ) @@ -567,6 +614,8 @@ static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8 { uint32_t ulTempReg; + ( void ) heth; + /* Calculate the selected MAC address high register. */ ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ]; @@ -592,21 +641,23 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u ); /* Open a do {} while ( 0 ) loop to be able to call break. */ do { + if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 ) + { + /* The packet has been sent back to the IP-task. + The IP-task will further handle it. + Do not release the descriptor. */ + bReleaseAfterSend = pdFALSE; + break; + } #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) { ProtocolPacket_t *pxPacket; - #if( ipconfigZERO_COPY_RX_DRIVER != 0 ) - { - configASSERT( bReleaseAfterSend != 0 ); - } - #endif /* ipconfigZERO_COPY_RX_DRIVER */ - /* If the peripheral must calculate the checksum, it wants the protocol checksum to have a value of zero. */ pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer ); - if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) + if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) { pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u; } @@ -644,6 +695,8 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u ); } #else { + configASSERT( bReleaseAfterSend != 0 ); + /* Move the buffer. */ pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer; /* The Network Buffer has been passed to DMA, no need to release it. */ @@ -653,7 +706,17 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u ); /* Ask to set the IPv4 checksum. Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */ - pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC; + #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) + { + pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC; + } + #else + { + pxDmaTxDesc->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CIC ); + pxDmaTxDesc->Status |= ETH_DMATXDESC_IC; + } + #endif + /* Prepare transmit descriptors to give to DMA. */ @@ -751,20 +814,24 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer; if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP ) { - uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort; + uint16_t usSourcePort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort ); + uint16_t usDestinationPort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ); - if( ( xPortHasUDPSocket( port ) == pdFALSE ) + if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE ) #if ipconfigUSE_LLMNR == 1 - && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) ) + && ( usDestinationPort != ipLLMNR_PORT ) + && ( usSourcePort != ipLLMNR_PORT ) #endif #if ipconfigUSE_NBNS == 1 - && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) ) + && ( usDestinationPort != ipNBNS_PORT ) + && ( usSourcePort != ipNBNS_PORT ) #endif #if ipconfigUSE_DNS == 1 - && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) ) + && ( usSourcePort != ipDNS_PORT ) #endif ) { /* Drop this packet, not for this device. */ + /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */ return pdFALSE; } } @@ -774,20 +841,59 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer; } /*-----------------------------------------------------------*/ +static void prvPassEthMessages( NetworkBufferDescriptor_t *pxDescriptor ) +{ +IPStackEvent_t xRxEvent; + + xRxEvent.eEventType = eNetworkRxEvent; + xRxEvent.pvData = ( void * ) pxDescriptor; + + if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS ) + { + /* The buffer could not be sent to the stack so must be released again. + This is a deferred handler taskr, not a real interrupt, so it is ok to + use the task level function here. */ + #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + { + do + { + NetworkBufferDescriptor_t *pxNext = pxDescriptor->pxNextBuffer; + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + pxDescriptor = pxNext; + } while( pxDescriptor != NULL ); + } + #else + { + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + } + #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ + iptraceETHERNET_RX_EVENT_LOST(); + FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) ); + } + else + { + iptraceNETWORK_INTERFACE_RECEIVE(); + } +} + static BaseType_t prvNetworkInterfaceInput( void ) { NetworkBufferDescriptor_t *pxCurDescriptor; NetworkBufferDescriptor_t *pxNewDescriptor = NULL; -BaseType_t xReceivedLength, xAccepted; +#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + NetworkBufferDescriptor_t *pxFirstDescriptor = NULL; + NetworkBufferDescriptor_t *pxLastDescriptor = NULL; +#endif +BaseType_t xReceivedLength = 0; __IO ETH_DMADescTypeDef *pxDMARxDescriptor; -xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; -const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 ); +const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( niDESCRIPTOR_WAIT_TIME_MS ); uint8_t *pucBuffer; pxDMARxDescriptor = xETH.RxDesc; - if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 ) + while( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0u ) { + BaseType_t xAccepted = pdTRUE; /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4; @@ -797,19 +903,9 @@ uint8_t *pucBuffer; /* Chained Mode */ /* Selects the next DMA Rx descriptor list for next buffer to read */ xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr; - } - else - { - xReceivedLength = 0; - } - /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */ - - /* get received frame */ - if( xReceivedLength > 0ul ) - { - /* In order to make the code easier and faster, only packets in a single buffer - will be accepted. This can be done by making the buffers large enough to + /* In order to make the code easier and faster, only packets in a single buffer + will be accepted. This can be done by making the buffers large enough to hold a complete Ethernet packet (1536 bytes). Therefore, two sanity checks: */ configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE ); @@ -859,20 +955,28 @@ uint8_t *pucBuffer; if( xAccepted != pdFALSE ) { pxCurDescriptor->xDataLength = xReceivedLength; - xRxEvent.pvData = ( void * ) pxCurDescriptor; - - /* Pass the data to the TCP/IP task for processing. */ - if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE ) + #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) { - /* Could not send the descriptor into the TCP/IP stack, it - must be released. */ - vReleaseNetworkBufferAndDescriptor( pxCurDescriptor ); - iptraceETHERNET_RX_EVENT_LOST(); + pxCurDescriptor->pxNextBuffer = NULL; + + if( pxFirstDescriptor == NULL ) + { + // Becomes the first message + pxFirstDescriptor = pxCurDescriptor; + } + else if( pxLastDescriptor != NULL ) + { + // Add to the tail + pxLastDescriptor->pxNextBuffer = pxCurDescriptor; + } + + pxLastDescriptor = pxCurDescriptor; } - else + #else { - iptraceNETWORK_INTERFACE_RECEIVE(); + prvPassEthMessages( pxCurDescriptor ); } + #endif } /* Release descriptors to DMA */ @@ -907,15 +1011,25 @@ uint8_t *pucBuffer; /* Resume DMA reception. */ xETH.Instance->DMARPDR = 0; } + pxDMARxDescriptor = xETH.RxDesc; } + #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + { + if( pxFirstDescriptor != NULL ) + { + prvPassEthMessages( pxFirstDescriptor ); + } + } + #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ + return ( xReceivedLength > 0 ); } /*-----------------------------------------------------------*/ BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue ) - { +{ uint16_t usPrevAddress = xETH.Init.PhyAddress; BaseType_t xResult; HAL_StatusTypeDef xHALResult; @@ -933,11 +1047,11 @@ HAL_StatusTypeDef xHALResult; xResult = -1; } return xResult; - } +} /*-----------------------------------------------------------*/ BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) - { +{ uint16_t usPrevAddress = xETH.Init.PhyAddress; BaseType_t xResult; HAL_StatusTypeDef xHALResult; @@ -947,15 +1061,15 @@ HAL_StatusTypeDef xHALResult; xETH.Init.PhyAddress = usPrevAddress; if( xHALResult == HAL_OK ) - { + { xResult = 0; - } - else - { + } + else + { xResult = -1; - } - return xResult; } + return xResult; +} /*-----------------------------------------------------------*/ void vMACBProbePhy( void ) @@ -979,27 +1093,27 @@ static void prvEthernetUpdateConfig( BaseType_t xForce ) { xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - /* Configure the MAC with the Duplex Mode fixed by the - auto-negotiation process. */ + /* Configure the MAC with the Duplex Mode fixed by the + auto-negotiation process. */ if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) - { - xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX; - } - else - { - xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX; - } + { + xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX; + } + else + { + xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX; + } - /* Configure the MAC with the speed fixed by the - auto-negotiation process. */ + /* Configure the MAC with the speed fixed by the + auto-negotiation process. */ if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) - { - xETH.Init.Speed = ETH_SPEED_10M; - } - else - { - xETH.Init.Speed = ETH_SPEED_100M; - } + { + xETH.Init.Speed = ETH_SPEED_10M; + } + else + { + xETH.Init.Speed = ETH_SPEED_100M; + } } else /* AutoNegotiation Disable */ { @@ -1064,11 +1178,9 @@ BaseType_t xReturn; /* Uncomment this in case BufferAllocation_1.c is used. */ -#define niBUFFER_1_PACKET_SIZE 1536 - void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { -static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) ); +static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) ); uint8_t *ucRAMBuffer = ucNetworkPackets; uint32_t ul; @@ -1076,7 +1188,7 @@ uint32_t ul; { pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING; *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) ); - ucRAMBuffer += niBUFFER_1_PACKET_SIZE; + ucRAMBuffer += ETH_MAX_PACKET_SIZE; } } /*-----------------------------------------------------------*/ @@ -1144,21 +1256,15 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL ); ulISREvents &= ~EMAC_IF_RX_EVENT; xResult = prvNetworkInterfaceInput(); - if( xResult > 0 ) - { - while( prvNetworkInterfaceInput() > 0 ) - { - } - } } if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) { /* Code to release TX buffers if zero-copy is used. */ ulISREvents &= ~EMAC_IF_TX_EVENT; - /* Check if DMA packets have been delivered. */ - vClearTXBuffers(); - } + /* Check if DMA packets have been delivered. */ + vClearTXBuffers(); + } if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) { @@ -1166,10 +1272,10 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL ); ulISREvents &= ~EMAC_IF_ERR_EVENT; } if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 ) - { + { /* Something has changed to a Link Status, need re-check. */ - prvEthernetUpdateConfig( pdFALSE ); - } + prvEthernetUpdateConfig( pdFALSE ); + } } } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/readme.txt b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/readme.txt index 73fd553a0..51170c041 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/readme.txt +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/readme.txt @@ -18,3 +18,43 @@ It is assumed that one of these words are defined: STM32F439xx The driver has been tested on both Eval and Discovery boards with both STM32F4 and STM32F7. + +Recommened settings for STM32Fxx Network Interface: + +// Defined in FreeRTOSIPConfig.h + +#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 +#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 1 +#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1 +#define ipconfigZERO_COPY_RX_DRIVER 1 +#define ipconfigZERO_COPY_TX_DRIVER 1 +#define ipconfigUSE_LINKED_RX_MESSAGES 1 + +// Defined in stm32f4xx_hal_conf.h +#define ETH_RXBUFNB 3 or 4 +#define ETH_TXBUFNB 2 or 3 +#define ETH_RX_BUF_SIZE ( ipconfigNETWORK_MTU + 36 ) +#define ETH_TX_BUF_SIZE ( ipconfigNETWORK_MTU + 36 ) + +The best size for 'ETH_RXBUFNB' and 'ETH_TXBUFNB' depends on the speed of the CPU. These macro's define the number of DMA buffers for reception and for transmission. +In general, if the CPU is very fast, you will need less buffers. You can obtain an estimate empirically. + +The optimal value of 'ETH_RX_BUF_SIZE' and 'ETH_TX_BUF_SIZE' depends on the actual value of 'ipconfigNETWORK_MTU'. +When MTU is 1500, MTU+36 becomes a well-aligned buffer of 1536 bytes ( 0x600 ). +When MTU is 1200, MTU+48 will make 1248 ( 0x4E0 ), which is also well aligned. + +Having well aligned buffers is important for CPU with memory cache. Often the caching system divides memory in blocks of 32 bytes. When two buffers share the same cache buffer, you are bound to see data errors. + +Without memory caching, let the size be at least a multiple of 8 ( for DMA ), and make it at least "ipconfigNETWORK_MTU + 14". + +The driver contains these files: + + stm32fxx_hal_eth.c + stm32f2xx_hal_eth.h + stm32f4xx_hal_eth.h + stm32f7xx_hal_eth.h + stm32fxx_hal_eth.h + +These files are copied from ST's HAL library. These work both for STM32F4 and STM32F7. +Please remove or rename these files from the HAL distribution that you are using. + diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.c index c67ad1901..dad16aaf8 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.c @@ -99,19 +99,15 @@ */ /* Includes ------------------------------------------------------------------*/ -#define __STM32_HAL_LEGACY 1 #if defined(STM32F7xx) #include "stm32f7xx_hal.h" - #include "stm32f7xx_hal_def.h" #define stm_is_F7 1 #elif defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) #include "stm32f4xx_hal.h" - #include "stm32f4xx_hal_def.h" #define stm_is_F4 1 #elif defined(STM32F2xx) #include "stm32f2xx_hal.h" - #include "stm32f2xx_hal_def.h" #define stm_is_F2 1 #else #error For what part should this be compiled? @@ -197,8 +193,8 @@ extern void vMACBProbePhy ( void ); */ HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth) { - uint32_t tmpreg = 0; - uint32_t hclk = 60000000; + uint32_t tmpreg = 0uL; + uint32_t hclk = 60000000uL; uint32_t err = ETH_SUCCESS; /* Check the ETH peripheral state */ @@ -244,33 +240,33 @@ HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth) /* Clear CSR Clock Range CR[2:0] bits */ tmpreg &= ETH_MACMIIAR_CR_MASK; - /* Get hclk frequency value (168,000,000) */ + /* Get hclk frequency value (e.g. 168,000,000) */ hclk = HAL_RCC_GetHCLKFreq(); /* Set CR bits depending on hclk value */ - if( ( hclk >= 20000000 ) && ( hclk < 35000000 ) ) + if(( hclk >= 20000000uL ) && ( hclk < 35000000uL ) ) { /* CSR Clock Range between 20-35 MHz */ - tmpreg |= (uint32_t) ETH_MACMIIAR_CR_Div16; + tmpreg |= ( uint32_t) ETH_MACMIIAR_CR_Div16; } - else if( ( hclk >= 35000000 ) && ( hclk < 60000000 ) ) + else if( ( hclk >= 35000000uL ) && ( hclk < 60000000uL ) ) { /* CSR Clock Range between 35-60 MHz */ tmpreg |= ( uint32_t ) ETH_MACMIIAR_CR_Div26; } - else if((hclk >= 60000000 ) && ( hclk < 100000000 ) ) + else if( ( hclk >= 60000000uL ) && ( hclk < 100000000uL ) ) { /* CSR Clock Range between 60-100 MHz */ tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div42; } - else if((hclk >= 100000000 ) && ( hclk < 150000000)) + else if( ( hclk >= 100000000uL ) && ( hclk < 150000000uL ) ) { /* CSR Clock Range between 100-150 MHz */ tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div62; } - else /* ((hclk >= 150000000 ) && ( hclk <= 168000000)) */ + else /* ( ( hclk >= 150000000uL ) && ( hclk <= 183000000uL ) ) */ { - /* CSR Clock Range between 150-168 MHz */ + /* CSR Clock Range between 150-183 MHz */ tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div102; } @@ -314,161 +310,6 @@ HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth) return HAL_OK; } -/** - * @brief Initializes the DMA Tx descriptors in chain mode. - * @param heth: pointer to a ETH_HandleTypeDef structure that contains - * the configuration information for ETHERNET module - * @param DMATxDescTab: Pointer to the first Tx desc list - * @param TxBuff: Pointer to the first TxBuffer list - * @param TxBuffCount: Number of the used Tx desc in the list - * @retval HAL status - */ -HAL_StatusTypeDef HAL_ETH_DMATxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *pxDMATable, uint8_t *ucDataBuffer, uint32_t ulBufferCount) -{ - uint32_t i = 0; - ETH_DMADescTypeDef *pxDMADescriptor; - - /* Process Locked */ - __HAL_LOCK( heth ); - - /* Set the ETH peripheral state to BUSY */ - heth->State = HAL_ETH_STATE_BUSY; - - /* Set the TxDesc pointer with the first one of the pxDMATable list */ - heth->TxDesc = pxDMATable; - - /* Fill each DMA descriptor with the right values */ - for( i=0; i < ulBufferCount; i++ ) - { - /* Get the pointer on the ith member of the descriptor list */ - pxDMADescriptor = pxDMATable + i; - - /* Set Second Address Chained bit */ - pxDMADescriptor->Status = ETH_DMATXDESC_TCH; - - pxDMADescriptor->ControlBufferSize = 0; - - /* Set Buffer1 address pointer */ - if( ucDataBuffer != NULL ) - { - pxDMADescriptor->Buffer1Addr = ( uint32_t )( &ucDataBuffer[ i * ETH_TX_BUF_SIZE ] ); - } - else - { - /* Buffer space is not provided because it uses zero-copy transmissions. */ - pxDMADescriptor->Buffer1Addr = ( uint32_t )0u; - } - - if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) - { - /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */ - pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL; - } - - /* Initialize the next descriptor with the Next Descriptor Polling Enable */ - if(i < ( ulBufferCount - 1 ) ) - { - /* Set next descriptor address register with next descriptor base address */ - pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMATable + i + 1 ); - } - else - { - /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ - pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) pxDMATable; - } - } - - /* Set Transmit Descriptor List Address Register */ - heth->Instance->DMATDLAR = ( uint32_t ) pxDMATable; - - /* Set ETH HAL State to Ready */ - heth->State= HAL_ETH_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK( heth ); - - /* Return function status */ - return HAL_OK; -} - -/** - * @brief Initializes the DMA Rx descriptors in chain mode. - * @param heth: pointer to a ETH_HandleTypeDef structure that contains - * the configuration information for ETHERNET module - * @param DMARxDescTab: Pointer to the first Rx desc list - * @param RxBuff: Pointer to the first RxBuffer list - * @param RxBuffCount: Number of the used Rx desc in the list - * @retval HAL status - */ -HAL_StatusTypeDef HAL_ETH_DMARxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *pxDMATable, uint8_t *ucDataBuffer, uint32_t ulBufferCount) -{ - uint32_t i = 0; - ETH_DMADescTypeDef *pxDMADescriptor; - - /* Process Locked */ - __HAL_LOCK( heth ); - - /* Set the ETH peripheral state to BUSY */ - heth->State = HAL_ETH_STATE_BUSY; - - /* Set the RxDesc pointer with the first one of the pxDMATable list */ - heth->RxDesc = pxDMATable; - - /* Fill each DMA descriptor with the right values */ - for(i=0; i < ulBufferCount; i++) - { - /* Get the pointer on the ith member of the descriptor list */ - pxDMADescriptor = pxDMATable+i; - - /* Set Own bit of the Rx descriptor Status */ - pxDMADescriptor->Status = ETH_DMARXDESC_OWN; - - /* Set Buffer1 size and Second Address Chained bit */ - pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | ETH_RX_BUF_SIZE; - - /* Set Buffer1 address pointer */ - if( ucDataBuffer != NULL ) - { - pxDMADescriptor->Buffer1Addr = ( uint32_t )( &ucDataBuffer[ i * ETH_RX_BUF_SIZE ] ); - } - else - { - /* Buffer space is not provided because it uses zero-copy reception. */ - pxDMADescriptor->Buffer1Addr = ( uint32_t )0u; - } - - if( heth->Init.RxMode == ETH_RXINTERRUPT_MODE ) - { - /* Enable Ethernet DMA Rx Descriptor interrupt */ - pxDMADescriptor->ControlBufferSize &= ~ETH_DMARXDESC_DIC; - } - - /* Initialize the next descriptor with the Next Descriptor Polling Enable */ - if(i < (ulBufferCount-1)) - { - /* Set next descriptor address register with next descriptor base address */ - pxDMADescriptor->Buffer2NextDescAddr = (uint32_t)(pxDMATable+i+1); - } - else - { - /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ - pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) pxDMATable; - } - } - - /* Set Receive Descriptor List Address Register */ - heth->Instance->DMARDLAR = ( uint32_t ) pxDMATable; - - /* Set ETH HAL State to Ready */ - heth->State= HAL_ETH_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK( heth ); - - /* Return function status */ - return HAL_OK; -} - /** * @brief Initializes the ETH MSP. * @param heth: pointer to a ETH_HandleTypeDef structure that contains @@ -480,6 +321,7 @@ __weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) /* NOTE : This function Should not be modified, when the callback is needed, the HAL_ETH_MspInit could be implemented in the user file */ + ( void ) heth; } /** @@ -493,6 +335,7 @@ __weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) /* NOTE : This function Should not be modified, when the callback is needed, the HAL_ETH_MspDeInit could be implemented in the user file */ + ( void ) heth; } /** @@ -522,209 +365,6 @@ __weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) * @{ */ -/** - * @brief Sends an Ethernet frame. - * @param heth: pointer to a ETH_HandleTypeDef structure that contains - * the configuration information for ETHERNET module - * @param FrameLength: Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_ETH_TransmitFrame(ETH_HandleTypeDef *heth, uint32_t FrameLength) -{ - uint32_t bufcount = 0, size = 0, i = 0; - __IO ETH_DMADescTypeDef *pxDmaTxDesc = heth->TxDesc; - /* Process Locked */ - __HAL_LOCK( heth ); - - /* Set the ETH peripheral state to BUSY */ - heth->State = HAL_ETH_STATE_BUSY; - - if( FrameLength == 0 ) - { - /* Set ETH HAL state to READY */ - heth->State = HAL_ETH_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK( heth ); - - return HAL_ERROR; - } - - /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ - if( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) != ( uint32_t ) RESET ) - { - /* OWN bit set */ - heth->State = HAL_ETH_STATE_BUSY_TX; - - /* Process Unlocked */ - __HAL_UNLOCK( heth ); - - return HAL_ERROR; - } - - /* Get the number of needed Tx buffers for the current frame, rounding up. */ - bufcount = ( FrameLength + ETH_TX_BUF_SIZE - 1 ) / ETH_TX_BUF_SIZE; - - if (bufcount == 1) - { - /* Set LAST and FIRST segment */ - pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS; - /* Set frame size */ - pxDmaTxDesc->ControlBufferSize = ( FrameLength & ETH_DMATXDESC_TBS1 ); - /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ - pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN; - /* Point to next descriptor */ - heth->TxDesc = ( ETH_DMADescTypeDef * ) ( heth->TxDesc->Buffer2NextDescAddr ); - } - else - { - for( i = 0; i < bufcount; i++ ) - { - /* Clear FIRST and LAST segment bits */ - uint32_t ulStatus = heth->TxDesc->Status & ~( ETH_DMATXDESC_FS | ETH_DMATXDESC_LS ); - - if( i == 0 ) - { - /* Setting the first segment bit */ - heth->TxDesc->Status = ulStatus | ETH_DMATXDESC_FS; - } - - /* Program size */ - if (i < (bufcount-1)) - { - heth->TxDesc->ControlBufferSize = (ETH_TX_BUF_SIZE & ETH_DMATXDESC_TBS1); - } - else - { - /* Setting the last segment bit */ - heth->TxDesc->Status = ulStatus | ETH_DMATXDESC_LS; - size = FrameLength - (bufcount-1)*ETH_TX_BUF_SIZE; - heth->TxDesc->ControlBufferSize = (size & ETH_DMATXDESC_TBS1); - } - - /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ - heth->TxDesc->Status |= ETH_DMATXDESC_OWN; - /* point to next descriptor */ - heth->TxDesc = (ETH_DMADescTypeDef *)( heth->TxDesc->Buffer2NextDescAddr ); - } - } - - __DSB(); - - /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ - if( ( heth->Instance->DMASR & ETH_DMASR_TBUS ) != ( uint32_t )RESET ) - { - heth->Instance->DMACHTDR = ( uint32_t )pxDmaTxDesc; - - /* Clear TBUS ETHERNET DMA flag */ - heth->Instance->DMASR = ETH_DMASR_TBUS; - /* Resume DMA transmission*/ - heth->Instance->DMATPDR = 0; - } - - /* Set ETH HAL State to Ready */ - heth->State = HAL_ETH_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK( heth ); - - /* Return function status */ - return HAL_OK; -} - -/** - * @brief Checks for received frames. - * @param heth: pointer to a ETH_HandleTypeDef structure that contains - * the configuration information for ETHERNET module - * @retval HAL status - */ -HAL_StatusTypeDef HAL_ETH_GetReceivedFrame_IT( ETH_HandleTypeDef *heth ) -{ - return HAL_ETH_GetReceivedFrame( heth ); -} - -HAL_StatusTypeDef HAL_ETH_GetReceivedFrame( ETH_HandleTypeDef *heth ) -{ -uint32_t ulCounter = 0; -ETH_DMADescTypeDef *pxDescriptor = heth->RxDesc; -HAL_StatusTypeDef xResult = HAL_ERROR; - - /* Process Locked */ - __HAL_LOCK( heth ); - - /* Check the ETH state to BUSY */ - heth->State = HAL_ETH_STATE_BUSY; - - /* Scan descriptors owned by CPU */ - while( ( ( pxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0ul ) && ( ulCounter < ETH_RXBUFNB ) ) - { - uint32_t ulStatus = pxDescriptor->Status; - - /* Just for security. */ - ulCounter++; - - if( ( ulStatus & ( ETH_DMARXDESC_FS | ETH_DMARXDESC_LS ) ) == ( uint32_t )ETH_DMARXDESC_FS ) - { - /* First segment in frame, but not the last. */ - heth->RxFrameInfos.FSRxDesc = pxDescriptor; - heth->RxFrameInfos.LSRxDesc = ( ETH_DMADescTypeDef *)NULL; - heth->RxFrameInfos.SegCount = 1; - /* Point to next descriptor. */ - pxDescriptor = (ETH_DMADescTypeDef*) (pxDescriptor->Buffer2NextDescAddr); - heth->RxDesc = pxDescriptor; - } - else if( ( ulStatus & ( ETH_DMARXDESC_LS | ETH_DMARXDESC_FS ) ) == 0ul ) - { - /* This is an intermediate segment, not first, not last. */ - /* Increment segment count. */ - heth->RxFrameInfos.SegCount++; - /* Move to the next descriptor. */ - pxDescriptor = ( ETH_DMADescTypeDef * ) ( pxDescriptor->Buffer2NextDescAddr ); - heth->RxDesc = pxDescriptor; - } - /* Must be a last segment */ - else - { - /* This is the last segment. */ - /* Check if last segment is first segment: one segment contains the frame */ - if( heth->RxFrameInfos.SegCount == 0 ) - { - /* Remember the first segment. */ - heth->RxFrameInfos.FSRxDesc = pxDescriptor; - } - - /* Increment segment count */ - heth->RxFrameInfos.SegCount++; - - /* Remember the last segment. */ - heth->RxFrameInfos.LSRxDesc = pxDescriptor; - - /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ - heth->RxFrameInfos.length = - ( ( ulStatus & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4; - - /* Get the address of the buffer start address */ - heth->RxFrameInfos.buffer = heth->RxFrameInfos.FSRxDesc->Buffer1Addr; - - /* Point to next descriptor */ - heth->RxDesc = ( ETH_DMADescTypeDef * ) pxDescriptor->Buffer2NextDescAddr; - - /* Return OK status: a packet was received. */ - xResult = HAL_OK; - break; - } - } - - /* Set ETH HAL State to Ready */ - heth->State = HAL_ETH_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK( heth ); - - /* Return function status */ - return xResult; -} - #define ETH_DMA_ALL_INTS \ ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | ETH_DMA_IT_AIS | ETH_DMA_IT_ER | \ ETH_DMA_IT_FBE | ETH_DMA_IT_ET | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \ @@ -772,6 +412,7 @@ __weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth) /* NOTE : This function Should not be modified, when the callback is needed, the HAL_ETH_TxCpltCallback could be implemented in the user file */ + ( void ) heth; } /** @@ -785,6 +426,7 @@ __weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) /* NOTE : This function Should not be modified, when the callback is needed, the HAL_ETH_TxCpltCallback could be implemented in the user file */ + ( void ) heth; } /** @@ -798,6 +440,7 @@ __weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) /* NOTE : This function Should not be modified, when the callback is needed, the HAL_ETH_TxCpltCallback could be implemented in the user file */ + ( void ) heth; } /** @@ -814,8 +457,8 @@ __weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) */ HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint32_t *RegValue) { -uint32_t tmpreg = 0; -uint32_t tickstart = 0; +uint32_t tmpreg = 0uL; +uint32_t tickstart = 0uL; HAL_StatusTypeDef xResult; /* Check parameters */ @@ -856,7 +499,7 @@ HAL_StatusTypeDef xResult; { tmpreg = heth->Instance->MACMIIAR; - if( ( tmpreg & ETH_MACMIIAR_MB ) == 0ul ) + if( ( tmpreg & ETH_MACMIIAR_MB ) == 0uL ) { /* Get MACMIIDR value */ *RegValue = ( uint32_t ) heth->Instance->MACMIIDR; @@ -1067,6 +710,28 @@ HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth) return HAL_OK; } +static void vRegisterDelay() +{ +uint32_t uxCount; + /* + * Regarding the HAL delay functions, I noticed that HAL delay is being used to workaround the + * "Successive write operations to the same register might not be fully taken into account" errata. + * The workaround requires a delay of four TX_CLK/RX_CLK clock cycles. For a 10 Mbit connection, + * these clocks are running at 2.5 MHz, so this delay would be at most 1.6 microseconds. + * 180 Mhz = 288 loops + * 168 Mhz = 269 loops + * 100 Mhz = 160 loops + * 84 Mhz = 134 loops + */ + #define WAIT_TIME_NS 1600uL /* 1.6 microseconds */ + #define CPU_MAX_FREQ SystemCoreClock /* 84, 100, 168 or 180 MHz */ + uint32_t NOP_COUNT = ( WAIT_TIME_NS * ( CPU_MAX_FREQ / 1000uL ) ) / 1000000uL; + for( uxCount = NOP_COUNT; uxCount > 0uL; uxCount-- ) + { + __NOP(); + } +} + static void prvWriteMACFCR( ETH_HandleTypeDef *heth, uint32_t ulValue) { /* Enable the MAC transmission */ @@ -1077,7 +742,7 @@ static void prvWriteMACFCR( ETH_HandleTypeDef *heth, uint32_t ulValue) Read it back, wait a ms and */ ( void ) heth->Instance->MACFCR; - HAL_Delay( ETH_REG_WRITE_DELAY ); + vRegisterDelay(); heth->Instance->MACFCR = ulValue; } @@ -1092,7 +757,7 @@ static void prvWriteDMAOMR( ETH_HandleTypeDef *heth, uint32_t ulValue) Read it back, wait a ms and */ ( void ) heth->Instance->DMAOMR; - HAL_Delay( ETH_REG_WRITE_DELAY ); + vRegisterDelay(); heth->Instance->DMAOMR = ulValue; } @@ -1107,7 +772,7 @@ static void prvWriteMACCR( ETH_HandleTypeDef *heth, uint32_t ulValue) Read it back, wait a ms and */ ( void ) heth->Instance->MACCR; - HAL_Delay( ETH_REG_WRITE_DELAY ); + vRegisterDelay(); heth->Instance->MACCR = ulValue; } @@ -1121,7 +786,7 @@ static void prvWriteMACCR( ETH_HandleTypeDef *heth, uint32_t ulValue) */ HAL_StatusTypeDef HAL_ETH_ConfigMAC(ETH_HandleTypeDef *heth, ETH_MACInitTypeDef *macconf) { - uint32_t tmpreg = 0; + uint32_t tmpreg = 0uL; /* Process Locked */ __HAL_LOCK( heth ); @@ -1202,7 +867,7 @@ HAL_StatusTypeDef HAL_ETH_ConfigMAC(ETH_HandleTypeDef *heth, ETH_MACInitTypeDef /* Wait until the write operation will be taken into account : at least four TX_CLK/RX_CLK clock cycles */ tmpreg = heth->Instance->MACFFR; - HAL_Delay(ETH_REG_WRITE_DELAY); + vRegisterDelay(); heth->Instance->MACFFR = tmpreg; /*--------------- ETHERNET MACHTHR and MACHTLR Configuration ---------------*/ @@ -1236,7 +901,7 @@ HAL_StatusTypeDef HAL_ETH_ConfigMAC(ETH_HandleTypeDef *heth, ETH_MACInitTypeDef /* Wait until the write operation will be taken into account : at least four TX_CLK/RX_CLK clock cycles */ tmpreg = heth->Instance->MACVLANTR; - HAL_Delay(ETH_REG_WRITE_DELAY); + vRegisterDelay(); heth->Instance->MACVLANTR = tmpreg; } else /* macconf == NULL : here we just configure Speed and Duplex mode */ @@ -1246,7 +911,7 @@ HAL_StatusTypeDef HAL_ETH_ConfigMAC(ETH_HandleTypeDef *heth, ETH_MACInitTypeDef tmpreg = heth->Instance->MACCR; /* Clear FES and DM bits */ - tmpreg &= ~((uint32_t)0x00004800); + tmpreg &= ~( ( uint32_t ) 0x00004800uL ); tmpreg |= (uint32_t)(heth->Init.Speed | heth->Init.DuplexMode); @@ -1273,7 +938,7 @@ HAL_StatusTypeDef HAL_ETH_ConfigMAC(ETH_HandleTypeDef *heth, ETH_MACInitTypeDef */ HAL_StatusTypeDef HAL_ETH_ConfigDMA(ETH_HandleTypeDef *heth, ETH_DMAInitTypeDef *dmaconf) { - uint32_t tmpreg = 0; + uint32_t tmpreg = 0uL; /* Process Locked */ __HAL_LOCK( heth ); @@ -1332,7 +997,7 @@ HAL_StatusTypeDef HAL_ETH_ConfigDMA(ETH_HandleTypeDef *heth, ETH_DMAInitTypeDef /* Wait until the write operation will be taken into account: at least four TX_CLK/RX_CLK clock cycles */ tmpreg = heth->Instance->DMABMR; - HAL_Delay(ETH_REG_WRITE_DELAY); + vRegisterDelay(); heth->Instance->DMABMR = tmpreg; /* Set the ETH state to Ready */ @@ -1402,7 +1067,7 @@ static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err) { ETH_MACInitTypeDef macinit; ETH_DMAInitTypeDef dmainit; - uint32_t tmpreg = 0; + uint32_t tmpreg = 0uL; if (err != ETH_SUCCESS) /* Auto-negotiation failed */ { @@ -1440,16 +1105,16 @@ static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err) macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT; macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT; - macinit.HashTableHigh = 0x0; - macinit.HashTableLow = 0x0; - macinit.PauseTime = 0x0; + macinit.HashTableHigh = 0x0uL; + macinit.HashTableLow = 0x0uL; + macinit.PauseTime = 0x0uL; macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE; macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4; macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE; macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT; - macinit.VLANTagIdentifier = 0x0; + macinit.VLANTagIdentifier = 0x0uL; /*------------------------ ETHERNET MACCR Configuration --------------------*/ /* Get the ETHERNET MACCR value */ @@ -1508,7 +1173,7 @@ static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err) /* Wait until the write operation will be taken into account: at least four TX_CLK/RX_CLK clock cycles */ tmpreg = heth->Instance->MACFFR; - HAL_Delay(ETH_REG_WRITE_DELAY); + vRegisterDelay(); heth->Instance->MACFFR = tmpreg; /*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*/ @@ -1549,7 +1214,7 @@ static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err) /* Wait until the write operation will be taken into account: at least four TX_CLK/RX_CLK clock cycles */ tmpreg = heth->Instance->MACVLANTR; - HAL_Delay(ETH_REG_WRITE_DELAY); + vRegisterDelay(); heth->Instance->MACVLANTR = tmpreg; /* Ethernet DMA default initialization ************************************/ @@ -1567,7 +1232,7 @@ static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err) dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; dmainit.EnhancedDescriptorFormat = ETH_DMAENHANCEDDESCRIPTOR_ENABLE; - dmainit.DescriptorSkipLength = 0x0; + dmainit.DescriptorSkipLength = 0x0uL; dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1; /* Get the ETHERNET DMAOMR value */ @@ -1617,7 +1282,7 @@ static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err) /* Wait until the write operation will be taken into account: at least four TX_CLK/RX_CLK clock cycles */ tmpreg = heth->Instance->DMABMR; - HAL_Delay(ETH_REG_WRITE_DELAY); + vRegisterDelay(); heth->Instance->DMABMR = tmpreg; if(heth->Init.RxMode == ETH_RXINTERRUPT_MODE) @@ -1647,11 +1312,14 @@ static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint { uint32_t tmpreg; + ( void ) heth; + /* Check the parameters */ assert_param( IS_ETH_MAC_ADDRESS0123( MacAddr ) ); /* Calculate the selected MAC address high register */ - tmpreg = 0x80000000ul | ( ( uint32_t )Addr[ 5 ] << 8) | (uint32_t)Addr[ 4 ]; + /* Register ETH_MACA0HR: Bit 31 MO: Always 1. */ + tmpreg = 0x80000000uL | ( ( uint32_t )Addr[ 5 ] << 8) | (uint32_t)Addr[ 4 ]; /* Load the selected MAC address high register */ ( * ( __IO uint32_t * ) ( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + MacAddr ) ) ) = tmpreg; /* Calculate the selected MAC address low register */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.h index f4b74d226..f91122594 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.h @@ -44,6 +44,14 @@ #define __STM32F4xx_HAL_ETH_H #define __STM32F7xx_HAL_ETH_H +#if defined(STM32F7xx) + #include "stm32f7xx_hal_def.h" +#elif defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) + #include "stm32f4xx_hal_def.h" +#elif defined(STM32F2xx) + #include "stm32f2xx_hal_def.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -367,6 +375,33 @@ * @} */ +#ifdef _lint + #ifdef __IO + #undef __IO + #endif + #define __IO + + #ifdef ETH_TypeDef + #undef ETH_TypeDef + #endif + #define ETH_TypeDef void + + #ifdef HAL_LockTypeDef + #undef HAL_LockTypeDef + #endif + #define HAL_LockTypeDef unsigned + + #ifdef ETH_RX_BUF_SIZE + #undef ETH_RX_BUF_SIZE + #endif + #define ETH_RX_BUF_SIZE 1536 + + #ifdef ETH_TX_BUF_SIZE + #undef ETH_TX_BUF_SIZE + #endif + #define ETH_TX_BUF_SIZE 1536 +#endif + /* Exported types ------------------------------------------------------------*/ /** @defgroup ETH_Exported_Types ETH Exported Types * @{ @@ -1244,33 +1279,37 @@ typedef struct /** @defgroup ETH_MAC_Debug_flags ETH MAC Debug flags * @{ */ -#define ETH_MAC_TXFIFO_FULL ((uint32_t)0x02000000) /* Tx FIFO full */ -#define ETH_MAC_TXFIFONOT_EMPTY ((uint32_t)0x01000000) /* Tx FIFO not empty */ -#define ETH_MAC_TXFIFO_WRITE_ACTIVE ((uint32_t)0x00400000) /* Tx FIFO write active */ -#define ETH_MAC_TXFIFO_IDLE ((uint32_t)0x00000000) /* Tx FIFO read status: Idle */ -#define ETH_MAC_TXFIFO_READ ((uint32_t)0x00100000) /* Tx FIFO read status: Read (transferring data to the MAC transmitter) */ -#define ETH_MAC_TXFIFO_WAITING ((uint32_t)0x00200000) /* Tx FIFO read status: Waiting for TxStatus from MAC transmitter */ -#define ETH_MAC_TXFIFO_WRITING ((uint32_t)0x00300000) /* Tx FIFO read status: Writing the received TxStatus or flushing the TxFIFO */ -#define ETH_MAC_TRANSMISSION_PAUSE ((uint32_t)0x00080000) /* MAC transmitter in pause */ -#define ETH_MAC_TRANSMITFRAMECONTROLLER_IDLE ((uint32_t)0x00000000) /* MAC transmit frame controller: Idle */ -#define ETH_MAC_TRANSMITFRAMECONTROLLER_WAITING ((uint32_t)0x00020000) /* MAC transmit frame controller: Waiting for Status of previous frame or IFG/backoff period to be over */ -#define ETH_MAC_TRANSMITFRAMECONTROLLER_GENRATING_PCF ((uint32_t)0x00040000) /* MAC transmit frame controller: Generating and transmitting a Pause control frame (in full duplex mode) */ -#define ETH_MAC_TRANSMITFRAMECONTROLLER_TRANSFERRING ((uint32_t)0x00060000) /* MAC transmit frame controller: Transferring input frame for transmission */ -#define ETH_MAC_MII_TRANSMIT_ACTIVE ((uint32_t)0x00010000) /* MAC MII transmit engine active */ -#define ETH_MAC_RXFIFO_EMPTY ((uint32_t)0x00000000) /* Rx FIFO fill level: empty */ -#define ETH_MAC_RXFIFO_BELOW_THRESHOLD ((uint32_t)0x00000100) /* Rx FIFO fill level: fill-level below flow-control de-activate threshold */ -#define ETH_MAC_RXFIFO_ABOVE_THRESHOLD ((uint32_t)0x00000200) /* Rx FIFO fill level: fill-level above flow-control activate threshold */ -#define ETH_MAC_RXFIFO_FULL ((uint32_t)0x00000300) /* Rx FIFO fill level: full */ -#define ETH_MAC_READCONTROLLER_IDLE ((uint32_t)0x00000060) /* Rx FIFO read controller IDLE state */ -#define ETH_MAC_READCONTROLLER_READING_DATA ((uint32_t)0x00000060) /* Rx FIFO read controller Reading frame data */ -#define ETH_MAC_READCONTROLLER_READING_STATUS ((uint32_t)0x00000060) /* Rx FIFO read controller Reading frame status (or time-stamp) */ -#define ETH_MAC_READCONTROLLER_ FLUSHING ((uint32_t)0x00000060) /* Rx FIFO read controller Flushing the frame data and status */ -#define ETH_MAC_RXFIFO_WRITE_ACTIVE ((uint32_t)0x00000010) /* Rx FIFO write controller active */ -#define ETH_MAC_SMALL_FIFO_NOTACTIVE ((uint32_t)0x00000000) /* MAC small FIFO read / write controllers not active */ -#define ETH_MAC_SMALL_FIFO_READ_ACTIVE ((uint32_t)0x00000002) /* MAC small FIFO read controller active */ -#define ETH_MAC_SMALL_FIFO_WRITE_ACTIVE ((uint32_t)0x00000004) /* MAC small FIFO write controller active */ -#define ETH_MAC_SMALL_FIFO_RW_ACTIVE ((uint32_t)0x00000006) /* MAC small FIFO read / write controllers active */ -#define ETH_MAC_MII_RECEIVE_PROTOCOL_ACTIVE ((uint32_t)0x00000001) /* MAC MII receive protocol engine active */ +#ifndef ETH_MAC_TXFIFO_FULL + #define ETH_MAC_TXFIFO_FULL ((uint32_t)0x02000000) /* Tx FIFO full */ + #define ETH_MAC_TXFIFONOT_EMPTY ((uint32_t)0x01000000) /* Tx FIFO not empty */ + #define ETH_MAC_TXFIFO_WRITE_ACTIVE ((uint32_t)0x00400000) /* Tx FIFO write active */ + #define ETH_MAC_TXFIFO_IDLE ((uint32_t)0x00000000) /* Tx FIFO read status: Idle */ + #define ETH_MAC_TXFIFO_READ ((uint32_t)0x00100000) /* Tx FIFO read status: Read (transferring data to the MAC transmitter) */ + #define ETH_MAC_TXFIFO_WAITING ((uint32_t)0x00200000) /* Tx FIFO read status: Waiting for TxStatus from MAC transmitter */ + #define ETH_MAC_TXFIFO_WRITING ((uint32_t)0x00300000) /* Tx FIFO read status: Writing the received TxStatus or flushing the TxFIFO */ + #define ETH_MAC_TRANSMISSION_PAUSE ((uint32_t)0x00080000) /* MAC transmitter in pause */ + #define ETH_MAC_TRANSMITFRAMECONTROLLER_IDLE ((uint32_t)0x00000000) /* MAC transmit frame controller: Idle */ + #define ETH_MAC_TRANSMITFRAMECONTROLLER_WAITING ((uint32_t)0x00020000) /* MAC transmit frame controller: Waiting for Status of previous frame or IFG/backoff period to be over */ + #define ETH_MAC_TRANSMITFRAMECONTROLLER_GENRATING_PCF ((uint32_t)0x00040000) /* MAC transmit frame controller: Generating and transmitting a Pause control frame (in full duplex mode) */ + #define ETH_MAC_TRANSMITFRAMECONTROLLER_TRANSFERRING ((uint32_t)0x00060000) /* MAC transmit frame controller: Transferring input frame for transmission */ + #define ETH_MAC_MII_TRANSMIT_ACTIVE ((uint32_t)0x00010000) /* MAC MII transmit engine active */ + #define ETH_MAC_RXFIFO_EMPTY ((uint32_t)0x00000000) /* Rx FIFO fill level: empty */ + #define ETH_MAC_RXFIFO_BELOW_THRESHOLD ((uint32_t)0x00000100) /* Rx FIFO fill level: fill-level below flow-control de-activate threshold */ + #define ETH_MAC_RXFIFO_ABOVE_THRESHOLD ((uint32_t)0x00000200) /* Rx FIFO fill level: fill-level above flow-control activate threshold */ + #define ETH_MAC_RXFIFO_FULL ((uint32_t)0x00000300) /* Rx FIFO fill level: full */ + #define ETH_MAC_READCONTROLLER_IDLE ((uint32_t)0x00000060) /* Rx FIFO read controller IDLE state */ + #define ETH_MAC_READCONTROLLER_READING_DATA ((uint32_t)0x00000060) /* Rx FIFO read controller Reading frame data */ + #define ETH_MAC_READCONTROLLER_READING_STATUS ((uint32_t)0x00000060) /* Rx FIFO read controller Reading frame status (or time-stamp) */ + #define ETH_MAC_READCONTROLLER_ FLUSHING ((uint32_t)0x00000060) /* Rx FIFO read controller Flushing the frame data and status */ + #define ETH_MAC_RXFIFO_WRITE_ACTIVE ((uint32_t)0x00000010) /* Rx FIFO write controller active */ + #define ETH_MAC_SMALL_FIFO_NOTACTIVE ((uint32_t)0x00000000) /* MAC small FIFO read / write controllers not active */ + #define ETH_MAC_SMALL_FIFO_READ_ACTIVE ((uint32_t)0x00000002) /* MAC small FIFO read controller active */ + #define ETH_MAC_SMALL_FIFO_WRITE_ACTIVE ((uint32_t)0x00000004) /* MAC small FIFO write controller active */ + #define ETH_MAC_SMALL_FIFO_RW_ACTIVE ((uint32_t)0x00000006) /* MAC small FIFO read / write controllers active */ + #define ETH_MAC_MII_RECEIVE_PROTOCOL_ACTIVE ((uint32_t)0x00000001) /* MAC MII receive protocol engine active */ +#else + /* stm32_hal_legacy.h has probably been included. That file defines 'ETH_MAC_TXFIFO_FULL' and all macro's here below. */ +#endif /** * @} */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/FaultInjection.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/FaultInjection.c index e100a4e97..502fbd661 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/FaultInjection.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/FaultInjection.c @@ -77,7 +77,8 @@ return pxNetworkBufferIn; if( ulCallCount > ulNextFaultCallCount ) { - ulNextFaultCallCount = ipconfigRAND32() % xMAX_FAULT_INJECTION_RATE; + xApplicationGetRandomNumber( &( ulNextFaultCallCount ) ); + ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE; if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE ) { ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE; @@ -85,7 +86,8 @@ return pxNetworkBufferIn; ulCallCount = 0; - ulFault = ipconfigRAND32() % xNUM_FAULT_TYPES; + xApplicationGetRandomNumber( &( ulFault ) ); + ulFault = ulFault % xNUM_FAULT_TYPES; if( ulFaultLogIndex < xFAULT_LOG_SIZE ) { diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c index b13b11571..1c11976cb 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c @@ -1,27 +1,27 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 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://aws.amazon.com/freertos - * http://www.FreeRTOS.org - */ +FreeRTOS+TCP V2.0.11 +Copyright (C) 2017 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://aws.amazon.com/freertos + http://www.FreeRTOS.org +*/ /* Standard includes. */ #include @@ -50,12 +50,10 @@ /* Provided memory configured as uncached. */ #include "uncached_memory.h" -#ifndef niEMAC_HANDLER_TASK_PRIORITY - #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1 +#ifndef BMSR_LINK_STATUS + #define BMSR_LINK_STATUS 0x0004UL #endif -#define niBMSR_LINK_STATUS 0x0004UL - #ifndef PHY_LS_HIGH_CHECK_TIME_MS /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not receiving packets. */ @@ -190,7 +188,7 @@ const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pd possible priority to ensure the interrupt handler can return directly to it. The task's handle is stored in xEMACTaskHandle so interrupts can notify the task when there is something to process. */ - xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ); + xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle ); } else { @@ -208,27 +206,7 @@ const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pd BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend ) { - #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) - { - ProtocolPacket_t *pxPacket; - - /* If the peripheral must calculate the checksum, it wants - the protocol checksum to have a value of zero. */ - pxPacket = ( ProtocolPacket_t * ) ( pxBuffer->pucEthernetBuffer ); - if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) - { - IPHeader_t *pxIPHeader = &( pxPacket->xUDPPacket.xIPHeader ); - - pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u; - pxIPHeader->usHeaderChecksum = 0u; - pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER ); - pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum ); - - usGenerateProtocolChecksum( (uint8_t*)&( pxPacket->xUDPPacket ), pxBuffer->xDataLength, pdTRUE ); - } - } - #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */ - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0 ) + if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) { iptraceNETWORK_INTERFACE_TRANSMIT(); emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend ); @@ -271,7 +249,7 @@ BaseType_t xReturn; } ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR ); - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0 ) + if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) { xReturn = pdTRUE; break; @@ -303,7 +281,7 @@ BaseType_t xGetPhyLinkStatus( void ) { BaseType_t xReturn; - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) == 0 ) + if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 ) { xReturn = pdFALSE; } @@ -320,12 +298,11 @@ static void prvEMACHandlerTask( void *pvParameters ) { TimeOut_t xPhyTime; TickType_t xPhyRemTime; +UBaseType_t uxLastMinBufferCount = 0; UBaseType_t uxCurrentCount; BaseType_t xResult = 0; uint32_t xStatus; const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL ); -UBaseType_t uxLastMinBufferCount = 0; -UBaseType_t uxCurrentBufferCount = 0; /* Remove compiler warnings about unused parameters. */ ( void ) pvParameters; @@ -339,14 +316,14 @@ UBaseType_t uxCurrentBufferCount = 0; for( ;; ) { - uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers(); - if( uxLastMinBufferCount != uxCurrentBufferCount ) + uxCurrentCount = uxGetMinimumFreeNetworkBuffers(); + if( uxLastMinBufferCount != uxCurrentCount ) { /* The logging produced below may be helpful while tuning +TCP: see how many buffers are in use. */ - uxLastMinBufferCount = uxCurrentBufferCount; + uxLastMinBufferCount = uxCurrentCount; FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", - uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) ); + uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) ); } #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) @@ -395,22 +372,19 @@ UBaseType_t uxCurrentBufferCount = 0; vTaskSetTimeOutState( &xPhyTime ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); xResult = 0; - /* Indicate that the Link Status is high, so that - xNetworkInterfaceOutput() can send packets. */ - ulPHYLinkStatus |= niBMSR_LINK_STATUS; } else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) { xStatus = ulReadMDIO( PHY_REG_01_BMSR ); - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != ( xStatus & niBMSR_LINK_STATUS ) ) + if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) ) { ulPHYLinkStatus = xStatus; - FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0 ) ); + FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) ); } vTaskSetTimeOutState( &xPhyTime ); - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0 ) + if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) { xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); } diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h index a38ec81d7..823dee0d3 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h @@ -35,6 +35,7 @@ extern "C" { #include "xil_exception.h" #include "xpseudo_asm.h" #include "xil_cache.h" +#include "xil_printf.h" #include "xuartps.h" #include "xscugic.h" #include "xemacps.h" /* defines XEmacPs API */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c index d71331c0e..fc09d2183 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c @@ -1,27 +1,36 @@ /* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 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://aws.amazon.com/freertos - * http://www.FreeRTOS.org - */ +FreeRTOS+TCP V2.0.11 +Copyright (C) 2017 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://aws.amazon.com/freertos + http://www.FreeRTOS.org +*/ + +#include "Zynq/x_emacpsif.h" +#include "Zynq/x_topology.h" +#include "xstatus.h" + +#include "xparameters.h" +#include "xparameters_ps.h" +#include "xil_exception.h" +#include "xil_mmu.h" #include "FreeRTOS.h" #include "task.h" @@ -34,15 +43,6 @@ #include "FreeRTOS_IP_Private.h" #include "NetworkBufferManagement.h" -#include "Zynq/x_emacpsif.h" -#include "Zynq/x_topology.h" -#include "xstatus.h" - -#include "xparameters.h" -#include "xparameters_ps.h" -#include "xil_exception.h" -#include "xil_mmu.h" - #include "uncached_memory.h" /* Two defines used to set or clear the EMAC interrupt */ @@ -56,6 +56,8 @@ #endif #define TX_OFFSET ipconfigPACKET_FILLER_SIZE +#define RX_BUFFER_ALIGNMENT 14 + /* Defined in NetworkInterface.c */ extern TaskHandle_t xEMACTaskHandle; @@ -119,6 +121,7 @@ size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount break; } #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) +#warning ipconfigZERO_COPY_TX_DRIVER is defined { void *pvBuffer = pxDMA_tx_buffers[ tail ]; NetworkBufferDescriptor_t *pxBuffer; @@ -289,8 +292,6 @@ TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u ); /* Start transmit */ xemacpsif->txBusy = pdTRUE; XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) ); - /* Reading it back is important compiler is optimised. */ - XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET ); } dsb(); @@ -313,35 +314,33 @@ void emacps_recv_handler(void *arg) portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } -static void prvPassEthMessages( NetworkBufferDescriptor_t *pxDescriptor ) +static NetworkBufferDescriptor_t *ethMsg = NULL; +static NetworkBufferDescriptor_t *ethLast = NULL; + +static void passEthMessages( void ) { IPStackEvent_t xRxEvent; xRxEvent.eEventType = eNetworkRxEvent; - xRxEvent.pvData = ( void * ) pxDescriptor; + xRxEvent.pvData = ( void * ) ethMsg; if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS ) { /* The buffer could not be sent to the stack so must be released again. This is a deferred handler taskr, not a real interrupt, so it is ok to use the task level function here. */ - #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - { - do - { - NetworkBufferDescriptor_t *pxNext = pxDescriptor->pxNextBuffer; - vReleaseNetworkBufferAndDescriptor( pxDescriptor ); - pxDescriptor = pxNext; - } while( pxDescriptor != NULL ); - } - #else + do { - vReleaseNetworkBufferAndDescriptor( pxDescriptor ); - } - #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ + NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer; + vReleaseNetworkBufferAndDescriptor( ethMsg ); + ethMsg = xNext; + } while( ethMsg != NULL ); + iptraceETHERNET_RX_EVENT_LOST(); - FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) ); + FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) ); } + + ethMsg = ethLast = NULL; } int emacps_check_rx( xemacpsif_s *xemacpsif ) @@ -350,10 +349,6 @@ NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer; int rx_bytes; volatile int msgCount = 0; int head = xemacpsif->rxHead; -#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - NetworkBufferDescriptor_t *pxFirstDescriptor = NULL; - NetworkBufferDescriptor_t *pxLastDescriptor = NULL; -#endif /* ipconfigUSE_LINKED_RX_MESSAGES */ /* There seems to be an issue (SI# 692601), see comments below. */ resetrx_on_no_rxdata(xemacpsif); @@ -369,7 +364,7 @@ int head = xemacpsif->rxHead; break; } - pxNewBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 ); + pxNewBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 ); if( pxNewBuffer == NULL ) { /* A packet has been received, but there is no replacement for this Network Buffer. @@ -390,6 +385,7 @@ int head = xemacpsif->rxHead; rx_bytes = xemacpsif->rxSegments[ head ].flags & XEMACPS_RXBUF_LEN_MASK; pxBuffer->xDataLength = rx_bytes; + if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 ) { Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)rx_bytes ); @@ -398,35 +394,26 @@ int head = xemacpsif->rxHead; /* store it in the receive queue, where it'll be processed by a different handler. */ iptraceNETWORK_INTERFACE_RECEIVE(); - #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - { - pxBuffer->pxNextBuffer = NULL; + pxBuffer->pxNextBuffer = NULL; - if( pxFirstDescriptor == NULL ) - { - // Becomes the first message - pxFirstDescriptor = pxBuffer; - } - else if( pxLastDescriptor != NULL ) - { - // Add to the tail - pxLastDescriptor->pxNextBuffer = pxBuffer; - } - - pxLastDescriptor = pxBuffer; + if( ethMsg == NULL ) + { + // Becomes the first message + ethMsg = pxBuffer; } - #else + else if( ethLast != NULL ) { - prvPassEthMessages( pxBuffer ); + // Add to the tail + ethLast->pxNextBuffer = pxBuffer; } - #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ + ethLast = pxBuffer; msgCount++; } { if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 ) { - Xil_DCacheInvalidateRange( ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE ); + Xil_DCacheInvalidateRange( ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT); } { uint32_t addr = ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK; @@ -435,12 +422,8 @@ int head = xemacpsif->rxHead; addr |= XEMACPS_RXBUF_WRAP_MASK; } /* Clearing 'XEMACPS_RXBUF_NEW_MASK' 0x00000001 *< Used bit.. */ - xemacpsif->rxSegments[ head ].flags = 0; xemacpsif->rxSegments[ head ].address = addr; - if (xemacpsif->rxSegments[ head ].address) - { - // Just to read it - } + xemacpsif->rxSegments[ head ].flags = 0; } } @@ -451,14 +434,10 @@ int head = xemacpsif->rxHead; xemacpsif->rxHead = head; } - #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + if( ethMsg != NULL ) { - if( pxFirstDescriptor != NULL ) - { - prvPassEthMessages( pxFirstDescriptor ); - } + passEthMessages( ); } - #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ return msgCount; } @@ -477,9 +456,9 @@ unsigned char *ucTxBuffer; xemacpsif->txSegments[ index ].address = ( uint32_t )ucTxBuffer; xemacpsif->txSegments[ index ].flags = XEMACPS_TXBUF_USED_MASK; #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) - pxDMA_tx_buffers[ index ] = ( unsigned char * )NULL; + pxDMA_tx_buffers[ index ] = ( void* )NULL; #else - pxDMA_tx_buffers[ index ] = ( unsigned char * )( ucTxBuffer + TX_OFFSET ); + pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET ); #endif ucTxBuffer += xemacpsif->uTxUnitSize; } @@ -528,7 +507,7 @@ XStatus init_dma(xemacpsif_s *xemacpsif) pxBuffer = pxDMA_rx_buffers[ iIndex ]; if( pxBuffer == NULL ) { - pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 ); + pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 ); if( pxBuffer == NULL ) { FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) ); @@ -544,7 +523,7 @@ XStatus init_dma(xemacpsif_s *xemacpsif) if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 ) { Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, - (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE ); + (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT); } } diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c index 3d835d9a2..e9443cda8 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c @@ -22,19 +22,19 @@ #include #include +#include "Zynq/x_emacpsif.h" + /* FreeRTOS includes. */ #include "FreeRTOS.h" #include "task.h" #include "queue.h" +///* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */ #include "FreeRTOS_IP.h" #include "FreeRTOS_Sockets.h" #include "FreeRTOS_IP_Private.h" #include "NetworkBufferManagement.h" -#include "NetworkInterface.h" - -#include "Zynq/x_emacpsif.h" extern TaskHandle_t xEMACTaskHandle; @@ -42,6 +42,8 @@ extern TaskHandle_t xEMACTaskHandle; *** to run it on a PEEP board ***/ +unsigned int link_speed = 100; + void setup_isr( xemacpsif_s *xemacpsif ) { /* @@ -139,6 +141,8 @@ int xResult; return xResult; } +BaseType_t xNetworkInterfaceInitialise( void ); + static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord) { xemacpsif_s *xemacpsif; @@ -214,6 +218,8 @@ static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord) } } +extern XEmacPs_Config mac_config; + void HandleTxErrors(xemacpsif_s *xemacpsif) { u32 netctrlreg; diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c index d1999a73e..12b8c60c8 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c @@ -53,23 +53,24 @@ #include #include +#include "Zynq/x_emacpsif.h" +//#include "lwipopts.h" +#include "xparameters_ps.h" +#include "xparameters.h" + /* FreeRTOS includes. */ #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "semphr.h" +///* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */ #include "FreeRTOS_IP.h" #include "FreeRTOS_Sockets.h" #include "FreeRTOS_IP_Private.h" #include "NetworkBufferManagement.h" -#include "Zynq/x_emacpsif.h" -#include "xparameters_ps.h" -#include "xparameters.h" - - int phy_detected = 0; /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c @@ -98,8 +99,6 @@ int phy_detected = 0; #define IEEE_CONTROL_REG_OFFSET 0 #define IEEE_STATUS_REG_OFFSET 1 -#define IEEE_PHYSID1_OFFSET 2 -#define IEEE_PHYSID2_OFFSET 3 #define IEEE_AUTONEGO_ADVERTISE_REG 4 #define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5 #define IEEE_1000_ADVERTISE_REG_OFFSET 9 @@ -136,6 +135,9 @@ int phy_detected = 0; #define IEEE_PAUSE_MASK 0x0400 #define IEEE_AUTONEG_ERROR_MASK 0x8000 +#define PHY_DETECT_REG 1 +#define PHY_DETECT_MASK 0x1808 + #define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140 #define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100 #define XEMACPS_GMII2RGMII_SPEED10_FD 0x100 @@ -161,17 +163,19 @@ int phy_detected = 0; static int detect_phy(XEmacPs *xemacpsp) { - u16 id_lower, id_upper; - u32 phy_addr, id; - - for (phy_addr = 0; phy_addr < 32; phy_addr++) { - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PHYSID1_OFFSET, &id_lower); - - if ((id_lower != ( u16 )0xFFFFu) && (id_lower != ( u16 )0x0u)) { - - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PHYSID2_OFFSET, &id_upper); - id = ( ( ( uint32_t ) id_upper ) << 16 ) | ( id_lower & 0xFFF0 ); - FreeRTOS_printf( ("XEmacPs detect_phy: %04lX at address %d.\n", id, phy_addr ) ); + u16 phy_reg; + u32 phy_addr; + + for (phy_addr = 31; phy_addr > 0; phy_addr--) { + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG, + &phy_reg); + + if ((phy_reg != 0xFFFF) && + ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { + /* Found a valid PHY address */ + FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n", + phy_addr)); + FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) ); phy_detected = phy_addr; return phy_addr; } @@ -234,8 +238,8 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS) return 10; - FreeRTOS_printf( ( "%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\n", - __FUNCTION__ ) ); + xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n", + __FUNCTION__); return 10; } else { @@ -253,8 +257,8 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) case (IEEE_CTRL_LINKSPEED_10M): return 10; default: - FreeRTOS_printf( ( "%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\n", - __FUNCTION__, phylinkspeed ) ); + xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n", + __FUNCTION__, phylinkspeed); return 10; } @@ -278,7 +282,7 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) #else u32 phy_addr = detect_phy(xemacpsp); #endif - FreeRTOS_printf( ( "Start PHY autonegotiation \n" ) ); + xil_printf("Start PHY autonegotiation \r\n"); #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 #else @@ -334,24 +338,24 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) break; } #endif - FreeRTOS_printf( ( "Waiting for PHY to complete autonegotiation.\n" ) ); + xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { - vTaskDelay(1); + sleep(1); #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 #else XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp); if (temp & IEEE_AUTONEG_ERROR_MASK) { - FreeRTOS_printf( ( "Auto negotiation error \n" ) ); + xil_printf("Auto negotiation error \r\n"); } #endif XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); } - FreeRTOS_printf( ( "autonegotiation complete \n" ) ); + xil_printf("autonegotiation complete \r\n"); #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 #else @@ -359,7 +363,7 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) #endif #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 - FreeRTOS_printf( ( "Waiting for Link to be up; Polling for SGMII core Reg \n" ) ); + xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n"); XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp); while(!(temp & 0x8000)) { XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp); @@ -376,7 +380,7 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp); return 10; } else { - FreeRTOS_printf( ( "get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\n" ) ); + xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n"); XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp); XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100); return 10; @@ -556,26 +560,26 @@ unsigned Phy_Setup (XEmacPs *xemacpsp) link_speed = 1000; configure_IEEE_phy_speed(xemacpsp, link_speed); convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD; - vTaskDelay(1); + sleep(1); #elif defined(ipconfigNIC_LINKSPEED100) SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100); link_speed = 100; configure_IEEE_phy_speed(xemacpsp, link_speed); convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD; - vTaskDelay(1); + sleep(1); #elif defined(ipconfigNIC_LINKSPEED10) SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10); link_speed = 10; configure_IEEE_phy_speed(xemacpsp, link_speed); convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD; - vTaskDelay(1); + sleep(1); #endif if (conv_present) { XEmacPs_PhyWrite(xemacpsp, convphyaddr, XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting); } - FreeRTOS_printf( ( "link speed: %d\n", link_speed ) ); + xil_printf("link speed: %d\r\n", link_speed); return link_speed; } diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c new file mode 100644 index 000000000..aa0a646b4 --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c @@ -0,0 +1,63 @@ +/* +FreeRTOS+TCP V2.0.11 +Copyright (C) 2018 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://aws.amazon.com/freertos + http://www.FreeRTOS.org +*/ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "list.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" + +/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet +driver will filter incoming packets and only pass the stack those packets it +considers need processing. */ +#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) +#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer +#else +#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) +#endif + +BaseType_t xNetworkInterfaceInitialise( void ) +{ + /* FIX ME. */ + return pdFALSE; +} + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend ) +{ + /* FIX ME. */ + return pdFALSE; +} + +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ + /* FIX ME. */ +} + +BaseType_t xGetPhyLinkStatus( void ) +{ + /* FIX ME. */ + return pdFALSE; +} \ No newline at end of file diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/ReadMe.txt b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/ReadMe.txt new file mode 100644 index 000000000..441cdbd2a --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/ReadMe.txt @@ -0,0 +1 @@ +Update NetworkInterface.c and include other files needed by FreeRTOS+TCP here. \ No newline at end of file diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/esp32/NetworkInterface.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/esp32/NetworkInterface.c new file mode 100644 index 000000000..0b34edf7b --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/esp32/NetworkInterface.c @@ -0,0 +1,193 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* Standard includes. */ +#include +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" +#include "FreeRTOS_IP_Private.h" +#include "FreeRTOS_DNS.h" +#include "NetworkBufferManagement.h" +#include "NetworkInterface.h" + +#include "esp_log.h" +#include "esp_wifi.h" +#include "esp_wifi_internal.h" +#include "tcpip_adapter.h" + +enum if_state_t { + INTERFACE_DOWN = 0, + INTERFACE_UP, +}; + +static const char *TAG = "NetInterface"; +volatile static uint32_t xInterfaceState = INTERFACE_DOWN; + +#if ( ipconfigHAS_PRINTF != 0 ) + static void prvMonitorResources(); +#endif + +BaseType_t xNetworkInterfaceInitialise( void ) +{ + static BaseType_t xMACAdrInitialized = pdFALSE; + uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ]; + + if (xInterfaceState == INTERFACE_UP) { + if (xMACAdrInitialized == pdFALSE) { + esp_wifi_get_mac(ESP_IF_WIFI_STA, ucMACAddress); + FreeRTOS_UpdateMACAddress(ucMACAddress); + xMACAdrInitialized = pdTRUE; + } + return pdTRUE; + } + return pdFALSE; +} + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend ) +{ + if (pxNetworkBuffer == NULL || pxNetworkBuffer->pucEthernetBuffer == NULL || pxNetworkBuffer->xDataLength == 0) { + ESP_LOGE(TAG, "Invalid params"); + return pdFALSE; + } + + esp_err_t ret; + if (xInterfaceState == INTERFACE_DOWN) { + ESP_LOGD(TAG, "Interface down"); + ret = ESP_FAIL; + } else { + ret = esp_wifi_internal_tx(ESP_IF_WIFI_STA, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to tx buffer %p, len %d, err %d", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret); + } + } + +#if ( ipconfigHAS_PRINTF != 0 ) + prvMonitorResources(); +#endif + if (xReleaseAfterSend == pdTRUE) { + vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer); + } + + return ret == ESP_OK ? pdTRUE : pdFALSE; +} + +void vNetworkNotifyIFDown() +{ + IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL }; + if (xInterfaceState != INTERFACE_DOWN) { + xInterfaceState = INTERFACE_DOWN; + xSendEventStructToIPTask( &xRxEvent, 0 ); + } +} + +void vNetworkNotifyIFUp() +{ + xInterfaceState = INTERFACE_UP; +} + +esp_err_t wlanif_input(void *netif, void *buffer, uint16_t len, void *eb) +{ + NetworkBufferDescriptor_t *pxNetworkBuffer; + IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; + const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 ); + +#if ( ipconfigHAS_PRINTF != 0 ) + prvMonitorResources(); +#endif + + if( eConsiderFrameForProcessing( buffer ) != eProcessBuffer ) { + ESP_LOGD(TAG, "Dropping packet"); + esp_wifi_internal_free_rx_buffer(eb); + return ESP_OK; + } + + pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(len, xDescriptorWaitTime); + if (pxNetworkBuffer != NULL) { + + /* Set the packet size, in case a larger buffer was returned. */ + pxNetworkBuffer->xDataLength = len; + + /* Copy the packet data. */ + memcpy(pxNetworkBuffer->pucEthernetBuffer, buffer, len); + xRxEvent.pvData = (void *) pxNetworkBuffer; + + if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) { + ESP_LOGE(TAG, "Failed to enqueue packet to network stack %p, len %d", buffer, len); + vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer); + return ESP_FAIL; + } + esp_wifi_internal_free_rx_buffer(eb); + return ESP_OK; + } else { + ESP_LOGE(TAG, "Failed to get buffer descriptor"); + return ESP_FAIL; + } +} + +#if ( ipconfigHAS_PRINTF != 0 ) + static void prvMonitorResources() + { + static UBaseType_t uxLastMinBufferCount = 0u; + static UBaseType_t uxCurrentBufferCount = 0u; + static size_t uxMinLastSize = 0uL; + size_t uxMinSize; + + uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers(); + + if( uxLastMinBufferCount != uxCurrentBufferCount ) + { + /* The logging produced below may be helpful + * while tuning +TCP: see how many buffers are in use. */ + uxLastMinBufferCount = uxCurrentBufferCount; + FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", + uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) ); + } + + uxMinSize = xPortGetMinimumEverFreeHeapSize(); + + if( uxMinLastSize != uxMinSize ) + { + uxMinLastSize = uxMinSize; + FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", xPortGetFreeHeapSize(), uxMinSize ) ); + } + + #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) + { + static UBaseType_t uxLastMinQueueSpace = 0; + UBaseType_t uxCurrentCount = 0u; + + uxCurrentCount = uxGetMinimumIPQueueSpace(); + + if( uxLastMinQueueSpace != uxCurrentCount ) + { + /* The logging produced below may be helpful + * while tuning +TCP: see how many buffers are in use. */ + uxLastMinQueueSpace = uxCurrentCount; + FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) ); + } + } + #endif /* ipconfigCHECK_IP_QUEUE_SPACE */ + } +#endif /* ( ipconfigHAS_PRINTF != 0 ) */ +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/include/phyHandling.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/include/phyHandling.h index d8e7e8de8..9e8a11387 100644 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/include/phyHandling.h +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/include/phyHandling.h @@ -1,28 +1,3 @@ -/* - * FreeRTOS+TCP 191100 experimental - * Copyright (C) 2018 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://aws.amazon.com/freertos - * http://www.FreeRTOS.org - */ - /* * Handling of Ethernet PHY's * PHY's communicate with an EMAC either through @@ -47,11 +22,11 @@ extern "C" { #endif /* A generic user-provided function that reads from the PHY-port at 'xAddress'( 0-based ). A 16-bit value shall be stored in - '*pusValue'. xRegister is the register number ( 0 .. 31 ). In fact all PHY registers are 16-bit. + '*pulValue'. xRegister is the register number ( 0 .. 31 ). In fact all PHY registers are 16-bit. Return non-zero in case the action failed. */ typedef BaseType_t ( *xApplicationPhyReadHook_t )( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue ); -/* A generic user-provided function that writes 'usValue' to the +/* A generic user-provided function that writes 'ulValue' to the PHY-port at 'xAddress' ( 0-based ). xRegister is the register number ( 0 .. 31 ). Return non-zero in case the action failed. */ typedef BaseType_t ( *xApplicationPhyWriteHook_t )( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ); @@ -118,10 +93,10 @@ void vPhyInitialise( EthernetPhy_t *pxPhyObject, xApplicationPhyReadHook_t fnPhy /* Discover all PHY's connected by polling 32 indexes ( zero-based ) */ BaseType_t xPhyDiscover( EthernetPhy_t *pxPhyObject ); -/* Send a reset commando to the connected PHY ports and send configuration. */ +/* Send a reset command to the connected PHY ports and send configuration. */ BaseType_t xPhyConfigure( EthernetPhy_t *pxPhyObject, const PhyProperties_t *pxPhyProperties ); -/* Give a commando to start auto negotiation on a set of PHY port's. */ +/* Give a command to start auto negotiation on a set of PHY port's. */ BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask ); /* Do not use auto negotiation but use predefined values from 'pxPhyObject->xPhyPreferences'. */ @@ -132,10 +107,9 @@ BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask ); last call to this function. */ BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception ); -static __inline uint32_t xPhyGetMask( EthernetPhy_t *pxPhyObject ) -{ - return ( ( ( uint32_t ) 1u ) << pxPhyObject-> xPortCount ) - 1; -} +/* Get the bitmask of a given 'EthernetPhy_t'. */ +#define xPhyGetMask( pxPhyObject ) \ + ( ( ( ( uint32_t ) 1u ) << ( pxPhyObject )->xPortCount ) - 1u ) #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c new file mode 100644 index 000000000..87161fd39 --- /dev/null +++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c @@ -0,0 +1,217 @@ +/* +FreeRTOS+TCP V2.0.11 +Copyright (C) 2018 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://aws.amazon.com/freertos + http://www.FreeRTOS.org +*/ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "list.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" +#include "FreeRTOS_IP_Private.h" +#include "FreeRTOS_DNS.h" +#include "NetworkBufferManagement.h" +#include "NetworkInterface.h" + +#include "wifi-decl.h" +#include "wmerrno.h" +#include "wifi.h" + +#include + +#define net_e(...) \ + wmlog_e("freertos_tcp", ##__VA_ARGS__) +#define net_w(...) \ + wmlog_w("freertos_tcp", ##__VA_ARGS__) +#define net_d(...) \ + wmlog("freertos_tcp", ##__VA_ARGS__) + +#if 0 //this is lwip structure. +#define MAX_INTERFACES_SUPPORTED 3 +static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED]; +#endif + +/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet +driver will filter incoming packets and only pass the stack those packets it +considers need processing. */ +#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) +#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer +#else +#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) +#endif + +#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) +#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) + +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +enum if_state_t { + INTERFACE_DOWN = 0, + INTERFACE_UP, +}; +struct ip_addr { + u32_t addr; +}; + +#define MLAN_BSS_TYPE_STA 0 + +extern uint8_t outbuf[2048]; +extern bool mlan_is_amsdu(const t_u8 *rcvdata); +extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface); +extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen); +extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata, NetworkBufferDescriptor_t *pxNetworkBuffer); +static volatile uint32_t xInterfaceState = INTERFACE_DOWN; + +static int process_data_packet(const t_u8 *databuf, const t_u16 datalen) +{ + int interface = BSS_TYPE_STA; + t_u8 *payload = NULL; + t_u16 payload_len = 0; + const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 ); + + NetworkBufferDescriptor_t *pxNetworkBuffer; + IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; + + payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface); + + if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) { + net_d("Dropping packet\r\n"); + return WM_SUCCESS; + } + + pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime); + + if (pxNetworkBuffer != NULL) { + /* Set the packet size, in case a larger buffer was returned. */ + pxNetworkBuffer->xDataLength = payload_len; + + /* Copy the packet data. */ + memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len); + + xRxEvent.pvData = (void *) pxNetworkBuffer; + if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) { + wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len); + vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer); + return WM_FAIL; + } + } + return WM_SUCCESS; +} + +/* Callback function called from the wifi module */ +void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata, + const t_u16 datalen) +{ + if (interface == BSS_TYPE_STA) + process_data_packet(rcvdata, datalen); +} + +BaseType_t xNetworkInterfaceInitialise( void ) +{ + uint8_t ret; + mac_addr_t mac_addr; + + ret = wifi_get_device_mac_addr(&mac_addr); + if (ret != WM_SUCCESS) { + net_d("Failed to get mac address"); + } + + FreeRTOS_UpdateMACAddress(mac_addr.mac); + + return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE; +} + +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ + /* FIX ME. */ +} + +BaseType_t xGetPhyLinkStatus( void ) +{ + /* FIX ME. */ + return pdFALSE; +} +void vNetworkNotifyIFDown() +{ + IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL }; + xInterfaceState = INTERFACE_DOWN; + if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) { + /* Could not send the message, so it is still pending. */ + net_e("Could not send network down event"); + } + else { + /* Message was sent so it is not pending. */ + net_d("Sent network down event"); + } +} + +void vNetworkNotifyIFUp() +{ + xInterfaceState = INTERFACE_UP; +} + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend ) +{ + uint8_t pkt_len; + + if (pxNetworkBuffer == NULL || + pxNetworkBuffer->pucEthernetBuffer == NULL || + pxNetworkBuffer->xDataLength == 0) { + net_d("Incorrect params"); + return pdFALSE; + } + memset(outbuf, 0x00, sizeof(outbuf)); + pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */ + memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer, + pxNetworkBuffer->xDataLength); + int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength); + if (ret != WM_SUCCESS) { + net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret); + } + + if (xReleaseAfterSend != pdFALSE) { + vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer); + } + + return ret == WM_SUCCESS ? pdTRUE : pdFALSE; +} diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort - Copy with task notification array.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort - Copy with task notification array.h deleted file mode 100644 index 19d678b4d..000000000 --- a/FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort - Copy with task notification array.h +++ /dev/null @@ -1,2565 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.1.5 - * Percepio AB, www.percepio.com - * - * Terms of Use - * This file is part of the trace recorder library (RECORDER), which is the - * intellectual property of Percepio AB (PERCEPIO) and provided under a - * license as follows. - * The RECORDER may be used free of charge for the purpose of recording data - * intended for analysis in PERCEPIO products. It may not be used or modified - * for other purposes without explicit permission from PERCEPIO. - * You may distribute the RECORDER in its original source code form, assuming - * this text (terms of use, disclaimer, copyright notice) is unchanged. You are - * allowed to distribute the RECORDER with minor modifications intended for - * configuration or porting of the RECORDER, e.g., to allow using it on a - * specific processor, processor family or with a specific communication - * interface. Any such modifications should be documented directly below - * this comment block. - * - * Disclaimer - * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty - * as to its use or performance. PERCEPIO does not and cannot warrant the - * performance or results you may obtain by using the RECORDER or documentation. - * PERCEPIO make no warranties, express or implied, as to noninfringement of - * third party rights, merchantability, or fitness for any particular purpose. - * In no event will PERCEPIO, its technology partners, or distributors be liable - * to you for any consequential, incidental or special damages, including any - * lost profits or lost savings, even if a representative of PERCEPIO has been - * advised of the possibility of such damages, or for any claim by any third - * party. Some jurisdictions do not allow the exclusion or limitation of - * incidental, consequential or special damages, or the exclusion of implied - * warranties or limitations on how long an implied warranty may last, so the - * above limitations may not apply to you. - * - * FreeRTOS-specific definitions needed by the trace recorder - * - * - * - * Tabs are used for indent in this file (1 tab = 4 spaces) - * - * Copyright Percepio AB, 2018. - * www.percepio.com - ******************************************************************************/ - -#ifndef TRC_KERNEL_PORT_H -#define TRC_KERNEL_PORT_H - -#include "FreeRTOS.h" /* Defines configUSE_TRACE_FACILITY */ -#include "trcPortDefines.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define TRC_USE_TRACEALYZER_RECORDER configUSE_TRACE_FACILITY - -/*** FreeRTOS version codes **************************************************/ -#define FREERTOS_VERSION_NOT_SET 0 -#define TRC_FREERTOS_VERSION_7_3 1 /* v7.3 is earliest supported.*/ -#define TRC_FREERTOS_VERSION_7_4 2 -#define TRC_FREERTOS_VERSION_7_5_OR_7_6 3 -#define TRC_FREERTOS_VERSION_8_X 4 /* Any v8.x.x*/ -#define TRC_FREERTOS_VERSION_9_0_0 5 -#define TRC_FREERTOS_VERSION_9_0_1 6 -#define TRC_FREERTOS_VERSION_9_0_2 7 -#define TRC_FREERTOS_VERSION_10_0_0 8 /* If using FreeRTOS v10.0.0 or later version */ - -#define TRC_FREERTOS_VERSION_9_X 42 /* Not allowed anymore */ - -#if (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_9_X) -/* This setting for TRC_CFG_FREERTOS_VERSION is no longer allowed as v9.0.1 needs special handling. */ -#error "Please specify your exact FreeRTOS version in trcConfig.h, from the options listed above." -#endif - -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) -#define prvGetStreamBufferType(x) ((( StreamBuffer_t * )x )->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) -#else -#define prvGetStreamBufferType(x) 0 -#endif - -/* Added mainly for our internal testing. This makes it easier to create test applications that - runs on multiple FreeRTOS versions. */ -#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X) - /* FreeRTOS v7.0 and later */ - #define STRING_CAST(x) ( (signed char*) x ) - #define TickType portTickType -#else - /* FreeRTOS v8.0 and later */ - #define STRING_CAST(x) x - #define TickType TickType_t -#endif - -#if (defined(TRC_USE_TRACEALYZER_RECORDER)) && (TRC_USE_TRACEALYZER_RECORDER == 1) - -/******************************************************************************* - * INCLUDE_xTaskGetCurrentTaskHandle must be set to 1 for tracing to work properly - ******************************************************************************/ -#undef INCLUDE_xTaskGetCurrentTaskHandle -#define INCLUDE_xTaskGetCurrentTaskHandle 1 - -#if (TRC_CFG_SCHEDULING_ONLY == 0) -/******************************************************************************* - * vTraceSetQueueName(void* object, const char* name) - * - * Parameter object: pointer to the Queue that shall be named - * Parameter name: the name to set (const string literal) - * - * Sets a name for Queue objects for display in Tracealyzer. - ******************************************************************************/ -void vTraceSetQueueName(void* object, const char* name); - -/******************************************************************************* - * vTraceSetSemaphoreName(void* object, const char* name) - * - * Parameter object: pointer to the Semaphore that shall be named - * Parameter name: the name to set (const string literal) - * - * Sets a name for Semaphore objects for display in Tracealyzer. - ******************************************************************************/ -void vTraceSetSemaphoreName(void* object, const char* name); - -/******************************************************************************* - * vTraceSetMutexName(void* object, const char* name) - * - * Parameter object: pointer to the Mutex that shall be named - * Parameter name: the name to set (const string literal) - * - * Sets a name for Semaphore objects for display in Tracealyzer. - ******************************************************************************/ -void vTraceSetMutexName(void* object, const char* name); - -#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) -/******************************************************************************* -* vTraceSetEventGroupName(void* object, const char* name) -* -* Parameter object: pointer to the EventGroup that shall be named -* Parameter name: the name to set (const string literal) -* -* Sets a name for EventGroup objects for display in Tracealyzer. -******************************************************************************/ -void vTraceSetEventGroupName(void* object, const char* name); -#else /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */ -#define vTraceSetEventGroupName(object, name) /* Do nothing */ -#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */ - -#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) -/******************************************************************************* -* vTraceSetStreamBufferName(void* object, const char* name) -* -* Parameter object: pointer to the StreamBuffer that shall be named -* Parameter name: the name to set (const string literal) -* -* Sets a name for StreamBuffer objects for display in Tracealyzer. -******************************************************************************/ -void vTraceSetStreamBufferName(void* object, const char* name); -#else /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ -#define vTraceSetStreamBufferName(object, name) /* Do nothing */ -#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ - -#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) -/******************************************************************************* - * vTraceSetMessageBufferName(void* object, const char* name) - * - * Parameter object: pointer to the MessageBuffer that shall be named - * Parameter name: the name to set (const string literal) - * - * Sets a name for MessageBuffer objects for display in Tracealyzer. - ******************************************************************************/ -void vTraceSetMessageBufferName(void* object, const char* name); -#else /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ -#define vTraceSetMessageBufferName(object, name) /* Do nothing */ -#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ - -#else /* (TRC_CFG_SCHEDULING_ONLY == 0) */ - -#define vTraceSetQueueName(object, name) /* Do nothing */ -#define vTraceSetSemaphoreName(object, name) /* Do nothing */ -#define vTraceSetMutexName(object, name) /* Do nothing */ -#define vTraceSetEventGroupName(object, name) /* Do nothing */ -#define vTraceSetStreamBufferName(object, name) /* Do nothing */ -#define vTraceSetMessageBufferName(object, name) /* Do nothing */ - -#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */ - -/******************************************************************************* - * Note: Setting names for event groups is difficult to support, this has been - * excluded intentionally. This since we don't know if event_groups.c is - * included in the build, so referencing it from the recorder may cause errors. - ******************************************************************************/ - -/* Gives the currently executing task (wrapper for RTOS-specific function) */ -void* prvTraceGetCurrentTaskHandle(void); - -#if (((TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) && (TRC_CFG_INCLUDE_ISR_TRACING == 1)) || (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)) -/* Tells if the scheduler currently is suspended (task-switches can't occur) */ -unsigned char prvTraceIsSchedulerSuspended(void); - -/******************************************************************************* - * INCLUDE_xTaskGetSchedulerState must be set to 1 for tracing to work properly - ******************************************************************************/ -#undef INCLUDE_xTaskGetSchedulerState -#define INCLUDE_xTaskGetSchedulerState 1 - -#endif /* (((TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) && (TRC_CFG_INCLUDE_ISR_TRACING == 1)) || (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)) */ - -#define TRACE_KERNEL_VERSION 0x1AA1 -#define TRACE_TICK_RATE_HZ configTICK_RATE_HZ /* Defined in "FreeRTOS.h" */ -#define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */ -#define TRACE_GET_CURRENT_TASK() prvTraceGetCurrentTaskHandle() - -#define TRACE_GET_OS_TICKS() (uiTraceTickCount) /* Streaming only */ - -/* If using dynamic allocation of snapshot trace buffer... */ -#define TRACE_MALLOC(size) pvPortMalloc(size) - -#if defined(configUSE_TIMERS) -#if (configUSE_TIMERS == 1) -#undef INCLUDE_xTimerGetTimerDaemonTaskHandle -#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 -#endif /* configUSE_TIMERS == 1*/ -#endif /* configUSE_TIMERS */ - -/* For ARM Cortex-M devices - assumes the ARM CMSIS API is available */ -#if (defined (__CORTEX_M)) - #define TRACE_ALLOC_CRITICAL_SECTION() uint32_t __irq_status; - #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = __get_PRIMASK(); __set_PRIMASK(1);} /* PRIMASK disables ALL interrupts - allows for tracing in any ISR */ - #define TRACE_EXIT_CRITICAL_SECTION() {__set_PRIMASK(__irq_status);} -#endif - -#if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Renesas_RX600) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Altera_NiosII)) - #define TRACE_ALLOC_CRITICAL_SECTION() int __irq_status; - #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();} - #define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);} -#endif - -#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32) - /* In the Win32 port, there are no real interrupts, so we can use the normal critical sections */ - #define TRACE_ALLOC_CRITICAL_SECTION() - #define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL() - #define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL() -#endif - -#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_POWERPC_Z4) -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) - /* FreeRTOS v8.0 or later */ - #define TRACE_ALLOC_CRITICAL_SECTION() UBaseType_t __irq_status; - #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();} - #define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);} -#else - /* FreeRTOS v7.x */ - #define TRACE_ALLOC_CRITICAL_SECTION() unsigned portBASE_TYPE __irq_status; - #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();} - #define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);} -#endif -#endif - -#ifndef TRACE_ENTER_CRITICAL_SECTION - #error "This hardware port has no definition for critical sections! See http://percepio.com/2014/10/27/how-to-define-critical-sections-for-the-recorder/" -#endif - - -#if (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_9_0_1) - /****************************************************************************** - * Fix for FreeRTOS v9.0.1 to correctly identify xQueuePeek events. - * - * In FreeRTOS v9.0.1, the below trace hooks are incorrectly used from three - * different functions. This as the earlier function xQueueGenericReceive - * has been replaced by xQueuePeek, xQueueSemaphoreTake and xQueueReceive. - * - * xQueueGenericReceive had a parameter "xJustPeeking", used by the trace hooks - * to tell between xQueuePeek events and others. This is no longer present, so - * we need another way to correctly identify peek events. Since all three - * functions call the same trace macros, the context of these macro is unknown. - * - * We therefore check the __LINE__ macro inside of the trace macros. This gives - * the line number of queue.c, where the macros are used. This can be used to - * tell if the context is xQueuePeek or another function. - * __LINE__ is a standard compiler feature since ancient times, so it should - * work on all common compilers. - * - * This might seem as a quite brittle and unusual solution, but works in this - * particular case and is only for FreeRTOS v9.0.1. - * Future versions of FreeRTOS should not need this fix, as we have submitted - * a correction of queue.c with individual trace macros for each function. - ******************************************************************************/ -#define isQueueReceiveHookActuallyPeek (__LINE__ > 1674) /* Half way between the closes trace points */ - -#elif (TRC_CFG_FREERTOS_VERSION <= TRC_FREERTOS_VERSION_9_0_0) -#define isQueueReceiveHookActuallyPeek xJustPeeking - -#elif (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1) -#define isQueueReceiveHookActuallyPeek (__LINE__ < 0) /* instead of pdFALSE to fix a warning of "constant condition" */ - -#endif - -extern uint16_t CurrentFilterMask; - -extern uint16_t CurrentFilterGroup; - -uint8_t prvTraceGetQueueType(void* handle); - -uint16_t prvTraceGetTaskNumberLow16(void* handle); -uint16_t prvTraceGetTaskNumberHigh16(void* handle); -void prvTraceSetTaskNumberLow16(void* handle, uint16_t value); -void prvTraceSetTaskNumberHigh16(void* handle, uint16_t value); - -uint16_t prvTraceGetQueueNumberLow16(void* handle); -uint16_t prvTraceGetQueueNumberHigh16(void* handle); -void prvTraceSetQueueNumberLow16(void* handle, uint16_t value); -void prvTraceSetQueueNumberHigh16(void* handle, uint16_t value); - -#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) -uint16_t prvTraceGetTimerNumberLow16(void* handle); -uint16_t prvTraceGetTimerNumberHigh16(void* handle); -void prvTraceSetTimerNumberLow16(void* handle, uint16_t value); -void prvTraceSetTimerNumberHigh16(void* handle, uint16_t value); -#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ - -#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) -uint16_t prvTraceGetEventGroupNumberLow16(void* handle); -uint16_t prvTraceGetEventGroupNumberHigh16(void* handle); -void prvTraceSetEventGroupNumberLow16(void* handle, uint16_t value); -void prvTraceSetEventGroupNumberHigh16(void* handle, uint16_t value); -#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ - -#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) -uint16_t prvTraceGetStreamBufferNumberLow16(void* handle); -uint16_t prvTraceGetStreamBufferNumberHigh16(void* handle); -void prvTraceSetStreamBufferNumberLow16(void* handle, uint16_t value); -void prvTraceSetStreamBufferNumberHigh16(void* handle, uint16_t value); -#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ - -#define TRACE_GET_TASK_FILTER(pxTask) prvTraceGetTaskNumberHigh16((void*)pxTask) -#define TRACE_SET_TASK_FILTER(pxTask, group) prvTraceSetTaskNumberHigh16((void*)pxTask, group) - -#define TRACE_GET_QUEUE_FILTER(pxObject) prvTraceGetQueueNumberHigh16((void*)pxObject) -#define TRACE_SET_QUEUE_FILTER(pxObject, group) prvTraceSetQueueNumberHigh16((void*)pxObject, group) - -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) -#define TRACE_GET_EVENTGROUP_FILTER(pxObject) prvTraceGetEventGroupNumberHigh16((void*)pxObject) -#define TRACE_SET_EVENTGROUP_FILTER(pxObject, group) prvTraceSetEventGroupNumberHigh16((void*)pxObject, group) -#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ -/* FreeRTOS versions before v10.0 does not support filtering for event groups */ -#define TRACE_GET_EVENTGROUP_FILTER(pxObject) 1 -#define TRACE_SET_EVENTGROUP_FILTER(pxObject, group) -#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ - -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) -#define TRACE_GET_TIMER_FILTER(pxObject) prvTraceGetTimerNumberHigh16((void*)pxObject) -#define TRACE_SET_TIMER_FILTER(pxObject, group) prvTraceSetTimerNumberHigh16((void*)pxObject, group) -#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ -/* FreeRTOS versions before v10.0 does not support filtering for timers */ -#define TRACE_GET_TIMER_FILTER(pxObject) 1 -#define TRACE_SET_TIMER_FILTER(pxObject, group) -#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ - -#define TRACE_GET_STREAMBUFFER_FILTER(pxObject) prvTraceGetStreamBufferNumberHigh16((void*)pxObject) -#define TRACE_SET_STREAMBUFFER_FILTER(pxObject, group) prvTraceSetStreamBufferNumberHigh16((void*)pxObject, group) - -/* We can only support filtering if FreeRTOS is at least v7.4 */ -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4) -#define TRACE_GET_OBJECT_FILTER(CLASS, pxObject) TRACE_GET_##CLASS##_FILTER(pxObject) -#define TRACE_SET_OBJECT_FILTER(CLASS, pxObject, group) TRACE_SET_##CLASS##_FILTER(pxObject, group) -#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4) */ -#define TRACE_GET_OBJECT_FILTER(CLASS, pxObject) 1 -#define TRACE_SET_OBJECT_FILTER(CLASS, pxObject, group) -#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4) */ - -/******************************************************************************/ -/*** Definitions for Snapshot mode ********************************************/ -/******************************************************************************/ -#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) - -/*** The object classes *******************************************************/ - -#define TRACE_NCLASSES 9 -#define TRACE_CLASS_QUEUE ((traceObjectClass)0) -#define TRACE_CLASS_SEMAPHORE ((traceObjectClass)1) -#define TRACE_CLASS_MUTEX ((traceObjectClass)2) -#define TRACE_CLASS_TASK ((traceObjectClass)3) -#define TRACE_CLASS_ISR ((traceObjectClass)4) -#define TRACE_CLASS_TIMER ((traceObjectClass)5) -#define TRACE_CLASS_EVENTGROUP ((traceObjectClass)6) -#define TRACE_CLASS_STREAMBUFFER ((traceObjectClass)7) -#define TRACE_CLASS_MESSAGEBUFFER ((traceObjectClass)8) - -/*** Definitions for Object Table ********************************************/ -#define TRACE_KERNEL_OBJECT_COUNT ((TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) + (TRC_CFG_NMESSAGEBUFFER)) - -/* Queue properties (except name): current number of message in queue */ -#define PropertyTableSizeQueue ((TRC_CFG_NAME_LEN_QUEUE) + 1) - -/* Semaphore properties (except name): state (signaled = 1, cleared = 0) */ -#define PropertyTableSizeSemaphore ((TRC_CFG_NAME_LEN_SEMAPHORE) + 1) - -/* Mutex properties (except name): owner (task handle, 0 = free) */ -#define PropertyTableSizeMutex ((TRC_CFG_NAME_LEN_MUTEX) + 1) - -/* Task properties (except name): Byte 0: Current priority - Byte 1: state (if already active) - Byte 2: legacy, not used - Byte 3: legacy, not used */ -#define PropertyTableSizeTask ((TRC_CFG_NAME_LEN_TASK) + 4) - -/* ISR properties: Byte 0: priority - Byte 1: state (if already active) */ -#define PropertyTableSizeISR ((TRC_CFG_NAME_LEN_ISR) + 2) - -/* TRC_CFG_NTIMER properties: Byte 0: state (unused for now) */ -#define PropertyTableSizeTimer ((TRC_CFG_NAME_LEN_TIMER) + 1) - -/* TRC_CFG_NEVENTGROUP properties: Byte 0-3: state (unused for now)*/ -#define PropertyTableSizeEventGroup ((TRC_CFG_NAME_LEN_EVENTGROUP) + 4) - -/* TRC_CFG_NSTREAMBUFFER properties: Byte 0-3: state (unused for now)*/ -#define PropertyTableSizeStreamBuffer ((TRC_CFG_NAME_LEN_STREAMBUFFER) + 4) - -/* TRC_CFG_NMESSAGEBUFFER properties: Byte 0-3: state (unused for now)*/ -#define PropertyTableSizeMessageBuffer ((TRC_CFG_NAME_LEN_MESSAGEBUFFER) + 4) - - -/* The layout of the byte array representing the Object Property Table */ -#define StartIndexQueue (0) -#define StartIndexSemaphore (StartIndexQueue + (TRC_CFG_NQUEUE) * PropertyTableSizeQueue) -#define StartIndexMutex (StartIndexSemaphore + (TRC_CFG_NSEMAPHORE) * PropertyTableSizeSemaphore) -#define StartIndexTask (StartIndexMutex + (TRC_CFG_NMUTEX) * PropertyTableSizeMutex) -#define StartIndexISR (StartIndexTask + (TRC_CFG_NTASK) * PropertyTableSizeTask) -#define StartIndexTimer (StartIndexISR + (TRC_CFG_NISR) * PropertyTableSizeISR) -#define StartIndexEventGroup (StartIndexTimer + (TRC_CFG_NTIMER) * PropertyTableSizeTimer) -#define StartIndexStreamBuffer (StartIndexEventGroup + (TRC_CFG_NEVENTGROUP) * PropertyTableSizeEventGroup) -#define StartIndexMessageBuffer (StartIndexStreamBuffer + (TRC_CFG_NSTREAMBUFFER) * PropertyTableSizeStreamBuffer) - -/* Number of bytes used by the object table */ -#define TRACE_OBJECT_TABLE_SIZE (StartIndexMessageBuffer + (TRC_CFG_NMESSAGEBUFFER) * PropertyTableSizeMessageBuffer) - -/* Flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */ -extern int uiInEventGroupSetBitsFromISR; - -/* Initialization of the object property table */ -void vTraceInitObjectPropertyTable(void); - -/* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */ -void vTraceInitObjectHandleStack(void); - -/* Returns the "Not enough handles" error message for the specified object class */ -const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass); - -void* prvTraceGetCurrentTaskHandle(void); - -/****************************************************************************** - * TraceQueueClassTable - * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_). - * Has one entry for each QueueType, gives TRACE_CLASS ID. - ******************************************************************************/ -extern traceObjectClass TraceQueueClassTable[5]; - - -/*** Event codes for snapshot mode - must match Tracealyzer config files ******/ - -#define NULL_EVENT (0x00UL) - -/******************************************************************************* - * EVENTGROUP_DIV - * - * Miscellaneous events. - ******************************************************************************/ -#define EVENTGROUP_DIV (NULL_EVENT + 1UL) /*0x01*/ -#define DIV_XPS (EVENTGROUP_DIV + 0UL) /*0x01*/ -#define DIV_TASK_READY (EVENTGROUP_DIV + 1UL) /*0x02*/ -#define DIV_NEW_TIME (EVENTGROUP_DIV + 2UL) /*0x03*/ - -/******************************************************************************* - * EVENTGROUP_TS - * - * Events for storing task-switches and interrupts. The RESUME events are - * generated if the task/interrupt is already marked active. - ******************************************************************************/ -#define EVENTGROUP_TS (EVENTGROUP_DIV + 3UL) /*0x04*/ -#define TS_ISR_BEGIN (EVENTGROUP_TS + 0UL) /*0x04*/ -#define TS_ISR_RESUME (EVENTGROUP_TS + 1UL) /*0x05*/ -#define TS_TASK_BEGIN (EVENTGROUP_TS + 2UL) /*0x06*/ -#define TS_TASK_RESUME (EVENTGROUP_TS + 3UL) /*0x07*/ - -/******************************************************************************* - * EVENTGROUP_OBJCLOSE_NAME - * - * About Close Events - * When an object is evicted from the object property table (object close), two - * internal events are stored (EVENTGROUP_OBJCLOSE_NAME and - * EVENTGROUP_OBJCLOSE_PROP), containing the handle-name mapping and object - * properties valid up to this point. - ******************************************************************************/ -#define EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS (EVENTGROUP_TS + 4UL) /*0x08*/ - -/******************************************************************************* - * EVENTGROUP_OBJCLOSE_PROP - * - * The internal event carrying properties of deleted objects - * The handle and object class of the closed object is not stored in this event, - * but is assumed to be the same as in the preceding CLOSE event. Thus, these - * two events must be generated from within a critical section. - * When queues are closed, arg1 is the "state" property (i.e., number of - * buffered messages/signals). - * When actors are closed, arg1 is priority, arg2 is handle of the "instance - * finish" event, and arg3 is event code of the "instance finish" event. - * In this case, the lower three bits is the object class of the instance finish - * handle. The lower three bits are not used (always zero) when queues are - * closed since the queue type is given in the previous OBJCLOSE_NAME event. - ******************************************************************************/ -#define EVENTGROUP_OBJCLOSE_PROP_TRCSUCCESS (EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + 8UL) /*0x10*/ - -/******************************************************************************* - * EVENTGROUP_CREATE - * - * The events in this group are used to log Kernel object creations. - * The lower three bits in the event code gives the object class, i.e., type of - * create operation (task, queue, semaphore, etc). - ******************************************************************************/ -#define EVENTGROUP_CREATE_OBJ_TRCSUCCESS (EVENTGROUP_OBJCLOSE_PROP_TRCSUCCESS + 8UL) /*0x18*/ - -/******************************************************************************* - * EVENTGROUP_SEND - * - * The events in this group are used to log Send/Give events on queues, - * semaphores and mutexes The lower three bits in the event code gives the - * object class, i.e., what type of object that is operated on (queue, semaphore - * or mutex). - ******************************************************************************/ -#define EVENTGROUP_SEND_TRCSUCCESS (EVENTGROUP_CREATE_OBJ_TRCSUCCESS + 8UL) /*0x20*/ - -/******************************************************************************* - * EVENTGROUP_RECEIVE - * - * The events in this group are used to log Receive/Take events on queues, - * semaphores and mutexes. The lower three bits in the event code gives the - * object class, i.e., what type of object that is operated on (queue, semaphore - * or mutex). - ******************************************************************************/ -#define EVENTGROUP_RECEIVE_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 8UL) /*0x28*/ - -/* Send/Give operations, from ISR */ -#define EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS \ - (EVENTGROUP_RECEIVE_TRCSUCCESS + 8UL) /*0x30*/ - -/* Receive/Take operations, from ISR */ -#define EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS \ - (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 8UL) /*0x38*/ - -/* "Failed" event type versions of above (timeout, failed allocation, etc) */ -#define EVENTGROUP_KSE_TRCFAILED \ - (EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS + 8UL) /*0x40*/ - -/* Failed create calls - memory allocation failed */ -#define EVENTGROUP_CREATE_OBJ_TRCFAILED (EVENTGROUP_KSE_TRCFAILED) /*0x40*/ - -/* Failed send/give - timeout! */ -#define EVENTGROUP_SEND_TRCFAILED (EVENTGROUP_CREATE_OBJ_TRCFAILED + 8UL) /*0x48*/ - -/* Failed receive/take - timeout! */ -#define EVENTGROUP_RECEIVE_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 8UL) /*0x50*/ - -/* Failed non-blocking send/give - queue full */ -#define EVENTGROUP_SEND_FROM_ISR_TRCFAILED (EVENTGROUP_RECEIVE_TRCFAILED + 8UL) /*0x58*/ - -/* Failed non-blocking receive/take - queue empty */ -#define EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED \ - (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 8UL) /*0x60*/ - -/* Events when blocking on receive/take */ -#define EVENTGROUP_RECEIVE_TRCBLOCK \ - (EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED + 8UL) /*0x68*/ - -/* Events when blocking on send/give */ -#define EVENTGROUP_SEND_TRCBLOCK (EVENTGROUP_RECEIVE_TRCBLOCK + 8UL) /*0x70*/ - -/* Events on queue peek (receive) */ -#define EVENTGROUP_PEEK_TRCSUCCESS (EVENTGROUP_SEND_TRCBLOCK + 8UL) /*0x78*/ - -/* Events on object delete (vTaskDelete or vQueueDelete) */ -#define EVENTGROUP_DELETE_OBJ_TRCSUCCESS (EVENTGROUP_PEEK_TRCSUCCESS + 8UL) /*0x80*/ - -/* Other events - object class is implied: TASK */ -#define EVENTGROUP_OTHERS (EVENTGROUP_DELETE_OBJ_TRCSUCCESS + 8UL) /*0x88*/ -#define TASK_DELAY_UNTIL (EVENTGROUP_OTHERS + 0UL) /*0x88*/ -#define TASK_DELAY (EVENTGROUP_OTHERS + 1UL) /*0x89*/ -#define TASK_SUSPEND (EVENTGROUP_OTHERS + 2UL) /*0x8A*/ -#define TASK_RESUME (EVENTGROUP_OTHERS + 3UL) /*0x8B*/ -#define TASK_RESUME_FROM_ISR (EVENTGROUP_OTHERS + 4UL) /*0x8C*/ -#define TASK_PRIORITY_SET (EVENTGROUP_OTHERS + 5UL) /*0x8D*/ -#define TASK_PRIORITY_INHERIT (EVENTGROUP_OTHERS + 6UL) /*0x8E*/ -#define TASK_PRIORITY_DISINHERIT (EVENTGROUP_OTHERS + 7UL) /*0x8F*/ - -#define EVENTGROUP_MISC_PLACEHOLDER (EVENTGROUP_OTHERS + 8UL) /*0x90*/ -#define PEND_FUNC_CALL (EVENTGROUP_MISC_PLACEHOLDER+0UL) /*0x90*/ -#define PEND_FUNC_CALL_FROM_ISR (EVENTGROUP_MISC_PLACEHOLDER+1UL) /*0x91*/ -#define PEND_FUNC_CALL_TRCFAILED (EVENTGROUP_MISC_PLACEHOLDER+2UL) /*0x92*/ -#define PEND_FUNC_CALL_FROM_ISR_TRCFAILED (EVENTGROUP_MISC_PLACEHOLDER+3UL) /*0x93*/ -#define MEM_MALLOC_SIZE (EVENTGROUP_MISC_PLACEHOLDER+4UL) /*0x94*/ -#define MEM_MALLOC_ADDR (EVENTGROUP_MISC_PLACEHOLDER+5UL) /*0x95*/ -#define MEM_FREE_SIZE (EVENTGROUP_MISC_PLACEHOLDER+6UL) /*0x96*/ -#define MEM_FREE_ADDR (EVENTGROUP_MISC_PLACEHOLDER+7UL) /*0x97*/ - -/* User events */ -#define EVENTGROUP_USEREVENT (EVENTGROUP_MISC_PLACEHOLDER + 8UL) /*0x98*/ -#define USER_EVENT (EVENTGROUP_USEREVENT + 0UL) - -/* Allow for 0-15 arguments (the number of args is added to event code) */ -#define USER_EVENT_LAST (EVENTGROUP_USEREVENT + 15UL) /*0xA7*/ - -/******************************************************************************* - * XTS Event - eXtended TimeStamp events - * The timestamps used in the recorder are "differential timestamps" (DTS), i.e. - * the time since the last stored event. The DTS fields are either 1 or 2 bytes - * in the other events, depending on the bytes available in the event struct. - * If the time since the last event (the DTS) is larger than allowed for by - * the DTS field of the current event, an XTS event is inserted immediately - * before the original event. The XTS event contains up to 3 additional bytes - * of the DTS value - the higher bytes of the true DTS value. The lower 1-2 - * bytes are stored in the normal DTS field. - * There are two types of XTS events, XTS8 and XTS16. An XTS8 event is stored - * when there is only room for 1 byte (8 bit) DTS data in the original event, - * which means a limit of 0xFF (255UL). The XTS16 is used when the original event - * has a 16 bit DTS field and thereby can handle values up to 0xFFFF (65535UL). - * - * Using a very high frequency time base can result in many XTS events. - * Preferably, the time between two OS ticks should fit in 16 bits, i.e., - * at most 65535. If your time base has a higher frequency, you can define - * the TRACE - ******************************************************************************/ - -#define EVENTGROUP_SYS (EVENTGROUP_USEREVENT + 16UL) /*0xA8*/ -#define XTS8 (EVENTGROUP_SYS + 0UL) /*0xA8*/ -#define XTS16 (EVENTGROUP_SYS + 1UL) /*0xA9*/ -#define EVENT_BEING_WRITTEN (EVENTGROUP_SYS + 2UL) /*0xAA*/ -#define RESERVED_DUMMY_CODE (EVENTGROUP_SYS + 3UL) /*0xAB*/ -#define LOW_POWER_BEGIN (EVENTGROUP_SYS + 4UL) /*0xAC*/ -#define LOW_POWER_END (EVENTGROUP_SYS + 5UL) /*0xAD*/ -#define XID (EVENTGROUP_SYS + 6UL) /*0xAE*/ -#define XTS16L (EVENTGROUP_SYS + 7UL) /*0xAF*/ - -#define EVENTGROUP_TIMER (EVENTGROUP_SYS + 8UL) /*0xB0*/ -#define TIMER_CREATE (EVENTGROUP_TIMER + 0UL) /*0xB0*/ -#define TIMER_START (EVENTGROUP_TIMER + 1UL) /*0xB1*/ -#define TIMER_RST (EVENTGROUP_TIMER + 2UL) /*0xB2*/ -#define TIMER_STOP (EVENTGROUP_TIMER + 3UL) /*0xB3*/ -#define TIMER_CHANGE_PERIOD (EVENTGROUP_TIMER + 4UL) /*0xB4*/ -#define TIMER_DELETE_OBJ (EVENTGROUP_TIMER + 5UL) /*0xB5*/ -#define TIMER_START_FROM_ISR (EVENTGROUP_TIMER + 6UL) /*0xB6*/ -#define TIMER_RESET_FROM_ISR (EVENTGROUP_TIMER + 7UL) /*0xB7*/ -#define TIMER_STOP_FROM_ISR (EVENTGROUP_TIMER + 8UL) /*0xB8*/ - -#define TIMER_CREATE_TRCFAILED (EVENTGROUP_TIMER + 9UL) /*0xB9*/ -#define TIMER_START_TRCFAILED (EVENTGROUP_TIMER + 10UL) /*0xBA*/ -#define TIMER_RESET_TRCFAILED (EVENTGROUP_TIMER + 11UL) /*0xBB*/ -#define TIMER_STOP_TRCFAILED (EVENTGROUP_TIMER + 12UL) /*0xBC*/ -#define TIMER_CHANGE_PERIOD_TRCFAILED (EVENTGROUP_TIMER + 13UL) /*0xBD*/ -#define TIMER_DELETE_TRCFAILED (EVENTGROUP_TIMER + 14UL) /*0xBE*/ -#define TIMER_START_FROM_ISR_TRCFAILED (EVENTGROUP_TIMER + 15UL) /*0xBF*/ -#define TIMER_RESET_FROM_ISR_TRCFAILED (EVENTGROUP_TIMER + 16UL) /*0xC0*/ -#define TIMER_STOP_FROM_ISR_TRCFAILED (EVENTGROUP_TIMER + 17UL) /*0xC1*/ - -#define EVENTGROUP_EG (EVENTGROUP_TIMER + 18UL) /*0xC2*/ -#define EVENT_GROUP_CREATE (EVENTGROUP_EG + 0UL) /*0xC2*/ -#define EVENT_GROUP_CREATE_TRCFAILED (EVENTGROUP_EG + 1UL) /*0xC3*/ -#define EVENT_GROUP_SYNC_TRCBLOCK (EVENTGROUP_EG + 2UL) /*0xC4*/ -#define EVENT_GROUP_SYNC_END (EVENTGROUP_EG + 3UL) /*0xC5*/ -#define EVENT_GROUP_WAIT_BITS_TRCBLOCK (EVENTGROUP_EG + 4UL) /*0xC6*/ -#define EVENT_GROUP_WAIT_BITS_END (EVENTGROUP_EG + 5UL) /*0xC7*/ -#define EVENT_GROUP_CLEAR_BITS (EVENTGROUP_EG + 6UL) /*0xC8*/ -#define EVENT_GROUP_CLEAR_BITS_FROM_ISR (EVENTGROUP_EG + 7UL) /*0xC9*/ -#define EVENT_GROUP_SET_BITS (EVENTGROUP_EG + 8UL) /*0xCA*/ -#define EVENT_GROUP_DELETE_OBJ (EVENTGROUP_EG + 9UL) /*0xCB*/ -#define EVENT_GROUP_SYNC_END_TRCFAILED (EVENTGROUP_EG + 10UL) /*0xCC*/ -#define EVENT_GROUP_WAIT_BITS_END_TRCFAILED (EVENTGROUP_EG + 11UL) /*0xCD*/ -#define EVENT_GROUP_SET_BITS_FROM_ISR (EVENTGROUP_EG + 12UL) /*0xCE*/ -#define EVENT_GROUP_SET_BITS_FROM_ISR_TRCFAILED (EVENTGROUP_EG + 13UL) /*0xCF*/ - -#define TASK_INSTANCE_FINISHED_NEXT_KSE (EVENTGROUP_EG + 14UL) /*0xD0*/ -#define TASK_INSTANCE_FINISHED_DIRECT (EVENTGROUP_EG + 15UL) /*0xD1*/ - -#define TRACE_TASK_NOTIFY_GROUP (EVENTGROUP_EG + 16UL) /*0xD2*/ -#define TRACE_TASK_NOTIFY (TRACE_TASK_NOTIFY_GROUP + 0UL) /*0xD2*/ -#define TRACE_TASK_NOTIFY_TAKE (TRACE_TASK_NOTIFY_GROUP + 1UL) /*0xD3*/ -#define TRACE_TASK_NOTIFY_TAKE_TRCBLOCK (TRACE_TASK_NOTIFY_GROUP + 2UL) /*0xD4*/ -#define TRACE_TASK_NOTIFY_TAKE_TRCFAILED (TRACE_TASK_NOTIFY_GROUP + 3UL) /*0xD5*/ -#define TRACE_TASK_NOTIFY_WAIT (TRACE_TASK_NOTIFY_GROUP + 4UL) /*0xD6*/ -#define TRACE_TASK_NOTIFY_WAIT_TRCBLOCK (TRACE_TASK_NOTIFY_GROUP + 5UL) /*0xD7*/ -#define TRACE_TASK_NOTIFY_WAIT_TRCFAILED (TRACE_TASK_NOTIFY_GROUP + 6UL) /*0xD8*/ -#define TRACE_TASK_NOTIFY_FROM_ISR (TRACE_TASK_NOTIFY_GROUP + 7UL) /*0xD9*/ -#define TRACE_TASK_NOTIFY_GIVE_FROM_ISR (TRACE_TASK_NOTIFY_GROUP + 8UL) /*0xDA*/ - -#define TIMER_EXPIRED (TRACE_TASK_NOTIFY_GROUP + 9UL) /* 0xDB */ - - /* Events on queue peek (receive) */ -#define EVENTGROUP_PEEK_TRCBLOCK (TRACE_TASK_NOTIFY_GROUP + 10UL) /*0xDC*/ -/* peek block on queue: 0xDC */ -/* peek block on semaphore: 0xDD */ -/* peek block on mutex: 0xDE */ - -/* Events on queue peek (receive) */ -#define EVENTGROUP_PEEK_TRCFAILED (EVENTGROUP_PEEK_TRCBLOCK + 3UL) /*0xDF*/ -/* peek failed on queue: 0xDF */ -/* peek failed on semaphore: 0xE0 */ -/* peek failed on mutex: 0xE1 */ - -#define EVENTGROUP_STREAMBUFFER_DIV (EVENTGROUP_PEEK_TRCFAILED + 3UL) /*0xE2*/ -#define TRACE_STREAMBUFFER_RESET (EVENTGROUP_STREAMBUFFER_DIV + 0) /*0xE2*/ -#define TRACE_MESSAGEBUFFER_RESET (EVENTGROUP_STREAMBUFFER_DIV + 1UL) /*0xE3*/ -#define TRACE_STREAMBUFFER_OBJCLOSE_NAME_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 2UL) /*0xE4*/ -#define TRACE_MESSAGEBUFFER_OBJCLOSE_NAME_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 3UL) /*0xE5*/ -#define TRACE_STREAMBUFFER_OBJCLOSE_PROP_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 4UL) /*0xE6*/ -#define TRACE_MESSAGEBUFFER_OBJCLOSE_PROP_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 5UL) /*0xE7*/ - -/* The following are using previously "lost" event codes */ -#define TRACE_STREAMBUFFER_CREATE_OBJ_TRCSUCCESS (EVENTGROUP_CREATE_OBJ_TRCSUCCESS + 4UL) /*0x1C*/ -#define TRACE_STREAMBUFFER_CREATE_OBJ_TRCFAILED (EVENTGROUP_CREATE_OBJ_TRCFAILED + 4UL) /*0x44*/ -#define TRACE_STREAMBUFFER_DELETE_OBJ_TRCSUCCESS (EVENTGROUP_DELETE_OBJ_TRCSUCCESS + 4UL) /*0x84*/ -#define TRACE_STREAMBUFFER_SEND_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 3UL) /*0x23*/ -#define TRACE_STREAMBUFFER_SEND_TRCBLOCK (EVENTGROUP_SEND_TRCBLOCK + 3UL) /*0x73*/ -#define TRACE_STREAMBUFFER_SEND_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 3UL) /*0x4B*/ -#define TRACE_STREAMBUFFER_RECEIVE_TRCSUCCESS (EVENTGROUP_RECEIVE_TRCSUCCESS + 3UL) /*0x2B*/ -#define TRACE_STREAMBUFFER_RECEIVE_TRCBLOCK (EVENTGROUP_RECEIVE_TRCBLOCK + 3UL) /*0x6B*/ -#define TRACE_STREAMBUFFER_RECEIVE_TRCFAILED (EVENTGROUP_RECEIVE_TRCFAILED + 3UL) /*0x53*/ -#define TRACE_STREAMBUFFER_SEND_FROM_ISR_TRCSUCCESS (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 3UL) /*0x33*/ -#define TRACE_STREAMBUFFER_SEND_FROM_ISR_TRCFAILED (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 3UL) /*0x5B*/ -#define TRACE_STREAMBUFFER_RECEIVE_FROM_ISR_TRCSUCCESS (EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS + 3UL) /*0x3B*/ -#define TRACE_STREAMBUFFER_RECEIVE_FROM_ISR_TRCFAILED (EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED + 3UL) /*0x63*/ - -/* The following are using previously "lost" event codes. These macros aren't even directly referenced, instead we do (equivalent STREAMBUFFER code) + 1. */ -#define TRACE_MESSAGEBUFFER_CREATE_OBJ_TRCSUCCESS (EVENTGROUP_CREATE_OBJ_TRCSUCCESS + 5UL) /*0x1D*/ -#define TRACE_MESSAGEBUFFER_CREATE_OBJ_TRCFAILED (EVENTGROUP_CREATE_OBJ_TRCFAILED + 5UL) /*0x45*/ -#define TRACE_MESSAGEBUFFER_DELETE_OBJ_TRCSUCCESS (EVENTGROUP_DELETE_OBJ_TRCSUCCESS + 5UL) /*0x85*/ -#define TRACE_MESSAGEBUFFER_SEND_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 4UL) /*0x24*/ -#define TRACE_MESSAGEBUFFER_SEND_TRCBLOCK (EVENTGROUP_SEND_TRCBLOCK + 4UL) /*0x74*/ -#define TRACE_MESSAGEBUFFER_SEND_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 4UL) /*0x4C*/ -#define TRACE_MESSAGEBUFFER_RECEIVE_TRCSUCCESS (EVENTGROUP_RECEIVE_TRCSUCCESS + 4UL) /*0x2C*/ -#define TRACE_MESSAGEBUFFER_RECEIVE_TRCBLOCK (EVENTGROUP_RECEIVE_TRCBLOCK + 4UL) /*0x6C*/ -#define TRACE_MESSAGEBUFFER_RECEIVE_TRCFAILED (EVENTGROUP_RECEIVE_TRCFAILED + 4UL) /*0x54*/ -#define TRACE_MESSAGEBUFFER_SEND_FROM_ISR_TRCSUCCESS (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 4UL) /*0x34*/ -#define TRACE_MESSAGEBUFFER_SEND_FROM_ISR_TRCFAILED (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 4UL) /*0x5C*/ -#define TRACE_MESSAGEBUFFER_RECEIVE_FROM_ISR_TRCSUCCESS (EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS + 4UL) /*0x3C*/ -#define TRACE_MESSAGEBUFFER_RECEIVE_FROM_ISR_TRCFAILED (EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED + 4UL) /*0x64*/ - -/* LAST EVENT (0xE7) */ - -/**************************** -* MACROS TO GET TRACE CLASS * -****************************/ -#define TRACE_GET_TRACE_CLASS_FROM_TASK_CLASS(kernelClass) (TRACE_CLASS_TASK) -#define TRACE_GET_TRACE_CLASS_FROM_TASK_OBJECT(pxObject) (TRACE_CLASS_TASK) - -#define TRACE_GET_TRACE_CLASS_FROM_QUEUE_CLASS(kernelClass) TraceQueueClassTable[kernelClass] -#define TRACE_GET_TRACE_CLASS_FROM_QUEUE_OBJECT(pxObject) TRACE_GET_TRACE_CLASS_FROM_QUEUE_CLASS(prvTraceGetQueueType(pxObject)) - -#define TRACE_GET_TRACE_CLASS_FROM_TIMER_CLASS(kernelClass) (TRACE_CLASS_TIMER) -#define TRACE_GET_TRACE_CLASS_FROM_TIMER_OBJECT(pxObject) (TRACE_CLASS_TIMER) - -#define TRACE_GET_TRACE_CLASS_FROM_EVENTGROUP_CLASS(kernelClass) (TRACE_CLASS_EVENTGROUP) -#define TRACE_GET_TRACE_CLASS_FROM_EVENTGROUP_OBJECT(pxObject) (TRACE_CLASS_EVENTGROUP) - -/* TRACE_GET_TRACE_CLASS_FROM_STREAMBUFFER_CLASS can only be accessed with a parameter indicating if it is a MessageBuffer */ -#define TRACE_GET_TRACE_CLASS_FROM_STREAMBUFFER_CLASS(xIsMessageBuffer) (xIsMessageBuffer == 1 ? TRACE_CLASS_MESSAGEBUFFER : TRACE_CLASS_STREAMBUFFER) -#define TRACE_GET_TRACE_CLASS_FROM_STREAMBUFFER_OBJECT(pxObject) (prvGetStreamBufferType(pxObject) == 1 ? TRACE_CLASS_MESSAGEBUFFER : TRACE_CLASS_STREAMBUFFER) - -/* Generic versions */ -#define TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass) TRACE_GET_TRACE_CLASS_FROM_##CLASS##_CLASS(kernelClass) -#define TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject) TRACE_GET_TRACE_CLASS_FROM_##CLASS##_OBJECT(pxObject) - -/****************************** -* MACROS TO GET OBJECT NUMBER * -******************************/ -#define TRACE_GET_TASK_NUMBER(pxTCB) (traceHandle)(prvTraceGetTaskNumberLow16(pxTCB)) -#define TRACE_SET_TASK_NUMBER(pxTCB) prvTraceSetTaskNumberLow16(pxTCB, prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(TASK, pxTCB))); - -#define TRACE_GET_QUEUE_NUMBER(queue) ( ( traceHandle ) prvTraceGetQueueNumberLow16(queue) ) -#define TRACE_SET_QUEUE_NUMBER(queue) prvTraceSetQueueNumberLow16(queue, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, queue))); - -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) -#define TRACE_GET_TIMER_NUMBER(tmr) ( ( traceHandle ) prvTraceGetTimerNumberLow16(tmr) ) -#define TRACE_SET_TIMER_NUMBER(tmr) prvTraceSetTimerNumberLow16(tmr, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr))); -#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ -#define TRACE_GET_TIMER_NUMBER(tmr) ( ( traceHandle ) ((Timer_t*)tmr)->uxTimerNumber ) -#define TRACE_SET_TIMER_NUMBER(tmr) ((Timer_t*)tmr)->uxTimerNumber = prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr)); -#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ - -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) -#define TRACE_GET_EVENTGROUP_NUMBER(eg) ( ( traceHandle ) prvTraceGetEventGroupNumberLow16(eg) ) -#define TRACE_SET_EVENTGROUP_NUMBER(eg) prvTraceSetEventGroupNumberLow16(eg, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg))); -#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ -#define TRACE_GET_EVENTGROUP_NUMBER(eg) ( ( traceHandle ) uxEventGroupGetNumber(eg) ) -#define TRACE_SET_EVENTGROUP_NUMBER(eg) ((EventGroup_t*)eg)->uxEventGroupNumber = prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg)); -#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ - - -#define TRACE_GET_STREAMBUFFER_NUMBER(sb) ( ( traceHandle ) prvTraceGetStreamBufferNumberLow16(sb) ) -#define TRACE_SET_STREAMBUFFER_NUMBER(sb) prvTraceSetStreamBufferNumberLow16(sb, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(STREAMBUFFER, sb))); - -/* Generic versions */ -#define TRACE_GET_OBJECT_NUMBER(CLASS, pxObject) TRACE_GET_##CLASS##_NUMBER(pxObject) -#define TRACE_SET_OBJECT_NUMBER(CLASS, pxObject) TRACE_SET_##CLASS##_NUMBER(pxObject) - -/****************************** -* MACROS TO GET EVENT CODES * -******************************/ -#define TRACE_GET_TASK_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_CLASS_TRACE_CLASS(TASK, kernelClass)) -#define TRACE_GET_QUEUE_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_CLASS_TRACE_CLASS(QUEUE, kernelClass)) -#define TRACE_GET_TIMER_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) -- THIS IS NOT USED -- -#define TRACE_GET_EVENTGROUP_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) -- THIS IS NOT USED -- -#define TRACE_GET_STREAMBUFFER_CLASS_EVENT_CODE(SERVICE, RESULT, isMessageBuffer) (uint8_t)(TRACE_STREAMBUFFER_##SERVICE##_##RESULT + (uint8_t)isMessageBuffer) - -#define TRACE_GET_TASK_OBJECT_EVENT_CODE(SERVICE, RESULT, pxTCB) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_CLASS_TASK) -#define TRACE_GET_QUEUE_OBJECT_EVENT_CODE(SERVICE, RESULT, pxObject) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxObject)) -#define TRACE_GET_TIMER_OBJECT_EVENT_CODE(SERVICE, RESULT, UNUSED) -- THIS IS NOT USED -- -#define TRACE_GET_EVENTGROUP_OBJECT_EVENT_CODE(SERVICE, RESULT, UNUSED) -- THIS IS NOT USED -- -#define TRACE_GET_STREAMBUFFER_OBJECT_EVENT_CODE(SERVICE, RESULT, pxObject) (uint8_t)(TRACE_STREAMBUFFER_##SERVICE##_##RESULT + prvGetStreamBufferType(pxObject)) - -/* Generic versions */ -#define TRACE_GET_CLASS_EVENT_CODE(SERVICE, RESULT, CLASS, kernelClass) TRACE_GET_##CLASS##_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) -#define TRACE_GET_OBJECT_EVENT_CODE(SERVICE, RESULT, CLASS, pxObject) TRACE_GET_##CLASS##_OBJECT_EVENT_CODE(SERVICE, RESULT, pxObject) - -/****************************** -* SPECIAL MACROS FOR TASKS * -******************************/ -#define TRACE_GET_TASK_PRIORITY(pxTCB) ((uint8_t)pxTCB->uxPriority) -#define TRACE_GET_TASK_NAME(pxTCB) ((char*)pxTCB->pcTaskName) - -/*** The trace macros for snapshot mode **************************************/ - -/* A macro that will update the tick count when returning from tickless idle */ -#undef traceINCREASE_TICK_COUNT -#define traceINCREASE_TICK_COUNT( xCount ) - -/* Called for each task that becomes ready */ -#undef traceMOVED_TASK_TO_READY_STATE -#define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ - trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB); - -/* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */ -#undef traceTASK_INCREMENT_TICK - -#if (TRC_CFG_FREERTOS_VERSION <= TRC_FREERTOS_VERSION_7_4) - -#define traceTASK_INCREMENT_TICK( xTickCount ) \ - if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) { trcKERNEL_HOOKS_INCREMENT_TICK(); } \ - if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE) { trcKERNEL_HOOKS_NEW_TIME(DIV_NEW_TIME, xTickCount + 1); } - -#else - -#define traceTASK_INCREMENT_TICK( xTickCount ) \ - if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || xPendedTicks == 0) { trcKERNEL_HOOKS_INCREMENT_TICK(); } \ - if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE) { trcKERNEL_HOOKS_NEW_TIME(DIV_NEW_TIME, xTickCount + 1); } - -#endif - -/* Called on each task-switch */ -#undef traceTASK_SWITCHED_IN -#define traceTASK_SWITCHED_IN() \ - trcKERNEL_HOOKS_TASK_SWITCH(TRACE_GET_CURRENT_TASK()); - -/* Called on vTaskCreate */ -#undef traceTASK_CREATE -#define traceTASK_CREATE(pxNewTCB) \ - if (pxNewTCB != NULL) \ - { \ - trcKERNEL_HOOKS_TASK_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, TASK, pxNewTCB), TASK, pxNewTCB); \ - } - -/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */ -#undef traceTASK_CREATE_FAILED -#define traceTASK_CREATE_FAILED() \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, TASK, NOT_USED), 0); - -/* Called on vTaskDelete */ -#undef traceTASK_DELETE -#define traceTASK_DELETE( pxTaskToDelete ) \ - { TRACE_ALLOC_CRITICAL_SECTION(); \ - TRACE_ENTER_CRITICAL_SECTION(); \ - trcKERNEL_HOOKS_TASK_DELETE(TRACE_GET_OBJECT_EVENT_CODE(DELETE_OBJ, TRCSUCCESS, TASK, pxTaskToDelete), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_NAME, TRCSUCCESS, TASK, pxTaskToDelete), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_PROP, TRCSUCCESS, TASK, pxTaskToDelete), pxTaskToDelete); \ - TRACE_EXIT_CRITICAL_SECTION(); } - -#if (TRC_CFG_SCHEDULING_ONLY == 0) - -#if defined(configUSE_TICKLESS_IDLE) -#if (configUSE_TICKLESS_IDLE != 0) - -#undef traceLOW_POWER_IDLE_BEGIN -#define traceLOW_POWER_IDLE_BEGIN() \ - { \ - extern uint32_t trace_disable_timestamp; \ - prvTraceStoreLowPower(0); \ - trace_disable_timestamp = 1; \ - } - -#undef traceLOW_POWER_IDLE_END -#define traceLOW_POWER_IDLE_END() \ - { \ - extern uint32_t trace_disable_timestamp; \ - trace_disable_timestamp = 0; \ - prvTraceStoreLowPower(1); \ - } - -#endif /* (configUSE_TICKLESS_IDLE != 0) */ -#endif /* defined(configUSE_TICKLESS_IDLE) */ - -/* Called on vTaskSuspend */ -#undef traceTASK_SUSPEND -#define traceTASK_SUSPEND( pxTaskToSuspend ) \ - trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend); - -/* Called from special case with timer only */ -#undef traceTASK_DELAY_SUSPEND -#define traceTASK_DELAY_SUSPEND( pxTaskToSuspend ) \ - trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend); \ - trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); - -/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */ -#undef traceTASK_DELAY -#define traceTASK_DELAY() \ - trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY, pxCurrentTCB, xTicksToDelay); \ - trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); - -/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */ -#undef traceTASK_DELAY_UNTIL -#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 -#define traceTASK_DELAY_UNTIL(xTimeToWake) \ - trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \ - trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); -#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ -#define traceTASK_DELAY_UNTIL() \ - trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \ - trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); -#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ - -/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */ -#undef traceQUEUE_CREATE -#define traceQUEUE_CREATE( pxNewQueue ) \ - trcKERNEL_HOOKS_OBJECT_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, QUEUE, pxNewQueue), QUEUE, pxNewQueue); - -/* Called in xQueueCreate, if the queue creation fails */ -#undef traceQUEUE_CREATE_FAILED -#define traceQUEUE_CREATE_FAILED( queueType ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, QUEUE, queueType), 0); - -/* Called on vQueueDelete */ -#undef traceQUEUE_DELETE -#define traceQUEUE_DELETE( pxQueue ) \ - { TRACE_ALLOC_CRITICAL_SECTION(); \ - TRACE_ENTER_CRITICAL_SECTION(); \ - trcKERNEL_HOOKS_OBJECT_DELETE(TRACE_GET_OBJECT_EVENT_CODE(DELETE_OBJ, TRCSUCCESS, QUEUE, pxQueue), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_NAME, TRCSUCCESS, QUEUE, pxQueue), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_PROP, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ - TRACE_EXIT_CRITICAL_SECTION(); } - -/* This macro is not necessary as of FreeRTOS v9.0.0 */ -#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) -/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */ -#undef traceCREATE_MUTEX -#define traceCREATE_MUTEX( pxNewQueue ) \ - trcKERNEL_HOOKS_OBJECT_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, QUEUE, pxNewQueue), QUEUE, pxNewQueue); - -/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */ -#undef traceCREATE_MUTEX_FAILED -#define traceCREATE_MUTEX_FAILED() \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, QUEUE, queueQUEUE_TYPE_MUTEX), 0); -#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */ - -/* Called when the Mutex can not be given, since not holder */ -#undef traceGIVE_MUTEX_RECURSIVE_FAILED -#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCFAILED, QUEUE, pxMutex), QUEUE, pxMutex); - -/* Called when a message is sent to a queue */ /* CS IS NEW ! */ -#undef traceQUEUE_SEND -#define traceQUEUE_SEND( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ - trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) == TRACE_CLASS_MUTEX ? (uint8_t)0 : (uint8_t)(pxQueue->uxMessagesWaiting + 1)); - -/* Called when a message failed to be sent to a queue (timeout) */ -#undef traceQUEUE_SEND_FAILED -#define traceQUEUE_SEND_FAILED( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); - -/* Called when the task is blocked due to a send operation on a full queue */ -#undef traceBLOCKING_ON_QUEUE_SEND -#define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); - -/* Called when a message is received from a queue */ -#undef traceQUEUE_RECEIVE -#define traceQUEUE_RECEIVE( pxQueue ) \ - if (isQueueReceiveHookActuallyPeek) \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ - } \ - trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) == TRACE_CLASS_MUTEX ? (uint8_t)TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()) : (uint8_t)(pxQueue->uxMessagesWaiting - 1)); - -/* Called when a receive operation on a queue fails (timeout) */ -#undef traceQUEUE_RECEIVE_FAILED -#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \ - if (isQueueReceiveHookActuallyPeek) \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); \ - } - -/* Called when the task is blocked due to a receive operation on an empty queue */ -#undef traceBLOCKING_ON_QUEUE_RECEIVE -#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \ - if (isQueueReceiveHookActuallyPeek) \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); \ - } \ - if (TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) != TRACE_CLASS_MUTEX) \ - { \ - trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); \ - } - -/* Called on xQueuePeek */ -#undef traceQUEUE_PEEK -#define traceQUEUE_PEEK( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); - -/* Called on xQueuePeek fail/timeout (added in FreeRTOS v9.0.2) */ -#undef traceQUEUE_PEEK_FAILED -#define traceQUEUE_PEEK_FAILED( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); - -/* Called on xQueuePeek blocking (added in FreeRTOS v9.0.2) */ -#undef traceBLOCKING_ON_QUEUE_PEEK -#define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); \ - if (TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) != TRACE_CLASS_MUTEX) \ - { \ - trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); \ - } - -/* Called when a message is sent from interrupt context, e.g., using xQueueSendFromISR */ -#undef traceQUEUE_SEND_FROM_ISR -#define traceQUEUE_SEND_FROM_ISR( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ - trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, pxQueue, (uint8_t)(pxQueue->uxMessagesWaiting + 1)); - -/* Called when a message send from interrupt context fails (since the queue was full) */ -#undef traceQUEUE_SEND_FROM_ISR_FAILED -#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); - -/* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */ -#undef traceQUEUE_RECEIVE_FROM_ISR -#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ - trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, pxQueue, (uint8_t)(pxQueue->uxMessagesWaiting - 1)); - -/* Called when a message receive from interrupt context fails (since the queue was empty) */ -#undef traceQUEUE_RECEIVE_FROM_ISR_FAILED -#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); - -#undef traceQUEUE_REGISTRY_ADD -#define traceQUEUE_REGISTRY_ADD(object, name) prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, object), TRACE_GET_OBJECT_NUMBER(QUEUE, object), name); - -/* Called in vTaskPrioritySet */ -#undef traceTASK_PRIORITY_SET -#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \ - trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_SET, pxTask, uxNewPriority); - -/* Called in vTaskPriorityInherit, which is called by Mutex operations */ -#undef traceTASK_PRIORITY_INHERIT -#define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \ - trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_INHERIT, pxTask, uxNewPriority); - -/* Called in vTaskPriorityDisinherit, which is called by Mutex operations */ -#undef traceTASK_PRIORITY_DISINHERIT -#define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \ - trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_DISINHERIT, pxTask, uxNewPriority); - -/* Called in vTaskResume */ -#undef traceTASK_RESUME -#define traceTASK_RESUME( pxTaskToResume ) \ - trcKERNEL_HOOKS_TASK_RESUME(TASK_RESUME, pxTaskToResume); - -/* Called in vTaskResumeFromISR */ -#undef traceTASK_RESUME_FROM_ISR -#define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) \ - trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR(TASK_RESUME_FROM_ISR, pxTaskToResume); - - -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) - -#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) - -extern void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t size); - -/* MALLOC and FREE are always stored, no matter if they happen inside filtered task */ -#undef traceMALLOC -#define traceMALLOC( pvAddress, uiSize ) \ - if (pvAddress != 0) \ - vTraceStoreMemMangEvent(MEM_MALLOC_SIZE, ( uint32_t ) pvAddress, (int32_t)uiSize); - -#undef traceFREE -#define traceFREE( pvAddress, uiSize ) \ - vTraceStoreMemMangEvent(MEM_FREE_SIZE, ( uint32_t ) pvAddress, -((int32_t)uiSize)); - -#endif /* (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) */ - -#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) - -/* Called in timer.c - xTimerCreate */ -#undef traceTIMER_CREATE -#define traceTIMER_CREATE(tmr) \ - trcKERNEL_HOOKS_OBJECT_CREATE(TIMER_CREATE, TIMER, tmr); - -#undef traceTIMER_CREATE_FAILED -#define traceTIMER_CREATE_FAILED() \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TIMER_CREATE_TRCFAILED, 0); - -/* Note that xCommandID can never be tmrCOMMAND_EXECUTE_CALLBACK (-1) since the trace macro is not called in that case */ -#undef traceTIMER_COMMAND_SEND -#define traceTIMER_COMMAND_SEND(tmr, xCommandID, xOptionalValue, xReturn) \ - if (xCommandID > tmrCOMMAND_START_DONT_TRACE) \ - { \ - if (xCommandID == tmrCOMMAND_CHANGE_PERIOD) \ - { \ - if (xReturn == pdPASS) { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TIMER_CHANGE_PERIOD, TIMER, tmr, xOptionalValue); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TIMER_CHANGE_PERIOD_TRCFAILED, TIMER, tmr, xOptionalValue); \ - } \ - } \ - else if ((xCommandID == tmrCOMMAND_DELETE) && (xReturn == pdPASS)) \ - { \ - trcKERNEL_HOOKS_OBJECT_DELETE(TIMER_DELETE_OBJ, EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr), EVENTGROUP_OBJCLOSE_PROP_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr), TIMER, tmr); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENTGROUP_TIMER + (uint32_t)xCommandID + ((xReturn == pdPASS) ? 0 : (TIMER_CREATE_TRCFAILED - TIMER_CREATE)), TIMER, tmr, xOptionalValue); \ - }\ - } - -#undef traceTIMER_EXPIRED -#define traceTIMER_EXPIRED(tmr) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TIMER_EXPIRED, TIMER, tmr); - -#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) */ - -#if (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) - -#undef tracePEND_FUNC_CALL -#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \ - if (ret == pdPASS){ \ - trcKERNEL_HOOKS_KERNEL_SERVICE(PEND_FUNC_CALL, TASK, xTimerGetTimerDaemonTaskHandle() ); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE(PEND_FUNC_CALL_TRCFAILED, TASK, xTimerGetTimerDaemonTaskHandle() ); \ - } - -#undef tracePEND_FUNC_CALL_FROM_ISR -#define tracePEND_FUNC_CALL_FROM_ISR(func, arg1, arg2, ret) \ - if (! uiInEventGroupSetBitsFromISR) \ - prvTraceStoreKernelCall(PEND_FUNC_CALL_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTimerGetTimerDaemonTaskHandle()) ); \ - uiInEventGroupSetBitsFromISR = 0; - -#endif /* (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) */ - -#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */ - -#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) - -#undef traceEVENT_GROUP_CREATE -#define traceEVENT_GROUP_CREATE(eg) \ - trcKERNEL_HOOKS_OBJECT_CREATE(EVENT_GROUP_CREATE, EVENTGROUP, eg); - -#undef traceEVENT_GROUP_CREATE_FAILED -#define traceEVENT_GROUP_CREATE_FAILED() \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(EVENT_GROUP_CREATE_TRCFAILED, 0); - -#undef traceEVENT_GROUP_DELETE -#define traceEVENT_GROUP_DELETE(eg) \ - { TRACE_ALLOC_CRITICAL_SECTION(); \ - TRACE_ENTER_CRITICAL_SECTION(); \ - trcKERNEL_HOOKS_OBJECT_DELETE(EVENT_GROUP_DELETE_OBJ, EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg), EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg), EVENTGROUP, eg); \ - TRACE_EXIT_CRITICAL_SECTION(); } - -#undef traceEVENT_GROUP_SYNC_BLOCK -#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SYNC_TRCBLOCK, EVENTGROUP, eg, bitsToWaitFor); - -#undef traceEVENT_GROUP_SYNC_END -#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \ - if (wasTimeout) \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SYNC_END_TRCFAILED, EVENTGROUP, eg, bitsToWaitFor); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SYNC_END, EVENTGROUP, eg, bitsToWaitFor); \ - } - -#undef traceEVENT_GROUP_WAIT_BITS_BLOCK -#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_WAIT_BITS_TRCBLOCK, EVENTGROUP, eg, bitsToWaitFor); \ - trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); - -#undef traceEVENT_GROUP_WAIT_BITS_END -#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \ - if (wasTimeout) \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_WAIT_BITS_END_TRCFAILED, EVENTGROUP, eg, bitsToWaitFor); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_WAIT_BITS_END, EVENTGROUP, eg, bitsToWaitFor); \ - } - -#undef traceEVENT_GROUP_CLEAR_BITS -#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_CLEAR_BITS, EVENTGROUP, eg, bitsToClear); - -#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR -#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(EVENT_GROUP_CLEAR_BITS_FROM_ISR, EVENTGROUP, eg, bitsToClear); - -#undef traceEVENT_GROUP_SET_BITS -#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SET_BITS, EVENTGROUP, eg, bitsToSet); - -#undef traceEVENT_GROUP_SET_BITS_FROM_ISR -#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(EVENT_GROUP_SET_BITS_FROM_ISR, EVENTGROUP, eg, bitsToSet); \ - uiInEventGroupSetBitsFromISR = 1; - -#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */ - -#undef traceTASK_NOTIFY_TAKE -#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) -#define traceTASK_NOTIFY_TAKE() \ - if (pxCurrentTCB->eNotifyState == eNotified){ \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE, TASK, pxCurrentTCB, xTicksToWait); \ - } \ - else{ \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCFAILED, TASK, pxCurrentTCB, xTicksToWait); \ - } -#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */ -#define traceTASK_NOTIFY_TAKE() \ - if (pxCurrentTCB->ucNotifyState[ uxIndexToWait ] == taskNOTIFICATION_RECEIVED){ \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE, TASK, pxCurrentTCB, xTicksToWait); \ - }else{ \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCFAILED, TASK, pxCurrentTCB, xTicksToWait);} -#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */ - -#undef traceTASK_NOTIFY_TAKE_BLOCK -#define traceTASK_NOTIFY_TAKE_BLOCK() \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCBLOCK, TASK, pxCurrentTCB, xTicksToWait); \ - trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); - -#undef traceTASK_NOTIFY_WAIT -#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) -#define traceTASK_NOTIFY_WAIT() \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \ - { \ - if (pxCurrentTCB->eNotifyState == eNotified) \ - prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ - else \ - prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCFAILED, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ - } -#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */ -#define traceTASK_NOTIFY_WAIT() \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \ - { \ - if (pxCurrentTCB->ucNotifyState[ uxIndexToWait ] == taskNOTIFICATION_RECEIVED) \ - prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ - else \ - prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCFAILED, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ - } -#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */ - -#undef traceTASK_NOTIFY_WAIT_BLOCK -#define traceTASK_NOTIFY_WAIT_BLOCK() \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \ - prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCBLOCK, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ - trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); - -#undef traceTASK_NOTIFY -#define traceTASK_NOTIFY() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ - prvTraceStoreKernelCall(TRACE_TASK_NOTIFY, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify)); - -#undef traceTASK_NOTIFY_FROM_ISR -#define traceTASK_NOTIFY_FROM_ISR() \ - if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ - prvTraceStoreKernelCall(TRACE_TASK_NOTIFY_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify)); - -#undef traceTASK_NOTIFY_GIVE_FROM_ISR -#define traceTASK_NOTIFY_GIVE_FROM_ISR() \ - if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ - prvTraceStoreKernelCall(TRACE_TASK_NOTIFY_GIVE_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify)); - -#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) - -#undef traceSTREAM_BUFFER_CREATE -#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) \ - trcKERNEL_HOOKS_OBJECT_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, STREAMBUFFER, pxStreamBuffer), STREAMBUFFER, pxStreamBuffer); - -#undef traceSTREAM_BUFFER_CREATE_FAILED -#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, STREAMBUFFER, xIsMessageBuffer), 0); - -#undef traceSTREAM_BUFFER_CREATE_STATIC_FAILED -#define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) \ - traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) - -#undef traceSTREAM_BUFFER_DELETE -#define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) \ - trcKERNEL_HOOKS_OBJECT_DELETE(TRACE_GET_OBJECT_EVENT_CODE(DELETE_OBJ, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_NAME, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_PROP, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); - -#undef traceSTREAM_BUFFER_RESET -#define traceSTREAM_BUFFER_RESET( xStreamBuffer ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(prvGetStreamBufferType(xStreamBuffer) > 0 ? TRACE_MESSAGEBUFFER_RESET : TRACE_STREAMBUFFER_RESET, STREAMBUFFER, xStreamBuffer); \ - trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, 0); - -#undef traceSTREAM_BUFFER_SEND -#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ - trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); - -#undef traceBLOCKING_ON_STREAM_BUFFER_SEND -#define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCBLOCK, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); - -#undef traceSTREAM_BUFFER_SEND_FAILED -#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); - -#undef traceSTREAM_BUFFER_RECEIVE -#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ - trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); - - -#undef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE -#define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCBLOCK, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); - -#undef traceSTREAM_BUFFER_RECEIVE_FAILED -#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) \ - trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); - -#undef traceSTREAM_BUFFER_SEND_FROM_ISR -#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ) \ - if( xReturn > ( size_t ) 0 ) \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ - trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ - } - -#undef traceSTREAM_BUFFER_RECEIVE_FROM_ISR -#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) \ - if( xReceivedLength > ( size_t ) 0 ) \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ - trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ - } \ - else \ - { \ - trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ - } - -#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ - -#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */ - -#endif /*#if TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT */ - -/******************************************************************************/ -/*** Definitions for Streaming mode *******************************************/ -/******************************************************************************/ -#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) - -/******************************************************************************* -* vTraceStoreKernelObjectName -* -* Set the name for a kernel object (defined by its address). -******************************************************************************/ -void vTraceStoreKernelObjectName(void* object, const char* name); - -/******************************************************************************* -* prvIsNewTCB -* -* Tells if this task is already executing, or if there has been a task-switch. -* Assumed to be called within a trace hook in kernel context. -*******************************************************************************/ -uint32_t prvIsNewTCB(void* pNewTCB); - -#define TRACE_GET_CURRENT_TASK() prvTraceGetCurrentTaskHandle() - -/*************************************************************************/ -/* KERNEL SPECIFIC OBJECT CONFIGURATION */ -/*************************************************************************/ - -/******************************************************************************* - * The event codes - should match the offline config file. - ******************************************************************************/ - -/*** Event codes for streaming - should match the Tracealyzer config file *****/ -#define PSF_EVENT_NULL_EVENT 0x00 - -#define PSF_EVENT_TRACE_START 0x01 -#define PSF_EVENT_TS_CONFIG 0x02 -#define PSF_EVENT_OBJ_NAME 0x03 -#define PSF_EVENT_TASK_PRIORITY 0x04 -#define PSF_EVENT_TASK_PRIO_INHERIT 0x05 -#define PSF_EVENT_TASK_PRIO_DISINHERIT 0x06 -#define PSF_EVENT_DEFINE_ISR 0x07 - -#define PSF_EVENT_TASK_CREATE 0x10 -#define PSF_EVENT_QUEUE_CREATE 0x11 -#define PSF_EVENT_SEMAPHORE_BINARY_CREATE 0x12 -#define PSF_EVENT_MUTEX_CREATE 0x13 -#define PSF_EVENT_TIMER_CREATE 0x14 -#define PSF_EVENT_EVENTGROUP_CREATE 0x15 -#define PSF_EVENT_SEMAPHORE_COUNTING_CREATE 0x16 -#define PSF_EVENT_MUTEX_RECURSIVE_CREATE 0x17 -#define PSF_EVENT_STREAMBUFFER_CREATE 0x18 -#define PSF_EVENT_MESSAGEBUFFER_CREATE 0x19 - -#define PSF_EVENT_TASK_DELETE 0x20 -#define PSF_EVENT_QUEUE_DELETE 0x21 -#define PSF_EVENT_SEMAPHORE_DELETE 0x22 -#define PSF_EVENT_MUTEX_DELETE 0x23 -#define PSF_EVENT_TIMER_DELETE 0x24 -#define PSF_EVENT_EVENTGROUP_DELETE 0x25 -#define PSF_EVENT_STREAMBUFFER_DELETE 0x28 -#define PSF_EVENT_MESSAGEBUFFER_DELETE 0x29 - -#define PSF_EVENT_TASK_READY 0x30 -#define PSF_EVENT_NEW_TIME 0x31 -#define PSF_EVENT_NEW_TIME_SCHEDULER_SUSPENDED 0x32 -#define PSF_EVENT_ISR_BEGIN 0x33 -#define PSF_EVENT_ISR_RESUME 0x34 -#define PSF_EVENT_TS_BEGIN 0x35 -#define PSF_EVENT_TS_RESUME 0x36 -#define PSF_EVENT_TASK_ACTIVATE 0x37 - -#define PSF_EVENT_MALLOC 0x38 -#define PSF_EVENT_FREE 0x39 - -#define PSF_EVENT_LOWPOWER_BEGIN 0x3A -#define PSF_EVENT_LOWPOWER_END 0x3B - -#define PSF_EVENT_IFE_NEXT 0x3C -#define PSF_EVENT_IFE_DIRECT 0x3D - -#define PSF_EVENT_TASK_CREATE_FAILED 0x40 -#define PSF_EVENT_QUEUE_CREATE_FAILED 0x41 -#define PSF_EVENT_SEMAPHORE_BINARY_CREATE_FAILED 0x42 -#define PSF_EVENT_MUTEX_CREATE_FAILED 0x43 -#define PSF_EVENT_TIMER_CREATE_FAILED 0x44 -#define PSF_EVENT_EVENTGROUP_CREATE_FAILED 0x45 -#define PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED 0x46 -#define PSF_EVENT_MUTEX_RECURSIVE_CREATE_FAILED 0x47 -#define PSF_EVENT_STREAMBUFFER_CREATE_FAILED 0x49 -#define PSF_EVENT_MESSAGEBUFFER_CREATE_FAILED 0x4A - -#define PSF_EVENT_TIMER_DELETE_FAILED 0x48 - -#define PSF_EVENT_QUEUE_SEND 0x50 -#define PSF_EVENT_SEMAPHORE_GIVE 0x51 -#define PSF_EVENT_MUTEX_GIVE 0x52 - -#define PSF_EVENT_QUEUE_SEND_FAILED 0x53 -#define PSF_EVENT_SEMAPHORE_GIVE_FAILED 0x54 -#define PSF_EVENT_MUTEX_GIVE_FAILED 0x55 - -#define PSF_EVENT_QUEUE_SEND_BLOCK 0x56 -#define PSF_EVENT_SEMAPHORE_GIVE_BLOCK 0x57 -#define PSF_EVENT_MUTEX_GIVE_BLOCK 0x58 - -#define PSF_EVENT_QUEUE_SEND_FROMISR 0x59 -#define PSF_EVENT_SEMAPHORE_GIVE_FROMISR 0x5A - -#define PSF_EVENT_QUEUE_SEND_FROMISR_FAILED 0x5C -#define PSF_EVENT_SEMAPHORE_GIVE_FROMISR_FAILED 0x5D - -#define PSF_EVENT_QUEUE_RECEIVE 0x60 -#define PSF_EVENT_SEMAPHORE_TAKE 0x61 -#define PSF_EVENT_MUTEX_TAKE 0x62 - -#define PSF_EVENT_QUEUE_RECEIVE_FAILED 0x63 -#define PSF_EVENT_SEMAPHORE_TAKE_FAILED 0x64 -#define PSF_EVENT_MUTEX_TAKE_FAILED 0x65 - -#define PSF_EVENT_QUEUE_RECEIVE_BLOCK 0x66 -#define PSF_EVENT_SEMAPHORE_TAKE_BLOCK 0x67 -#define PSF_EVENT_MUTEX_TAKE_BLOCK 0x68 - -#define PSF_EVENT_QUEUE_RECEIVE_FROMISR 0x69 -#define PSF_EVENT_SEMAPHORE_TAKE_FROMISR 0x6A - -#define PSF_EVENT_QUEUE_RECEIVE_FROMISR_FAILED 0x6C -#define PSF_EVENT_SEMAPHORE_TAKE_FROMISR_FAILED 0x6D - -#define PSF_EVENT_QUEUE_PEEK 0x70 -#define PSF_EVENT_SEMAPHORE_PEEK 0x71 -#define PSF_EVENT_MUTEX_PEEK 0x72 - -#define PSF_EVENT_QUEUE_PEEK_FAILED 0x73 -#define PSF_EVENT_SEMAPHORE_PEEK_FAILED 0x74 -#define PSF_EVENT_MUTEX_PEEK_FAILED 0x75 - -#define PSF_EVENT_QUEUE_PEEK_BLOCK 0x76 -#define PSF_EVENT_SEMAPHORE_PEEK_BLOCK 0x77 -#define PSF_EVENT_MUTEX_PEEK_BLOCK 0x78 - -#define PSF_EVENT_TASK_DELAY_UNTIL 0x79 -#define PSF_EVENT_TASK_DELAY 0x7A -#define PSF_EVENT_TASK_SUSPEND 0x7B -#define PSF_EVENT_TASK_RESUME 0x7C -#define PSF_EVENT_TASK_RESUME_FROMISR 0x7D - -#define PSF_EVENT_TIMER_PENDFUNCCALL 0x80 -#define PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR 0x81 -#define PSF_EVENT_TIMER_PENDFUNCCALL_FAILED 0x82 -#define PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR_FAILED 0x83 - -#define PSF_EVENT_USER_EVENT 0x90 - -#define PSF_EVENT_TIMER_START 0xA0 -#define PSF_EVENT_TIMER_RESET 0xA1 -#define PSF_EVENT_TIMER_STOP 0xA2 -#define PSF_EVENT_TIMER_CHANGEPERIOD 0xA3 -#define PSF_EVENT_TIMER_START_FROMISR 0xA4 -#define PSF_EVENT_TIMER_RESET_FROMISR 0xA5 -#define PSF_EVENT_TIMER_STOP_FROMISR 0xA6 -#define PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR 0xA7 -#define PSF_EVENT_TIMER_START_FAILED 0xA8 -#define PSF_EVENT_TIMER_RESET_FAILED 0xA9 -#define PSF_EVENT_TIMER_STOP_FAILED 0xAA -#define PSF_EVENT_TIMER_CHANGEPERIOD_FAILED 0xAB -#define PSF_EVENT_TIMER_START_FROMISR_FAILED 0xAC -#define PSF_EVENT_TIMER_RESET_FROMISR_FAILED 0xAD -#define PSF_EVENT_TIMER_STOP_FROMISR_FAILED 0xAE -#define PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR_FAILED 0xAF - -#define PSF_EVENT_EVENTGROUP_SYNC 0xB0 -#define PSF_EVENT_EVENTGROUP_WAITBITS 0xB1 -#define PSF_EVENT_EVENTGROUP_CLEARBITS 0xB2 -#define PSF_EVENT_EVENTGROUP_CLEARBITS_FROMISR 0xB3 -#define PSF_EVENT_EVENTGROUP_SETBITS 0xB4 -#define PSF_EVENT_EVENTGROUP_SETBITS_FROMISR 0xB5 -#define PSF_EVENT_EVENTGROUP_SYNC_BLOCK 0xB6 -#define PSF_EVENT_EVENTGROUP_WAITBITS_BLOCK 0xB7 -#define PSF_EVENT_EVENTGROUP_SYNC_FAILED 0xB8 -#define PSF_EVENT_EVENTGROUP_WAITBITS_FAILED 0xB9 - -#define PSF_EVENT_QUEUE_SEND_FRONT 0xC0 -#define PSF_EVENT_QUEUE_SEND_FRONT_FAILED 0xC1 -#define PSF_EVENT_QUEUE_SEND_FRONT_BLOCK 0xC2 -#define PSF_EVENT_QUEUE_SEND_FRONT_FROMISR 0xC3 -#define PSF_EVENT_QUEUE_SEND_FRONT_FROMISR_FAILED 0xC4 -#define PSF_EVENT_MUTEX_GIVE_RECURSIVE 0xC5 -#define PSF_EVENT_MUTEX_GIVE_RECURSIVE_FAILED 0xC6 -#define PSF_EVENT_MUTEX_TAKE_RECURSIVE 0xC7 -#define PSF_EVENT_MUTEX_TAKE_RECURSIVE_FAILED 0xC8 - -#define PSF_EVENT_TASK_NOTIFY 0xC9 -#define PSF_EVENT_TASK_NOTIFY_TAKE 0xCA -#define PSF_EVENT_TASK_NOTIFY_TAKE_BLOCK 0xCB -#define PSF_EVENT_TASK_NOTIFY_TAKE_FAILED 0xCC -#define PSF_EVENT_TASK_NOTIFY_WAIT 0xCD -#define PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK 0xCE -#define PSF_EVENT_TASK_NOTIFY_WAIT_FAILED 0xCF -#define PSF_EVENT_TASK_NOTIFY_FROM_ISR 0xD0 -#define PSF_EVENT_TASK_NOTIFY_GIVE_FROM_ISR 0xD1 - -#define PSF_EVENT_TIMER_EXPIRED 0xD2 - -#define PSF_EVENT_STREAMBUFFER_SEND 0xD3 -#define PSF_EVENT_STREAMBUFFER_SEND_BLOCK 0xD4 -#define PSF_EVENT_STREAMBUFFER_SEND_FAILED 0xD5 -#define PSF_EVENT_STREAMBUFFER_RECEIVE 0xD6 -#define PSF_EVENT_STREAMBUFFER_RECEIVE_BLOCK 0xD7 -#define PSF_EVENT_STREAMBUFFER_RECEIVE_FAILED 0xD8 -#define PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR 0xD9 -#define PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR_FAILED 0xDA -#define PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR 0xDB -#define PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR_FAILED 0xDC -#define PSF_EVENT_STREAMBUFFER_RESET 0xDD - -#define PSF_EVENT_MESSAGEBUFFER_SEND 0xDE -#define PSF_EVENT_MESSAGEBUFFER_SEND_BLOCK 0xDF -#define PSF_EVENT_MESSAGEBUFFER_SEND_FAILED 0xE0 -#define PSF_EVENT_MESSAGEBUFFER_RECEIVE 0xE1 -#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_BLOCK 0xE2 -#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_FAILED 0xE3 -#define PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR 0xE4 -#define PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR_FAILED 0xE5 -#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR 0xE6 -#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR_FAILED 0xE7 -#define PSF_EVENT_MESSAGEBUFFER_RESET 0xE8 - -/*** The trace macros for streaming ******************************************/ - -/* A macro that will update the tick count when returning from tickless idle */ -#undef traceINCREASE_TICK_COUNT -/* Note: This can handle time adjustments of max 2^32 ticks, i.e., 35 seconds at 120 MHz. Thus, tick-less idle periods longer than 2^32 ticks will appear "compressed" on the time line.*/ -#define traceINCREASE_TICK_COUNT( xCount ) { extern uint32_t uiTraceTickCount; uiTraceTickCount += xCount; } - -#if (TRC_CFG_INCLUDE_OSTICK_EVENTS == 1) -#define OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) if (uxSchedulerSuspended == (unsigned portBASE_TYPE) pdFALSE) { prvTraceStoreEvent1(PSF_EVENT_NEW_TIME, (uint32_t)(xTickCount + 1)); } -#else -#define OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) -#endif - -/* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */ -#undef traceTASK_INCREMENT_TICK -#if TRC_CFG_FREERTOS_VERSION <= TRC_FREERTOS_VERSION_7_4 -#define traceTASK_INCREMENT_TICK( xTickCount ) \ - if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) { extern uint32_t uiTraceTickCount; uiTraceTickCount++; } \ - OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) -#else -#define traceTASK_INCREMENT_TICK( xTickCount ) \ - if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxPendedTicks == 0) { extern uint32_t uiTraceTickCount; uiTraceTickCount++; } \ - OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) -#endif /* TRC_CFG_FREERTOS_VERSION <= TRC_FREERTOS_VERSION_7_4 */ - -/* Called on each task-switch */ -#undef traceTASK_SWITCHED_IN -#define traceTASK_SWITCHED_IN() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - { \ - if (prvIsNewTCB(pxCurrentTCB)) \ - { \ - prvTraceStoreEvent2(PSF_EVENT_TASK_ACTIVATE, (uint32_t)pxCurrentTCB, pxCurrentTCB->uxPriority); \ - } \ - } - -/* Called for each task that becomes ready */ -#if (TRC_CFG_INCLUDE_READY_EVENTS == 1) -#undef traceMOVED_TASK_TO_READY_STATE -#define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_READY, (uint32_t)pxTCB); -#endif - -#undef traceTASK_CREATE -#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 -#define traceTASK_CREATE(pxNewTCB) \ - if (pxNewTCB != NULL) \ - { \ - prvTraceSaveSymbol(pxNewTCB, pxNewTCB->pcTaskName); \ - prvTraceSaveObjectData(pxNewTCB, pxNewTCB->uxPriority); \ - prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, pxNewTCB->pcTaskName, pxNewTCB); \ - TRACE_SET_OBJECT_FILTER(TASK, pxNewTCB, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxNewTCB) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_CREATE, (uint32_t)pxNewTCB, pxNewTCB->uxPriority); \ - } -#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ -#define traceTASK_CREATE(pxNewTCB) \ - if (pxNewTCB != NULL) \ - { \ - prvTraceSaveSymbol(pxNewTCB, (const char*)pcName); \ - prvTraceSaveObjectData(pxNewTCB, uxPriority); \ - prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, (const char*)pcName, pxNewTCB); \ - TRACE_SET_OBJECT_FILTER(TASK, pxNewTCB, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxNewTCB) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_CREATE, (uint32_t)pxNewTCB, uxPriority); \ - } -#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ - -/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */ -#undef traceTASK_CREATE_FAILED -#define traceTASK_CREATE_FAILED() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent0(PSF_EVENT_TASK_CREATE_FAILED); - -/* Called on vTaskDelete */ -#undef traceTASK_DELETE // We don't allow for filtering out "delete" events. They are important and not very frequent. Moreover, we can't exclude create events, so this should be symmetrical. -#define traceTASK_DELETE( pxTaskToDelete ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToDelete) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_DELETE, (uint32_t)pxTaskToDelete, (pxTaskToDelete != NULL) ? (pxTaskToDelete->uxPriority) : 0); \ - prvTraceDeleteSymbol(pxTaskToDelete); \ - prvTraceDeleteObjectData(pxTaskToDelete); - -#if (TRC_CFG_SCHEDULING_ONLY == 0) - -#if (defined(configUSE_TICKLESS_IDLE) && configUSE_TICKLESS_IDLE != 0) - -#undef traceLOW_POWER_IDLE_BEGIN -#define traceLOW_POWER_IDLE_BEGIN() \ - { \ - prvTraceStoreEvent1(PSF_EVENT_LOWPOWER_BEGIN, xExpectedIdleTime); \ - } - -#undef traceLOW_POWER_IDLE_END -#define traceLOW_POWER_IDLE_END() \ - { \ - prvTraceStoreEvent0(PSF_EVENT_LOWPOWER_END); \ - } - -#endif /* (defined(configUSE_TICKLESS_IDLE) && configUSE_TICKLESS_IDLE != 0) */ - -/* Called on vTaskSuspend */ -#undef traceTASK_SUSPEND -#define traceTASK_SUSPEND( pxTaskToSuspend ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToSuspend) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_SUSPEND, (uint32_t)pxTaskToSuspend); - -/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */ -#undef traceTASK_DELAY -#define traceTASK_DELAY() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_DELAY, xTicksToDelay); - -/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */ -#undef traceTASK_DELAY_UNTIL -#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 -#define traceTASK_DELAY_UNTIL(xTimeToWake) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_DELAY_UNTIL, (uint32_t)xTimeToWake); -#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ -#define traceTASK_DELAY_UNTIL() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_DELAY_UNTIL, (uint32_t)xTimeToWake); -#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ - -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) -#define traceQUEUE_CREATE_HELPER() \ - case queueQUEUE_TYPE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE, (uint32_t)pxNewQueue); \ - break; \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_RECURSIVE_CREATE, (uint32_t)pxNewQueue); \ - break; -#else -#define traceQUEUE_CREATE_HELPER() -#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */ - -/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */ -#undef traceQUEUE_CREATE -#define traceQUEUE_CREATE( pxNewQueue )\ - TRACE_SET_OBJECT_FILTER(QUEUE, pxNewQueue, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - { \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxNewQueue) & CurrentFilterMask) \ - { \ - switch (pxNewQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(PSF_EVENT_QUEUE_CREATE, (uint32_t)pxNewQueue, uxQueueLength); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - prvTraceStoreEvent1(PSF_EVENT_SEMAPHORE_BINARY_CREATE, (uint32_t)pxNewQueue); \ - break; \ - traceQUEUE_CREATE_HELPER() \ - } \ - } \ - } - -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) -#define traceQUEUE_CREATE_FAILED_HELPER() \ - case queueQUEUE_TYPE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE_FAILED, 0); \ - break; \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_RECURSIVE_CREATE_FAILED, 0); \ - break; -#else -#define traceQUEUE_CREATE_FAILED_HELPER() -#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */ - -/* Called in xQueueCreate, if the queue creation fails */ -#undef traceQUEUE_CREATE_FAILED -#define traceQUEUE_CREATE_FAILED( queueType ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - { \ - switch (queueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(PSF_EVENT_QUEUE_CREATE_FAILED, 0, uxQueueLength); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - prvTraceStoreEvent1(PSF_EVENT_SEMAPHORE_BINARY_CREATE_FAILED, 0); \ - break; \ - traceQUEUE_CREATE_FAILED_HELPER() \ - } \ - } - -#undef traceQUEUE_DELETE // We don't allow for filtering out "delete" events. They are important and not very frequent. Moreover, we can't exclude create events, so this should be symmetrical. -#define traceQUEUE_DELETE( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - { \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - { \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(PSF_EVENT_QUEUE_DELETE, (uint32_t)pxQueue, (pxQueue != NULL) ? (pxQueue->uxMessagesWaiting) : 0); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent2(PSF_EVENT_MUTEX_DELETE, (uint32_t)pxQueue, (pxQueue != NULL) ? (pxQueue->uxMessagesWaiting) : 0); \ - break; \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_DELETE, (uint32_t)pxQueue, (pxQueue != NULL) ? (pxQueue->uxMessagesWaiting) : 0); \ - break; \ - } \ - } \ - } \ - prvTraceDeleteSymbol(pxQueue); - -/* Called in xQueueCreateCountingSemaphore, if the queue creation fails */ -#undef traceCREATE_COUNTING_SEMAPHORE -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) -#define traceCREATE_COUNTING_SEMAPHORE() \ - TRACE_SET_OBJECT_FILTER(QUEUE, xHandle, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, xHandle) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)xHandle, uxMaxCount) -#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_OR_7_6) -#define traceCREATE_COUNTING_SEMAPHORE() \ - TRACE_SET_OBJECT_FILTER(QUEUE, xHandle, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, xHandle) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)xHandle, uxInitialCount); -#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4) -#define traceCREATE_COUNTING_SEMAPHORE() \ - TRACE_SET_OBJECT_FILTER(QUEUE, xHandle, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, xHandle) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)xHandle, uxCountValue); -#else -#define traceCREATE_COUNTING_SEMAPHORE() \ - TRACE_SET_OBJECT_FILTER(QUEUE, pxHandle, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxHandle) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)pxHandle, uxCountValue); -#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X */ - -#undef traceCREATE_COUNTING_SEMAPHORE_FAILED -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) -#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxMaxCount); -#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_OR_7_6) -#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxInitialCount); -#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4) -#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxCountValue); -#else -#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxCountValue); -#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X */ - - -/* This macro is not necessary as of FreeRTOS v9.0.0 */ -#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) -/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */ -#undef traceCREATE_MUTEX -#define traceCREATE_MUTEX( pxNewQueue ) \ - TRACE_SET_OBJECT_FILTER(QUEUE, pxNewQueue, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - { \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxNewQueue) & CurrentFilterMask) \ - { \ - switch (pxNewQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE, (uint32_t)pxNewQueue); \ - break; \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_RECURSIVE_CREATE, (uint32_t)pxNewQueue); \ - break; \ - } \ - }\ - } - -/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */ -#undef traceCREATE_MUTEX_FAILED -#define traceCREATE_MUTEX_FAILED() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE_FAILED, 0); -#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */ - -/* Called when a message is sent to a queue */ /* CS IS NEW ! */ -#undef traceQUEUE_SEND -#define traceQUEUE_SEND( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND : PSF_EVENT_QUEUE_SEND_FRONT, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_GIVE, (uint32_t)pxQueue); \ - break; \ - } - -/* Called when a message failed to be sent to a queue (timeout) */ -#undef traceQUEUE_SEND_FAILED -#define traceQUEUE_SEND_FAILED( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FAILED : PSF_EVENT_QUEUE_SEND_FRONT_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_GIVE_FAILED, (uint32_t)pxQueue); \ - break; \ - } - -/* Called when the task is blocked due to a send operation on a full queue */ -#undef traceBLOCKING_ON_QUEUE_SEND -#define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_BLOCK : PSF_EVENT_QUEUE_SEND_FRONT_BLOCK, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_BLOCK, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_GIVE_BLOCK, (uint32_t)pxQueue); \ - break; \ - } - -/**************************************************************************/ -/* Makes sure xQueueGiveFromISR also has a xCopyPosition parameter */ -/**************************************************************************/ -/* Helpers needed to correctly expand names */ -#define TZ__CAT2(a,b) a ## b -#define TZ__CAT(a,b) TZ__CAT2(a, b) - -/* Expands name if this header is included... uxQueueType must be a macro that only exists in queue.c or whatever, and it must expand to nothing or to something that's valid in identifiers */ -#define xQueueGiveFromISR(a,b) TZ__CAT(xQueueGiveFromISR__, uxQueueType) (a,b) - -/* If in queue.c, the "uxQueueType" macro expands to "pcHead". queueSEND_TO_BACK is the value we need to send in */ -#define xQueueGiveFromISR__pcHead(__a, __b) MyWrapper(__a, __b, const BaseType_t xCopyPosition); \ -BaseType_t xQueueGiveFromISR(__a, __b) { return MyWrapper(xQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK); } \ -BaseType_t MyWrapper(__a, __b, const BaseType_t xCopyPosition) - -/* If not in queue.c, "uxQueueType" isn't expanded */ -#define xQueueGiveFromISR__uxQueueType(__a, __b) xQueueGiveFromISR(__a,__b) - -/**************************************************************************/ -/* End of xQueueGiveFromISR fix */ -/**************************************************************************/ - -/* Called when a message is sent from interrupt context, e.g., using xQueueSendFromISR */ -#undef traceQUEUE_SEND_FROM_ISR -#define traceQUEUE_SEND_FROM_ISR( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FROMISR : PSF_EVENT_QUEUE_SEND_FRONT_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \ - break; \ - } - -/* Called when a message send from interrupt context fails (since the queue was full) */ -#undef traceQUEUE_SEND_FROM_ISR_FAILED -#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FROMISR_FAILED : PSF_EVENT_QUEUE_SEND_FRONT_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ - break; \ - } - -/* Called when a message is received from a queue */ -#undef traceQUEUE_RECEIVE -#define traceQUEUE_RECEIVE( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - if (isQueueReceiveHookActuallyPeek) \ - prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \ - else\ - prvTraceStoreEvent3(PSF_EVENT_QUEUE_RECEIVE, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - if (isQueueReceiveHookActuallyPeek) \ - prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \ - else \ - prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_TAKE, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - if (isQueueReceiveHookActuallyPeek) \ - prvTraceStoreEvent2(PSF_EVENT_MUTEX_PEEK, (uint32_t)pxQueue, xTicksToWait); \ - else \ - prvTraceStoreEvent2(PSF_EVENT_MUTEX_TAKE, (uint32_t)pxQueue, xTicksToWait); \ - break; \ - } - -/* Called when a receive operation on a queue fails (timeout) */ -#undef traceQUEUE_RECEIVE_FAILED -#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_QUEUE_PEEK_FAILED : PSF_EVENT_QUEUE_RECEIVE_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_SEMAPHORE_PEEK_FAILED : PSF_EVENT_SEMAPHORE_TAKE_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent2(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_FAILED : PSF_EVENT_MUTEX_TAKE_FAILED, (uint32_t)pxQueue, xTicksToWait); \ - break; \ - } - -/* Called when the task is blocked due to a receive operation on an empty queue */ -#undef traceBLOCKING_ON_QUEUE_RECEIVE -#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_QUEUE_PEEK_BLOCK : PSF_EVENT_QUEUE_RECEIVE_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_SEMAPHORE_PEEK_BLOCK : PSF_EVENT_SEMAPHORE_TAKE_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent2(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_BLOCK : PSF_EVENT_MUTEX_TAKE_BLOCK, (uint32_t)pxQueue, xTicksToWait); \ - break; \ - } - -#if (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1) -/* Called when a peek operation on a queue fails (timeout) */ -#undef traceQUEUE_PEEK_FAILED -#define traceQUEUE_PEEK_FAILED( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent2(PSF_EVENT_MUTEX_PEEK_FAILED, (uint32_t)pxQueue, xTicksToWait); \ - break; \ - } - -/* Called when the task is blocked due to a peek operation on an empty queue */ -#undef traceBLOCKING_ON_QUEUE_PEEK -#define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent2(PSF_EVENT_MUTEX_PEEK_BLOCK, (uint32_t)pxQueue, xTicksToWait); \ - break; \ - } - -#endif /* (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1) */ - -/* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */ -#undef traceQUEUE_RECEIVE_FROM_ISR -#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(PSF_EVENT_QUEUE_RECEIVE_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting - 1); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_TAKE_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting - 1); \ - break; \ - } - -/* Called when a message receive from interrupt context fails (since the queue was empty) */ -#undef traceQUEUE_RECEIVE_FROM_ISR_FAILED -#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent2(PSF_EVENT_QUEUE_RECEIVE_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_TAKE_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ - break; \ - } - -/* Called on xQueuePeek */ -#undef traceQUEUE_PEEK -#define traceQUEUE_PEEK( pxQueue ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ - switch (pxQueue->ucQueueType) \ - { \ - case queueQUEUE_TYPE_BASE: \ - prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ - case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ - prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ - break; \ - case queueQUEUE_TYPE_MUTEX: \ - case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ - prvTraceStoreEvent1(PSF_EVENT_MUTEX_PEEK, (uint32_t)pxQueue); \ - break; \ - } - -/* Called in vTaskPrioritySet */ -#undef traceTASK_PRIORITY_SET -#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \ - prvTraceSaveObjectData(pxTask, uxNewPriority); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxTask) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_PRIORITY, (uint32_t)pxTask, uxNewPriority); - -/* Called in vTaskPriorityInherit, which is called by Mutex operations */ -#undef traceTASK_PRIORITY_INHERIT -#define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxTask) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_PRIO_INHERIT, (uint32_t)pxTask, uxNewPriority); - -/* Called in vTaskPriorityDisinherit, which is called by Mutex operations */ -#undef traceTASK_PRIORITY_DISINHERIT -#define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxTask) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_PRIO_DISINHERIT, (uint32_t)pxTask, uxNewPriority); - -/* Called in vTaskResume */ -#undef traceTASK_RESUME -#define traceTASK_RESUME( pxTaskToResume ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToResume) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_RESUME, (uint32_t)pxTaskToResume); - -/* Called in vTaskResumeFromISR */ -#undef traceTASK_RESUME_FROM_ISR -#define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToResume) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_RESUME_FROMISR, (uint32_t)pxTaskToResume); - -#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) - -#undef traceMALLOC -#define traceMALLOC( pvAddress, uiSize ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_MALLOC, (uint32_t)pvAddress, uiSize); - -#undef traceFREE -#define traceFREE( pvAddress, uiSize ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_FREE, (uint32_t)pvAddress, (uint32_t)(0 - uiSize)); /* "0 -" instead of just "-" to get rid of a warning... */ - -#endif /* (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) */ - -#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) - -/* Called in timer.c - xTimerCreate */ -#undef traceTIMER_CREATE -#define traceTIMER_CREATE(tmr) \ - TRACE_SET_OBJECT_FILTER(TIMER, tmr, CurrentFilterGroup); \ - prvTraceSaveSymbol(tmr, tmr->pcTimerName); \ - prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, tmr->pcTimerName, tmr); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TIMER, tmr) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TIMER_CREATE, (uint32_t)tmr, tmr->xTimerPeriodInTicks); - -#undef traceTIMER_CREATE_FAILED -#define traceTIMER_CREATE_FAILED() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent0(PSF_EVENT_TIMER_CREATE_FAILED); - -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) -#define traceTIMER_COMMAND_SEND_8_0_CASES(tmr) \ - case tmrCOMMAND_RESET: \ - prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_RESET : PSF_EVENT_TIMER_RESET_FAILED, (uint32_t)tmr, xOptionalValue); \ - break; \ - case tmrCOMMAND_START_FROM_ISR: \ - prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_START_FROMISR : PSF_EVENT_TIMER_START_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \ - break; \ - case tmrCOMMAND_RESET_FROM_ISR: \ - prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_RESET_FROMISR : PSF_EVENT_TIMER_RESET_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \ - break; \ - case tmrCOMMAND_STOP_FROM_ISR: \ - prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_STOP_FROMISR : PSF_EVENT_TIMER_STOP_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \ - break; \ - case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR: \ - prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR : PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \ - break; -#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X */ -#define traceTIMER_COMMAND_SEND_8_0_CASES(tmr) -#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X */ - -/* Note that xCommandID can never be tmrCOMMAND_EXECUTE_CALLBACK (-1) since the trace macro is not called in that case */ -#undef traceTIMER_COMMAND_SEND -#define traceTIMER_COMMAND_SEND(tmr, xCommandID, xOptionalValue, xReturn) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TIMER, tmr) & CurrentFilterMask) \ - switch(xCommandID) \ - { \ - case tmrCOMMAND_START: \ - prvTraceStoreEvent1((xReturn == pdPASS) ? PSF_EVENT_TIMER_START : PSF_EVENT_TIMER_START_FAILED, (uint32_t)tmr); \ - break; \ - case tmrCOMMAND_STOP: \ - prvTraceStoreEvent1((xReturn == pdPASS) ? PSF_EVENT_TIMER_STOP : PSF_EVENT_TIMER_STOP_FAILED, (uint32_t)tmr); \ - break; \ - case tmrCOMMAND_CHANGE_PERIOD: \ - prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_CHANGEPERIOD : PSF_EVENT_TIMER_CHANGEPERIOD_FAILED, (uint32_t)tmr, xOptionalValue); \ - break; \ - case tmrCOMMAND_DELETE: \ - prvTraceStoreEvent1((xReturn == pdPASS) ? PSF_EVENT_TIMER_DELETE : PSF_EVENT_TIMER_DELETE_FAILED, (uint32_t)tmr); \ - break; \ - traceTIMER_COMMAND_SEND_8_0_CASES(tmr) \ - } - -#undef traceTIMER_EXPIRED -#define traceTIMER_EXPIRED(tmr) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TIMER, tmr) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TIMER_EXPIRED, (uint32_t)tmr->pxCallbackFunction, (uint32_t)tmr->pvTimerID); - -#endif /* #if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) */ - - -#if (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) - -#undef tracePEND_FUNC_CALL -#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \ - prvTraceStoreEvent1((ret == pdPASS) ? PSF_EVENT_TIMER_PENDFUNCCALL : PSF_EVENT_TIMER_PENDFUNCCALL_FAILED, (uint32_t)func); - -#undef tracePEND_FUNC_CALL_FROM_ISR -#define tracePEND_FUNC_CALL_FROM_ISR(func, arg1, arg2, ret) \ - prvTraceStoreEvent1((ret == pdPASS) ? PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR : PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR_FAILED, (uint32_t)func); - -#endif /* (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) */ - -#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) - -#undef traceEVENT_GROUP_CREATE -#define traceEVENT_GROUP_CREATE(eg) \ - TRACE_SET_OBJECT_FILTER(EVENTGROUP, eg, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_EVENTGROUP_CREATE, (uint32_t)eg); - -#undef traceEVENT_GROUP_DELETE -#define traceEVENT_GROUP_DELETE(eg) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_EVENTGROUP_DELETE, (uint32_t)eg); \ - prvTraceDeleteSymbol(eg); - -#undef traceEVENT_GROUP_CREATE_FAILED -#define traceEVENT_GROUP_CREATE_FAILED() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent0(PSF_EVENT_EVENTGROUP_CREATE_FAILED); - -#undef traceEVENT_GROUP_SYNC_BLOCK -#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_SYNC_BLOCK, (uint32_t)eg, bitsToWaitFor); - -#undef traceEVENT_GROUP_SYNC_END -#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent2((wasTimeout != pdTRUE) ? PSF_EVENT_EVENTGROUP_SYNC : PSF_EVENT_EVENTGROUP_SYNC_FAILED, (uint32_t)eg, bitsToWaitFor); - -#undef traceEVENT_GROUP_WAIT_BITS_BLOCK -#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_WAITBITS_BLOCK, (uint32_t)eg, bitsToWaitFor); - -#undef traceEVENT_GROUP_WAIT_BITS_END -#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent2((wasTimeout != pdTRUE) ? PSF_EVENT_EVENTGROUP_WAITBITS : PSF_EVENT_EVENTGROUP_WAITBITS_FAILED, (uint32_t)eg, bitsToWaitFor); - -#undef traceEVENT_GROUP_CLEAR_BITS -#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_CLEARBITS, (uint32_t)eg, bitsToClear); - -#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR -#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_CLEARBITS_FROMISR, (uint32_t)eg, bitsToClear); - -#undef traceEVENT_GROUP_SET_BITS -#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_SETBITS, (uint32_t)eg, bitsToSet); - -#undef traceEVENT_GROUP_SET_BITS_FROM_ISR -#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \ - if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_SETBITS_FROMISR, (uint32_t)eg, bitsToSet); - -#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */ - -#undef traceTASK_NOTIFY_TAKE -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) -#define traceTASK_NOTIFY_TAKE() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ - if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE, (uint32_t)pxCurrentTCB, xTicksToWait); \ - else \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} -#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ -#define traceTASK_NOTIFY_TAKE() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ - if (pxCurrentTCB->eNotifyState == eNotified) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE, (uint32_t)pxCurrentTCB, xTicksToWait); \ - else \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} -#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ - -#undef traceTASK_NOTIFY_TAKE_BLOCK -#define traceTASK_NOTIFY_TAKE_BLOCK() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_BLOCK, (uint32_t)pxCurrentTCB, xTicksToWait); - -#undef traceTASK_NOTIFY_WAIT -#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) -#define traceTASK_NOTIFY_WAIT() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ - if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT, (uint32_t)pxCurrentTCB, xTicksToWait); \ - else \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} -#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ -#define traceTASK_NOTIFY_WAIT() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ - if (pxCurrentTCB->eNotifyState == eNotified) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT, (uint32_t)pxCurrentTCB, xTicksToWait); \ - else \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} -#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ - -#undef traceTASK_NOTIFY_WAIT_BLOCK -#define traceTASK_NOTIFY_WAIT_BLOCK() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK, (uint32_t)pxCurrentTCB, xTicksToWait); - -#undef traceTASK_NOTIFY -#define traceTASK_NOTIFY() \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY, (uint32_t)xTaskToNotify); - -#undef traceTASK_NOTIFY_FROM_ISR -#define traceTASK_NOTIFY_FROM_ISR() \ - if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY_FROM_ISR, (uint32_t)xTaskToNotify); - -#undef traceTASK_NOTIFY_GIVE_FROM_ISR -#define traceTASK_NOTIFY_GIVE_FROM_ISR() \ - if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ - prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY_GIVE_FROM_ISR, (uint32_t)xTaskToNotify); - -#undef traceQUEUE_REGISTRY_ADD -#define traceQUEUE_REGISTRY_ADD(object, name) \ - prvTraceSaveSymbol(object, (const char*)name); \ - prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, name, object); - -#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) - -#undef traceSTREAM_BUFFER_CREATE -#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) \ - TRACE_SET_OBJECT_FILTER(STREAMBUFFER, pxStreamBuffer, CurrentFilterGroup); \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, pxStreamBuffer) & CurrentFilterMask) \ - prvTraceStoreEvent2(xIsMessageBuffer == 1 ? PSF_EVENT_MESSAGEBUFFER_CREATE : PSF_EVENT_STREAMBUFFER_CREATE, (uint32_t)pxStreamBuffer, xBufferSizeBytes); - -#undef traceSTREAM_BUFFER_CREATE_FAILED -#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - prvTraceStoreEvent2(xIsMessageBuffer == 1 ? PSF_EVENT_MESSAGEBUFFER_CREATE_FAILED : PSF_EVENT_STREAMBUFFER_CREATE_FAILED, 0 , xBufferSizeBytes); - -#undef traceSTREAM_BUFFER_CREATE_STATIC_FAILED -#define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) \ - traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) - -#undef traceSTREAM_BUFFER_DELETE -#define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, pxStreamBuffer) & CurrentFilterMask) \ - prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_DELETE : PSF_EVENT_STREAMBUFFER_DELETE, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ - prvTraceDeleteSymbol(xStreamBuffer); - -#undef traceSTREAM_BUFFER_RESET -#define traceSTREAM_BUFFER_RESET( xStreamBuffer ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ - prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RESET : PSF_EVENT_STREAMBUFFER_RESET, (uint32_t)xStreamBuffer, 0); - -#undef traceSTREAM_BUFFER_SEND -#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ - prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND : PSF_EVENT_STREAMBUFFER_SEND, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); - -#undef traceBLOCKING_ON_STREAM_BUFFER_SEND -#define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ - prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_BLOCK : PSF_EVENT_STREAMBUFFER_SEND_BLOCK, (uint32_t)xStreamBuffer); - -#undef traceSTREAM_BUFFER_SEND_FAILED -#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ - prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FAILED : PSF_EVENT_STREAMBUFFER_SEND_FAILED, (uint32_t)xStreamBuffer); - -#undef traceSTREAM_BUFFER_RECEIVE -#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ - prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE: PSF_EVENT_STREAMBUFFER_RECEIVE, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); - -#undef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE -#define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ - prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_BLOCK: PSF_EVENT_STREAMBUFFER_RECEIVE_BLOCK, (uint32_t)xStreamBuffer); - -#undef traceSTREAM_BUFFER_RECEIVE_FAILED -#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) \ - if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ - prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FAILED: PSF_EVENT_STREAMBUFFER_RECEIVE_FAILED, (uint32_t)xStreamBuffer); - -#undef traceSTREAM_BUFFER_SEND_FROM_ISR -#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ) \ - if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ - { \ - if ( xReturn > ( size_t ) 0 ) \ - { \ - prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR : PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ - } \ - else \ - { \ - prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR_FAILED : PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR_FAILED, (uint32_t)xStreamBuffer); \ - } \ - } - -#undef traceSTREAM_BUFFER_RECEIVE_FROM_ISR -#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) \ -if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ - { \ - if ( xReceivedLength > ( size_t ) 0 ) \ - { \ - prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR : PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ - } \ - else \ - { \ - prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR_FAILED : PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR_FAILED, (uint32_t)xStreamBuffer); \ - } \ - } - -#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ - -#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */ - -#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ - -#else /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ - -/* When recorder is disabled */ -#define vTraceSetQueueName(object, name) -#define vTraceSetSemaphoreName(object, name) -#define vTraceSetMutexName(object, name) -#define vTraceSetEventGroupName(object, name) -#define vTraceSetStreamBufferName(object, name) -#define vTraceSetMessageBufferName(object, name) - -#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ - -#ifdef __cplusplus -} -#endif - -#endif /* TRC_KERNEL_PORT_H */ -- 2.39.5