Sync up with Amazon-freertos repo (10th March 2020) (#34)

* Sync up with amazon-freertos

* Sync up with amazon-freertos

* Sync up with amazon-freertos
This commit is contained in:
AniruddhaKanhere 2020-03-11 10:19:48 -07:00 committed by GitHub
parent 0acffef047
commit ecf0f12aa1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1645 additions and 7927 deletions

View file

@ -305,7 +305,15 @@ static void prvEMACDeferredInterruptHandlerTask( void * pvParameters )
if( xBytesReceived < 0 )
{
/* This is an error. Logged. */
FreeRTOS_printf( ( "R_ETHER_Read_ZC2: rc = %d\n", xBytesReceived ) );
if( xBytesReceived == ETHER_ERR_LINK )
{
/* Auto-negotiation is not completed, and transmission/
reception is not enabled. Will be logged elsewhere. */
}
else
{
FreeRTOS_printf( ( "R_ETHER_Read_ZC2: rc = %d not %d\n", xBytesReceived, ETHER_ERR_LINK ) );
}
}
else if( xBytesReceived > 0 )
{
@ -452,7 +460,6 @@ void prvLinkStatusChange( BaseType_t xStatus )
{
if( xReportedStatus != xStatus )
{
FreeRTOS_printf( ( "prvLinkStatusChange( %d )\n", xStatus ) );
xReportedStatus = xStatus;
}
}

View file

@ -0,0 +1,81 @@
This is a FreeeRTOS+TCP driver that works for both STM32F4xx and STM32F7xx parts.
The code of stm32fxx_hal_eth.c is based on both drivers as provided by ST.
These modules should be included:
NetworkInterface.c
stm32fxx_hal_eth.c
It is assumed that one of these words are defined:
STM32F7xx
STM32F407xx
STM32F417xx
STM32F427xx
STM32F437xx
STM32F429xx
STM32F439xx
The driver has been tested on both Eval and Discovery boards with both STM32F4 and STM32F7.
Recommended settings for STM32Fxx Network Interface:
// Defined in FreeRTOSIPConfig.h
#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1
#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 1
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1
#define ipconfigZERO_COPY_RX_DRIVER 1
#define ipconfigZERO_COPY_TX_DRIVER 1
#define ipconfigUSE_LINKED_RX_MESSAGES 1
// Defined in stm32f4xx_hal_conf.h
#define ETH_RXBUFNB 3 or 4
#define ETH_TXBUFNB 2 or 3
#define ETH_RX_BUF_SIZE ( ipconfigNETWORK_MTU + 36 )
#define ETH_TX_BUF_SIZE ( ipconfigNETWORK_MTU + 36 )
The best size for 'ETH_RXBUFNB' and 'ETH_TXBUFNB' depends on the speed of the CPU. These macro's define the number of DMA buffers for reception and for transmission.
In general, if the CPU is very fast, you will need less buffers. You can obtain an estimate empirically.
The optimal value of 'ETH_RX_BUF_SIZE' and 'ETH_TX_BUF_SIZE' depends on the actual value of 'ipconfigNETWORK_MTU'.
When MTU is 1500, MTU+36 becomes a well-aligned buffer of 1536 bytes ( 0x600 ).
When MTU is 1200, MTU+48 will make 1248 ( 0x4E0 ), which is also well aligned.
Having well aligned buffers is important for CPU with memory cache. Often the caching system divides memory in blocks of 32 bytes. When two buffers share the same cache buffer, you are bound to see data errors.
Without memory caching, let the size be at least a multiple of 8 ( for DMA ), and make it at least "ipconfigNETWORK_MTU + 14".
STM32F7xx only:
Networkinterface.c will place the 2 DMA tables in a special section called 'first_data'.
In case 'BufferAllocation_1.c' is used, the network packets will also be declared in this section 'first_data'.
As long as the part has no caching, this section can be placed anywhere in RAM.
On an STM32F7 with an L1 data cache, it shall be placed in the first 64KB of RAM, which is always uncached.
The linker script must be changed for this, for instance as follows:
.data :
{
. = ALIGN(4);
_sdata = .; // create a global symbol at data start
+ *(.first_data) // .first_data sections
*(.data) // .data sections
*(.data*) // .data* sections
. = ALIGN(4);
_edata = .; // define a global symbol at data end
} >RAM AT> FLASH
The driver contains these files:
stm32fxx_hal_eth.c
stm32f2xx_hal_eth.h
stm32f4xx_hal_eth.h
stm32f7xx_hal_eth.h
stm32fxx_hal_eth.h
These files are copied from ST's HAL library. These work both for STM32F4 and STM32F7.
Please remove or rename these files from the HAL distribution that you are using.

View file

@ -1,27 +1,27 @@
/*
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
*/
* FreeRTOS V202002.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/* Standard includes. */
#include <stdint.h>
@ -38,6 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
@ -50,10 +51,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* Provided memory configured as uncached. */
#include "uncached_memory.h"
#ifndef BMSR_LINK_STATUS
#define BMSR_LINK_STATUS 0x0004UL
#ifndef niEMAC_HANDLER_TASK_PRIORITY
/* Define the priority of the task prvEMACHandlerTask(). */
#define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1
#endif
#define niBMSR_LINK_STATUS 0x0004uL
#ifndef PHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
receiving packets. */
@ -83,6 +87,13 @@ FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
#define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
#endif
#if( ipconfigZERO_COPY_RX_DRIVER == 0 || ipconfigZERO_COPY_TX_DRIVER == 0 )
#error Please define both 'ipconfigZERO_COPY_RX_DRIVER' and 'ipconfigZERO_COPY_TX_DRIVER' as 1
#endif
#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 || ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
#warning Please define both 'ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM' and 'ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM' as 1
#endif
/*-----------------------------------------------------------*/
/*
@ -96,6 +107,10 @@ static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );
*/
static void prvEMACHandlerTask( void *pvParameters );
#if ( ipconfigHAS_PRINTF != 0 )
static void prvMonitorResources( void );
#endif
/*-----------------------------------------------------------*/
/* EMAC data/descriptions. */
@ -119,7 +134,7 @@ XEmacPs_Config mac_config =
extern int phy_detected;
/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
static uint32_t ulPHYLinkStatus = 0;
static uint32_t ulPHYLinkStatus = 0uL;
#if( ipconfigUSE_LLMNR == 1 )
static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
@ -188,7 +203,7 @@ const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pd
possible priority to ensure the interrupt handler can return directly
to it. The task's handle is stored in xEMACTaskHandle so interrupts can
notify the task when there is something to process. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle );
}
else
{
@ -206,7 +221,24 @@ const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pd
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )
{
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
{
ProtocolPacket_t *pxPacket;
/* If the peripheral must calculate the checksum, it wants
the protocol checksum to have a value of zero. */
pxPacket = ( ProtocolPacket_t * ) ( pxBuffer->pucEthernetBuffer );
if( ( pxPacket->xICMPPacket.xIPHeader.ucProtocol != ipPROTOCOL_UDP ) &&
( pxPacket->xICMPPacket.xIPHeader.ucProtocol != ipPROTOCOL_TCP ) )
{
/* The EMAC will calculate the checksum of the IP-header.
It can only calculate protocol checksums of UDP and TCP,
so for ICMP and other protocols it must be done manually. */
usGenerateProtocolChecksum( (uint8_t*)&( pxPacket->xUDPPacket ), pxBuffer->xDataLength, pdTRUE );
}
}
#endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */
if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL )
{
iptraceNETWORK_INTERFACE_TRANSMIT();
emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
@ -249,7 +281,7 @@ BaseType_t xReturn;
}
ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL )
{
xReturn = pdTRUE;
break;
@ -281,7 +313,7 @@ BaseType_t xGetPhyLinkStatus( void )
{
BaseType_t xReturn;
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) == 0uL )
{
xReturn = pdFALSE;
}
@ -294,12 +326,58 @@ BaseType_t xReturn;
}
/*-----------------------------------------------------------*/
#if ( ipconfigHAS_PRINTF != 0 )
static void prvMonitorResources()
{
static UBaseType_t uxLastMinBufferCount = 0u;
static size_t uxMinLastSize = 0uL;
UBaseType_t uxCurrentBufferCount;
size_t uxMinSize;
uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();
if( uxLastMinBufferCount != uxCurrentBufferCount )
{
/* The logging produced below may be helpful
* while tuning +TCP: see how many buffers are in use. */
uxLastMinBufferCount = uxCurrentBufferCount;
FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
uxGetNumberOfFreeNetworkBuffers(),
uxCurrentBufferCount ) );
}
uxMinSize = xPortGetMinimumEverFreeHeapSize();
if( uxMinLastSize != uxMinSize )
{
uxMinLastSize = uxMinSize;
FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", xPortGetFreeHeapSize(), uxMinSize ) );
}
#if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
{
static UBaseType_t uxLastMinQueueSpace = 0;
UBaseType_t uxCurrentCount = 0u;
uxCurrentCount = uxGetMinimumIPQueueSpace();
if( uxLastMinQueueSpace != uxCurrentCount )
{
/* The logging produced below may be helpful
* while tuning +TCP: see how many buffers are in use. */
uxLastMinQueueSpace = uxCurrentCount;
FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
}
}
#endif /* ipconfigCHECK_IP_QUEUE_SPACE */
}
#endif /* ( ipconfigHAS_PRINTF != 0 ) */
/*-----------------------------------------------------------*/
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 );
@ -316,30 +394,11 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
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 )
#if ( ipconfigHAS_PRINTF != 0 )
{
/* 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 ) );
prvMonitorResources();
}
}
#endif /* ipconfigCHECK_IP_QUEUE_SPACE */
#endif /* ipconfigHAS_PRINTF != 0 ) */
if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )
{
@ -372,19 +431,26 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
xResult = 0;
if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) == 0uL )
{
/* Indicate that the Link Status is high, so that
xNetworkInterfaceOutput() can send packets. */
ulPHYLinkStatus |= niBMSR_LINK_STATUS;
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS assume 1\n" ) );
}
}
else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
{
xStatus = ulReadMDIO( PHY_REG_01_BMSR );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != ( xStatus & niBMSR_LINK_STATUS ) )
{
ulPHYLinkStatus = xStatus;
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL ) );
}
vTaskSetTimeOutState( &xPhyTime );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL )
{
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
}

View file

@ -5,6 +5,7 @@ NetworkInterface for Xilinx' Zynq
Please include the following source files:
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/NetworkInterface.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/uncached_memory.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
@ -23,3 +24,14 @@ 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
It is recommended to have these defined :
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1
#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 1
#define ipconfigUSE_LINKED_RX_MESSAGES 1
It is obligatory to define:
#define ipconfigZERO_COPY_RX_DRIVER 1
#define ipconfigZERO_COPY_TX_DRIVER 1

View file

@ -1,10 +1,35 @@
/*
* FreeRTOS V202002.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*
* 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
* 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.
@ -43,23 +68,35 @@
#include "uncached_memory.h"
#define UNCACHED_MEMORY_SIZE 0x100000ul
/* Reserve 1 MB of memory. */
#define uncMEMORY_SIZE 0x100000uL
/* Make sure that each pointer has an alignment of 4 KB. */
#define uncALIGNMENT_SIZE 0x1000uL
#define DDR_MEMORY_END (XPAR_PS7_DDR_0_S_AXI_HIGHADDR+1)
#define uncMEMORY_ATTRIBUTE 0x1C02
static void vInitialiseUncachedMemory( void );
static uint8_t *pucHeadOfMemory;
static uint32_t ulMemorySize;
static uint8_t *pucStartOfMemory = NULL;
/* The linker file defines some pseudo variables. '_end' is one of them.
It is located at the first free byte in RAM. */
extern u8 _end;
/*-----------------------------------------------------------*/
uint8_t ucIsCachedMemory( const uint8_t *pucBuffer )
{
uint8_t ucReturn;
if( ( pucStartOfMemory != NULL ) &&
( pucBuffer >= pucStartOfMemory ) &&
( pucBuffer < ( pucStartOfMemory + UNCACHED_MEMORY_SIZE ) ) )
( pucBuffer < ( pucStartOfMemory + uncMEMORY_SIZE ) ) )
{
ucReturn = pdFALSE;
}
@ -70,10 +107,12 @@ uint8_t ucReturn;
return ucReturn;
}
/*-----------------------------------------------------------*/
uint8_t *pucGetUncachedMemory( uint32_t ulSize )
{
uint8_t *pucReturn;
uint32_t ulSkipSize;
if( pucStartOfMemory == NULL )
{
@ -85,48 +124,40 @@ uint8_t *pucReturn;
}
else
{
uint32_t ulSkipSize;
pucReturn = pucHeadOfMemory;
ulSkipSize = ( ulSize + 0x1000ul ) & ~0xffful;
/* Make sure that the next pointer return will have a good alignment. */
ulSkipSize = ( ulSize + uncALIGNMENT_SIZE ) & ~( uncALIGNMENT_SIZE - 1uL );
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 ) ) );
pucStartOfMemory = ( uint8_t * ) &( _end );
if( ( ( u32 )pucStartOfMemory ) + UNCACHED_MEMORY_SIZE > DDR_MEMORY_END )
/* Align the start address to 1 MB boundary. */
pucStartOfMemory = ( uint8_t * )( ( ( uint32_t )pucStartOfMemory + uncMEMORY_SIZE ) & ( ~( uncMEMORY_SIZE - 1 ) ) );
if( ( ( u32 )pucStartOfMemory ) + uncMEMORY_SIZE > DDR_MEMORY_END )
{
// vLoggingPrintf("vInitialiseUncachedMemory: Can not allocate uncached memory\n" );
FreeRTOS_printf( ( "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
/* 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. */
Xil_SetTlbAttributes( ( uint32_t ) pucStartOfMemory, uncMEMORY_ATTRIBUTE );
/* For experiments in the SDIO driver, make the remaining uncached memory public */
/* For experiments in the SDIO driver, make the remaining uncached memory
public */
pucHeadOfMemory = pucStartOfMemory;
ulMemorySize = UNCACHED_MEMORY_SIZE;
memset( pucStartOfMemory, '\0', UNCACHED_MEMORY_SIZE );
ulMemorySize = uncMEMORY_SIZE;
memset( pucStartOfMemory, '\0', uncMEMORY_SIZE );
}
}

View file

@ -26,7 +26,6 @@ extern "C" {
#include <stdint.h>
#include "xstatus.h"
#include "sleep.h"
#include "xparameters.h"
#include "xparameters_ps.h" /* defines XPAR values */
#include "xil_types.h"
@ -35,7 +34,6 @@ extern "C" {
#include "xil_exception.h"
#include "xpseudo_asm.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xuartps.h"
#include "xscugic.h"
#include "xemacps.h" /* defines XEmacPs API */

View file

@ -1,36 +1,27 @@
/*
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"
* FreeRTOS V202002.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#include "FreeRTOS.h"
#include "task.h"
@ -43,6 +34,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
#include "Zynq/x_emacpsif.h"
#include "Zynq/x_topology.h"
#include "xstatus.h"
#include "xparameters.h"
#include "xparameters_ps.h"
#include "xil_exception.h"
#include "xil_mmu.h"
#include "uncached_memory.h"
/* Two defines used to set or clear the EMAC interrupt */
@ -56,7 +56,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#define TX_OFFSET ipconfigPACKET_FILLER_SIZE
#define RX_BUFFER_ALIGNMENT 14
#define dmaRX_TX_BUFFER_SIZE 1536
/* Defined in NetworkInterface.c */
extern TaskHandle_t xEMACTaskHandle;
@ -120,8 +120,6 @@ size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount
{
break;
}
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
#warning ipconfigZERO_COPY_TX_DRIVER is defined
{
void *pvBuffer = pxDMA_tx_buffers[ tail ];
NetworkBufferDescriptor_t *pxBuffer;
@ -140,7 +138,6 @@ size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount
}
}
}
#endif
/* Clear all but the "used" and "wrap" bits. */
if( tail < ipconfigNIC_N_TX_DESC - 1 )
{
@ -170,6 +167,11 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xemacpsif = (xemacpsif_s *)(arg);
/* This function is called from an ISR. The Xilinx ISR-handler has already
cleared the TXCOMPL and TXSR_USEDREAD status bits in the XEMACPS_TXSR register.
But it forgets to do a read-back. Do so now to avoid ever-returning ISR's. */
( void ) XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET);
/* 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.
*/
@ -188,7 +190,7 @@ 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 ) )
if( ( xLength >= ( BaseType_t ) sizeof( struct xARP_PACKET ) ) && ( ( ( uint32_t ) xLength ) <= dmaRX_TX_BUFFER_SIZE ) )
{
xReturn = pdTRUE;
}
@ -207,12 +209,8 @@ 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
/* This driver wants to own all network buffers which are to be transmitted. */
configASSERT( iReleaseAfterSend != pdFALSE );
/* Open a do {} while ( 0 ) loop to be able to call break. */
do
@ -235,7 +233,6 @@ TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );
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 )
@ -244,15 +241,7 @@ TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );
}
/* 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;
@ -292,6 +281,8 @@ TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );
/* Start transmit */
xemacpsif->txBusy = pdTRUE;
XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) );
/* Read back the register to make sure the data is flushed. */
( void ) XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET );
}
dsb();
@ -306,6 +297,11 @@ void emacps_recv_handler(void *arg)
xemacpsif = (xemacpsif_s *)(arg);
xemacpsif->isr_events |= EMAC_IF_RX_EVENT;
/* The driver has already cleared the FRAMERX, BUFFNA and error bits
in the XEMACPS_RXSR register,
But it forgets to do a read-back. Do so now. */
( void ) XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET);
if( xEMACTaskHandle != NULL )
{
vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
@ -314,33 +310,35 @@ void emacps_recv_handler(void *arg)
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
static NetworkBufferDescriptor_t *ethMsg = NULL;
static NetworkBufferDescriptor_t *ethLast = NULL;
static void passEthMessages( void )
static void prvPassEthMessages( NetworkBufferDescriptor_t *pxDescriptor )
{
IPStackEvent_t xRxEvent;
xRxEvent.eEventType = eNetworkRxEvent;
xRxEvent.pvData = ( void * ) ethMsg;
xRxEvent.pvData = ( void * ) pxDescriptor;
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )
{
/* The buffer could not be sent to the stack so must be released again.
This is a deferred handler taskr, not a real interrupt, so it is ok to
use the task level function here. */
do
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer;
vReleaseNetworkBufferAndDescriptor( ethMsg );
ethMsg = xNext;
} while( ethMsg != NULL );
do
{
NetworkBufferDescriptor_t *pxNext = pxDescriptor->pxNextBuffer;
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
pxDescriptor = pxNext;
} while( pxDescriptor != NULL );
}
#else
{
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
iptraceETHERNET_RX_EVENT_LOST();
FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) );
FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) );
}
ethMsg = ethLast = NULL;
}
int emacps_check_rx( xemacpsif_s *xemacpsif )
@ -349,6 +347,10 @@ NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer;
int rx_bytes;
volatile int msgCount = 0;
int head = xemacpsif->rxHead;
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
NetworkBufferDescriptor_t *pxFirstDescriptor = NULL;
NetworkBufferDescriptor_t *pxLastDescriptor = NULL;
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
/* There seems to be an issue (SI# 692601), see comments below. */
resetrx_on_no_rxdata(xemacpsif);
@ -364,12 +366,12 @@ int head = xemacpsif->rxHead;
break;
}
pxNewBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );
pxNewBuffer = pxGetNetworkBufferWithDescriptor( dmaRX_TX_BUFFER_SIZE, ( 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" ) );
FreeRTOS_printf( ("emacps_check_rx: unable to allocate a Network Buffer\n" ) );
pxNewBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];
}
else
@ -394,26 +396,35 @@ int head = xemacpsif->rxHead;
/* store it in the receive queue, where it'll be processed by a
different handler. */
iptraceNETWORK_INTERFACE_RECEIVE();
pxBuffer->pxNextBuffer = NULL;
if( ethMsg == NULL )
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
// Becomes the first message
ethMsg = pxBuffer;
}
else if( ethLast != NULL )
{
// Add to the tail
ethLast->pxNextBuffer = pxBuffer;
}
pxBuffer->pxNextBuffer = NULL;
if( pxFirstDescriptor == NULL )
{
// Becomes the first message
pxFirstDescriptor = pxBuffer;
}
else if( pxLastDescriptor != NULL )
{
// Add to the tail
pxLastDescriptor->pxNextBuffer = pxBuffer;
}
pxLastDescriptor = pxBuffer;
}
#else
{
prvPassEthMessages( pxBuffer );
}
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
ethLast = pxBuffer;
msgCount++;
}
{
if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 )
{
Xil_DCacheInvalidateRange( ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);
Xil_DCacheInvalidateRange( ( ( uint32_t ) pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, ( uint32_t ) dmaRX_TX_BUFFER_SIZE );
}
{
uint32_t addr = ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;
@ -422,8 +433,10 @@ int head = xemacpsif->rxHead;
addr |= XEMACPS_RXBUF_WRAP_MASK;
}
/* Clearing 'XEMACPS_RXBUF_NEW_MASK' 0x00000001 *< Used bit.. */
xemacpsif->rxSegments[ head ].address = addr;
xemacpsif->rxSegments[ head ].flags = 0;
xemacpsif->rxSegments[ head ].address = addr;
/* Make sure that the value has reached the peripheral by reading it back. */
( void ) xemacpsif->rxSegments[ head ].address;
}
}
@ -434,10 +447,14 @@ int head = xemacpsif->rxHead;
xemacpsif->rxHead = head;
}
if( ethMsg != NULL )
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
passEthMessages( );
if( pxFirstDescriptor != NULL )
{
prvPassEthMessages( pxFirstDescriptor );
}
}
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
return msgCount;
}
@ -455,11 +472,7 @@ unsigned char *ucTxBuffer;
{
xemacpsif->txSegments[ index ].address = ( uint32_t )ucTxBuffer;
xemacpsif->txSegments[ index ].flags = XEMACPS_TXBUF_USED_MASK;
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
pxDMA_tx_buffers[ index ] = ( void* )NULL;
#else
pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET );
#endif
pxDMA_tx_buffers[ index ] = ( unsigned char * )NULL;
ucTxBuffer += xemacpsif->uTxUnitSize;
}
xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags =
@ -479,8 +492,7 @@ XStatus init_dma(xemacpsif_s *xemacpsif)
xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] );
/* Also round-up to 4KB */
xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful;
xemacpsif->uTxUnitSize = dmaRX_TX_BUFFER_SIZE;
/*
* We allocate 65536 bytes for RX BDs which can accommodate a
* maximum of 8192 BDs which is much more than any application
@ -507,7 +519,7 @@ XStatus init_dma(xemacpsif_s *xemacpsif)
pxBuffer = pxDMA_rx_buffers[ iIndex ];
if( pxBuffer == NULL )
{
pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );
pxBuffer = pxGetNetworkBufferWithDescriptor( dmaRX_TX_BUFFER_SIZE, ( TickType_t ) 0 );
if( pxBuffer == NULL )
{
FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) );
@ -523,7 +535,7 @@ XStatus init_dma(xemacpsif_s *xemacpsif)
if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
{
Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE,
(unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);
(unsigned)dmaRX_TX_BUFFER_SIZE );
}
}

View file

@ -22,19 +22,19 @@
#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"
#include "NetworkInterface.h"
#include "Zynq/x_emacpsif.h"
extern TaskHandle_t xEMACTaskHandle;
@ -42,8 +42,6 @@ extern TaskHandle_t xEMACTaskHandle;
*** to run it on a PEEP board
***/
unsigned int link_speed = 100;
void setup_isr( xemacpsif_s *xemacpsif )
{
/*
@ -141,8 +139,6 @@ int xResult;
return xResult;
}
BaseType_t xNetworkInterfaceInitialise( void );
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
{
xemacpsif_s *xemacpsif;
@ -218,8 +214,6 @@ static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
}
}
extern XEmacPs_Config mac_config;
void HandleTxErrors(xemacpsif_s *xemacpsif)
{
u32 netctrlreg;

View file

@ -53,24 +53,23 @@
#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"
#include "Zynq/x_emacpsif.h"
#include "xparameters_ps.h"
#include "xparameters.h"
int phy_detected = 0;
/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
@ -99,6 +98,8 @@ int phy_detected = 0;
#define IEEE_CONTROL_REG_OFFSET 0
#define IEEE_STATUS_REG_OFFSET 1
#define IEEE_PHYSID1_OFFSET 2
#define IEEE_PHYSID2_OFFSET 3
#define IEEE_AUTONEGO_ADVERTISE_REG 4
#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5
#define IEEE_1000_ADVERTISE_REG_OFFSET 9
@ -135,9 +136,6 @@ int phy_detected = 0;
#define IEEE_PAUSE_MASK 0x0400
#define IEEE_AUTONEG_ERROR_MASK 0x8000
#define PHY_DETECT_REG 1
#define PHY_DETECT_MASK 0x1808
#define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140
#define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100
#define XEMACPS_GMII2RGMII_SPEED10_FD 0x100
@ -161,21 +159,24 @@ int phy_detected = 0;
#define EMAC0_BASE_ADDRESS 0xE000B000
#define EMAC1_BASE_ADDRESS 0xE000C000
#define PHY_ADDRESS_COUNT 32
#define MINIMUM_SLEEP_TIME 2
static int detect_phy(XEmacPs *xemacpsp)
{
u16 phy_reg;
u32 phy_addr;
u16 id_lower, id_upper;
u32 phy_addr, id;
for (phy_addr = 31; phy_addr > 0; phy_addr--) {
XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
&phy_reg);
for (phy_addr = 0; phy_addr < PHY_ADDRESS_COUNT; phy_addr++) {
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PHYSID1_OFFSET, &id_lower);
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" ) );
if ((id_lower != ( u16 )0xFFFFu) && (id_lower != ( u16 )0x0u)) {
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PHYSID2_OFFSET, &id_upper);
id = ( ( ( uint32_t ) id_upper ) << 16 ) | ( id_lower & 0xFFF0 );
FreeRTOS_printf( ("XEmacPs detect_phy: %04lX at address %d.\n", id, phy_addr ) );
phy_detected = phy_addr;
return phy_addr;
}
@ -238,8 +239,8 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
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__);
FreeRTOS_printf( ( "%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\n",
__FUNCTION__ ) );
return 10;
} else {
@ -257,8 +258,8 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
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);
FreeRTOS_printf( ( "%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\n",
__FUNCTION__, phylinkspeed ) );
return 10;
}
@ -282,7 +283,7 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
#else
u32 phy_addr = detect_phy(xemacpsp);
#endif
xil_printf("Start PHY autonegotiation \r\n");
FreeRTOS_printf( ( "Start PHY autonegotiation \n" ) );
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
#else
@ -338,24 +339,24 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
break;
}
#endif
xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
FreeRTOS_printf( ( "Waiting for PHY to complete autonegotiation.\n" ) );
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
sleep(1);
vTaskDelay( MINIMUM_SLEEP_TIME );
#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");
FreeRTOS_printf( ( "Auto negotiation error \n" ) );
}
#endif
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
&status);
}
xil_printf("autonegotiation complete \r\n");
FreeRTOS_printf( ( "autonegotiation complete \n" ) );
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
#else
@ -363,7 +364,7 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
#endif
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
FreeRTOS_printf( ( "Waiting for Link to be up; Polling for SGMII core Reg \n" ) );
XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
while(!(temp & 0x8000)) {
XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
@ -380,7 +381,7 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
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");
FreeRTOS_printf( ( "get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\n" ) );
XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);
return 10;
@ -560,26 +561,26 @@ unsigned Phy_Setup (XEmacPs *xemacpsp)
link_speed = 1000;
configure_IEEE_phy_speed(xemacpsp, link_speed);
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
sleep(1);
vTaskDelay( MINIMUM_SLEEP_TIME );
#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);
vTaskDelay( MINIMUM_SLEEP_TIME );
#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);
vTaskDelay( MINIMUM_SLEEP_TIME );
#endif
if (conv_present) {
XEmacPs_PhyWrite(xemacpsp, convphyaddr,
XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
}
xil_printf("link speed: %d\r\n", link_speed);
FreeRTOS_printf( ( "link speed: %d\n", link_speed ) );
return link_speed;
}

View file

@ -44,6 +44,14 @@ enum if_state_t {
static const char *TAG = "NetInterface";
volatile static uint32_t xInterfaceState = INTERFACE_DOWN;
/* protect the function declaration itself instead of using
#if everywhere. */
#if ( ipconfigHAS_PRINTF != 0 )
static void prvPrintResourceStats();
#else
#define prvPrintResourceStats()
#endif
BaseType_t xNetworkInterfaceInitialise( void )
{
static BaseType_t xMACAdrInitialized = pdFALSE;
@ -78,6 +86,8 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBu
}
}
prvPrintResourceStats();
if (xReleaseAfterSend == pdTRUE) {
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
}
@ -105,6 +115,8 @@ esp_err_t wlanif_input(void *netif, void *buffer, uint16_t len, void *eb)
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
prvPrintResourceStats();
if( eConsiderFrameForProcessing( buffer ) != eProcessBuffer ) {
ESP_LOGD(TAG, "Dropping packet");
esp_wifi_internal_free_rx_buffer(eb);
@ -114,10 +126,10 @@ esp_err_t wlanif_input(void *netif, void *buffer, uint16_t len, void *eb)
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(len, xDescriptorWaitTime);
if (pxNetworkBuffer != NULL) {
/* Set the packet size, in case a larger buffer was returned. */
pxNetworkBuffer->xDataLength = len;
/* Set the packet size, in case a larger buffer was returned. */
pxNetworkBuffer->xDataLength = len;
/* Copy the packet data. */
/* Copy the packet data. */
memcpy(pxNetworkBuffer->pucEthernetBuffer, buffer, len);
xRxEvent.pvData = (void *) pxNetworkBuffer;
@ -133,3 +145,50 @@ esp_err_t wlanif_input(void *netif, void *buffer, uint16_t len, void *eb)
return ESP_FAIL;
}
}
#if ( ipconfigHAS_PRINTF != 0 )
static void prvPrintResourceStats()
{
static UBaseType_t uxLastMinBufferCount = 0u;
static UBaseType_t uxCurrentBufferCount = 0u;
static size_t uxMinLastSize = 0uL;
size_t uxMinSize;
uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();
if( uxLastMinBufferCount != uxCurrentBufferCount )
{
/* The logging produced below may be helpful
* while tuning +TCP: see how many buffers are in use. */
uxLastMinBufferCount = uxCurrentBufferCount;
FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) );
}
uxMinSize = xPortGetMinimumEverFreeHeapSize();
if( uxMinLastSize != uxMinSize )
{
uxMinLastSize = uxMinSize;
FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", xPortGetFreeHeapSize(), uxMinSize ) );
}
#if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
{
static UBaseType_t uxLastMinQueueSpace = 0;
UBaseType_t uxCurrentCount = 0u;
uxCurrentCount = uxGetMinimumIPQueueSpace();
if( uxLastMinQueueSpace != uxCurrentCount )
{
/* The logging produced below may be helpful
* while tuning +TCP: see how many buffers are in use. */
uxLastMinQueueSpace = uxCurrentCount;
FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
}
}
#endif /* ipconfigCHECK_IP_QUEUE_SPACE */
}
#endif /* ( ipconfigHAS_PRINTF != 0 ) */
/*-----------------------------------------------------------*/