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