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