-/*\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
}\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
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
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
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
\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
/* 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
}\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
}\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
}\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
{\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
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
}\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
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
}\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
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