Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip-eth by
Diff: arch/lpc17_emac.c
- Revision:
- 1:0c9d93e2f51c
- Parent:
- 0:f4db29eb9e47
- Child:
- 2:5208926bd863
diff -r f4db29eb9e47 -r 0c9d93e2f51c arch/lpc17_emac.c
--- a/arch/lpc17_emac.c Fri Jun 22 09:32:29 2012 +0000
+++ b/arch/lpc17_emac.c Fri Jun 22 11:17:21 2012 +0000
@@ -1,44 +1,47 @@
-/**********************************************************************
-* $Id$ lpc17_emac.c 2011-11-20
-*//**
-* @file lpc17_emac.c
-* @brief LPC17 ethernet driver for LWIP
-* @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$ lpc17_emac.c 2011-11-20
+*//**
+* @file lpc17_emac.c
+* @brief LPC17 ethernet driver for LWIP
+* @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.
**********************************************************************/
-#include "lwip/opt.h"
-#include "lwip/sys.h"
-#include "lwip/def.h"
-#include "lwip/mem.h"
-#include "lwip/pbuf.h"
-#include "lwip/stats.h"
-#include "lwip/snmp.h"
-#include "netif/etharp.h"
+#include "lwip/opt.h"
+#include "lwip/sys.h"
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/stats.h"
+#include "lwip/snmp.h"
+#include "netif/etharp.h"
#include "netif/ppp_oe.h"
-#include "lpc177x_8x_emac.h"
-#include "lpc177x_8x_clkpwr.h"
+#include "lpc17xx_emac.h"
#include "lpc17_emac.h"
#include "lpc_emac_config.h"
#include "lpc_phy.h"
-
+#include "sys_arch.h"
+
+#include "mbed_interface.h"
+#include <string.h>
+
#ifndef LPC_EMAC_RMII
#error LPC_EMAC_RMII is not defined!
#endif
@@ -50,92 +53,92 @@
#if LPC_NUM_BUFF_RXDESCS < 3
#error LPC_NUM_BUFF_RXDESCS must be at least 3
#endif
-
-/** @defgroup lwip17xx_emac_DRIVER lpc17 EMAC driver for LWIP
- * @ingroup lwip_emac
- *
- * @{
+
+/** @defgroup lwip17xx_emac_DRIVER lpc17 EMAC driver for LWIP
+ * @ingroup lwip_emac
+ *
+ * @{
*/
-
-#if NO_SYS == 0
-/** \brief Driver transmit and receive thread priorities
- *
+
+#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
* the same. */
-#define tskRECPKT_PRIORITY (DEFAULT_THREAD_PRIO + 4)
-#define tskTXCLEAN_PRIORITY (DEFAULT_THREAD_PRIO + 5)
-
-/** \brief Debug output formatter lock define
- *
+#define RX_PRIORITY (osPriorityNormal)
+#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
- * define when the system is under load will cause the output to
- * be unreadable. There is a small tradeoff in performance for this
+ * TX messages (so they are actually readable). Not enabling this
+ * define when the system is under load will cause the output to
+ * be unreadable. There is a small tradeoff in performance for this
* so use it only for debug. */
//#define LOCK_RX_THREAD
-
-/** \brief Receive group interrupts
- */
-#define RXINTGROUP (EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_DONE)
-
-/** \brief Transmit group interrupts
- */
-#define TXINTGROUP (EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR | EMAC_INT_TX_DONE)
-#else
-#define RXINTGROUP 0
-#define TXINTGROUP 0
-#endif
-
- /** \brief Structure of a TX/RX descriptor
- */
-typedef struct
-{
- volatile u32_t packet; /**< Pointer to buffer */
- volatile u32_t control; /**< Control word */
-} LPC_TXRX_DESC_T;
-
-/** \brief Structure of a RX status entry
- */
-typedef struct
-{
- volatile u32_t statusinfo; /**< RX status word */
- volatile u32_t statushashcrc; /**< RX hash CRC */
+
+/** \brief Receive group interrupts
+ */
+#define RXINTGROUP (EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_DONE)
+
+/** \brief Transmit group interrupts
+ */
+#define TXINTGROUP (EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR | EMAC_INT_TX_DONE)
+#else
+#define RXINTGROUP 0
+#define TXINTGROUP 0
+#endif
+
+ /** \brief Structure of a TX/RX descriptor
+ */
+typedef struct
+{
+ volatile u32_t packet; /**< Pointer to buffer */
+ volatile u32_t control; /**< Control word */
+} LPC_TXRX_DESC_T;
+
+/** \brief Structure of a RX status entry
+ */
+typedef struct
+{
+ volatile u32_t statusinfo; /**< RX status word */
+ volatile u32_t statushashcrc; /**< RX hash CRC */
} LPC_TXRX_STATUS_T;
-
-/* LPC EMAC driver data structure */
-struct lpc_enetdata {
- /* prxs must be 8 byte aligned! */
- LPC_TXRX_STATUS_T prxs[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX statuses */
- struct netif *netif; /**< Reference back to LWIP parent netif */
- LPC_TXRX_DESC_T ptxd[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX descriptor list */
- LPC_TXRX_STATUS_T ptxs[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX statuses */
- LPC_TXRX_DESC_T prxd[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX descriptor list */
- struct pbuf *rxb[LPC_NUM_BUFF_RXDESCS]; /**< RX pbuf pointer list, zero-copy mode */
- u32_t rx_fill_desc_index; /**< RX descriptor next available index */
- volatile u32_t rx_free_descs; /**< Count of free RX descriptors */
- struct pbuf *txb[LPC_NUM_BUFF_TXDESCS]; /**< TX pbuf pointer list, zero-copy mode */
- u32_t lpc_last_tx_idx; /**< TX last descriptor index, zero-copy mode */
-#if NO_SYS == 0
+
+/* LPC EMAC driver data structure */
+struct lpc_enetdata {
+ /* prxs must be 8 byte aligned! */
+ LPC_TXRX_STATUS_T prxs[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX statuses */
+ struct netif *netif; /**< Reference back to LWIP parent netif */
+ LPC_TXRX_DESC_T ptxd[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX descriptor list */
+ LPC_TXRX_STATUS_T ptxs[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX statuses */
+ LPC_TXRX_DESC_T prxd[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX descriptor list */
+ struct pbuf *rxb[LPC_NUM_BUFF_RXDESCS]; /**< RX pbuf pointer list, zero-copy mode */
+ u32_t rx_fill_desc_index; /**< RX descriptor next available index */
+ volatile u32_t rx_free_descs; /**< Count of free RX descriptors */
+ struct pbuf *txb[LPC_NUM_BUFF_TXDESCS]; /**< TX pbuf pointer list, zero-copy mode */
+ u32_t lpc_last_tx_idx; /**< TX last descriptor index, zero-copy mode */
+#if NO_SYS == 0
sys_sem_t RxSem; /**< RX receive thread wakeup semaphore */
sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */
sys_mutex_t TXLockMutex; /**< TX critical section mutex */
- xSemaphoreHandle xTXDCountSem; /**< TX free buffer counting semaphore */
-#endif
-};
-
-/** \brief LPC EMAC driver work data
- */
+ sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */
+#endif
+};
+
+/** \brief LPC EMAC driver work data
+ */
ALIGNED(8) 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)
{
/* Write value at PHY address and register */
- LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
- LPC_EMAC->MWTD = Value;
+ LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
+ LPC_EMAC->MWTD = Value;
}
/* Write a value via the MII link (blocking) */
@@ -145,16 +148,16 @@
err_t sts = ERR_OK;
/* Write value at PHY address and register */
- lpc_mii_write_noblock(PhyReg, Value);
-
+ lpc_mii_write_noblock(PhyReg, Value);
+
/* Wait for unbusy status */
while (mst > 0) {
sts = LPC_EMAC->MIND;
- if ((sts & EMAC_MIND_BUSY) == 0)
+ if ((sts & EMAC_MIND_BUSY) == 0)
mst = 0;
else {
mst--;
- msDelay(1);
+ osDelay(1);
}
}
@@ -175,7 +178,7 @@
{
u32_t data = LPC_EMAC->MRDD;
LPC_EMAC->MCMD = 0;
-
+
return data;
}
@@ -183,8 +186,8 @@
void lpc_mii_read_noblock(u32_t PhyReg)
{
/* Read value at PHY address and register */
- LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
- LPC_EMAC->MCMD = EMAC_MCMD_READ;
+ LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
+ LPC_EMAC->MCMD = EMAC_MCMD_READ;
}
/* Read a value via the MII link (blocking) */
@@ -199,17 +202,17 @@
/* Wait for unbusy status */
while (mst > 0) {
sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL;
- if ((sts & EMAC_MIND_BUSY) == 0) {
+ if ((sts & EMAC_MIND_BUSY) == 0) {
mst = 0;
*data = LPC_EMAC->MRDD;
} else {
mst--;
- msDelay(1);
+ osDelay(1);
}
}
LPC_EMAC->MCMD = 0;
-
+
if (sts != 0)
sts = ERR_TIMEOUT;
@@ -218,10 +221,10 @@
/** \brief Queues a pbuf into the RX descriptor list
*
- * \param[in] lpc_enetif Pointer to the drvier data structure
- * \param[in] p Pointer to pbuf to queue
+ * \param[in] lpc_enetif Pointer to the drvier data structure
+ * \param[in] p Pointer to pbuf to queue
*/
-static void lpc_rxqueue_pbuf(struct lpc_enetdata *lpc_enetif, struct pbuf *p)
+static void lpc_rxqueue_pbuf(struct lpc_enetdata *lpc_enetif, struct pbuf *p)
{
u32_t idx;
@@ -254,8 +257,8 @@
/** \brief Attempt to allocate and requeue a new pbuf for RX
*
- * \param[in] netif Pointer to the netif structure
- * \returns 1 if a packet was allocated and requeued, otherwise 0
+ * \param[in] netif Pointer to the netif structure
+ * \returns 1 if a packet was allocated and requeued, otherwise 0
*/
s32_t lpc_rx_queue(struct netif *netif)
{
@@ -279,7 +282,7 @@
/* pbufs allocated from the RAM pool should be non-chained. */
LWIP_ASSERT("lpc_rx_queue: pbuf is not contiguous (chained)",
pbuf_clen(p) <= 1);
-
+
/* Queue packet */
lpc_rxqueue_pbuf(lpc_enetif, p);
@@ -299,8 +302,6 @@
*/
static err_t lpc_rx_setup(struct lpc_enetdata *lpc_enetif)
{
- s32_t idx;
-
/* Setup pointers to RX structures */
LPC_EMAC->RxDescriptor = (u32_t) &lpc_enetif->prxd[0];
LPC_EMAC->RxStatus = (u32_t) &lpc_enetif->prxs[0];
@@ -317,31 +318,30 @@
/** \brief Allocates a pbuf and returns the data from the incoming packet.
*
- * \param[in] netif the lwip network interface structure for this lpc_enetif
- * \return a pbuf filled with the received packet (including MAC header)
- * NULL on memory error
+ * \param[in] netif the lwip network interface structure for this lpc_enetif
+ * \return a pbuf filled with the received packet (including MAC header)
+ * NULL on memory error
*/
-static struct pbuf *lpc_low_level_input(struct netif *netif)
-{
- struct lpc_enetdata *lpc_enetif = netif->state;
- struct pbuf *p = NULL, *q;
+static struct pbuf *lpc_low_level_input(struct netif *netif)
+{
+ struct lpc_enetdata *lpc_enetif = netif->state;
+ struct pbuf *p = NULL;
u32_t idx, length;
- u8_t *src;
-
+
#ifdef LOCK_RX_THREAD
#if NO_SYS == 0
/* Get exclusive access */
sys_mutex_lock(&lpc_enetif->TXLockMutex);
#endif
#endif
-
+
/* Monitor RX overrun status. This should never happen unless
(possibly) the internal bus is behing held up by something.
Unless your system is running at a very low clock speed or
there are possibilities that the internal buses may be held
up for a long time, this can probably safely be removed. */
if (LPC_EMAC->IntStatus & EMAC_INT_RX_OVERRUN) {
- LINK_STATS_INC(link.err);
+ LINK_STATS_INC(link.err);
LINK_STATS_INC(link.drop);
/* Temporarily disable RX */
@@ -379,9 +379,9 @@
idx = LPC_EMAC->RxConsumeIndex;
if (LPC_EMAC->RxProduceIndex != idx) {
/* Handle errors */
- if (lpc_enetif->prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR |
+ if (lpc_enetif->prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR |
EMAC_RINFO_SYM_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_LEN_ERR)) {
-#if LINK_STATS
+#if LINK_STATS
if (lpc_enetif->prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR |
EMAC_RINFO_SYM_ERR | EMAC_RINFO_ALIGN_ERR))
LINK_STATS_INC(link.chkerr);
@@ -399,7 +399,7 @@
lpc_rxqueue_pbuf(lpc_enetif, p);
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
- ("lpc_low_level_input: Packet dropped with errors (0x%x)\n",
+ ("lpc_low_level_input: Packet dropped with errors (0x%x)\n",
lpc_enetif->prxs[idx].statusinfo));
} else {
/* A packet is waiting, get length */
@@ -432,53 +432,53 @@
#endif
#endif
- return p;
+ return p;
}
/** \brief Attempt to read a packet from the EMAC interface.
*
- * \param[in] netif the lwip network interface structure for this lpc_enetif
+ * \param[in] netif the lwip network interface structure for this lpc_enetif
*/
-void lpc_enetif_input(struct netif *netif)
-{
- struct eth_hdr *ethhdr;
+void lpc_enetif_input(struct netif *netif)
+{
+ struct eth_hdr *ethhdr;
struct pbuf *p;
-
- /* move received packet into a new pbuf */
+
+ /* move received packet into a new pbuf */
p = lpc_low_level_input(netif);
if (p == NULL)
return;
-
- /* points to packet payload, which starts with an Ethernet header */
+
+ /* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
-
- switch (htons(ethhdr->type)) {
- case ETHTYPE_IP:
- case ETHTYPE_ARP:
-#if PPPOE_SUPPORT
- case ETHTYPE_PPPOEDISC:
- case ETHTYPE_PPPOE:
-#endif /* PPPOE_SUPPORT */
- /* full packet send to tcpip_thread to process */
- if (netif->input(p, netif) != ERR_OK) {
- LWIP_DEBUGF(NETIF_DEBUG, ("lpc_enetif_input: IP input error\n"));
+
+ switch (htons(ethhdr->type)) {
+ case ETHTYPE_IP:
+ case ETHTYPE_ARP:
+#if PPPOE_SUPPORT
+ case ETHTYPE_PPPOEDISC:
+ case ETHTYPE_PPPOE:
+#endif /* PPPOE_SUPPORT */
+ /* full packet send to tcpip_thread to process */
+ if (netif->input(p, netif) != ERR_OK) {
+ LWIP_DEBUGF(NETIF_DEBUG, ("lpc_enetif_input: IP input error\n"));
/* Free buffer */
pbuf_free(p);
- }
- break;
-
- default:
+ }
+ break;
+
+ default:
/* Return buffer */
- pbuf_free(p);
- break;
- }
+ pbuf_free(p);
+ break;
+ }
}
/** \brief Determine if the passed address is usable for the ethernet
* DMA controller.
*
- * \param[in] addr Address of packet to check for DMA safe operation
- * \return 1 if the packet address is not safe, otherwise 0
+ * \param[in] addr Address of packet to check for DMA safe operation
+ * \return 1 if the packet address is not safe, otherwise 0
*/
static s32_t lpc_packet_addr_notsafe(void *addr) {
/* Check for legal address ranges */
@@ -518,7 +518,7 @@
/** \brief Free TX buffers that are complete
*
* \param[in] lpc_enetif Pointer to driver data structure
- * \param[in] cidx EMAC current descriptor comsumer index
+ * \param[in] cidx EMAC current descriptor comsumer index
*/
static void lpc_tx_reclaim_st(struct lpc_enetdata *lpc_enetif, u32_t cidx)
{
@@ -538,7 +538,7 @@
}
#if NO_SYS == 0
- xSemaphoreGive(lpc_enetif->xTXDCountSem);
+ osSemaphoreRelease(lpc_enetif->xTXDCountSem.id);
#endif
lpc_enetif->lpc_last_tx_idx++;
if (lpc_enetif->lpc_last_tx_idx >= LPC_NUM_BUFF_TXDESCS)
@@ -553,7 +553,7 @@
/** \brief User call for freeingTX buffers that are complete
*
- * \param[in] netif the lwip network interface structure for this lpc_enetif
+ * \param[in] netif the lwip network interface structure for this lpc_enetif
*/
void lpc_tx_reclaim(struct netif *netif)
{
@@ -564,14 +564,14 @@
/** \brief Polls if an available TX descriptor is ready. Can be used to
* determine if the low level transmit function will block.
*
- * \param[in] netif the lwip network interface structure for this lpc_enetif
- * \return 0 if no descriptors are read, or >0
+ * \param[in] netif the lwip network interface structure for this lpc_enetif
+ * \return 0 if no descriptors are read, or >0
*/
s32_t lpc_tx_ready(struct netif *netif)
{
s32_t fb;
u32_t idx, cidx;
-
+
cidx = LPC_EMAC->TxConsumeIndex;
idx = LPC_EMAC->TxProduceIndex;
@@ -591,17 +591,16 @@
* interrupt context, as it may block until TX descriptors
* become available.
*
- * \param[in] netif the lwip network interface structure for this lpc_enetif
- * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type)
- * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent
+ * \param[in] netif the lwip network interface structure for this lpc_enetif
+ * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type)
+ * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent
*/
-static err_t lpc_low_level_output(struct netif *netif, struct pbuf *p)
+static err_t lpc_low_level_output(struct netif *netif, struct pbuf *p)
{
struct lpc_enetdata *lpc_enetif = netif->state;
struct pbuf *q;
u8_t *dst;
- u32_t idx, sz = 0;
- err_t err = ERR_OK;
+ u32_t idx;
struct pbuf *np;
u32_t dn, notdmasafe = 0;
@@ -629,10 +628,10 @@
/* This buffer better be contiguous! */
LWIP_ASSERT("lpc_low_level_output: New transmit pbuf is chained",
(pbuf_clen(np) == 1));
-
+
/* Copy to DMA safe pbuf */
dst = (u8_t *) np->payload;
- for(q = p; q != NULL; q = q->next) {
+ for(q = p; q != NULL; q = q->next) {
/* Copy the buffer to the descriptor's buffer */
MEMCPY(dst, (u8_t *) q->payload, q->len);
dst += q->len;
@@ -651,16 +650,16 @@
#else
if (notdmasafe)
LWIP_ASSERT("lpc_low_level_output: Not a DMA safe pbuf",
- (notdmasafe == 0));
+ (notdmasafe == 0));
#endif
/* Wait until enough descriptors are available for the transfer. */
/* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */
while (dn > lpc_tx_ready(netif))
#if NO_SYS == 0
- xSemaphoreTake(lpc_enetif->xTXDCountSem, 0);
+ osSemaphoreWait(lpc_enetif->xTXDCountSem.id, osWaitForever);
#else
- msDelay(1);
+ osDelay(1);
#endif
/* Get free TX buffer index */
@@ -715,8 +714,8 @@
/* Restore access */
sys_mutex_unlock(&lpc_enetif->TXLockMutex);
#endif
-
- return ERR_OK;
+
+ return ERR_OK;
}
/** \brief LPC EMAC interrupt handler.
@@ -730,7 +729,6 @@
/* Interrupts are not used without an RTOS */
NVIC_DisableIRQ(ENET_IRQn);
#else
- signed portBASE_TYPE xRecTaskWoken = pdFALSE, XTXTaskWoken = pdFALSE;
uint32_t ints;
/* Interrupts are of 2 groups - transmit or receive. Based on the
@@ -740,24 +738,17 @@
ints = LPC_EMAC->IntStatus;
if (ints & RXINTGROUP) {
- /* RX group interrupt(s) */
- /* Give semaphore to wakeup RX receive task. Note the FreeRTOS
- method is used instead of the LWIP arch method. */
- xSemaphoreGiveFromISR(lpc_enetdata.RxSem, &xRecTaskWoken);
+ /* 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. Note the FreeRTOS
- method is used instead of the LWIP arch method. */
- xSemaphoreGiveFromISR(lpc_enetdata.TxCleanSem, &XTXTaskWoken);
+ /* TX group interrupt(s): Give semaphore to wakeup TX cleanup task. */
+ sys_sem_signal(&lpc_enetdata.TxCleanSem);
}
/* Clear pending interrupts */
LPC_EMAC->IntClear = ints;
-
- /* Context switch needed? */
- portEND_SWITCHING_ISR( xRecTaskWoken || XTXTaskWoken );
#endif
}
@@ -766,11 +757,10 @@
*
* This task is called when a packet is received. It will
* pass the packet to the LWIP core.
- *
- * \param[in] pvParameters Not used yet
+ *
+ * \param[in] pvParameters Not used yet
*/
-static portTASK_FUNCTION( vPacketReceiveTask, pvParameters )
-{
+static void packet_rx(void* pvParameters) {
struct lpc_enetdata *lpc_enetif = pvParameters;
while (1) {
@@ -788,11 +778,10 @@
* This task is called when a transmit interrupt occurs and
* reclaims the pbuf and descriptor used for the packet once
* the packet has been transferred.
- *
- * \param[in] pvParameters Not used yet
+ *
+ * \param[in] pvParameters Not used yet
*/
-static portTASK_FUNCTION( vTransmitCleanupTask, pvParameters )
-{
+static void packet_tx(void* pvParameters) {
struct lpc_enetdata *lpc_enetif = pvParameters;
s32_t idx;
@@ -804,7 +793,7 @@
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.err);
LINK_STATS_INC(link.drop);
#if NO_SYS == 0
@@ -841,13 +830,16 @@
*
* \param[in] netif Pointer to LWIP netif structure
*/
-static err_t low_level_init(struct netif *netif)
-{
+static err_t low_level_init(struct netif *netif)
+{
struct lpc_enetdata *lpc_enetif = netif->state;
- err_t err = ERR_OK;
-
+ err_t err = ERR_OK;
+
/* Enable MII clocking */
- CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCENET, ENABLE);
+ LPC_SC->PCONP |= CLKPWR_PCONP_PCENET;
+
+ LPC_PINCON->PINSEL2 = 0x50150105; /* Enable P1 Ethernet Pins. */
+ LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
/* Reset all MAC logic */
LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX |
@@ -855,7 +847,7 @@
EMAC_MAC1_SOFT_RES;
LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES |
EMAC_CR_PASS_RUNT_FRM;
- msDelay(10);
+ osDelay(10);
/* Initial MAC initialization */
LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
@@ -915,41 +907,41 @@
return err;
}
-
-/* This function provides a method for the PHY to setup the EMAC
- for the PHY negotiated duplex mode */
-void lpc_emac_set_duplex(int full_duplex)
-{
- if (full_duplex) {
- LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
- LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
- LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
- } else {
- LPC_EMAC->MAC2 &= ~EMAC_MAC2_FULL_DUP;
- LPC_EMAC->Command &= ~EMAC_CR_FULL_DUP;
- LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
- }
-}
-
-/* This function provides a method for the PHY to setup the EMAC
- for the PHY negotiated bit rate */
-void lpc_emac_set_speed(int mbs_100)
-{
- if (mbs_100)
- LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
- else
- LPC_EMAC->SUPP = 0;
+
+/* This function provides a method for the PHY to setup the EMAC
+ for the PHY negotiated duplex mode */
+void lpc_emac_set_duplex(int full_duplex)
+{
+ if (full_duplex) {
+ LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
+ LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
+ LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
+ } else {
+ LPC_EMAC->MAC2 &= ~EMAC_MAC2_FULL_DUP;
+ LPC_EMAC->Command &= ~EMAC_CR_FULL_DUP;
+ LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
+ }
}
-
-/**
+
+/* This function provides a method for the PHY to setup the EMAC
+ for the PHY negotiated bit rate */
+void lpc_emac_set_speed(int mbs_100)
+{
+ if (mbs_100)
+ LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
+ else
+ LPC_EMAC->SUPP = 0;
+}
+
+/**
* This function is the ethernet packet send function. It calls
- * etharp_output after checking link status.
- *
- * \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
+ * etharp_output after checking link status.
+ *
+ * \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
* \return ERR_OK or error code
- */
+ */
err_t lpc_etharp_output(struct netif *netif, struct pbuf *q,
ip_addr_t *ipaddr)
{
@@ -958,83 +950,92 @@
return etharp_output(netif, q, ipaddr);
return ERR_CONN;
-}
-
-/**
- * Should be called at the beginning of the program to set up the
- * network interface.
- *
- * This function should be passed as a parameter to netif_add().
- *
- * @param[in] netif the lwip network interface structure for this lpc_enetif
- * @return ERR_OK if the loopif is initialized
- * ERR_MEM if private data couldn't be allocated
- * any other err_t on error
- */
-err_t lpc_enetif_init(struct netif *netif)
-{
- err_t err;
-
- LWIP_ASSERT("netif != NULL", (netif != NULL));
-
+}
+
+#if NO_SYS == 0
+/* periodic PHY status update */
+void phy_update(void const *nif) {
+ lpc_phy_sts_sm((struct netif*)nif);
+}
+osTimerDef(phy_update, phy_update);
+#endif
+
+/**
+ * Should be called at the beginning of the program to set up the
+ * network interface.
+ *
+ * This function should be passed as a parameter to netif_add().
+ *
+ * @param[in] netif the lwip network interface structure for this lpc_enetif
+ * @return ERR_OK if the loopif is initialized
+ * ERR_MEM if private data couldn't be allocated
+ * any other err_t on error
+ */
+err_t lpc_enetif_init(struct netif *netif)
+{
+ err_t err;
+
+ LWIP_ASSERT("netif != NULL", (netif != NULL));
+
lpc_enetdata.netif = netif;
/* set MAC hardware address */
- board_get_macaddr(netif->hwaddr);
- netif->hwaddr_len = ETHARP_HWADDR_LEN;
-
- /* maximum transfer unit */
- netif->mtu = 1500;
-
- /* device capabilities */
- netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_UP |
- NETIF_FLAG_ETHERNET;
-
+ mbed_mac_address((char *)netif->hwaddr);
+ netif->hwaddr_len = ETHARP_HWADDR_LEN;
+
+ /* maximum transfer unit */
+ netif->mtu = 1500;
+
+ /* device capabilities */
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET;
+
/* Initialize the hardware */
netif->state = &lpc_enetdata;
- err = low_level_init(netif);
+ err = low_level_init(netif);
if (err != ERR_OK)
return err;
-#if LWIP_NETIF_HOSTNAME
- /* Initialize interface hostname */
- netif->hostname = "lwiplpc";
+#if LWIP_NETIF_HOSTNAME
+ /* Initialize interface hostname */
+ netif->hostname = "lwiplpc";
#endif /* LWIP_NETIF_HOSTNAME */
- netif->name[0] = 'e';
+ netif->name[0] = 'e';
netif->name[1] = 'n';
- netif->output = lpc_etharp_output;
+ netif->output = lpc_etharp_output;
netif->linkoutput = lpc_low_level_output;
- /* For FreeRTOS, start tasks */
+ /* CMSIS-RTOS, start tasks */
#if NO_SYS == 0
- lpc_enetdata.xTXDCountSem = xSemaphoreCreateCounting(LPC_NUM_BUFF_TXDESCS,
- LPC_NUM_BUFF_TXDESCS);
- LWIP_ASSERT("xTXDCountSem creation error",
- (lpc_enetdata.xTXDCountSem != NULL));
-
- err = sys_mutex_new(&lpc_enetdata.TXLockMutex);
+ #ifdef CMSIS_OS_RTX
+ memset(lpc_enetdata.xTXDCountSem.data, 0, sizeof(lpc_enetdata.xTXDCountSem.data));
+ lpc_enetdata.xTXDCountSem.def.semaphore = lpc_enetdata.xTXDCountSem.data;
+ #endif
+ lpc_enetdata.xTXDCountSem.id = osSemaphoreCreate(&lpc_enetdata.xTXDCountSem.def, LPC_NUM_BUFF_TXDESCS);
+ LWIP_ASSERT("xTXDCountSem creation error", (lpc_enetdata.xTXDCountSem.id != NULL));
+
+ err = sys_mutex_new(&lpc_enetdata.TXLockMutex);
LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK));
-
+
/* Packet receive task */
err = sys_sem_new(&lpc_enetdata.RxSem, 0);
- LWIP_ASSERT("RxSem creation error", (err == ERR_OK));
- sys_thread_new("receive_thread", vPacketReceiveTask, netif->state,
- DEFAULT_THREAD_STACKSIZE, tskRECPKT_PRIORITY);
-
+ LWIP_ASSERT("RxSem creation error", (err == ERR_OK));
+ sys_thread_new("receive_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY);
+
/* Transmit cleanup task */
- err = sys_sem_new(&lpc_enetdata.TxCleanSem, 0);
- LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK));
- sys_thread_new("txclean_thread", vTransmitCleanupTask, netif->state,
- DEFAULT_THREAD_STACKSIZE, tskTXCLEAN_PRIORITY);
+ 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;
+
+ return ERR_OK;
}
-/**
- * @}
+/**
+ * @}
*/
-/* --------------------------------- End Of File ------------------------------ */
+/* --------------------------------- End Of File ------------------------------ */
