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