]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/pic32mzef/NetworkInterface_eth.c
Sync FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP with the version in GitHub at (23665258ca...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / pic32mzef / NetworkInterface_eth.c
1 /*******************************************************************************\r
2 *  Network Interface file\r
3 *\r
4 *  Summary:\r
5 *   Network Interface file for FreeRTOS-Plus-TCP stack\r
6 *\r
7 *  Description:\r
8 *   - Interfaces PIC32 to the FreeRTOS TCP/IP stack\r
9 *******************************************************************************/\r
10 \r
11 /*******************************************************************************\r
12 *  File Name:  pic32_NetworkInterface.c\r
13 *  Copyright 2017 Microchip Technology Incorporated and its subsidiaries.\r
14 *\r
15 *  Permission is hereby granted, free of charge, to any person obtaining a copy of\r
16 *  this software and associated documentation files (the "Software"), to deal in\r
17 *  the Software without restriction, including without limitation the rights to\r
18 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\r
19 *  of the Software, and to permit persons to whom the Software is furnished to do\r
20 *  so, subject to the following conditions:\r
21 *  The above copyright notice and this permission notice shall be included in all\r
22 *  copies or substantial portions of the Software.\r
23 *\r
24 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
25 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
26 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
27 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
28 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
29 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
30 *  SOFTWARE\r
31 *******************************************************************************/\r
32 #include <sys/kmem.h>\r
33 \r
34 #include "FreeRTOS.h"\r
35 #include "semphr.h"\r
36 #include "event_groups.h"\r
37 #include "FreeRTOS_IP.h"\r
38 #include "FreeRTOS_IP_Private.h"\r
39 \r
40 #include "NetworkInterface.h"\r
41 #include "NetworkBufferManagement.h"\r
42 \r
43 \r
44 #include "NetworkInterface.h"\r
45 #include "NetworkConfig.h"\r
46 \r
47 #include "peripheral/eth/plib_eth.h"\r
48 \r
49 #include "system_config.h"\r
50 #include "system/console/sys_console.h"\r
51 #include "system/debug/sys_debug.h"\r
52 #include "system/command/sys_command.h"\r
53 \r
54 #include "driver/ethmac/drv_ethmac.h"\r
55 #include "driver/miim/drv_miim.h"\r
56 \r
57 #include "tcpip/tcpip.h"\r
58 #include "tcpip/src/tcpip_private.h"\r
59 #include "tcpip/src/link_list.h"\r
60 \r
61 #ifdef PIC32_USE_ETHERNET\r
62 \r
63     /* local definitions and data */\r
64 \r
65     /* debug messages */\r
66     #if ( PIC32_MAC_DEBUG_MESSAGES != 0 )\r
67         #define PIC32_MAC_DbgPrint( format, ... )    SYS_CONSOLE_PRINT( format, ## __VA_ARGS__ )\r
68     #else\r
69         #define PIC32_MAC_DbgPrint( format, ... )\r
70     #endif /* (PIC32_MAC_DEBUG_MESSAGES != 0) */\r
71 \r
72     typedef enum\r
73     {\r
74         PIC32_MAC_EVENT_INIT_NONE = 0x000,      /* no event/invalid */\r
75 \r
76         PIC32_MAC_EVENT_INIT_DONE = 0x001,      /* initialization done event */\r
77         PIC32_MAC_EVENT_TIMEOUT = 0x002,        /* periodic timeout event */\r
78         PIC32_MAC_EVENT_IF_PENDING = 0x004,     /* an interface event signal: RX, TX, errors. etc. */\r
79     } PIC32_MAC_EVENT_TYPE;\r
80 \r
81     typedef enum\r
82     {\r
83         eMACInit,                               /* Must initialise MAC. */\r
84         eMACPass,                               /* Initialisation was successful. */\r
85         eMACFailed,                             /* Initialisation failed. */\r
86     } eMAC_INIT_STATUS_TYPE;\r
87 \r
88     static TCPIP_STACK_HEAP_HANDLE macHeapHandle;\r
89 \r
90     static const TCPIP_MAC_OBJECT * macObject; /* the one and only MAC object; */\r
91 \r
92     static SYS_MODULE_OBJ macObjHandle;        /* the MAC object instance, obtained at initialization */\r
93     static TCPIP_MAC_HANDLE macCliHandle;      /* client handle */\r
94     static volatile SYS_STATUS macObjStatus;   /* current MAC status */\r
95 \r
96     static TaskHandle_t macTaskHandle;\r
97 \r
98     static TimerHandle_t macTmrHandle;\r
99 \r
100     static bool macLinkStatus;              /* true if link is ON */\r
101 \r
102     static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;\r
103 \r
104     /* local prototypes */\r
105     static bool StartInitMac( void );\r
106     static void StartInitCleanup( void );\r
107 \r
108     static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl );\r
109 \r
110     static bool MacSyncFunction( void * synchHandle,\r
111                                  TCPIP_MAC_SYNCH_REQUEST req );\r
112 \r
113     /* the PIC32 MAC task function */\r
114     static void MacHandlerTask( void * params );\r
115 \r
116     /* MAC interrupt event function */\r
117     static void MAC_EventFunction( TCPIP_MAC_EVENT event,\r
118                                    const void * eventParam );\r
119 \r
120     /* timer callback for link maintenance, etc; */\r
121     static void MacTmrCallback( TimerHandle_t xTimer );\r
122 \r
123     /* MAC RX packets functions */\r
124     static void MacRxPackets( void );\r
125     static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt );\r
126 \r
127 \r
128     /* memory allocation mapping to FreeRTOS */\r
129     static void * _malloc( size_t nBytes )\r
130     {\r
131         return pvPortMalloc( nBytes );\r
132     }\r
133 \r
134     /*-----------------------------------------------------------*/\r
135 \r
136     static void * _calloc( size_t nElems,\r
137                            size_t elemSize )\r
138     {\r
139         size_t nBytes = nElems * elemSize;\r
140 \r
141         void * ptr = pvPortMalloc( nBytes );\r
142 \r
143         if( ptr != 0 )\r
144         {\r
145             memset( ptr, 0, nBytes );\r
146         }\r
147 \r
148         return ptr;\r
149     }\r
150 \r
151     /*-----------------------------------------------------------*/\r
152 \r
153     static void _free( void * pBuff )\r
154     {\r
155         vPortFree( pBuff );\r
156     }\r
157 \r
158     /* extern references */\r
159     /* */\r
160     /* use the configuration data from the system_init.c */\r
161     extern const TCPIP_NETWORK_CONFIG TCPIP_HOSTS_CONFIGURATION[];\r
162 \r
163     /* BufferAllocation_2.c:: packet allocation function */\r
164     extern TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,\r
165                                                        uint16_t segLoadLen,\r
166                                                        TCPIP_MAC_PACKET_FLAGS flags );\r
167 \r
168     extern void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,\r
169                                     NetworkBufferDescriptor_t * pxBufferDescriptor,\r
170                                     size_t pktLength );\r
171     extern void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt );\r
172 \r
173     /* cannot use the system_init.c::tcpipHeapConfig because FreeRTOS does not have a calloc function! */\r
174     /* we build it here! */\r
175 \r
176     /* make sure we're running with external heap! Redirect to FreeRTOS. */\r
177     #if !defined( TCPIP_STACK_USE_EXTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP_POOL )\r
178         #error "TCPIP_STACK_USE_EXTERNAL_HEAP should be defined for this project!"\r
179     #endif\r
180 \r
181     static const TCPIP_STACK_HEAP_EXTERNAL_CONFIG tcpipHeapConfig =\r
182     {\r
183         .heapType   = TCPIP_STACK_HEAP_TYPE_EXTERNAL_HEAP,\r
184         .heapFlags  = TCPIP_STACK_HEAP_FLAG_ALLOC_UNCACHED | TCPIP_STACK_HEAP_FLAG_NO_MTHREAD_SYNC,\r
185         .heapUsage  = TCPIP_STACK_HEAP_USE_DEFAULT,\r
186         .malloc_fnc = _malloc,\r
187         .calloc_fnc = _calloc,\r
188         .free_fnc   = _free,\r
189     };\r
190 \r
191     #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
192         static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
193                                      int argc,\r
194                                      char ** argv );\r
195         static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
196                                      int argc,\r
197                                      char ** argv );\r
198         static int _Command_Version( SYS_CMD_DEVICE_NODE * pCmdIO,\r
199                                      int argc,\r
200                                      char ** argv );\r
201 \r
202         static const SYS_CMD_DESCRIPTOR macCmdTbl[] =\r
203         {\r
204             { "macinfo", _Command_MacInfo, ": Check MAC statistics" },\r
205             { "netinfo", _Command_NetInfo, ": Net info" },\r
206             { "version", _Command_Version, ": Version info" },\r
207         };\r
208     #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
209 \r
210 \r
211     /* FreeRTOS implementation functions */\r
212     BaseType_t xNetworkInterfaceInitialise( void )\r
213     {\r
214     BaseType_t xResult;\r
215 \r
216         if( xMacInitStatus == eMACInit )\r
217         {\r
218                         /* This is the first time this function is called. */\r
219             if( StartInitMac() != false )\r
220             {\r
221                 /* Indicate that the MAC initialisation succeeded. */\r
222                 xMacInitStatus = eMACPass;\r
223             }\r
224             else\r
225             {\r
226                 xMacInitStatus = eMACFailed;\r
227             }\r
228         }\r
229 \r
230         if( xMacInitStatus == eMACPass )\r
231         {\r
232             xResult = xGetPhyLinkStatus();\r
233         }\r
234         else\r
235         {\r
236             xResult = pdFAIL;\r
237         }\r
238 \r
239         PIC32_MAC_DbgPrint( "xNetworkInterfaceInitialise: %d %d\r\n", ( int ) xMacInitStatus, ( int ) xResult );\r
240 \r
241         return xResult;\r
242     }\r
243 \r
244 \r
245     /*-----------------------------------------------------------*/\r
246 \r
247     BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,\r
248                                         BaseType_t xReleaseAfterSend )\r
249     {\r
250         TCPIP_MAC_RES macRes;\r
251         TCPIP_MAC_PACKET * pTxPkt;\r
252 \r
253         BaseType_t retRes = pdFALSE;\r
254 \r
255 \r
256         if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )\r
257         {\r
258             TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pxDescriptor->pucEthernetBuffer - PIC32_BUFFER_PKT_PTR_OSSET );\r
259             configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
260             pTxPkt = *ppkt;\r
261             configASSERT( pTxPkt != 0 );\r
262 \r
263             /* prepare the packet for transmission */\r
264             /* set the correct data length: */\r
265             configASSERT( pTxPkt->pDSeg->segSize >= pTxPkt->pDSeg->segLen );\r
266             pTxPkt->pDSeg->segLen = pxDescriptor->xDataLength;\r
267             pTxPkt->next = 0; /* unlink it */\r
268             macRes = ( macObject->TCPIP_MAC_PacketTx )( macCliHandle, pTxPkt );\r
269 \r
270             if( macRes >= 0 )\r
271             {\r
272                 retRes = pdTRUE;\r
273                 pxDescriptor->pucEthernetBuffer = 0; /* it will be released by the MAC driver once it's transmitted */\r
274                 iptraceNETWORK_INTERFACE_TRANSMIT();\r
275             }\r
276 \r
277             /* else same error occurred; this normally should not happen! But the buffer is left in there so it shold be freed! */\r
278 \r
279             /* The buffer has been sent so can be released. */\r
280             if( xReleaseAfterSend != pdFALSE )\r
281             {\r
282                 vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
283             }\r
284         }\r
285 \r
286         return retRes;\r
287     }\r
288 \r
289 \r
290     /************************************* Section: helper functions ************************************************** */\r
291     /* */\r
292 \r
293     void PIC32_GetMACAddress( uint8_t macAdd[ 6 ] )\r
294     {\r
295         #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )\r
296             PLIB_ETH_MACGetAddress( ETH_ID_0, macAdd );\r
297         #else\r
298         #error "MAC Address: not supported architecture!"\r
299         #endif\r
300     }\r
301 \r
302 \r
303     /*-----------------------------------------------------------*/\r
304 \r
305     const void * const PIC32_GetMacConfigData( void )\r
306     {\r
307         #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )\r
308             extern const TCPIP_MODULE_MAC_PIC32INT_CONFIG tcpipMACPIC32INTInitData;\r
309 \r
310             return &tcpipMACPIC32INTInitData;\r
311         #else\r
312         #error "MAC Address: not supported architecture!"\r
313         #endif\r
314     }\r
315 \r
316     /************************************* Section: worker code ************************************************** */\r
317     /* */\r
318 \r
319 \r
320     static bool StartInitMac( void )\r
321     {\r
322         TCPIP_MAC_MODULE_CTRL macCtrl;\r
323         SYS_MODULE_INIT moduleInit;\r
324         EventBits_t evBits;\r
325 \r
326 \r
327         /* perform some initialization of all variables so that we can cleanup what failed */\r
328         /* if something failed, the routine will be called again and again by FreeRTOS! */\r
329         macHeapHandle = 0;\r
330         macObjHandle = 0;\r
331         macCliHandle = 0;\r
332         macTmrHandle = 0;\r
333         macTaskHandle = 0;\r
334         macObject = TCPIP_HOSTS_CONFIGURATION[ 0 ].pMacObject; /* the MAC object we use */\r
335         macObjStatus = SYS_STATUS_UNINITIALIZED;\r
336         macLinkStatus = false;\r
337 \r
338         int netUpFail = 0;\r
339 \r
340         while( true )\r
341         {\r
342             /* start the allocator */\r
343             macHeapHandle = TCPIP_HEAP_Create( ( const TCPIP_STACK_HEAP_CONFIG * ) &tcpipHeapConfig, 0 );\r
344 \r
345             if( macHeapHandle == 0 )\r
346             {\r
347                 netUpFail = 1;\r
348                 break;\r
349             }\r
350 \r
351             if( TCPIP_PKT_Initialize( macHeapHandle, 0, 0 ) == false )\r
352             {\r
353                 netUpFail = 2;\r
354                 break;\r
355             }\r
356 \r
357             moduleInit.sys.powerState = SYS_MODULE_POWER_RUN_FULL;\r
358 \r
359             /* Initialize the MAC. MAC address is defined to 0x000000000000 in\r
360              * FreeRTOSConfig.h and therefore it will be initialized to the\r
361              * factory programmed MAC address. */\r
362             SetMacCtrl( &macCtrl );\r
363             /* Set the mac address in the FreeRTOS+TCP stack. */\r
364             FreeRTOS_UpdateMACAddress( macCtrl.ifPhyAddress.v );\r
365 \r
366             TCPIP_MAC_INIT macInit =\r
367             {\r
368                 .moduleInit = { moduleInit.value },\r
369                 .macControl = &macCtrl,\r
370                 .moduleData = PIC32_GetMacConfigData(),\r
371             };\r
372 \r
373             macObjHandle = ( macObject->TCPIP_MAC_Initialize )( TCPIP_MODULE_MAC_PIC32INT, &macInit.moduleInit );\r
374 \r
375             if( macObjHandle == SYS_MODULE_OBJ_INVALID )\r
376             {\r
377                 macObjHandle = 0;\r
378                 netUpFail = 4;\r
379                 break;\r
380             }\r
381 \r
382             /* open the MAC */\r
383             macCliHandle = ( macObject->TCPIP_MAC_Open )( TCPIP_MODULE_MAC_PIC32INT, DRV_IO_INTENT_READWRITE );\r
384 \r
385             if( macCliHandle == DRV_HANDLE_INVALID )\r
386             {\r
387                 macCliHandle = 0;\r
388                 netUpFail = 5;\r
389                 break;\r
390             }\r
391 \r
392             if( !( macObject->TCPIP_MAC_EventMaskSet )( macCliHandle, ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ), true ) )\r
393             {\r
394                 netUpFail = 6;\r
395                 break;\r
396             }\r
397 \r
398             /* completed the MAC initialization */\r
399             /* continue the initialization */\r
400             macTmrHandle = xTimerCreate( PIC32_MAC_TIMER_NAME, PIC32_MAC_TIMER_PERIOD, pdTRUE, 0, MacTmrCallback );\r
401 \r
402             if( ( macTmrHandle == 0 ) || ( xTimerStart( macTmrHandle, 0 ) != pdPASS ) )\r
403             {\r
404                 netUpFail = 8;\r
405                 break;\r
406             }\r
407 \r
408             /* spawn the PIC32 MAC task function */\r
409             /* and wait for its event signal */\r
410             macObjStatus = SYS_STATUS_BUSY;\r
411 \r
412             if( xTaskCreate( MacHandlerTask, PIC32_MAC_TASK_NAME, PIC32_MAC_TASK_STACK_SIZE, xTaskGetCurrentTaskHandle(), PIC32_MAC_TASK_PRI, &macTaskHandle ) != pdPASS )\r
413             { /* failed */\r
414                 netUpFail = 9;\r
415                 break;\r
416             }\r
417 \r
418             xTaskNotifyWait( PIC32_MAC_EVENT_INIT_DONE, PIC32_MAC_EVENT_INIT_DONE, &evBits, PIC32_MAC_INIT_TIMEOUT );\r
419 \r
420             if( ( evBits & PIC32_MAC_EVENT_INIT_DONE ) == 0 )\r
421             { /* timed out */\r
422                 netUpFail = 10;\r
423                 break;\r
424             }\r
425 \r
426             if( macObjStatus != SYS_STATUS_READY )\r
427             { /* failed somehow ??? */\r
428                 netUpFail = 11;\r
429                 break;\r
430             }\r
431 \r
432             netUpFail = 0;\r
433             break;\r
434         }\r
435 \r
436         if( netUpFail == 0 )\r
437         {\r
438             PIC32_MAC_DbgPrint( " MAC Init success!\r\n" );\r
439 \r
440             #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
441                 /* create command group */\r
442                 if( !SYS_CMD_ADDGRP( macCmdTbl, sizeof( macCmdTbl ) / sizeof( *macCmdTbl ), "mac", ": mac commands" ) )\r
443                 {\r
444                     PIC32_MAC_DbgPrint( "Failed to create MAC Commands\r\n" );\r
445                 }\r
446             #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
447 \r
448             return true;\r
449         }\r
450         else\r
451         {\r
452             StartInitCleanup();\r
453             PIC32_MAC_DbgPrint( "MAC Init failed: %d!\r\n", netUpFail );\r
454 \r
455             return false;\r
456         }\r
457     }\r
458 \r
459     /*-----------------------------------------------------------*/\r
460 \r
461     static void StartInitCleanup( void )\r
462     {\r
463         if( macHeapHandle != 0 )\r
464         {\r
465             TCPIP_HEAP_Delete( macHeapHandle );\r
466             macHeapHandle = 0;\r
467         }\r
468 \r
469         if( macObjHandle != 0 )\r
470         {\r
471             ( macObject->TCPIP_MAC_Deinitialize )( macObjHandle );\r
472             macObjHandle = 0;\r
473         }\r
474 \r
475         if( macTmrHandle != 0 )\r
476         {\r
477             xTimerDelete( macTmrHandle, portMAX_DELAY );\r
478             macTmrHandle = 0;\r
479         }\r
480 \r
481         if( macTaskHandle != 0 )\r
482         {\r
483             vTaskDelete( macTaskHandle );\r
484             macTaskHandle = 0;\r
485         }\r
486     }\r
487 \r
488     /*-----------------------------------------------------------*/\r
489 \r
490     static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl )\r
491     {\r
492         TCPIP_MAC_ADDR macAdd;\r
493         uint8_t unsetMACAddr[ 6 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };     /* not set MAC address */\r
494 \r
495         pMacCtrl->nIfs = 1;\r
496 \r
497         pMacCtrl->mallocF = TCPIP_HEAP_MallocOutline;\r
498         pMacCtrl->callocF = TCPIP_HEAP_CallocOutline;\r
499         pMacCtrl->freeF = TCPIP_HEAP_FreeOutline;\r
500         pMacCtrl->memH = macHeapHandle;\r
501 \r
502 \r
503         pMacCtrl->pktAllocF = PIC32_MacPacketAllocate;\r
504         pMacCtrl->pktFreeF = ( TCPIP_MAC_PKT_FreeF ) _TCPIP_PKT_FREE_FNC;\r
505         pMacCtrl->pktAckF = ( TCPIP_MAC_PKT_AckF ) _TCPIP_PKT_ACK_FNC;\r
506 \r
507         pMacCtrl->synchF = MacSyncFunction;\r
508 \r
509         pMacCtrl->eventF = MAC_EventFunction;\r
510         pMacCtrl->eventParam = 0;\r
511 \r
512         pMacCtrl->moduleId = TCPIP_MODULE_MAC_PIC32INT;\r
513         pMacCtrl->netIx = 0;\r
514         pMacCtrl->macAction = TCPIP_MAC_ACTION_INIT;\r
515         pMacCtrl->powerMode = TCPIP_MAC_POWER_FULL;\r
516 \r
517         macAdd.v[ 0 ] = configMAC_ADDR0;\r
518         macAdd.v[ 1 ] = configMAC_ADDR1;\r
519         macAdd.v[ 2 ] = configMAC_ADDR2;\r
520         macAdd.v[ 3 ] = configMAC_ADDR3;\r
521         macAdd.v[ 4 ] = configMAC_ADDR4;\r
522         macAdd.v[ 5 ] = configMAC_ADDR5;\r
523 \r
524         if( memcmp( macAdd.v, unsetMACAddr, sizeof( unsetMACAddr ) ) == 0 )\r
525         { /* if unspecified we use the factory pre-programmed address */\r
526             PIC32_GetMACAddress( pMacCtrl->ifPhyAddress.v );\r
527         }\r
528         else\r
529         { /* use the config suggested one */\r
530             memcpy( pMacCtrl->ifPhyAddress.v, macAdd.v, sizeof( macAdd ) );\r
531         }\r
532     }\r
533 \r
534     /*-----------------------------------------------------------*/\r
535 \r
536     static bool MacSyncFunction( void * synchHandle,\r
537                                  TCPIP_MAC_SYNCH_REQUEST req )\r
538     {\r
539         switch( req )\r
540         {\r
541             case TCPIP_MAC_SYNCH_REQUEST_OBJ_CREATE:\r
542                 vSemaphoreCreateBinary( *( SemaphoreHandle_t * ) synchHandle );\r
543 \r
544                 return ( *( SemaphoreHandle_t * ) synchHandle == NULL ) ? false : true;\r
545 \r
546             case TCPIP_MAC_SYNCH_REQUEST_OBJ_DELETE:\r
547                 vSemaphoreDelete( *( SemaphoreHandle_t * ) synchHandle );\r
548                 *( SemaphoreHandle_t * ) synchHandle = NULL;\r
549 \r
550                 return true;\r
551 \r
552             case TCPIP_MAC_SYNCH_REQUEST_OBJ_LOCK:\r
553 \r
554                 return ( xSemaphoreTake( *( SemaphoreHandle_t * ) synchHandle, portMAX_DELAY ) == pdTRUE ) ? true : false;\r
555 \r
556             case TCPIP_MAC_SYNCH_REQUEST_OBJ_UNLOCK:\r
557 \r
558                 return ( xSemaphoreGive( *( SemaphoreHandle_t * ) synchHandle ) == pdTRUE ) ? true : false;\r
559 \r
560             case TCPIP_MAC_SYNCH_REQUEST_CRIT_ENTER:\r
561                 vTaskSuspendAll();\r
562 \r
563                 return true;\r
564 \r
565             case TCPIP_MAC_SYNCH_REQUEST_CRIT_LEAVE:\r
566                 xTaskResumeAll();\r
567 \r
568                 return true;\r
569 \r
570             default:\r
571 \r
572                 return false;\r
573         }\r
574     }\r
575 \r
576 \r
577     /*-----------------------------------------------------------*/\r
578 \r
579     static void MacHandlerTask( void * params )\r
580     {\r
581         EventBits_t evBits;\r
582 \r
583         /* perform the MAC initialization */\r
584         while( macObjStatus == SYS_STATUS_BUSY )\r
585         {\r
586             /* process the underlying MAC module tasks */\r
587             ( macObject->TCPIP_MAC_Tasks )( macObjHandle );\r
588 \r
589             SYS_STATUS macStatus = ( macObject->TCPIP_MAC_Status )( macObjHandle );\r
590 \r
591             if( macStatus == SYS_STATUS_BUSY )\r
592             { /* still pending */\r
593                 vTaskDelay( PIC32_MAC_TASK_INIT_PENDING_DELAY );\r
594             }\r
595             else\r
596             { /* completed ...somehow */\r
597                 macObjStatus = macStatus;\r
598 \r
599                 xTaskNotify( ( TaskHandle_t ) params, PIC32_MAC_EVENT_INIT_DONE, eSetBits );\r
600 \r
601                 if( macStatus != SYS_STATUS_READY )\r
602                 { /* failed miserably */\r
603                     vTaskDelete( 0 );\r
604                 }\r
605 \r
606                 /* done, up and running */\r
607             }\r
608         }\r
609 \r
610         while( true )\r
611         {\r
612             xTaskNotifyWait( PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, &evBits, portMAX_DELAY );\r
613 \r
614             if( ( evBits & PIC32_MAC_EVENT_TIMEOUT ) != 0 )\r
615             {                                                                       /* timeout occurred... */\r
616                 ( macObject->TCPIP_MAC_Tasks )( macObjHandle );\r
617                 bool linkCurr = ( macObject->TCPIP_MAC_LinkCheck )( macCliHandle ); /* check link status */\r
618 \r
619                 if( macLinkStatus != linkCurr )\r
620                 { /* link status changed; some event could ve fired here if needed */\r
621                     PIC32_MAC_DbgPrint( " MAC link: %s!\r\n", linkCurr ? "ON" : "OFF" );\r
622                     macLinkStatus = linkCurr;\r
623                 }\r
624             }\r
625 \r
626             if( ( evBits & PIC32_MAC_EVENT_IF_PENDING ) != 0 )\r
627             { /* IF events signal */\r
628                 TCPIP_MAC_EVENT activeEvents = ( macObject->TCPIP_MAC_EventPendingGet )( macCliHandle );\r
629 \r
630                 if( activeEvents != TCPIP_MAC_EV_NONE )\r
631                 {\r
632                     /* acknowledge the events */\r
633                     ( macObject->TCPIP_MAC_EventAcknowledge )( macCliHandle, activeEvents );\r
634 \r
635                     /* check for RX */\r
636                     if( ( activeEvents & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_RX_OVFLOW | TCPIP_MAC_EV_RX_BUFNA ) ) != 0 )\r
637                     { /* RX packets available */\r
638                         MacRxPackets();\r
639                     }\r
640 \r
641                     /* call the driver process function; */\r
642                     /* PIC32 driver requests it through TCPIP_MAC_ParametersGet() which is bypassed here! */\r
643                     ( macObject->TCPIP_MAC_Process )( macCliHandle );\r
644                 }\r
645             }\r
646 \r
647             /* do what you have to do and then wait for another event... */\r
648         }\r
649     }\r
650 \r
651     /*-----------------------------------------------------------*/\r
652 \r
653     static void MacTmrCallback( TimerHandle_t xTimer )\r
654     {\r
655         xTaskNotify( macTaskHandle, PIC32_MAC_EVENT_TIMEOUT, eSetBits );\r
656     }\r
657 \r
658     /* MAC interrupt event function */\r
659     /* MAC signals an event, probably from within ISR */\r
660     /* we care just for RX related events */\r
661     static void MAC_EventFunction( TCPIP_MAC_EVENT event,\r
662                                    const void * eventParam )\r
663     {\r
664         BaseType_t xHigherPriorityTaskWoken;\r
665 \r
666         if( ( event & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ) ) != 0 )\r
667         {\r
668             xHigherPriorityTaskWoken = pdFALSE;\r
669             xTaskNotifyFromISR( macTaskHandle, PIC32_MAC_EVENT_IF_PENDING, eSetBits, &xHigherPriorityTaskWoken );\r
670 \r
671             if( xHigherPriorityTaskWoken )\r
672             {\r
673                 portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
674             }\r
675         }\r
676     }\r
677 \r
678     /*-----------------------------------------------------------*/\r
679 \r
680     BaseType_t xGetPhyLinkStatus( void )\r
681     {\r
682         return macLinkStatus == true ? pdPASS : pdFAIL;\r
683     }\r
684 \r
685 \r
686     /* receive packets from the MAC driver */\r
687     static void MacRxPackets( void )\r
688     {\r
689         TCPIP_MAC_PACKET * pRxPkt;\r
690 \r
691         /* get all the new MAC packets */\r
692         while( ( pRxPkt = ( macObject->TCPIP_MAC_PacketRx )( macCliHandle, 0, 0 ) ) != 0 )\r
693         {\r
694             MacProcessRxPacket( pRxPkt );\r
695         }\r
696     }\r
697 \r
698     /*-----------------------------------------------------------*/\r
699 \r
700     static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt )\r
701     {\r
702         bool pktSuccess, pktLost;\r
703         size_t pktLength;\r
704         TCPIP_MAC_DATA_SEGMENT * pSeg;\r
705         uint8_t * pPktBuff;\r
706         NetworkBufferDescriptor_t * pxBufferDescriptor;\r
707         IPStackEvent_t xRxEvent;\r
708 \r
709         pxBufferDescriptor = 0;\r
710         pktSuccess = pktLost = false;\r
711 \r
712         while( true )\r
713         {\r
714             pktLength = 0;\r
715             int nSegs = 0;\r
716             pSeg = pRxPkt->pDSeg;\r
717             pPktBuff = pSeg->segLoad;\r
718 \r
719             /* calculate the packet size */\r
720             do\r
721             {\r
722                 pktLength += pSeg->segLen;\r
723                 pSeg = pSeg->next;\r
724                 nSegs++;\r
725             } while( pSeg != 0 );\r
726 \r
727             if( nSegs > 1 )\r
728             { /* no support in FreeRTOS for multi segment packets! */\r
729                 break;\r
730             }\r
731 \r
732             /* sizeof(TCPIP_MAC_ETHERNET_HEADER) is subtracted by the driver */\r
733             /* but FreeRTOS needs the whole frame! */\r
734             pktLength += sizeof( TCPIP_MAC_ETHERNET_HEADER );\r
735 \r
736             if( eConsiderFrameForProcessing( pPktBuff ) != eProcessBuffer )\r
737             {\r
738                 break;\r
739             }\r
740 \r
741             /* get the network descriptor (no data buffer) to hold this packet */\r
742             pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( 0, 0 );\r
743 \r
744             if( pxBufferDescriptor == 0 )\r
745             {\r
746                 pktLost = true;\r
747                 break;\r
748             }\r
749 \r
750             PIC32_MacAssociate( pRxPkt, pxBufferDescriptor, pktLength );\r
751 \r
752             xRxEvent.eEventType = eNetworkRxEvent;\r
753             xRxEvent.pvData = ( void * ) pxBufferDescriptor;\r
754 \r
755             /* Send the data to the TCP/IP stack */\r
756             if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
757             { /* failed */\r
758                 pktLost = true;\r
759             }\r
760             else\r
761             { /* success */\r
762                 pktSuccess = true;\r
763                 iptraceNETWORK_INTERFACE_RECEIVE();\r
764             }\r
765 \r
766             break;\r
767         }\r
768 \r
769         if( !pktSuccess )\r
770         { /* smth went wrong; nothing sent to the */\r
771             if( pxBufferDescriptor != 0 )\r
772             {\r
773                 pxBufferDescriptor->pucEthernetBuffer = 0;\r
774                 vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
775             }\r
776 \r
777             if( pktLost )\r
778             {\r
779                 iptraceETHERNET_RX_EVENT_LOST();\r
780             }\r
781 \r
782             /* acknowledge the packet to the MAC driver */\r
783             if( pRxPkt->ackFunc )\r
784             {\r
785                 ( *pRxPkt->ackFunc )( pRxPkt, pRxPkt->ackParam );\r
786             }\r
787             else\r
788             {\r
789                 PIC32_MacPacketOrphan( pRxPkt );\r
790             }\r
791         }\r
792     }\r
793 \r
794     #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
795         /* */\r
796         static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
797                                      int argc,\r
798                                      char ** argv )\r
799         {\r
800             TCPIP_MAC_RES macRes;\r
801             TCPIP_MAC_RX_STATISTICS rxStatistics;\r
802             TCPIP_MAC_TX_STATISTICS txStatistics;\r
803             TCPIP_MAC_STATISTICS_REG_ENTRY regEntries[ 8 ];\r
804             TCPIP_MAC_STATISTICS_REG_ENTRY * pRegEntry;\r
805             int jx, hwEntries;\r
806             char entryName[ sizeof( pRegEntry->registerName ) + 1 ];\r
807 \r
808             const void * cmdIoParam = pCmdIO->cmdIoParam;\r
809 \r
810             if( argc != 1 )\r
811             {\r
812                 ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Usage: macinfo \r\n" );\r
813                 ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Ex: macinfo \r\n" );\r
814 \r
815                 return false;\r
816             }\r
817 \r
818             ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s driver statistics\r\n", macObject->macName );\r
819             macRes = ( macObject->TCPIP_MAC_StatisticsGet )( macCliHandle, &rxStatistics, &txStatistics );\r
820 \r
821             if( macRes == TCPIP_MAC_RES_OK )\r
822             {\r
823                 ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnRxOkPackets: %d, nRxPendBuffers: %d, nRxSchedBuffers: %d, ",\r
824                                              rxStatistics.nRxOkPackets, rxStatistics.nRxPendBuffers, rxStatistics.nRxSchedBuffers );\r
825                 ( *pCmdIO->pCmdApi->print )( cmdIoParam, "nRxErrorPackets: %d, nRxFragmentErrors: %d\r\n", rxStatistics.nRxErrorPackets, rxStatistics.nRxFragmentErrors );\r
826                 ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnTxOkPackets: %d, nTxPendBuffers: %d, nTxErrorPackets: %d, nTxQueueFull: %d\r\n",\r
827                                              txStatistics.nTxOkPackets, txStatistics.nTxPendBuffers, txStatistics.nTxErrorPackets, txStatistics.nTxQueueFull );\r
828             }\r
829             else\r
830             {\r
831                 ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );\r
832             }\r
833 \r
834             ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s hardware statistics\r\n", macObject->macName );\r
835             macRes = ( macObject->TCPIP_MAC_RegisterStatisticsGet )( macCliHandle, regEntries, sizeof( regEntries ) / sizeof( *regEntries ), &hwEntries );\r
836 \r
837             if( macRes == TCPIP_MAC_RES_OK )\r
838             {\r
839                 entryName[ sizeof( entryName ) - 1 ] = 0;\r
840 \r
841                 for( jx = 0, pRegEntry = regEntries; jx < hwEntries && jx < sizeof( regEntries ) / sizeof( *regEntries ); jx++, pRegEntry++ )\r
842                 {\r
843                     strncpy( entryName, pRegEntry->registerName, sizeof( entryName ) - 1 );\r
844                     ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\t%s: 0x%8x\r\n", entryName, pRegEntry->registerValue );\r
845                 }\r
846             }\r
847             else\r
848             {\r
849                 ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );\r
850             }\r
851 \r
852             return true;\r
853         }\r
854 \r
855         /*-----------------------------------------------------------*/\r
856 \r
857         static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
858                                      int argc,\r
859                                      char ** argv )\r
860         {\r
861             const void * cmdIoParam = pCmdIO->cmdIoParam;\r
862 \r
863             union\r
864             {\r
865                 uint32_t ul;\r
866                 uint8_t b[ 4 ];\r
867             }\r
868             sUl;\r
869 \r
870             sUl.ul = FreeRTOS_GetIPAddress();\r
871 \r
872             bool linkUp = FreeRTOS_IsNetworkUp() == pdTRUE;\r
873 \r
874             ( *pCmdIO->pCmdApi->print )( cmdIoParam, "IP address: %d.%d.%d.%d\r\n", sUl.b[ 0 ], sUl.b[ 1 ], sUl.b[ 2 ], sUl.b[ 3 ] );\r
875             ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Link is: %s\r\n", linkUp ? "Up" : "Down" );\r
876 \r
877             return true;\r
878         }\r
879 \r
880 #include "aws_application_version.h"\r
881 \r
882 static int _Command_Version(SYS_CMD_DEVICE_NODE* pCmdIO, int argc, char** argv)\r
883 {\r
884     configPRINTF( ( "App version - maj: %d, min: %d, build: %d\r\n",  xAppFirmwareVersion.u.x.ucMajor, xAppFirmwareVersion.u.x.ucMinor, xAppFirmwareVersion.u.x.usBuild) );\r
885     return 0;\r
886 }\r
887 \r
888     #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
889 #endif /* #ifdef PIC32_USE_ETHERNET */\r