From 06eece0c95b654505d0340031bd2614fb920db04 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Wed, 2 Nov 2022 16:15:11 +0800 Subject: [PATCH 1/7] Implemented Maty's solution --- .../DriverSAM/NetworkInterface.c | 106 ++++++++++-------- .../NetworkInterface/DriverSAM/gmac_SAM.c | 67 ++++++----- .../NetworkInterface/DriverSAM/gmac_SAM.h | 26 ++++- 3 files changed, 125 insertions(+), 74 deletions(-) diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 402865aaf7..4c9d3952af 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -53,6 +53,15 @@ /* This file is included to see if 'CONF_BOARD_ENABLE_CACHE' is defined. */ #include "conf_board.h" +/* The SAME70 family has the possibility of caching RAM. + * 'NETWORK_BUFFERS_CACHED' can be defined in either "conf_eth.h" + * or in "FreeRTOSIPConfig.h". + * For now, NETWORK_BUFFERS_CACHED should be defined as zero. + * D-cache may be enabled. + */ +#if ( NETWORK_BUFFERS_CACHED != 0 ) + #error please define this macro as zero +#endif /* Interrupt events to process. Currently only the Rx event is processed * although code for other events is included to allow for possible future @@ -95,10 +104,9 @@ #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1 #endif -#if ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) +#if ( NETWORK_BUFFERS_CACHED != 0 ) && ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) #include "core_cm7.h" #warning This driver assumes the presence of DCACHE - #define NETWORK_BUFFERS_CACHED 1 #define CACHE_LINE_SIZE 32 #define NETWORK_BUFFER_HEADER_SIZE ( ipconfigPACKET_FILLER_SIZE + 8 ) @@ -113,26 +121,24 @@ uint32_t size ) { /* SAME70 does not have clean/invalidate per area. */ - /* SCB_CleanInvalidateDCache_by_Addr( ( uint32_t * )addr, size); */ - SCB_CleanInvalidateDCache(); + SCB_CleanInvalidateDCache_by_Addr( ( uint32_t * ) addr, size ); } /*-----------------------------------------------------------*/ - static void cache_invalidate_by_addr( addr, - size ) \ + static void cache_invalidate_by_addr( uint32_t addr, + uint32_t size ) { /* SAME70 does not have clean/invalidate per area. */ - /* SCB_InvalidateDCache_by_Addr( ( uint32_t * )addr, size); */ - SCB_InvalidateDCache(); + SCB_InvalidateDCache_by_Addr( ( uint32_t * ) addr, size ); } /*-----------------------------------------------------------*/ -#else /* if ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) */ +#else /* The DMA buffers are located in non-cached RAM. */ #warning Sure there is no caching? #define cache_clean_invalidate() do {} while( 0 ) #define cache_clean_invalidate_by_addr( addr, size ) do {} while( 0 ) #define cache_invalidate_by_addr( addr, size ) do {} while( 0 ) -#endif /* if ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) */ +#endif /* if ( NETWORK_BUFFERS_CACHED != 0 ) && ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) */ /*-----------------------------------------------------------*/ @@ -186,11 +192,6 @@ static void hand_tx_errors( void ); /*-----------------------------------------------------------*/ -/* Bit map of outstanding ETH interrupt events for processing. Currently only - * the Rx interrupt is handled, although code is included for other events to - * enable future expansion. */ -static volatile uint32_t ulISREvents; - /* A copy of PHY register 1: 'PHY_REG_01_BMSR' */ static volatile BaseType_t xGMACSwitchRequired; @@ -205,8 +206,9 @@ static gmac_device_t gs_gmac_dev; * related interrupts. */ TaskHandle_t xEMACTaskHandle = NULL; +/* TX buffers that have been sent must be returned to the driver + * using this queue. */ static QueueHandle_t xTxBufferQueue; -int tx_release_count[ 4 ]; /* xTXDescriptorSemaphore is a counting semaphore with * a maximum count of GMAC_TX_BUFFERS, which is the number of @@ -271,21 +273,21 @@ void xRxCallback( uint32_t ulStatus ) if( ( ( ulStatus & GMAC_RSR_REC ) != 0 ) && ( xEMACTaskHandle != NULL ) ) { /* let the prvEMACHandlerTask know that there was an RX event. */ - ulISREvents |= EMAC_IF_RX_EVENT; - /* Only an RX interrupt can wakeup prvEMACHandlerTask. */ - vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired ); + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_EVENT, eSetBits, &( xGMACSwitchRequired ) ); } } /*-----------------------------------------------------------*/ +/* The following function can be called by gmac_reset_tx_mem(). + */ void returnTxBuffer( uint8_t * puc_buffer ) { /* Called from a non-ISR context. */ if( xTxBufferQueue != NULL ) { + /* return 'puc_buffer' to the pool of transmission buffers. */ xQueueSend( xTxBufferQueue, &puc_buffer, 0 ); - xTaskNotifyGive( xEMACTaskHandle ); - ulISREvents |= EMAC_IF_TX_EVENT; + xTaskNotify( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits ); } } @@ -295,11 +297,21 @@ void xTxCallback( uint32_t ulStatus, if( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) ) { /* let the prvEMACHandlerTask know that there was an TX event. */ - ulISREvents |= EMAC_IF_TX_EVENT; /* Wakeup prvEMACHandlerTask. */ - vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired ); - xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired ); - tx_release_count[ 2 ]++; + if( puc_buffer == NULL ) + { + /* (GMAC_TSR) Retry Limit Exceeded */ + /* Can not send logging, we're in an ISR. */ + } + else + { + xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired ); + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits, &( xGMACSwitchRequired ) ); + + /* TX statistics. Only works when 'GMAC_STATS' + * is defined as 1. See gmac_SAM.h for more information. */ + TX_STAT_INCREMENT( tx_callback ); + } } } /*-----------------------------------------------------------*/ @@ -445,7 +457,9 @@ BaseType_t xNetworkInterfaceInitialise( void ) if( xTXDescriptorSemaphore == NULL ) { - xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS ); + /* When there are N TX descriptors, we want to use + * at most "N-1" simultaneously. */ + xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS - 1U, ( UBaseType_t ) GMAC_TX_BUFFERS - 1U ); configASSERT( xTXDescriptorSemaphore ); } @@ -483,7 +497,6 @@ static void hand_tx_errors( void ) gmac_enable_transmit( GMAC, false ); /* Reinit TX descriptors. */ -/* gmac_tx_init(ps_gmac_dev); */ gmac_reset_tx_mem( &gs_gmac_dev ); /* Clear error status. */ gmac_clear_tx_status( GMAC, GMAC_TX_ERRORS ); @@ -498,7 +511,7 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript BaseType_t bReleaseAfterSend ) { /* Do not wait too long for a free TX DMA buffer. */ - const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u ); + const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50U ); uint32_t ulTransmitSize; ulTransmitSize = pxDescriptor->xDataLength; @@ -514,6 +527,8 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript * statement. */ do { + uint32_t ulResult; + if( xPhyObject.ulLinkStatusMask == 0ul ) { /* Do not attempt to send packets as long as the Link Status is low. */ @@ -531,10 +546,11 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS ) { /* Time-out waiting for a free TX descriptor. */ - tx_release_count[ 3 ]++; + TX_STAT_INCREMENT( tx_enqueue_fail ); break; } + TX_STAT_INCREMENT( tx_enqueue_ok ); #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) { /* Confirm that the pxDescriptor may be kept by the driver. */ @@ -550,7 +566,8 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript } #endif - gmac_dev_write( &gs_gmac_dev, ( void * ) pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ); + ulResult = gmac_dev_write( &gs_gmac_dev, ( void * ) pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ); + configASSERT( ulResult == GMAC_OK ) #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) { @@ -594,7 +611,7 @@ static BaseType_t prvGMACInit( void ) { /* Set MDC clock divider. */ - gmac_set_mdc_clock( GMAC, sysclk_get_cpu_hz() ); + gmac_set_mdc_clock( GMAC, sysclk_get_peripheral_hz() ); vPhyInitialise( &xPhyObject, xPHY_Read, xPHY_Write ); xPhyDiscover( &xPhyObject ); @@ -840,7 +857,7 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB static void prvEMACHandlerTask( void * pvParameters ) { UBaseType_t uxCount; - UBaseType_t uxLowestSemCount = 0; + UBaseType_t uxLowestSemCount = GMAC_TX_BUFFERS + 1; #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) NetworkBufferDescriptor_t * pxBuffer; @@ -849,6 +866,7 @@ static void prvEMACHandlerTask( void * pvParameters ) BaseType_t xResult = 0; uint32_t xStatus; const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS ); + uint32_t ulISREvents = 0U; /* Remove compiler warnings about unused parameters. */ ( void ) pvParameters; @@ -879,16 +897,14 @@ static void prvEMACHandlerTask( void * pvParameters ) } #endif /* ( ipconfigHAS_PRINTF != 0 ) */ - if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 ) - { - /* No events to process now, wait for the next. */ - ulTaskNotifyTake( pdFALSE, ulMaxBlockTime ); - } + /* Wait for a new event or a time-out. */ + xTaskNotifyWait( 0U, /* ulBitsToClearOnEntry */ + EMAC_IF_ALL_EVENT, /* ulBitsToClearOnExit */ + &( ulISREvents ), /* pulNotificationValue */ + ulMaxBlockTime ); if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 ) { - ulISREvents &= ~EMAC_IF_RX_EVENT; - /* Wait for the EMAC interrupt to indicate that another packet has been * received. */ xResult = prvEMACRxPoll(); @@ -896,9 +912,6 @@ static void prvEMACHandlerTask( void * pvParameters ) if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) { - /* Future extension: code to release TX buffers if zero-copy is used. */ - ulISREvents &= ~EMAC_IF_TX_EVENT; - while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE ) { #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) @@ -908,21 +921,21 @@ static void prvEMACHandlerTask( void * pvParameters ) if( pxBuffer != NULL ) { vReleaseNetworkBufferAndDescriptor( pxBuffer ); - tx_release_count[ 0 ]++; + TX_STAT_INCREMENT( tx_release_ok ); } else { - tx_release_count[ 1 ]++; + TX_STAT_INCREMENT( tx_release_bad ); } } #else /* if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) */ { - tx_release_count[ 0 ]++; + TX_STAT_INCREMENT( tx_release_ok ); } #endif /* if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) */ uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore ); - if( uxCount < GMAC_TX_BUFFERS ) + if( uxCount < ( GMAC_TX_BUFFERS - 1 ) ) { /* Tell the counting semaphore that one more TX descriptor is available. */ xSemaphoreGive( xTXDescriptorSemaphore ); @@ -933,7 +946,6 @@ static void prvEMACHandlerTask( void * pvParameters ) if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) { /* Future extension: logging about errors that occurred. */ - ulISREvents &= ~EMAC_IF_ERR_EVENT; } gmac_enable_management( GMAC, true ); diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c index 7b2d445f7c..eab7fc726e 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c @@ -89,11 +89,20 @@ #endif #if ( GMAC_RX_BUFFERS <= 1 ) - #error Configuration error + #error Configuration error, GMAC_RX_BUFFERS must be at least 2 #endif #if ( GMAC_TX_BUFFERS <= 1 ) - #error Configuration error + #error Configuration error, GMAC_TX_BUFFERS must be at least 2 +#endif + +/* Interesting bits in the Transmission Status Register. */ +#define TSR_TSR_BITS ( GMAC_TSR_TXCOMP | GMAC_TSR_COL | GMAC_TSR_RLE | GMAC_TSR_UND ) + +#if ( GMAC_STATS != 0 ) + #warning Statistics are enabled + struct SGmacStats gmacStats; + TransmitStats_t xTransmitStats; #endif /** @@ -488,12 +497,6 @@ static uint32_t gmac_dev_poll( gmac_device_t * p_gmac_dev ) int32_t ulIndex = p_gmac_dev->ul_rx_idx; gmac_rx_descriptor_t * pxHead = &gs_rx_desc[ ulIndex ]; -/* #warning Just for debugging */ -/* if((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0) */ -/* { */ -/* NVIC_DisableIRQ( GMAC_IRQn ); */ -/* } */ - #if ( ipconfigZERO_COPY_RX_DRIVER == 0 ) { /* Discard any incomplete frames */ @@ -616,7 +619,7 @@ uint32_t gmac_dev_read( gmac_device_t * p_gmac_dev, /* Read +2 bytes because buffers are aligned at -2 bytes */ bytesLeft = min( bytesLeft + 2, ( int32_t ) ul_frame_size ); - #if ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) + #if ( NETWORK_BUFFERS_CACHED != 0 ) && ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) SCB_InvalidateDCache(); #endif @@ -670,20 +673,25 @@ uint32_t gmac_dev_read( gmac_device_t * p_gmac_dev, pxHead = &gs_rx_desc[ nextIdx ]; pxHead->addr.val &= ~( GMAC_RXD_OWNERSHIP ); circ_inc32( &nextIdx, GMAC_RX_BUFFERS ); + + if( pxHead->addr.val ) + { + /* Just read it back to make sure that + * it was written to SRAM. */ + } } while( ( pxHead->status.val & GMAC_RXD_EOF ) == 0 ); p_gmac_dev->ul_rx_idx = nextIdx; *p_rcv_size = bytesLeft; -/* #warning Just for debugging */ -/* NVIC_EnableIRQ( GMAC_IRQn ); */ - return GMAC_OK; } -extern void vGMACGenerateChecksum( uint8_t * apBuffer, - size_t uxLength ); +#if ( SAME70 == 0 ) + extern void vGMACGenerateChecksum( uint8_t * apBuffer, + size_t uxLength ); +#endif /** * \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the @@ -705,6 +713,8 @@ uint32_t gmac_dev_write( gmac_device_t * p_gmac_dev, Gmac * p_hw = p_gmac_dev->p_hw; + configASSERT( p_buffer != NULL ); + configASSERT( ul_size >= ipconfigETHERNET_MINIMUM_PACKET_BYTES ); /* Check parameter */ if( ul_size > GMAC_TX_UNITSIZE ) @@ -739,12 +749,15 @@ uint32_t gmac_dev_write( gmac_device_t * p_gmac_dev, memcpy( ( void * ) p_tx_td->addr, p_buffer, ul_size ); } #endif /* ipconfigZERO_COPY_TX_DRIVER */ - vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr, ( size_t ) ul_size ); + #if ( SAME70 == 0 ) + { + #warning Is this a SAM4E? + /* Needs to be called for SAM4E series only. */ + vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr, ( size_t ) ul_size ); + } + #endif } - /*#warning Trying out */ - gmac_start_transmission( p_hw ); - /* Update transmit descriptor status */ /* The buffer size defined is the length of ethernet frame, @@ -763,6 +776,12 @@ uint32_t gmac_dev_write( gmac_device_t * p_gmac_dev, ul_size | GMAC_TXD_LAST; } + if( p_tx_td->status.val ) + { + /* Just read it back to make sure that + * it was written to SRAM. */ + } + circ_inc32( &p_gmac_dev->l_tx_head, GMAC_TX_BUFFERS ); /* Now start to transmit if it is still not done */ @@ -862,9 +881,6 @@ void gmac_dev_halt( Gmac * p_gmac ) */ #if ( GMAC_STATS != 0 ) - extern int logPrintf( const char * pcFormat, - ... ); - void gmac_show_irq_counts() { int index; @@ -873,7 +889,7 @@ void gmac_dev_halt( Gmac * p_gmac ) { if( gmacStats.intStatus[ intPairs[ index ].index ] ) { - logPrintf( "%s : %6u\n", intPairs[ index ].name, gmacStats.intStatus[ intPairs[ index ].index ] ); + FreeRTOS_printf( ( "%s : %6u\n", intPairs[ index ].name, gmacStats.intStatus[ intPairs[ index ].index ] ) ); } } } @@ -922,7 +938,7 @@ void gmac_handler( gmac_device_t * p_gmac_dev ) } /* TX packet */ - if( ( ul_isr & GMAC_ISR_TCOMP ) || ( ul_tsr & ( GMAC_TSR_TXCOMP | GMAC_TSR_COL | GMAC_TSR_RLE | GMAC_TSR_UND ) ) ) + if( ( ul_isr & GMAC_ISR_TCOMP ) || ( ( ul_tsr & TSR_TSR_BITS ) != 0U ) ) { ul_tx_status_flag = GMAC_TSR_TXCOMP; /* A frame transmitted */ @@ -968,7 +984,8 @@ void gmac_handler( gmac_device_t * p_gmac_dev ) if( ul_tsr & GMAC_TSR_RLE ) { - /* Notify upper layer RLE */ + /* Notify upper layer RLE + * (GMAC_TSR) Retry Limit Exceeded */ xTxCallback( ul_tx_status_flag, NULL ); } @@ -991,7 +1008,7 @@ void gmac_handler( gmac_device_t * p_gmac_dev ) /*/ @cond 0 */ /**INDENT-OFF**/ #ifdef __cplusplus - } +} #endif /**INDENT-ON**/ /*/ @endcond */ diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h index 212e25ea3c..4ece496a12 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h @@ -1544,10 +1544,15 @@ /**INDENT-ON**/ /*/ @endcond */ + #ifndef GMAC_STATS + #define GMAC_STATS 0 + #endif + + #if ( GMAC_STATS == 0 ) - #define GMAC_STATS 0 + #define TX_STAT_INCREMENT( field ) do {} while( ipFALSE_BOOL ) - #if ( GMAC_STATS != 0 ) + #else /* Here below some code to study the types and * frequencies of GMAC interrupts. */ @@ -1599,6 +1604,23 @@ void gmac_show_irq_counts(); +/* + * The following struct replaces the earlier: + * int tx_release_count[ 4 ]; + * The purpose of this struct is to describe the TX events. + */ + typedef struct STransmitStats + { + unsigned tx_enqueue_ok; /* xNetworkInterfaceOutput() success. */ + unsigned tx_enqueue_fail; /* xNetworkInterfaceOutput() failed, no slot available. */ + unsigned tx_callback; /* Transmission ready, buffer returned to driver. */ + unsigned tx_release_ok; /* Buffer released. */ + unsigned tx_release_bad; /* Buffer corruption. */ + } TransmitStats_t; + + extern TransmitStats_t xTransmitStats; + #define TX_STAT_INCREMENT( field ) xTransmitStats.field++ + #endif /* if ( GMAC_STATS != 0 ) */ #endif /* GMAC_H_INCLUDED */ From d89a334d51ed073ee78533befc9a3bc67377820c Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Thu, 3 Nov 2022 11:07:44 +0800 Subject: [PATCH 2/7] Added a new statistic 'tx_write_fail' --- .../NetworkInterface/DriverSAM/NetworkInterface.c | 8 ++++++-- source/portable/NetworkInterface/DriverSAM/gmac_SAM.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 4c9d3952af..7bbbc81425 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -193,7 +193,7 @@ static void hand_tx_errors( void ); /*-----------------------------------------------------------*/ /* A copy of PHY register 1: 'PHY_REG_01_BMSR' */ -static volatile BaseType_t xGMACSwitchRequired; +static BaseType_t xGMACSwitchRequired; /* LLMNR multicast address. */ static const uint8_t llmnr_mac_address[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC }; @@ -567,7 +567,11 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript #endif ulResult = gmac_dev_write( &gs_gmac_dev, ( void * ) pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ); - configASSERT( ulResult == GMAC_OK ) + + if( ulResult != GMAC_OK ) + { + TX_STAT_INCREMENT( tx_write_fail ); + } #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) { diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h index 4ece496a12..414300b875 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h @@ -1613,6 +1613,7 @@ { unsigned tx_enqueue_ok; /* xNetworkInterfaceOutput() success. */ unsigned tx_enqueue_fail; /* xNetworkInterfaceOutput() failed, no slot available. */ + unsigned tx_write_fail; /* gmac_dev_write() did not return GMAC-OK. */ unsigned tx_callback; /* Transmission ready, buffer returned to driver. */ unsigned tx_release_ok; /* Buffer released. */ unsigned tx_release_bad; /* Buffer corruption. */ From 0c38c80f6e6e467d8e9399fd09d9d736a53deb92 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 3 Nov 2022 06:09:01 +0000 Subject: [PATCH 3/7] Uncrustify: triggered by comment. --- source/portable/NetworkInterface/DriverSAM/gmac_SAM.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c index eab7fc726e..17222dc8ac 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c @@ -1008,7 +1008,7 @@ void gmac_handler( gmac_device_t * p_gmac_dev ) /*/ @cond 0 */ /**INDENT-OFF**/ #ifdef __cplusplus -} + } #endif /**INDENT-ON**/ /*/ @endcond */ From 62ec542e86a097ad1b6e3de7141aa7d9f0b1ffb4 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Fri, 4 Nov 2022 16:01:51 +0800 Subject: [PATCH 4/7] Increase NETWORK_BUFFER_SIZE in order to include the 'ipBUFFER_PADDING' bytes --- .../DriverSAM/NetworkInterface.c | 17 ++++++----------- .../NetworkInterface/DriverSAM/gmac_SAM.c | 14 ++++++++++++-- .../NetworkInterface/DriverSAM/gmac_SAM.h | 11 +++++++---- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 7bbbc81425..3f72a30017 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -71,12 +71,6 @@ #define EMAC_IF_ERR_EVENT 4UL #define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT ) -/* 1536 bytes is more than needed, 1524 would be enough. - * But 1536 is a multiple of 32, which gives a great alignment for - * cached memories. */ - -#define NETWORK_BUFFER_SIZE 1536 - #ifndef EMAC_MAX_BLOCK_TIME_MS /* The task 'prvEMACHandlerTask()' will wake-up every 100 ms, to see @@ -518,9 +512,10 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript pxSendPacket = ( IPPacket_t * ) pxDescriptor->pucEthernetBuffer; - if( ulTransmitSize > NETWORK_BUFFER_SIZE ) + /* 'GMAC_TX_UNITSIZE' is the netto size of a transmission buffer. */ + if( ulTransmitSize > GMAC_TX_UNITSIZE ) { - ulTransmitSize = NETWORK_BUFFER_SIZE; + ulTransmitSize = GMAC_TX_UNITSIZE; } /* A do{}while(0) loop is introduced to allow the use of multiple break @@ -566,7 +561,7 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript } #endif - ulResult = gmac_dev_write( &gs_gmac_dev, ( void * ) pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ); + ulResult = gmac_dev_write( &gs_gmac_dev, ( void * ) pxDescriptor->pucEthernetBuffer, ulTransmitSize ); if( ulResult != GMAC_OK ) { @@ -773,7 +768,7 @@ static uint32_t prvEMACRxPoll( void ) * descriptor then allocate one now. */ if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) ) { - pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime ); + pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( GMAC_RX_UNITSIZE, xBlockTime ); } if( pxNextNetworkBufferDescriptor != NULL ) @@ -789,7 +784,7 @@ static uint32_t prvEMACRxPoll( void ) } /* Read the next packet from the hardware into pucUseBuffer. */ - ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount, &pucDMABuffer ); + ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, GMAC_RX_UNITSIZE, &ulReceiveCount, &pucDMABuffer ); if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) ) { diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c index 17222dc8ac..5e15b2ddf1 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c @@ -120,8 +120,18 @@ * @{ */ -#define NETWORK_BUFFER_SIZE 1536 - +/* + * When BufferAllocation_1.c is used, the network buffer space + * is declared statically as 'ucNetworkPackets[]'. + * Like the DMA descriptors, this array is located in a non-cached area. + * Here an example of the total size: + * + * #define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 24 + * #define GMAC_FRAME_LENTGH_MAX 1536 + * Hidden space for back-pointer and IP-type 16 + * + * Total size: 24 * ( 1536 + 16 ) = 37248 bytes + */ __attribute__( ( aligned( 32 ) ) ) __attribute__( ( section( ".first_data" ) ) ) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * NETWORK_BUFFER_SIZE ]; diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h index 414300b875..4b7def2928 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h @@ -96,12 +96,15 @@ /** The MAC can support frame lengths up to 1536 bytes */ #define GMAC_FRAME_LENTGH_MAX 1536 + #define GMAC_RX_UNITSIZE GMAC_FRAME_LENTGH_MAX /**< Maximum size for RX buffer */ + #define GMAC_TX_UNITSIZE GMAC_FRAME_LENTGH_MAX /**< Maximum size for TX buffer */ -/*#define GMAC_RX_UNITSIZE 128 / **< Fixed size for RX buffer * / */ - #define GMAC_RX_UNITSIZE 1536 /**< Fixed size for RX buffer */ + /* A network buffer starts with 10 hidden bytes (ipBUFFER_PADDING) + * in which a pointer is stored. Round up this extra size to a multiple of 16, + * in order to get well-aligned buffers. */ -/*#define GMAC_TX_UNITSIZE 1518 / **< Size for ETH frame length * / */ - #define GMAC_TX_UNITSIZE 1536 /**< Size for ETH frame length */ + #define BUFFER_PADDING ( ( ipBUFFER_PADDING + 16U ) & ~0x0FU ) + #define NETWORK_BUFFER_SIZE ( GMAC_FRAME_LENTGH_MAX + BUFFER_PADDING ) /** GMAC clock speed */ #define GMAC_MCK_SPEED_240MHZ ( 240 * 1000 * 1000 ) From 4d052605b4ad45b9681990a9eae7098c3b747a4f Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Fri, 4 Nov 2022 16:38:11 +0800 Subject: [PATCH 5/7] ICMP checksum calculated manually --- .../DriverSAM/NetworkInterface.c | 27 +++++++---- .../NetworkInterface/DriverSAM/gmac_SAM.c | 19 +++----- .../NetworkInterface/DriverSAM/gmac_SAM.h | 45 ++++++++++--------- 3 files changed, 49 insertions(+), 42 deletions(-) diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 3f72a30017..7974b72a49 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -512,7 +512,7 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript pxSendPacket = ( IPPacket_t * ) pxDescriptor->pucEthernetBuffer; - /* 'GMAC_TX_UNITSIZE' is the netto size of a transmission buffer. */ + /* 'GMAC_TX_UNITSIZE' is the netto size of a transmission buffer. */ if( ulTransmitSize > GMAC_TX_UNITSIZE ) { ulTransmitSize = GMAC_TX_UNITSIZE; @@ -737,17 +737,26 @@ void vGMACGenerateChecksum( uint8_t * pucBuffer, { ProtocolPacket_t * xProtPacket = ( ProtocolPacket_t * ) pucBuffer; - if( xProtPacket->xTCPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) + /* The SAM4E has problems offloading checksums for transmission. + * The SAME70 does not set the CRC for ICMP packets (ping). */ + + if( xProtPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) { - IPHeader_t * pxIPHeader = &( xProtPacket->xTCPPacket.xIPHeader ); + #if ( SAME70 != 0 ) + if( ( xProtPacket->xICMPPacket.xIPHeader.ucProtocol != ipPROTOCOL_UDP ) && + ( xProtPacket->xICMPPacket.xIPHeader.ucProtocol != ipPROTOCOL_TCP ) ) + #endif + { + IPHeader_t * pxIPHeader = &( xProtPacket->xTCPPacket.xIPHeader ); - /* Calculate the IP header checksum. */ - pxIPHeader->usHeaderChecksum = 0x00; - pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER ); - pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum ); + /* Calculate the IP header checksum. */ + pxIPHeader->usHeaderChecksum = 0x00; + pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER ); + pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum ); - /* Calculate the TCP checksum for an outgoing packet. */ - usGenerateProtocolChecksum( pucBuffer, uxLength, pdTRUE ); + /* Calculate the TCP checksum for an outgoing packet. */ + usGenerateProtocolChecksum( pucBuffer, uxLength, pdTRUE ); + } } } /*-----------------------------------------------------------*/ diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c index 5e15b2ddf1..e9de1ab6a0 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c @@ -698,11 +698,6 @@ uint32_t gmac_dev_read( gmac_device_t * p_gmac_dev, return GMAC_OK; } -#if ( SAME70 == 0 ) - extern void vGMACGenerateChecksum( uint8_t * apBuffer, - size_t uxLength ); -#endif - /** * \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the * GMAC Tx buffers, and then indicates to the GMAC that the buffer is ready. @@ -759,13 +754,11 @@ uint32_t gmac_dev_write( gmac_device_t * p_gmac_dev, memcpy( ( void * ) p_tx_td->addr, p_buffer, ul_size ); } #endif /* ipconfigZERO_COPY_TX_DRIVER */ - #if ( SAME70 == 0 ) - { - #warning Is this a SAM4E? - /* Needs to be called for SAM4E series only. */ - vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr, ( size_t ) ul_size ); - } - #endif + { + #warning Is this a SAM4E? + /* Needs to be called for SAM4E series only. */ + vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr, ( size_t ) ul_size ); + } } /* Update transmit descriptor status */ @@ -1018,7 +1011,7 @@ void gmac_handler( gmac_device_t * p_gmac_dev ) /*/ @cond 0 */ /**INDENT-OFF**/ #ifdef __cplusplus - } +} #endif /**INDENT-ON**/ /*/ @endcond */ diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h index 4b7def2928..d59965f0d9 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.h @@ -99,42 +99,42 @@ #define GMAC_RX_UNITSIZE GMAC_FRAME_LENTGH_MAX /**< Maximum size for RX buffer */ #define GMAC_TX_UNITSIZE GMAC_FRAME_LENTGH_MAX /**< Maximum size for TX buffer */ - /* A network buffer starts with 10 hidden bytes (ipBUFFER_PADDING) - * in which a pointer is stored. Round up this extra size to a multiple of 16, - * in order to get well-aligned buffers. */ +/* A network buffer starts with 10 hidden bytes (ipBUFFER_PADDING) + * in which a pointer is stored. Round up this extra size to a multiple of 16, + * in order to get well-aligned buffers. */ - #define BUFFER_PADDING ( ( ipBUFFER_PADDING + 16U ) & ~0x0FU ) - #define NETWORK_BUFFER_SIZE ( GMAC_FRAME_LENTGH_MAX + BUFFER_PADDING ) + #define BUFFER_PADDING ( ( ipBUFFER_PADDING + 16U ) & ~0x0FU ) + #define NETWORK_BUFFER_SIZE ( GMAC_FRAME_LENTGH_MAX + BUFFER_PADDING ) /** GMAC clock speed */ - #define GMAC_MCK_SPEED_240MHZ ( 240 * 1000 * 1000 ) - #define GMAC_MCK_SPEED_160MHZ ( 160 * 1000 * 1000 ) - #define GMAC_MCK_SPEED_120MHZ ( 120 * 1000 * 1000 ) - #define GMAC_MCK_SPEED_80MHZ ( 80 * 1000 * 1000 ) - #define GMAC_MCK_SPEED_40MHZ ( 40 * 1000 * 1000 ) - #define GMAC_MCK_SPEED_20MHZ ( 20 * 1000 * 1000 ) + #define GMAC_MCK_SPEED_240MHZ ( 240 * 1000 * 1000 ) + #define GMAC_MCK_SPEED_160MHZ ( 160 * 1000 * 1000 ) + #define GMAC_MCK_SPEED_120MHZ ( 120 * 1000 * 1000 ) + #define GMAC_MCK_SPEED_80MHZ ( 80 * 1000 * 1000 ) + #define GMAC_MCK_SPEED_40MHZ ( 40 * 1000 * 1000 ) + #define GMAC_MCK_SPEED_20MHZ ( 20 * 1000 * 1000 ) /** GMAC maintain code default value*/ - #define GMAC_MAN_CODE_VALUE ( 10 ) + #define GMAC_MAN_CODE_VALUE ( 10 ) /** GMAC maintain start of frame default value*/ - #define GMAC_MAN_SOF_VALUE ( 1 ) + #define GMAC_MAN_SOF_VALUE ( 1 ) /** GMAC maintain read/write*/ - #define GMAC_MAN_RW_TYPE ( 2 ) + #define GMAC_MAN_RW_TYPE ( 2 ) /** GMAC maintain read only*/ - #define GMAC_MAN_READ_ONLY ( 1 ) + #define GMAC_MAN_READ_ONLY ( 1 ) /** GMAC address length */ - #define GMAC_ADDR_LENGTH ( 6 ) + #define GMAC_ADDR_LENGTH ( 6 ) - #define GMAC_DUPLEX_HALF 0 - #define GMAC_DUPLEX_FULL 1 + #define GMAC_DUPLEX_HALF 0 + #define GMAC_DUPLEX_FULL 1 - #define GMAC_SPEED_10M 0 - #define GMAC_SPEED_100M 1 + #define GMAC_SPEED_10M 0 + #define GMAC_SPEED_100M 1 /** * \brief Return codes for GMAC APIs. @@ -1539,6 +1539,11 @@ void gmac_reset_tx_mem( gmac_device_t * p_dev ); +/* The SAM4E has problems offloading checksums for transmission. + * The SAME70 does not set the CRC for ICMP packets (ping). */ + extern void vGMACGenerateChecksum( uint8_t * apBuffer, + size_t uxLength ); + /*/ @cond 0 */ /**INDENT-OFF**/ #ifdef __cplusplus From 6974fcd89e8a4af214a8f94d69f5083e5d8b2232 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 7 Nov 2022 06:40:47 +0000 Subject: [PATCH 6/7] Uncrustify: triggered by comment. --- source/portable/NetworkInterface/DriverSAM/gmac_SAM.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c index fcfb13727a..5c19b5191e 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c @@ -1010,7 +1010,7 @@ void gmac_handler( gmac_device_t * p_gmac_dev ) /*/ @cond 0 */ /**INDENT-OFF**/ #ifdef __cplusplus -} + } #endif /**INDENT-ON**/ /*/ @endcond */ From 0b7d22302879dedf2c469a87dbcd3384482f1762 Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon, 7 Nov 2022 01:12:18 -0800 Subject: [PATCH 7/7] Update gmac_SAM.c --- source/portable/NetworkInterface/DriverSAM/gmac_SAM.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c index 5c19b5191e..e864e1be72 100644 --- a/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c +++ b/source/portable/NetworkInterface/DriverSAM/gmac_SAM.c @@ -111,8 +111,8 @@ * See \ref gmac_quickstart. * * Driver for the GMAC (Ethernet Media Access Controller). - * This file contains basic functions for the GMAC, with support for all modes, settings - * and clock speeds. + * This file contains basic functions for the GMAC, with support for all modes, + * settings and clock speeds. * * \section dependencies Dependencies * This driver does not depend on other modules.