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
81 #include "phyHandling.h"
\r
85 #include "stm32f7xx_hal.h"
\r
87 #include "stm32f4xx_hal.h"
\r
90 /* Interrupt events to process. Currently only the Rx event is processed
\r
91 although code for other events is included to allow for possible future
\r
93 #define EMAC_IF_RX_EVENT 1UL
\r
94 #define EMAC_IF_TX_EVENT 2UL
\r
95 #define EMAC_IF_ERR_EVENT 4UL
\r
96 #define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )
\r
98 #define ETH_DMA_ALL_INTS \
\r
99 ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | ETH_DMA_IT_ER | \
\r
100 ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \
\r
101 ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )
\r
105 #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
108 * Most users will want a PHY that negotiates about
\r
109 * the connection properties: speed, dmix and duplex.
\r
110 * On some rare cases, you want to select what is being
\r
111 * advertised, properties like MDIX and duplex.
\r
114 #if !defined( ipconfigETHERNET_AN_ENABLE )
\r
115 /* Enable auto-negotiation */
\r
116 #define ipconfigETHERNET_AN_ENABLE 1
\r
119 #if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE )
\r
120 #define ipconfigETHERNET_AUTO_CROSS_ENABLE 1
\r
123 #if( ipconfigETHERNET_AN_ENABLE == 0 )
\r
125 * The following three defines are only used in case there
\r
126 * is no auto-negotiation.
\r
128 #if !defined( ipconfigETHERNET_CROSSED_LINK )
\r
129 #define ipconfigETHERNET_CROSSED_LINK 1
\r
132 #if !defined( ipconfigETHERNET_USE_100MB )
\r
133 #define ipconfigETHERNET_USE_100MB 1
\r
136 #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX )
\r
137 #define ipconfigETHERNET_USE_FULL_DUPLEX 1
\r
139 #endif /* ipconfigETHERNET_AN_ENABLE == 0 */
\r
141 /* Default the size of the stack used by the EMAC deferred handler task to twice
\r
142 the size of the stack used by the idle task - but allow this to be overridden in
\r
143 FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
\r
144 #ifndef configEMAC_TASK_STACK_SIZE
\r
145 #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
\r
148 /* Two choices must be made: RMII versus MII,
\r
149 and the index of the PHY in use ( between 0 and 31 ). */
\r
150 #ifndef ipconfigUSE_RMII
\r
152 #define ipconfigUSE_RMII 1
\r
154 #define ipconfigUSE_RMII 0
\r
155 #endif /* STM32F7xx */
\r
156 #endif /* ipconfigUSE_RMII */
\r
160 /*-----------------------------------------------------------*/
\r
163 * A deferred interrupt handler task that processes
\r
165 static void prvEMACHandlerTask( void *pvParameters );
\r
168 * Force a negotiation with the Switch or Router and wait for LS.
\r
170 static void prvEthernetUpdateConfig( BaseType_t xForce );
\r
173 * See if there is a new packet and forward it to the IP-task.
\r
175 static BaseType_t prvNetworkInterfaceInput( void );
\r
177 #if( ipconfigUSE_LLMNR != 0 )
\r
179 * For LLMNR, an extra MAC-address must be configured to
\r
180 * be able to receive the multicast messages.
\r
182 static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr);
\r
186 * Check if a given packet should be accepted.
\r
188 static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer );
\r
191 * Initialise the TX descriptors.
\r
193 static void prvDMATxDescListInit( void );
\r
196 * Initialise the RX descriptors.
\r
198 static void prvDMARxDescListInit( void );
\r
200 /* After packets have been sent, the network
\r
201 buffers will be released. */
\r
202 static void vClearTXBuffers( void );
\r
204 /*-----------------------------------------------------------*/
\r
206 /* Bit map of outstanding ETH interrupt events for processing. Currently only
\r
207 the Rx interrupt is handled, although code is included for other events to
\r
208 enable future expansion. */
\r
209 static volatile uint32_t ulISREvents;
\r
211 #if( ipconfigUSE_LLMNR == 1 )
\r
212 static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
\r
215 static EthernetPhy_t xPhyObject;
\r
217 /* Ethernet handle. */
\r
218 static ETH_HandleTypeDef xETH;
\r
220 /* xTXDescriptorSemaphore is a counting semaphore with
\r
221 a maximum count of ETH_TXBUFNB, which is the number of
\r
222 DMA TX descriptors. */
\r
223 static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
\r
226 * Note: it is adviced to define both
\r
228 * #define ipconfigZERO_COPY_RX_DRIVER 1
\r
229 * #define ipconfigZERO_COPY_TX_DRIVER 1
\r
231 * The method using memcpy is slower and probaly uses more RAM memory.
\r
232 * The possibility is left in the code just for comparison.
\r
234 * It is adviced to define ETH_TXBUFNB at least 4. Note that no
\r
235 * TX buffers are allocated in a zero-copy driver.
\r
237 /* MAC buffers: ---------------------------------------------------------*/
\r
239 /* Put the DMA descriptors in '.first_data'.
\r
240 This is important for STM32F7, which has an L1 data cache.
\r
241 The first 64KB of the SRAM is not cached. */
\r
243 /* Ethernet Rx MA Descriptor */
\r
244 __attribute__ ((aligned (32)))
\r
245 __attribute__ ((section(".first_data")))
\r
246 ETH_DMADescTypeDef DMARxDscrTab[ ETH_RXBUFNB ];
\r
248 #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
\r
249 /* Ethernet Receive Buffer */
\r
250 __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END;
\r
253 /* Ethernet Tx DMA Descriptor */
\r
254 __attribute__ ((aligned (32)))
\r
255 __attribute__ ((section(".first_data")))
\r
256 ETH_DMADescTypeDef DMATxDscrTab[ ETH_TXBUFNB ];
\r
258 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
\r
259 /* Ethernet Transmit Buffer */
\r
260 __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END;
\r
263 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
264 /* DMATxDescToClear points to the next TX DMA descriptor
\r
265 that must be cleared by vClearTXBuffers(). */
\r
266 static __IO ETH_DMADescTypeDef *DMATxDescToClear;
\r
269 /* ucMACAddress as it appears in main.c */
\r
270 extern const uint8_t ucMACAddress[ 6 ];
\r
272 /* Holds the handle of the task used as a deferred interrupt processor. The
\r
273 handle is used so direct notifications can be sent to the task for all EMAC/DMA
\r
274 related interrupts. */
\r
275 static TaskHandle_t xEMACTaskHandle = NULL;
\r
277 /* For local use only: describe the PHY's properties: */
\r
278 const PhyProperties_t xPHYProperties =
\r
280 #if( ipconfigETHERNET_AN_ENABLE != 0 )
\r
281 .ucSpeed = PHY_SPEED_AUTO,
\r
282 .ucDuplex = PHY_DUPLEX_AUTO,
\r
284 #if( ipconfigETHERNET_USE_100MB != 0 )
\r
285 .ucSpeed = PHY_SPEED_100,
\r
287 .ucSpeed = PHY_SPEED_10,
\r
290 #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )
\r
291 .duplex = PHY_DUPLEX_FULL,
\r
293 .duplex = PHY_DUPLEX_HALF,
\r
297 #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )
\r
298 .ucMDI_X = PHY_MDIX_AUTO,
\r
299 #elif( ipconfigETHERNET_CROSSED_LINK != 0 )
\r
300 .ucMDI_X = PHY_MDIX_CROSSED,
\r
302 .ucMDI_X = PHY_MDIX_DIRECT,
\r
306 /*-----------------------------------------------------------*/
\r
308 void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )
\r
310 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
312 /* Ethernet RX-Complete callback function, elsewhere declared as weak. */
\r
313 ulISREvents |= EMAC_IF_RX_EVENT;
\r
314 /* Wakeup the prvEMACHandlerTask. */
\r
315 if( xEMACTaskHandle != NULL )
\r
317 vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
\r
318 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
\r
321 /*-----------------------------------------------------------*/
\r
323 void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )
\r
325 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
327 /* This call-back is only useful in case packets are being sent
\r
328 zero-copy. Once they're sent, the buffers will be released
\r
329 by the function vClearTXBuffers(). */
\r
330 ulISREvents |= EMAC_IF_TX_EVENT;
\r
331 /* Wakeup the prvEMACHandlerTask. */
\r
332 if( xEMACTaskHandle != NULL )
\r
334 vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
\r
335 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
\r
339 /*-----------------------------------------------------------*/
\r
341 static void vClearTXBuffers()
\r
343 __IO ETH_DMADescTypeDef *txLastDescriptor = xETH.TxDesc;
\r
344 size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
\r
345 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
346 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
347 uint8_t *ucPayLoad;
\r
350 /* This function is called after a TX-completion interrupt.
\r
351 It will release each Network Buffer used in xNetworkInterfaceOutput().
\r
352 'uxCount' represents the number of descriptors given to DMA for transmission.
\r
353 After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */
\r
354 while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )
\r
356 if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )
\r
360 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
362 ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;
\r
364 if( ucPayLoad != NULL )
\r
366 pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );
\r
367 if( pxNetworkBuffer != NULL )
\r
369 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;
\r
371 DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;
\r
374 #endif /* ipconfigZERO_COPY_TX_DRIVER */
\r
376 DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );
\r
379 /* Tell the counting semaphore that one more TX descriptor is available. */
\r
380 xSemaphoreGive( xTXDescriptorSemaphore );
\r
383 /*-----------------------------------------------------------*/
\r
385 BaseType_t xNetworkInterfaceInitialise( void )
\r
387 HAL_StatusTypeDef hal_eth_init_status;
\r
388 BaseType_t xResult;
\r
390 if( xEMACTaskHandle == NULL )
\r
392 if( xTXDescriptorSemaphore == NULL )
\r
394 xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );
\r
395 configASSERT( xTXDescriptorSemaphore );
\r
398 /* Initialise ETH */
\r
400 xETH.Instance = ETH;
\r
401 xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
\r
402 xETH.Init.Speed = ETH_SPEED_100M;
\r
403 xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
\r
404 /* Value of PhyAddress doesn't matter, will be probed for. */
\r
405 xETH.Init.PhyAddress = 0;
\r
407 xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;
\r
408 xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;
\r
410 /* using the ETH_CHECKSUM_BY_HARDWARE option:
\r
411 both the IP and the protocol checksums will be calculated
\r
412 by the peripheral. */
\r
413 xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
\r
415 #if( ipconfigUSE_RMII != 0 )
\r
417 xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
\r
421 xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
\r
423 #endif /* ipconfigUSE_RMII */
\r
425 hal_eth_init_status = HAL_ETH_Init( &xETH );
\r
427 /* Only for inspection by debugger. */
\r
428 ( void ) hal_eth_init_status;
\r
430 /* Set the TxDesc and RxDesc pointers. */
\r
431 xETH.TxDesc = DMATxDscrTab;
\r
432 xETH.RxDesc = DMARxDscrTab;
\r
434 /* Make sure that all unused fields are cleared. */
\r
435 memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );
\r
436 memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );
\r
438 /* Initialize Tx Descriptors list: Chain Mode */
\r
439 DMATxDescToClear = DMATxDscrTab;
\r
441 /* Initialise TX-descriptors. */
\r
442 prvDMATxDescListInit();
\r
444 /* Initialise RX-descriptors. */
\r
445 prvDMARxDescListInit();
\r
447 #if( ipconfigUSE_LLMNR != 0 )
\r
449 /* Program the LLMNR address at index 1. */
\r
450 prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );
\r
454 /* Force a negotiation with the Switch or Router and wait for LS. */
\r
455 prvEthernetUpdateConfig( pdTRUE );
\r
457 /* The deferred interrupt handler task is created at the highest
\r
458 possible priority to ensure the interrupt handler can return directly
\r
459 to it. The task's handle is stored in xEMACTaskHandle so interrupts can
\r
460 notify the task when there is something to process. */
\r
461 xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
\r
462 } /* if( xEMACTaskHandle == NULL ) */
\r
464 if( xPhyObject.ulLinkStatusMask != 0 )
\r
466 xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;
\r
468 FreeRTOS_printf( ( "Link Status is high\n" ) ) ;
\r
472 /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
\r
473 and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */
\r
475 FreeRTOS_printf( ( "Link Status still low\n" ) ) ;
\r
477 /* When returning non-zero, the stack will become active and
\r
478 start DHCP (in configured) */
\r
481 /*-----------------------------------------------------------*/
\r
483 static void prvDMATxDescListInit()
\r
485 ETH_DMADescTypeDef *pxDMADescriptor;
\r
488 /* Get the pointer on the first member of the descriptor list */
\r
489 pxDMADescriptor = DMATxDscrTab;
\r
491 /* Fill each DMA descriptor with the right values */
\r
492 for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ )
\r
494 /* Set Second Address Chained bit */
\r
495 pxDMADescriptor->Status = ETH_DMATXDESC_TCH;
\r
497 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
\r
499 /* Set Buffer1 address pointer */
\r
500 pxDMADescriptor->Buffer1Addr = ( uint32_t )( Tx_Buff[ xIndex ] );
\r
504 if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE )
\r
506 /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */
\r
507 pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;
\r
510 /* Initialize the next descriptor with the Next Descriptor Polling Enable */
\r
511 if( xIndex < ETH_TXBUFNB - 1 )
\r
513 /* Set next descriptor address register with next descriptor base address */
\r
514 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 );
\r
518 /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
\r
519 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab;
\r
523 /* Set Transmit Descriptor List Address Register */
\r
524 xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab;
\r
526 /*-----------------------------------------------------------*/
\r
528 static void prvDMARxDescListInit()
\r
530 ETH_DMADescTypeDef *pxDMADescriptor;
\r
536 /* Get the pointer on the first member of the descriptor list */
\r
537 pxDMADescriptor = DMARxDscrTab;
\r
539 /* Fill each DMA descriptor with the right values */
\r
540 for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ )
\r
543 /* Set Buffer1 size and Second Address Chained bit */
\r
544 pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;
\r
546 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
548 /* Set Buffer1 address pointer */
\r
549 NetworkBufferDescriptor_t *pxBuffer;
\r
551 pxBuffer = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, 100ul );
\r
552 /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB'
\r
553 Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */
\r
554 configASSERT( pxBuffer != NULL );
\r
555 if( pxBuffer != NULL )
\r
557 pxDMADescriptor->Buffer1Addr = (uint32_t)pxBuffer->pucEthernetBuffer;
\r
558 pxDMADescriptor->Status = ETH_DMARXDESC_OWN;
\r
563 /* Set Buffer1 address pointer */
\r
564 pxDMADescriptor->Buffer1Addr = ( uint32_t )( Rx_Buff[ xIndex ] );
\r
565 /* Set Own bit of the Rx descriptor Status */
\r
566 pxDMADescriptor->Status = ETH_DMARXDESC_OWN;
\r
570 /* Initialize the next descriptor with the Next Descriptor Polling Enable */
\r
571 if( xIndex < ETH_RXBUFNB - 1 )
\r
573 /* Set next descriptor address register with next descriptor base address */
\r
574 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t )( pxDMADescriptor + 1 );
\r
578 /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
\r
579 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab;
\r
583 /* Set Receive Descriptor List Address Register */
\r
584 xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab;
\r
586 /*-----------------------------------------------------------*/
\r
588 static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr)
\r
590 uint32_t ulTempReg;
\r
592 /* Calculate the selected MAC address high register. */
\r
593 ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];
\r
595 /* Load the selected MAC address high register. */
\r
596 ( *(__IO uint32_t *)( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg;
\r
598 /* Calculate the selected MAC address low register. */
\r
599 ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ];
\r
601 /* Load the selected MAC address low register */
\r
602 ( *(__IO uint32_t *) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg;
\r
604 /*-----------------------------------------------------------*/
\r
606 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
\r
608 BaseType_t xReturn = pdFAIL;
\r
609 uint32_t ulTransmitSize = 0;
\r
610 __IO ETH_DMADescTypeDef *pxDmaTxDesc;
\r
611 /* Do not wait too long for a free TX DMA buffer. */
\r
612 const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
\r
614 #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
\r
616 ProtocolPacket_t *pxPacket;
\r
618 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
620 configASSERT( bReleaseAfterSend != 0 );
\r
622 #endif /* ipconfigZERO_COPY_RX_DRIVER */
\r
624 /* If the peripheral must calculate the checksum, it wants
\r
625 the protocol checksum to have a value of zero. */
\r
626 pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );
\r
628 if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )
\r
630 pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;
\r
635 /* Open a do {} while ( 0 ) loop to be able to call break. */
\r
638 if( xPhyObject.ulLinkStatusMask != 0 )
\r
640 if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
\r
642 /* Time-out waiting for a free TX descriptor. */
\r
646 /* This function does the actual transmission of the packet. The packet is
\r
647 contained in 'pxDescriptor' that is passed to the function. */
\r
648 pxDmaTxDesc = xETH.TxDesc;
\r
650 /* Is this buffer available? */
\r
651 configASSERT ( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 );
\r
654 /* Is this buffer available? */
\r
655 /* Get bytes in current buffer. */
\r
656 ulTransmitSize = pxDescriptor->xDataLength;
\r
658 if( ulTransmitSize > ETH_TX_BUF_SIZE )
\r
660 ulTransmitSize = ETH_TX_BUF_SIZE;
\r
663 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
\r
665 /* Copy the bytes. */
\r
666 memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );
\r
670 /* Move the buffer. */
\r
671 pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;
\r
672 /* The Network Buffer has been passed to DMA, no need to release it. */
\r
673 bReleaseAfterSend = pdFALSE_UNSIGNED;
\r
675 #endif /* ipconfigZERO_COPY_TX_DRIVER */
\r
677 /* Ask to set the IPv4 checksum.
\r
678 Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */
\r
679 pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;
\r
681 /* Prepare transmit descriptors to give to DMA. */
\r
683 /* Set LAST and FIRST segment */
\r
684 pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;
\r
685 /* Set frame size */
\r
686 pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );
\r
687 /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
\r
688 pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;
\r
690 /* Point to next descriptor */
\r
691 xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );
\r
692 /* Ensure completion of memory access */
\r
694 /* Resume DMA transmission*/
\r
695 xETH.Instance->DMATPDR = 0;
\r
696 iptraceNETWORK_INTERFACE_TRANSMIT();
\r
702 /* The PHY has no Link Status, packet shall be dropped. */
\r
705 /* The buffer has been sent so can be released. */
\r
706 if( bReleaseAfterSend != pdFALSE )
\r
708 vReleaseNetworkBufferAndDescriptor( pxDescriptor );
\r
713 /*-----------------------------------------------------------*/
\r
715 static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer )
\r
717 const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
\r
719 switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType )
\r
721 case ipARP_FRAME_TYPE:
\r
722 /* Check it later. */
\r
724 case ipIPv4_FRAME_TYPE:
\r
725 /* Check it here. */
\r
728 /* Refuse the packet. */
\r
732 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
734 const IPHeader_t *pxIPHeader = &(pxProtPacket->xTCPPacket.xIPHeader);
\r
735 uint32_t ulDestinationIPAddress;
\r
737 /* Ensure that the incoming packet is not fragmented (only outgoing packets
\r
738 * can be fragmented) as these are the only handled IP frames currently. */
\r
739 if( ( pxIPHeader->usFragmentOffset & FreeRTOS_ntohs( ipFRAGMENT_OFFSET_BIT_MASK ) ) != 0U )
\r
743 /* HT: Might want to make the following configurable because
\r
744 * most IP messages have a standard length of 20 bytes */
\r
746 /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes
\r
747 * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */
\r
748 if( pxIPHeader->ucVersionHeaderLength < 0x45 || pxIPHeader->ucVersionHeaderLength > 0x4F )
\r
753 ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;
\r
754 /* Is the packet for this node? */
\r
755 if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&
\r
756 /* Is it a broadcast address x.x.x.255 ? */
\r
757 ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) &&
\r
758 #if( ipconfigUSE_LLMNR == 1 )
\r
759 ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&
\r
761 ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) {
\r
762 FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) );
\r
766 if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )
\r
768 uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;
\r
770 if( ( xPortHasUDPSocket( port ) == pdFALSE )
\r
771 #if ipconfigUSE_LLMNR == 1
\r
772 && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )
\r
774 #if ipconfigUSE_NBNS == 1
\r
775 && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )
\r
777 #if ipconfigUSE_DNS == 1
\r
778 && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )
\r
781 /* Drop this packet, not for this device. */
\r
786 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
789 /*-----------------------------------------------------------*/
\r
791 static BaseType_t prvNetworkInterfaceInput( void )
\r
793 NetworkBufferDescriptor_t *pxCurDescriptor;
\r
794 NetworkBufferDescriptor_t *pxNewDescriptor = NULL;
\r
795 BaseType_t xReceivedLength, xAccepted;
\r
796 __IO ETH_DMADescTypeDef *pxDMARxDescriptor;
\r
797 xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
\r
798 const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
\r
799 uint8_t *pucBuffer;
\r
801 pxDMARxDescriptor = xETH.RxDesc;
\r
803 if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )
\r
805 /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
\r
806 xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;
\r
808 pucBuffer = (uint8_t *) pxDMARxDescriptor->Buffer1Addr;
\r
810 /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */
\r
811 /* Chained Mode */
\r
812 /* Selects the next DMA Rx descriptor list for next buffer to read */
\r
813 xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;
\r
817 xReceivedLength = 0;
\r
820 /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */
\r
822 /* get received frame */
\r
823 if( xReceivedLength > 0ul )
\r
825 /* In order to make the code easier and faster, only packets in a single buffer
\r
826 will be accepted. This can be done by making the buffers large enough to
\r
827 hold a complete Ethernet packet (1536 bytes).
\r
828 Therefore, two sanity checks: */
\r
829 configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );
\r
831 if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )
\r
833 /* Not an Ethernet frame-type or a checmsum error. */
\r
834 xAccepted = pdFALSE;
\r
838 /* See if this packet must be handled. */
\r
839 xAccepted = xMayAcceptPacket( pucBuffer );
\r
842 if( xAccepted != pdFALSE )
\r
844 /* The packet wil be accepted, but check first if a new Network Buffer can
\r
845 be obtained. If not, the packet will still be dropped. */
\r
846 pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, xDescriptorWaitTime );
\r
848 if( pxNewDescriptor == NULL )
\r
850 /* A new descriptor can not be allocated now. This packet will be dropped. */
\r
851 xAccepted = pdFALSE;
\r
854 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
856 /* Find out which Network Buffer was originally passed to the descriptor. */
\r
857 pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
\r
858 configASSERT( pxCurDescriptor != NULL );
\r
862 /* In this mode, the two descriptors are the same. */
\r
863 pxCurDescriptor = pxNewDescriptor;
\r
864 if( pxNewDescriptor != NULL )
\r
866 /* The packet is acepted and a new Network Buffer was created,
\r
867 copy data to the Network Bufffer. */
\r
868 memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength );
\r
873 if( xAccepted != pdFALSE )
\r
875 pxCurDescriptor->xDataLength = xReceivedLength;
\r
876 xRxEvent.pvData = ( void * ) pxCurDescriptor;
\r
878 /* Pass the data to the TCP/IP task for processing. */
\r
879 if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )
\r
881 /* Could not send the descriptor into the TCP/IP stack, it
\r
882 must be released. */
\r
883 vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );
\r
884 iptraceETHERNET_RX_EVENT_LOST();
\r
888 iptraceNETWORK_INTERFACE_RECEIVE();
\r
892 /* Release descriptors to DMA */
\r
893 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
895 /* Set Buffer1 address pointer */
\r
896 if( pxNewDescriptor != NULL )
\r
898 pxDMARxDescriptor->Buffer1Addr = (uint32_t)pxNewDescriptor->pucEthernetBuffer;
\r
902 /* The packet was dropped and the same Network
\r
903 Buffer will be used to receive a new packet. */
\r
906 #endif /* ipconfigZERO_COPY_RX_DRIVER */
\r
908 /* Set Buffer1 size and Second Address Chained bit */
\r
909 pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;
\r
910 pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;
\r
912 /* Ensure completion of memory access */
\r
914 /* When Rx Buffer unavailable flag is set clear it and resume
\r
916 if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )
\r
918 /* Clear RBUS ETHERNET DMA flag. */
\r
919 xETH.Instance->DMASR = ETH_DMASR_RBUS;
\r
921 /* Resume DMA reception. */
\r
922 xETH.Instance->DMARPDR = 0;
\r
926 return ( xReceivedLength > 0 );
\r
928 /*-----------------------------------------------------------*/
\r
931 BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )
\r
933 uint16_t usPrevAddress = xETH.Init.PhyAddress;
\r
934 BaseType_t xResult;
\r
935 HAL_StatusTypeDef xHALResult;
\r
937 xETH.Init.PhyAddress = xAddress;
\r
938 xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t )xRegister, pulValue );
\r
939 xETH.Init.PhyAddress = usPrevAddress;
\r
941 if( xHALResult == HAL_OK )
\r
951 /*-----------------------------------------------------------*/
\r
953 BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )
\r
955 uint16_t usPrevAddress = xETH.Init.PhyAddress;
\r
956 BaseType_t xResult;
\r
957 HAL_StatusTypeDef xHALResult;
\r
959 xETH.Init.PhyAddress = xAddress;
\r
960 xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t )xRegister, ulValue );
\r
961 xETH.Init.PhyAddress = usPrevAddress;
\r
963 if( xHALResult == HAL_OK )
\r
973 /*-----------------------------------------------------------*/
\r
977 BaseType_t xPhyCount;
\r
978 BaseType_t xPhyIndex;
\r
980 vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );
\r
981 xPhyCount = xPhyDiscover( &xPhyObject );
\r
982 FreeRTOS_printf( ( "PHY count %ld\n", xPhyCount ) );
\r
983 for( xPhyIndex = 0; xPhyIndex < xPhyCount; xPhyIndex++ )
\r
985 FreeRTOS_printf( ( "PHY[%d] at address %d ( 0x%08X )\n",
\r
987 xPhyObject.ucPhyIndexes[ xPhyIndex ],
\r
988 xPhyObject.ulPhyIDs[ xPhyIndex ] ) );
\r
994 void vMACBProbePhy( void )
\r
996 vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );
\r
997 xPhyDiscover( &xPhyObject );
\r
998 xPhyConfigure( &xPhyObject, &xPHYProperties );
\r
1000 /*-----------------------------------------------------------*/
\r
1002 static void prvEthernetUpdateConfig( BaseType_t xForce )
\r
1004 FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n",
\r
1005 xPhyObject.ulLinkStatusMask,
\r
1006 ( int )xForce ) );
\r
1008 if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )
\r
1010 /* Restart the auto-negotiation. */
\r
1011 if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )
\r
1013 xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );
\r
1015 /* Configure the MAC with the Duplex Mode fixed by the
\r
1016 auto-negotiation process. */
\r
1017 if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )
\r
1019 xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
\r
1023 xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
\r
1026 /* Configure the MAC with the speed fixed by the
\r
1027 auto-negotiation process. */
\r
1028 if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )
\r
1030 xETH.Init.Speed = ETH_SPEED_10M;
\r
1034 xETH.Init.Speed = ETH_SPEED_100M;
\r
1037 else /* AutoNegotiation Disable */
\r
1039 /* Check parameters */
\r
1040 assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );
\r
1041 assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );
\r
1043 if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX )
\r
1045 xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;
\r
1049 xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;
\r
1052 if( xETH.Init.Speed == ETH_SPEED_10M )
\r
1054 xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;
\r
1058 xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;
\r
1061 xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;
\r
1063 /* Use predefined (fixed) configuration. */
\r
1064 xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );
\r
1067 /* ETHERNET MAC Re-Configuration */
\r
1068 HAL_ETH_ConfigMAC( &xETH, (ETH_MACInitTypeDef *) NULL);
\r
1070 /* Restart MAC interface */
\r
1071 HAL_ETH_Start( &xETH);
\r
1075 /* Stop MAC interface */
\r
1076 HAL_ETH_Stop( &xETH );
\r
1079 /*-----------------------------------------------------------*/
\r
1081 BaseType_t xGetPhyLinkStatus( void )
\r
1083 BaseType_t xReturn;
\r
1085 if( xPhyObject.ulLinkStatusMask != 0 )
\r
1096 /*-----------------------------------------------------------*/
\r
1098 /* Uncomment this in case BufferAllocation_1.c is used. */
\r
1101 #define niBUFFER_1_PACKET_SIZE 1536
\r
1103 static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
\r
1105 void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
\r
1108 uint8_t *ucRAMBuffer = ucNetworkPackets;
\r
1111 for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
\r
1113 pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
\r
1114 *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
\r
1115 ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
\r
1119 /*-----------------------------------------------------------*/
\r
1121 static void prvEMACHandlerTask( void *pvParameters )
\r
1123 UBaseType_t uxLastMinBufferCount = 0;
\r
1124 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
\r
1125 UBaseType_t uxLastMinQueueSpace = 0;
\r
1127 UBaseType_t uxCurrentCount;
\r
1128 BaseType_t xResult;
\r
1129 const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
\r
1131 /* Remove compiler warnings about unused parameters. */
\r
1132 ( void ) pvParameters;
\r
1137 uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
\r
1138 if( uxLastMinBufferCount != uxCurrentCount )
\r
1140 /* The logging produced below may be helpful
\r
1141 while tuning +TCP: see how many buffers are in use. */
\r
1142 uxLastMinBufferCount = uxCurrentCount;
\r
1143 FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
\r
1144 uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
\r
1147 if( xTXDescriptorSemaphore != NULL )
\r
1149 static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;
\r
1151 uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );
\r
1152 if( uxLowestSemCount > uxCurrentCount )
\r
1154 uxLowestSemCount = uxCurrentCount;
\r
1155 FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );
\r
1160 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
\r
1162 uxCurrentCount = uxGetMinimumIPQueueSpace();
\r
1163 if( uxLastMinQueueSpace != uxCurrentCount )
\r
1165 /* The logging produced below may be helpful
\r
1166 while tuning +TCP: see how many buffers are in use. */
\r
1167 uxLastMinQueueSpace = uxCurrentCount;
\r
1168 FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
\r
1171 #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
\r
1173 if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
\r
1175 /* No events to process now, wait for the next. */
\r
1176 ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
\r
1179 if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
\r
1181 ulISREvents &= ~EMAC_IF_RX_EVENT;
\r
1183 xResult = prvNetworkInterfaceInput();
\r
1186 while( prvNetworkInterfaceInput() > 0 )
\r
1192 if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
\r
1194 /* Code to release TX buffers if zero-copy is used. */
\r
1195 ulISREvents &= ~EMAC_IF_TX_EVENT;
\r
1196 /* Check if DMA packets have been delivered. */
\r
1197 vClearTXBuffers();
\r
1200 if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
\r
1202 /* Future extension: logging about errors that occurred. */
\r
1203 ulISREvents &= ~EMAC_IF_ERR_EVENT;
\r
1205 if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
\r
1207 /* Something has changed to a Link Status, need re-check. */
\r
1208 prvEthernetUpdateConfig( pdFALSE );
\r
1212 /*-----------------------------------------------------------*/
\r
1214 void ETH_IRQHandler( void )
\r
1216 HAL_ETH_IRQHandler( &xETH );
\r