NXP LPC1768 Ethernet driver for lwip and CMSIS-RTOS

Dependents:   EthernetInterface EthernetInterface EthernetInterface_RSF EthernetInterface ... more

Legacy Networking Libraries

This is an mbed 2 networking library. For mbed 5, the networking libraries have been revised to better support additional network stacks and thread safety here.

This library is based on the code of the NXP LPC port of the Lightweight TCP/IP Stack

Copyright(C) 2011, NXP Semiconductor
All rights reserved.

Software that is described herein is for illustrative purposes only
which provides customers with programming information regarding the
products. This software is supplied "AS IS" without any warranties.
NXP Semiconductors assumes no responsibility or liability for the
use of the software, conveys no license or title under any patent,
copyright, or mask work right to the product. NXP Semiconductors
reserves the right to make changes in the software without
notification. NXP Semiconductors also make no representation or
warranty that such application will be suitable for the specified
use without further testing or modification.

Files at this revision

API Documentation at this revision

Comitter:
bogdanm
Date:
Mon Aug 19 18:39:00 2013 +0300
Parent:
6:59b01b9349d5
Child:
8:59490137c7a7
Commit message:
Sync with official mbed library release 66

Changed in this revision

arch/lpc17_emac.c Show annotated file Show diff for this revision Revisions of this file
arch/lpc17_emac.h Show annotated file Show diff for this revision Revisions of this file
arch/lpc_emac_config.h Show annotated file Show diff for this revision Revisions of this file
arch/lpc_phy_dp83848.c Show annotated file Show diff for this revision Revisions of this file
--- a/arch/lpc17_emac.c	Mon Jun 03 12:06:46 2013 +0100
+++ b/arch/lpc17_emac.c	Mon Aug 19 18:39:00 2013 +0300
@@ -6,7 +6,7 @@
 * @version	1.0
 * @date		20. Nov. 2011
 * @author	NXP MCU SW Application Team
-* 
+*
 * Copyright(C) 2011, NXP Semiconductor
 * All rights reserved.
 *
@@ -62,7 +62,7 @@
 
 #if NO_SYS == 0
 /** \brief  Driver transmit and receive thread priorities
- * 
+ *
  * Thread priorities for receive thread and TX cleanup thread. Alter
  * to prioritize receive or transmit bandwidth. In a heavily loaded
  * system or with LEIP_DEBUG enabled, the priorities might be better
@@ -71,7 +71,7 @@
 #define TX_PRIORITY   (osPriorityNormal)
 
 /** \brief  Debug output formatter lock define
- * 
+ *
  * When using FreeRTOS and with LWIP_DEBUG enabled, enabling this
  * define will allow RX debug messages to not interleave with the
  * TX messages (so they are actually readable). Not enabling this
@@ -138,13 +138,19 @@
 #  else
 #     define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned))
 #  endif
-#else
-#   define ETHMEM_SECTION ALIGNED(8)
+#elif defined(TARGET_LPC1768)
+#  if defined(TOOLCHAIN_GCC_ARM)
+#     define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned))
+#  endif
+#endif
+
+#ifndef ETHMEM_SECTION
+#define ETHMEM_SECTION ALIGNED(8)
 #endif
 
 /** \brief  LPC EMAC driver work data
  */
-ETHMEM_SECTION struct lpc_enetdata lpc_enetdata; 
+ETHMEM_SECTION struct lpc_enetdata lpc_enetdata;
 
 /* Write a value via the MII link (non-blocking) */
 void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value)
@@ -196,7 +202,7 @@
 }
 
 /* Starts a read operation via the MII link (non-blocking) */
-void lpc_mii_read_noblock(u32_t PhyReg) 
+void lpc_mii_read_noblock(u32_t PhyReg)
 {
 	/* Read value at PHY address and register */
 	LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
@@ -204,7 +210,7 @@
 }
 
 /* Read a value via the MII link (blocking) */
-err_t lpc_mii_read(u32_t PhyReg, u32_t *data) 
+err_t lpc_mii_read(u32_t PhyReg, u32_t *data)
 {
 	u32_t mst = 250;
 	err_t sts = ERR_OK;
@@ -307,7 +313,7 @@
 }
 
 /** \brief  Sets up the RX descriptor ring buffers.
- * 
+ *
  *  This function sets up the descriptor list used for receive packets.
  *
  *  \param[in]  lpc_enetif  Pointer to driver data structure
@@ -414,7 +420,7 @@
 			LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
 				("lpc_low_level_input: Packet dropped with errors (0x%x)\n",
 				lpc_enetif->prxs[idx].statusinfo));
-			
+
 			p = NULL;
 		} else {
 			/* A packet is waiting, get length */
@@ -424,10 +430,31 @@
 			p = lpc_enetif->rxb[idx];
 			p->len = (u16_t) length;
 
-			/* Free pbuf from desriptor */
+			/* Free pbuf from descriptor */
 			lpc_enetif->rxb[idx] = NULL;
 			lpc_enetif->rx_free_descs++;
 
+			/* Attempt to queue new buffer(s) */
+			if (lpc_rx_queue(lpc_enetif->netif) == 0) {
+    			/* Drop the frame due to OOM. */
+    			LINK_STATS_INC(link.drop);
+
+    			/* Re-queue the pbuf for receive */
+    			lpc_rxqueue_pbuf(lpc_enetif, p);
+
+    			LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
+    				("lpc_low_level_input: Packet index %d dropped for OOM\n",
+    				idx));
+			
+#ifdef LOCK_RX_THREAD
+#if NO_SYS == 0
+        		sys_mutex_unlock(&lpc_enetif->TXLockMutex);
+#endif
+#endif
+
+		        return NULL;
+			}
+
 			LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
 				("lpc_low_level_input: Packet received: %p, size %d (index=%d)\n",
 				p, length, idx));
@@ -435,9 +462,6 @@
 			/* Save size */
 			p->tot_len = (u16_t) length;
 			LINK_STATS_INC(link.recv);
-
-			/* Queue new buffer(s) */
-			lpc_rx_queue(lpc_enetif->netif);
 		}
 	}
 
@@ -447,7 +471,7 @@
 #endif
 #endif
 
-	return p;  
+	return p;
 }
 
 /** \brief  Attempt to read a packet from the EMAC interface.
@@ -497,11 +521,11 @@
  */
 static s32_t lpc_packet_addr_notsafe(void *addr) {
 	/* Check for legal address ranges */
-#if defined(TARGET_LPC1768)  
+#if defined(TARGET_LPC1768)
 	if ((((u32_t) addr >= 0x2007C000) && ((u32_t) addr < 0x20083FFF))) {
 #elif defined(TARGET_LPC4088)
 	if ((((u32_t) addr >= 0x20000000) && ((u32_t) addr < 0x20007FFF))) {
-#endif  
+#endif
 	    return 0;
 	}
 	return 1;
@@ -618,14 +642,14 @@
 	struct lpc_enetdata *lpc_enetif = netif->state;
 	struct pbuf *q;
 	u8_t *dst;
-    u32_t idx;
+    u32_t idx, notdmasafe = 0;
 	struct pbuf *np;
-	u32_t dn, notdmasafe = 0;
+	s32_t dn;
 
 	/* Zero-copy TX buffers may be fragmented across mutliple payload
 	   chains. Determine the number of descriptors needed for the
 	   transfer. The pbuf chaining can be a mess! */
-	dn = (u32_t) pbuf_clen(p);
+	dn = (s32_t) pbuf_clen(p);
 
 	/* Test to make sure packet addresses are DMA safe. A DMA safe
 	   address is once that uses external memory or periphheral RAM.
@@ -641,7 +665,7 @@
 		/* Allocate a pbuf in DMA memory */
 		np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
 		if (np == NULL)
-			return ERR_MEM;	
+			return ERR_MEM;
 
 		/* This buffer better be contiguous! */
 		LWIP_ASSERT("lpc_low_level_output: New transmit pbuf is chained",
@@ -654,7 +678,7 @@
 	  		MEMCPY(dst, (u8_t *) q->payload, q->len);
 		  dst += q->len;
 		}
-		np->len = p->tot_len; 
+		np->len = p->tot_len;
 
 		LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
 			("lpc_low_level_output: Switched to DMA safe buffer, old=%p, new=%p\n",
@@ -759,12 +783,12 @@
         /* RX group interrupt(s): Give semaphore to wakeup RX receive task.*/
         sys_sem_signal(&lpc_enetdata.RxSem);
     }
-    
+
     if (ints & TXINTGROUP) {
         /* TX group interrupt(s): Give semaphore to wakeup TX cleanup task. */
         sys_sem_signal(&lpc_enetdata.TxCleanSem);
     }
-    
+
 	/* Clear pending interrupts */
 	LPC_EMAC->IntClear = ints;
 #endif
@@ -780,11 +804,11 @@
  */
 static void packet_rx(void* pvParameters) {
     struct lpc_enetdata *lpc_enetif = pvParameters;
-    
+
     while (1) {
         /* Wait for receive task to wakeup */
         sys_arch_sem_wait(&lpc_enetif->RxSem, 0);
-        
+
         /* Process packets until all empty */
         while (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex)
             lpc_enetif_input(lpc_enetif->netif);
@@ -802,18 +826,18 @@
 static void packet_tx(void* pvParameters) {
     struct lpc_enetdata *lpc_enetif = pvParameters;
     s32_t idx;
-    
+
     while (1) {
         /* Wait for transmit cleanup task to wakeup */
         sys_arch_sem_wait(&lpc_enetif->TxCleanSem, 0);
-        
+
         /* Error handling for TX underruns. This should never happen unless
            something is holding the bus or the clocks are going too slow. It
             can probably be safely removed. */
         if (LPC_EMAC->IntStatus & EMAC_INT_TX_UNDERRUN) {
             LINK_STATS_INC(link.err);
             LINK_STATS_INC(link.drop);
-            
+
 #if NO_SYS == 0
             /* Get exclusive access */
             sys_mutex_lock(&lpc_enetif->TXLockMutex);
@@ -821,7 +845,7 @@
             /* Reset the TX side */
             LPC_EMAC->MAC1 |= EMAC_MAC1_RES_TX;
             LPC_EMAC->IntClear = EMAC_INT_TX_UNDERRUN;
-            
+
             /* De-allocate all queued TX pbufs */
             for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) {
                 if (lpc_enetif->txb[idx] != NULL) {
@@ -829,7 +853,7 @@
                     lpc_enetif->txb[idx] = NULL;
                 }
             }
-            
+
 #if NO_SYS == 0
             /* Restore access */
             sys_mutex_unlock(&lpc_enetif->TXLockMutex);
@@ -855,8 +879,8 @@
 
 	/* Enable MII clocking */
 	LPC_SC->PCONP |= CLKPWR_PCONP_PCENET;
-	
-#if defined(TARGET_LPC1768)  
+
+#if defined(TARGET_LPC1768)
 	LPC_PINCON->PINSEL2 = 0x50150105;                  /* Enable P1 Ethernet Pins. */
 	LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
 #elif defined(TARGET_LPC4088)
@@ -880,8 +904,8 @@
   LPC_IOCON->P1_16 |= 0x01;     /* ENET_MDC */
   LPC_IOCON->P1_17 &= ~0x07;
   LPC_IOCON->P1_17 |= 0x01;     /* ENET_MDIO */
-#endif  
-	
+#endif
+
 	/* Reset all MAC logic */
 	LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX |
 		EMAC_MAC1_RES_RX | EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES |
@@ -889,7 +913,7 @@
 	LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES |
 		EMAC_CR_PASS_RUNT_FRM;
 	osDelay(10);
-	
+
 	/* Initial MAC initialization */
 	LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
 	LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN |
@@ -980,7 +1004,7 @@
  *
  * \param[in] netif the lwip network interface structure for this lpc_enetif
  * \param[in] q Pointer to pbug to send
- * \param[in] ipaddr IP address 
+ * \param[in] ipaddr IP address
  * \return ERR_OK or error code
  */
 err_t lpc_etharp_output(struct netif *netif, struct pbuf *q,
@@ -1017,11 +1041,20 @@
 	err_t err;
 
 	LWIP_ASSERT("netif != NULL", (netif != NULL));
-    
+
 	lpc_enetdata.netif = netif;
 
 	/* set MAC hardware address */
+#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
+	netif->hwaddr[0] = MBED_MAC_ADDR_0;
+	netif->hwaddr[1] = MBED_MAC_ADDR_1;
+	netif->hwaddr[2] = MBED_MAC_ADDR_2;
+	netif->hwaddr[3] = MBED_MAC_ADDR_3;
+	netif->hwaddr[4] = MBED_MAC_ADDR_4;
+	netif->hwaddr[5] = MBED_MAC_ADDR_5;
+#else
 	mbed_mac_address((char *)netif->hwaddr);
+#endif
 	netif->hwaddr_len = ETHARP_HWADDR_LEN;
 
  	/* maximum transfer unit */
@@ -1068,12 +1101,12 @@
 	err = sys_sem_new(&lpc_enetdata.TxCleanSem, 0);
 	LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK));
 	sys_thread_new("txclean_thread", packet_tx, netif->state, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY);
-	
+
 	/* periodic PHY status update */
 	osTimerId phy_timer = osTimerCreate(osTimer(phy_update), osTimerPeriodic, (void *)netif);
 	osTimerStart(phy_timer, 250);
 #endif
-    
+
     return ERR_OK;
 }
 
--- a/arch/lpc17_emac.h	Mon Jun 03 12:06:46 2013 +0100
+++ b/arch/lpc17_emac.h	Mon Aug 19 18:39:00 2013 +0300
@@ -21,31 +21,31 @@
 * notification. NXP Semiconductors also make no representation or
 * warranty that such application will be suitable for the specified
 * use without further testing or modification.
-**********************************************************************/
-
-#ifndef __LPC17_EMAC_H
-#define __LPC17_EMAC_H
-
+**********************************************************************/
+
+#ifndef __LPC17_EMAC_H
+#define __LPC17_EMAC_H
+
 #include "lwip/opt.h"
-#include "lwip/netif.h"
+#include "lwip/netif.h"
 
 #ifdef __cplusplus
 extern "C"
 {
-#endif
+#endif
 
 /* These functions are only visible when not using an RTOS */ 
 #if NO_SYS == 1
-void lpc_enetif_input(struct netif *netif);
+void lpc_enetif_input(struct netif *netif);
 s32_t lpc_tx_ready(struct netif *netif);
-s32_t lpc_rx_queue(struct netif *netif);
-void lpc_tx_reclaim(struct netif *netif);
+s32_t lpc_rx_queue(struct netif *netif);
+void lpc_tx_reclaim(struct netif *netif);
 #endif
 
 err_t lpc_enetif_init(struct netif *netif);
 
 #ifdef __cplusplus
 }
-#endif
+#endif
 
-#endif /* __LPC17_EMAC_H */
+#endif /* __LPC17_EMAC_H */
--- a/arch/lpc_emac_config.h	Mon Jun 03 12:06:46 2013 +0100
+++ b/arch/lpc_emac_config.h	Mon Aug 19 18:39:00 2013 +0300
@@ -1,45 +1,45 @@
-/**********************************************************************
-* $Id$		lpc_emac_config.h			2011-11-20
-*//**
-* @file		lpc_emac_config.h
-* @brief	PHY and EMAC configuration file
-* @version	1.0
-* @date		20 Nov. 2011
-* @author	NXP MCU SW Application Team
-* 
-* Copyright(C) 2011, NXP Semiconductor
-* All rights reserved.
-*
-***********************************************************************
-* Software that is described herein is for illustrative purposes only
-* which provides customers with programming information regarding the
-* products. This software is supplied "AS IS" without any warranties.
-* NXP Semiconductors assumes no responsibility or liability for the
-* use of the software, conveys no license or title under any patent,
-* copyright, or mask work right to the product. NXP Semiconductors
-* reserves the right to make changes in the software without
-* notification. NXP Semiconductors also make no representation or
-* warranty that such application will be suitable for the specified
-* use without further testing or modification.
+/**********************************************************************
+* $Id$		lpc_emac_config.h			2011-11-20
+*//**
+* @file		lpc_emac_config.h
+* @brief	PHY and EMAC configuration file
+* @version	1.0
+* @date		20 Nov. 2011
+* @author	NXP MCU SW Application Team
+* 
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+***********************************************************************
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
 **********************************************************************/
 
 #ifndef __LPC_EMAC_CONFIG_H
 #define __LPC_EMAC_CONFIG_H
 
 #include "lwip/opt.h"
-
+
 #ifdef __cplusplus
 extern "C"
 {
 #endif
-
-/** @defgroup lwip_phy_config	LWIP PHY configuration
- * @ingroup lwip_phy
- *
- * Configuration options for the PHY connected to the LPC EMAC.
- * @{
- */
-
+
+/** @defgroup lwip_phy_config	LWIP PHY configuration
+ * @ingroup lwip_phy
+ *
+ * Configuration options for the PHY connected to the LPC EMAC.
+ * @{
+ */
+
 /** \brief  The PHY address connected the to MII/RMII
  */
 #define LPC_PHYDEF_PHYADDR 1    /**< The PHY address on the PHY device. */
@@ -62,18 +62,18 @@
  *          operation if PHY_USE_AUTONEG is not enabled.
  */
 #define PHY_USE_100MBS 1 /**< Sets data rate to 100Mbps. */
-
-/**		  
- * @}
+
+/**		  
+ * @}
  */
-
-/** @defgroup lwip_emac_config	LWIP EMAC configuration
- * @ingroup lwip_emac
- *
- * Configuration options for the LPC EMAC.
- * @{
+
+/** @defgroup lwip_emac_config	LWIP EMAC configuration
+ * @ingroup lwip_emac
+ *
+ * Configuration options for the LPC EMAC.
+ * @{
  */
-
+
 /** \brief  Selects RMII or MII connection type in the EMAC peripheral
  */
 #define LPC_EMAC_RMII 1         /**< Use the RMII or MII driver variant .*/
@@ -87,21 +87,21 @@
  *          be a minimum value of 2.
  */
 #define LPC_NUM_BUFF_TXDESCS 3
-
-/** \brief  Set this define to 1 to enable bounce buffers for transmit pbufs
- *          that cannot be sent via the zero-copy method. Some chained pbufs
- *          may have a payload address that links to an area of memory that
- *          cannot be used for transmit DMA operations. If this define is
- *          set to 1, an extra check will be made with the pbufs. If a buffer
- *          is determined to be non-usable for zero-copy, a temporary bounce
- *          buffer will be created and used instead.
- */
-#define LPC_TX_PBUF_BOUNCE_EN 1
 
-/**		  
- * @}
+/** \brief  Set this define to 1 to enable bounce buffers for transmit pbufs
+ *          that cannot be sent via the zero-copy method. Some chained pbufs
+ *          may have a payload address that links to an area of memory that
+ *          cannot be used for transmit DMA operations. If this define is
+ *          set to 1, an extra check will be made with the pbufs. If a buffer
+ *          is determined to be non-usable for zero-copy, a temporary bounce
+ *          buffer will be created and used instead.
  */
-
+#define LPC_TX_PBUF_BOUNCE_EN 1
+
+/**		  
+ * @}
+ */
+
 #ifdef __cplusplus
 }
 #endif
--- a/arch/lpc_phy_dp83848.c	Mon Jun 03 12:06:46 2013 +0100
+++ b/arch/lpc_phy_dp83848.c	Mon Aug 19 18:39:00 2013 +0300
@@ -228,9 +228,9 @@
 	u32_t tmp;
 	s32_t i;
 
-	physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2;
-	physts.phy_full_duplex = olddphysts.phy_full_duplex = 2;
-	physts.phy_link_active = olddphysts.phy_link_active = 2;
+	physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 0;
+	physts.phy_full_duplex = olddphysts.phy_full_duplex = 0;
+	physts.phy_link_active = olddphysts.phy_link_active = 0;
 	phyustate = 0;
 
 	/* Only first read and write are checked for failure */