2 * Some constants, hardware definitions and comments taken from ST's HAL driver
\r
3 * library, COPYRIGHT(c) 2015 STMicroelectronics.
\r
7 * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
\r
8 * Authors include Hein Tibosch and Richard Barry
\r
10 *******************************************************************************
\r
11 ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
\r
14 *** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
\r
15 *** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
\r
18 *** FreeRTOS+TCP is functional and has been used in commercial products ***
\r
19 *** for some time. Be aware however that we are still refining its ***
\r
20 *** design, the source code does not yet quite conform to the strict ***
\r
21 *** coding and style standards mandated by Real Time Engineers ltd., and ***
\r
22 *** the documentation and testing is not necessarily complete. ***
\r
24 *** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
\r
25 *** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
\r
26 *** the sole discretion of Real Time Engineers Ltd., be offered versions ***
\r
27 *** under a license other than that described below. ***
\r
30 ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
\r
31 *******************************************************************************
\r
33 * FreeRTOS+TCP can be used under two different free open source licenses. The
\r
34 * license that applies is dependent on the processor on which FreeRTOS+TCP is
\r
35 * executed, as follows:
\r
37 * If FreeRTOS+TCP is executed on one of the processors listed under the Special
\r
38 * License Arrangements heading of the FreeRTOS+TCP license information web
\r
39 * page, then it can be used under the terms of the FreeRTOS Open Source
\r
40 * License. If FreeRTOS+TCP is used on any other processor, then it can be used
\r
41 * under the terms of the GNU General Public License V2. Links to the relevant
\r
44 * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
\r
45 * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
\r
46 * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
\r
48 * FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
\r
49 * use FreeRTOS+TCP unless you agree that you use the software 'as is'.
\r
50 * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
\r
51 * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
\r
52 * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
\r
53 * implied, expressed, or statutory.
\r
55 * 1 tab == 4 spaces!
\r
57 * http://www.FreeRTOS.org
\r
58 * http://www.FreeRTOS.org/plus
\r
59 * http://www.FreeRTOS.org/labs
\r
63 /* Standard includes. */
\r
68 /* FreeRTOS includes. */
\r
69 #include "FreeRTOS.h"
\r
74 /* FreeRTOS+TCP includes. */
\r
75 #include "FreeRTOS_IP.h"
\r
76 #include "FreeRTOS_Sockets.h"
\r
77 #include "FreeRTOS_IP_Private.h"
\r
78 #include "FreeRTOS_DNS.h"
\r
79 #include "NetworkBufferManagement.h"
\r
80 #include "NetworkInterface.h"
\r
82 #include "phyHandling.h"
\r
86 #include "stm32f7xx_hal.h"
\r
88 #include "stm32f4xx_hal.h"
\r
91 /* Interrupt events to process. Currently only the Rx event is processed
\r
92 although code for other events is included to allow for possible future
\r
94 #define EMAC_IF_RX_EVENT 1UL
\r
95 #define EMAC_IF_TX_EVENT 2UL
\r
96 #define EMAC_IF_ERR_EVENT 4UL
\r
97 #define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )
\r
99 #define ETH_DMA_ALL_INTS \
\r
100 ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | ETH_DMA_IT_ER | \
\r
101 ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \
\r
102 ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )
\r
106 #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */
\r
109 * Most users will want a PHY that negotiates about
\r
110 * the connection properties: speed, dmix and duplex.
\r
111 * On some rare cases, you want to select what is being
\r
112 * advertised, properties like MDIX and duplex.
\r
115 #if !defined( ipconfigETHERNET_AN_ENABLE )
\r
116 /* Enable auto-negotiation */
\r
117 #define ipconfigETHERNET_AN_ENABLE 1
\r
120 #if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE )
\r
121 #define ipconfigETHERNET_AUTO_CROSS_ENABLE 1
\r
124 #if( ipconfigETHERNET_AN_ENABLE == 0 )
\r
126 * The following three defines are only used in case there
\r
127 * is no auto-negotiation.
\r
129 #if !defined( ipconfigETHERNET_CROSSED_LINK )
\r
130 #define ipconfigETHERNET_CROSSED_LINK 1
\r
133 #if !defined( ipconfigETHERNET_USE_100MB )
\r
134 #define ipconfigETHERNET_USE_100MB 1
\r
137 #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX )
\r
138 #define ipconfigETHERNET_USE_FULL_DUPLEX 1
\r
140 #endif /* ipconfigETHERNET_AN_ENABLE == 0 */
\r
142 /* Default the size of the stack used by the EMAC deferred handler task to twice
\r
143 the size of the stack used by the idle task - but allow this to be overridden in
\r
144 FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
\r
145 #ifndef configEMAC_TASK_STACK_SIZE
\r
146 #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
\r
149 /* Two choices must be made: RMII versus MII,
\r
150 and the index of the PHY in use ( between 0 and 31 ). */
\r
151 #ifndef ipconfigUSE_RMII
\r
153 #define ipconfigUSE_RMII 1
\r
155 #define ipconfigUSE_RMII 0
\r
156 #endif /* STM32F7xx */
\r
157 #endif /* ipconfigUSE_RMII */
\r
159 #ifndef ipconfigPHY_INDEX
\r
161 #define ipconfigPHY_INDEX 0
\r
163 #define ipconfigPHY_INDEX 1
\r
164 #endif /* STM32F7xx */
\r
165 #endif /* ipconfigPHY_INDEX */
\r
168 /*-----------------------------------------------------------*/
\r
171 * A deferred interrupt handler task that processes
\r
173 static void prvEMACHandlerTask( void *pvParameters );
\r
176 * Force a negotiation with the Switch or Router and wait for LS.
\r
178 static void prvEthernetUpdateConfig( BaseType_t xForce );
\r
181 * See if there is a new packet and forward it to the IP-task.
\r
183 static BaseType_t prvNetworkInterfaceInput( void );
\r
185 #if( ipconfigUSE_LLMNR != 0 )
\r
187 * For LLMNR, an extra MAC-address must be configured to
\r
188 * be able to receive the multicast messages.
\r
190 static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr);
\r
194 * Check if a given packet should be accepted.
\r
196 static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer );
\r
199 * Initialise the TX descriptors.
\r
201 static void prvDMATxDescListInit( void );
\r
204 * Initialise the RX descriptors.
\r
206 static void prvDMARxDescListInit( void );
\r
208 /* After packets have been sent, the network
\r
209 buffers will be released. */
\r
210 static void vClearTXBuffers( void );
\r
212 /*-----------------------------------------------------------*/
\r
214 /* Bit map of outstanding ETH interrupt events for processing. Currently only
\r
215 the Rx interrupt is handled, although code is included for other events to
\r
216 enable future expansion. */
\r
217 static volatile uint32_t ulISREvents;
\r
219 #if( ipconfigUSE_LLMNR == 1 )
\r
220 static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
\r
223 static EthernetPhy_t xPhyObject;
\r
225 /* Ethernet handle. */
\r
226 static ETH_HandleTypeDef xETH;
\r
228 /* xTXDescriptorSemaphore is a counting semaphore with
\r
229 a maximum count of ETH_TXBUFNB, which is the number of
\r
230 DMA TX descriptors. */
\r
231 static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
\r
234 * Note: it is adviced to define both
\r
236 * #define ipconfigZERO_COPY_RX_DRIVER 1
\r
237 * #define ipconfigZERO_COPY_TX_DRIVER 1
\r
239 * The method using memcpy is slower and probaly uses more RAM memory.
\r
240 * The possibility is left in the code just for comparison.
\r
242 * It is adviced to define ETH_TXBUFNB at least 4. Note that no
\r
243 * TX buffers are allocated in a zero-copy driver.
\r
245 /* MAC buffers: ---------------------------------------------------------*/
\r
247 /* Put the DMA descriptors in '.first_data'.
\r
248 This is important for STM32F7, which has an L1 data cache.
\r
249 The first 64KB of the SRAM is not cached. */
\r
251 /* Ethernet Rx MA Descriptor */
\r
252 __attribute__ ((aligned (32)))
\r
253 __attribute__ ((section(".first_data")))
\r
254 ETH_DMADescTypeDef DMARxDscrTab[ ETH_RXBUFNB ];
\r
256 #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
\r
257 /* Ethernet Receive Buffer */
\r
258 __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END;
\r
261 /* Ethernet Tx DMA Descriptor */
\r
262 __attribute__ ((aligned (32)))
\r
263 __attribute__ ((section(".first_data")))
\r
264 ETH_DMADescTypeDef DMATxDscrTab[ ETH_TXBUFNB ];
\r
266 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
\r
267 /* Ethernet Transmit Buffer */
\r
268 __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END;
\r
271 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
272 /* DMATxDescToClear points to the next TX DMA descriptor
\r
273 that must be cleared by vClearTXBuffers(). */
\r
274 static __IO ETH_DMADescTypeDef *DMATxDescToClear;
\r
277 /* ucMACAddress as it appears in main.c */
\r
278 extern const uint8_t ucMACAddress[ 6 ];
\r
280 /* Holds the handle of the task used as a deferred interrupt processor. The
\r
281 handle is used so direct notifications can be sent to the task for all EMAC/DMA
\r
282 related interrupts. */
\r
283 static TaskHandle_t xEMACTaskHandle = NULL;
\r
285 /* For local use only: describe the PHY's properties: */
\r
286 const PhyProperties_t xPHYProperties =
\r
288 #if( ipconfigETHERNET_AN_ENABLE != 0 )
\r
289 .ucSpeed = PHY_SPEED_AUTO,
\r
290 .ucDuplex = PHY_DUPLEX_AUTO,
\r
292 #if( ipconfigETHERNET_USE_100MB != 0 )
\r
293 .ucSpeed = PHY_SPEED_100,
\r
295 .ucSpeed = PHY_SPEED_10,
\r
298 #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )
\r
299 .duplex = PHY_DUPLEX_FULL,
\r
301 .duplex = PHY_DUPLEX_HALF,
\r
305 #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )
\r
306 .ucMDI_X = PHY_MDIX_AUTO,
\r
307 #elif( ipconfigETHERNET_CROSSED_LINK != 0 )
\r
308 .ucMDI_X = PHY_MDIX_CROSSED,
\r
310 .ucMDI_X = PHY_MDIX_DIRECT,
\r
314 /*-----------------------------------------------------------*/
\r
316 void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )
\r
318 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
320 /* Ethernet RX-Complete callback function, elsewhere declared as weak. */
\r
321 ulISREvents |= EMAC_IF_RX_EVENT;
\r
322 /* Wakeup the prvEMACHandlerTask. */
\r
323 if( xEMACTaskHandle != NULL )
\r
325 vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
\r
326 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
\r
329 /*-----------------------------------------------------------*/
\r
331 void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )
\r
333 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
335 /* This call-back is only useful in case packets are being sent
\r
336 zero-copy. Once they're sent, the buffers will be released
\r
337 by the function vClearTXBuffers(). */
\r
338 ulISREvents |= EMAC_IF_TX_EVENT;
\r
339 /* Wakeup the prvEMACHandlerTask. */
\r
340 if( xEMACTaskHandle != NULL )
\r
342 vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
\r
343 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
\r
347 /*-----------------------------------------------------------*/
\r
349 static void vClearTXBuffers()
\r
351 __IO ETH_DMADescTypeDef *txLastDescriptor = xETH.TxDesc;
\r
352 size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
\r
353 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
354 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
355 uint8_t *ucPayLoad;
\r
358 /* This function is called after a TX-completion interrupt.
\r
359 It will release each Network Buffer used in xNetworkInterfaceOutput().
\r
360 'uxCount' represents the number of descriptors given to DMA for transmission.
\r
361 After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */
\r
362 while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )
\r
364 if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )
\r
368 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
370 ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;
\r
372 if( ucPayLoad != NULL )
\r
374 pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );
\r
375 if( pxNetworkBuffer != NULL )
\r
377 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;
\r
379 DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;
\r
382 #endif /* ipconfigZERO_COPY_TX_DRIVER */
\r
384 DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );
\r
387 /* Tell the counting semaphore that one more TX descriptor is available. */
\r
388 xSemaphoreGive( xTXDescriptorSemaphore );
\r
391 /*-----------------------------------------------------------*/
\r
393 BaseType_t xNetworkInterfaceInitialise( void )
\r
395 HAL_StatusTypeDef hal_eth_init_status;
\r
396 BaseType_t xResult;
\r
398 if( xEMACTaskHandle == NULL )
\r
400 if( xTXDescriptorSemaphore == NULL )
\r
402 xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );
\r
403 configASSERT( xTXDescriptorSemaphore );
\r
406 /* Initialise ETH */
\r
408 xETH.Instance = ETH;
\r
409 //#warning Enable auto-nego again
\r
410 xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
\r
411 // xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
\r
412 xETH.Init.Speed = ETH_SPEED_100M;
\r
413 xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
\r
414 xETH.Init.PhyAddress = ipconfigPHY_INDEX;
\r
416 xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;
\r
417 xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;
\r
419 /* using the ETH_CHECKSUM_BY_HARDWARE option:
\r
420 both the IP and the protocol checksums will be calculated
\r
421 by the peripheral. */
\r
422 xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
\r
424 #if( ipconfigUSE_RMII != 0 )
\r
426 xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
\r
430 xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
\r
432 #endif /* ipconfigUSE_RMII */
\r
434 hal_eth_init_status = HAL_ETH_Init( &xETH );
\r
436 /* Only for inspection by debugger. */
\r
437 ( void ) hal_eth_init_status;
\r
439 /* Set the TxDesc and RxDesc pointers. */
\r
440 xETH.TxDesc = DMATxDscrTab;
\r
441 xETH.RxDesc = DMARxDscrTab;
\r
443 /* Make sure that all unused fields are cleared. */
\r
444 memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );
\r
445 memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );
\r
447 /* Initialize Tx Descriptors list: Chain Mode */
\r
448 DMATxDescToClear = DMATxDscrTab;
\r
450 /* Initialise TX-descriptors. */
\r
451 prvDMATxDescListInit();
\r
453 /* Initialise RX-descriptors. */
\r
454 prvDMARxDescListInit();
\r
456 #if( ipconfigUSE_LLMNR != 0 )
\r
458 /* Program the LLMNR address at index 1. */
\r
459 prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );
\r
463 /* Force a negotiation with the Switch or Router and wait for LS. */
\r
464 prvEthernetUpdateConfig( pdTRUE );
\r
466 /* The deferred interrupt handler task is created at the highest
\r
467 possible priority to ensure the interrupt handler can return directly
\r
468 to it. The task's handle is stored in xEMACTaskHandle so interrupts can
\r
469 notify the task when there is something to process. */
\r
470 xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
\r
471 } /* if( xEMACTaskHandle == NULL ) */
\r
473 if( xPhyObject.ulLinkStatusMask != 0 )
\r
475 xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;
\r
477 FreeRTOS_printf( ( "Link Status is high\n" ) ) ;
\r
481 /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
\r
482 and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */
\r
484 FreeRTOS_printf( ( "Link Status still low\n" ) ) ;
\r
486 /* When returning non-zero, the stack will become active and
\r
487 start DHCP (in configured) */
\r
490 /*-----------------------------------------------------------*/
\r
492 static void prvDMATxDescListInit()
\r
494 ETH_DMADescTypeDef *pxDMADescriptor;
\r
497 /* Get the pointer on the first member of the descriptor list */
\r
498 pxDMADescriptor = DMATxDscrTab;
\r
500 /* Fill each DMA descriptor with the right values */
\r
501 for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ )
\r
503 /* Set Second Address Chained bit */
\r
504 pxDMADescriptor->Status = ETH_DMATXDESC_TCH;
\r
506 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
\r
508 /* Set Buffer1 address pointer */
\r
509 pxDMADescriptor->Buffer1Addr = ( uint32_t )( Tx_Buff[ xIndex ] );
\r
513 if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE )
\r
515 /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */
\r
516 pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;
\r
519 /* Initialize the next descriptor with the Next Descriptor Polling Enable */
\r
520 if( xIndex < ETH_TXBUFNB - 1 )
\r
522 /* Set next descriptor address register with next descriptor base address */
\r
523 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 );
\r
527 /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
\r
528 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab;
\r
532 /* Set Transmit Descriptor List Address Register */
\r
533 xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab;
\r
535 /*-----------------------------------------------------------*/
\r
537 static void prvDMARxDescListInit()
\r
539 ETH_DMADescTypeDef *pxDMADescriptor;
\r
545 /* Get the pointer on the first member of the descriptor list */
\r
546 pxDMADescriptor = DMARxDscrTab;
\r
548 /* Fill each DMA descriptor with the right values */
\r
549 for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ )
\r
552 /* Set Buffer1 size and Second Address Chained bit */
\r
553 pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;
\r
555 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
557 /* Set Buffer1 address pointer */
\r
558 NetworkBufferDescriptor_t *pxBuffer;
\r
560 pxBuffer = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, 100ul );
\r
561 /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB'
\r
562 Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */
\r
563 configASSERT( pxBuffer != NULL );
\r
564 if( pxBuffer != NULL )
\r
566 pxDMADescriptor->Buffer1Addr = (uint32_t)pxBuffer->pucEthernetBuffer;
\r
567 pxDMADescriptor->Status = ETH_DMARXDESC_OWN;
\r
572 /* Set Buffer1 address pointer */
\r
573 pxDMADescriptor->Buffer1Addr = ( uint32_t )( Rx_Buff[ xIndex ] );
\r
574 /* Set Own bit of the Rx descriptor Status */
\r
575 pxDMADescriptor->Status = ETH_DMARXDESC_OWN;
\r
579 /* Initialize the next descriptor with the Next Descriptor Polling Enable */
\r
580 if( xIndex < ETH_RXBUFNB - 1 )
\r
582 /* Set next descriptor address register with next descriptor base address */
\r
583 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t )( pxDMADescriptor + 1 );
\r
587 /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
\r
588 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab;
\r
592 /* Set Receive Descriptor List Address Register */
\r
593 xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab;
\r
595 /*-----------------------------------------------------------*/
\r
597 static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr)
\r
599 uint32_t ulTempReg;
\r
601 /* Calculate the selected MAC address high register. */
\r
602 ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];
\r
604 /* Load the selected MAC address high register. */
\r
605 ( *(__IO uint32_t *)( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg;
\r
607 /* Calculate the selected MAC address low register. */
\r
608 ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ];
\r
610 /* Load the selected MAC address low register */
\r
611 ( *(__IO uint32_t *) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg;
\r
613 /*-----------------------------------------------------------*/
\r
615 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
\r
617 BaseType_t xReturn = pdFAIL;
\r
618 uint32_t ulTransmitSize = 0;
\r
619 __IO ETH_DMADescTypeDef *pxDmaTxDesc;
\r
620 /* Do not wait too long for a free TX DMA buffer. */
\r
621 const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
\r
623 #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
\r
625 ProtocolPacket_t *pxPacket;
\r
627 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
629 configASSERT( bReleaseAfterSend != 0 );
\r
631 #endif /* ipconfigZERO_COPY_RX_DRIVER */
\r
633 /* If the peripheral must calculate the checksum, it wants
\r
634 the protocol checksum to have a value of zero. */
\r
635 pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );
\r
637 if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )
\r
639 pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;
\r
644 /* Open a do {} while ( 0 ) loop to be able to call break. */
\r
647 if( xPhyObject.ulLinkStatusMask != 0 )
\r
649 if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
\r
651 /* Time-out waiting for a free TX descriptor. */
\r
655 /* This function does the actual transmission of the packet. The packet is
\r
656 contained in 'pxDescriptor' that is passed to the function. */
\r
657 pxDmaTxDesc = xETH.TxDesc;
\r
659 /* Is this buffer available? */
\r
660 configASSERT ( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 );
\r
663 /* Is this buffer available? */
\r
664 /* Get bytes in current buffer. */
\r
665 ulTransmitSize = pxDescriptor->xDataLength;
\r
667 if( ulTransmitSize > ETH_TX_BUF_SIZE )
\r
669 ulTransmitSize = ETH_TX_BUF_SIZE;
\r
672 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
\r
674 /* Copy the bytes. */
\r
675 memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );
\r
679 /* Move the buffer. */
\r
680 pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;
\r
681 /* The Network Buffer has been passed to DMA, no need to release it. */
\r
682 bReleaseAfterSend = pdFALSE_UNSIGNED;
\r
684 #endif /* ipconfigZERO_COPY_TX_DRIVER */
\r
686 /* Ask to set the IPv4 checksum.
\r
687 Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */
\r
688 pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;
\r
690 /* Prepare transmit descriptors to give to DMA. */
\r
692 /* Set LAST and FIRST segment */
\r
693 pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;
\r
694 /* Set frame size */
\r
695 pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );
\r
696 /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
\r
697 pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;
\r
699 /* Point to next descriptor */
\r
700 xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );
\r
701 /* Ensure completion of memory access */
\r
703 /* Resume DMA transmission*/
\r
704 xETH.Instance->DMATPDR = 0;
\r
705 iptraceNETWORK_INTERFACE_TRANSMIT();
\r
711 /* The PHY has no Link Status, packet shall be dropped. */
\r
714 /* The buffer has been sent so can be released. */
\r
715 if( bReleaseAfterSend != pdFALSE )
\r
717 vReleaseNetworkBufferAndDescriptor( pxDescriptor );
\r
722 /*-----------------------------------------------------------*/
\r
724 static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer )
\r
726 const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
\r
728 switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType )
\r
730 case ipARP_FRAME_TYPE:
\r
731 /* Check it later. */
\r
733 case ipIPv4_FRAME_TYPE:
\r
734 /* Check it here. */
\r
737 /* Refuse the packet. */
\r
741 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
743 const IPHeader_t *pxIPHeader = &(pxProtPacket->xTCPPacket.xIPHeader);
\r
744 uint32_t ulDestinationIPAddress;
\r
746 /* Ensure that the incoming packet is not fragmented (only outgoing packets
\r
747 * can be fragmented) as these are the only handled IP frames currently. */
\r
748 if( ( pxIPHeader->usFragmentOffset & FreeRTOS_ntohs( ipFRAGMENT_OFFSET_BIT_MASK ) ) != 0U )
\r
752 /* HT: Might want to make the following configurable because
\r
753 * most IP messages have a standard length of 20 bytes */
\r
755 /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes
\r
756 * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */
\r
757 if( pxIPHeader->ucVersionHeaderLength < 0x45 || pxIPHeader->ucVersionHeaderLength > 0x4F )
\r
762 ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;
\r
763 /* Is the packet for this node? */
\r
764 if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&
\r
765 /* Is it a broadcast address x.x.x.255 ? */
\r
766 ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) &&
\r
767 #if( ipconfigUSE_LLMNR == 1 )
\r
768 ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&
\r
770 ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) {
\r
771 FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) );
\r
775 if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )
\r
777 uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;
\r
779 if( ( xPortHasUDPSocket( port ) == pdFALSE )
\r
780 #if ipconfigUSE_LLMNR == 1
\r
781 && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )
\r
783 #if ipconfigUSE_NBNS == 1
\r
784 && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )
\r
786 #if ipconfigUSE_DNS == 1
\r
787 && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )
\r
790 /* Drop this packet, not for this device. */
\r
795 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
798 /*-----------------------------------------------------------*/
\r
800 static BaseType_t prvNetworkInterfaceInput( void )
\r
802 NetworkBufferDescriptor_t *pxCurDescriptor;
\r
803 NetworkBufferDescriptor_t *pxNewDescriptor = NULL;
\r
804 BaseType_t xReceivedLength, xAccepted;
\r
805 __IO ETH_DMADescTypeDef *pxDMARxDescriptor;
\r
806 xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
\r
807 const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
\r
808 uint8_t *pucBuffer;
\r
810 pxDMARxDescriptor = xETH.RxDesc;
\r
812 if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )
\r
814 /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
\r
815 xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;
\r
817 pucBuffer = (uint8_t *) pxDMARxDescriptor->Buffer1Addr;
\r
819 /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */
\r
820 /* Chained Mode */
\r
821 /* Selects the next DMA Rx descriptor list for next buffer to read */
\r
822 xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;
\r
826 xReceivedLength = 0;
\r
829 /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */
\r
831 /* get received frame */
\r
832 if( xReceivedLength > 0ul )
\r
834 /* In order to make the code easier and faster, only packets in a single buffer
\r
835 will be accepted. This can be done by making the buffers large enough to
\r
836 hold a complete Ethernet packet (1536 bytes).
\r
837 Therefore, two sanity checks: */
\r
838 configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );
\r
840 if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )
\r
842 /* Not an Ethernet frame-type or a checmsum error. */
\r
843 xAccepted = pdFALSE;
\r
847 /* See if this packet must be handled. */
\r
848 xAccepted = xMayAcceptPacket( pucBuffer );
\r
851 if( xAccepted != pdFALSE )
\r
853 /* The packet wil be accepted, but check first if a new Network Buffer can
\r
854 be obtained. If not, the packet will still be dropped. */
\r
855 pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, xDescriptorWaitTime );
\r
857 if( pxNewDescriptor == NULL )
\r
859 /* A new descriptor can not be allocated now. This packet will be dropped. */
\r
860 xAccepted = pdFALSE;
\r
863 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
865 /* Find out which Network Buffer was originally passed to the descriptor. */
\r
866 pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
\r
867 configASSERT( pxCurDescriptor != NULL );
\r
871 /* In this mode, the two descriptors are the same. */
\r
872 pxCurDescriptor = pxNewDescriptor;
\r
873 if( pxNewDescriptor != NULL )
\r
875 /* The packet is acepted and a new Network Buffer was created,
\r
876 copy data to the Network Bufffer. */
\r
877 memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength );
\r
882 if( xAccepted != pdFALSE )
\r
884 pxCurDescriptor->xDataLength = xReceivedLength;
\r
885 xRxEvent.pvData = ( void * ) pxCurDescriptor;
\r
887 /* Pass the data to the TCP/IP task for processing. */
\r
888 if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )
\r
890 /* Could not send the descriptor into the TCP/IP stack, it
\r
891 must be released. */
\r
892 vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );
\r
893 iptraceETHERNET_RX_EVENT_LOST();
\r
897 iptraceNETWORK_INTERFACE_RECEIVE();
\r
901 /* Release descriptors to DMA */
\r
902 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
904 /* Set Buffer1 address pointer */
\r
905 if( pxNewDescriptor != NULL )
\r
907 pxDMARxDescriptor->Buffer1Addr = (uint32_t)pxNewDescriptor->pucEthernetBuffer;
\r
911 /* The packet was dropped and the same Network
\r
912 Buffer will be used to receive a new packet. */
\r
915 #endif /* ipconfigZERO_COPY_RX_DRIVER */
\r
917 /* Set Buffer1 size and Second Address Chained bit */
\r
918 pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;
\r
919 pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;
\r
921 /* Ensure completion of memory access */
\r
923 /* When Rx Buffer unavailable flag is set clear it and resume
\r
925 if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )
\r
927 /* Clear RBUS ETHERNET DMA flag. */
\r
928 xETH.Instance->DMASR = ETH_DMASR_RBUS;
\r
930 /* Resume DMA reception. */
\r
931 xETH.Instance->DMARPDR = 0;
\r
935 return ( xReceivedLength > 0 );
\r
937 /*-----------------------------------------------------------*/
\r
940 BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )
\r
942 uint16_t usPrevAddress = xETH.Init.PhyAddress;
\r
943 BaseType_t xResult;
\r
944 HAL_StatusTypeDef xHALResult;
\r
946 xETH.Init.PhyAddress = xAddress;
\r
947 xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t )xRegister, pulValue );
\r
948 xETH.Init.PhyAddress = usPrevAddress;
\r
950 if( xHALResult == HAL_OK )
\r
960 /*-----------------------------------------------------------*/
\r
962 BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )
\r
964 uint16_t usPrevAddress = xETH.Init.PhyAddress;
\r
965 BaseType_t xResult;
\r
966 HAL_StatusTypeDef xHALResult;
\r
968 xETH.Init.PhyAddress = xAddress;
\r
969 xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t )xRegister, ulValue );
\r
970 xETH.Init.PhyAddress = usPrevAddress;
\r
972 if( xHALResult == HAL_OK )
\r
982 /*-----------------------------------------------------------*/
\r
986 BaseType_t xPhyCount;
\r
987 BaseType_t xPhyIndex;
\r
989 vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );
\r
990 xPhyCount = xPhyDiscover( &xPhyObject );
\r
991 FreeRTOS_printf( ( "PHY count %ld\n", xPhyCount ) );
\r
992 for( xPhyIndex = 0; xPhyIndex < xPhyCount; xPhyIndex++ )
\r
994 FreeRTOS_printf( ( "PHY[%d] at address %d ( 0x%08X )\n",
\r
996 xPhyObject.ucPhyIndexes[ xPhyIndex ],
\r
997 xPhyObject.ulPhyIDs[ xPhyIndex ] ) );
\r
1003 void vMACBProbePhy( void )
\r
1005 vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );
\r
1006 xPhyDiscover( &xPhyObject );
\r
1007 xPhyConfigure( &xPhyObject, &xPHYProperties );
\r
1009 /*-----------------------------------------------------------*/
\r
1011 static void prvEthernetUpdateConfig( BaseType_t xForce )
\r
1013 FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02X Force %d\n",
\r
1014 xPhyObject.ulLinkStatusMask,
\r
1015 ( int )xForce ) );
\r
1017 if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )
\r
1019 /* Restart the auto-negotiation. */
\r
1020 if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )
\r
1022 xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );
\r
1024 /* Configure the MAC with the Duplex Mode fixed by the
\r
1025 auto-negotiation process. */
\r
1026 if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )
\r
1028 xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
\r
1032 xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
\r
1035 /* Configure the MAC with the speed fixed by the
\r
1036 auto-negotiation process. */
\r
1037 if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )
\r
1039 xETH.Init.Speed = ETH_SPEED_10M;
\r
1043 xETH.Init.Speed = ETH_SPEED_100M;
\r
1046 else /* AutoNegotiation Disable */
\r
1048 /* Check parameters */
\r
1049 assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );
\r
1050 assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );
\r
1052 if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX )
\r
1054 xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;
\r
1058 xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;
\r
1061 if( xETH.Init.Speed == ETH_SPEED_10M )
\r
1063 xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;
\r
1067 xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;
\r
1070 xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;
\r
1072 /* Use predefined (fixed) configuration. */
\r
1073 xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );
\r
1076 /* ETHERNET MAC Re-Configuration */
\r
1077 HAL_ETH_ConfigMAC( &xETH, (ETH_MACInitTypeDef *) NULL);
\r
1079 /* Restart MAC interface */
\r
1080 HAL_ETH_Start( &xETH);
\r
1084 /* Stop MAC interface */
\r
1085 HAL_ETH_Stop( &xETH );
\r
1088 /*-----------------------------------------------------------*/
\r
1090 BaseType_t xGetPhyLinkStatus( void )
\r
1092 BaseType_t xReturn;
\r
1094 if( xPhyObject.ulLinkStatusMask != 0 )
\r
1105 /*-----------------------------------------------------------*/
\r
1107 #define niBUFFER_1_PACKET_SIZE 1536
\r
1109 static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
\r
1111 void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
\r
1114 uint8_t *ucRAMBuffer = ucNetworkPackets;
\r
1117 for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
\r
1119 pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
\r
1120 *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
\r
1121 ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
\r
1124 /*-----------------------------------------------------------*/
\r
1126 static void prvEMACHandlerTask( void *pvParameters )
\r
1128 UBaseType_t uxLastMinBufferCount = 0;
\r
1129 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
\r
1130 UBaseType_t uxLastMinQueueSpace = 0;
\r
1132 UBaseType_t uxCurrentCount;
\r
1133 BaseType_t xResult;
\r
1134 const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
\r
1136 /* Remove compiler warnings about unused parameters. */
\r
1137 ( void ) pvParameters;
\r
1142 uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
\r
1143 if( uxLastMinBufferCount != uxCurrentCount )
\r
1145 /* The logging produced below may be helpful
\r
1146 while tuning +TCP: see how many buffers are in use. */
\r
1147 uxLastMinBufferCount = uxCurrentCount;
\r
1148 FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
\r
1149 uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
\r
1152 if( xTXDescriptorSemaphore != NULL )
\r
1154 static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;
\r
1156 uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );
\r
1157 if( uxLowestSemCount > uxCurrentCount )
\r
1159 uxLowestSemCount = uxCurrentCount;
\r
1160 FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );
\r
1165 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
\r
1167 uxCurrentCount = uxGetMinimumIPQueueSpace();
\r
1168 if( uxLastMinQueueSpace != uxCurrentCount )
\r
1170 /* The logging produced below may be helpful
\r
1171 while tuning +TCP: see how many buffers are in use. */
\r
1172 uxLastMinQueueSpace = uxCurrentCount;
\r
1173 FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
\r
1176 #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
\r
1178 if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
\r
1180 /* No events to process now, wait for the next. */
\r
1181 ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
\r
1184 if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
\r
1186 ulISREvents &= ~EMAC_IF_RX_EVENT;
\r
1188 xResult = prvNetworkInterfaceInput();
\r
1191 while( prvNetworkInterfaceInput() > 0 )
\r
1197 if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
\r
1199 /* Code to release TX buffers if zero-copy is used. */
\r
1200 ulISREvents &= ~EMAC_IF_TX_EVENT;
\r
1201 /* Check if DMA packets have been delivered. */
\r
1202 vClearTXBuffers();
\r
1205 if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
\r
1207 /* Future extension: logging about errors that occurred. */
\r
1208 ulISREvents &= ~EMAC_IF_ERR_EVENT;
\r
1210 if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
\r
1212 /* Something has changed to a Link Status, need re-check. */
\r
1213 prvEthernetUpdateConfig( pdFALSE );
\r
1217 /*-----------------------------------------------------------*/
\r
1219 void ETH_IRQHandler( void )
\r
1221 HAL_ETH_IRQHandler( &xETH );
\r