5353/* This file is included to see if 'CONF_BOARD_ENABLE_CACHE' is defined. */
5454#include "conf_board.h"
5555
56+ /* The SAME70 family has the possibility of caching RAM.
57+ * 'NETWORK_BUFFERS_CACHED' can be defined in either "conf_eth.h"
58+ * or in "FreeRTOSIPConfig.h".
59+ * For now, NETWORK_BUFFERS_CACHED should be defined as zero.
60+ * D-cache may be enabled.
61+ */
62+ #if ( NETWORK_BUFFERS_CACHED != 0 )
63+ #error please define this macro as zero
64+ #endif
5665
5766/* Interrupt events to process. Currently only the Rx event is processed
5867 * although code for other events is included to allow for possible future
95104 #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1
96105#endif
97106
98- #if ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE )
107+ #if ( NETWORK_BUFFERS_CACHED != 0 ) && ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE )
99108 #include "core_cm7.h"
100109 #warning This driver assumes the presence of DCACHE
101- #define NETWORK_BUFFERS_CACHED 1
102110 #define CACHE_LINE_SIZE 32
103111 #define NETWORK_BUFFER_HEADER_SIZE ( ipconfigPACKET_FILLER_SIZE + 8 )
104112
113121 uint32_t size )
114122 {
115123 /* SAME70 does not have clean/invalidate per area. */
116- /* SCB_CleanInvalidateDCache_by_Addr( ( uint32_t * )addr, size); */
117- SCB_CleanInvalidateDCache ();
124+ SCB_CleanInvalidateDCache_by_Addr ( ( uint32_t * ) addr , size );
118125 }
119126 /*-----------------------------------------------------------*/
120127
121- static void cache_invalidate_by_addr ( addr ,
122- size ) \
128+ static void cache_invalidate_by_addr ( uint32_t addr ,
129+ uint32_t size )
123130 {
124131 /* SAME70 does not have clean/invalidate per area. */
125- /* SCB_InvalidateDCache_by_Addr( ( uint32_t * )addr, size); */
126- SCB_InvalidateDCache ();
132+ SCB_InvalidateDCache_by_Addr ( ( uint32_t * ) addr , size );
127133 }
128134 /*-----------------------------------------------------------*/
129135
130- #else /* if ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) */
136+ #else /* The DMA buffers are located in non-cached RAM. */
131137 #warning Sure there is no caching?
132138 #define cache_clean_invalidate () do {} while( 0 )
133139 #define cache_clean_invalidate_by_addr ( addr , size ) do {} while( 0 )
134140 #define cache_invalidate_by_addr ( addr , size ) do {} while( 0 )
135- #endif /* if ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) */
141+ #endif /* if ( NETWORK_BUFFERS_CACHED != 0 ) && ( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE ) */
136142
137143/*-----------------------------------------------------------*/
138144
@@ -186,13 +192,8 @@ static void hand_tx_errors( void );
186192
187193/*-----------------------------------------------------------*/
188194
189- /* Bit map of outstanding ETH interrupt events for processing. Currently only
190- * the Rx interrupt is handled, although code is included for other events to
191- * enable future expansion. */
192- static volatile uint32_t ulISREvents ;
193-
194195/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
195- static volatile BaseType_t xGMACSwitchRequired ;
196+ static BaseType_t xGMACSwitchRequired ;
196197
197198/* LLMNR multicast address. */
198199static const uint8_t llmnr_mac_address [] = { 0x01 , 0x00 , 0x5E , 0x00 , 0x00 , 0xFC };
@@ -205,8 +206,9 @@ static gmac_device_t gs_gmac_dev;
205206 * related interrupts. */
206207TaskHandle_t xEMACTaskHandle = NULL ;
207208
209+ /* TX buffers that have been sent must be returned to the driver
210+ * using this queue. */
208211static QueueHandle_t xTxBufferQueue ;
209- int tx_release_count [ 4 ];
210212
211213/* xTXDescriptorSemaphore is a counting semaphore with
212214 * a maximum count of GMAC_TX_BUFFERS, which is the number of
@@ -271,21 +273,21 @@ void xRxCallback( uint32_t ulStatus )
271273 if ( ( ( ulStatus & GMAC_RSR_REC ) != 0 ) && ( xEMACTaskHandle != NULL ) )
272274 {
273275 /* let the prvEMACHandlerTask know that there was an RX event. */
274- ulISREvents |= EMAC_IF_RX_EVENT ;
275- /* Only an RX interrupt can wakeup prvEMACHandlerTask. */
276- vTaskNotifyGiveFromISR ( xEMACTaskHandle , ( BaseType_t * ) & xGMACSwitchRequired );
276+ xTaskNotifyFromISR ( xEMACTaskHandle , EMAC_IF_RX_EVENT , eSetBits , & ( xGMACSwitchRequired ) );
277277 }
278278}
279279/*-----------------------------------------------------------*/
280280
281+ /* The following function can be called by gmac_reset_tx_mem().
282+ */
281283void returnTxBuffer ( uint8_t * puc_buffer )
282284{
283285 /* Called from a non-ISR context. */
284286 if ( xTxBufferQueue != NULL )
285287 {
288+ /* return 'puc_buffer' to the pool of transmission buffers. */
286289 xQueueSend ( xTxBufferQueue , & puc_buffer , 0 );
287- xTaskNotifyGive ( xEMACTaskHandle );
288- ulISREvents |= EMAC_IF_TX_EVENT ;
290+ xTaskNotify ( xEMACTaskHandle , EMAC_IF_TX_EVENT , eSetBits );
289291 }
290292}
291293
@@ -295,11 +297,21 @@ void xTxCallback( uint32_t ulStatus,
295297 if ( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) )
296298 {
297299 /* let the prvEMACHandlerTask know that there was an TX event. */
298- ulISREvents |= EMAC_IF_TX_EVENT ;
299300 /* Wakeup prvEMACHandlerTask. */
300- vTaskNotifyGiveFromISR ( xEMACTaskHandle , ( BaseType_t * ) & xGMACSwitchRequired );
301- xQueueSendFromISR ( xTxBufferQueue , & puc_buffer , ( BaseType_t * ) & xGMACSwitchRequired );
302- tx_release_count [ 2 ]++ ;
301+ if ( puc_buffer == NULL )
302+ {
303+ /* (GMAC_TSR) Retry Limit Exceeded */
304+ /* Can not send logging, we're in an ISR. */
305+ }
306+ else
307+ {
308+ xQueueSendFromISR ( xTxBufferQueue , & puc_buffer , ( BaseType_t * ) & xGMACSwitchRequired );
309+ xTaskNotifyFromISR ( xEMACTaskHandle , EMAC_IF_TX_EVENT , eSetBits , & ( xGMACSwitchRequired ) );
310+
311+ /* TX statistics. Only works when 'GMAC_STATS'
312+ * is defined as 1. See gmac_SAM.h for more information. */
313+ TX_STAT_INCREMENT ( tx_callback );
314+ }
303315 }
304316}
305317/*-----------------------------------------------------------*/
@@ -445,7 +457,9 @@ BaseType_t xNetworkInterfaceInitialise( void )
445457
446458 if ( xTXDescriptorSemaphore == NULL )
447459 {
448- xTXDescriptorSemaphore = xSemaphoreCreateCounting ( ( UBaseType_t ) GMAC_TX_BUFFERS , ( UBaseType_t ) GMAC_TX_BUFFERS );
460+ /* When there are N TX descriptors, we want to use
461+ * at most "N-1" simultaneously. */
462+ xTXDescriptorSemaphore = xSemaphoreCreateCounting ( ( UBaseType_t ) GMAC_TX_BUFFERS - 1U , ( UBaseType_t ) GMAC_TX_BUFFERS - 1U );
449463 configASSERT ( xTXDescriptorSemaphore );
450464 }
451465
@@ -483,7 +497,6 @@ static void hand_tx_errors( void )
483497 gmac_enable_transmit ( GMAC , false );
484498
485499 /* Reinit TX descriptors. */
486- /* gmac_tx_init(ps_gmac_dev); */
487500 gmac_reset_tx_mem ( & gs_gmac_dev );
488501 /* Clear error status. */
489502 gmac_clear_tx_status ( GMAC , GMAC_TX_ERRORS );
@@ -498,7 +511,7 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript
498511 BaseType_t bReleaseAfterSend )
499512{
500513/* Do not wait too long for a free TX DMA buffer. */
501- const TickType_t xBlockTimeTicks = pdMS_TO_TICKS ( 50u );
514+ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS ( 50U );
502515 uint32_t ulTransmitSize ;
503516
504517 ulTransmitSize = pxDescriptor -> xDataLength ;
@@ -514,6 +527,8 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript
514527 * statement. */
515528 do
516529 {
530+ uint32_t ulResult ;
531+
517532 if ( xPhyObject .ulLinkStatusMask == 0ul )
518533 {
519534 /* 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
531546 if ( xSemaphoreTake ( xTXDescriptorSemaphore , xBlockTimeTicks ) != pdPASS )
532547 {
533548 /* Time-out waiting for a free TX descriptor. */
534- tx_release_count [ 3 ] ++ ;
549+ TX_STAT_INCREMENT ( tx_enqueue_fail ) ;
535550 break ;
536551 }
537552
553+ TX_STAT_INCREMENT ( tx_enqueue_ok );
538554 #if ( ipconfigZERO_COPY_TX_DRIVER != 0 )
539555 {
540556 /* Confirm that the pxDescriptor may be kept by the driver. */
@@ -550,7 +566,12 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript
550566 }
551567 #endif
552568
553- gmac_dev_write ( & gs_gmac_dev , ( void * ) pxDescriptor -> pucEthernetBuffer , pxDescriptor -> xDataLength );
569+ ulResult = gmac_dev_write ( & gs_gmac_dev , ( void * ) pxDescriptor -> pucEthernetBuffer , pxDescriptor -> xDataLength );
570+
571+ if ( ulResult != GMAC_OK )
572+ {
573+ TX_STAT_INCREMENT ( tx_write_fail );
574+ }
554575
555576 #if ( ipconfigZERO_COPY_TX_DRIVER != 0 )
556577 {
@@ -594,7 +615,7 @@ static BaseType_t prvGMACInit( void )
594615
595616 {
596617 /* Set MDC clock divider. */
597- gmac_set_mdc_clock ( GMAC , sysclk_get_cpu_hz () );
618+ gmac_set_mdc_clock ( GMAC , sysclk_get_peripheral_hz () );
598619
599620 vPhyInitialise ( & xPhyObject , xPHY_Read , xPHY_Write );
600621 xPhyDiscover ( & xPhyObject );
@@ -840,7 +861,7 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB
840861static void prvEMACHandlerTask ( void * pvParameters )
841862{
842863 UBaseType_t uxCount ;
843- UBaseType_t uxLowestSemCount = 0 ;
864+ UBaseType_t uxLowestSemCount = GMAC_TX_BUFFERS + 1 ;
844865
845866 #if ( ipconfigZERO_COPY_TX_DRIVER != 0 )
846867 NetworkBufferDescriptor_t * pxBuffer ;
@@ -849,6 +870,7 @@ static void prvEMACHandlerTask( void * pvParameters )
849870 BaseType_t xResult = 0 ;
850871 uint32_t xStatus ;
851872 const TickType_t ulMaxBlockTime = pdMS_TO_TICKS ( EMAC_MAX_BLOCK_TIME_MS );
873+ uint32_t ulISREvents = 0U ;
852874
853875 /* Remove compiler warnings about unused parameters. */
854876 ( void ) pvParameters ;
@@ -879,26 +901,21 @@ static void prvEMACHandlerTask( void * pvParameters )
879901 }
880902 #endif /* ( ipconfigHAS_PRINTF != 0 ) */
881903
882- if ( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
883- {
884- /* No events to process now, wait for the next. */
885- ulTaskNotifyTake ( pdFALSE , ulMaxBlockTime );
886- }
904+ /* Wait for a new event or a time-out. */
905+ xTaskNotifyWait ( 0U , /* ulBitsToClearOnEntry */
906+ EMAC_IF_ALL_EVENT , /* ulBitsToClearOnExit */
907+ & ( ulISREvents ), /* pulNotificationValue */
908+ ulMaxBlockTime );
887909
888910 if ( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
889911 {
890- ulISREvents &= ~EMAC_IF_RX_EVENT ;
891-
892912 /* Wait for the EMAC interrupt to indicate that another packet has been
893913 * received. */
894914 xResult = prvEMACRxPoll ();
895915 }
896916
897917 if ( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
898918 {
899- /* Future extension: code to release TX buffers if zero-copy is used. */
900- ulISREvents &= ~EMAC_IF_TX_EVENT ;
901-
902919 while ( xQueueReceive ( xTxBufferQueue , & pucBuffer , 0 ) != pdFALSE )
903920 {
904921 #if ( ipconfigZERO_COPY_TX_DRIVER != 0 )
@@ -908,21 +925,21 @@ static void prvEMACHandlerTask( void * pvParameters )
908925 if ( pxBuffer != NULL )
909926 {
910927 vReleaseNetworkBufferAndDescriptor ( pxBuffer );
911- tx_release_count [ 0 ] ++ ;
928+ TX_STAT_INCREMENT ( tx_release_ok ) ;
912929 }
913930 else
914931 {
915- tx_release_count [ 1 ] ++ ;
932+ TX_STAT_INCREMENT ( tx_release_bad ) ;
916933 }
917934 }
918935 #else /* if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) */
919936 {
920- tx_release_count [ 0 ] ++ ;
937+ TX_STAT_INCREMENT ( tx_release_ok ) ;
921938 }
922939 #endif /* if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) */
923940 uxCount = uxQueueMessagesWaiting ( ( QueueHandle_t ) xTXDescriptorSemaphore );
924941
925- if ( uxCount < GMAC_TX_BUFFERS )
942+ if ( uxCount < ( GMAC_TX_BUFFERS - 1 ) )
926943 {
927944 /* Tell the counting semaphore that one more TX descriptor is available. */
928945 xSemaphoreGive ( xTXDescriptorSemaphore );
@@ -933,7 +950,6 @@ static void prvEMACHandlerTask( void * pvParameters )
933950 if ( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
934951 {
935952 /* Future extension: logging about errors that occurred. */
936- ulISREvents &= ~EMAC_IF_ERR_EVENT ;
937953 }
938954
939955 gmac_enable_management ( GMAC , true );
0 commit comments