]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
Sync with TCP version from AWS, including:
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / STM32Fxx / NetworkInterface.c
1 /*\r
2  * Some constants, hardware definitions and comments taken from ST's HAL driver\r
3  * library, COPYRIGHT(c) 2015 STMicroelectronics.\r
4  */\r
5 \r
6 /*\r
7  * FreeRTOS+TCP V2.0.3\r
8  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
9  *\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
16  *\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
19  *\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
26  *\r
27  * http://aws.amazon.com/freertos\r
28  * http://www.FreeRTOS.org\r
29  */\r
30 \r
31 \r
32 /* Standard includes. */\r
33 #include <stdint.h>\r
34 #include <stdio.h>\r
35 #include <stdlib.h>\r
36 \r
37 /* FreeRTOS includes. */\r
38 #include "FreeRTOS.h"\r
39 #include "task.h"\r
40 #include "queue.h"\r
41 #include "semphr.h"\r
42 \r
43 /* FreeRTOS+TCP includes. */\r
44 #include "FreeRTOS_IP.h"\r
45 #include "FreeRTOS_Sockets.h"\r
46 #include "FreeRTOS_IP_Private.h"\r
47 #include "FreeRTOS_DNS.h"\r
48 #include "NetworkBufferManagement.h"\r
49 #include "NetworkInterface.h"\r
50 #include "phyHandling.h"\r
51 \r
52 /* ST includes. */\r
53 #ifdef STM32F7xx\r
54         #include "stm32f7xx_hal.h"\r
55 #else\r
56         #include "stm32f4xx_hal.h"\r
57 #endif\r
58 \r
59 /* Interrupt events to process.  Currently only the Rx event is processed\r
60 although code for other events is included to allow for possible future\r
61 expansion. */\r
62 #define EMAC_IF_RX_EVENT        1UL\r
63 #define EMAC_IF_TX_EVENT        2UL\r
64 #define EMAC_IF_ERR_EVENT       4UL\r
65 #define EMAC_IF_ALL_EVENT       ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
66 \r
67 #define ETH_DMA_ALL_INTS \\r
68         ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | ETH_DMA_IT_ER | \\r
69           ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \\r
70           ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )\r
71 \r
72 \r
73 \r
74 #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
75 \r
76 /*\r
77  * Most users will want a PHY that negotiates about\r
78  * the connection properties: speed, dmix and duplex.\r
79  * On some rare cases, you want to select what is being\r
80  * advertised, properties like MDIX and duplex.\r
81  */\r
82 \r
83 #if !defined( ipconfigETHERNET_AN_ENABLE )\r
84         /* Enable auto-negotiation */\r
85         #define ipconfigETHERNET_AN_ENABLE                              1\r
86 #endif\r
87 \r
88 #if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE )\r
89         #define ipconfigETHERNET_AUTO_CROSS_ENABLE              1\r
90 #endif\r
91 \r
92 #if( ipconfigETHERNET_AN_ENABLE == 0 )\r
93         /*\r
94          * The following three defines are only used in case there\r
95          * is no auto-negotiation.\r
96          */\r
97         #if !defined( ipconfigETHERNET_CROSSED_LINK )\r
98                 #define ipconfigETHERNET_CROSSED_LINK                   1\r
99         #endif\r
100 \r
101         #if !defined( ipconfigETHERNET_USE_100MB )\r
102                 #define ipconfigETHERNET_USE_100MB                              1\r
103         #endif\r
104 \r
105         #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX )\r
106                 #define ipconfigETHERNET_USE_FULL_DUPLEX                1\r
107         #endif\r
108 #endif /* ipconfigETHERNET_AN_ENABLE == 0 */\r
109 \r
110 /* Default the size of the stack used by the EMAC deferred handler task to twice\r
111 the size of the stack used by the idle task - but allow this to be overridden in\r
112 FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
113 #ifndef configEMAC_TASK_STACK_SIZE\r
114         #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )\r
115 #endif\r
116 \r
117 /* Two choices must be made: RMII versus MII,\r
118 and the index of the PHY in use ( between 0 and 31 ). */\r
119 #ifndef ipconfigUSE_RMII\r
120         #ifdef STM32F7xx\r
121                 #define ipconfigUSE_RMII        1\r
122         #else\r
123                 #define ipconfigUSE_RMII        0\r
124         #endif /* STM32F7xx */\r
125 #endif /* ipconfigUSE_RMII */\r
126 \r
127 \r
128 \r
129 /*-----------------------------------------------------------*/\r
130 \r
131 /*\r
132  * A deferred interrupt handler task that processes\r
133  */\r
134 static void prvEMACHandlerTask( void *pvParameters );\r
135 \r
136 /*\r
137  * Force a negotiation with the Switch or Router and wait for LS.\r
138  */\r
139 static void prvEthernetUpdateConfig( BaseType_t xForce );\r
140 \r
141 /*\r
142  * See if there is a new packet and forward it to the IP-task.\r
143  */\r
144 static BaseType_t prvNetworkInterfaceInput( void );\r
145 \r
146 #if( ipconfigUSE_LLMNR != 0 )\r
147         /*\r
148          * For LLMNR, an extra MAC-address must be configured to\r
149          * be able to receive the multicast messages.\r
150          */\r
151         static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr);\r
152 #endif\r
153 \r
154 /*\r
155  * Check if a given packet should be accepted.\r
156  */\r
157 static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer );\r
158 \r
159 /*\r
160  * Initialise the TX descriptors.\r
161  */\r
162 static void prvDMATxDescListInit( void );\r
163 \r
164 /*\r
165  * Initialise the RX descriptors.\r
166  */\r
167 static void prvDMARxDescListInit( void );\r
168 \r
169 /* After packets have been sent, the network\r
170 buffers will be released. */\r
171 static void vClearTXBuffers( void );\r
172 \r
173 /*-----------------------------------------------------------*/\r
174 \r
175 /* Bit map of outstanding ETH interrupt events for processing.  Currently only\r
176 the Rx interrupt is handled, although code is included for other events to\r
177 enable future expansion. */\r
178 static volatile uint32_t ulISREvents;\r
179 \r
180 #if( ipconfigUSE_LLMNR == 1 )\r
181         static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
182 #endif\r
183 \r
184 static EthernetPhy_t xPhyObject;\r
185 \r
186 /* Ethernet handle. */\r
187 static ETH_HandleTypeDef xETH;\r
188 \r
189 /* xTXDescriptorSemaphore is a counting semaphore with\r
190 a maximum count of ETH_TXBUFNB, which is the number of\r
191 DMA TX descriptors. */\r
192 static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
193 \r
194 /*\r
195  * Note: it is adviced to define both\r
196  *\r
197  *     #define  ipconfigZERO_COPY_RX_DRIVER   1\r
198  *     #define  ipconfigZERO_COPY_TX_DRIVER   1\r
199  *\r
200  * The method using memcpy is slower and probaly uses more RAM memory.\r
201  * The possibility is left in the code just for comparison.\r
202  *\r
203  * It is adviced to define ETH_TXBUFNB at least 4. Note that no\r
204  * TX buffers are allocated in a zero-copy driver.\r
205  */\r
206 /* MAC buffers: ---------------------------------------------------------*/\r
207 \r
208 /* Put the DMA descriptors in '.first_data'.\r
209 This is important for STM32F7, which has an L1 data cache.\r
210 The first 64KB of the SRAM is not cached. */\r
211 \r
212 /* Ethernet Rx MA Descriptor */\r
213 __attribute__ ((aligned (32)))\r
214 __attribute__ ((section(".first_data")))\r
215         ETH_DMADescTypeDef  DMARxDscrTab[ ETH_RXBUFNB ];\r
216 \r
217 #if( ipconfigZERO_COPY_RX_DRIVER == 0 )\r
218         /* Ethernet Receive Buffer */\r
219         __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END;\r
220 #endif\r
221 \r
222 /* Ethernet Tx DMA Descriptor */\r
223 __attribute__ ((aligned (32)))\r
224 __attribute__ ((section(".first_data")))\r
225         ETH_DMADescTypeDef  DMATxDscrTab[ ETH_TXBUFNB ];\r
226 \r
227 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
228         /* Ethernet Transmit Buffer */\r
229         __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END;\r
230 #endif\r
231 \r
232 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
233         /* DMATxDescToClear points to the next TX DMA descriptor\r
234         that must be cleared by vClearTXBuffers(). */\r
235         static __IO ETH_DMADescTypeDef  *DMATxDescToClear;\r
236 #endif\r
237 \r
238 /* ucMACAddress as it appears in main.c */\r
239 extern const uint8_t ucMACAddress[ 6 ];\r
240 \r
241 /* Holds the handle of the task used as a deferred interrupt processor.  The\r
242 handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
243 related interrupts. */\r
244 static TaskHandle_t xEMACTaskHandle = NULL;\r
245 \r
246 /* For local use only: describe the PHY's properties: */\r
247 const PhyProperties_t xPHYProperties =\r
248 {\r
249         #if( ipconfigETHERNET_AN_ENABLE != 0 )\r
250                 .ucSpeed = PHY_SPEED_AUTO,\r
251                 .ucDuplex = PHY_DUPLEX_AUTO,\r
252         #else\r
253                 #if( ipconfigETHERNET_USE_100MB != 0 )\r
254                         .ucSpeed = PHY_SPEED_100,\r
255                 #else\r
256                         .ucSpeed = PHY_SPEED_10,\r
257                 #endif\r
258 \r
259                 #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )\r
260                         .duplex = PHY_DUPLEX_FULL,\r
261                 #else\r
262                         .duplex = PHY_DUPLEX_HALF,\r
263                 #endif\r
264         #endif\r
265 \r
266         #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )\r
267                 .ucMDI_X = PHY_MDIX_AUTO,\r
268         #elif( ipconfigETHERNET_CROSSED_LINK != 0 )\r
269                 .ucMDI_X = PHY_MDIX_CROSSED,\r
270         #else\r
271                 .ucMDI_X = PHY_MDIX_DIRECT,\r
272         #endif\r
273 };\r
274 \r
275 /*-----------------------------------------------------------*/\r
276 \r
277 void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )\r
278 {\r
279 BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
280 \r
281         /* Ethernet RX-Complete callback function, elsewhere declared as weak. */\r
282     ulISREvents |= EMAC_IF_RX_EVENT;\r
283         /* Wakeup the prvEMACHandlerTask. */\r
284         if( xEMACTaskHandle != NULL )\r
285         {\r
286                 vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
287                 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
288         }\r
289 }\r
290 /*-----------------------------------------------------------*/\r
291 \r
292 void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )\r
293 {\r
294 BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
295 \r
296         /* This call-back is only useful in case packets are being sent\r
297         zero-copy.  Once they're sent, the buffers will be released\r
298         by the function vClearTXBuffers(). */\r
299         ulISREvents |= EMAC_IF_TX_EVENT;\r
300         /* Wakeup the prvEMACHandlerTask. */\r
301         if( xEMACTaskHandle != NULL )\r
302         {\r
303                 vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
304                 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
305         }\r
306 \r
307 }\r
308 /*-----------------------------------------------------------*/\r
309 \r
310 static void vClearTXBuffers()\r
311 {\r
312 __IO ETH_DMADescTypeDef  *txLastDescriptor = xETH.TxDesc;\r
313 size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
314 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
315         NetworkBufferDescriptor_t *pxNetworkBuffer;\r
316         uint8_t *ucPayLoad;\r
317 #endif\r
318 \r
319         /* This function is called after a TX-completion interrupt.\r
320         It will release each Network Buffer used in xNetworkInterfaceOutput().\r
321         'uxCount' represents the number of descriptors given to DMA for transmission.\r
322         After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */\r
323         while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )\r
324         {\r
325                 if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )\r
326                 {\r
327                         break;\r
328                 }\r
329                 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
330                 {\r
331                         ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;\r
332 \r
333                         if( ucPayLoad != NULL )\r
334                         {\r
335                                 pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );\r
336                                 if( pxNetworkBuffer != NULL )\r
337                                 {\r
338                                         vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;\r
339                                 }\r
340                                 DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;\r
341                         }\r
342                 }\r
343                 #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
344 \r
345                 DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );\r
346 \r
347                 uxCount--;\r
348                 /* Tell the counting semaphore that one more TX descriptor is available. */\r
349                 xSemaphoreGive( xTXDescriptorSemaphore );\r
350         }\r
351 }\r
352 /*-----------------------------------------------------------*/\r
353 \r
354 BaseType_t xNetworkInterfaceInitialise( void )\r
355 {\r
356 HAL_StatusTypeDef hal_eth_init_status;\r
357 BaseType_t xResult;\r
358 \r
359         if( xEMACTaskHandle == NULL )\r
360         {\r
361                 if( xTXDescriptorSemaphore == NULL )\r
362                 {\r
363                         xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );\r
364                         configASSERT( xTXDescriptorSemaphore );\r
365                 }\r
366 \r
367                 /* Initialise ETH */\r
368 \r
369                 xETH.Instance = ETH;\r
370                 xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;\r
371                 xETH.Init.Speed = ETH_SPEED_100M;\r
372                 xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
373                 /* Value of PhyAddress doesn't matter, will be probed for. */\r
374                 xETH.Init.PhyAddress = 0;\r
375 \r
376                 xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;\r
377                 xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;\r
378 \r
379                 /* using the ETH_CHECKSUM_BY_HARDWARE option:\r
380                 both the IP and the protocol checksums will be calculated\r
381                 by the peripheral. */\r
382                 xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;\r
383 \r
384                 #if( ipconfigUSE_RMII != 0 )\r
385                 {\r
386                         xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;\r
387                 }\r
388                 #else\r
389                 {\r
390                         xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;\r
391                 }\r
392                 #endif /* ipconfigUSE_RMII */\r
393 \r
394                 hal_eth_init_status = HAL_ETH_Init( &xETH );\r
395 \r
396                 /* Only for inspection by debugger. */\r
397                 ( void ) hal_eth_init_status;\r
398 \r
399                 /* Set the TxDesc and RxDesc pointers. */\r
400                 xETH.TxDesc = DMATxDscrTab;\r
401                 xETH.RxDesc = DMARxDscrTab;\r
402 \r
403                 /* Make sure that all unused fields are cleared. */\r
404                 memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );\r
405                 memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );\r
406 \r
407                 /* Initialize Tx Descriptors list: Chain Mode */\r
408                 DMATxDescToClear = DMATxDscrTab;\r
409 \r
410                 /* Initialise TX-descriptors. */\r
411                 prvDMATxDescListInit();\r
412 \r
413                 /* Initialise RX-descriptors. */\r
414                 prvDMARxDescListInit();\r
415 \r
416                 #if( ipconfigUSE_LLMNR != 0 )\r
417                 {\r
418                         /* Program the LLMNR address at index 1. */\r
419                         prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );\r
420                 }\r
421                 #endif\r
422 \r
423                 /* Force a negotiation with the Switch or Router and wait for LS. */\r
424                 prvEthernetUpdateConfig( pdTRUE );\r
425 \r
426                 /* The deferred interrupt handler task is created at the highest\r
427                 possible priority to ensure the interrupt handler can return directly\r
428                 to it.  The task's handle is stored in xEMACTaskHandle so interrupts can\r
429                 notify the task when there is something to process. */\r
430                 xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
431         } /* if( xEMACTaskHandle == NULL ) */\r
432 \r
433         if( xPhyObject.ulLinkStatusMask != 0 )\r
434         {\r
435                 xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;\r
436                 xResult = pdPASS;\r
437                 FreeRTOS_printf( ( "Link Status is high\n" ) ) ;\r
438         }\r
439         else\r
440         {\r
441                 /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running\r
442                 and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */\r
443                 xResult = pdFAIL;\r
444                 FreeRTOS_printf( ( "Link Status still low\n" ) ) ;\r
445         }\r
446         /* When returning non-zero, the stack will become active and\r
447     start DHCP (in configured) */\r
448         return xResult;\r
449 }\r
450 /*-----------------------------------------------------------*/\r
451 \r
452 static void prvDMATxDescListInit()\r
453 {\r
454 ETH_DMADescTypeDef *pxDMADescriptor;\r
455 BaseType_t xIndex;\r
456 \r
457         /* Get the pointer on the first member of the descriptor list */\r
458         pxDMADescriptor = DMATxDscrTab;\r
459 \r
460         /* Fill each DMA descriptor with the right values */\r
461         for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ )\r
462         {\r
463                 /* Set Second Address Chained bit */\r
464                 pxDMADescriptor->Status = ETH_DMATXDESC_TCH;\r
465 \r
466                 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
467                 {\r
468                         /* Set Buffer1 address pointer */\r
469                         pxDMADescriptor->Buffer1Addr = ( uint32_t )( Tx_Buff[ xIndex ] );\r
470                 }\r
471                 #endif\r
472 \r
473                 if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE )\r
474                 {\r
475                         /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */\r
476                         pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;\r
477                 }\r
478 \r
479                 /* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
480                 if( xIndex < ETH_TXBUFNB - 1 )\r
481                 {\r
482                         /* Set next descriptor address register with next descriptor base address */\r
483                         pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 );\r
484                 }\r
485                 else\r
486                 {\r
487                         /* For last descriptor, set next descriptor address register equal to the first descriptor base address */\r
488                         pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab;\r
489                 }\r
490         }\r
491 \r
492         /* Set Transmit Descriptor List Address Register */\r
493         xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab;\r
494 }\r
495 /*-----------------------------------------------------------*/\r
496 \r
497 static void prvDMARxDescListInit()\r
498 {\r
499 ETH_DMADescTypeDef *pxDMADescriptor;\r
500 BaseType_t xIndex;\r
501         /*\r
502          * RX-descriptors.\r
503          */\r
504 \r
505         /* Get the pointer on the first member of the descriptor list */\r
506         pxDMADescriptor = DMARxDscrTab;\r
507 \r
508         /* Fill each DMA descriptor with the right values */\r
509         for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ )\r
510         {\r
511 \r
512                 /* Set Buffer1 size and Second Address Chained bit */\r
513                 pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  \r
514 \r
515                 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
516                 {\r
517                 /* Set Buffer1 address pointer */\r
518                 NetworkBufferDescriptor_t *pxBuffer;\r
519 \r
520                         pxBuffer = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, 100ul );\r
521                         /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB'\r
522                         Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */\r
523                         configASSERT( pxBuffer != NULL );\r
524                         if( pxBuffer != NULL )\r
525                         {\r
526                                 pxDMADescriptor->Buffer1Addr = (uint32_t)pxBuffer->pucEthernetBuffer;\r
527                                 pxDMADescriptor->Status = ETH_DMARXDESC_OWN;\r
528                         }\r
529                 }\r
530                 #else\r
531                 {\r
532                         /* Set Buffer1 address pointer */\r
533                         pxDMADescriptor->Buffer1Addr = ( uint32_t )( Rx_Buff[ xIndex ] );\r
534                         /* Set Own bit of the Rx descriptor Status */\r
535                         pxDMADescriptor->Status = ETH_DMARXDESC_OWN;\r
536                 }\r
537                 #endif\r
538 \r
539                 /* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
540                 if( xIndex < ETH_RXBUFNB - 1 )\r
541                 {\r
542                         /* Set next descriptor address register with next descriptor base address */\r
543                         pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t )( pxDMADescriptor + 1 );\r
544                 }\r
545                 else\r
546                 {\r
547                         /* For last descriptor, set next descriptor address register equal to the first descriptor base address */\r
548                         pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab;\r
549                 }\r
550 \r
551         }\r
552         /* Set Receive Descriptor List Address Register */\r
553         xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab;\r
554 }\r
555 /*-----------------------------------------------------------*/\r
556 \r
557 static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr)\r
558 {\r
559 uint32_t ulTempReg;\r
560 \r
561         /* Calculate the selected MAC address high register. */\r
562         ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];\r
563 \r
564         /* Load the selected MAC address high register. */\r
565         ( *(__IO uint32_t *)( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg;\r
566 \r
567         /* Calculate the selected MAC address low register. */\r
568         ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ];\r
569 \r
570         /* Load the selected MAC address low register */\r
571         ( *(__IO uint32_t *) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg;\r
572 }\r
573 /*-----------------------------------------------------------*/\r
574 \r
575 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
576 {\r
577 BaseType_t xReturn = pdFAIL;\r
578 uint32_t ulTransmitSize = 0;\r
579 __IO ETH_DMADescTypeDef *pxDmaTxDesc;\r
580 /* Do not wait too long for a free TX DMA buffer. */\r
581 const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );\r
582 \r
583         #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
584         {\r
585         ProtocolPacket_t *pxPacket;\r
586 \r
587                 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
588                 {\r
589                         configASSERT( bReleaseAfterSend != 0 );\r
590                 }\r
591                 #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
592 \r
593                 /* If the peripheral must calculate the checksum, it wants\r
594                 the protocol checksum to have a value of zero. */\r
595                 pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );\r
596 \r
597                 if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )\r
598                 {\r
599                         pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;\r
600                 }\r
601         }\r
602         #endif\r
603 \r
604         /* Open a do {} while ( 0 ) loop to be able to call break. */\r
605         do\r
606         {\r
607                 if( xPhyObject.ulLinkStatusMask != 0 )\r
608                 {\r
609                         if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
610                         {\r
611                                 /* Time-out waiting for a free TX descriptor. */\r
612                                 break;\r
613                         }\r
614 \r
615                         /* This function does the actual transmission of the packet. The packet is\r
616                         contained in 'pxDescriptor' that is passed to the function. */\r
617                         pxDmaTxDesc = xETH.TxDesc;\r
618 \r
619                         /* Is this buffer available? */\r
620                         configASSERT ( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 );\r
621 \r
622                         {\r
623                                 /* Is this buffer available? */\r
624                                 /* Get bytes in current buffer. */\r
625                                 ulTransmitSize = pxDescriptor->xDataLength;\r
626 \r
627                                 if( ulTransmitSize > ETH_TX_BUF_SIZE )\r
628                                 {\r
629                                         ulTransmitSize = ETH_TX_BUF_SIZE;\r
630                                 }\r
631 \r
632                                 #if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
633                                 {\r
634                                         /* Copy the bytes. */\r
635                                         memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );\r
636                                 }\r
637                                 #else\r
638                                 {\r
639                                         /* Move the buffer. */\r
640                                         pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;\r
641                                         /* The Network Buffer has been passed to DMA, no need to release it. */\r
642                                         bReleaseAfterSend = pdFALSE_UNSIGNED;\r
643                                 }\r
644                                 #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
645 \r
646                                 /* Ask to set the IPv4 checksum.\r
647                                 Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */\r
648                                 pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;\r
649 \r
650                                 /* Prepare transmit descriptors to give to DMA. */\r
651 \r
652                                 /* Set LAST and FIRST segment */\r
653                                 pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;\r
654                                 /* Set frame size */\r
655                                 pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );\r
656                                 /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */\r
657                                 pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;\r
658 \r
659                                 /* Point to next descriptor */\r
660                                 xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );\r
661                                 /* Ensure completion of memory access */\r
662                                 __DSB();\r
663                                 /* Resume DMA transmission*/\r
664                                 xETH.Instance->DMATPDR = 0;\r
665                                 iptraceNETWORK_INTERFACE_TRANSMIT();\r
666                                 xReturn = pdPASS;\r
667                         }\r
668                 }\r
669                 else\r
670                 {\r
671                         /* The PHY has no Link Status, packet shall be dropped. */\r
672                 }\r
673         } while( 0 );\r
674         /* The buffer has been sent so can be released. */\r
675         if( bReleaseAfterSend != pdFALSE )\r
676         {\r
677                 vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
678         }\r
679 \r
680         return xReturn;\r
681 }\r
682 /*-----------------------------------------------------------*/\r
683 \r
684 static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer )\r
685 {\r
686 const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;\r
687 \r
688         switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType )\r
689         {\r
690         case ipARP_FRAME_TYPE:\r
691                 /* Check it later. */\r
692                 return pdTRUE;\r
693         case ipIPv4_FRAME_TYPE:\r
694                 /* Check it here. */\r
695                 break;\r
696         default:\r
697                 /* Refuse the packet. */\r
698                 return pdFALSE;\r
699         }\r
700 \r
701         #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
702         {\r
703                 const IPHeader_t *pxIPHeader = &(pxProtPacket->xTCPPacket.xIPHeader);\r
704                 uint32_t ulDestinationIPAddress;\r
705 \r
706                 /* Ensure that the incoming packet is not fragmented (only outgoing packets\r
707                  * can be fragmented) as these are the only handled IP frames currently. */\r
708                 if( ( pxIPHeader->usFragmentOffset & FreeRTOS_ntohs( ipFRAGMENT_OFFSET_BIT_MASK ) ) != 0U )\r
709                 {\r
710                         return pdFALSE;\r
711                 }\r
712                 /* HT: Might want to make the following configurable because\r
713                  * most IP messages have a standard length of 20 bytes */\r
714 \r
715                 /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes\r
716                  * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */\r
717                 if( pxIPHeader->ucVersionHeaderLength < 0x45 || pxIPHeader->ucVersionHeaderLength > 0x4F )\r
718                 {\r
719                         return pdFALSE;\r
720                 }\r
721 \r
722                 ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;\r
723                 /* Is the packet for this node? */\r
724                 if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&\r
725                         /* Is it a broadcast address x.x.x.255 ? */\r
726                         ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) &&\r
727                 #if( ipconfigUSE_LLMNR == 1 )\r
728                         ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&\r
729                 #endif\r
730                         ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) {\r
731                         FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) );\r
732                         return pdFALSE;\r
733                 }\r
734 \r
735                 if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )\r
736                 {\r
737                         uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;\r
738 \r
739                         if( ( xPortHasUDPSocket( port ) == pdFALSE )\r
740                         #if ipconfigUSE_LLMNR == 1\r
741                                 && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )\r
742                         #endif\r
743                         #if ipconfigUSE_NBNS == 1\r
744                                 && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )\r
745                         #endif\r
746                         #if ipconfigUSE_DNS == 1\r
747                                 && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )\r
748                         #endif\r
749                                 ) {\r
750                                 /* Drop this packet, not for this device. */\r
751                                 return pdFALSE;\r
752                         }\r
753                 }\r
754         }\r
755         #endif  /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
756         return pdTRUE;\r
757 }\r
758 /*-----------------------------------------------------------*/\r
759 \r
760 static BaseType_t prvNetworkInterfaceInput( void )\r
761 {\r
762 NetworkBufferDescriptor_t *pxCurDescriptor;\r
763 NetworkBufferDescriptor_t *pxNewDescriptor = NULL;\r
764 BaseType_t xReceivedLength, xAccepted;\r
765 __IO ETH_DMADescTypeDef *pxDMARxDescriptor;\r
766 xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
767 const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
768 uint8_t *pucBuffer;\r
769 \r
770         pxDMARxDescriptor = xETH.RxDesc;\r
771 \r
772         if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )\r
773         {\r
774                 /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */\r
775                 xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;\r
776 \r
777                 pucBuffer = (uint8_t *) pxDMARxDescriptor->Buffer1Addr;\r
778 \r
779                 /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */\r
780                 /* Chained Mode */    \r
781                 /* Selects the next DMA Rx descriptor list for next buffer to read */ \r
782                 xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;\r
783         }\r
784         else\r
785         {\r
786                 xReceivedLength = 0;\r
787         }\r
788 \r
789         /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */\r
790 \r
791         /* get received frame */\r
792         if( xReceivedLength > 0ul )\r
793         {\r
794                 /* In order to make the code easier and faster, only packets in a single buffer\r
795                 will be accepted.  This can be done by making the buffers large enough to\r
796                 hold a complete Ethernet packet (1536 bytes).\r
797                 Therefore, two sanity checks: */\r
798                 configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );\r
799 \r
800                 if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )\r
801                 {\r
802                         /* Not an Ethernet frame-type or a checmsum error. */\r
803                         xAccepted = pdFALSE;\r
804                 }\r
805                 else\r
806                 {\r
807                         /* See if this packet must be handled. */\r
808                         xAccepted = xMayAcceptPacket( pucBuffer );\r
809                 }\r
810 \r
811                 if( xAccepted != pdFALSE )\r
812                 {\r
813                         /* The packet wil be accepted, but check first if a new Network Buffer can\r
814                         be obtained. If not, the packet will still be dropped. */\r
815                         pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, xDescriptorWaitTime );\r
816 \r
817                         if( pxNewDescriptor == NULL )\r
818                         {\r
819                                 /* A new descriptor can not be allocated now. This packet will be dropped. */\r
820                                 xAccepted = pdFALSE;\r
821                         }\r
822                 }\r
823                 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
824                 {\r
825                         /* Find out which Network Buffer was originally passed to the descriptor. */\r
826                         pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
827                         configASSERT( pxCurDescriptor != NULL );\r
828                 }\r
829                 #else\r
830                 {\r
831                         /* In this mode, the two descriptors are the same. */\r
832                         pxCurDescriptor = pxNewDescriptor;\r
833                         if( pxNewDescriptor != NULL )\r
834                         {\r
835                                 /* The packet is acepted and a new Network Buffer was created,\r
836                                 copy data to the Network Bufffer. */\r
837                                 memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength );\r
838                         }\r
839                 }\r
840                 #endif\r
841 \r
842                 if( xAccepted != pdFALSE )\r
843                 {\r
844                         pxCurDescriptor->xDataLength = xReceivedLength;\r
845                         xRxEvent.pvData = ( void * ) pxCurDescriptor;\r
846 \r
847                         /* Pass the data to the TCP/IP task for processing. */\r
848                         if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )\r
849                         {\r
850                                 /* Could not send the descriptor into the TCP/IP stack, it\r
851                                 must be released. */\r
852                                 vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );\r
853                                 iptraceETHERNET_RX_EVENT_LOST();\r
854                         }\r
855                         else\r
856                         {\r
857                                 iptraceNETWORK_INTERFACE_RECEIVE();\r
858                         }\r
859                 }\r
860 \r
861                 /* Release descriptors to DMA */\r
862                 #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
863                 {\r
864                         /* Set Buffer1 address pointer */\r
865                         if( pxNewDescriptor != NULL )\r
866                         {\r
867                                 pxDMARxDescriptor->Buffer1Addr = (uint32_t)pxNewDescriptor->pucEthernetBuffer;\r
868                         }\r
869                         else\r
870                         {\r
871                                 /* The packet was dropped and the same Network\r
872                                 Buffer will be used to receive a new packet. */\r
873                         }\r
874                 }\r
875                 #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
876 \r
877                 /* Set Buffer1 size and Second Address Chained bit */\r
878                 pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  \r
879                 pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;\r
880 \r
881                 /* Ensure completion of memory access */\r
882                 __DSB();\r
883                 /* When Rx Buffer unavailable flag is set clear it and resume\r
884                 reception. */\r
885                 if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )\r
886                 {\r
887                         /* Clear RBUS ETHERNET DMA flag. */\r
888                         xETH.Instance->DMASR = ETH_DMASR_RBUS;\r
889 \r
890                         /* Resume DMA reception. */\r
891                         xETH.Instance->DMARPDR = 0;\r
892                 }\r
893         }\r
894 \r
895         return ( xReceivedLength > 0 );\r
896 }\r
897 /*-----------------------------------------------------------*/\r
898 \r
899 \r
900 BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )\r
901 {\r
902 uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
903 BaseType_t xResult;\r
904 HAL_StatusTypeDef xHALResult;\r
905 \r
906         xETH.Init.PhyAddress = xAddress;\r
907         xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t )xRegister, pulValue );\r
908         xETH.Init.PhyAddress = usPrevAddress;\r
909 \r
910         if( xHALResult == HAL_OK )\r
911         {\r
912                 xResult = 0;\r
913         }\r
914         else\r
915         {\r
916                 xResult = -1;\r
917         }\r
918         return xResult;\r
919 }\r
920 /*-----------------------------------------------------------*/\r
921 \r
922 BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )\r
923 {\r
924 uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
925 BaseType_t xResult;\r
926 HAL_StatusTypeDef xHALResult;\r
927 \r
928         xETH.Init.PhyAddress = xAddress;\r
929         xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t )xRegister, ulValue );\r
930         xETH.Init.PhyAddress = usPrevAddress;\r
931 \r
932         if( xHALResult == HAL_OK )\r
933         {\r
934                 xResult = 0;\r
935         }\r
936         else\r
937         {\r
938                 xResult = -1;\r
939         }\r
940         return xResult;\r
941 }\r
942 /*-----------------------------------------------------------*/\r
943 \r
944 void phy_test()\r
945 {\r
946 BaseType_t xPhyCount;\r
947 BaseType_t xPhyIndex;\r
948 \r
949         vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );\r
950         xPhyCount = xPhyDiscover( &xPhyObject );\r
951         FreeRTOS_printf( ( "PHY count %ld\n", xPhyCount ) );\r
952         for( xPhyIndex = 0; xPhyIndex < xPhyCount; xPhyIndex++ )\r
953         {\r
954                 FreeRTOS_printf( ( "PHY[%d] at address %d ( 0x%08X )\n",\r
955                         xPhyIndex,\r
956                         xPhyObject.ucPhyIndexes[ xPhyIndex ],\r
957                         xPhyObject.ulPhyIDs[ xPhyIndex ] ) );\r
958 \r
959         }\r
960         \r
961 }\r
962 \r
963 void vMACBProbePhy( void )\r
964 {\r
965         vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );\r
966         xPhyDiscover( &xPhyObject );\r
967         xPhyConfigure( &xPhyObject, &xPHYProperties );\r
968 }\r
969 /*-----------------------------------------------------------*/\r
970 \r
971 static void prvEthernetUpdateConfig( BaseType_t xForce )\r
972 {\r
973         FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n",\r
974                 xPhyObject.ulLinkStatusMask,\r
975                 ( int )xForce ) );\r
976 \r
977         if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )\r
978         {\r
979                 /* Restart the auto-negotiation. */\r
980                 if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )\r
981                 {\r
982                         xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );\r
983 \r
984                         /* Configure the MAC with the Duplex Mode fixed by the\r
985                         auto-negotiation process. */\r
986                         if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )\r
987                         {\r
988                                 xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
989                         }\r
990                         else\r
991                         {\r
992                                 xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;\r
993                         }\r
994 \r
995                         /* Configure the MAC with the speed fixed by the\r
996                         auto-negotiation process. */\r
997                         if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )\r
998                         {\r
999                                 xETH.Init.Speed = ETH_SPEED_10M;\r
1000                         }\r
1001                         else\r
1002                         {\r
1003                                 xETH.Init.Speed = ETH_SPEED_100M;\r
1004                         }\r
1005                 }\r
1006                 else /* AutoNegotiation Disable */\r
1007                 {\r
1008                         /* Check parameters */\r
1009                         assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );\r
1010                         assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );\r
1011 \r
1012                         if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX )\r
1013                         {\r
1014                                 xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;\r
1015                         }\r
1016                         else\r
1017                         {\r
1018                                 xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;\r
1019                         }\r
1020 \r
1021                         if( xETH.Init.Speed == ETH_SPEED_10M )\r
1022                         {\r
1023                                 xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;\r
1024                         }\r
1025                         else\r
1026                         {\r
1027                                 xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;\r
1028                         }\r
1029 \r
1030                         xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;\r
1031 \r
1032                         /* Use predefined (fixed) configuration. */\r
1033                         xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );\r
1034                 }\r
1035 \r
1036                 /* ETHERNET MAC Re-Configuration */\r
1037                 HAL_ETH_ConfigMAC( &xETH, (ETH_MACInitTypeDef *) NULL);\r
1038 \r
1039                 /* Restart MAC interface */\r
1040                 HAL_ETH_Start( &xETH);\r
1041         }\r
1042         else\r
1043         {\r
1044                 /* Stop MAC interface */\r
1045                 HAL_ETH_Stop( &xETH );\r
1046         }\r
1047 }\r
1048 /*-----------------------------------------------------------*/\r
1049 \r
1050 BaseType_t xGetPhyLinkStatus( void )\r
1051 {\r
1052 BaseType_t xReturn;\r
1053 \r
1054         if( xPhyObject.ulLinkStatusMask != 0 )\r
1055         {\r
1056                 xReturn = pdPASS;\r
1057         }\r
1058         else\r
1059         {\r
1060                 xReturn = pdFAIL;\r
1061         }\r
1062 \r
1063         return xReturn;\r
1064 }\r
1065 /*-----------------------------------------------------------*/\r
1066 \r
1067 /* Uncomment this in case BufferAllocation_1.c is used. */\r
1068 \r
1069 /*\r
1070 #define niBUFFER_1_PACKET_SIZE          1536\r
1071 \r
1072 static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
1073 \r
1074 void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
1075 {\r
1076 \r
1077 uint8_t *ucRAMBuffer = ucNetworkPackets;\r
1078 uint32_t ul;\r
1079 \r
1080         for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
1081         {\r
1082                 pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
1083                 *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
1084                 ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
1085         }\r
1086 }\r
1087 */\r
1088 /*-----------------------------------------------------------*/\r
1089 \r
1090 static void prvEMACHandlerTask( void *pvParameters )\r
1091 {\r
1092 UBaseType_t uxLastMinBufferCount = 0;\r
1093 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
1094 UBaseType_t uxLastMinQueueSpace = 0;\r
1095 #endif\r
1096 UBaseType_t uxCurrentCount;\r
1097 BaseType_t xResult;\r
1098 const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
1099 \r
1100         /* Remove compiler warnings about unused parameters. */\r
1101         ( void ) pvParameters;\r
1102 \r
1103         for( ;; )\r
1104         {\r
1105                 xResult = 0;\r
1106                 uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
1107                 if( uxLastMinBufferCount != uxCurrentCount )\r
1108                 {\r
1109                         /* The logging produced below may be helpful\r
1110                         while tuning +TCP: see how many buffers are in use. */\r
1111                         uxLastMinBufferCount = uxCurrentCount;\r
1112                         FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
1113                                 uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
1114                 }\r
1115 \r
1116                 if( xTXDescriptorSemaphore != NULL )\r
1117                 {\r
1118                 static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;\r
1119 \r
1120                         uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
1121                         if( uxLowestSemCount > uxCurrentCount )\r
1122                         {\r
1123                                 uxLowestSemCount = uxCurrentCount;\r
1124                                 FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );\r
1125                         }\r
1126 \r
1127                 }\r
1128 \r
1129                 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
1130                 {\r
1131                         uxCurrentCount = uxGetMinimumIPQueueSpace();\r
1132                         if( uxLastMinQueueSpace != uxCurrentCount )\r
1133                         {\r
1134                                 /* The logging produced below may be helpful\r
1135                                 while tuning +TCP: see how many buffers are in use. */\r
1136                                 uxLastMinQueueSpace = uxCurrentCount;\r
1137                                 FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
1138                         }\r
1139                 }\r
1140                 #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
1141 \r
1142                 if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )\r
1143                 {\r
1144                         /* No events to process now, wait for the next. */\r
1145                         ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
1146                 }\r
1147 \r
1148                 if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
1149                 {\r
1150                         ulISREvents &= ~EMAC_IF_RX_EVENT;\r
1151 \r
1152                         xResult = prvNetworkInterfaceInput();\r
1153                         if( xResult > 0 )\r
1154                         {\r
1155                                 while( prvNetworkInterfaceInput() > 0 )\r
1156                                 {\r
1157                                 }\r
1158                         }\r
1159                 }\r
1160 \r
1161                 if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
1162                 {\r
1163                         /* Code to release TX buffers if zero-copy is used. */\r
1164                         ulISREvents &= ~EMAC_IF_TX_EVENT;\r
1165                         /* Check if DMA packets have been delivered. */\r
1166                         vClearTXBuffers();\r
1167                 }\r
1168 \r
1169                 if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
1170                 {\r
1171                         /* Future extension: logging about errors that occurred. */\r
1172                         ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
1173                 }\r
1174                 if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )\r
1175                 {\r
1176                         /* Something has changed to a Link Status, need re-check. */\r
1177                         prvEthernetUpdateConfig( pdFALSE );\r
1178                 }\r
1179         }\r
1180 }\r
1181 /*-----------------------------------------------------------*/\r
1182 \r
1183 void ETH_IRQHandler( void )\r
1184 {\r
1185         HAL_ETH_IRQHandler( &xETH );\r
1186 }\r
1187 \r