]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c
Sync FreeRTOS-Labs -CLI -TCP -Trace with the version in FreeRTOS-Plus.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / Common / phyHandling.c
index 47757e3bddb62d233ac94d3ad9ccc82e91d4a3f0..fa76959427f5bb5145ecdf1db68d91106f6a6491 100644 (file)
@@ -1,28 +1,3 @@
-/*\r
- * FreeRTOS+TCP 191100 experimental\r
- * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
- * this software and associated documentation files (the "Software"), to deal in\r
- * the Software without restriction, including without limitation the rights to\r
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
- * the Software, and to permit persons to whom the Software is furnished to do so,\r
- * subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included in all\r
- * copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- *\r
- * http://aws.amazon.com/freertos\r
- * http://www.FreeRTOS.org\r
- */\r
-\r
 /*\r
  * Handling of Ethernet PHY's\r
  * PHY's communicate with an EMAC either through\r
 #endif\r
 \r
 #ifndef        ipconfigPHY_LS_HIGH_CHECK_TIME_MS\r
-       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       /* Check if the LinkStatus in the PHY is still high after 15 seconds of not\r
        receiving packets. */\r
-       #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS       15000\r
+       #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS       15000uL\r
 #endif\r
 \r
 #ifndef        ipconfigPHY_LS_LOW_CHECK_TIME_MS\r
-       /* Check if the LinkSStatus in the PHY is still low every second. */\r
-       #define ipconfigPHY_LS_LOW_CHECK_TIME_MS        1000\r
+       /* Check if the LinkStatus in the PHY is still low every second. */\r
+       #define ipconfigPHY_LS_LOW_CHECK_TIME_MS        1000uL\r
+#endif\r
+\r
+/* As the following 3 macro's are OK in most situations, and so they're not\r
+included in 'FreeRTOSIPConfigDefaults.h'.\r
+Users can change their values in the project's 'FreeRTOSIPConfig.h'. */\r
+#ifndef phyPHY_MAX_RESET_TIME_MS\r
+       #define phyPHY_MAX_RESET_TIME_MS                        1000uL\r
+#endif\r
+\r
+#ifndef phyPHY_MAX_NEGOTIATE_TIME_MS\r
+       #define phyPHY_MAX_NEGOTIATE_TIME_MS            3000uL\r
+#endif\r
+\r
+#ifndef phySHORT_DELAY_MS\r
+       #define phySHORT_DELAY_MS                                       50uL\r
 #endif\r
 \r
 /* Naming and numbering of basic PHY registers. */\r
  * Description of all capabilities that can be advertised to\r
  * the peer (usually a switch or router).\r
  */\r
-#define phyADVERTISE_CSMA                      0x0001u /* Only selector supported. */\r
+\r
+#define phyADVERTISE_CSMA                      0x0001u /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */\r
 #define phyADVERTISE_10HALF                    0x0020u /* Try for 10mbps half-duplex. */\r
 #define phyADVERTISE_10FULL                    0x0040u /* Try for 10mbps full-duplex. */\r
 #define phyADVERTISE_100HALF           0x0080u /* Try for 100mbps half-duplex. */\r
 #define phyADVERTISE_100FULL           0x0100u /* Try for 100mbps full-duplex. */\r
 \r
 #define phyADVERTISE_ALL                       ( phyADVERTISE_10HALF | phyADVERTISE_10FULL | \\r
-                                                                         phyADVERTISE_100HALF | phyADVERTISE_100FULL )\r
+                                                                         phyADVERTISE_100HALF | phyADVERTISE_100FULL | \\r
+                                                                         phyADVERTISE_CSMA )\r
 \r
-/* Send a reset commando to a set of PHY-ports. */\r
+/* Send a reset command to a set of PHY-ports. */\r
 static uint32_t xPhyReset( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask );\r
 \r
 static BaseType_t xHas_1F_PHYSPCS( uint32_t ulPhyID )\r
@@ -224,7 +216,7 @@ BaseType_t xPhyAddress;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-/* Send a reset commando to a set of PHY-ports. */\r
+/* Send a reset command to a set of PHY-ports. */\r
 static uint32_t xPhyReset( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )\r
 {\r
 uint32_t ulDoneMask, ulConfig;\r
@@ -232,7 +224,7 @@ TickType_t xRemainingTime;
 TimeOut_t xTimer;\r
 BaseType_t xPhyIndex;\r
 \r
-       /* A bit-mask ofPHY ports that are ready. */\r
+       /* A bit-mask of PHY ports that are ready. */\r
        ulDoneMask = 0ul;\r
 \r
        /* Set the RESET bits high. */\r
@@ -245,7 +237,7 @@ BaseType_t xPhyIndex;
                pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig | phyBMCR_RESET );\r
        }\r
 \r
-       xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( 1000UL );\r
+       xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_RESET_TIME_MS );\r
        vTaskSetTimeOutState( &xTimer );\r
 \r
        /* The reset should last less than a second. */\r
@@ -272,19 +264,23 @@ BaseType_t xPhyIndex;
                        break;\r
                }\r
                /* Block for a while */\r
-               vTaskDelay( pdMS_TO_TICKS( 50ul ) );\r
+               vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );\r
        }\r
 \r
        /* Clear the reset bits. */\r
        for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )\r
        {\r
-       BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];\r
+               if( ( ulDoneMask & ( 1ul << xPhyIndex ) ) == 0uL )\r
+               {\r
+               BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];\r
 \r
-               pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );\r
-               pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig & ~phyBMCR_RESET );\r
+                       /* The reset operation timed out, clear the bit manually. */\r
+                       pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );\r
+                       pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig & ~phyBMCR_RESET );\r
+               }\r
        }\r
 \r
-       vTaskDelay( pdMS_TO_TICKS( 50ul ) );\r
+       vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );\r
 \r
        return ulDoneMask;\r
 }\r
@@ -297,7 +293,7 @@ BaseType_t xPhyIndex;
 \r
        if( pxPhyObject->xPortCount < 1 )\r
        {\r
-               FreeRTOS_printf( ( "xPhyResetAll: No PHY's detected.\n" ) );\r
+               FreeRTOS_printf( ( "xPhyConfigure: No PHY's detected.\n" ) );\r
                return -1;\r
        }\r
 \r
@@ -308,11 +304,12 @@ BaseType_t xPhyIndex;
     /* Set advertise register. */\r
        if( ( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO ) && ( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO ) )\r
        {\r
-               ulAdvertise = phyADVERTISE_CSMA | phyADVERTISE_ALL;\r
+               ulAdvertise = phyADVERTISE_ALL;\r
                /* Reset auto-negotiation capability. */\r
        }\r
        else\r
        {\r
+               /* Always select protocol 802.3u. */\r
                ulAdvertise = phyADVERTISE_CSMA;\r
 \r
                if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO )\r
@@ -361,7 +358,7 @@ BaseType_t xPhyIndex;
                }\r
        }\r
 \r
-       /* Send a reset commando to a set of PHY-ports. */\r
+       /* Send a reset command to a set of PHY-ports. */\r
        xPhyReset( pxPhyObject, xPhyGetMask( pxPhyObject ) );\r
 \r
        for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )\r
@@ -450,6 +447,10 @@ BaseType_t xPhyIndex;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+/* xPhyFixedValue(): this function is called in case auto-negotiation is disabled.\r
+The caller has set the values in 'xPhyPreferences' (ucDuplex and ucSpeed).\r
+The PHY register phyREG_00_BMCR will be set for every connected PHY that matches\r
+with ulPhyMask. */\r
 BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )\r
 {\r
 BaseType_t xPhyIndex;\r
@@ -480,6 +481,9 @@ uint32_t ulValue, ulBitMask = ( uint32_t )1u;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+/* xPhyStartAutoNegotiation() is the alternative xPhyFixedValue():\r
+It sets the BMCR_AN_RESTART bit and waits for the auto-negotiation completion\r
+( phyBMSR_AN_COMPLETE ). */\r
 BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )\r
 {\r
 uint32_t xPhyIndex, ulDoneMask, ulBitMask;\r
@@ -491,7 +495,7 @@ TimeOut_t xTimer;
        {\r
                return 0;\r
        }\r
-       for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )\r
+       for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++ )\r
        {\r
                if( ( ulPhyMask & ( 1lu << xPhyIndex ) ) != 0lu )\r
                {\r
@@ -502,14 +506,14 @@ TimeOut_t xTimer;
                        pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue | phyBMCR_AN_RESTART );\r
                }\r
        }\r
-       xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( 3000UL );\r
+       xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_NEGOTIATE_TIME_MS );\r
        vTaskSetTimeOutState( &xTimer );\r
        ulDoneMask = 0;\r
        /* Wait until the auto-negotiation will be completed */\r
        for( ;; )\r
        {\r
                ulBitMask = ( uint32_t )1u;\r
-               for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )\r
+               for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )\r
                {\r
                        if( ( ulPhyMask & ulBitMask ) != 0lu )\r
                        {\r
@@ -531,17 +535,17 @@ TimeOut_t xTimer;
                }\r
                if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE )\r
                {\r
-                       FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) );\r
+                       FreeRTOS_printf( ( "xPhyStartAutoNegotiation: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) );\r
                        break;\r
                }\r
-               vTaskDelay( pdMS_TO_TICKS( 50 ) );\r
+               vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );\r
        }\r
 \r
        if( ulDoneMask != ( uint32_t)0u )\r
        {\r
                ulBitMask = ( uint32_t )1u;\r
                pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask );\r
-               for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )\r
+               for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )\r
                {\r
                BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];\r
                uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];\r
@@ -623,7 +627,7 @@ TimeOut_t xTimer;
                                pxPhyObject->fnPhyRead( xPhyAddress, PHYREG_10_PHYSTS, &ulRegValue);\r
                        }\r
 \r
-                       FreeRTOS_printf( ( ">> Autonego ready: %08lx: %s duplex %u mbit %s status\n",\r
+                       FreeRTOS_printf( ( "Autonego ready: %08lx: %s duplex %u mbit %s status\n",\r
                                ulRegValue,\r
                                ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half",\r
                                ( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100,\r
@@ -676,6 +680,9 @@ BaseType_t xNeedCheck = pdFALSE;
        }\r
        else if( xTaskCheckForTimeOut( &( pxPhyObject->xLinkStatusTimer ), &( pxPhyObject->xLinkStatusRemaining ) ) != pdFALSE )\r
        {\r
+               /* Frequent checking the PHY Link Status can affect for the performance of Ethernet controller.\r
+               As long as packets are received, no polling is needed.\r
+               Otherwise, polling will be done when the 'xLinkStatusTimer' expires. */\r
                for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )\r
                {\r
                BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];\r
@@ -700,10 +707,12 @@ BaseType_t xNeedCheck = pdFALSE;
                vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );\r
                if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 )\r
                {\r
+                       /* The link status is high, so don't poll the PHY too often. */\r
                        pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );\r
                }\r
                else\r
                {\r
+                       /* The link status is low, polling may be done more frequently. */\r
                        pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );\r
                }\r
        }\r