lpcware

lwip LPC176x EMAC

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by nkarakotas on Wed Dec 21 07:37:55 MST 2011
Hi,

After using uIP I decided to try out lwip as it's designed for 32 bit and offer better performance. Im having a few problems with the EMAC drivers. I keep on receiving corrupted packets unless there is somewhere problems when copying the data to the pbuf. Below is the EMAC.c and the part of the ethernetif.c. Does anyone have any clues?

Regards


static void ethernetif_input( void * pvParameters )
{

    struct ethernetif   *ethernetif;
    struct eth_hdr      *ethhdr;
    struct pbuf         *p;
    struct netif *netif;


    netif = (struct netif*) pvParameters;

    for( ;; )
    {
        do
        {
            ethernetif = netif->state;

            /* move received packet into a new pbuf */
            p = low_level_input( netif );

            if( p == NULL )
            {
                /* No packet could be read.  Wait a for an interrupt to tell us
                there is more data available. */
                vEMACWaitForInput();
            }

        } while( p == NULL );

        /* points to packet payload, which starts with an Ethernet header */
        ethhdr = p->payload;

        switch( htons( ethhdr->type ) )
        {
            /* IP packet? */
            case ETHTYPE_IP:
            case ETHTYPE_ARP:
                 if (netif->input(p, netif)!=ERR_OK){
                     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
                     pbuf_free(p);
                     p = NULL;
                 }
                 break;
        }


    }
}
static struct pbuf *low_level_input( struct netif *netif )
{

    struct pbuf             *p = NULL;
    static xSemaphoreHandle xRxSemaphore = NULL;

    /* Parameter not used. */
    ( void ) netif;

    if( xRxSemaphore == NULL )
        vSemaphoreCreateBinary( xRxSemaphore );

    /* Access to the emac is guarded using a semaphore. */
       if( xSemaphoreTake( xRxSemaphore, netifGUARD_BLOCK_TIME ) )
    {
        if( EMAC_CheckReceiveIndex() == TRUE )
        {

            p = EMAC_ReadPacketBuffer( NULL );

            if(p != NULL){

                #if LINK_STATS
                    lwip_stats.link.recv++;
                #endif /* LINK_STATS */

            }
            else
            {
                // drop packet();
                #if LINK_STATS
                    lwip_stats.link.memerr++;
                    lwip_stats.link.drop++;
                #endif /* LINK_STATS */
            }
        }

        xSemaphoreGive( xRxSemaphore );
    }

    return p;
}
Part of [B]emac.c[/B]
/*--------------------------- rx_descr_init ---------------------------------*/
/*********************************************************************//**
* @brief       Initializes RX Descriptor
* @param[in]   None
* @return      None
***********************************************************************/
static void rx_descr_init (void)
{

    uint32_t i;

    for (i = 0; i < EMAC_NUM_RX_FRAG; i++)
    {
        RX_DESC_PACKET(i)  = RX_BUF(i);
        RX_DESC_CTRL(i)    = EMAC_RCTRL_INT | (EMAC_ETH_FRAG_SIZE-1);
        RX_STAT_INFO(i)    = 0;
        RX_STAT_HASHCRC(i) = 0;
    }

    /* Set EMAC Receive Descriptor Registers. */
    LPC_EMAC->RxDescriptor    = RX_DESC_BASE;
    LPC_EMAC->RxStatus        = RX_STAT_BASE;
    LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG-1;

    /* Rx Descriptors Point to 0 */
    LPC_EMAC->RxConsumeIndex  = 0;
}

struct pbuf* EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
{

    struct pbuf* p;
    uint32_t size;
    uint32_t Index;

    /* init p pointer */
    p = NULL;

    Index = LPC_EMAC->RxConsumeIndex;

    if(Index != LPC_EMAC->RxProduceIndex)
    {
        size = (RX_STAT_INFO(Index) & 0x7ff)+1;
        if (size > EMAC_ETH_FRAG_SIZE) size = EMAC_ETH_FRAG_SIZE;

        /* allocate buffer */
        p = pbuf_alloc(PBUF_LINK, size, PBUF_RAM);
        if (p != NULL)
        {
            struct pbuf* q;
            uint8_t *ptr;

            ptr = (uint8_t*)RX_BUF(Index);
            for (q = p; q != NULL; q= q->next)
            {
                memcpy(q->payload, ptr, q->len);
                ptr += q->len;
            }
        }

        /* move Index to the next */
        if(++Index > LPC_EMAC->RxDescriptorNumber)
            Index = 0;

        /* set consume index */
        LPC_EMAC->RxConsumeIndex = Index;
    }


    return p;
}

void ENET_IRQHandler( void )
{
unsigned long ulStatus;
long lHigherPriorityTaskWoken = pdFALSE;

    ulStatus = LPC_EMAC->IntStatus;

    /* Clear the interrupt. */
    LPC_EMAC->IntClear = ulStatus;

    if( ulStatus & EMAC_INT_RX_DONE )
    {
        /* Ensure the uIP task is not blocked as data has arrived. */
        xSemaphoreGiveFromISR( xSemaphore, &lHigherPriorityTaskWoken );
    }

    if( ulStatus & EMAC_INT_TX_DONE )
    {
        EMAC_UpdateTxProduceIndex();
    }

    portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
}


DEBUG OUTPUT:
netif_set_ipaddr: netif address being changed
netif: IP address of interface 192.168.1.16
netif: netmask of interface 255.255.255.0
netif: GW address of interface 192.168.1.30
netif: added interface em IP addr 192.168.1.16 netmask 255.255.255.0 gw 192.168.1.30
pbuf_alloc(length=64)
pbuf_alloc(length=64) == 0x10005e8c
tcpip_thread: PACKET 0x10001a10
IP packet dropped due to bad version number 15
IP header:
+-------------------------------+
|15 |15 |  0xff |     65535     | (v, hl, tos, len)
+-------------------------------+
|    65535      |000|      26   | (id, flags, offset)
+-------------------------------+
|  146  |  224  |    0x824b     | (ttl, proto, chksum)
+-------------------------------+
|    8  |    6  |    0  |    1  | (src)
+-------------------------------+
|    8  |    0  |    6  |    4  | (dest)
+-------------------------------+
pbuf_free(0x10005e8c)
pbuf_free: deallocating 0x10005e8c

Outcomes