]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/pic32mzef/NetworkInterface_eth.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / pic32mzef / NetworkInterface_eth.c
index 1b7584c44cb74813ccc21306360783ed9193ee6d..5fe4438bd2709660bf3d6dbe772b9b4601e3b685 100644 (file)
-/*******************************************************************************\r
-*  Network Interface file\r
-*\r
-*  Summary:\r
-*   Network Interface file for FreeRTOS-Plus-TCP stack\r
-*\r
-*  Description:\r
-*   - Interfaces PIC32 to the FreeRTOS TCP/IP stack\r
-*******************************************************************************/\r
-\r
-/*******************************************************************************\r
-*  File Name:  pic32_NetworkInterface.c\r
-*  Copyright 2017 Microchip Technology Incorporated and its subsidiaries.\r
-*\r
-*  Permission is hereby granted, free of charge, to any person obtaining a copy of\r
-*  this software and associated documentation files (the "Software"), to deal in\r
-*  the Software without restriction, including without limitation the rights to\r
-*  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\r
-*  of the Software, and to permit persons to whom the Software is furnished to do\r
-*  so, subject to the following conditions:\r
-*  The above copyright notice and this permission notice shall be included in all\r
-*  copies or substantial portions of the Software.\r
-*\r
-*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
-*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
-*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
-*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
-*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
-*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
-*  SOFTWARE\r
-*******************************************************************************/\r
-#include <sys/kmem.h>\r
-\r
-#include "FreeRTOS.h"\r
-#include "semphr.h"\r
-#include "event_groups.h"\r
-#include "FreeRTOS_IP.h"\r
-#include "FreeRTOS_IP_Private.h"\r
-\r
-#include "NetworkInterface.h"\r
-#include "NetworkBufferManagement.h"\r
-\r
-\r
-#include "NetworkInterface.h"\r
-#include "NetworkConfig.h"\r
-\r
-#include "peripheral/eth/plib_eth.h"\r
-\r
-#include "system_config.h"\r
-#include "system/console/sys_console.h"\r
-#include "system/debug/sys_debug.h"\r
-#include "system/command/sys_command.h"\r
-\r
-#include "driver/ethmac/drv_ethmac.h"\r
-#include "driver/miim/drv_miim.h"\r
-\r
-#include "tcpip/tcpip.h"\r
-#include "tcpip/src/tcpip_private.h"\r
-#include "tcpip/src/link_list.h"\r
-\r
-#ifdef PIC32_USE_ETHERNET\r
-\r
-    /* local definitions and data */\r
-\r
-    /* debug messages */\r
-    #if ( PIC32_MAC_DEBUG_MESSAGES != 0 )\r
-        #define PIC32_MAC_DbgPrint( format, ... )    SYS_CONSOLE_PRINT( format, ## __VA_ARGS__ )\r
-    #else\r
-        #define PIC32_MAC_DbgPrint( format, ... )\r
-    #endif /* (PIC32_MAC_DEBUG_MESSAGES != 0) */\r
-\r
-    typedef enum\r
-    {\r
-        PIC32_MAC_EVENT_INIT_NONE = 0x000,      /* no event/invalid */\r
-\r
-        PIC32_MAC_EVENT_INIT_DONE = 0x001,      /* initialization done event */\r
-        PIC32_MAC_EVENT_TIMEOUT = 0x002,        /* periodic timeout event */\r
-        PIC32_MAC_EVENT_IF_PENDING = 0x004,     /* an interface event signal: RX, TX, errors. etc. */\r
-    } PIC32_MAC_EVENT_TYPE;\r
-\r
-    typedef enum\r
-    {\r
-        eMACInit,                               /* Must initialise MAC. */\r
-        eMACPass,                               /* Initialisation was successful. */\r
-        eMACFailed,                             /* Initialisation failed. */\r
-    } eMAC_INIT_STATUS_TYPE;\r
-\r
-    static TCPIP_STACK_HEAP_HANDLE macHeapHandle;\r
-\r
-    static const TCPIP_MAC_OBJECT * macObject; /* the one and only MAC object; */\r
-\r
-    static SYS_MODULE_OBJ macObjHandle;        /* the MAC object instance, obtained at initialization */\r
-    static TCPIP_MAC_HANDLE macCliHandle;      /* client handle */\r
-    static volatile SYS_STATUS macObjStatus;   /* current MAC status */\r
-\r
-    static TaskHandle_t macTaskHandle;\r
-\r
-    static TimerHandle_t macTmrHandle;\r
-\r
-    static bool macLinkStatus;              /* true if link is ON */\r
-\r
-    static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;\r
-\r
-    /* local prototypes */\r
-    static bool StartInitMac( void );\r
-    static void StartInitCleanup( void );\r
-\r
-    static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl );\r
-\r
-    static bool MacSyncFunction( void * synchHandle,\r
-                                 TCPIP_MAC_SYNCH_REQUEST req );\r
-\r
-    /* the PIC32 MAC task function */\r
-    static void MacHandlerTask( void * params );\r
-\r
-    /* MAC interrupt event function */\r
-    static void MAC_EventFunction( TCPIP_MAC_EVENT event,\r
-                                   const void * eventParam );\r
-\r
-    /* timer callback for link maintenance, etc; */\r
-    static void MacTmrCallback( TimerHandle_t xTimer );\r
-\r
-    /* MAC RX packets functions */\r
-    static void MacRxPackets( void );\r
-    static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt );\r
-\r
-\r
-    /* memory allocation mapping to FreeRTOS */\r
-    static void * _malloc( size_t nBytes )\r
-    {\r
-        return pvPortMalloc( nBytes );\r
-    }\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    static void * _calloc( size_t nElems,\r
-                           size_t elemSize )\r
-    {\r
-        size_t nBytes = nElems * elemSize;\r
-\r
-        void * ptr = pvPortMalloc( nBytes );\r
-\r
-        if( ptr != 0 )\r
-        {\r
-            memset( ptr, 0, nBytes );\r
-        }\r
-\r
-        return ptr;\r
-    }\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    static void _free( void * pBuff )\r
-    {\r
-        vPortFree( pBuff );\r
-    }\r
-\r
-    /* extern references */\r
-    /* */\r
-    /* use the configuration data from the system_init.c */\r
-    extern const TCPIP_NETWORK_CONFIG TCPIP_HOSTS_CONFIGURATION[];\r
-\r
-    /* BufferAllocation_2.c:: packet allocation function */\r
-    extern TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,\r
-                                                       uint16_t segLoadLen,\r
-                                                       TCPIP_MAC_PACKET_FLAGS flags );\r
-\r
-    extern void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,\r
-                                    NetworkBufferDescriptor_t * pxBufferDescriptor,\r
-                                    size_t pktLength );\r
-    extern void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt );\r
-\r
-    /* cannot use the system_init.c::tcpipHeapConfig because FreeRTOS does not have a calloc function! */\r
-    /* we build it here! */\r
-\r
-    /* make sure we're running with external heap! Redirect to FreeRTOS. */\r
-    #if !defined( TCPIP_STACK_USE_EXTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP_POOL )\r
-        #error "TCPIP_STACK_USE_EXTERNAL_HEAP should be defined for this project!"\r
-    #endif\r
-\r
-    static const TCPIP_STACK_HEAP_EXTERNAL_CONFIG tcpipHeapConfig =\r
-    {\r
-        .heapType   = TCPIP_STACK_HEAP_TYPE_EXTERNAL_HEAP,\r
-        .heapFlags  = TCPIP_STACK_HEAP_FLAG_ALLOC_UNCACHED | TCPIP_STACK_HEAP_FLAG_NO_MTHREAD_SYNC,\r
-        .heapUsage  = TCPIP_STACK_HEAP_USE_DEFAULT,\r
-        .malloc_fnc = _malloc,\r
-        .calloc_fnc = _calloc,\r
-        .free_fnc   = _free,\r
-    };\r
-\r
-    #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
-        static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
-                                     int argc,\r
-                                     char ** argv );\r
-        static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
-                                     int argc,\r
-                                     char ** argv );\r
-        static int _Command_Version( SYS_CMD_DEVICE_NODE * pCmdIO,\r
-                                     int argc,\r
-                                     char ** argv );\r
-\r
-        static const SYS_CMD_DESCRIPTOR macCmdTbl[] =\r
-        {\r
-            { "macinfo", _Command_MacInfo, ": Check MAC statistics" },\r
-            { "netinfo", _Command_NetInfo, ": Net info" },\r
-            { "version", _Command_Version, ": Version info" },\r
-        };\r
-    #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
-\r
-\r
-    /* FreeRTOS implementation functions */\r
-    BaseType_t xNetworkInterfaceInitialise( void )\r
-    {\r
-    BaseType_t xResult;\r
-\r
-        if( xMacInitStatus == eMACInit )\r
-        {\r
-                       /* This is the first time this function is called. */\r
-            if( StartInitMac() != false )\r
-            {\r
-                /* Indicate that the MAC initialisation succeeded. */\r
-                xMacInitStatus = eMACPass;\r
-            }\r
-            else\r
-            {\r
-                xMacInitStatus = eMACFailed;\r
-            }\r
-        }\r
-\r
-        if( xMacInitStatus == eMACPass )\r
-        {\r
-            xResult = xGetPhyLinkStatus();\r
-        }\r
-        else\r
-        {\r
-            xResult = pdFAIL;\r
-        }\r
-\r
-       PIC32_MAC_DbgPrint( "xNetworkInterfaceInitialise: %d %d\r\n", ( int ) xMacInitStatus, ( int ) xResult );\r
-\r
-        return xResult;\r
-    }\r
-\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,\r
-                                        BaseType_t xReleaseAfterSend )\r
-    {\r
-        TCPIP_MAC_RES macRes;\r
-        TCPIP_MAC_PACKET * pTxPkt;\r
-\r
-        BaseType_t retRes = pdFALSE;\r
-\r
-\r
-        if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )\r
-        {\r
-            TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pxDescriptor->pucEthernetBuffer - PIC32_BUFFER_PKT_PTR_OSSET );\r
-            configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
-            pTxPkt = *ppkt;\r
-            configASSERT( pTxPkt != 0 );\r
-\r
-            /* prepare the packet for transmission */\r
-            /* set the correct data length: */\r
-            configASSERT( pTxPkt->pDSeg->segSize >= pTxPkt->pDSeg->segLen );\r
-            pTxPkt->pDSeg->segLen = pxDescriptor->xDataLength;\r
-            pTxPkt->next = 0; /* unlink it */\r
-            macRes = ( macObject->TCPIP_MAC_PacketTx )( macCliHandle, pTxPkt );\r
-\r
-            if( macRes >= 0 )\r
-            {\r
-                retRes = pdTRUE;\r
-                pxDescriptor->pucEthernetBuffer = 0; /* it will be released by the MAC driver once it's transmitted */\r
-                iptraceNETWORK_INTERFACE_TRANSMIT();\r
-            }\r
-\r
-            /* else same error occurred; this normally should not happen! But the buffer is left in there so it shold be freed! */\r
-\r
-            /* The buffer has been sent so can be released. */\r
-            if( xReleaseAfterSend != pdFALSE )\r
-            {\r
-                vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
-            }\r
-        }\r
-\r
-        return retRes;\r
-    }\r
-\r
-\r
-    /************************************* Section: helper functions ************************************************** */\r
-    /* */\r
-\r
-    void PIC32_GetMACAddress( uint8_t macAdd[ 6 ] )\r
-    {\r
-        #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )\r
-            PLIB_ETH_MACGetAddress( ETH_ID_0, macAdd );\r
-        #else\r
-        #error "MAC Address: not supported architecture!"\r
-        #endif\r
-    }\r
-\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    const void * const PIC32_GetMacConfigData( void )\r
-    {\r
-        #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )\r
-            extern const TCPIP_MODULE_MAC_PIC32INT_CONFIG tcpipMACPIC32INTInitData;\r
-\r
-            return &tcpipMACPIC32INTInitData;\r
-        #else\r
-        #error "MAC Address: not supported architecture!"\r
-        #endif\r
-    }\r
-\r
-    /************************************* Section: worker code ************************************************** */\r
-    /* */\r
-\r
-\r
-    static bool StartInitMac( void )\r
-    {\r
-        TCPIP_MAC_MODULE_CTRL macCtrl;\r
-        SYS_MODULE_INIT moduleInit;\r
-        EventBits_t evBits;\r
-\r
-\r
-        /* perform some initialization of all variables so that we can cleanup what failed */\r
-        /* if something failed, the routine will be called again and again by FreeRTOS! */\r
-        macHeapHandle = 0;\r
-        macObjHandle = 0;\r
-        macCliHandle = 0;\r
-        macTmrHandle = 0;\r
-        macTaskHandle = 0;\r
-        macObject = TCPIP_HOSTS_CONFIGURATION[ 0 ].pMacObject; /* the MAC object we use */\r
-        macObjStatus = SYS_STATUS_UNINITIALIZED;\r
-        macLinkStatus = false;\r
-\r
-        int netUpFail = 0;\r
-\r
-        while( true )\r
-        {\r
-            /* start the allocator */\r
-            macHeapHandle = TCPIP_HEAP_Create( ( const TCPIP_STACK_HEAP_CONFIG * ) &tcpipHeapConfig, 0 );\r
-\r
-            if( macHeapHandle == 0 )\r
-            {\r
-                netUpFail = 1;\r
-                break;\r
-            }\r
-\r
-            if( TCPIP_PKT_Initialize( macHeapHandle, 0, 0 ) == false )\r
-            {\r
-                netUpFail = 2;\r
-                break;\r
-            }\r
-\r
-            moduleInit.sys.powerState = SYS_MODULE_POWER_RUN_FULL;\r
-\r
-            /* Initialize the MAC. MAC address is defined to 0x000000000000 in\r
-             * FreeRTOSConfig.h and therefore it will be initialized to the\r
-             * factory programmed MAC address. */\r
-            SetMacCtrl( &macCtrl );\r
-            /* Set the mac address in the FreeRTOS+TCP stack. */\r
-            FreeRTOS_UpdateMACAddress( macCtrl.ifPhyAddress.v );\r
-\r
-            TCPIP_MAC_INIT macInit =\r
-            {\r
-                .moduleInit = { moduleInit.value },\r
-                .macControl = &macCtrl,\r
-                .moduleData = PIC32_GetMacConfigData(),\r
-            };\r
-\r
-            macObjHandle = ( macObject->TCPIP_MAC_Initialize )( TCPIP_MODULE_MAC_PIC32INT, &macInit.moduleInit );\r
-\r
-            if( macObjHandle == SYS_MODULE_OBJ_INVALID )\r
-            {\r
-                macObjHandle = 0;\r
-                netUpFail = 4;\r
-                break;\r
-            }\r
-\r
-            /* open the MAC */\r
-            macCliHandle = ( macObject->TCPIP_MAC_Open )( TCPIP_MODULE_MAC_PIC32INT, DRV_IO_INTENT_READWRITE );\r
-\r
-            if( macCliHandle == DRV_HANDLE_INVALID )\r
-            {\r
-                macCliHandle = 0;\r
-                netUpFail = 5;\r
-                break;\r
-            }\r
-\r
-            if( !( macObject->TCPIP_MAC_EventMaskSet )( macCliHandle, ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ), true ) )\r
-            {\r
-                netUpFail = 6;\r
-                break;\r
-            }\r
-\r
-            /* completed the MAC initialization */\r
-            /* continue the initialization */\r
-            macTmrHandle = xTimerCreate( PIC32_MAC_TIMER_NAME, PIC32_MAC_TIMER_PERIOD, pdTRUE, 0, MacTmrCallback );\r
-\r
-            if( ( macTmrHandle == 0 ) || ( xTimerStart( macTmrHandle, 0 ) != pdPASS ) )\r
-            {\r
-                netUpFail = 8;\r
-                break;\r
-            }\r
-\r
-            /* spawn the PIC32 MAC task function */\r
-            /* and wait for its event signal */\r
-            macObjStatus = SYS_STATUS_BUSY;\r
-\r
-            if( xTaskCreate( MacHandlerTask, PIC32_MAC_TASK_NAME, PIC32_MAC_TASK_STACK_SIZE, xTaskGetCurrentTaskHandle(), PIC32_MAC_TASK_PRI, &macTaskHandle ) != pdPASS )\r
-            { /* failed */\r
-                netUpFail = 9;\r
-                break;\r
-            }\r
-\r
-            xTaskNotifyWait( PIC32_MAC_EVENT_INIT_DONE, PIC32_MAC_EVENT_INIT_DONE, &evBits, PIC32_MAC_INIT_TIMEOUT );\r
-\r
-            if( ( evBits & PIC32_MAC_EVENT_INIT_DONE ) == 0 )\r
-            { /* timed out */\r
-                netUpFail = 10;\r
-                break;\r
-            }\r
-\r
-            if( macObjStatus != SYS_STATUS_READY )\r
-            { /* failed somehow ??? */\r
-                netUpFail = 11;\r
-                break;\r
-            }\r
-\r
-            netUpFail = 0;\r
-            break;\r
-        }\r
-\r
-        if( netUpFail == 0 )\r
-        {\r
-            PIC32_MAC_DbgPrint( " MAC Init success!\r\n" );\r
-\r
-            #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
-                /* create command group */\r
-                if( !SYS_CMD_ADDGRP( macCmdTbl, sizeof( macCmdTbl ) / sizeof( *macCmdTbl ), "mac", ": mac commands" ) )\r
-                {\r
-                    PIC32_MAC_DbgPrint( "Failed to create MAC Commands\r\n" );\r
-                }\r
-            #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
-\r
-            return true;\r
-        }\r
-        else\r
-        {\r
-            StartInitCleanup();\r
-            PIC32_MAC_DbgPrint( "MAC Init failed: %d!\r\n", netUpFail );\r
-\r
-            return false;\r
-        }\r
-    }\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    static void StartInitCleanup( void )\r
-    {\r
-        if( macHeapHandle != 0 )\r
-        {\r
-            TCPIP_HEAP_Delete( macHeapHandle );\r
-            macHeapHandle = 0;\r
-        }\r
-\r
-        if( macObjHandle != 0 )\r
-        {\r
-            ( macObject->TCPIP_MAC_Deinitialize )( macObjHandle );\r
-            macObjHandle = 0;\r
-        }\r
-\r
-        if( macTmrHandle != 0 )\r
-        {\r
-            xTimerDelete( macTmrHandle, portMAX_DELAY );\r
-            macTmrHandle = 0;\r
-        }\r
-\r
-        if( macTaskHandle != 0 )\r
-        {\r
-            vTaskDelete( macTaskHandle );\r
-            macTaskHandle = 0;\r
-        }\r
-    }\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl )\r
-    {\r
-        TCPIP_MAC_ADDR macAdd;\r
-        uint8_t unsetMACAddr[ 6 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };     /* not set MAC address */\r
-\r
-        pMacCtrl->nIfs = 1;\r
-\r
-        pMacCtrl->mallocF = TCPIP_HEAP_MallocOutline;\r
-        pMacCtrl->callocF = TCPIP_HEAP_CallocOutline;\r
-        pMacCtrl->freeF = TCPIP_HEAP_FreeOutline;\r
-        pMacCtrl->memH = macHeapHandle;\r
-\r
-\r
-        pMacCtrl->pktAllocF = PIC32_MacPacketAllocate;\r
-        pMacCtrl->pktFreeF = ( TCPIP_MAC_PKT_FreeF ) _TCPIP_PKT_FREE_FNC;\r
-        pMacCtrl->pktAckF = ( TCPIP_MAC_PKT_AckF ) _TCPIP_PKT_ACK_FNC;\r
-\r
-        pMacCtrl->synchF = MacSyncFunction;\r
-\r
-        pMacCtrl->eventF = MAC_EventFunction;\r
-        pMacCtrl->eventParam = 0;\r
-\r
-        pMacCtrl->moduleId = TCPIP_MODULE_MAC_PIC32INT;\r
-        pMacCtrl->netIx = 0;\r
-        pMacCtrl->macAction = TCPIP_MAC_ACTION_INIT;\r
-        pMacCtrl->powerMode = TCPIP_MAC_POWER_FULL;\r
-\r
-        macAdd.v[ 0 ] = configMAC_ADDR0;\r
-        macAdd.v[ 1 ] = configMAC_ADDR1;\r
-        macAdd.v[ 2 ] = configMAC_ADDR2;\r
-        macAdd.v[ 3 ] = configMAC_ADDR3;\r
-        macAdd.v[ 4 ] = configMAC_ADDR4;\r
-        macAdd.v[ 5 ] = configMAC_ADDR5;\r
-\r
-        if( memcmp( macAdd.v, unsetMACAddr, sizeof( unsetMACAddr ) ) == 0 )\r
-        { /* if unspecified we use the factory pre-programmed address */\r
-            PIC32_GetMACAddress( pMacCtrl->ifPhyAddress.v );\r
-        }\r
-        else\r
-        { /* use the config suggested one */\r
-            memcpy( pMacCtrl->ifPhyAddress.v, macAdd.v, sizeof( macAdd ) );\r
-        }\r
-    }\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    static bool MacSyncFunction( void * synchHandle,\r
-                                 TCPIP_MAC_SYNCH_REQUEST req )\r
-    {\r
-        switch( req )\r
-        {\r
-            case TCPIP_MAC_SYNCH_REQUEST_OBJ_CREATE:\r
-                vSemaphoreCreateBinary( *( SemaphoreHandle_t * ) synchHandle );\r
-\r
-                return ( *( SemaphoreHandle_t * ) synchHandle == NULL ) ? false : true;\r
-\r
-            case TCPIP_MAC_SYNCH_REQUEST_OBJ_DELETE:\r
-                vSemaphoreDelete( *( SemaphoreHandle_t * ) synchHandle );\r
-                *( SemaphoreHandle_t * ) synchHandle = NULL;\r
-\r
-                return true;\r
-\r
-            case TCPIP_MAC_SYNCH_REQUEST_OBJ_LOCK:\r
-\r
-                return ( xSemaphoreTake( *( SemaphoreHandle_t * ) synchHandle, portMAX_DELAY ) == pdTRUE ) ? true : false;\r
-\r
-            case TCPIP_MAC_SYNCH_REQUEST_OBJ_UNLOCK:\r
-\r
-                return ( xSemaphoreGive( *( SemaphoreHandle_t * ) synchHandle ) == pdTRUE ) ? true : false;\r
-\r
-            case TCPIP_MAC_SYNCH_REQUEST_CRIT_ENTER:\r
-                vTaskSuspendAll();\r
-\r
-                return true;\r
-\r
-            case TCPIP_MAC_SYNCH_REQUEST_CRIT_LEAVE:\r
-                xTaskResumeAll();\r
-\r
-                return true;\r
-\r
-            default:\r
-\r
-                return false;\r
-        }\r
-    }\r
-\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    static void MacHandlerTask( void * params )\r
-    {\r
-        EventBits_t evBits;\r
-\r
-        /* perform the MAC initialization */\r
-        while( macObjStatus == SYS_STATUS_BUSY )\r
-        {\r
-            /* process the underlying MAC module tasks */\r
-            ( macObject->TCPIP_MAC_Tasks )( macObjHandle );\r
-\r
-            SYS_STATUS macStatus = ( macObject->TCPIP_MAC_Status )( macObjHandle );\r
-\r
-            if( macStatus == SYS_STATUS_BUSY )\r
-            { /* still pending */\r
-                vTaskDelay( PIC32_MAC_TASK_INIT_PENDING_DELAY );\r
-            }\r
-            else\r
-            { /* completed ...somehow */\r
-                macObjStatus = macStatus;\r
-\r
-                xTaskNotify( ( TaskHandle_t ) params, PIC32_MAC_EVENT_INIT_DONE, eSetBits );\r
-\r
-                if( macStatus != SYS_STATUS_READY )\r
-                { /* failed miserably */\r
-                    vTaskDelete( 0 );\r
-                }\r
-\r
-                /* done, up and running */\r
-            }\r
-        }\r
-\r
-        while( true )\r
-        {\r
-            xTaskNotifyWait( PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, &evBits, portMAX_DELAY );\r
-\r
-            if( ( evBits & PIC32_MAC_EVENT_TIMEOUT ) != 0 )\r
-            {                                                                       /* timeout occurred... */\r
-                ( macObject->TCPIP_MAC_Tasks )( macObjHandle );\r
-                bool linkCurr = ( macObject->TCPIP_MAC_LinkCheck )( macCliHandle ); /* check link status */\r
-\r
-                if( macLinkStatus != linkCurr )\r
-                { /* link status changed; some event could ve fired here if needed */\r
-                    PIC32_MAC_DbgPrint( " MAC link: %s!\r\n", linkCurr ? "ON" : "OFF" );\r
-                    macLinkStatus = linkCurr;\r
-                }\r
-            }\r
-\r
-            if( ( evBits & PIC32_MAC_EVENT_IF_PENDING ) != 0 )\r
-            { /* IF events signal */\r
-                TCPIP_MAC_EVENT activeEvents = ( macObject->TCPIP_MAC_EventPendingGet )( macCliHandle );\r
-\r
-                if( activeEvents != TCPIP_MAC_EV_NONE )\r
-                {\r
-                    /* acknowledge the events */\r
-                    ( macObject->TCPIP_MAC_EventAcknowledge )( macCliHandle, activeEvents );\r
-\r
-                    /* check for RX */\r
-                    if( ( activeEvents & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_RX_OVFLOW | TCPIP_MAC_EV_RX_BUFNA ) ) != 0 )\r
-                    { /* RX packets available */\r
-                        MacRxPackets();\r
-                    }\r
-\r
-                    /* call the driver process function; */\r
-                    /* PIC32 driver requests it through TCPIP_MAC_ParametersGet() which is bypassed here! */\r
-                    ( macObject->TCPIP_MAC_Process )( macCliHandle );\r
-                }\r
-            }\r
-\r
-            /* do what you have to do and then wait for another event... */\r
-        }\r
-    }\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    static void MacTmrCallback( TimerHandle_t xTimer )\r
-    {\r
-        xTaskNotify( macTaskHandle, PIC32_MAC_EVENT_TIMEOUT, eSetBits );\r
-    }\r
-\r
-    /* MAC interrupt event function */\r
-    /* MAC signals an event, probably from within ISR */\r
-    /* we care just for RX related events */\r
-    static void MAC_EventFunction( TCPIP_MAC_EVENT event,\r
-                                   const void * eventParam )\r
-    {\r
-        BaseType_t xHigherPriorityTaskWoken;\r
-\r
-        if( ( event & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ) ) != 0 )\r
-        {\r
-            xHigherPriorityTaskWoken = pdFALSE;\r
-            xTaskNotifyFromISR( macTaskHandle, PIC32_MAC_EVENT_IF_PENDING, eSetBits, &xHigherPriorityTaskWoken );\r
-\r
-            if( xHigherPriorityTaskWoken )\r
-            {\r
-                portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
-            }\r
-        }\r
-    }\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    BaseType_t xGetPhyLinkStatus( void )\r
-    {\r
-        return macLinkStatus == true ? pdPASS : pdFAIL;\r
-    }\r
-\r
-\r
-    /* receive packets from the MAC driver */\r
-    static void MacRxPackets( void )\r
-    {\r
-        TCPIP_MAC_PACKET * pRxPkt;\r
-\r
-        /* get all the new MAC packets */\r
-        while( ( pRxPkt = ( macObject->TCPIP_MAC_PacketRx )( macCliHandle, 0, 0 ) ) != 0 )\r
-        {\r
-            MacProcessRxPacket( pRxPkt );\r
-        }\r
-    }\r
-\r
-    /*-----------------------------------------------------------*/\r
-\r
-    static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt )\r
-    {\r
-        bool pktSuccess, pktLost;\r
-        size_t pktLength;\r
-        TCPIP_MAC_DATA_SEGMENT * pSeg;\r
-        uint8_t * pPktBuff;\r
-        NetworkBufferDescriptor_t * pxBufferDescriptor;\r
-        IPStackEvent_t xRxEvent;\r
-\r
-        pxBufferDescriptor = 0;\r
-        pktSuccess = pktLost = false;\r
-\r
-        while( true )\r
-        {\r
-            pktLength = 0;\r
-            int nSegs = 0;\r
-            pSeg = pRxPkt->pDSeg;\r
-            pPktBuff = pSeg->segLoad;\r
-\r
-            /* calculate the packet size */\r
-            do\r
-            {\r
-                pktLength += pSeg->segLen;\r
-                pSeg = pSeg->next;\r
-                nSegs++;\r
-            } while( pSeg != 0 );\r
-\r
-            if( nSegs > 1 )\r
-            { /* no support in FreeRTOS for multi segment packets! */\r
-                break;\r
-            }\r
-\r
-            /* sizeof(TCPIP_MAC_ETHERNET_HEADER) is subtracted by the driver */\r
-            /* but FreeRTOS needs the whole frame! */\r
-            pktLength += sizeof( TCPIP_MAC_ETHERNET_HEADER );\r
-\r
-            if( eConsiderFrameForProcessing( pPktBuff ) != eProcessBuffer )\r
-            {\r
-                break;\r
-            }\r
-\r
-            /* get the network descriptor (no data buffer) to hold this packet */\r
-            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( 0, 0 );\r
-\r
-            if( pxBufferDescriptor == 0 )\r
-            {\r
-                pktLost = true;\r
-                break;\r
-            }\r
-\r
-            PIC32_MacAssociate( pRxPkt, pxBufferDescriptor, pktLength );\r
-\r
-            xRxEvent.eEventType = eNetworkRxEvent;\r
-            xRxEvent.pvData = ( void * ) pxBufferDescriptor;\r
-\r
-            /* Send the data to the TCP/IP stack */\r
-            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
-            { /* failed */\r
-                pktLost = true;\r
-            }\r
-            else\r
-            { /* success */\r
-                pktSuccess = true;\r
-                iptraceNETWORK_INTERFACE_RECEIVE();\r
-            }\r
-\r
-            break;\r
-        }\r
-\r
-        if( !pktSuccess )\r
-        { /* smth went wrong; nothing sent to the */\r
-            if( pxBufferDescriptor != 0 )\r
-            {\r
-                pxBufferDescriptor->pucEthernetBuffer = 0;\r
-                vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
-            }\r
-\r
-            if( pktLost )\r
-            {\r
-                iptraceETHERNET_RX_EVENT_LOST();\r
-            }\r
-\r
-            /* acknowledge the packet to the MAC driver */\r
-            if( pRxPkt->ackFunc )\r
-            {\r
-                ( *pRxPkt->ackFunc )( pRxPkt, pRxPkt->ackParam );\r
-            }\r
-            else\r
-            {\r
-                PIC32_MacPacketOrphan( pRxPkt );\r
-            }\r
-        }\r
-    }\r
-\r
-    #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
-        /* */\r
-        static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
-                                     int argc,\r
-                                     char ** argv )\r
-        {\r
-            TCPIP_MAC_RES macRes;\r
-            TCPIP_MAC_RX_STATISTICS rxStatistics;\r
-            TCPIP_MAC_TX_STATISTICS txStatistics;\r
-            TCPIP_MAC_STATISTICS_REG_ENTRY regEntries[ 8 ];\r
-            TCPIP_MAC_STATISTICS_REG_ENTRY * pRegEntry;\r
-            int jx, hwEntries;\r
-            char entryName[ sizeof( pRegEntry->registerName ) + 1 ];\r
-\r
-            const void * cmdIoParam = pCmdIO->cmdIoParam;\r
-\r
-            if( argc != 1 )\r
-            {\r
-                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Usage: macinfo \r\n" );\r
-                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Ex: macinfo \r\n" );\r
-\r
-                return false;\r
-            }\r
-\r
-            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s driver statistics\r\n", macObject->macName );\r
-            macRes = ( macObject->TCPIP_MAC_StatisticsGet )( macCliHandle, &rxStatistics, &txStatistics );\r
-\r
-            if( macRes == TCPIP_MAC_RES_OK )\r
-            {\r
-                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnRxOkPackets: %d, nRxPendBuffers: %d, nRxSchedBuffers: %d, ",\r
-                                             rxStatistics.nRxOkPackets, rxStatistics.nRxPendBuffers, rxStatistics.nRxSchedBuffers );\r
-                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "nRxErrorPackets: %d, nRxFragmentErrors: %d\r\n", rxStatistics.nRxErrorPackets, rxStatistics.nRxFragmentErrors );\r
-                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnTxOkPackets: %d, nTxPendBuffers: %d, nTxErrorPackets: %d, nTxQueueFull: %d\r\n",\r
-                                             txStatistics.nTxOkPackets, txStatistics.nTxPendBuffers, txStatistics.nTxErrorPackets, txStatistics.nTxQueueFull );\r
-            }\r
-            else\r
-            {\r
-                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );\r
-            }\r
-\r
-            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s hardware statistics\r\n", macObject->macName );\r
-            macRes = ( macObject->TCPIP_MAC_RegisterStatisticsGet )( macCliHandle, regEntries, sizeof( regEntries ) / sizeof( *regEntries ), &hwEntries );\r
-\r
-            if( macRes == TCPIP_MAC_RES_OK )\r
-            {\r
-                entryName[ sizeof( entryName ) - 1 ] = 0;\r
-\r
-                for( jx = 0, pRegEntry = regEntries; jx < hwEntries && jx < sizeof( regEntries ) / sizeof( *regEntries ); jx++, pRegEntry++ )\r
-                {\r
-                    strncpy( entryName, pRegEntry->registerName, sizeof( entryName ) - 1 );\r
-                    ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\t%s: 0x%8x\r\n", entryName, pRegEntry->registerValue );\r
-                }\r
-            }\r
-            else\r
-            {\r
-                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );\r
-            }\r
-\r
-            return true;\r
-        }\r
-\r
-        /*-----------------------------------------------------------*/\r
-\r
-        static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
-                                     int argc,\r
-                                     char ** argv )\r
-        {\r
-            const void * cmdIoParam = pCmdIO->cmdIoParam;\r
-\r
-            union\r
-            {\r
-                uint32_t ul;\r
-                uint8_t b[ 4 ];\r
-            }\r
-            sUl;\r
-\r
-            sUl.ul = FreeRTOS_GetIPAddress();\r
-\r
-            bool linkUp = FreeRTOS_IsNetworkUp() == pdTRUE;\r
-\r
-            ( *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
-            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Link is: %s\r\n", linkUp ? "Up" : "Down" );\r
-\r
-            return true;\r
-        }\r
-\r
-#include "aws_application_version.h"\r
-\r
-static int _Command_Version(SYS_CMD_DEVICE_NODE* pCmdIO, int argc, char** argv)\r
-{\r
-    configPRINTF( ( "App version - maj: %d, min: %d, build: %d\r\n",  xAppFirmwareVersion.u.x.ucMajor, xAppFirmwareVersion.u.x.ucMinor, xAppFirmwareVersion.u.x.usBuild) );\r
-    return 0;\r
-}\r
-\r
-    #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
-#endif /* #ifdef PIC32_USE_ETHERNET */\r
+/*******************************************************************************
+*  Network Interface file
+*
+*  Summary:
+*   Network Interface file for FreeRTOS-Plus-TCP stack
+*
+*  Description:
+*   - Interfaces PIC32 to the FreeRTOS TCP/IP stack
+*******************************************************************************/
+
+/*******************************************************************************
+*  File Name:  pic32_NetworkInterface.c
+*  Copyright 2017 Microchip Technology Incorporated and its subsidiaries.
+*
+*  Permission is hereby granted, free of charge, to any person obtaining a copy of
+*  this software and associated documentation files (the "Software"), to deal in
+*  the Software without restriction, including without limitation the rights to
+*  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+*  of the Software, and to permit persons to whom the Software is furnished to do
+*  so, subject to the following conditions:
+*  The above copyright notice and this permission notice shall be included in all
+*  copies or substantial portions of the Software.
+*
+*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+*  SOFTWARE
+*******************************************************************************/
+#include <sys/kmem.h>
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+#include "event_groups.h"
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_IP_Private.h"
+
+#include "NetworkInterface.h"
+#include "NetworkBufferManagement.h"
+
+
+#include "NetworkInterface.h"
+#include "NetworkConfig.h"
+
+#include "peripheral/eth/plib_eth.h"
+
+#include "system_config.h"
+#include "system/console/sys_console.h"
+#include "system/debug/sys_debug.h"
+#include "system/command/sys_command.h"
+
+#include "driver/ethmac/drv_ethmac.h"
+#include "driver/miim/drv_miim.h"
+
+#include "tcpip/tcpip.h"
+#include "tcpip/src/tcpip_private.h"
+#include "tcpip/src/link_list.h"
+
+#ifdef PIC32_USE_ETHERNET
+
+    /* local definitions and data */
+
+    /* debug messages */
+    #if ( PIC32_MAC_DEBUG_MESSAGES != 0 )
+        #define PIC32_MAC_DbgPrint( format, ... )    SYS_CONSOLE_PRINT( format, ## __VA_ARGS__ )
+    #else
+        #define PIC32_MAC_DbgPrint( format, ... )
+    #endif /* (PIC32_MAC_DEBUG_MESSAGES != 0) */
+
+    typedef enum
+    {
+        PIC32_MAC_EVENT_INIT_NONE = 0x000,      /* no event/invalid */
+
+        PIC32_MAC_EVENT_INIT_DONE = 0x001,      /* initialization done event */
+        PIC32_MAC_EVENT_TIMEOUT = 0x002,        /* periodic timeout event */
+        PIC32_MAC_EVENT_IF_PENDING = 0x004,     /* an interface event signal: RX, TX, errors. etc. */
+    } PIC32_MAC_EVENT_TYPE;
+
+    typedef enum
+    {
+        eMACInit,                               /* Must initialise MAC. */
+        eMACPass,                               /* Initialisation was successful. */
+        eMACFailed,                             /* Initialisation failed. */
+    } eMAC_INIT_STATUS_TYPE;
+
+    static TCPIP_STACK_HEAP_HANDLE macHeapHandle;
+
+    static const TCPIP_MAC_OBJECT * macObject; /* the one and only MAC object; */
+
+    static SYS_MODULE_OBJ macObjHandle;        /* the MAC object instance, obtained at initialization */
+    static TCPIP_MAC_HANDLE macCliHandle;      /* client handle */
+    static volatile SYS_STATUS macObjStatus;   /* current MAC status */
+
+    static TaskHandle_t macTaskHandle;
+
+    static TimerHandle_t macTmrHandle;
+
+    static bool macLinkStatus;              /* true if link is ON */
+
+    static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
+
+    /* local prototypes */
+    static bool StartInitMac( void );
+    static void StartInitCleanup( void );
+
+    static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl );
+
+    static bool MacSyncFunction( void * synchHandle,
+                                 TCPIP_MAC_SYNCH_REQUEST req );
+
+    /* the PIC32 MAC task function */
+    static void MacHandlerTask( void * params );
+
+    /* MAC interrupt event function */
+    static void MAC_EventFunction( TCPIP_MAC_EVENT event,
+                                   const void * eventParam );
+
+    /* timer callback for link maintenance, etc; */
+    static void MacTmrCallback( TimerHandle_t xTimer );
+
+    /* MAC RX packets functions */
+    static void MacRxPackets( void );
+    static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt );
+
+
+    /* memory allocation mapping to FreeRTOS */
+    static void * _malloc( size_t nBytes )
+    {
+        return pvPortMalloc( nBytes );
+    }
+
+    /*-----------------------------------------------------------*/
+
+    static void * _calloc( size_t nElems,
+                           size_t elemSize )
+    {
+        size_t nBytes = nElems * elemSize;
+
+        void * ptr = pvPortMalloc( nBytes );
+
+        if( ptr != 0 )
+        {
+            memset( ptr, 0, nBytes );
+        }
+
+        return ptr;
+    }
+
+    /*-----------------------------------------------------------*/
+
+    static void _free( void * pBuff )
+    {
+        vPortFree( pBuff );
+    }
+
+    /* extern references */
+    /* */
+    /* use the configuration data from the system_init.c */
+    extern const TCPIP_NETWORK_CONFIG TCPIP_HOSTS_CONFIGURATION[];
+
+    /* BufferAllocation_2.c:: packet allocation function */
+    extern TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,
+                                                       uint16_t segLoadLen,
+                                                       TCPIP_MAC_PACKET_FLAGS flags );
+
+    extern void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,
+                                    NetworkBufferDescriptor_t * pxBufferDescriptor,
+                                    size_t pktLength );
+    extern void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt );
+
+    /* cannot use the system_init.c::tcpipHeapConfig because FreeRTOS does not have a calloc function! */
+    /* we build it here! */
+
+    /* make sure we're running with external heap! Redirect to FreeRTOS. */
+    #if !defined( TCPIP_STACK_USE_EXTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP_POOL )
+        #error "TCPIP_STACK_USE_EXTERNAL_HEAP should be defined for this project!"
+    #endif
+
+    static const TCPIP_STACK_HEAP_EXTERNAL_CONFIG tcpipHeapConfig =
+    {
+        .heapType   = TCPIP_STACK_HEAP_TYPE_EXTERNAL_HEAP,
+        .heapFlags  = TCPIP_STACK_HEAP_FLAG_ALLOC_UNCACHED | TCPIP_STACK_HEAP_FLAG_NO_MTHREAD_SYNC,
+        .heapUsage  = TCPIP_STACK_HEAP_USE_DEFAULT,
+        .malloc_fnc = _malloc,
+        .calloc_fnc = _calloc,
+        .free_fnc   = _free,
+    };
+
+    #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )
+        static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
+                                     int argc,
+                                     char ** argv );
+        static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
+                                     int argc,
+                                     char ** argv );
+        static int _Command_Version( SYS_CMD_DEVICE_NODE * pCmdIO,
+                                     int argc,
+                                     char ** argv );
+
+        static const SYS_CMD_DESCRIPTOR macCmdTbl[] =
+        {
+            { "macinfo", _Command_MacInfo, ": Check MAC statistics" },
+            { "netinfo", _Command_NetInfo, ": Net info" },
+            { "version", _Command_Version, ": Version info" },
+        };
+    #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */
+
+
+    /* FreeRTOS implementation functions */
+    BaseType_t xNetworkInterfaceInitialise( void )
+    {
+    BaseType_t xResult;
+
+        if( xMacInitStatus == eMACInit )
+        {
+                       /* This is the first time this function is called. */
+            if( StartInitMac() != false )
+            {
+                /* Indicate that the MAC initialisation succeeded. */
+                xMacInitStatus = eMACPass;
+            }
+            else
+            {
+                xMacInitStatus = eMACFailed;
+            }
+        }
+
+        if( xMacInitStatus == eMACPass )
+        {
+            xResult = xGetPhyLinkStatus();
+        }
+        else
+        {
+            xResult = pdFAIL;
+        }
+
+       PIC32_MAC_DbgPrint( "xNetworkInterfaceInitialise: %d %d\r\n", ( int ) xMacInitStatus, ( int ) xResult );
+
+        return xResult;
+    }
+
+
+    /*-----------------------------------------------------------*/
+
+    BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
+                                        BaseType_t xReleaseAfterSend )
+    {
+        TCPIP_MAC_RES macRes;
+        TCPIP_MAC_PACKET * pTxPkt;
+
+        BaseType_t retRes = pdFALSE;
+
+
+        if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )
+        {
+            TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pxDescriptor->pucEthernetBuffer - PIC32_BUFFER_PKT_PTR_OSSET );
+            configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
+            pTxPkt = *ppkt;
+            configASSERT( pTxPkt != 0 );
+
+            /* prepare the packet for transmission */
+            /* set the correct data length: */
+            configASSERT( pTxPkt->pDSeg->segSize >= pTxPkt->pDSeg->segLen );
+            pTxPkt->pDSeg->segLen = pxDescriptor->xDataLength;
+            pTxPkt->next = 0; /* unlink it */
+            macRes = ( macObject->TCPIP_MAC_PacketTx )( macCliHandle, pTxPkt );
+
+            if( macRes >= 0 )
+            {
+                retRes = pdTRUE;
+                pxDescriptor->pucEthernetBuffer = 0; /* it will be released by the MAC driver once it's transmitted */
+                iptraceNETWORK_INTERFACE_TRANSMIT();
+            }
+
+            /* else same error occurred; this normally should not happen! But the buffer is left in there so it shold be freed! */
+
+            /* The buffer has been sent so can be released. */
+            if( xReleaseAfterSend != pdFALSE )
+            {
+                vReleaseNetworkBufferAndDescriptor( pxDescriptor );
+            }
+        }
+
+        return retRes;
+    }
+
+
+    /************************************* Section: helper functions ************************************************** */
+    /* */
+
+    void PIC32_GetMACAddress( uint8_t macAdd[ 6 ] )
+    {
+        #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )
+            PLIB_ETH_MACGetAddress( ETH_ID_0, macAdd );
+        #else
+        #error "MAC Address: not supported architecture!"
+        #endif
+    }
+
+
+    /*-----------------------------------------------------------*/
+
+    const void * const PIC32_GetMacConfigData( void )
+    {
+        #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )
+            extern const TCPIP_MODULE_MAC_PIC32INT_CONFIG tcpipMACPIC32INTInitData;
+
+            return &tcpipMACPIC32INTInitData;
+        #else
+        #error "MAC Address: not supported architecture!"
+        #endif
+    }
+
+    /************************************* Section: worker code ************************************************** */
+    /* */
+
+
+    static bool StartInitMac( void )
+    {
+        TCPIP_MAC_MODULE_CTRL macCtrl;
+        SYS_MODULE_INIT moduleInit;
+        EventBits_t evBits;
+
+
+        /* perform some initialization of all variables so that we can cleanup what failed */
+        /* if something failed, the routine will be called again and again by FreeRTOS! */
+        macHeapHandle = 0;
+        macObjHandle = 0;
+        macCliHandle = 0;
+        macTmrHandle = 0;
+        macTaskHandle = 0;
+        macObject = TCPIP_HOSTS_CONFIGURATION[ 0 ].pMacObject; /* the MAC object we use */
+        macObjStatus = SYS_STATUS_UNINITIALIZED;
+        macLinkStatus = false;
+
+        int netUpFail = 0;
+
+        while( true )
+        {
+            /* start the allocator */
+            macHeapHandle = TCPIP_HEAP_Create( ( const TCPIP_STACK_HEAP_CONFIG * ) &tcpipHeapConfig, 0 );
+
+            if( macHeapHandle == 0 )
+            {
+                netUpFail = 1;
+                break;
+            }
+
+            if( TCPIP_PKT_Initialize( macHeapHandle, 0, 0 ) == false )
+            {
+                netUpFail = 2;
+                break;
+            }
+
+            moduleInit.sys.powerState = SYS_MODULE_POWER_RUN_FULL;
+
+            /* Initialize the MAC. MAC address is defined to 0x000000000000 in
+             * FreeRTOSConfig.h and therefore it will be initialized to the
+             * factory programmed MAC address. */
+            SetMacCtrl( &macCtrl );
+            /* Set the mac address in the FreeRTOS+TCP stack. */
+            FreeRTOS_UpdateMACAddress( macCtrl.ifPhyAddress.v );
+
+            TCPIP_MAC_INIT macInit =
+            {
+                .moduleInit = { moduleInit.value },
+                .macControl = &macCtrl,
+                .moduleData = PIC32_GetMacConfigData(),
+            };
+
+            macObjHandle = ( macObject->TCPIP_MAC_Initialize )( TCPIP_MODULE_MAC_PIC32INT, &macInit.moduleInit );
+
+            if( macObjHandle == SYS_MODULE_OBJ_INVALID )
+            {
+                macObjHandle = 0;
+                netUpFail = 4;
+                break;
+            }
+
+            /* open the MAC */
+            macCliHandle = ( macObject->TCPIP_MAC_Open )( TCPIP_MODULE_MAC_PIC32INT, DRV_IO_INTENT_READWRITE );
+
+            if( macCliHandle == DRV_HANDLE_INVALID )
+            {
+                macCliHandle = 0;
+                netUpFail = 5;
+                break;
+            }
+
+            if( !( macObject->TCPIP_MAC_EventMaskSet )( macCliHandle, ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ), true ) )
+            {
+                netUpFail = 6;
+                break;
+            }
+
+            /* completed the MAC initialization */
+            /* continue the initialization */
+            macTmrHandle = xTimerCreate( PIC32_MAC_TIMER_NAME, PIC32_MAC_TIMER_PERIOD, pdTRUE, 0, MacTmrCallback );
+
+            if( ( macTmrHandle == 0 ) || ( xTimerStart( macTmrHandle, 0 ) != pdPASS ) )
+            {
+                netUpFail = 8;
+                break;
+            }
+
+            /* spawn the PIC32 MAC task function */
+            /* and wait for its event signal */
+            macObjStatus = SYS_STATUS_BUSY;
+
+            if( xTaskCreate( MacHandlerTask, PIC32_MAC_TASK_NAME, PIC32_MAC_TASK_STACK_SIZE, xTaskGetCurrentTaskHandle(), PIC32_MAC_TASK_PRI, &macTaskHandle ) != pdPASS )
+            { /* failed */
+                netUpFail = 9;
+                break;
+            }
+
+            xTaskNotifyWait( PIC32_MAC_EVENT_INIT_DONE, PIC32_MAC_EVENT_INIT_DONE, &evBits, PIC32_MAC_INIT_TIMEOUT );
+
+            if( ( evBits & PIC32_MAC_EVENT_INIT_DONE ) == 0 )
+            { /* timed out */
+                netUpFail = 10;
+                break;
+            }
+
+            if( macObjStatus != SYS_STATUS_READY )
+            { /* failed somehow ??? */
+                netUpFail = 11;
+                break;
+            }
+
+            netUpFail = 0;
+            break;
+        }
+
+        if( netUpFail == 0 )
+        {
+            PIC32_MAC_DbgPrint( " MAC Init success!\r\n" );
+
+            #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )
+                /* create command group */
+                if( !SYS_CMD_ADDGRP( macCmdTbl, sizeof( macCmdTbl ) / sizeof( *macCmdTbl ), "mac", ": mac commands" ) )
+                {
+                    PIC32_MAC_DbgPrint( "Failed to create MAC Commands\r\n" );
+                }
+            #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */
+
+            return true;
+        }
+        else
+        {
+            StartInitCleanup();
+            PIC32_MAC_DbgPrint( "MAC Init failed: %d!\r\n", netUpFail );
+
+            return false;
+        }
+    }
+
+    /*-----------------------------------------------------------*/
+
+    static void StartInitCleanup( void )
+    {
+        if( macHeapHandle != 0 )
+        {
+            TCPIP_HEAP_Delete( macHeapHandle );
+            macHeapHandle = 0;
+        }
+
+        if( macObjHandle != 0 )
+        {
+            ( macObject->TCPIP_MAC_Deinitialize )( macObjHandle );
+            macObjHandle = 0;
+        }
+
+        if( macTmrHandle != 0 )
+        {
+            xTimerDelete( macTmrHandle, portMAX_DELAY );
+            macTmrHandle = 0;
+        }
+
+        if( macTaskHandle != 0 )
+        {
+            vTaskDelete( macTaskHandle );
+            macTaskHandle = 0;
+        }
+    }
+
+    /*-----------------------------------------------------------*/
+
+    static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl )
+    {
+        TCPIP_MAC_ADDR macAdd;
+        uint8_t unsetMACAddr[ 6 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };     /* not set MAC address */
+
+        pMacCtrl->nIfs = 1;
+
+        pMacCtrl->mallocF = TCPIP_HEAP_MallocOutline;
+        pMacCtrl->callocF = TCPIP_HEAP_CallocOutline;
+        pMacCtrl->freeF = TCPIP_HEAP_FreeOutline;
+        pMacCtrl->memH = macHeapHandle;
+
+
+        pMacCtrl->pktAllocF = PIC32_MacPacketAllocate;
+        pMacCtrl->pktFreeF = ( TCPIP_MAC_PKT_FreeF ) _TCPIP_PKT_FREE_FNC;
+        pMacCtrl->pktAckF = ( TCPIP_MAC_PKT_AckF ) _TCPIP_PKT_ACK_FNC;
+
+        pMacCtrl->synchF = MacSyncFunction;
+
+        pMacCtrl->eventF = MAC_EventFunction;
+        pMacCtrl->eventParam = 0;
+
+        pMacCtrl->moduleId = TCPIP_MODULE_MAC_PIC32INT;
+        pMacCtrl->netIx = 0;
+        pMacCtrl->macAction = TCPIP_MAC_ACTION_INIT;
+        pMacCtrl->powerMode = TCPIP_MAC_POWER_FULL;
+
+        macAdd.v[ 0 ] = configMAC_ADDR0;
+        macAdd.v[ 1 ] = configMAC_ADDR1;
+        macAdd.v[ 2 ] = configMAC_ADDR2;
+        macAdd.v[ 3 ] = configMAC_ADDR3;
+        macAdd.v[ 4 ] = configMAC_ADDR4;
+        macAdd.v[ 5 ] = configMAC_ADDR5;
+
+        if( memcmp( macAdd.v, unsetMACAddr, sizeof( unsetMACAddr ) ) == 0 )
+        { /* if unspecified we use the factory pre-programmed address */
+            PIC32_GetMACAddress( pMacCtrl->ifPhyAddress.v );
+        }
+        else
+        { /* use the config suggested one */
+            memcpy( pMacCtrl->ifPhyAddress.v, macAdd.v, sizeof( macAdd ) );
+        }
+    }
+
+    /*-----------------------------------------------------------*/
+
+    static bool MacSyncFunction( void * synchHandle,
+                                 TCPIP_MAC_SYNCH_REQUEST req )
+    {
+        switch( req )
+        {
+            case TCPIP_MAC_SYNCH_REQUEST_OBJ_CREATE:
+                vSemaphoreCreateBinary( *( SemaphoreHandle_t * ) synchHandle );
+
+                return ( *( SemaphoreHandle_t * ) synchHandle == NULL ) ? false : true;
+
+            case TCPIP_MAC_SYNCH_REQUEST_OBJ_DELETE:
+                vSemaphoreDelete( *( SemaphoreHandle_t * ) synchHandle );
+                *( SemaphoreHandle_t * ) synchHandle = NULL;
+
+                return true;
+
+            case TCPIP_MAC_SYNCH_REQUEST_OBJ_LOCK:
+
+                return ( xSemaphoreTake( *( SemaphoreHandle_t * ) synchHandle, portMAX_DELAY ) == pdTRUE ) ? true : false;
+
+            case TCPIP_MAC_SYNCH_REQUEST_OBJ_UNLOCK:
+
+                return ( xSemaphoreGive( *( SemaphoreHandle_t * ) synchHandle ) == pdTRUE ) ? true : false;
+
+            case TCPIP_MAC_SYNCH_REQUEST_CRIT_ENTER:
+                vTaskSuspendAll();
+
+                return true;
+
+            case TCPIP_MAC_SYNCH_REQUEST_CRIT_LEAVE:
+                xTaskResumeAll();
+
+                return true;
+
+            default:
+
+                return false;
+        }
+    }
+
+
+    /*-----------------------------------------------------------*/
+
+    static void MacHandlerTask( void * params )
+    {
+        EventBits_t evBits;
+
+        /* perform the MAC initialization */
+        while( macObjStatus == SYS_STATUS_BUSY )
+        {
+            /* process the underlying MAC module tasks */
+            ( macObject->TCPIP_MAC_Tasks )( macObjHandle );
+
+            SYS_STATUS macStatus = ( macObject->TCPIP_MAC_Status )( macObjHandle );
+
+            if( macStatus == SYS_STATUS_BUSY )
+            { /* still pending */
+                vTaskDelay( PIC32_MAC_TASK_INIT_PENDING_DELAY );
+            }
+            else
+            { /* completed ...somehow */
+                macObjStatus = macStatus;
+
+                xTaskNotify( ( TaskHandle_t ) params, PIC32_MAC_EVENT_INIT_DONE, eSetBits );
+
+                if( macStatus != SYS_STATUS_READY )
+                { /* failed miserably */
+                    vTaskDelete( 0 );
+                }
+
+                /* done, up and running */
+            }
+        }
+
+        while( true )
+        {
+            xTaskNotifyWait( PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, &evBits, portMAX_DELAY );
+
+            if( ( evBits & PIC32_MAC_EVENT_TIMEOUT ) != 0 )
+            {                                                                       /* timeout occurred... */
+                ( macObject->TCPIP_MAC_Tasks )( macObjHandle );
+                bool linkCurr = ( macObject->TCPIP_MAC_LinkCheck )( macCliHandle ); /* check link status */
+
+                if( macLinkStatus != linkCurr )
+                { /* link status changed; some event could ve fired here if needed */
+                    PIC32_MAC_DbgPrint( " MAC link: %s!\r\n", linkCurr ? "ON" : "OFF" );
+                    macLinkStatus = linkCurr;
+                }
+            }
+
+            if( ( evBits & PIC32_MAC_EVENT_IF_PENDING ) != 0 )
+            { /* IF events signal */
+                TCPIP_MAC_EVENT activeEvents = ( macObject->TCPIP_MAC_EventPendingGet )( macCliHandle );
+
+                if( activeEvents != TCPIP_MAC_EV_NONE )
+                {
+                    /* acknowledge the events */
+                    ( macObject->TCPIP_MAC_EventAcknowledge )( macCliHandle, activeEvents );
+
+                    /* check for RX */
+                    if( ( activeEvents & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_RX_OVFLOW | TCPIP_MAC_EV_RX_BUFNA ) ) != 0 )
+                    { /* RX packets available */
+                        MacRxPackets();
+                    }
+
+                    /* call the driver process function; */
+                    /* PIC32 driver requests it through TCPIP_MAC_ParametersGet() which is bypassed here! */
+                    ( macObject->TCPIP_MAC_Process )( macCliHandle );
+                }
+            }
+
+            /* do what you have to do and then wait for another event... */
+        }
+    }
+
+    /*-----------------------------------------------------------*/
+
+    static void MacTmrCallback( TimerHandle_t xTimer )
+    {
+        xTaskNotify( macTaskHandle, PIC32_MAC_EVENT_TIMEOUT, eSetBits );
+    }
+
+    /* MAC interrupt event function */
+    /* MAC signals an event, probably from within ISR */
+    /* we care just for RX related events */
+    static void MAC_EventFunction( TCPIP_MAC_EVENT event,
+                                   const void * eventParam )
+    {
+        BaseType_t xHigherPriorityTaskWoken;
+
+        if( ( event & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ) ) != 0 )
+        {
+            xHigherPriorityTaskWoken = pdFALSE;
+            xTaskNotifyFromISR( macTaskHandle, PIC32_MAC_EVENT_IF_PENDING, eSetBits, &xHigherPriorityTaskWoken );
+
+            if( xHigherPriorityTaskWoken )
+            {
+                portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
+            }
+        }
+    }
+
+    /*-----------------------------------------------------------*/
+
+    BaseType_t xGetPhyLinkStatus( void )
+    {
+        return macLinkStatus == true ? pdPASS : pdFAIL;
+    }
+
+
+    /* receive packets from the MAC driver */
+    static void MacRxPackets( void )
+    {
+        TCPIP_MAC_PACKET * pRxPkt;
+
+        /* get all the new MAC packets */
+        while( ( pRxPkt = ( macObject->TCPIP_MAC_PacketRx )( macCliHandle, 0, 0 ) ) != 0 )
+        {
+            MacProcessRxPacket( pRxPkt );
+        }
+    }
+
+    /*-----------------------------------------------------------*/
+
+    static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt )
+    {
+        bool pktSuccess, pktLost;
+        size_t pktLength;
+        TCPIP_MAC_DATA_SEGMENT * pSeg;
+        uint8_t * pPktBuff;
+        NetworkBufferDescriptor_t * pxBufferDescriptor;
+        IPStackEvent_t xRxEvent;
+
+        pxBufferDescriptor = 0;
+        pktSuccess = pktLost = false;
+
+        while( true )
+        {
+            pktLength = 0;
+            int nSegs = 0;
+            pSeg = pRxPkt->pDSeg;
+            pPktBuff = pSeg->segLoad;
+
+            /* calculate the packet size */
+            do
+            {
+                pktLength += pSeg->segLen;
+                pSeg = pSeg->next;
+                nSegs++;
+            } while( pSeg != 0 );
+
+            if( nSegs > 1 )
+            { /* no support in FreeRTOS for multi segment packets! */
+                break;
+            }
+
+            /* sizeof(TCPIP_MAC_ETHERNET_HEADER) is subtracted by the driver */
+            /* but FreeRTOS needs the whole frame! */
+            pktLength += sizeof( TCPIP_MAC_ETHERNET_HEADER );
+
+            if( eConsiderFrameForProcessing( pPktBuff ) != eProcessBuffer )
+            {
+                break;
+            }
+
+            /* get the network descriptor (no data buffer) to hold this packet */
+            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( 0, 0 );
+
+            if( pxBufferDescriptor == 0 )
+            {
+                pktLost = true;
+                break;
+            }
+
+            PIC32_MacAssociate( pRxPkt, pxBufferDescriptor, pktLength );
+
+            xRxEvent.eEventType = eNetworkRxEvent;
+            xRxEvent.pvData = ( void * ) pxBufferDescriptor;
+
+            /* Send the data to the TCP/IP stack */
+            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
+            { /* failed */
+                pktLost = true;
+            }
+            else
+            { /* success */
+                pktSuccess = true;
+                iptraceNETWORK_INTERFACE_RECEIVE();
+            }
+
+            break;
+        }
+
+        if( !pktSuccess )
+        { /* smth went wrong; nothing sent to the */
+            if( pxBufferDescriptor != 0 )
+            {
+                pxBufferDescriptor->pucEthernetBuffer = 0;
+                vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
+            }
+
+            if( pktLost )
+            {
+                iptraceETHERNET_RX_EVENT_LOST();
+            }
+
+            /* acknowledge the packet to the MAC driver */
+            if( pRxPkt->ackFunc )
+            {
+                ( *pRxPkt->ackFunc )( pRxPkt, pRxPkt->ackParam );
+            }
+            else
+            {
+                PIC32_MacPacketOrphan( pRxPkt );
+            }
+        }
+    }
+
+    #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )
+        /* */
+        static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
+                                     int argc,
+                                     char ** argv )
+        {
+            TCPIP_MAC_RES macRes;
+            TCPIP_MAC_RX_STATISTICS rxStatistics;
+            TCPIP_MAC_TX_STATISTICS txStatistics;
+            TCPIP_MAC_STATISTICS_REG_ENTRY regEntries[ 8 ];
+            TCPIP_MAC_STATISTICS_REG_ENTRY * pRegEntry;
+            int jx, hwEntries;
+            char entryName[ sizeof( pRegEntry->registerName ) + 1 ];
+
+            const void * cmdIoParam = pCmdIO->cmdIoParam;
+
+            if( argc != 1 )
+            {
+                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Usage: macinfo \r\n" );
+                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Ex: macinfo \r\n" );
+
+                return false;
+            }
+
+            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s driver statistics\r\n", macObject->macName );
+            macRes = ( macObject->TCPIP_MAC_StatisticsGet )( macCliHandle, &rxStatistics, &txStatistics );
+
+            if( macRes == TCPIP_MAC_RES_OK )
+            {
+                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnRxOkPackets: %d, nRxPendBuffers: %d, nRxSchedBuffers: %d, ",
+                                             rxStatistics.nRxOkPackets, rxStatistics.nRxPendBuffers, rxStatistics.nRxSchedBuffers );
+                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "nRxErrorPackets: %d, nRxFragmentErrors: %d\r\n", rxStatistics.nRxErrorPackets, rxStatistics.nRxFragmentErrors );
+                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnTxOkPackets: %d, nTxPendBuffers: %d, nTxErrorPackets: %d, nTxQueueFull: %d\r\n",
+                                             txStatistics.nTxOkPackets, txStatistics.nTxPendBuffers, txStatistics.nTxErrorPackets, txStatistics.nTxQueueFull );
+            }
+            else
+            {
+                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );
+            }
+
+            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s hardware statistics\r\n", macObject->macName );
+            macRes = ( macObject->TCPIP_MAC_RegisterStatisticsGet )( macCliHandle, regEntries, sizeof( regEntries ) / sizeof( *regEntries ), &hwEntries );
+
+            if( macRes == TCPIP_MAC_RES_OK )
+            {
+                entryName[ sizeof( entryName ) - 1 ] = 0;
+
+                for( jx = 0, pRegEntry = regEntries; jx < hwEntries && jx < sizeof( regEntries ) / sizeof( *regEntries ); jx++, pRegEntry++ )
+                {
+                    strncpy( entryName, pRegEntry->registerName, sizeof( entryName ) - 1 );
+                    ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\t%s: 0x%8x\r\n", entryName, pRegEntry->registerValue );
+                }
+            }
+            else
+            {
+                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );
+            }
+
+            return true;
+        }
+
+        /*-----------------------------------------------------------*/
+
+        static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
+                                     int argc,
+                                     char ** argv )
+        {
+            const void * cmdIoParam = pCmdIO->cmdIoParam;
+
+            union
+            {
+                uint32_t ul;
+                uint8_t b[ 4 ];
+            }
+            sUl;
+
+            sUl.ul = FreeRTOS_GetIPAddress();
+
+            bool linkUp = FreeRTOS_IsNetworkUp() == pdTRUE;
+
+            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "IP address: %d.%d.%d.%d\r\n", sUl.b[ 0 ], sUl.b[ 1 ], sUl.b[ 2 ], sUl.b[ 3 ] );
+            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Link is: %s\r\n", linkUp ? "Up" : "Down" );
+
+            return true;
+        }
+
+#include "aws_application_version.h"
+
+static int _Command_Version(SYS_CMD_DEVICE_NODE* pCmdIO, int argc, char** argv)
+{
+    configPRINTF( ( "App version - maj: %d, min: %d, build: %d\r\n",  xAppFirmwareVersion.u.x.ucMajor, xAppFirmwareVersion.u.x.ucMinor, xAppFirmwareVersion.u.x.usBuild) );
+    return 0;
+}
+
+    #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */
+#endif /* #ifdef PIC32_USE_ETHERNET */