diff options
Diffstat (limited to 'FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq')
10 files changed, 2106 insertions, 2261 deletions
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c index 1c11976cb..c8f965395 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c @@ -1,398 +1,398 @@ -/*
-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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* 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 "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-/* Xilinx library files. */
-#include <xemacps.h>
-#include "Zynq/x_topology.h"
-#include "Zynq/x_emacpsif.h"
-#include "Zynq/x_emacpsif_hw.h"
-
-/* Provided memory configured as uncached. */
-#include "uncached_memory.h"
-
-#ifndef BMSR_LINK_STATUS
- #define BMSR_LINK_STATUS 0x0004UL
-#endif
-
-#ifndef PHY_LS_HIGH_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
- receiving packets. */
- #define PHY_LS_HIGH_CHECK_TIME_MS 15000
-#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
-
-/* 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
-
-/* Naming and numbering of PHY registers. */
-#define PHY_REG_01_BMSR 0x01 /* Basic mode status register */
-
-#ifndef iptraceEMAC_TASK_STARTING
- #define iptraceEMAC_TASK_STARTING() do { } while( 0 )
-#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
-
-/*-----------------------------------------------------------*/
-
-/*
- * Look for the link to be up every few milliseconds until either xMaxTime time
- * has passed or a link is found.
- */
-static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );
-
-/*
- * A deferred interrupt handler for all MAC/DMA interrupt sources.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*-----------------------------------------------------------*/
-
-/* EMAC data/descriptions. */
-static xemacpsif_s xEMACpsif;
-struct xtopology_t xXTopology =
-{
- .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,
- .emac_type = xemac_type_emacps,
- .intc_baseaddr = 0x0,
- .intc_emac_intr = 0x0,
- .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,
- .scugic_emac_intr = 0x36,
-};
-
-XEmacPs_Config mac_config =
-{
- .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID, /**< Unique ID of device */
- .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */
-};
-
-extern int phy_detected;
-
-/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
-static uint32_t ulPHYLinkStatus = 0;
-
-#if( ipconfigUSE_LLMNR == 1 )
- static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
-#endif
-
-/* ucMACAddress as it appears in main.c */
-extern const uint8_t ucMACAddress[ 6 ];
-
-/* 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
-related interrupts. */
-TaskHandle_t xEMACTaskHandle = NULL;
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-uint32_t ulLinkSpeed, ulDMAReg;
-BaseType_t xStatus, xLinkStatus;
-XEmacPs *pxEMAC_PS;
-const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );
-
- /* Guard against the init function being called more than once. */
- if( xEMACTaskHandle == NULL )
- {
- pxEMAC_PS = &( xEMACpsif.emacps );
- memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );
-
- xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);
- if( xStatus != XST_SUCCESS )
- {
- FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );
- }
-
- /* Initialize the mac and set the MAC address. */
- XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );
-
- #if( ipconfigUSE_LLMNR == 1 )
- {
- /* Also add LLMNR multicast MAC address. */
- XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );
- }
- #endif /* ipconfigUSE_LLMNR == 1 */
-
- XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );
- ulLinkSpeed = Phy_Setup( pxEMAC_PS );
- XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);
-
- /* Setting the operating speed of the MAC needs a delay. */
- vTaskDelay( pdMS_TO_TICKS( 25UL ) );
-
- ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);
-
- /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive
- packets from the receiver packet buffer memory when no AHB resource is available. */
- XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
- ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);
-
- setup_isr( &xEMACpsif );
- init_dma( &xEMACpsif );
- start_emacps( &xEMACpsif );
-
- prvGMACWaitLS( xWaitLinkDelay );
-
- /* 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, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
- }
- else
- {
- /* Initialisation was already performed, just wait for the link. */
- prvGMACWaitLS( xWaitRelinkDelay );
- }
-
- /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the
- DHCP process and all other communication will fail. */
- xLinkStatus = xGetPhyLinkStatus();
-
- return ( xLinkStatus != pdFALSE );
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )
-{
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- iptraceNETWORK_INTERFACE_TRANSMIT();
- emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
- }
- else if( bReleaseAfterSend != pdFALSE )
- {
- /* No link. */
- vReleaseNetworkBufferAndDescriptor( pxBuffer );
- }
-
- return pdTRUE;
-}
-/*-----------------------------------------------------------*/
-
-static inline unsigned long ulReadMDIO( unsigned ulRegister )
-{
-uint16_t usValue;
-
- XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );
- return usValue;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )
-{
-TickType_t xStartTime, xEndTime;
-const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );
-BaseType_t xReturn;
-
- xStartTime = xTaskGetTickCount();
-
- for( ;; )
- {
- xEndTime = xTaskGetTickCount();
-
- if( xEndTime - xStartTime > xMaxTime )
- {
- xReturn = pdFALSE;
- break;
- }
- ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- xReturn = pdTRUE;
- break;
- }
-
- vTaskDelay( xShortDelay );
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
-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( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
- {
- xReturn = pdFALSE;
- }
- else
- {
- xReturn = pdTRUE;
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-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 );
-
- /* Remove compiler warnings about unused parameters. */
- ( void ) pvParameters;
-
- /* A possibility to set some additional task properties like calling
- portTASK_USES_FLOATING_POINT() */
- iptraceEMAC_TASK_STARTING();
-
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
- 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 ) );
- }
-
- #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
- {
- static UBaseType_t uxLastMinQueueSpace = 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( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )
- {
- /* No events to process now, wait for the next. */
- ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
- }
-
- if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )
- {
- xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;
- xResult = emacps_check_rx( &xEMACpsif );
- }
-
- if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )
- {
- xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;
- emacps_check_tx( &xEMACpsif );
- }
-
- if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )
- {
- xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;
- emacps_check_errors( &xEMACpsif );
- }
-
- if( xResult > 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 );
- xResult = 0;
- }
- else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
- {
- xStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
- {
- ulPHYLinkStatus = xStatus;
- FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
- }
-
- vTaskSetTimeOutState( &xPhyTime );
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- }
- else
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
- }
- }
- }
-}
-/*-----------------------------------------------------------*/
+/* +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 <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +/* 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 "NetworkBufferManagement.h" +#include "NetworkInterface.h" + +/* Xilinx library files. */ +#include <xemacps.h> +#include "Zynq/x_topology.h" +#include "Zynq/x_emacpsif.h" +#include "Zynq/x_emacpsif_hw.h" + +/* Provided memory configured as uncached. */ +#include "uncached_memory.h" + +#ifndef BMSR_LINK_STATUS + #define BMSR_LINK_STATUS 0x0004UL +#endif + +#ifndef PHY_LS_HIGH_CHECK_TIME_MS + /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not + receiving packets. */ + #define PHY_LS_HIGH_CHECK_TIME_MS 15000 +#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 + +/* 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 + +/* Naming and numbering of PHY registers. */ +#define PHY_REG_01_BMSR 0x01 /* Basic mode status register */ + +#ifndef iptraceEMAC_TASK_STARTING + #define iptraceEMAC_TASK_STARTING() do { } while( 0 ) +#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 + +/*-----------------------------------------------------------*/ + +/* + * Look for the link to be up every few milliseconds until either xMaxTime time + * has passed or a link is found. + */ +static BaseType_t prvGMACWaitLS( TickType_t xMaxTime ); + +/* + * A deferred interrupt handler for all MAC/DMA interrupt sources. + */ +static void prvEMACHandlerTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* EMAC data/descriptions. */ +static xemacpsif_s xEMACpsif; +struct xtopology_t xXTopology = +{ + .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR, + .emac_type = xemac_type_emacps, + .intc_baseaddr = 0x0, + .intc_emac_intr = 0x0, + .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR, + .scugic_emac_intr = 0x36, +}; + +XEmacPs_Config mac_config = +{ + .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID, /**< Unique ID of device */ + .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */ +}; + +extern int phy_detected; + +/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */ +static uint32_t ulPHYLinkStatus = 0; + +#if( ipconfigUSE_LLMNR == 1 ) + static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC }; +#endif + +/* ucMACAddress as it appears in main.c */ +extern const uint8_t ucMACAddress[ 6 ]; + +/* 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 +related interrupts. */ +TaskHandle_t xEMACTaskHandle = NULL; + +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceInitialise( void ) +{ +uint32_t ulLinkSpeed, ulDMAReg; +BaseType_t xStatus, xLinkStatus; +XEmacPs *pxEMAC_PS; +const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL ); + + /* Guard against the init function being called more than once. */ + if( xEMACTaskHandle == NULL ) + { + pxEMAC_PS = &( xEMACpsif.emacps ); + memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) ); + + xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress); + if( xStatus != XST_SUCCESS ) + { + FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) ); + } + + /* Initialize the mac and set the MAC address. */ + XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 ); + + #if( ipconfigUSE_LLMNR == 1 ) + { + /* Also add LLMNR multicast MAC address. */ + XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 ); + } + #endif /* ipconfigUSE_LLMNR == 1 */ + + XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 ); + ulLinkSpeed = Phy_Setup( pxEMAC_PS ); + XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed); + + /* Setting the operating speed of the MAC needs a delay. */ + vTaskDelay( pdMS_TO_TICKS( 25UL ) ); + + ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET); + + /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive + packets from the receiver packet buffer memory when no AHB resource is available. */ + XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET, + ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK); + + setup_isr( &xEMACpsif ); + init_dma( &xEMACpsif ); + start_emacps( &xEMACpsif ); + + prvGMACWaitLS( xWaitLinkDelay ); + + /* 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, configMAX_PRIORITIES - 1, &xEMACTaskHandle ); + } + else + { + /* Initialisation was already performed, just wait for the link. */ + prvGMACWaitLS( xWaitRelinkDelay ); + } + + /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the + DHCP process and all other communication will fail. */ + xLinkStatus = xGetPhyLinkStatus(); + + return ( xLinkStatus != pdFALSE ); +} +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend ) +{ + if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) + { + iptraceNETWORK_INTERFACE_TRANSMIT(); + emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend ); + } + else if( bReleaseAfterSend != pdFALSE ) + { + /* No link. */ + vReleaseNetworkBufferAndDescriptor( pxBuffer ); + } + + return pdTRUE; +} +/*-----------------------------------------------------------*/ + +static inline unsigned long ulReadMDIO( unsigned ulRegister ) +{ +uint16_t usValue; + + XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue ); + return usValue; +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvGMACWaitLS( TickType_t xMaxTime ) +{ +TickType_t xStartTime, xEndTime; +const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL ); +BaseType_t xReturn; + + xStartTime = xTaskGetTickCount(); + + for( ;; ) + { + xEndTime = xTaskGetTickCount(); + + if( xEndTime - xStartTime > xMaxTime ) + { + xReturn = pdFALSE; + break; + } + ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR ); + + if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) + { + xReturn = pdTRUE; + break; + } + + vTaskDelay( xShortDelay ); + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ +static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) ); +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( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +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 ); + + /* Remove compiler warnings about unused parameters. */ + ( void ) pvParameters; + + /* A possibility to set some additional task properties like calling + portTASK_USES_FLOATING_POINT() */ + iptraceEMAC_TASK_STARTING(); + + vTaskSetTimeOutState( &xPhyTime ); + xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); + + 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 ) ); + } + + #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) + { + static UBaseType_t uxLastMinQueueSpace = 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( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 ) + { + /* No events to process now, wait for the next. */ + ulTaskNotifyTake( pdFALSE, ulMaxBlockTime ); + } + + if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 ) + { + xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT; + xResult = emacps_check_rx( &xEMACpsif ); + } + + if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 ) + { + xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT; + emacps_check_tx( &xEMACpsif ); + } + + if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 ) + { + xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT; + emacps_check_errors( &xEMACpsif ); + } + + if( xResult > 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 ); + xResult = 0; + } + else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) + { + xStatus = ulReadMDIO( PHY_REG_01_BMSR ); + + if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) ) + { + ulPHYLinkStatus = xStatus; + FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) ); + } + + vTaskSetTimeOutState( &xPhyTime ); + if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) + { + xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); + } + else + { + xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); + } + } + } +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt index 74b241dcf..f9e54bb2f 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt @@ -1,25 +1,25 @@ -
-
-NetworkInterface for Xilinx' Zynq
-
-Please include the following source files:
-
- $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/NetworkInterface.c
- $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_dma.c
- $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
- $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c
-
-And include the following source files from the Xilinx library:
-
- $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c
- $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_control.c
- $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_g.c
- $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_intr.c
-
- E.g. ps7_cortexa9_0/libsrc/emacps_v2_0/src/xemacps_intr.c
-
-The following source files are NOT used for the FreeRTOS+TCP interface:
-
- $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_bdring.c
- $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_hw.c
- $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_sinit.c
+ + +NetworkInterface for Xilinx' Zynq + +Please include the following source files: + + $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/NetworkInterface.c + $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_dma.c + $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c + $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c + +And include the following source files from the Xilinx library: + + $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c + $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_control.c + $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_g.c + $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_intr.c + + E.g. ps7_cortexa9_0/libsrc/emacps_v2_0/src/xemacps_intr.c + +The following source files are NOT used for the FreeRTOS+TCP interface: + + $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_bdring.c + $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_hw.c + $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_sinit.c diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/uncached_memory.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/uncached_memory.c deleted file mode 100644 index b43e50ec2..000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/uncached_memory.c +++ /dev/null @@ -1,132 +0,0 @@ -/*
- * uncached_memory.c
- *
- * This module will declare 1 MB of memory and switch off the caching for it.
- *
- * pucGetUncachedMemory( ulSize ) returns a trunc of this memory with a length
- * rounded up to a multiple of 4 KB
- *
- * ucIsCachedMemory( pucBuffer ) returns non-zero if a given pointer is NOT
- * within the range of the 1 MB non-cached memory.
- *
- */
-
-/*
- * After "_end", 1 MB of uncached memory will be allocated for DMA transfers.
- * Both the DMA descriptors as well as all EMAC TX-buffers will be allocated in
- * uncached memory.
- */
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.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"
-
-#define UNCACHED_MEMORY_SIZE 0x100000ul
-
-#define DDR_MEMORY_END (XPAR_PS7_DDR_0_S_AXI_HIGHADDR+1)
-
-static void vInitialiseUncachedMemory( void );
-
-static uint8_t *pucHeadOfMemory;
-static uint32_t ulMemorySize;
-static uint8_t *pucStartOfMemory = NULL;
-
-uint8_t ucIsCachedMemory( const uint8_t *pucBuffer )
-{
-uint8_t ucReturn;
-
- if( ( pucStartOfMemory != NULL ) &&
- ( pucBuffer >= pucStartOfMemory ) &&
- ( pucBuffer < ( pucStartOfMemory + UNCACHED_MEMORY_SIZE ) ) )
- {
- ucReturn = pdFALSE;
- }
- else
- {
- ucReturn = pdTRUE;
- }
-
- return ucReturn;
-}
-
-uint8_t *pucGetUncachedMemory( uint32_t ulSize )
-{
-uint8_t *pucReturn;
-
- if( pucStartOfMemory == NULL )
- {
- vInitialiseUncachedMemory( );
- }
- if( ( pucStartOfMemory == NULL ) || ( ulSize > ulMemorySize ) )
- {
- pucReturn = NULL;
- }
- else
- {
- uint32_t ulSkipSize;
-
- pucReturn = pucHeadOfMemory;
- ulSkipSize = ( ulSize + 0x1000ul ) & ~0xffful;
- pucHeadOfMemory += ulSkipSize;
- ulMemorySize -= ulSkipSize;
- }
-
- return pucReturn;
-}
-
-extern u8 _end;
-
-static void vInitialiseUncachedMemory( )
-{
- /* At the end of program's space... */
- pucStartOfMemory = (uint8_t *) &_end;
- /*
- * Align the start address to 1 MB boundary.
- */
- pucStartOfMemory = (uint8_t *)( ( ( uint32_t )pucStartOfMemory + UNCACHED_MEMORY_SIZE ) & ( ~( UNCACHED_MEMORY_SIZE - 1 ) ) );
-
- if( ( ( u32 )pucStartOfMemory ) + UNCACHED_MEMORY_SIZE > DDR_MEMORY_END )
- {
-// vLoggingPrintf("vInitialiseUncachedMemory: Can not allocate uncached memory\n" );
- }
- else
- {
- /*
- * Some objects want to be stored in uncached memory. Hence the 1 MB
- * address range that starts after "_end" is made uncached
- * by setting appropriate attributes in the translation table.
- */
- /* FIXME claudio rossi. Modified to prevent data abort exception (misaligned access)
- * when application is compiled with -O1 or more optimization flag.
- */
-/* Xil_SetTlbAttributes( ( uint32_t )pucStartOfMemory, 0xc02 ); // addr, attr */
- Xil_SetTlbAttributes( ( uint32_t )pucStartOfMemory, 0x1c02 ); // addr, attr
-
- /* For experiments in the SDIO driver, make the remaining uncached memory public */
- pucHeadOfMemory = pucStartOfMemory;
- ulMemorySize = UNCACHED_MEMORY_SIZE;
- memset( pucStartOfMemory, '\0', UNCACHED_MEMORY_SIZE );
- }
-}
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/uncached_memory.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/uncached_memory.h deleted file mode 100644 index 5a8e5f37f..000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/uncached_memory.h +++ /dev/null @@ -1,23 +0,0 @@ -/*
- * uncached_memory.h
- *
- * This module will declare 1 MB of memory and switch off the caching for it.
- *
- * pucGetUncachedMemory( ulSize ) returns a trunc of this memory with a length
- * rounded up to a multiple of 4 KB
- *
- * ucIsCachedMemory( pucBuffer ) returns non-zero if a given pointer is NOT
- * within the range of the 1 MB non-cached memory.
- *
- */
-
-#ifndef UNCACHEMEMORY_H
-
-#define UNCACHEMEMORY_H
-
-uint8_t *pucGetUncachedMemory( uint32_t ulSize );
-
-uint8_t ucIsCachedMemory( const uint8_t *pucBuffer );
-
-#endif /* UNCACHEMEMORY_H */
-
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h index 823dee0d3..2f1b0df20 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h @@ -1,144 +1,144 @@ -/*
- * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#ifndef __NETIF_XEMACPSIF_H__
-#define __NETIF_XEMACPSIF_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-#include "xstatus.h"
-#include "sleep.h"
-#include "xparameters.h"
-#include "xparameters_ps.h" /* defines XPAR values */
-#include "xil_types.h"
-#include "xil_assert.h"
-#include "xil_io.h"
-#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 */
-
-//#include "netif/xpqueue.h"
-//#include "xlwipconfig.h"
-
-void xemacpsif_setmac(uint32_t index, uint8_t *addr);
-uint8_t* xemacpsif_getmac(uint32_t index);
-//int xemacpsif_init(struct netif *netif);
-//int xemacpsif_input(struct netif *netif);
-#ifdef NOTNOW_BHILL
-unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);
-#endif
-
-/* xaxiemacif_hw.c */
-void xemacps_error_handler(XEmacPs * Temac);
-
-struct xBD_TYPE {
- uint32_t address;
- uint32_t flags;
-};
-
-/*
- * Missing declaration in 'src/xemacps_hw.h' :
- * When set, the GEM DMA will automatically
- * discard receive packets from the receiver packet
- * buffer memory when no AHB resource is
- * available.
- * When low, then received packets will remain to be
- * stored in the SRAM based packet buffer until
- * AHB buffer resource next becomes available.
- */
-#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK 0x01000000
-
-#define EMAC_IF_RX_EVENT 1
-#define EMAC_IF_TX_EVENT 2
-#define EMAC_IF_ERR_EVENT 4
-#define EMAC_IF_ALL_EVENT 7
-
-/* structure within each netif, encapsulating all information required for
- * using a particular temac instance
- */
-typedef struct {
- XEmacPs emacps;
-
- /* pointers to memory holding buffer descriptors (used only with SDMA) */
- struct xBD_TYPE *rxSegments;
- struct xBD_TYPE *txSegments;
-
- unsigned char *tx_space;
- unsigned uTxUnitSize;
-
- char *remain_mem;
- unsigned remain_siz;
-
- volatile int rxHead, rxTail;
- volatile int txHead, txTail;
-
- volatile int txBusy;
-
- volatile uint32_t isr_events;
-
- unsigned int last_rx_frms_cntr;
-
-} xemacpsif_s;
-
-//extern xemacpsif_s xemacpsif;
-
-int is_tx_space_available(xemacpsif_s *emac);
-
-/* xaxiemacif_dma.c */
-
-struct xNETWORK_BUFFER;
-
-int emacps_check_rx( xemacpsif_s *xemacpsif );
-void emacps_check_tx( xemacpsif_s *xemacpsif );
-int emacps_check_errors( xemacpsif_s *xemacps );
-void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );
-
-extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );
-extern unsigned Phy_Setup( XEmacPs *xemacpsp );
-extern void setup_isr( xemacpsif_s *xemacpsif );
-extern XStatus init_dma( xemacpsif_s *xemacpsif );
-extern void start_emacps( xemacpsif_s *xemacpsif );
-
-void EmacEnableIntr(void);
-void EmacDisableIntr(void);
-
-XStatus init_axi_dma(xemacpsif_s *xemacpsif);
-void process_sent_bds( xemacpsif_s *xemacpsif );
-
-void emacps_send_handler(void *arg);
-void emacps_recv_handler(void *arg);
-void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);
-void HandleTxErrors(xemacpsif_s *xemacpsif);
-XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);
-
-void clean_dma_txdescs(xemacpsif_s *xemacpsif);
-void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __NETIF_XAXIEMACIF_H__ */
+/* + * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved. + * + * Xilinx, Inc. + * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A + * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS + * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR + * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION + * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE + * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. + * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO + * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO + * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE + * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __NETIF_XEMACPSIF_H__ +#define __NETIF_XEMACPSIF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#include "xstatus.h" +#include "sleep.h" +#include "xparameters.h" +#include "xparameters_ps.h" /* defines XPAR values */ +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#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 */ + +//#include "netif/xpqueue.h" +//#include "xlwipconfig.h" + +void xemacpsif_setmac(uint32_t index, uint8_t *addr); +uint8_t* xemacpsif_getmac(uint32_t index); +//int xemacpsif_init(struct netif *netif); +//int xemacpsif_input(struct netif *netif); +#ifdef NOTNOW_BHILL +unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp); +#endif + +/* xaxiemacif_hw.c */ +void xemacps_error_handler(XEmacPs * Temac); + +struct xBD_TYPE { + uint32_t address; + uint32_t flags; +}; + +/* + * Missing declaration in 'src/xemacps_hw.h' : + * When set, the GEM DMA will automatically + * discard receive packets from the receiver packet + * buffer memory when no AHB resource is + * available. + * When low, then received packets will remain to be + * stored in the SRAM based packet buffer until + * AHB buffer resource next becomes available. + */ +#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK 0x01000000 + +#define EMAC_IF_RX_EVENT 1 +#define EMAC_IF_TX_EVENT 2 +#define EMAC_IF_ERR_EVENT 4 +#define EMAC_IF_ALL_EVENT 7 + +/* structure within each netif, encapsulating all information required for + * using a particular temac instance + */ +typedef struct { + XEmacPs emacps; + + /* pointers to memory holding buffer descriptors (used only with SDMA) */ + struct xBD_TYPE *rxSegments; + struct xBD_TYPE *txSegments; + + unsigned char *tx_space; + unsigned uTxUnitSize; + + char *remain_mem; + unsigned remain_siz; + + volatile int rxHead, rxTail; + volatile int txHead, txTail; + + volatile int txBusy; + + volatile uint32_t isr_events; + + unsigned int last_rx_frms_cntr; + +} xemacpsif_s; + +//extern xemacpsif_s xemacpsif; + +int is_tx_space_available(xemacpsif_s *emac); + +/* xaxiemacif_dma.c */ + +struct xNETWORK_BUFFER; + +int emacps_check_rx( xemacpsif_s *xemacpsif ); +void emacps_check_tx( xemacpsif_s *xemacpsif ); +int emacps_check_errors( xemacpsif_s *xemacps ); +void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount ); + +extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend ); +extern unsigned Phy_Setup( XEmacPs *xemacpsp ); +extern void setup_isr( xemacpsif_s *xemacpsif ); +extern XStatus init_dma( xemacpsif_s *xemacpsif ); +extern void start_emacps( xemacpsif_s *xemacpsif ); + +void EmacEnableIntr(void); +void EmacDisableIntr(void); + +XStatus init_axi_dma(xemacpsif_s *xemacpsif); +void process_sent_bds( xemacpsif_s *xemacpsif ); + +void emacps_send_handler(void *arg); +void emacps_recv_handler(void *arg); +void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord); +void HandleTxErrors(xemacpsif_s *xemacpsif); +XEmacPs_Config *xemacps_lookup_config(unsigned mac_base); + +void clean_dma_txdescs(xemacpsif_s *xemacpsif); +void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif); + +#ifdef __cplusplus +} +#endif + +#endif /* __NETIF_XAXIEMACIF_H__ */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c index fc09d2183..13a62852d 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c @@ -1,626 +1,626 @@ -/*
-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"
-#include "timers.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-
-#include "uncached_memory.h"
-
-/* Two defines used to set or clear the EMAC interrupt */
-#define INTC_BASE_ADDR XPAR_SCUGIC_CPU_BASEADDR
-#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_DIST_BASEADDR
-
-
-
-#if( ipconfigPACKET_FILLER_SIZE != 2 )
- #error Please define ipconfigPACKET_FILLER_SIZE as the value '2'
-#endif
-#define TX_OFFSET ipconfigPACKET_FILLER_SIZE
-
-#define RX_BUFFER_ALIGNMENT 14
-
-/* Defined in NetworkInterface.c */
-extern TaskHandle_t xEMACTaskHandle;
-
-/*
- pxDMA_tx_buffers: these are character arrays, each one is big enough to hold 1 MTU.
- The actual TX buffers are located in uncached RAM.
-*/
-static unsigned char *pxDMA_tx_buffers[ ipconfigNIC_N_TX_DESC ] = { NULL };
-
-/*
- pxDMA_rx_buffers: these are pointers to 'NetworkBufferDescriptor_t'.
- Once a message has been received by the EMAC, the descriptor can be passed
- immediately to the IP-task.
-*/
-static NetworkBufferDescriptor_t *pxDMA_rx_buffers[ ipconfigNIC_N_RX_DESC ] = { NULL };
-
-/*
- The FreeRTOS+TCP port is using a fixed 'topology', which is declared in
- ./portable/NetworkInterface/Zynq/NetworkInterface.c
-*/
-extern struct xtopology_t xXTopology;
-
-static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
-
-/*
- The FreeRTOS+TCP port does not make use of "src/xemacps_bdring.c".
- In stead 'struct xemacpsif_s' has a "head" and a "tail" index.
- "head" is the next index to be written, used.
- "tail" is the next index to be read, freed.
-*/
-
-int is_tx_space_available( xemacpsif_s *xemacpsif )
-{
-size_t uxCount;
-
- if( xTXDescriptorSemaphore != NULL )
- {
- uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
- }
- else
- {
- uxCount = ( UBaseType_t ) 0u;
- }
-
- return uxCount;
-}
-
-void emacps_check_tx( xemacpsif_s *xemacpsif )
-{
-int tail = xemacpsif->txTail;
-int head = xemacpsif->txHead;
-size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
-
- /* uxCount is the number of TX descriptors that are in use by the DMA. */
- /* When done, "TXBUF_USED" will be set. */
-
- while( ( uxCount > 0 ) && ( ( xemacpsif->txSegments[ tail ].flags & XEMACPS_TXBUF_USED_MASK ) != 0 ) )
- {
- if( ( tail == head ) && ( uxCount != ipconfigNIC_N_TX_DESC ) )
- {
- break;
- }
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-#warning ipconfigZERO_COPY_TX_DRIVER is defined
- {
- void *pvBuffer = pxDMA_tx_buffers[ tail ];
- NetworkBufferDescriptor_t *pxBuffer;
-
- if( pvBuffer != NULL )
- {
- pxDMA_tx_buffers[ tail ] = NULL;
- pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer );
- if( pxBuffer != NULL )
- {
- vReleaseNetworkBufferAndDescriptor( pxBuffer );
- }
- else
- {
- FreeRTOS_printf( ( "emacps_check_tx: Can not find network buffer\n" ) );
- }
- }
- }
-#endif
- /* Clear all but the "used" and "wrap" bits. */
- if( tail < ipconfigNIC_N_TX_DESC - 1 )
- {
- xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK;
- }
- else
- {
- xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;
- }
- uxCount--;
- /* Tell the counting semaphore that one more TX descriptor is available. */
- xSemaphoreGive( xTXDescriptorSemaphore );
- if( ++tail == ipconfigNIC_N_TX_DESC )
- {
- tail = 0;
- }
- xemacpsif->txTail = tail;
- }
-
- return;
-}
-
-void emacps_send_handler(void *arg)
-{
-xemacpsif_s *xemacpsif;
-BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
- xemacpsif = (xemacpsif_s *)(arg);
-
- /* In this port for FreeRTOS+TCP, the EMAC interrupts will only set a bit in
- "isr_events". The task in NetworkInterface will wake-up and do the necessary work.
- */
- xemacpsif->isr_events |= EMAC_IF_TX_EVENT;
- xemacpsif->txBusy = pdFALSE;
-
- if( xEMACTaskHandle != NULL )
- {
- vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
- }
-
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-
-static BaseType_t xValidLength( BaseType_t xLength )
-{
-BaseType_t xReturn;
-
- if( ( xLength >= ( BaseType_t ) sizeof( struct xARP_PACKET ) ) && ( ( ( uint32_t ) xLength ) <= ipTOTAL_ETHERNET_FRAME_SIZE ) )
- {
- xReturn = pdTRUE;
- }
- else
- {
- xReturn = pdFALSE;
- }
-
- return xReturn;
-}
-
-XStatus emacps_send_message(xemacpsif_s *xemacpsif, NetworkBufferDescriptor_t *pxBuffer, int iReleaseAfterSend )
-{
-int head = xemacpsif->txHead;
-int iHasSent = 0;
-uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress;
-TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );
-
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
- /* This driver wants to own all network buffers which are to be transmitted. */
- configASSERT( iReleaseAfterSend != pdFALSE );
- }
- #endif
-
- /* Open a do {} while ( 0 ) loop to be able to call break. */
- do
- {
- uint32_t ulFlags = 0;
-
- if( xValidLength( pxBuffer->xDataLength ) != pdTRUE )
- {
- break;
- }
-
- if( xTXDescriptorSemaphore == NULL )
- {
- break;
- }
-
- if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
- {
- FreeRTOS_printf( ( "emacps_send_message: Time-out waiting for TX buffer\n" ) );
- break;
- }
-
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- /* Pass the pointer (and its ownership) directly to DMA. */
- pxDMA_tx_buffers[ head ] = pxBuffer->pucEthernetBuffer;
- if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
- {
- Xil_DCacheFlushRange( ( unsigned )pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
- }
- /* Buffer has been transferred, do not release it. */
- iReleaseAfterSend = pdFALSE;
-#else
- if( pxDMA_tx_buffers[ head ] == NULL )
- {
- FreeRTOS_printf( ( "emacps_send_message: pxDMA_tx_buffers[ %d ] == NULL\n", head ) );
- break;
- }
- /* Copy the message to unbuffered space in RAM. */
- memcpy( pxDMA_tx_buffers[ head ], pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
-#endif
- /* Packets will be sent one-by-one, so for each packet
- the TXBUF_LAST bit will be set. */
- ulFlags |= XEMACPS_TXBUF_LAST_MASK;
- ulFlags |= ( pxBuffer->xDataLength & XEMACPS_TXBUF_LEN_MASK );
- if( head == ( ipconfigNIC_N_TX_DESC - 1 ) )
- {
- ulFlags |= XEMACPS_TXBUF_WRAP_MASK;
- }
-
- /* Copy the address of the buffer and set the flags. */
- xemacpsif->txSegments[ head ].address = ( uint32_t )pxDMA_tx_buffers[ head ];
- xemacpsif->txSegments[ head ].flags = ulFlags;
-
- iHasSent = pdTRUE;
- if( ++head == ipconfigNIC_N_TX_DESC )
- {
- head = 0;
- }
- /* Update the TX-head index. These variable are declared volatile so they will be
- accessed as little as possible. */
- xemacpsif->txHead = head;
- } while( pdFALSE );
-
- if( iReleaseAfterSend != pdFALSE )
- {
- vReleaseNetworkBufferAndDescriptor( pxBuffer );
- pxBuffer = NULL;
- }
-
- /* Data Synchronization Barrier */
- dsb();
-
- if( iHasSent != pdFALSE )
- {
- /* Make STARTTX high */
- uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET);
- /* Start transmit */
- xemacpsif->txBusy = pdTRUE;
- XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) );
- }
- dsb();
-
- return 0;
-}
-
-void emacps_recv_handler(void *arg)
-{
- xemacpsif_s *xemacpsif;
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
- xemacpsif = (xemacpsif_s *)(arg);
- xemacpsif->isr_events |= EMAC_IF_RX_EVENT;
-
- if( xEMACTaskHandle != NULL )
- {
- vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
- }
-
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-
-static NetworkBufferDescriptor_t *ethMsg = NULL;
-static NetworkBufferDescriptor_t *ethLast = NULL;
-
-static void passEthMessages( void )
-{
-IPStackEvent_t xRxEvent;
-
- xRxEvent.eEventType = eNetworkRxEvent;
- 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. */
- do
- {
- NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer;
- vReleaseNetworkBufferAndDescriptor( ethMsg );
- ethMsg = xNext;
- } while( ethMsg != NULL );
-
- iptraceETHERNET_RX_EVENT_LOST();
- FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) );
- }
-
- ethMsg = ethLast = NULL;
-}
-
-int emacps_check_rx( xemacpsif_s *xemacpsif )
-{
-NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer;
-int rx_bytes;
-volatile int msgCount = 0;
-int head = xemacpsif->rxHead;
-
- /* There seems to be an issue (SI# 692601), see comments below. */
- resetrx_on_no_rxdata(xemacpsif);
-
- /* This FreeRTOS+TCP driver shall be compiled with the option
- "ipconfigUSE_LINKED_RX_MESSAGES" enabled. It allows the driver to send a
- chain of RX messages within one message to the IP-task. */
- for( ;; )
- {
- if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) ||
- ( pxDMA_rx_buffers[ head ] == NULL ) )
- {
- break;
- }
-
- 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.
- The packet will be dropped, and it Network Buffer will stay in place. */
- FreeRTOS_printf( ("emacps_check_rx: unable to allocate a Netwrok Buffer\n" ) );
- pxNewBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];
- }
- else
- {
- pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];
-
- /* Just avoiding to use or refer to the same buffer again */
- pxDMA_rx_buffers[ head ] = pxNewBuffer;
-
- /*
- * Adjust the buffer size to the actual number of bytes received.
- */
- 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 );
- }
-
- /* store it in the receive queue, where it'll be processed by a
- different handler. */
- iptraceNETWORK_INTERFACE_RECEIVE();
- pxBuffer->pxNextBuffer = NULL;
-
- if( ethMsg == NULL )
- {
- // Becomes the first message
- ethMsg = pxBuffer;
- }
- else if( ethLast != NULL )
- {
- // Add to the tail
- ethLast->pxNextBuffer = pxBuffer;
- }
-
- ethLast = pxBuffer;
- msgCount++;
- }
- {
- if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 )
- {
- 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;
- if( head == ( ipconfigNIC_N_RX_DESC - 1 ) )
- {
- addr |= XEMACPS_RXBUF_WRAP_MASK;
- }
- /* Clearing 'XEMACPS_RXBUF_NEW_MASK' 0x00000001 *< Used bit.. */
- xemacpsif->rxSegments[ head ].address = addr;
- xemacpsif->rxSegments[ head ].flags = 0;
- }
- }
-
- if( ++head == ipconfigNIC_N_RX_DESC )
- {
- head = 0;
- }
- xemacpsif->rxHead = head;
- }
-
- if( ethMsg != NULL )
- {
- passEthMessages( );
- }
-
- return msgCount;
-}
-
-void clean_dma_txdescs(xemacpsif_s *xemacpsif)
-{
-int index;
-unsigned char *ucTxBuffer;
-
- /* Clear all TX descriptors and assign uncached memory to each descriptor.
- "tx_space" points to the first available TX buffer. */
- ucTxBuffer = xemacpsif->tx_space;
-
- for( index = 0; index < ipconfigNIC_N_TX_DESC; index++ )
- {
- 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 ] = ( void* )NULL;
-#else
- pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET );
-#endif
- ucTxBuffer += xemacpsif->uTxUnitSize;
- }
- xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags =
- XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;
-}
-
-XStatus init_dma(xemacpsif_s *xemacpsif)
-{
- NetworkBufferDescriptor_t *pxBuffer;
-
- int iIndex;
- UBaseType_t xRxSize;
- UBaseType_t xTxSize;
- struct xtopology_t *xtopologyp = &xXTopology;
-
- xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] );
-
- xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] );
-
- /* Also round-up to 4KB */
- xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful;
- /*
- * We allocate 65536 bytes for RX BDs which can accommodate a
- * maximum of 8192 BDs which is much more than any application
- * will ever need.
- */
- xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize ) );
- xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) );
- xemacpsif->tx_space = ( unsigned char * )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) );
-
- /* These variables will be used in XEmacPs_Start (see src/xemacps.c). */
- xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments;
- xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments;
-
- if( xTXDescriptorSemaphore == NULL )
- {
- xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC );
- configASSERT( xTXDescriptorSemaphore );
- }
- /*
- * Allocate RX descriptors, 1 RxBD at a time.
- */
- for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ )
- {
- pxBuffer = pxDMA_rx_buffers[ iIndex ];
- if( pxBuffer == NULL )
- {
- 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" ) );
- return -1;
- }
- }
-
- xemacpsif->rxSegments[ iIndex ].flags = 0;
- xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;
-
- pxDMA_rx_buffers[ iIndex ] = pxBuffer;
- /* Make sure this memory is not in cache for now. */
- if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
- {
- Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE,
- (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);
- }
- }
-
- xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK;
-
- memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize );
-
- clean_dma_txdescs( xemacpsif );
-
- {
- uint32_t value;
- value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET );
-
- // 1xxxx: Attempt to use INCR16 AHB bursts
- value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST;
-#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
- value |= XEMACPS_DMACR_TCPCKSUM_MASK;
-#else
-#warning Are you sure the EMAC should not calculate outgoing checksums?
- value &= ~XEMACPS_DMACR_TCPCKSUM_MASK;
-#endif
- XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value );
- }
- {
- uint32_t value;
- value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET );
-
- /* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ).
- Now tell the EMAC that received messages should be stored at "address + 2". */
- value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000;
-
-#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 )
- value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
-#else
-#warning Are you sure the EMAC should not calculate incoming checksums?
- value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK;
-#endif
- XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value );
- }
-
- /*
- * Connect the device driver handler that will be called when an
- * interrupt for the device occurs, the handler defined above performs
- * the specific interrupt processing for the device.
- */
- XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
- (Xil_ExceptionHandler)XEmacPs_IntrHandler,
- (void *)&xemacpsif->emacps);
- /*
- * Enable the interrupt for emacps.
- */
- EmacEnableIntr( );
-
- return 0;
-}
-
-/*
- * resetrx_on_no_rxdata():
- *
- * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata
- * called by the user.
- * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.
- * Under heavy Rx traffic because of the HW bug there are times when the Rx path
- * becomes unresponsive. The workaround for it is to check for the Rx path for
- * traffic (by reading the stats registers regularly). If the stats register
- * does not increment for sometime (proving no Rx traffic), the function resets
- * the Rx data path.
- *
- */
-
-void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
-{
- unsigned long regctrl;
- unsigned long tempcntr;
-
- tempcntr = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET );
- if ( ( tempcntr == 0 ) && ( xemacpsif->last_rx_frms_cntr == 0 ) )
- {
- regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET);
- regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
- XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET, regctrl);
- regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
- regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
- XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
- }
- xemacpsif->last_rx_frms_cntr = tempcntr;
-}
-
-void EmacDisableIntr(void)
-{
- XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);
-}
-
-void EmacEnableIntr(void)
-{
- XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);
-}
-
+/* +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" +#include "timers.h" +#include "semphr.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" +#include "FreeRTOS_IP_Private.h" +#include "NetworkBufferManagement.h" + +#include "uncached_memory.h" + +/* Two defines used to set or clear the EMAC interrupt */ +#define INTC_BASE_ADDR XPAR_SCUGIC_CPU_BASEADDR +#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_DIST_BASEADDR + + + +#if( ipconfigPACKET_FILLER_SIZE != 2 ) + #error Please define ipconfigPACKET_FILLER_SIZE as the value '2' +#endif +#define TX_OFFSET ipconfigPACKET_FILLER_SIZE + +#define RX_BUFFER_ALIGNMENT 14 + +/* Defined in NetworkInterface.c */ +extern TaskHandle_t xEMACTaskHandle; + +/* + pxDMA_tx_buffers: these are character arrays, each one is big enough to hold 1 MTU. + The actual TX buffers are located in uncached RAM. +*/ +static unsigned char *pxDMA_tx_buffers[ ipconfigNIC_N_TX_DESC ] = { NULL }; + +/* + pxDMA_rx_buffers: these are pointers to 'NetworkBufferDescriptor_t'. + Once a message has been received by the EMAC, the descriptor can be passed + immediately to the IP-task. +*/ +static NetworkBufferDescriptor_t *pxDMA_rx_buffers[ ipconfigNIC_N_RX_DESC ] = { NULL }; + +/* + The FreeRTOS+TCP port is using a fixed 'topology', which is declared in + ./portable/NetworkInterface/Zynq/NetworkInterface.c +*/ +extern struct xtopology_t xXTopology; + +static SemaphoreHandle_t xTXDescriptorSemaphore = NULL; + +/* + The FreeRTOS+TCP port does not make use of "src/xemacps_bdring.c". + In stead 'struct xemacpsif_s' has a "head" and a "tail" index. + "head" is the next index to be written, used. + "tail" is the next index to be read, freed. +*/ + +int is_tx_space_available( xemacpsif_s *xemacpsif ) +{ +size_t uxCount; + + if( xTXDescriptorSemaphore != NULL ) + { + uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore ); + } + else + { + uxCount = ( UBaseType_t ) 0u; + } + + return uxCount; +} + +void emacps_check_tx( xemacpsif_s *xemacpsif ) +{ +int tail = xemacpsif->txTail; +int head = xemacpsif->txHead; +size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore ); + + /* uxCount is the number of TX descriptors that are in use by the DMA. */ + /* When done, "TXBUF_USED" will be set. */ + + while( ( uxCount > 0 ) && ( ( xemacpsif->txSegments[ tail ].flags & XEMACPS_TXBUF_USED_MASK ) != 0 ) ) + { + if( ( tail == head ) && ( uxCount != ipconfigNIC_N_TX_DESC ) ) + { + break; + } +#if( ipconfigZERO_COPY_TX_DRIVER != 0 ) +#warning ipconfigZERO_COPY_TX_DRIVER is defined + { + void *pvBuffer = pxDMA_tx_buffers[ tail ]; + NetworkBufferDescriptor_t *pxBuffer; + + if( pvBuffer != NULL ) + { + pxDMA_tx_buffers[ tail ] = NULL; + pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer ); + if( pxBuffer != NULL ) + { + vReleaseNetworkBufferAndDescriptor( pxBuffer ); + } + else + { + FreeRTOS_printf( ( "emacps_check_tx: Can not find network buffer\n" ) ); + } + } + } +#endif + /* Clear all but the "used" and "wrap" bits. */ + if( tail < ipconfigNIC_N_TX_DESC - 1 ) + { + xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK; + } + else + { + xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK; + } + uxCount--; + /* Tell the counting semaphore that one more TX descriptor is available. */ + xSemaphoreGive( xTXDescriptorSemaphore ); + if( ++tail == ipconfigNIC_N_TX_DESC ) + { + tail = 0; + } + xemacpsif->txTail = tail; + } + + return; +} + +void emacps_send_handler(void *arg) +{ +xemacpsif_s *xemacpsif; +BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + xemacpsif = (xemacpsif_s *)(arg); + + /* In this port for FreeRTOS+TCP, the EMAC interrupts will only set a bit in + "isr_events". The task in NetworkInterface will wake-up and do the necessary work. + */ + xemacpsif->isr_events |= EMAC_IF_TX_EVENT; + xemacpsif->txBusy = pdFALSE; + + if( xEMACTaskHandle != NULL ) + { + vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); + } + + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); +} + +static BaseType_t xValidLength( BaseType_t xLength ) +{ +BaseType_t xReturn; + + if( ( xLength >= ( BaseType_t ) sizeof( struct xARP_PACKET ) ) && ( ( ( uint32_t ) xLength ) <= ipTOTAL_ETHERNET_FRAME_SIZE ) ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} + +XStatus emacps_send_message(xemacpsif_s *xemacpsif, NetworkBufferDescriptor_t *pxBuffer, int iReleaseAfterSend ) +{ +int head = xemacpsif->txHead; +int iHasSent = 0; +uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress; +TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u ); + + #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) + { + /* This driver wants to own all network buffers which are to be transmitted. */ + configASSERT( iReleaseAfterSend != pdFALSE ); + } + #endif + + /* Open a do {} while ( 0 ) loop to be able to call break. */ + do + { + uint32_t ulFlags = 0; + + if( xValidLength( pxBuffer->xDataLength ) != pdTRUE ) + { + break; + } + + if( xTXDescriptorSemaphore == NULL ) + { + break; + } + + if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS ) + { + FreeRTOS_printf( ( "emacps_send_message: Time-out waiting for TX buffer\n" ) ); + break; + } + +#if( ipconfigZERO_COPY_TX_DRIVER != 0 ) + /* Pass the pointer (and its ownership) directly to DMA. */ + pxDMA_tx_buffers[ head ] = pxBuffer->pucEthernetBuffer; + if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 ) + { + Xil_DCacheFlushRange( ( unsigned )pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength ); + } + /* Buffer has been transferred, do not release it. */ + iReleaseAfterSend = pdFALSE; +#else + if( pxDMA_tx_buffers[ head ] == NULL ) + { + FreeRTOS_printf( ( "emacps_send_message: pxDMA_tx_buffers[ %d ] == NULL\n", head ) ); + break; + } + /* Copy the message to unbuffered space in RAM. */ + memcpy( pxDMA_tx_buffers[ head ], pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength ); +#endif + /* Packets will be sent one-by-one, so for each packet + the TXBUF_LAST bit will be set. */ + ulFlags |= XEMACPS_TXBUF_LAST_MASK; + ulFlags |= ( pxBuffer->xDataLength & XEMACPS_TXBUF_LEN_MASK ); + if( head == ( ipconfigNIC_N_TX_DESC - 1 ) ) + { + ulFlags |= XEMACPS_TXBUF_WRAP_MASK; + } + + /* Copy the address of the buffer and set the flags. */ + xemacpsif->txSegments[ head ].address = ( uint32_t )pxDMA_tx_buffers[ head ]; + xemacpsif->txSegments[ head ].flags = ulFlags; + + iHasSent = pdTRUE; + if( ++head == ipconfigNIC_N_TX_DESC ) + { + head = 0; + } + /* Update the TX-head index. These variable are declared volatile so they will be + accessed as little as possible. */ + xemacpsif->txHead = head; + } while( pdFALSE ); + + if( iReleaseAfterSend != pdFALSE ) + { + vReleaseNetworkBufferAndDescriptor( pxBuffer ); + pxBuffer = NULL; + } + + /* Data Synchronization Barrier */ + dsb(); + + if( iHasSent != pdFALSE ) + { + /* Make STARTTX high */ + uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET); + /* Start transmit */ + xemacpsif->txBusy = pdTRUE; + XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) ); + } + dsb(); + + return 0; +} + +void emacps_recv_handler(void *arg) +{ + xemacpsif_s *xemacpsif; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + xemacpsif = (xemacpsif_s *)(arg); + xemacpsif->isr_events |= EMAC_IF_RX_EVENT; + + if( xEMACTaskHandle != NULL ) + { + vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); + } + + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); +} + +static NetworkBufferDescriptor_t *ethMsg = NULL; +static NetworkBufferDescriptor_t *ethLast = NULL; + +static void passEthMessages( void ) +{ +IPStackEvent_t xRxEvent; + + xRxEvent.eEventType = eNetworkRxEvent; + 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. */ + do + { + NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer; + vReleaseNetworkBufferAndDescriptor( ethMsg ); + ethMsg = xNext; + } while( ethMsg != NULL ); + + iptraceETHERNET_RX_EVENT_LOST(); + FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) ); + } + + ethMsg = ethLast = NULL; +} + +int emacps_check_rx( xemacpsif_s *xemacpsif ) +{ +NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer; +int rx_bytes; +volatile int msgCount = 0; +int head = xemacpsif->rxHead; + + /* There seems to be an issue (SI# 692601), see comments below. */ + resetrx_on_no_rxdata(xemacpsif); + + /* This FreeRTOS+TCP driver shall be compiled with the option + "ipconfigUSE_LINKED_RX_MESSAGES" enabled. It allows the driver to send a + chain of RX messages within one message to the IP-task. */ + for( ;; ) + { + if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) || + ( pxDMA_rx_buffers[ head ] == NULL ) ) + { + break; + } + + 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. + The packet will be dropped, and it Network Buffer will stay in place. */ + FreeRTOS_printf( ("emacps_check_rx: unable to allocate a Netwrok Buffer\n" ) ); + pxNewBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ]; + } + else + { + pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ]; + + /* Just avoiding to use or refer to the same buffer again */ + pxDMA_rx_buffers[ head ] = pxNewBuffer; + + /* + * Adjust the buffer size to the actual number of bytes received. + */ + 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 ); + } + + /* store it in the receive queue, where it'll be processed by a + different handler. */ + iptraceNETWORK_INTERFACE_RECEIVE(); + pxBuffer->pxNextBuffer = NULL; + + if( ethMsg == NULL ) + { + // Becomes the first message + ethMsg = pxBuffer; + } + else if( ethLast != NULL ) + { + // Add to the tail + ethLast->pxNextBuffer = pxBuffer; + } + + ethLast = pxBuffer; + msgCount++; + } + { + if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 ) + { + 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; + if( head == ( ipconfigNIC_N_RX_DESC - 1 ) ) + { + addr |= XEMACPS_RXBUF_WRAP_MASK; + } + /* Clearing 'XEMACPS_RXBUF_NEW_MASK' 0x00000001 *< Used bit.. */ + xemacpsif->rxSegments[ head ].address = addr; + xemacpsif->rxSegments[ head ].flags = 0; + } + } + + if( ++head == ipconfigNIC_N_RX_DESC ) + { + head = 0; + } + xemacpsif->rxHead = head; + } + + if( ethMsg != NULL ) + { + passEthMessages( ); + } + + return msgCount; +} + +void clean_dma_txdescs(xemacpsif_s *xemacpsif) +{ +int index; +unsigned char *ucTxBuffer; + + /* Clear all TX descriptors and assign uncached memory to each descriptor. + "tx_space" points to the first available TX buffer. */ + ucTxBuffer = xemacpsif->tx_space; + + for( index = 0; index < ipconfigNIC_N_TX_DESC; index++ ) + { + 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 ] = ( void* )NULL; +#else + pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET ); +#endif + ucTxBuffer += xemacpsif->uTxUnitSize; + } + xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags = + XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK; +} + +XStatus init_dma(xemacpsif_s *xemacpsif) +{ + NetworkBufferDescriptor_t *pxBuffer; + + int iIndex; + UBaseType_t xRxSize; + UBaseType_t xTxSize; + struct xtopology_t *xtopologyp = &xXTopology; + + xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] ); + + xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] ); + + /* Also round-up to 4KB */ + xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful; + /* + * We allocate 65536 bytes for RX BDs which can accommodate a + * maximum of 8192 BDs which is much more than any application + * will ever need. + */ + xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize ) ); + xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) ); + xemacpsif->tx_space = ( unsigned char * )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) ); + + /* These variables will be used in XEmacPs_Start (see src/xemacps.c). */ + xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments; + xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments; + + if( xTXDescriptorSemaphore == NULL ) + { + xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC ); + configASSERT( xTXDescriptorSemaphore ); + } + /* + * Allocate RX descriptors, 1 RxBD at a time. + */ + for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ ) + { + pxBuffer = pxDMA_rx_buffers[ iIndex ]; + if( pxBuffer == NULL ) + { + 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" ) ); + return -1; + } + } + + xemacpsif->rxSegments[ iIndex ].flags = 0; + xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK; + + pxDMA_rx_buffers[ iIndex ] = pxBuffer; + /* Make sure this memory is not in cache for now. */ + if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 ) + { + Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, + (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT); + } + } + + xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK; + + memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ); + + clean_dma_txdescs( xemacpsif ); + + { + uint32_t value; + value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET ); + + // 1xxxx: Attempt to use INCR16 AHB bursts + value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST; +#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) + value |= XEMACPS_DMACR_TCPCKSUM_MASK; +#else +#warning Are you sure the EMAC should not calculate outgoing checksums? + value &= ~XEMACPS_DMACR_TCPCKSUM_MASK; +#endif + XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value ); + } + { + uint32_t value; + value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET ); + + /* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ). + Now tell the EMAC that received messages should be stored at "address + 2". */ + value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000; + +#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ) + value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK; +#else +#warning Are you sure the EMAC should not calculate incoming checksums? + value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK; +#endif + XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value ); + } + + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr, + (Xil_ExceptionHandler)XEmacPs_IntrHandler, + (void *)&xemacpsif->emacps); + /* + * Enable the interrupt for emacps. + */ + EmacEnableIntr( ); + + return 0; +} + +/* + * resetrx_on_no_rxdata(): + * + * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata + * called by the user. + * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic. + * Under heavy Rx traffic because of the HW bug there are times when the Rx path + * becomes unresponsive. The workaround for it is to check for the Rx path for + * traffic (by reading the stats registers regularly). If the stats register + * does not increment for sometime (proving no Rx traffic), the function resets + * the Rx data path. + * + */ + +void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif) +{ + unsigned long regctrl; + unsigned long tempcntr; + + tempcntr = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET ); + if ( ( tempcntr == 0 ) && ( xemacpsif->last_rx_frms_cntr == 0 ) ) + { + regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, regctrl); + regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET); + regctrl |= (XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl); + } + xemacpsif->last_rx_frms_cntr = tempcntr; +} + +void EmacDisableIntr(void) +{ + XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr); +} + +void EmacEnableIntr(void) +{ + XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr); +} + diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c index e9443cda8..be00f4f9c 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c @@ -1,243 +1,243 @@ -/*
- * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#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"
-
-extern TaskHandle_t xEMACTaskHandle;
-
-/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
- *** to run it on a PEEP board
- ***/
-
-unsigned int link_speed = 100;
-
-void setup_isr( xemacpsif_s *xemacpsif )
-{
- /*
- * Setup callbacks
- */
- XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
- (void *) emacps_send_handler,
- (void *) xemacpsif);
-
- XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
- (void *) emacps_recv_handler,
- (void *) xemacpsif);
-
- XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
- (void *) emacps_error_handler,
- (void *) xemacpsif);
-}
-
-void start_emacps (xemacpsif_s *xemacps)
-{
- /* start the temac */
- XEmacPs_Start(&xemacps->emacps);
-}
-
-extern struct xtopology_t xXTopology;
-
-volatile int error_msg_count = 0;
-volatile const char *last_err_msg = "";
-
-struct xERROR_MSG {
- void *arg;
- u8 Direction;
- u32 ErrorWord;
-};
-
-static struct xERROR_MSG xErrorList[ 8 ];
-static BaseType_t xErrorHead, xErrorTail;
-
-void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)
-{
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- xemacpsif_s *xemacpsif;
- BaseType_t xNextHead = xErrorHead;
-
- xemacpsif = (xemacpsif_s *)(arg);
-
- if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
- {
- if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
- xNextHead = 0;
- if( xNextHead != xErrorTail )
- {
-
- xErrorList[ xErrorHead ].arg = arg;
- xErrorList[ xErrorHead ].Direction = Direction;
- xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
-
- xErrorHead = xNextHead;
-
- xemacpsif = (xemacpsif_s *)(arg);
- xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
- }
-
- if( xEMACTaskHandle != NULL )
- {
- vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
- }
-
- }
-
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-
-static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);
-
-int emacps_check_errors( xemacpsif_s *xemacps )
-{
-int xResult;
-
- ( void ) xemacps;
-
- if( xErrorHead == xErrorTail )
- {
- xResult = 0;
- }
- else
- {
- xResult = 1;
- emacps_handle_error(
- xErrorList[ xErrorTail ].arg,
- xErrorList[ xErrorTail ].Direction,
- xErrorList[ xErrorTail ].ErrorWord );
- }
-
- return xResult;
-}
-
-BaseType_t xNetworkInterfaceInitialise( void );
-
-static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
-{
- xemacpsif_s *xemacpsif;
- struct xtopology_t *xtopologyp;
- XEmacPs *xemacps;
-
- xemacpsif = (xemacpsif_s *)(arg);
-
- xtopologyp = &xXTopology;
-
- xemacps = &xemacpsif->emacps;
-
- /* Do not appear to be used. */
- ( void ) xemacps;
- ( void ) xtopologyp;
-
- last_err_msg = NULL;
-
- if( ErrorWord != 0 )
- {
- switch (Direction) {
- case XEMACPS_RECV:
- if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
- {
- last_err_msg = "Receive DMA error";
- xNetworkInterfaceInitialise( );
- }
- if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
- {
- last_err_msg = "Receive over run";
- emacps_recv_handler(arg);
- }
- if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
- {
- last_err_msg = "Receive buffer not available";
- emacps_recv_handler(arg);
- }
- break;
- case XEMACPS_SEND:
- if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
- {
- last_err_msg = "Transmit DMA error";
- xNetworkInterfaceInitialise( );
- }
- if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
- {
- last_err_msg = "Transmit under run";
- HandleTxErrors( xemacpsif );
- }
- if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
- {
- last_err_msg = "Transmit buffer exhausted";
- HandleTxErrors( xemacpsif );
- }
- if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
- {
- last_err_msg = "Transmit retry excessed limits";
- HandleTxErrors( xemacpsif );
- }
- if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
- {
- last_err_msg = "Transmit collision";
- emacps_check_tx( xemacpsif );
- }
- break;
- }
- }
- // Break on this statement and inspect error_msg if you like
- if( last_err_msg != NULL )
- {
- error_msg_count++;
- FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
- }
-}
-
-extern XEmacPs_Config mac_config;
-
-void HandleTxErrors(xemacpsif_s *xemacpsif)
-{
- u32 netctrlreg;
-
- //taskENTER_CRITICAL()
- {
- netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET);
- netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
- XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET, netctrlreg);
-
- clean_dma_txdescs( xemacpsif );
- netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET);
- netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
- XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET, netctrlreg);
- }
- //taskEXIT_CRITICAL( );
-}
+/* + * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved. + * + * Xilinx, Inc. + * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A + * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS + * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR + * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION + * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE + * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. + * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO + * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO + * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE + * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + + +/* Standard includes. */ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#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" + +extern TaskHandle_t xEMACTaskHandle; + +/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c + *** to run it on a PEEP board + ***/ + +unsigned int link_speed = 100; + +void setup_isr( xemacpsif_s *xemacpsif ) +{ + /* + * Setup callbacks + */ + XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND, + (void *) emacps_send_handler, + (void *) xemacpsif); + + XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV, + (void *) emacps_recv_handler, + (void *) xemacpsif); + + XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR, + (void *) emacps_error_handler, + (void *) xemacpsif); +} + +void start_emacps (xemacpsif_s *xemacps) +{ + /* start the temac */ + XEmacPs_Start(&xemacps->emacps); +} + +extern struct xtopology_t xXTopology; + +volatile int error_msg_count = 0; +volatile const char *last_err_msg = ""; + +struct xERROR_MSG { + void *arg; + u8 Direction; + u32 ErrorWord; +}; + +static struct xERROR_MSG xErrorList[ 8 ]; +static BaseType_t xErrorHead, xErrorTail; + +void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xemacpsif_s *xemacpsif; + BaseType_t xNextHead = xErrorHead; + + xemacpsif = (xemacpsif_s *)(arg); + + if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) ) + { + if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) ) + xNextHead = 0; + if( xNextHead != xErrorTail ) + { + + xErrorList[ xErrorHead ].arg = arg; + xErrorList[ xErrorHead ].Direction = Direction; + xErrorList[ xErrorHead ].ErrorWord = ErrorWord; + + xErrorHead = xNextHead; + + xemacpsif = (xemacpsif_s *)(arg); + xemacpsif->isr_events |= EMAC_IF_ERR_EVENT; + } + + if( xEMACTaskHandle != NULL ) + { + vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); + } + + } + + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); +} + +static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord); + +int emacps_check_errors( xemacpsif_s *xemacps ) +{ +int xResult; + + ( void ) xemacps; + + if( xErrorHead == xErrorTail ) + { + xResult = 0; + } + else + { + xResult = 1; + emacps_handle_error( + xErrorList[ xErrorTail ].arg, + xErrorList[ xErrorTail ].Direction, + xErrorList[ xErrorTail ].ErrorWord ); + } + + return xResult; +} + +BaseType_t xNetworkInterfaceInitialise( void ); + +static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord) +{ + xemacpsif_s *xemacpsif; + struct xtopology_t *xtopologyp; + XEmacPs *xemacps; + + xemacpsif = (xemacpsif_s *)(arg); + + xtopologyp = &xXTopology; + + xemacps = &xemacpsif->emacps; + + /* Do not appear to be used. */ + ( void ) xemacps; + ( void ) xtopologyp; + + last_err_msg = NULL; + + if( ErrorWord != 0 ) + { + switch (Direction) { + case XEMACPS_RECV: + if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 ) + { + last_err_msg = "Receive DMA error"; + xNetworkInterfaceInitialise( ); + } + if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 ) + { + last_err_msg = "Receive over run"; + emacps_recv_handler(arg); + } + if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 ) + { + last_err_msg = "Receive buffer not available"; + emacps_recv_handler(arg); + } + break; + case XEMACPS_SEND: + if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 ) + { + last_err_msg = "Transmit DMA error"; + xNetworkInterfaceInitialise( ); + } + if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 ) + { + last_err_msg = "Transmit under run"; + HandleTxErrors( xemacpsif ); + } + if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 ) + { + last_err_msg = "Transmit buffer exhausted"; + HandleTxErrors( xemacpsif ); + } + if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 ) + { + last_err_msg = "Transmit retry excessed limits"; + HandleTxErrors( xemacpsif ); + } + if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 ) + { + last_err_msg = "Transmit collision"; + emacps_check_tx( xemacpsif ); + } + break; + } + } + // Break on this statement and inspect error_msg if you like + if( last_err_msg != NULL ) + { + error_msg_count++; + FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) ); + } +} + +extern XEmacPs_Config mac_config; + +void HandleTxErrors(xemacpsif_s *xemacpsif) +{ + u32 netctrlreg; + + //taskENTER_CRITICAL() + { + netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, netctrlreg); + + clean_dma_txdescs( xemacpsif ); + netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, netctrlreg); + } + //taskEXIT_CRITICAL( ); +} diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.h index f3c424a4b..7b0e4fd36 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.h @@ -1,39 +1,39 @@ -/*
- * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#ifndef __XEMACPSIF_HW_H_
-#define __XEMACPSIF_HW_H_
-
-#include "Zynq/x_emacpsif.h"
-//#include "lwip/netif.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-XEmacPs_Config * lookup_config(unsigned mac_base);
-
-//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);
-
-int emacps_check_errors( xemacpsif_s *xemacps );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/* + * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved. + * + * Xilinx, Inc. + * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A + * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS + * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR + * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION + * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE + * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. + * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO + * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO + * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE + * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __XEMACPSIF_HW_H_ +#define __XEMACPSIF_HW_H_ + +#include "Zynq/x_emacpsif.h" +//#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +XEmacPs_Config * lookup_config(unsigned mac_base); + +//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif); + +int emacps_check_errors( xemacpsif_s *xemacps ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c index 12b8c60c8..742ff8b96 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c @@ -1,585 +1,585 @@ -/*
- * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Advanced Micro Devices, Inc. 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
- * OWNER 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.
- */
-
-/*
- * Some portions copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#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"
-
-int phy_detected = 0;
-
-/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
- *** to run it on a PEEP board
- ***/
-
-/* Advertisement control register. */
-#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_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \
- ADVERTISE_10HALF | ADVERTISE_100HALF)
-#define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF)
-#define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF)
-
-#define ADVERTISE_1000 0x0300
-
-
-//#define PHY_REG_00_BMCR 0x00 // Basic mode control register
-//#define PHY_REG_01_BMSR 0x01 // Basic mode status register
-//#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
-//#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
-//#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
-
-#define IEEE_CONTROL_REG_OFFSET 0
-#define IEEE_STATUS_REG_OFFSET 1
-#define IEEE_AUTONEGO_ADVERTISE_REG 4
-#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5
-#define IEEE_1000_ADVERTISE_REG_OFFSET 9
-#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10
-#define IEEE_COPPER_SPECIFIC_CONTROL_REG 16
-#define IEEE_SPECIFIC_STATUS_REG 17
-#define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19
-#define IEEE_CONTROL_REG_MAC 21
-#define IEEE_PAGE_ADDRESS_REGISTER 22
-
-
-#define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040
-#define IEEE_CTRL_LINKSPEED_MASK 0x0040
-#define IEEE_CTRL_LINKSPEED_1000M 0x0040
-#define IEEE_CTRL_LINKSPEED_100M 0x2000
-#define IEEE_CTRL_LINKSPEED_10M 0x0000
-#define IEEE_CTRL_RESET_MASK 0x8000
-#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#define IEEE_CTRL_RESET 0x9140
-#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
-#endif
-#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008
-#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020
-#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200
-#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100
-#define IEEE_AN1_ABILITY_MASK 0x1FE0
-#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00
-#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380
-#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060
-#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030
-
-#define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800
-#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
-#define XEMACPS_GMII2RGMII_REG_NUM 0x10
-
-/* Frequency setting */
-#define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4)
-#define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8)
-#define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)
-#define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)
-#ifdef PEEP
-#define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031
-#define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001
-#define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011
-#endif
-#define SLCR_LOCK_KEY_VALUE 0x767B
-#define SLCR_UNLOCK_KEY_VALUE 0xDF0D
-#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214)
-#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF
-
-#define EMAC0_BASE_ADDRESS 0xE000B000
-#define EMAC1_BASE_ADDRESS 0xE000C000
-
-static int detect_phy(XEmacPs *xemacpsp)
-{
- 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;
- }
- }
-
- FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\n" ) );
-
- /* default to zero */
- return 0;
-}
-
-#ifdef PEEP
-unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
-{
-
- u16 control;
- u16 status;
- u16 partner_capabilities;
- u16 partner_capabilities_1000;
- u16 phylinkspeed;
- u32 phy_addr = detect_phy(xemacpsp);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
- ADVERTISE_1000);
- /* Advertise PHY speed of 100 and 10 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
- ADVERTISE_100_AND_10);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
- &control);
- control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |
- IEEE_STAT_AUTONEGOTIATE_RESTART);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
-
- /* Read PHY control and status registers is successful. */
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-
- if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &
- IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {
-
- while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
- &status);
- }
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
- &partner_capabilities);
-
- if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,
- &partner_capabilities_1000);
- if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)
- return 1000;
- }
-
- if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)
- return 100;
- if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)
- return 10;
-
- xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",
- __FUNCTION__);
- return 10;
-
- } else {
-
- /* Update TEMAC speed accordingly */
- if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
- /* Get commanded link speed */
- phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;
-
- switch (phylinkspeed) {
- case (IEEE_CTRL_LINKSPEED_1000M):
- return 1000;
- case (IEEE_CTRL_LINKSPEED_100M):
- return 100;
- case (IEEE_CTRL_LINKSPEED_10M):
- return 10;
- default:
- xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",
- __FUNCTION__, phylinkspeed);
- return 10;
- }
-
- } else {
-
- return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;
-
- }
- }
-}
-
-#else /* Zynq */
-unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
-{
- u16 temp;
- u16 control;
- u16 status;
- u16 partner_capabilities;
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
- u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
-#else
- u32 phy_addr = detect_phy(xemacpsp);
-#endif
- xil_printf("Start PHY autonegotiation \r\n");
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
- XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
- control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
- control |= IEEE_ASYMMETRIC_PAUSE_MASK;
- control |= IEEE_PAUSE_MASK;
- control |= ADVERTISE_100;
- control |= ADVERTISE_10;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
- &control);
- control |= ADVERTISE_1000;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
- control);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
- &control);
- control |= (7 << 12); /* max number of gigabit attempts */
- control |= (1 << 11); /* enable downshift */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
- control);
-#endif
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
- control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
- control &= IEEE_CTRL_ISOLATE_DISABLE;
-#endif
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
-
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- control |= IEEE_CTRL_RESET_MASK;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
-
- while (1) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- if (control & IEEE_CTRL_RESET_MASK)
- continue;
- else
- break;
- }
-#endif
- 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) ) {
- 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) {
- xil_printf("Auto negotiation error \r\n");
- }
-#endif
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
- &status);
- }
-
- xil_printf("autonegotiation complete \r\n");
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);
-#endif
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
- 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);
- }
- if((temp & 0x0C00) == 0x0800) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
- return 1000;
- }
- else if((temp & 0x0C00) == 0x0400) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
- return 100;
- }
- else if((temp & 0x0C00) == 0x0000) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
- return 10;
- } else {
- 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;
- }
-#else
- if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */
- return 1000;
- else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */
- return 100;
- else /* 10Mbps */
- return 10;
-#endif
-}
-#endif
-
-unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)
-{
- u16 control;
- u32 phy_addr = detect_phy(xemacpsp);
-
- XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
- control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
- control |= IEEE_ASYMMETRIC_PAUSE_MASK;
- control |= IEEE_PAUSE_MASK;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- control &= ~IEEE_CTRL_LINKSPEED_1000M;
- control &= ~IEEE_CTRL_LINKSPEED_100M;
- control &= ~IEEE_CTRL_LINKSPEED_10M;
-
- if (speed == 1000) {
- control |= IEEE_CTRL_LINKSPEED_1000M;
- }
-
- else if (speed == 100) {
- control |= IEEE_CTRL_LINKSPEED_100M;
- /* Dont advertise PHY speed of 1000 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);
- /* Dont advertise PHY speed of 10 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
- ADVERTISE_100);
- }
-
- else if (speed == 10) {
- control |= IEEE_CTRL_LINKSPEED_10M;
- /* Dont advertise PHY speed of 1000 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
- 0);
- /* Dont advertise PHY speed of 100 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
- ADVERTISE_10);
- }
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
- control | IEEE_CTRL_RESET_MASK);
- {
- volatile int wait;
- for (wait=0; wait < 100000; wait++);
- }
- return 0;
-}
-
-static void SetUpSLCRDivisors(int mac_baseaddr, int speed)
-{
- volatile u32 slcrBaseAddress;
-#ifndef PEEP
- u32 SlcrDiv0;
- u32 SlcrDiv1=0;
- u32 SlcrTxClkCntrl;
-#endif
-
- *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
-
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
- slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
- } else {
- slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
- }
-#ifdef PEEP
- if (speed == 1000) {
- *(volatile unsigned int *)(slcrBaseAddress) =
- SLCR_GEM_1G_CLK_CTRL_VALUE;
- } else if (speed == 100) {
- *(volatile unsigned int *)(slcrBaseAddress) =
- SLCR_GEM_100M_CLK_CTRL_VALUE;
- } else {
- *(volatile unsigned int *)(slcrBaseAddress) =
- SLCR_GEM_10M_CLK_CTRL_VALUE;
- }
-#else
- if (speed == 1000) {
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
-#endif
- } else {
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
-#endif
- }
- } else if (speed == 100) {
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
-#endif
- } else {
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
-#endif
- }
- } else {
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
-#endif
- } else {
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
-#endif
- }
- }
- SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);
- SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
- SlcrTxClkCntrl |= (SlcrDiv1 << 20);
- SlcrTxClkCntrl |= (SlcrDiv0 << 8);
- *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;
-#endif
- *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
- return;
-}
-
-
-unsigned link_speed;
-unsigned Phy_Setup (XEmacPs *xemacpsp)
-{
- unsigned long conv_present = 0;
- unsigned long convspeeddupsetting = 0;
- unsigned long convphyaddr = 0;
-
-#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
- convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
- conv_present = 1;
-#else
-#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
- convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
- conv_present = 1;
-#endif
-#endif
-
-#ifdef ipconfigNIC_LINKSPEED_AUTODETECT
- link_speed = get_IEEE_phy_speed(xemacpsp);
- if (link_speed == 1000) {
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
- } else if (link_speed == 100) {
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
- } else {
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
- }
-#elif defined(ipconfigNIC_LINKSPEED1000)
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
- link_speed = 1000;
- configure_IEEE_phy_speed(xemacpsp, link_speed);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
- 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;
- 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;
- sleep(1);
-#endif
- if (conv_present) {
- XEmacPs_PhyWrite(xemacpsp, convphyaddr,
- XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
- }
-
- xil_printf("link speed: %d\r\n", link_speed);
- return link_speed;
-}
-
+/* + * Copyright (c) 2007-2008, Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Advanced Micro Devices, Inc. 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 + * OWNER 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. + */ + +/* + * Some portions copyright (c) 2010-2013 Xilinx, Inc. All rights reserved. + * + * Xilinx, Inc. + * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A + * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS + * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR + * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION + * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE + * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. + * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO + * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO + * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE + * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +/* Standard includes. */ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#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" + +int phy_detected = 0; + +/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c + *** to run it on a PEEP board + ***/ + +/* Advertisement control register. */ +#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_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \ + ADVERTISE_10HALF | ADVERTISE_100HALF) +#define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF) +#define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF) + +#define ADVERTISE_1000 0x0300 + + +//#define PHY_REG_00_BMCR 0x00 // Basic mode control register +//#define PHY_REG_01_BMSR 0x01 // Basic mode status register +//#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1 +//#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2 +//#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg + +#define IEEE_CONTROL_REG_OFFSET 0 +#define IEEE_STATUS_REG_OFFSET 1 +#define IEEE_AUTONEGO_ADVERTISE_REG 4 +#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5 +#define IEEE_1000_ADVERTISE_REG_OFFSET 9 +#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10 +#define IEEE_COPPER_SPECIFIC_CONTROL_REG 16 +#define IEEE_SPECIFIC_STATUS_REG 17 +#define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19 +#define IEEE_CONTROL_REG_MAC 21 +#define IEEE_PAGE_ADDRESS_REGISTER 22 + + +#define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040 +#define IEEE_CTRL_LINKSPEED_MASK 0x0040 +#define IEEE_CTRL_LINKSPEED_1000M 0x0040 +#define IEEE_CTRL_LINKSPEED_100M 0x2000 +#define IEEE_CTRL_LINKSPEED_10M 0x0000 +#define IEEE_CTRL_RESET_MASK 0x8000 +#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000 +#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 +#define IEEE_CTRL_RESET 0x9140 +#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF +#endif +#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008 +#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020 +#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200 +#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100 +#define IEEE_AN1_ABILITY_MASK 0x1FE0 +#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00 +#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380 +#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060 +#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030 + +#define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800 +#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 +#define XEMACPS_GMII2RGMII_REG_NUM 0x10 + +/* Frequency setting */ +#define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4) +#define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8) +#define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140) +#define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144) +#ifdef PEEP +#define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031 +#define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001 +#define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011 +#endif +#define SLCR_LOCK_KEY_VALUE 0x767B +#define SLCR_UNLOCK_KEY_VALUE 0xDF0D +#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214) +#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF + +#define EMAC0_BASE_ADDRESS 0xE000B000 +#define EMAC1_BASE_ADDRESS 0xE000C000 + +static int detect_phy(XEmacPs *xemacpsp) +{ + 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; + } + } + + FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\n" ) ); + + /* default to zero */ + return 0; +} + +#ifdef PEEP +unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) +{ + + u16 control; + u16 status; + u16 partner_capabilities; + u16 partner_capabilities_1000; + u16 phylinkspeed; + u32 phy_addr = detect_phy(xemacpsp); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + ADVERTISE_1000); + /* Advertise PHY speed of 100 and 10 Mbps */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, + ADVERTISE_100_AND_10); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, + &control); + control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE | + IEEE_STAT_AUTONEGOTIATE_RESTART); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + /* Read PHY control and status registers is successful. */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status & + IEEE_STAT_AUTONEGOTIATE_CAPABLE)) { + + while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, + &status); + } + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, + &partner_capabilities); + + if (status & IEEE_STAT_1GBPS_EXTENSIONS) { + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET, + &partner_capabilities_1000); + if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS) + return 1000; + } + + if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS) + return 100; + if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS) + return 10; + + xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n", + __FUNCTION__); + return 10; + + } else { + + /* Update TEMAC speed accordingly */ + if (status & IEEE_STAT_1GBPS_EXTENSIONS) { + /* Get commanded link speed */ + phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK; + + switch (phylinkspeed) { + case (IEEE_CTRL_LINKSPEED_1000M): + return 1000; + case (IEEE_CTRL_LINKSPEED_100M): + return 100; + case (IEEE_CTRL_LINKSPEED_10M): + return 10; + default: + xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n", + __FUNCTION__, phylinkspeed); + return 10; + } + + } else { + + return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10; + + } + } +} + +#else /* Zynq */ +unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) +{ + u16 temp; + u16 control; + u16 status; + u16 partner_capabilities; +#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 + u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR; +#else + u32 phy_addr = detect_phy(xemacpsp); +#endif + xil_printf("Start PHY autonegotiation \r\n"); + +#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 +#else + XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); + control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); + control |= IEEE_ASYMMETRIC_PAUSE_MASK; + control |= IEEE_PAUSE_MASK; + control |= ADVERTISE_100; + control |= ADVERTISE_10; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + &control); + control |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, + &control); + control |= (7 << 12); /* max number of gigabit attempts */ + control |= (1 << 11); /* enable downshift */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, + control); +#endif + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; + control |= IEEE_STAT_AUTONEGOTIATE_RESTART; +#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 + control &= IEEE_CTRL_ISOLATE_DISABLE; +#endif + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + +#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 +#else + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_RESET_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + while (1) { + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + if (control & IEEE_CTRL_RESET_MASK) + continue; + else + break; + } +#endif + 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) ) { + 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) { + xil_printf("Auto negotiation error \r\n"); + } +#endif + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, + &status); + } + + xil_printf("autonegotiation complete \r\n"); + +#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 +#else + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities); +#endif + +#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 + 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); + } + if((temp & 0x0C00) == 0x0800) { + XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp); + return 1000; + } + else if((temp & 0x0C00) == 0x0400) { + XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp); + return 100; + } + else if((temp & 0x0C00) == 0x0000) { + XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp); + return 10; + } else { + 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; + } +#else + if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */ + return 1000; + else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */ + return 100; + else /* 10Mbps */ + return 10; +#endif +} +#endif + +unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed) +{ + u16 control; + u32 phy_addr = detect_phy(xemacpsp); + + XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); + control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); + control |= IEEE_ASYMMETRIC_PAUSE_MASK; + control |= IEEE_PAUSE_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control &= ~IEEE_CTRL_LINKSPEED_1000M; + control &= ~IEEE_CTRL_LINKSPEED_100M; + control &= ~IEEE_CTRL_LINKSPEED_10M; + + if (speed == 1000) { + control |= IEEE_CTRL_LINKSPEED_1000M; + } + + else if (speed == 100) { + control |= IEEE_CTRL_LINKSPEED_100M; + /* Dont advertise PHY speed of 1000 Mbps */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0); + /* Dont advertise PHY speed of 10 Mbps */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, + ADVERTISE_100); + } + + else if (speed == 10) { + control |= IEEE_CTRL_LINKSPEED_10M; + /* Dont advertise PHY speed of 1000 Mbps */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + 0); + /* Dont advertise PHY speed of 100 Mbps */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, + ADVERTISE_10); + } + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, + control | IEEE_CTRL_RESET_MASK); + { + volatile int wait; + for (wait=0; wait < 100000; wait++); + } + return 0; +} + +static void SetUpSLCRDivisors(int mac_baseaddr, int speed) +{ + volatile u32 slcrBaseAddress; +#ifndef PEEP + u32 SlcrDiv0; + u32 SlcrDiv1=0; + u32 SlcrTxClkCntrl; +#endif + + *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE; + + if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) { + slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR; + } else { + slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR; + } +#ifdef PEEP + if (speed == 1000) { + *(volatile unsigned int *)(slcrBaseAddress) = + SLCR_GEM_1G_CLK_CTRL_VALUE; + } else if (speed == 100) { + *(volatile unsigned int *)(slcrBaseAddress) = + SLCR_GEM_100M_CLK_CTRL_VALUE; + } else { + *(volatile unsigned int *)(slcrBaseAddress) = + SLCR_GEM_10M_CLK_CTRL_VALUE; + } +#else + if (speed == 1000) { + if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) { +#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1; +#endif + } else { +#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1; +#endif + } + } else if (speed == 100) { + if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) { +#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1; +#endif + } else { +#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1; +#endif + } + } else { + if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) { +#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1; +#endif + } else { +#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1; +#endif + } + } + SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress); + SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK; + SlcrTxClkCntrl |= (SlcrDiv1 << 20); + SlcrTxClkCntrl |= (SlcrDiv0 << 8); + *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl; +#endif + *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE; + return; +} + + +unsigned link_speed; +unsigned Phy_Setup (XEmacPs *xemacpsp) +{ + unsigned long conv_present = 0; + unsigned long convspeeddupsetting = 0; + unsigned long convphyaddr = 0; + +#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR + convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR; + conv_present = 1; +#else +#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR + convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR; + conv_present = 1; +#endif +#endif + +#ifdef ipconfigNIC_LINKSPEED_AUTODETECT + link_speed = get_IEEE_phy_speed(xemacpsp); + if (link_speed == 1000) { + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD; + } else if (link_speed == 100) { + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD; + } else { + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD; + } +#elif defined(ipconfigNIC_LINKSPEED1000) + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000); + link_speed = 1000; + configure_IEEE_phy_speed(xemacpsp, link_speed); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD; + 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; + 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; + sleep(1); +#endif + if (conv_present) { + XEmacPs_PhyWrite(xemacpsp, convphyaddr, + XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting); + } + + xil_printf("link speed: %d\r\n", link_speed); + return link_speed; +} + diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_topology.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_topology.h index bb5178346..1d8fede15 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_topology.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_topology.h @@ -1,46 +1,46 @@ -/*
- * Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#ifndef __XTOPOLOGY_H_
-#define __XTOPOLOGY_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };
-
-struct xtopology_t {
- unsigned emac_baseaddr;
- enum xemac_types emac_type;
- unsigned intc_baseaddr;
- unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */
- unsigned scugic_baseaddr; /* valid only for Zynq */
- unsigned scugic_emac_intr; /* valid only for GEM */
-};
-
-extern int x_topology_n_emacs;
-extern struct xtopology_t x_topology[];
-
-int x_topology_find_index(unsigned base);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/* + * Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved. + * + * Xilinx, Inc. + * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A + * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS + * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR + * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION + * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE + * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. + * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO + * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO + * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE + * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __XTOPOLOGY_H_ +#define __XTOPOLOGY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps }; + +struct xtopology_t { + unsigned emac_baseaddr; + enum xemac_types emac_type; + unsigned intc_baseaddr; + unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */ + unsigned scugic_baseaddr; /* valid only for Zynq */ + unsigned scugic_emac_intr; /* valid only for GEM */ +}; + +extern int x_topology_n_emacs; +extern struct xtopology_t x_topology[]; + +int x_topology_find_index(unsigned base); + +#ifdef __cplusplus +} +#endif + +#endif |