Rewrite from scratch a TCP/IP stack for mbed. So far the following parts are usable: Drivers: - EMAC driver (from CMSIS 2.0) Protocols: - Ethernet protocol - ARP over ethernet for IPv4 - IPv4 over Ethernet - ICMPv4 over IPv4 - UDPv4 over IPv4 APIs: - Sockets for UDPv4 The structure of this stack is designed to be very modular. Each protocol can register one or more protocol to handle its payload, and in each protocol, an API can be hooked (like Sockets for example). This is an early release.

mbedNetIF.cpp

Committer:
Benoit
Date:
2011-06-26
Revision:
7:8e12f7357b9f
Parent:
5:3cd83fcb1467

File content as of revision 7:8e12f7357b9f:

/*
 * $Id: mbedNetIF.c 28 2011-06-10 10:16:30Z benoit $
 * $Author: benoit $
 * $Date: 2011-06-10 12:16:30 +0200 (ven., 10 juin 2011) $
 * $Rev: 28 $
 * 
 * 
 * 
 * 
 * 
 */
 
#include "mbedNetIF.h"
#include "Ethernet.h"
#include "mbedNet.h"
#include "NetIF.h"
#include "Debug.h"
#include "lpc17xx_pinsel.h"
#include "lpc17xx_emac.h"
#include <string.h>


#define    DEBUG_CURRENT_MODULE_NAME    "mbedNetIF"
#define    DEBUG_CURRENT_MODULE_ID        DEBUG_MODULE_MBEDNETIF


static int32_t Init(NetIF_t *netif);
static int32_t Read(uint8_t **packet, int32_t *length);
static int32_t Write(uint8_t *packet, int32_t length);
static void Enable(void);
static void Disable(void);
static uint8_t *GetTxBuffer(void);


#define    MBEDNETIF_DRIVER_NAME    "mbedEMAC"


static EMAC_CFG_Type			Emac_Config;
static PINSEL_CFG_Type			PinCfg;
static uint8_t					rxPacket[EMAC_ETH_MAX_FLEN],
								txPacket[EMAC_ETH_MAX_FLEN];
static EMAC_PACKETBUF_Type		rxBuffer,
								txBuffer;
static NetIF_t					*mbedNetIF = NULL;

static Bool_t EMAC_TxBufferNotFull(void);


NetIF_Driver_t mbedNetIF_Driver = 
{ 
    MBEDNETIF_DRIVER_NAME,  
    Init, 
    Read, 
    Write, 
	Enable,
	Disable,
    GetTxBuffer,
    &ethernet,
    EMAC_ETH_MAX_FLEN
};


static int32_t Init(NetIF_t *netIF)
{
    int32_t                result = 0;
    uint8_t                initMac[6];
    Ethernet_Addr_t        *hwAddress = (Ethernet_Addr_t *)netIF->driverParameter;

    initMac[0] = hwAddress->MA0;
    initMac[1] = hwAddress->MA1;
    initMac[2] = hwAddress->MA2;
    initMac[3] = hwAddress->MA3;
    initMac[4] = hwAddress->MA4;
    initMac[5] = hwAddress->MA5;
    
    DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing device driver '%s' with hardware address %02x:%02x:%02x:%02x:%02x:%02x",
        netIF->driver->name,
        initMac[0],
        initMac[1],
        initMac[2],
        initMac[3],
        initMac[4],
        initMac[5]
    ));

    rxBuffer.pbDataBuf = (uint32_t *)&rxPacket;
	
	mbedNetIF = netIF;
    
    PinCfg.Funcnum = 1;
    PinCfg.OpenDrain = 0;
    PinCfg.Pinmode = 0;
    PinCfg.Portnum = 1;

    PinCfg.Pinnum = 0;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 1;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 4;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 8;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 9;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 10;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 14;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 15;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 16;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 17;
    PINSEL_ConfigPin(&PinCfg);
    
    Emac_Config.Mode = EMAC_MODE_AUTO;
    Emac_Config.pbEMAC_Addr = initMac;
    
    memset(txPacket, 0, sizeof(txPacket));
    
    if (EMAC_Init(&Emac_Config) == ERROR)
    {
        DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Error during initializing EMAC, restart after a while"));
    }

    Write(txPacket, 14);    /* Send dummy frame at init as workaround described in chapter 3.3 of errata sheet document 'ES_LPC176x' rev 9 from June 2011 page 6 */
	
	//NVIC_SetPriority(ENET_IRQn, 10);
	
	Disable();
		
    DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("leaving with code %d", result));
    return result;
}


static int32_t Read(uint8_t **packet, int32_t *length)
{
    int32_t        result = 0;

    if (EMAC_CheckReceiveIndex() == FALSE)
    {
        mbedNet_LastError = mbedNetResult_QueueEmpty;
        result = -1;
    }
	else
	{
	    rxBuffer.ulDataLen = EMAC_GetReceiveDataSize();
	    *length = rxBuffer.ulDataLen;
	    EMAC_ReadPacketBuffer(&rxBuffer);
	    EMAC_UpdateRxConsumeIndex();
	    
	    *packet = (uint8_t *)rxBuffer.pbDataBuf;
	    DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("received %d byte frame", *length));
	}
    
    DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("leaving with code %d", result));
    return result;
}


static int32_t Write(uint8_t *packet, int32_t length)
{
    int32_t        result = 0;
    
    DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("request to send %d bytes", length));
    
    if (EMAC_TxBufferNotFull())
    {
        DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0)
        {
            Debug_DumpBufferHex(packet, length);
        }
        txBuffer.ulDataLen = length;
        txBuffer.pbDataBuf = (uint32_t *)packet;
        EMAC_WritePacketBuffer(&txBuffer);
        EMAC_UpdateTxProduceIndex();
        DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("transmitted %d byte frame", length));
    }
    else
    {
        DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("transmission queue is full"));
        mbedNet_LastError = mbedNetResult_QueueEmpty;
        result = -1;
    }
    DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("leaving with code %d", result));
    return result;
}


static void Enable(void)
{
	/* Enable receive and transmit mode of MAC Ethernet core */
	LPC_EMAC->Command  |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN);
	LPC_EMAC->MAC1     |= EMAC_MAC1_REC_EN;	
	NVIC_EnableIRQ(ENET_IRQn);
}


static void Disable(void)
{
	/* Disable receive and transmit mode of MAC Ethernet core */
	NVIC_DisableIRQ(ENET_IRQn);
	LPC_EMAC->Command  &= ~(EMAC_CR_RX_EN | EMAC_CR_TX_EN);
	LPC_EMAC->MAC1     &= ~EMAC_MAC1_REC_EN;	
	while(EMAC_CheckReceiveIndex()) EMAC_UpdateRxConsumeIndex();
}


static uint8_t *GetTxBuffer(void)
{
    return txPacket;
}


static Bool_t EMAC_TxBufferNotFull(void)
{
    uint32_t    tmp = LPC_EMAC->TxProduceIndex + 1;
    
    if (tmp == EMAC_NUM_TX_FRAG) tmp = 0;
    return (LPC_EMAC->TxConsumeIndex != tmp) ? True : False;
}


extern "C" void ENET_IRQHandler(void)
{
	uint32_t 		status;
	NetPacket_t		rxP;
	
	status = LPC_EMAC->IntStatus;
	LPC_EMAC->IntClear = status;
	
	if(status & EMAC_INT_RX_DONE) 
	{
		while(EMAC_CheckReceiveIndex() == TRUE)
		{
			if (Read(&rxP.data, &rxP.length) == 0)
			{
				rxP.depth = -1;
				ethernet.HandlePacket(mbedNetIF, &rxP);
			}
		}
	}
}