2 * Some constants, hardware definitions and comments taken from ST's HAL driver
\r
3 * library, COPYRIGHT(c) 2015 STMicroelectronics.
\r
7 * FreeRTOS+TCP V2.0.11
\r
8 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
10 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
11 * this software and associated documentation files (the "Software"), to deal in
\r
12 * the Software without restriction, including without limitation the rights to
\r
13 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
14 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
15 * subject to the following conditions:
\r
17 * The above copyright notice and this permission notice shall be included in all
\r
18 * copies or substantial portions of the Software.
\r
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
23 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
24 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
27 * http://aws.amazon.com/freertos
\r
28 * http://www.FreeRTOS.org
\r
31 /* Standard includes. */
\r
36 /* FreeRTOS includes. */
\r
37 #include "FreeRTOS.h"
\r
42 /* FreeRTOS+TCP includes. */
\r
43 #include "FreeRTOS_IP.h"
\r
44 #include "FreeRTOS_Sockets.h"
\r
45 #include "FreeRTOS_IP_Private.h"
\r
46 #include "FreeRTOS_DNS.h"
\r
47 #include "NetworkBufferManagement.h"
\r
48 #include "NetworkInterface.h"
\r
49 #include "phyHandling.h"
\r
51 #define __STM32_HAL_LEGACY 1
\r
54 #if defined( STM32F7xx )
\r
55 #include "stm32f7xx_hal.h"
\r
56 #elif defined( STM32F4xx )
\r
57 #include "stm32f4xx_hal.h"
\r
58 #elif defined( STM32F2xx )
\r
59 #include "stm32f2xx_hal.h"
\r
64 #include "stm32fxx_hal_eth.h"
\r
66 /* Interrupt events to process. Currently only the Rx event is processed
\r
67 although code for other events is included to allow for possible future
\r
69 #define EMAC_IF_RX_EVENT 1UL
\r
70 #define EMAC_IF_TX_EVENT 2UL
\r
71 #define EMAC_IF_ERR_EVENT 4UL
\r
72 #define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )
\r
74 #define ETH_DMA_ALL_INTS \
\r
75 ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | ETH_DMA_IT_ER | \
\r
76 ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \
\r
77 ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )
\r
79 #ifndef niEMAC_HANDLER_TASK_PRIORITY
\r
80 #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1
\r
83 #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
86 * Most users will want a PHY that negotiates about
\r
87 * the connection properties: speed, dmix and duplex.
\r
88 * On some rare cases, you want to select what is being
\r
89 * advertised, properties like MDIX and duplex.
\r
92 #if !defined( ipconfigETHERNET_AN_ENABLE )
\r
93 /* Enable auto-negotiation */
\r
94 #define ipconfigETHERNET_AN_ENABLE 1
\r
97 #if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE )
\r
98 #define ipconfigETHERNET_AUTO_CROSS_ENABLE 1
\r
101 #if( ipconfigETHERNET_AN_ENABLE == 0 )
\r
103 * The following three defines are only used in case there
\r
104 * is no auto-negotiation.
\r
106 #if !defined( ipconfigETHERNET_CROSSED_LINK )
\r
107 #define ipconfigETHERNET_CROSSED_LINK 1
\r
110 #if !defined( ipconfigETHERNET_USE_100MB )
\r
111 #define ipconfigETHERNET_USE_100MB 1
\r
114 #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX )
\r
115 #define ipconfigETHERNET_USE_FULL_DUPLEX 1
\r
117 #endif /* ipconfigETHERNET_AN_ENABLE == 0 */
\r
119 /* Default the size of the stack used by the EMAC deferred handler task to twice
\r
120 the size of the stack used by the idle task - but allow this to be overridden in
\r
121 FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
\r
122 #ifndef configEMAC_TASK_STACK_SIZE
\r
123 #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
\r
126 /* Two choices must be made: RMII versus MII,
\r
127 and the index of the PHY in use ( between 0 and 31 ). */
\r
128 #ifndef ipconfigUSE_RMII
\r
130 #define ipconfigUSE_RMII 1
\r
132 #define ipconfigUSE_RMII 0
\r
133 #endif /* STM32F7xx */
\r
134 #endif /* ipconfigUSE_RMII */
\r
136 #if( ipconfigUSE_RMII != 0 )
\r
137 #warning Using RMII, make sure if this is correct
\r
139 #warning Using MII, make sure if this is correct
\r
142 /*-----------------------------------------------------------*/
\r
145 * A deferred interrupt handler task that processes
\r
147 static void prvEMACHandlerTask( void *pvParameters );
\r
150 * Force a negotiation with the Switch or Router and wait for LS.
\r
152 static void prvEthernetUpdateConfig( BaseType_t xForce );
\r
155 * See if there is a new packet and forward it to the IP-task.
\r
157 static BaseType_t prvNetworkInterfaceInput( void );
\r
159 #if( ipconfigUSE_LLMNR != 0 )
\r
161 * For LLMNR, an extra MAC-address must be configured to
\r
162 * be able to receive the multicast messages.
\r
164 static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr);
\r
168 * Check if a given packet should be accepted.
\r
170 static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer );
\r
173 * Initialise the TX descriptors.
\r
175 static void prvDMATxDescListInit( void );
\r
178 * Initialise the RX descriptors.
\r
180 static void prvDMARxDescListInit( void );
\r
182 /* After packets have been sent, the network
\r
183 buffers will be released. */
\r
184 static void vClearTXBuffers( void );
\r
186 /*-----------------------------------------------------------*/
\r
188 /* Bit map of outstanding ETH interrupt events for processing. Currently only
\r
189 the Rx interrupt is handled, although code is included for other events to
\r
190 enable future expansion. */
\r
191 static volatile uint32_t ulISREvents;
\r
193 #if( ipconfigUSE_LLMNR == 1 )
\r
194 static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
\r
197 static EthernetPhy_t xPhyObject;
\r
199 /* Ethernet handle. */
\r
200 static ETH_HandleTypeDef xETH;
\r
202 /* xTXDescriptorSemaphore is a counting semaphore with
\r
203 a maximum count of ETH_TXBUFNB, which is the number of
\r
204 DMA TX descriptors. */
\r
205 static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
\r
208 * Note: it is adviced to define both
\r
210 * #define ipconfigZERO_COPY_RX_DRIVER 1
\r
211 * #define ipconfigZERO_COPY_TX_DRIVER 1
\r
213 * The method using memcpy is slower and probaly uses more RAM memory.
\r
214 * The possibility is left in the code just for comparison.
\r
216 * It is adviced to define ETH_TXBUFNB at least 4. Note that no
\r
217 * TX buffers are allocated in a zero-copy driver.
\r
219 /* MAC buffers: ---------------------------------------------------------*/
\r
221 /* Put the DMA descriptors in '.first_data'.
\r
222 This is important for STM32F7, which has an L1 data cache.
\r
223 The first 64KB of the SRAM is not cached. */
\r
225 /* Ethernet Rx MA Descriptor */
\r
226 __attribute__ ((aligned (32)))
\r
227 __attribute__ ((section(".first_data")))
\r
228 ETH_DMADescTypeDef DMARxDscrTab[ ETH_RXBUFNB ];
\r
230 #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
\r
231 /* Ethernet Receive Buffer */
\r
232 __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END;
\r
235 /* Ethernet Tx DMA Descriptor */
\r
236 __attribute__ ((aligned (32)))
\r
237 __attribute__ ((section(".first_data")))
\r
238 ETH_DMADescTypeDef DMATxDscrTab[ ETH_TXBUFNB ];
\r
240 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
\r
241 /* Ethernet Transmit Buffer */
\r
242 __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END;
\r
245 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
246 /* DMATxDescToClear points to the next TX DMA descriptor
\r
247 that must be cleared by vClearTXBuffers(). */
\r
248 static __IO ETH_DMADescTypeDef *DMATxDescToClear;
\r
251 /* Holds the handle of the task used as a deferred interrupt processor. The
\r
252 handle is used so direct notifications can be sent to the task for all EMAC/DMA
\r
253 related interrupts. */
\r
254 static TaskHandle_t xEMACTaskHandle = NULL;
\r
256 /* For local use only: describe the PHY's properties: */
\r
257 const PhyProperties_t xPHYProperties =
\r
259 #if( ipconfigETHERNET_AN_ENABLE != 0 )
\r
260 .ucSpeed = PHY_SPEED_AUTO,
\r
261 .ucDuplex = PHY_DUPLEX_AUTO,
\r
263 #if( ipconfigETHERNET_USE_100MB != 0 )
\r
264 .ucSpeed = PHY_SPEED_100,
\r
266 .ucSpeed = PHY_SPEED_10,
\r
269 #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )
\r
270 .duplex = PHY_DUPLEX_FULL,
\r
272 .duplex = PHY_DUPLEX_HALF,
\r
276 #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )
\r
277 .ucMDI_X = PHY_MDIX_AUTO,
\r
278 #elif( ipconfigETHERNET_CROSSED_LINK != 0 )
\r
279 .ucMDI_X = PHY_MDIX_CROSSED,
\r
281 .ucMDI_X = PHY_MDIX_DIRECT,
\r
285 /*-----------------------------------------------------------*/
\r
287 void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )
\r
289 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
291 /* Ethernet RX-Complete callback function, elsewhere declared as weak. */
\r
292 ulISREvents |= EMAC_IF_RX_EVENT;
\r
293 /* Wakeup the prvEMACHandlerTask. */
\r
294 if( xEMACTaskHandle != NULL )
\r
296 vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
\r
297 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
\r
300 /*-----------------------------------------------------------*/
\r
302 void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )
\r
304 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
306 /* This call-back is only useful in case packets are being sent
\r
307 zero-copy. Once they're sent, the buffers will be released
\r
308 by the function vClearTXBuffers(). */
\r
309 ulISREvents |= EMAC_IF_TX_EVENT;
\r
310 /* Wakeup the prvEMACHandlerTask. */
\r
311 if( xEMACTaskHandle != NULL )
\r
313 vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
\r
314 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
\r
318 /*-----------------------------------------------------------*/
\r
320 static void vClearTXBuffers()
\r
322 __IO ETH_DMADescTypeDef *txLastDescriptor = xETH.TxDesc;
\r
323 size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
\r
324 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
325 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
326 uint8_t *ucPayLoad;
\r
329 /* This function is called after a TX-completion interrupt.
\r
330 It will release each Network Buffer used in xNetworkInterfaceOutput().
\r
331 'uxCount' represents the number of descriptors given to DMA for transmission.
\r
332 After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */
\r
333 while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )
\r
335 if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )
\r
339 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
341 ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;
\r
343 if( ucPayLoad != NULL )
\r
345 pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );
\r
346 if( pxNetworkBuffer != NULL )
\r
348 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;
\r
350 DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;
\r
353 #endif /* ipconfigZERO_COPY_TX_DRIVER */
\r
355 DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );
\r
358 /* Tell the counting semaphore that one more TX descriptor is available. */
\r
359 xSemaphoreGive( xTXDescriptorSemaphore );
\r
362 /*-----------------------------------------------------------*/
\r
364 BaseType_t xNetworkInterfaceInitialise( void )
\r
366 HAL_StatusTypeDef hal_eth_init_status;
\r
367 BaseType_t xResult;
\r
369 if( xEMACTaskHandle == NULL )
\r
371 if( xTXDescriptorSemaphore == NULL )
\r
373 xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );
\r
374 configASSERT( xTXDescriptorSemaphore );
\r
377 /* Initialise ETH */
\r
379 xETH.Instance = ETH;
\r
380 xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
\r
381 xETH.Init.Speed = ETH_SPEED_100M;
\r
382 xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
\r
383 /* Value of PhyAddress doesn't matter, will be probed for. */
\r
384 xETH.Init.PhyAddress = 0;
\r
386 xETH.Init.MACAddr = ( uint8_t *)FreeRTOS_GetMACAddress();
\r
387 xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;
\r
389 /* using the ETH_CHECKSUM_BY_HARDWARE option:
\r
390 both the IP and the protocol checksums will be calculated
\r
391 by the peripheral. */
\r
392 xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
\r
394 #if( ipconfigUSE_RMII != 0 )
\r
396 xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
\r
400 xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
\r
402 #endif /* ipconfigUSE_RMII */
\r
404 hal_eth_init_status = HAL_ETH_Init( &xETH );
\r
406 /* Only for inspection by debugger. */
\r
407 ( void ) hal_eth_init_status;
\r
409 /* Set the TxDesc and RxDesc pointers. */
\r
410 xETH.TxDesc = DMATxDscrTab;
\r
411 xETH.RxDesc = DMARxDscrTab;
\r
413 /* Make sure that all unused fields are cleared. */
\r
414 memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );
\r
415 memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );
\r
417 /* Initialize Tx Descriptors list: Chain Mode */
\r
418 DMATxDescToClear = DMATxDscrTab;
\r
420 /* Initialise TX-descriptors. */
\r
421 prvDMATxDescListInit();
\r
423 /* Initialise RX-descriptors. */
\r
424 prvDMARxDescListInit();
\r
426 #if( ipconfigUSE_LLMNR != 0 )
\r
428 /* Program the LLMNR address at index 1. */
\r
429 prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );
\r
433 /* Force a negotiation with the Switch or Router and wait for LS. */
\r
434 prvEthernetUpdateConfig( pdTRUE );
\r
436 /* The deferred interrupt handler task is created at the highest
\r
437 possible priority to ensure the interrupt handler can return directly
\r
438 to it. The task's handle is stored in xEMACTaskHandle so interrupts can
\r
439 notify the task when there is something to process. */
\r
440 xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle );
\r
441 } /* if( xEMACTaskHandle == NULL ) */
\r
443 if( xPhyObject.ulLinkStatusMask != 0 )
\r
445 xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;
\r
447 FreeRTOS_printf( ( "Link Status is high\n" ) ) ;
\r
451 /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
\r
452 and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */
\r
454 FreeRTOS_printf( ( "Link Status still low\n" ) ) ;
\r
456 /* When returning non-zero, the stack will become active and
\r
457 start DHCP (in configured) */
\r
460 /*-----------------------------------------------------------*/
\r
462 static void prvDMATxDescListInit()
\r
464 ETH_DMADescTypeDef *pxDMADescriptor;
\r
467 /* Get the pointer on the first member of the descriptor list */
\r
468 pxDMADescriptor = DMATxDscrTab;
\r
470 /* Fill each DMA descriptor with the right values */
\r
471 for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ )
\r
473 /* Set Second Address Chained bit */
\r
474 pxDMADescriptor->Status = ETH_DMATXDESC_TCH;
\r
476 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
\r
478 /* Set Buffer1 address pointer */
\r
479 pxDMADescriptor->Buffer1Addr = ( uint32_t )( Tx_Buff[ xIndex ] );
\r
483 if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE )
\r
485 /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */
\r
486 pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;
\r
489 /* Initialize the next descriptor with the Next Descriptor Polling Enable */
\r
490 if( xIndex < ETH_TXBUFNB - 1 )
\r
492 /* Set next descriptor address register with next descriptor base address */
\r
493 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 );
\r
497 /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
\r
498 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab;
\r
502 /* Set Transmit Descriptor List Address Register */
\r
503 xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab;
\r
505 /*-----------------------------------------------------------*/
\r
507 static void prvDMARxDescListInit()
\r
509 ETH_DMADescTypeDef *pxDMADescriptor;
\r
515 /* Get the pointer on the first member of the descriptor list */
\r
516 pxDMADescriptor = DMARxDscrTab;
\r
518 /* Fill each DMA descriptor with the right values */
\r
519 for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ )
\r
522 /* Set Buffer1 size and Second Address Chained bit */
\r
523 pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;
\r
525 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
527 /* Set Buffer1 address pointer */
\r
528 NetworkBufferDescriptor_t *pxBuffer;
\r
530 pxBuffer = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, 100ul );
\r
531 /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB'
\r
532 Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */
\r
533 configASSERT( pxBuffer != NULL );
\r
534 if( pxBuffer != NULL )
\r
536 pxDMADescriptor->Buffer1Addr = (uint32_t)pxBuffer->pucEthernetBuffer;
\r
537 pxDMADescriptor->Status = ETH_DMARXDESC_OWN;
\r
542 /* Set Buffer1 address pointer */
\r
543 pxDMADescriptor->Buffer1Addr = ( uint32_t )( Rx_Buff[ xIndex ] );
\r
544 /* Set Own bit of the Rx descriptor Status */
\r
545 pxDMADescriptor->Status = ETH_DMARXDESC_OWN;
\r
549 /* Initialize the next descriptor with the Next Descriptor Polling Enable */
\r
550 if( xIndex < ETH_RXBUFNB - 1 )
\r
552 /* Set next descriptor address register with next descriptor base address */
\r
553 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t )( pxDMADescriptor + 1 );
\r
557 /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
\r
558 pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab;
\r
562 /* Set Receive Descriptor List Address Register */
\r
563 xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab;
\r
565 /*-----------------------------------------------------------*/
\r
567 static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr)
\r
569 uint32_t ulTempReg;
\r
571 /* Calculate the selected MAC address high register. */
\r
572 ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];
\r
574 /* Load the selected MAC address high register. */
\r
575 ( *(__IO uint32_t *)( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg;
\r
577 /* Calculate the selected MAC address low register. */
\r
578 ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ];
\r
580 /* Load the selected MAC address low register */
\r
581 ( *(__IO uint32_t *) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg;
\r
583 /*-----------------------------------------------------------*/
\r
585 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
\r
587 BaseType_t xReturn = pdFAIL;
\r
588 uint32_t ulTransmitSize = 0;
\r
589 __IO ETH_DMADescTypeDef *pxDmaTxDesc;
\r
590 /* Do not wait too long for a free TX DMA buffer. */
\r
591 const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
\r
593 /* Open a do {} while ( 0 ) loop to be able to call break. */
\r
596 if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )
\r
598 /* The packet has been sent back to the IP-task.
\r
599 The IP-task will further handle it.
\r
600 Do not release the descriptor. */
\r
601 bReleaseAfterSend = pdFALSE;
\r
604 #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
\r
606 ProtocolPacket_t *pxPacket;
\r
608 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
610 configASSERT( bReleaseAfterSend != 0 );
\r
612 #endif /* ipconfigZERO_COPY_RX_DRIVER */
\r
614 /* If the peripheral must calculate the checksum, it wants
\r
615 the protocol checksum to have a value of zero. */
\r
616 pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );
\r
618 if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )
\r
620 pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;
\r
623 #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */
\r
624 if( xPhyObject.ulLinkStatusMask != 0 )
\r
626 if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
\r
628 /* Time-out waiting for a free TX descriptor. */
\r
632 /* This function does the actual transmission of the packet. The packet is
\r
633 contained in 'pxDescriptor' that is passed to the function. */
\r
634 pxDmaTxDesc = xETH.TxDesc;
\r
636 /* Is this buffer available? */
\r
637 configASSERT ( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 );
\r
640 /* Is this buffer available? */
\r
641 /* Get bytes in current buffer. */
\r
642 ulTransmitSize = pxDescriptor->xDataLength;
\r
644 if( ulTransmitSize > ETH_TX_BUF_SIZE )
\r
646 ulTransmitSize = ETH_TX_BUF_SIZE;
\r
649 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
\r
651 /* Copy the bytes. */
\r
652 memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );
\r
656 /* Move the buffer. */
\r
657 pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;
\r
658 /* The Network Buffer has been passed to DMA, no need to release it. */
\r
659 bReleaseAfterSend = pdFALSE_UNSIGNED;
\r
661 #endif /* ipconfigZERO_COPY_TX_DRIVER */
\r
663 /* Ask to set the IPv4 checksum.
\r
664 Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */
\r
665 pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;
\r
667 /* Prepare transmit descriptors to give to DMA. */
\r
669 /* Set LAST and FIRST segment */
\r
670 pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;
\r
671 /* Set frame size */
\r
672 pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );
\r
674 #if( NETWORK_BUFFERS_CACHED != 0 )
\r
676 BaseType_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE );
\r
677 uint32_t *pulBuffer = ( uint32_t )( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE );
\r
678 cache_clean_invalidate_by_addr( pulBuffer, xlength );
\r
682 /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
\r
683 pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;
\r
685 /* Point to next descriptor */
\r
686 xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );
\r
687 /* Ensure completion of memory access */
\r
689 /* Resume DMA transmission*/
\r
690 xETH.Instance->DMATPDR = 0;
\r
691 iptraceNETWORK_INTERFACE_TRANSMIT();
\r
697 /* The PHY has no Link Status, packet shall be dropped. */
\r
700 /* The buffer has been sent so can be released. */
\r
701 if( bReleaseAfterSend != pdFALSE )
\r
703 vReleaseNetworkBufferAndDescriptor( pxDescriptor );
\r
708 /*-----------------------------------------------------------*/
\r
710 static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer )
\r
712 const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
\r
714 switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType )
\r
716 case ipARP_FRAME_TYPE:
\r
717 /* Check it later. */
\r
719 case ipIPv4_FRAME_TYPE:
\r
720 /* Check it here. */
\r
723 /* Refuse the packet. */
\r
727 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
729 const IPHeader_t *pxIPHeader = &(pxProtPacket->xTCPPacket.xIPHeader);
\r
730 uint32_t ulDestinationIPAddress;
\r
732 /* Ensure that the incoming packet is not fragmented (only outgoing packets
\r
733 * can be fragmented) as these are the only handled IP frames currently. */
\r
734 if( ( pxIPHeader->usFragmentOffset & FreeRTOS_ntohs( ipFRAGMENT_OFFSET_BIT_MASK ) ) != 0U )
\r
738 /* HT: Might want to make the following configurable because
\r
739 * most IP messages have a standard length of 20 bytes */
\r
741 /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes
\r
742 * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */
\r
743 if( pxIPHeader->ucVersionHeaderLength < 0x45 || pxIPHeader->ucVersionHeaderLength > 0x4F )
\r
748 ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;
\r
749 /* Is the packet for this node? */
\r
750 if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&
\r
751 /* Is it a broadcast address x.x.x.255 ? */
\r
752 ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) &&
\r
753 #if( ipconfigUSE_LLMNR == 1 )
\r
754 ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&
\r
756 ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) {
\r
757 FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) );
\r
761 if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )
\r
763 uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;
\r
765 if( ( xPortHasUDPSocket( port ) == pdFALSE )
\r
766 #if ipconfigUSE_LLMNR == 1
\r
767 && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )
\r
769 #if ipconfigUSE_NBNS == 1
\r
770 && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )
\r
772 #if ipconfigUSE_DNS == 1
\r
773 && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )
\r
776 /* Drop this packet, not for this device. */
\r
781 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
784 /*-----------------------------------------------------------*/
\r
786 static BaseType_t prvNetworkInterfaceInput( void )
\r
788 NetworkBufferDescriptor_t *pxCurDescriptor;
\r
789 NetworkBufferDescriptor_t *pxNewDescriptor = NULL;
\r
790 BaseType_t xReceivedLength, xAccepted;
\r
791 __IO ETH_DMADescTypeDef *pxDMARxDescriptor;
\r
792 xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
\r
793 const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
\r
794 uint8_t *pucBuffer;
\r
796 pxDMARxDescriptor = xETH.RxDesc;
\r
798 if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )
\r
800 /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
\r
801 xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;
\r
803 pucBuffer = (uint8_t *) pxDMARxDescriptor->Buffer1Addr;
\r
805 /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */
\r
806 /* Chained Mode */
\r
807 /* Selects the next DMA Rx descriptor list for next buffer to read */
\r
808 xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;
\r
812 xReceivedLength = 0;
\r
815 /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */
\r
817 /* get received frame */
\r
818 if( xReceivedLength > 0ul )
\r
820 /* In order to make the code easier and faster, only packets in a single buffer
\r
821 will be accepted. This can be done by making the buffers large enough to
\r
822 hold a complete Ethernet packet (1536 bytes).
\r
823 Therefore, two sanity checks: */
\r
824 configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );
\r
826 if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )
\r
828 /* Not an Ethernet frame-type or a checmsum error. */
\r
829 xAccepted = pdFALSE;
\r
833 /* See if this packet must be handled. */
\r
834 xAccepted = xMayAcceptPacket( pucBuffer );
\r
837 if( xAccepted != pdFALSE )
\r
839 /* The packet wil be accepted, but check first if a new Network Buffer can
\r
840 be obtained. If not, the packet will still be dropped. */
\r
841 pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, xDescriptorWaitTime );
\r
843 if( pxNewDescriptor == NULL )
\r
845 /* A new descriptor can not be allocated now. This packet will be dropped. */
\r
846 xAccepted = pdFALSE;
\r
849 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
851 /* Find out which Network Buffer was originally passed to the descriptor. */
\r
852 pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
\r
853 configASSERT( pxCurDescriptor != NULL );
\r
857 /* In this mode, the two descriptors are the same. */
\r
858 pxCurDescriptor = pxNewDescriptor;
\r
859 if( pxNewDescriptor != NULL )
\r
861 /* The packet is acepted and a new Network Buffer was created,
\r
862 copy data to the Network Bufffer. */
\r
863 memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength );
\r
868 if( xAccepted != pdFALSE )
\r
870 pxCurDescriptor->xDataLength = xReceivedLength;
\r
871 xRxEvent.pvData = ( void * ) pxCurDescriptor;
\r
873 /* Pass the data to the TCP/IP task for processing. */
\r
874 if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )
\r
876 /* Could not send the descriptor into the TCP/IP stack, it
\r
877 must be released. */
\r
878 vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );
\r
879 iptraceETHERNET_RX_EVENT_LOST();
\r
883 iptraceNETWORK_INTERFACE_RECEIVE();
\r
887 /* Release descriptors to DMA */
\r
888 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
890 /* Set Buffer1 address pointer */
\r
891 if( pxNewDescriptor != NULL )
\r
893 pxDMARxDescriptor->Buffer1Addr = (uint32_t)pxNewDescriptor->pucEthernetBuffer;
\r
897 /* The packet was dropped and the same Network
\r
898 Buffer will be used to receive a new packet. */
\r
901 #endif /* ipconfigZERO_COPY_RX_DRIVER */
\r
903 /* Set Buffer1 size and Second Address Chained bit */
\r
904 pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;
\r
905 pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;
\r
907 /* Ensure completion of memory access */
\r
909 /* When Rx Buffer unavailable flag is set clear it and resume
\r
911 if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )
\r
913 /* Clear RBUS ETHERNET DMA flag. */
\r
914 xETH.Instance->DMASR = ETH_DMASR_RBUS;
\r
916 /* Resume DMA reception. */
\r
917 xETH.Instance->DMARPDR = 0;
\r
921 return ( xReceivedLength > 0 );
\r
923 /*-----------------------------------------------------------*/
\r
926 BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )
\r
928 uint16_t usPrevAddress = xETH.Init.PhyAddress;
\r
929 BaseType_t xResult;
\r
930 HAL_StatusTypeDef xHALResult;
\r
932 xETH.Init.PhyAddress = xAddress;
\r
933 xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t )xRegister, pulValue );
\r
934 xETH.Init.PhyAddress = usPrevAddress;
\r
936 if( xHALResult == HAL_OK )
\r
946 /*-----------------------------------------------------------*/
\r
948 BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )
\r
950 uint16_t usPrevAddress = xETH.Init.PhyAddress;
\r
951 BaseType_t xResult;
\r
952 HAL_StatusTypeDef xHALResult;
\r
954 xETH.Init.PhyAddress = xAddress;
\r
955 xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t )xRegister, ulValue );
\r
956 xETH.Init.PhyAddress = usPrevAddress;
\r
958 if( xHALResult == HAL_OK )
\r
968 /*-----------------------------------------------------------*/
\r
970 void vMACBProbePhy( void )
\r
972 vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );
\r
973 xPhyDiscover( &xPhyObject );
\r
974 xPhyConfigure( &xPhyObject, &xPHYProperties );
\r
976 /*-----------------------------------------------------------*/
\r
978 static void prvEthernetUpdateConfig( BaseType_t xForce )
\r
980 FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n",
\r
981 xPhyObject.ulLinkStatusMask,
\r
984 if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )
\r
986 /* Restart the auto-negotiation. */
\r
987 if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )
\r
989 xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );
\r
991 /* Configure the MAC with the Duplex Mode fixed by the
\r
992 auto-negotiation process. */
\r
993 if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )
\r
995 xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
\r
999 xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
\r
1002 /* Configure the MAC with the speed fixed by the
\r
1003 auto-negotiation process. */
\r
1004 if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )
\r
1006 xETH.Init.Speed = ETH_SPEED_10M;
\r
1010 xETH.Init.Speed = ETH_SPEED_100M;
\r
1013 else /* AutoNegotiation Disable */
\r
1015 /* Check parameters */
\r
1016 assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );
\r
1017 assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );
\r
1019 if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX )
\r
1021 xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;
\r
1025 xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;
\r
1028 if( xETH.Init.Speed == ETH_SPEED_10M )
\r
1030 xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;
\r
1034 xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;
\r
1037 xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;
\r
1039 /* Use predefined (fixed) configuration. */
\r
1040 xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );
\r
1043 /* ETHERNET MAC Re-Configuration */
\r
1044 HAL_ETH_ConfigMAC( &xETH, (ETH_MACInitTypeDef *) NULL);
\r
1046 /* Restart MAC interface */
\r
1047 HAL_ETH_Start( &xETH);
\r
1051 /* Stop MAC interface */
\r
1052 HAL_ETH_Stop( &xETH );
\r
1055 /*-----------------------------------------------------------*/
\r
1057 BaseType_t xGetPhyLinkStatus( void )
\r
1059 BaseType_t xReturn;
\r
1061 if( xPhyObject.ulLinkStatusMask != 0 )
\r
1072 /*-----------------------------------------------------------*/
\r
1074 /* Uncomment this in case BufferAllocation_1.c is used. */
\r
1076 #define niBUFFER_1_PACKET_SIZE 1536
\r
1078 void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
\r
1080 static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
\r
1081 uint8_t *ucRAMBuffer = ucNetworkPackets;
\r
1084 for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
\r
1086 pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
\r
1087 *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
\r
1088 ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
\r
1091 /*-----------------------------------------------------------*/
\r
1093 static void prvEMACHandlerTask( void *pvParameters )
\r
1095 UBaseType_t uxLastMinBufferCount = 0;
\r
1096 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
\r
1097 UBaseType_t uxLastMinQueueSpace = 0;
\r
1099 UBaseType_t uxCurrentCount;
\r
1100 BaseType_t xResult;
\r
1101 const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
\r
1103 /* Remove compiler warnings about unused parameters. */
\r
1104 ( void ) pvParameters;
\r
1109 uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
\r
1110 if( uxLastMinBufferCount != uxCurrentCount )
\r
1112 /* The logging produced below may be helpful
\r
1113 while tuning +TCP: see how many buffers are in use. */
\r
1114 uxLastMinBufferCount = uxCurrentCount;
\r
1115 FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
\r
1116 uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
\r
1119 if( xTXDescriptorSemaphore != NULL )
\r
1121 static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;
\r
1123 uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );
\r
1124 if( uxLowestSemCount > uxCurrentCount )
\r
1126 uxLowestSemCount = uxCurrentCount;
\r
1127 FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );
\r
1132 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
\r
1134 uxCurrentCount = uxGetMinimumIPQueueSpace();
\r
1135 if( uxLastMinQueueSpace != uxCurrentCount )
\r
1137 /* The logging produced below may be helpful
\r
1138 while tuning +TCP: see how many buffers are in use. */
\r
1139 uxLastMinQueueSpace = uxCurrentCount;
\r
1140 FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
\r
1143 #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
\r
1145 if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
\r
1147 /* No events to process now, wait for the next. */
\r
1148 ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
\r
1151 if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
\r
1153 ulISREvents &= ~EMAC_IF_RX_EVENT;
\r
1155 xResult = prvNetworkInterfaceInput();
\r
1158 while( prvNetworkInterfaceInput() > 0 )
\r
1164 if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
\r
1166 /* Code to release TX buffers if zero-copy is used. */
\r
1167 ulISREvents &= ~EMAC_IF_TX_EVENT;
\r
1168 /* Check if DMA packets have been delivered. */
\r
1169 vClearTXBuffers();
\r
1172 if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
\r
1174 /* Future extension: logging about errors that occurred. */
\r
1175 ulISREvents &= ~EMAC_IF_ERR_EVENT;
\r
1177 if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
\r
1179 /* Something has changed to a Link Status, need re-check. */
\r
1180 prvEthernetUpdateConfig( pdFALSE );
\r
1184 /*-----------------------------------------------------------*/
\r
1186 void ETH_IRQHandler( void )
\r
1188 HAL_ETH_IRQHandler( &xETH );
\r