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.
Committer:
mbed_official
Date:
Fri Jun 22 09:32:29 2012 +0000
Revision:
0:f4db29eb9e47
Child:
1:0c9d93e2f51c
Initial import from NXP lwip_lpc: http://sw.lpcware.com/index.php?p=lwip_lpc.git&a=snapshot&h=7b84446afe97af955acad1d720696a0de73ab7cf&fmt=zip

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 0:f4db29eb9e47 1 /**********************************************************************
mbed_official 0:f4db29eb9e47 2 * $Id$ lpc17_emac.c 2011-11-20
mbed_official 0:f4db29eb9e47 3 *//**
mbed_official 0:f4db29eb9e47 4 * @file lpc17_emac.c
mbed_official 0:f4db29eb9e47 5 * @brief LPC17 ethernet driver for LWIP
mbed_official 0:f4db29eb9e47 6 * @version 1.0
mbed_official 0:f4db29eb9e47 7 * @date 20. Nov. 2011
mbed_official 0:f4db29eb9e47 8 * @author NXP MCU SW Application Team
mbed_official 0:f4db29eb9e47 9 *
mbed_official 0:f4db29eb9e47 10 * Copyright(C) 2011, NXP Semiconductor
mbed_official 0:f4db29eb9e47 11 * All rights reserved.
mbed_official 0:f4db29eb9e47 12 *
mbed_official 0:f4db29eb9e47 13 ***********************************************************************
mbed_official 0:f4db29eb9e47 14 * Software that is described herein is for illustrative purposes only
mbed_official 0:f4db29eb9e47 15 * which provides customers with programming information regarding the
mbed_official 0:f4db29eb9e47 16 * products. This software is supplied "AS IS" without any warranties.
mbed_official 0:f4db29eb9e47 17 * NXP Semiconductors assumes no responsibility or liability for the
mbed_official 0:f4db29eb9e47 18 * use of the software, conveys no license or title under any patent,
mbed_official 0:f4db29eb9e47 19 * copyright, or mask work right to the product. NXP Semiconductors
mbed_official 0:f4db29eb9e47 20 * reserves the right to make changes in the software without
mbed_official 0:f4db29eb9e47 21 * notification. NXP Semiconductors also make no representation or
mbed_official 0:f4db29eb9e47 22 * warranty that such application will be suitable for the specified
mbed_official 0:f4db29eb9e47 23 * use without further testing or modification.
mbed_official 0:f4db29eb9e47 24 **********************************************************************/
mbed_official 0:f4db29eb9e47 25
mbed_official 0:f4db29eb9e47 26 #include "lwip/opt.h"
mbed_official 0:f4db29eb9e47 27 #include "lwip/sys.h"
mbed_official 0:f4db29eb9e47 28 #include "lwip/def.h"
mbed_official 0:f4db29eb9e47 29 #include "lwip/mem.h"
mbed_official 0:f4db29eb9e47 30 #include "lwip/pbuf.h"
mbed_official 0:f4db29eb9e47 31 #include "lwip/stats.h"
mbed_official 0:f4db29eb9e47 32 #include "lwip/snmp.h"
mbed_official 0:f4db29eb9e47 33 #include "netif/etharp.h"
mbed_official 0:f4db29eb9e47 34 #include "netif/ppp_oe.h"
mbed_official 0:f4db29eb9e47 35
mbed_official 0:f4db29eb9e47 36 #include "lpc177x_8x_emac.h"
mbed_official 0:f4db29eb9e47 37 #include "lpc177x_8x_clkpwr.h"
mbed_official 0:f4db29eb9e47 38 #include "lpc17_emac.h"
mbed_official 0:f4db29eb9e47 39 #include "lpc_emac_config.h"
mbed_official 0:f4db29eb9e47 40 #include "lpc_phy.h"
mbed_official 0:f4db29eb9e47 41
mbed_official 0:f4db29eb9e47 42 #ifndef LPC_EMAC_RMII
mbed_official 0:f4db29eb9e47 43 #error LPC_EMAC_RMII is not defined!
mbed_official 0:f4db29eb9e47 44 #endif
mbed_official 0:f4db29eb9e47 45
mbed_official 0:f4db29eb9e47 46 #if LPC_NUM_BUFF_TXDESCS < 2
mbed_official 0:f4db29eb9e47 47 #error LPC_NUM_BUFF_TXDESCS must be at least 2
mbed_official 0:f4db29eb9e47 48 #endif
mbed_official 0:f4db29eb9e47 49
mbed_official 0:f4db29eb9e47 50 #if LPC_NUM_BUFF_RXDESCS < 3
mbed_official 0:f4db29eb9e47 51 #error LPC_NUM_BUFF_RXDESCS must be at least 3
mbed_official 0:f4db29eb9e47 52 #endif
mbed_official 0:f4db29eb9e47 53
mbed_official 0:f4db29eb9e47 54 /** @defgroup lwip17xx_emac_DRIVER lpc17 EMAC driver for LWIP
mbed_official 0:f4db29eb9e47 55 * @ingroup lwip_emac
mbed_official 0:f4db29eb9e47 56 *
mbed_official 0:f4db29eb9e47 57 * @{
mbed_official 0:f4db29eb9e47 58 */
mbed_official 0:f4db29eb9e47 59
mbed_official 0:f4db29eb9e47 60 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 61 /** \brief Driver transmit and receive thread priorities
mbed_official 0:f4db29eb9e47 62 *
mbed_official 0:f4db29eb9e47 63 * Thread priorities for receive thread and TX cleanup thread. Alter
mbed_official 0:f4db29eb9e47 64 * to prioritize receive or transmit bandwidth. In a heavily loaded
mbed_official 0:f4db29eb9e47 65 * system or with LEIP_DEBUG enabled, the priorities might be better
mbed_official 0:f4db29eb9e47 66 * the same. */
mbed_official 0:f4db29eb9e47 67 #define tskRECPKT_PRIORITY (DEFAULT_THREAD_PRIO + 4)
mbed_official 0:f4db29eb9e47 68 #define tskTXCLEAN_PRIORITY (DEFAULT_THREAD_PRIO + 5)
mbed_official 0:f4db29eb9e47 69
mbed_official 0:f4db29eb9e47 70 /** \brief Debug output formatter lock define
mbed_official 0:f4db29eb9e47 71 *
mbed_official 0:f4db29eb9e47 72 * When using FreeRTOS and with LWIP_DEBUG enabled, enabling this
mbed_official 0:f4db29eb9e47 73 * define will allow RX debug messages to not interleave with the
mbed_official 0:f4db29eb9e47 74 * TX messages (so they are actually readable). Not enabling this
mbed_official 0:f4db29eb9e47 75 * define when the system is under load will cause the output to
mbed_official 0:f4db29eb9e47 76 * be unreadable. There is a small tradeoff in performance for this
mbed_official 0:f4db29eb9e47 77 * so use it only for debug. */
mbed_official 0:f4db29eb9e47 78 //#define LOCK_RX_THREAD
mbed_official 0:f4db29eb9e47 79
mbed_official 0:f4db29eb9e47 80 /** \brief Receive group interrupts
mbed_official 0:f4db29eb9e47 81 */
mbed_official 0:f4db29eb9e47 82 #define RXINTGROUP (EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_DONE)
mbed_official 0:f4db29eb9e47 83
mbed_official 0:f4db29eb9e47 84 /** \brief Transmit group interrupts
mbed_official 0:f4db29eb9e47 85 */
mbed_official 0:f4db29eb9e47 86 #define TXINTGROUP (EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR | EMAC_INT_TX_DONE)
mbed_official 0:f4db29eb9e47 87 #else
mbed_official 0:f4db29eb9e47 88 #define RXINTGROUP 0
mbed_official 0:f4db29eb9e47 89 #define TXINTGROUP 0
mbed_official 0:f4db29eb9e47 90 #endif
mbed_official 0:f4db29eb9e47 91
mbed_official 0:f4db29eb9e47 92 /** \brief Structure of a TX/RX descriptor
mbed_official 0:f4db29eb9e47 93 */
mbed_official 0:f4db29eb9e47 94 typedef struct
mbed_official 0:f4db29eb9e47 95 {
mbed_official 0:f4db29eb9e47 96 volatile u32_t packet; /**< Pointer to buffer */
mbed_official 0:f4db29eb9e47 97 volatile u32_t control; /**< Control word */
mbed_official 0:f4db29eb9e47 98 } LPC_TXRX_DESC_T;
mbed_official 0:f4db29eb9e47 99
mbed_official 0:f4db29eb9e47 100 /** \brief Structure of a RX status entry
mbed_official 0:f4db29eb9e47 101 */
mbed_official 0:f4db29eb9e47 102 typedef struct
mbed_official 0:f4db29eb9e47 103 {
mbed_official 0:f4db29eb9e47 104 volatile u32_t statusinfo; /**< RX status word */
mbed_official 0:f4db29eb9e47 105 volatile u32_t statushashcrc; /**< RX hash CRC */
mbed_official 0:f4db29eb9e47 106 } LPC_TXRX_STATUS_T;
mbed_official 0:f4db29eb9e47 107
mbed_official 0:f4db29eb9e47 108 /* LPC EMAC driver data structure */
mbed_official 0:f4db29eb9e47 109 struct lpc_enetdata {
mbed_official 0:f4db29eb9e47 110 /* prxs must be 8 byte aligned! */
mbed_official 0:f4db29eb9e47 111 LPC_TXRX_STATUS_T prxs[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX statuses */
mbed_official 0:f4db29eb9e47 112 struct netif *netif; /**< Reference back to LWIP parent netif */
mbed_official 0:f4db29eb9e47 113 LPC_TXRX_DESC_T ptxd[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX descriptor list */
mbed_official 0:f4db29eb9e47 114 LPC_TXRX_STATUS_T ptxs[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX statuses */
mbed_official 0:f4db29eb9e47 115 LPC_TXRX_DESC_T prxd[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX descriptor list */
mbed_official 0:f4db29eb9e47 116 struct pbuf *rxb[LPC_NUM_BUFF_RXDESCS]; /**< RX pbuf pointer list, zero-copy mode */
mbed_official 0:f4db29eb9e47 117 u32_t rx_fill_desc_index; /**< RX descriptor next available index */
mbed_official 0:f4db29eb9e47 118 volatile u32_t rx_free_descs; /**< Count of free RX descriptors */
mbed_official 0:f4db29eb9e47 119 struct pbuf *txb[LPC_NUM_BUFF_TXDESCS]; /**< TX pbuf pointer list, zero-copy mode */
mbed_official 0:f4db29eb9e47 120 u32_t lpc_last_tx_idx; /**< TX last descriptor index, zero-copy mode */
mbed_official 0:f4db29eb9e47 121 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 122 sys_sem_t RxSem; /**< RX receive thread wakeup semaphore */
mbed_official 0:f4db29eb9e47 123 sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */
mbed_official 0:f4db29eb9e47 124 sys_mutex_t TXLockMutex; /**< TX critical section mutex */
mbed_official 0:f4db29eb9e47 125 xSemaphoreHandle xTXDCountSem; /**< TX free buffer counting semaphore */
mbed_official 0:f4db29eb9e47 126 #endif
mbed_official 0:f4db29eb9e47 127 };
mbed_official 0:f4db29eb9e47 128
mbed_official 0:f4db29eb9e47 129 /** \brief LPC EMAC driver work data
mbed_official 0:f4db29eb9e47 130 */
mbed_official 0:f4db29eb9e47 131 ALIGNED(8) struct lpc_enetdata lpc_enetdata;
mbed_official 0:f4db29eb9e47 132
mbed_official 0:f4db29eb9e47 133 /* Write a value via the MII link (non-blocking) */
mbed_official 0:f4db29eb9e47 134 void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value)
mbed_official 0:f4db29eb9e47 135 {
mbed_official 0:f4db29eb9e47 136 /* Write value at PHY address and register */
mbed_official 0:f4db29eb9e47 137 LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
mbed_official 0:f4db29eb9e47 138 LPC_EMAC->MWTD = Value;
mbed_official 0:f4db29eb9e47 139 }
mbed_official 0:f4db29eb9e47 140
mbed_official 0:f4db29eb9e47 141 /* Write a value via the MII link (blocking) */
mbed_official 0:f4db29eb9e47 142 err_t lpc_mii_write(u32_t PhyReg, u32_t Value)
mbed_official 0:f4db29eb9e47 143 {
mbed_official 0:f4db29eb9e47 144 u32_t mst = 250;
mbed_official 0:f4db29eb9e47 145 err_t sts = ERR_OK;
mbed_official 0:f4db29eb9e47 146
mbed_official 0:f4db29eb9e47 147 /* Write value at PHY address and register */
mbed_official 0:f4db29eb9e47 148 lpc_mii_write_noblock(PhyReg, Value);
mbed_official 0:f4db29eb9e47 149
mbed_official 0:f4db29eb9e47 150 /* Wait for unbusy status */
mbed_official 0:f4db29eb9e47 151 while (mst > 0) {
mbed_official 0:f4db29eb9e47 152 sts = LPC_EMAC->MIND;
mbed_official 0:f4db29eb9e47 153 if ((sts & EMAC_MIND_BUSY) == 0)
mbed_official 0:f4db29eb9e47 154 mst = 0;
mbed_official 0:f4db29eb9e47 155 else {
mbed_official 0:f4db29eb9e47 156 mst--;
mbed_official 0:f4db29eb9e47 157 msDelay(1);
mbed_official 0:f4db29eb9e47 158 }
mbed_official 0:f4db29eb9e47 159 }
mbed_official 0:f4db29eb9e47 160
mbed_official 0:f4db29eb9e47 161 if (sts != 0)
mbed_official 0:f4db29eb9e47 162 sts = ERR_TIMEOUT;
mbed_official 0:f4db29eb9e47 163
mbed_official 0:f4db29eb9e47 164 return sts;
mbed_official 0:f4db29eb9e47 165 }
mbed_official 0:f4db29eb9e47 166
mbed_official 0:f4db29eb9e47 167 /* Reads current MII link busy status */
mbed_official 0:f4db29eb9e47 168 u32_t lpc_mii_is_busy(void)
mbed_official 0:f4db29eb9e47 169 {
mbed_official 0:f4db29eb9e47 170 return (u32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY);
mbed_official 0:f4db29eb9e47 171 }
mbed_official 0:f4db29eb9e47 172
mbed_official 0:f4db29eb9e47 173 /* Starts a read operation via the MII link (non-blocking) */
mbed_official 0:f4db29eb9e47 174 u32_t lpc_mii_read_data(void)
mbed_official 0:f4db29eb9e47 175 {
mbed_official 0:f4db29eb9e47 176 u32_t data = LPC_EMAC->MRDD;
mbed_official 0:f4db29eb9e47 177 LPC_EMAC->MCMD = 0;
mbed_official 0:f4db29eb9e47 178
mbed_official 0:f4db29eb9e47 179 return data;
mbed_official 0:f4db29eb9e47 180 }
mbed_official 0:f4db29eb9e47 181
mbed_official 0:f4db29eb9e47 182 /* Starts a read operation via the MII link (non-blocking) */
mbed_official 0:f4db29eb9e47 183 void lpc_mii_read_noblock(u32_t PhyReg)
mbed_official 0:f4db29eb9e47 184 {
mbed_official 0:f4db29eb9e47 185 /* Read value at PHY address and register */
mbed_official 0:f4db29eb9e47 186 LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
mbed_official 0:f4db29eb9e47 187 LPC_EMAC->MCMD = EMAC_MCMD_READ;
mbed_official 0:f4db29eb9e47 188 }
mbed_official 0:f4db29eb9e47 189
mbed_official 0:f4db29eb9e47 190 /* Read a value via the MII link (blocking) */
mbed_official 0:f4db29eb9e47 191 err_t lpc_mii_read(u32_t PhyReg, u32_t *data)
mbed_official 0:f4db29eb9e47 192 {
mbed_official 0:f4db29eb9e47 193 u32_t mst = 250;
mbed_official 0:f4db29eb9e47 194 err_t sts = ERR_OK;
mbed_official 0:f4db29eb9e47 195
mbed_official 0:f4db29eb9e47 196 /* Read value at PHY address and register */
mbed_official 0:f4db29eb9e47 197 lpc_mii_read_noblock(PhyReg);
mbed_official 0:f4db29eb9e47 198
mbed_official 0:f4db29eb9e47 199 /* Wait for unbusy status */
mbed_official 0:f4db29eb9e47 200 while (mst > 0) {
mbed_official 0:f4db29eb9e47 201 sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL;
mbed_official 0:f4db29eb9e47 202 if ((sts & EMAC_MIND_BUSY) == 0) {
mbed_official 0:f4db29eb9e47 203 mst = 0;
mbed_official 0:f4db29eb9e47 204 *data = LPC_EMAC->MRDD;
mbed_official 0:f4db29eb9e47 205 } else {
mbed_official 0:f4db29eb9e47 206 mst--;
mbed_official 0:f4db29eb9e47 207 msDelay(1);
mbed_official 0:f4db29eb9e47 208 }
mbed_official 0:f4db29eb9e47 209 }
mbed_official 0:f4db29eb9e47 210
mbed_official 0:f4db29eb9e47 211 LPC_EMAC->MCMD = 0;
mbed_official 0:f4db29eb9e47 212
mbed_official 0:f4db29eb9e47 213 if (sts != 0)
mbed_official 0:f4db29eb9e47 214 sts = ERR_TIMEOUT;
mbed_official 0:f4db29eb9e47 215
mbed_official 0:f4db29eb9e47 216 return sts;
mbed_official 0:f4db29eb9e47 217 }
mbed_official 0:f4db29eb9e47 218
mbed_official 0:f4db29eb9e47 219 /** \brief Queues a pbuf into the RX descriptor list
mbed_official 0:f4db29eb9e47 220 *
mbed_official 0:f4db29eb9e47 221 * \param[in] lpc_enetif Pointer to the drvier data structure
mbed_official 0:f4db29eb9e47 222 * \param[in] p Pointer to pbuf to queue
mbed_official 0:f4db29eb9e47 223 */
mbed_official 0:f4db29eb9e47 224 static void lpc_rxqueue_pbuf(struct lpc_enetdata *lpc_enetif, struct pbuf *p)
mbed_official 0:f4db29eb9e47 225 {
mbed_official 0:f4db29eb9e47 226 u32_t idx;
mbed_official 0:f4db29eb9e47 227
mbed_official 0:f4db29eb9e47 228 /* Get next free descriptor index */
mbed_official 0:f4db29eb9e47 229 idx = lpc_enetif->rx_fill_desc_index;
mbed_official 0:f4db29eb9e47 230
mbed_official 0:f4db29eb9e47 231 /* Setup descriptor and clear statuses */
mbed_official 0:f4db29eb9e47 232 lpc_enetif->prxd[idx].control = EMAC_RCTRL_INT | ((u32_t) (p->len - 1));
mbed_official 0:f4db29eb9e47 233 lpc_enetif->prxd[idx].packet = (u32_t) p->payload;
mbed_official 0:f4db29eb9e47 234 lpc_enetif->prxs[idx].statusinfo = 0xFFFFFFFF;
mbed_official 0:f4db29eb9e47 235 lpc_enetif->prxs[idx].statushashcrc = 0xFFFFFFFF;
mbed_official 0:f4db29eb9e47 236
mbed_official 0:f4db29eb9e47 237 /* Save pbuf pointer for push to network layer later */
mbed_official 0:f4db29eb9e47 238 lpc_enetif->rxb[idx] = p;
mbed_official 0:f4db29eb9e47 239
mbed_official 0:f4db29eb9e47 240 /* Wrap at end of descriptor list */
mbed_official 0:f4db29eb9e47 241 idx++;
mbed_official 0:f4db29eb9e47 242 if (idx >= LPC_NUM_BUFF_RXDESCS)
mbed_official 0:f4db29eb9e47 243 idx = 0;
mbed_official 0:f4db29eb9e47 244
mbed_official 0:f4db29eb9e47 245 /* Queue descriptor(s) */
mbed_official 0:f4db29eb9e47 246 lpc_enetif->rx_free_descs -= 1;
mbed_official 0:f4db29eb9e47 247 lpc_enetif->rx_fill_desc_index = idx;
mbed_official 0:f4db29eb9e47 248 LPC_EMAC->RxConsumeIndex = idx;
mbed_official 0:f4db29eb9e47 249
mbed_official 0:f4db29eb9e47 250 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 0:f4db29eb9e47 251 ("lpc_rxqueue_pbuf: pbuf packet queued: %p (free desc=%d)\n", p,
mbed_official 0:f4db29eb9e47 252 lpc_enetif->rx_free_descs));
mbed_official 0:f4db29eb9e47 253 }
mbed_official 0:f4db29eb9e47 254
mbed_official 0:f4db29eb9e47 255 /** \brief Attempt to allocate and requeue a new pbuf for RX
mbed_official 0:f4db29eb9e47 256 *
mbed_official 0:f4db29eb9e47 257 * \param[in] netif Pointer to the netif structure
mbed_official 0:f4db29eb9e47 258 * \returns 1 if a packet was allocated and requeued, otherwise 0
mbed_official 0:f4db29eb9e47 259 */
mbed_official 0:f4db29eb9e47 260 s32_t lpc_rx_queue(struct netif *netif)
mbed_official 0:f4db29eb9e47 261 {
mbed_official 0:f4db29eb9e47 262 struct lpc_enetdata *lpc_enetif = netif->state;
mbed_official 0:f4db29eb9e47 263 struct pbuf *p;
mbed_official 0:f4db29eb9e47 264 s32_t queued = 0;
mbed_official 0:f4db29eb9e47 265
mbed_official 0:f4db29eb9e47 266 /* Attempt to requeue as many packets as possible */
mbed_official 0:f4db29eb9e47 267 while (lpc_enetif->rx_free_descs > 0) {
mbed_official 0:f4db29eb9e47 268 /* Allocate a pbuf from the pool. We need to allocate at the
mbed_official 0:f4db29eb9e47 269 maximum size as we don't know the size of the yet to be
mbed_official 0:f4db29eb9e47 270 received packet. */
mbed_official 0:f4db29eb9e47 271 p = pbuf_alloc(PBUF_RAW, (u16_t) EMAC_ETH_MAX_FLEN, PBUF_RAM);
mbed_official 0:f4db29eb9e47 272 if (p == NULL) {
mbed_official 0:f4db29eb9e47 273 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 0:f4db29eb9e47 274 ("lpc_rx_queue: could not allocate RX pbuf (free desc=%d)\n",
mbed_official 0:f4db29eb9e47 275 lpc_enetif->rx_free_descs));
mbed_official 0:f4db29eb9e47 276 return queued;
mbed_official 0:f4db29eb9e47 277 }
mbed_official 0:f4db29eb9e47 278
mbed_official 0:f4db29eb9e47 279 /* pbufs allocated from the RAM pool should be non-chained. */
mbed_official 0:f4db29eb9e47 280 LWIP_ASSERT("lpc_rx_queue: pbuf is not contiguous (chained)",
mbed_official 0:f4db29eb9e47 281 pbuf_clen(p) <= 1);
mbed_official 0:f4db29eb9e47 282
mbed_official 0:f4db29eb9e47 283 /* Queue packet */
mbed_official 0:f4db29eb9e47 284 lpc_rxqueue_pbuf(lpc_enetif, p);
mbed_official 0:f4db29eb9e47 285
mbed_official 0:f4db29eb9e47 286 /* Update queued count */
mbed_official 0:f4db29eb9e47 287 queued++;
mbed_official 0:f4db29eb9e47 288 }
mbed_official 0:f4db29eb9e47 289
mbed_official 0:f4db29eb9e47 290 return queued;
mbed_official 0:f4db29eb9e47 291 }
mbed_official 0:f4db29eb9e47 292
mbed_official 0:f4db29eb9e47 293 /** \brief Sets up the RX descriptor ring buffers.
mbed_official 0:f4db29eb9e47 294 *
mbed_official 0:f4db29eb9e47 295 * This function sets up the descriptor list used for receive packets.
mbed_official 0:f4db29eb9e47 296 *
mbed_official 0:f4db29eb9e47 297 * \param[in] lpc_enetif Pointer to driver data structure
mbed_official 0:f4db29eb9e47 298 * \returns Always returns ERR_OK
mbed_official 0:f4db29eb9e47 299 */
mbed_official 0:f4db29eb9e47 300 static err_t lpc_rx_setup(struct lpc_enetdata *lpc_enetif)
mbed_official 0:f4db29eb9e47 301 {
mbed_official 0:f4db29eb9e47 302 s32_t idx;
mbed_official 0:f4db29eb9e47 303
mbed_official 0:f4db29eb9e47 304 /* Setup pointers to RX structures */
mbed_official 0:f4db29eb9e47 305 LPC_EMAC->RxDescriptor = (u32_t) &lpc_enetif->prxd[0];
mbed_official 0:f4db29eb9e47 306 LPC_EMAC->RxStatus = (u32_t) &lpc_enetif->prxs[0];
mbed_official 0:f4db29eb9e47 307 LPC_EMAC->RxDescriptorNumber = LPC_NUM_BUFF_RXDESCS - 1;
mbed_official 0:f4db29eb9e47 308
mbed_official 0:f4db29eb9e47 309 lpc_enetif->rx_free_descs = LPC_NUM_BUFF_RXDESCS;
mbed_official 0:f4db29eb9e47 310 lpc_enetif->rx_fill_desc_index = 0;
mbed_official 0:f4db29eb9e47 311
mbed_official 0:f4db29eb9e47 312 /* Build RX buffer and descriptors */
mbed_official 0:f4db29eb9e47 313 lpc_rx_queue(lpc_enetif->netif);
mbed_official 0:f4db29eb9e47 314
mbed_official 0:f4db29eb9e47 315 return ERR_OK;
mbed_official 0:f4db29eb9e47 316 }
mbed_official 0:f4db29eb9e47 317
mbed_official 0:f4db29eb9e47 318 /** \brief Allocates a pbuf and returns the data from the incoming packet.
mbed_official 0:f4db29eb9e47 319 *
mbed_official 0:f4db29eb9e47 320 * \param[in] netif the lwip network interface structure for this lpc_enetif
mbed_official 0:f4db29eb9e47 321 * \return a pbuf filled with the received packet (including MAC header)
mbed_official 0:f4db29eb9e47 322 * NULL on memory error
mbed_official 0:f4db29eb9e47 323 */
mbed_official 0:f4db29eb9e47 324 static struct pbuf *lpc_low_level_input(struct netif *netif)
mbed_official 0:f4db29eb9e47 325 {
mbed_official 0:f4db29eb9e47 326 struct lpc_enetdata *lpc_enetif = netif->state;
mbed_official 0:f4db29eb9e47 327 struct pbuf *p = NULL, *q;
mbed_official 0:f4db29eb9e47 328 u32_t idx, length;
mbed_official 0:f4db29eb9e47 329 u8_t *src;
mbed_official 0:f4db29eb9e47 330
mbed_official 0:f4db29eb9e47 331 #ifdef LOCK_RX_THREAD
mbed_official 0:f4db29eb9e47 332 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 333 /* Get exclusive access */
mbed_official 0:f4db29eb9e47 334 sys_mutex_lock(&lpc_enetif->TXLockMutex);
mbed_official 0:f4db29eb9e47 335 #endif
mbed_official 0:f4db29eb9e47 336 #endif
mbed_official 0:f4db29eb9e47 337
mbed_official 0:f4db29eb9e47 338 /* Monitor RX overrun status. This should never happen unless
mbed_official 0:f4db29eb9e47 339 (possibly) the internal bus is behing held up by something.
mbed_official 0:f4db29eb9e47 340 Unless your system is running at a very low clock speed or
mbed_official 0:f4db29eb9e47 341 there are possibilities that the internal buses may be held
mbed_official 0:f4db29eb9e47 342 up for a long time, this can probably safely be removed. */
mbed_official 0:f4db29eb9e47 343 if (LPC_EMAC->IntStatus & EMAC_INT_RX_OVERRUN) {
mbed_official 0:f4db29eb9e47 344 LINK_STATS_INC(link.err);
mbed_official 0:f4db29eb9e47 345 LINK_STATS_INC(link.drop);
mbed_official 0:f4db29eb9e47 346
mbed_official 0:f4db29eb9e47 347 /* Temporarily disable RX */
mbed_official 0:f4db29eb9e47 348 LPC_EMAC->MAC1 &= ~EMAC_MAC1_REC_EN;
mbed_official 0:f4db29eb9e47 349
mbed_official 0:f4db29eb9e47 350 /* Reset the RX side */
mbed_official 0:f4db29eb9e47 351 LPC_EMAC->MAC1 |= EMAC_MAC1_RES_RX;
mbed_official 0:f4db29eb9e47 352 LPC_EMAC->IntClear = EMAC_INT_RX_OVERRUN;
mbed_official 0:f4db29eb9e47 353
mbed_official 0:f4db29eb9e47 354 /* De-allocate all queued RX pbufs */
mbed_official 0:f4db29eb9e47 355 for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) {
mbed_official 0:f4db29eb9e47 356 if (lpc_enetif->rxb[idx] != NULL) {
mbed_official 0:f4db29eb9e47 357 pbuf_free(lpc_enetif->rxb[idx]);
mbed_official 0:f4db29eb9e47 358 lpc_enetif->rxb[idx] = NULL;
mbed_official 0:f4db29eb9e47 359 }
mbed_official 0:f4db29eb9e47 360 }
mbed_official 0:f4db29eb9e47 361
mbed_official 0:f4db29eb9e47 362 /* Start RX side again */
mbed_official 0:f4db29eb9e47 363 lpc_rx_setup(lpc_enetif);
mbed_official 0:f4db29eb9e47 364
mbed_official 0:f4db29eb9e47 365 /* Re-enable RX */
mbed_official 0:f4db29eb9e47 366 LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;
mbed_official 0:f4db29eb9e47 367
mbed_official 0:f4db29eb9e47 368 #ifdef LOCK_RX_THREAD
mbed_official 0:f4db29eb9e47 369 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 370 sys_mutex_unlock(&lpc_enetif->TXLockMutex);
mbed_official 0:f4db29eb9e47 371 #endif
mbed_official 0:f4db29eb9e47 372 #endif
mbed_official 0:f4db29eb9e47 373
mbed_official 0:f4db29eb9e47 374 return NULL;
mbed_official 0:f4db29eb9e47 375 }
mbed_official 0:f4db29eb9e47 376
mbed_official 0:f4db29eb9e47 377 /* Determine if a frame has been received */
mbed_official 0:f4db29eb9e47 378 length = 0;
mbed_official 0:f4db29eb9e47 379 idx = LPC_EMAC->RxConsumeIndex;
mbed_official 0:f4db29eb9e47 380 if (LPC_EMAC->RxProduceIndex != idx) {
mbed_official 0:f4db29eb9e47 381 /* Handle errors */
mbed_official 0:f4db29eb9e47 382 if (lpc_enetif->prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR |
mbed_official 0:f4db29eb9e47 383 EMAC_RINFO_SYM_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_LEN_ERR)) {
mbed_official 0:f4db29eb9e47 384 #if LINK_STATS
mbed_official 0:f4db29eb9e47 385 if (lpc_enetif->prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR |
mbed_official 0:f4db29eb9e47 386 EMAC_RINFO_SYM_ERR | EMAC_RINFO_ALIGN_ERR))
mbed_official 0:f4db29eb9e47 387 LINK_STATS_INC(link.chkerr);
mbed_official 0:f4db29eb9e47 388 if (lpc_enetif->prxs[idx].statusinfo & EMAC_RINFO_LEN_ERR)
mbed_official 0:f4db29eb9e47 389 LINK_STATS_INC(link.lenerr);
mbed_official 0:f4db29eb9e47 390 #endif
mbed_official 0:f4db29eb9e47 391
mbed_official 0:f4db29eb9e47 392 /* Drop the frame */
mbed_official 0:f4db29eb9e47 393 LINK_STATS_INC(link.drop);
mbed_official 0:f4db29eb9e47 394
mbed_official 0:f4db29eb9e47 395 /* Re-queue the pbuf for receive */
mbed_official 0:f4db29eb9e47 396 lpc_enetif->rx_free_descs++;
mbed_official 0:f4db29eb9e47 397 p = lpc_enetif->rxb[idx];
mbed_official 0:f4db29eb9e47 398 lpc_enetif->rxb[idx] = NULL;
mbed_official 0:f4db29eb9e47 399 lpc_rxqueue_pbuf(lpc_enetif, p);
mbed_official 0:f4db29eb9e47 400
mbed_official 0:f4db29eb9e47 401 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 0:f4db29eb9e47 402 ("lpc_low_level_input: Packet dropped with errors (0x%x)\n",
mbed_official 0:f4db29eb9e47 403 lpc_enetif->prxs[idx].statusinfo));
mbed_official 0:f4db29eb9e47 404 } else {
mbed_official 0:f4db29eb9e47 405 /* A packet is waiting, get length */
mbed_official 0:f4db29eb9e47 406 length = (lpc_enetif->prxs[idx].statusinfo & 0x7FF) + 1;
mbed_official 0:f4db29eb9e47 407
mbed_official 0:f4db29eb9e47 408 /* Zero-copy */
mbed_official 0:f4db29eb9e47 409 p = lpc_enetif->rxb[idx];
mbed_official 0:f4db29eb9e47 410 p->len = (u16_t) length;
mbed_official 0:f4db29eb9e47 411
mbed_official 0:f4db29eb9e47 412 /* Free pbuf from desriptor */
mbed_official 0:f4db29eb9e47 413 lpc_enetif->rxb[idx] = NULL;
mbed_official 0:f4db29eb9e47 414 lpc_enetif->rx_free_descs++;
mbed_official 0:f4db29eb9e47 415
mbed_official 0:f4db29eb9e47 416 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 0:f4db29eb9e47 417 ("lpc_low_level_input: Packet received: %p, size %d (index=%d)\n",
mbed_official 0:f4db29eb9e47 418 p, length, idx));
mbed_official 0:f4db29eb9e47 419
mbed_official 0:f4db29eb9e47 420 /* Save size */
mbed_official 0:f4db29eb9e47 421 p->tot_len = (u16_t) length;
mbed_official 0:f4db29eb9e47 422 LINK_STATS_INC(link.recv);
mbed_official 0:f4db29eb9e47 423
mbed_official 0:f4db29eb9e47 424 /* Queue new buffer(s) */
mbed_official 0:f4db29eb9e47 425 lpc_rx_queue(lpc_enetif->netif);
mbed_official 0:f4db29eb9e47 426 }
mbed_official 0:f4db29eb9e47 427 }
mbed_official 0:f4db29eb9e47 428
mbed_official 0:f4db29eb9e47 429 #ifdef LOCK_RX_THREAD
mbed_official 0:f4db29eb9e47 430 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 431 sys_mutex_unlock(&lpc_enetif->TXLockMutex);
mbed_official 0:f4db29eb9e47 432 #endif
mbed_official 0:f4db29eb9e47 433 #endif
mbed_official 0:f4db29eb9e47 434
mbed_official 0:f4db29eb9e47 435 return p;
mbed_official 0:f4db29eb9e47 436 }
mbed_official 0:f4db29eb9e47 437
mbed_official 0:f4db29eb9e47 438 /** \brief Attempt to read a packet from the EMAC interface.
mbed_official 0:f4db29eb9e47 439 *
mbed_official 0:f4db29eb9e47 440 * \param[in] netif the lwip network interface structure for this lpc_enetif
mbed_official 0:f4db29eb9e47 441 */
mbed_official 0:f4db29eb9e47 442 void lpc_enetif_input(struct netif *netif)
mbed_official 0:f4db29eb9e47 443 {
mbed_official 0:f4db29eb9e47 444 struct eth_hdr *ethhdr;
mbed_official 0:f4db29eb9e47 445 struct pbuf *p;
mbed_official 0:f4db29eb9e47 446
mbed_official 0:f4db29eb9e47 447 /* move received packet into a new pbuf */
mbed_official 0:f4db29eb9e47 448 p = lpc_low_level_input(netif);
mbed_official 0:f4db29eb9e47 449 if (p == NULL)
mbed_official 0:f4db29eb9e47 450 return;
mbed_official 0:f4db29eb9e47 451
mbed_official 0:f4db29eb9e47 452 /* points to packet payload, which starts with an Ethernet header */
mbed_official 0:f4db29eb9e47 453 ethhdr = p->payload;
mbed_official 0:f4db29eb9e47 454
mbed_official 0:f4db29eb9e47 455 switch (htons(ethhdr->type)) {
mbed_official 0:f4db29eb9e47 456 case ETHTYPE_IP:
mbed_official 0:f4db29eb9e47 457 case ETHTYPE_ARP:
mbed_official 0:f4db29eb9e47 458 #if PPPOE_SUPPORT
mbed_official 0:f4db29eb9e47 459 case ETHTYPE_PPPOEDISC:
mbed_official 0:f4db29eb9e47 460 case ETHTYPE_PPPOE:
mbed_official 0:f4db29eb9e47 461 #endif /* PPPOE_SUPPORT */
mbed_official 0:f4db29eb9e47 462 /* full packet send to tcpip_thread to process */
mbed_official 0:f4db29eb9e47 463 if (netif->input(p, netif) != ERR_OK) {
mbed_official 0:f4db29eb9e47 464 LWIP_DEBUGF(NETIF_DEBUG, ("lpc_enetif_input: IP input error\n"));
mbed_official 0:f4db29eb9e47 465 /* Free buffer */
mbed_official 0:f4db29eb9e47 466 pbuf_free(p);
mbed_official 0:f4db29eb9e47 467 }
mbed_official 0:f4db29eb9e47 468 break;
mbed_official 0:f4db29eb9e47 469
mbed_official 0:f4db29eb9e47 470 default:
mbed_official 0:f4db29eb9e47 471 /* Return buffer */
mbed_official 0:f4db29eb9e47 472 pbuf_free(p);
mbed_official 0:f4db29eb9e47 473 break;
mbed_official 0:f4db29eb9e47 474 }
mbed_official 0:f4db29eb9e47 475 }
mbed_official 0:f4db29eb9e47 476
mbed_official 0:f4db29eb9e47 477 /** \brief Determine if the passed address is usable for the ethernet
mbed_official 0:f4db29eb9e47 478 * DMA controller.
mbed_official 0:f4db29eb9e47 479 *
mbed_official 0:f4db29eb9e47 480 * \param[in] addr Address of packet to check for DMA safe operation
mbed_official 0:f4db29eb9e47 481 * \return 1 if the packet address is not safe, otherwise 0
mbed_official 0:f4db29eb9e47 482 */
mbed_official 0:f4db29eb9e47 483 static s32_t lpc_packet_addr_notsafe(void *addr) {
mbed_official 0:f4db29eb9e47 484 /* Check for legal address ranges */
mbed_official 0:f4db29eb9e47 485 if ((((u32_t) addr >= 0x20000000) && ((u32_t) addr < 0x20008000)) ||
mbed_official 0:f4db29eb9e47 486 (((u32_t) addr >= 0x80000000) && ((u32_t) addr < 0xF0000000)))
mbed_official 0:f4db29eb9e47 487 return 0;
mbed_official 0:f4db29eb9e47 488
mbed_official 0:f4db29eb9e47 489 return 1;
mbed_official 0:f4db29eb9e47 490 }
mbed_official 0:f4db29eb9e47 491
mbed_official 0:f4db29eb9e47 492 /** \brief Sets up the TX descriptor ring buffers.
mbed_official 0:f4db29eb9e47 493 *
mbed_official 0:f4db29eb9e47 494 * This function sets up the descriptor list used for transmit packets.
mbed_official 0:f4db29eb9e47 495 *
mbed_official 0:f4db29eb9e47 496 * \param[in] lpc_enetif Pointer to driver data structure
mbed_official 0:f4db29eb9e47 497 */
mbed_official 0:f4db29eb9e47 498 static err_t lpc_tx_setup(struct lpc_enetdata *lpc_enetif)
mbed_official 0:f4db29eb9e47 499 {
mbed_official 0:f4db29eb9e47 500 s32_t idx;
mbed_official 0:f4db29eb9e47 501
mbed_official 0:f4db29eb9e47 502 /* Build TX descriptors for local buffers */
mbed_official 0:f4db29eb9e47 503 for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) {
mbed_official 0:f4db29eb9e47 504 lpc_enetif->ptxd[idx].control = 0;
mbed_official 0:f4db29eb9e47 505 lpc_enetif->ptxs[idx].statusinfo = 0xFFFFFFFF;
mbed_official 0:f4db29eb9e47 506 }
mbed_official 0:f4db29eb9e47 507
mbed_official 0:f4db29eb9e47 508 /* Setup pointers to TX structures */
mbed_official 0:f4db29eb9e47 509 LPC_EMAC->TxDescriptor = (u32_t) &lpc_enetif->ptxd[0];
mbed_official 0:f4db29eb9e47 510 LPC_EMAC->TxStatus = (u32_t) &lpc_enetif->ptxs[0];
mbed_official 0:f4db29eb9e47 511 LPC_EMAC->TxDescriptorNumber = LPC_NUM_BUFF_TXDESCS - 1;
mbed_official 0:f4db29eb9e47 512
mbed_official 0:f4db29eb9e47 513 lpc_enetif->lpc_last_tx_idx = 0;
mbed_official 0:f4db29eb9e47 514
mbed_official 0:f4db29eb9e47 515 return ERR_OK;
mbed_official 0:f4db29eb9e47 516 }
mbed_official 0:f4db29eb9e47 517
mbed_official 0:f4db29eb9e47 518 /** \brief Free TX buffers that are complete
mbed_official 0:f4db29eb9e47 519 *
mbed_official 0:f4db29eb9e47 520 * \param[in] lpc_enetif Pointer to driver data structure
mbed_official 0:f4db29eb9e47 521 * \param[in] cidx EMAC current descriptor comsumer index
mbed_official 0:f4db29eb9e47 522 */
mbed_official 0:f4db29eb9e47 523 static void lpc_tx_reclaim_st(struct lpc_enetdata *lpc_enetif, u32_t cidx)
mbed_official 0:f4db29eb9e47 524 {
mbed_official 0:f4db29eb9e47 525 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 526 /* Get exclusive access */
mbed_official 0:f4db29eb9e47 527 sys_mutex_lock(&lpc_enetif->TXLockMutex);
mbed_official 0:f4db29eb9e47 528 #endif
mbed_official 0:f4db29eb9e47 529
mbed_official 0:f4db29eb9e47 530 while (cidx != lpc_enetif->lpc_last_tx_idx) {
mbed_official 0:f4db29eb9e47 531 if (lpc_enetif->txb[lpc_enetif->lpc_last_tx_idx] != NULL) {
mbed_official 0:f4db29eb9e47 532 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 0:f4db29eb9e47 533 ("lpc_tx_reclaim_st: Freeing packet %p (index %d)\n",
mbed_official 0:f4db29eb9e47 534 lpc_enetif->txb[lpc_enetif->lpc_last_tx_idx],
mbed_official 0:f4db29eb9e47 535 lpc_enetif->lpc_last_tx_idx));
mbed_official 0:f4db29eb9e47 536 pbuf_free(lpc_enetif->txb[lpc_enetif->lpc_last_tx_idx]);
mbed_official 0:f4db29eb9e47 537 lpc_enetif->txb[lpc_enetif->lpc_last_tx_idx] = NULL;
mbed_official 0:f4db29eb9e47 538 }
mbed_official 0:f4db29eb9e47 539
mbed_official 0:f4db29eb9e47 540 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 541 xSemaphoreGive(lpc_enetif->xTXDCountSem);
mbed_official 0:f4db29eb9e47 542 #endif
mbed_official 0:f4db29eb9e47 543 lpc_enetif->lpc_last_tx_idx++;
mbed_official 0:f4db29eb9e47 544 if (lpc_enetif->lpc_last_tx_idx >= LPC_NUM_BUFF_TXDESCS)
mbed_official 0:f4db29eb9e47 545 lpc_enetif->lpc_last_tx_idx = 0;
mbed_official 0:f4db29eb9e47 546 }
mbed_official 0:f4db29eb9e47 547
mbed_official 0:f4db29eb9e47 548 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 549 /* Restore access */
mbed_official 0:f4db29eb9e47 550 sys_mutex_unlock(&lpc_enetif->TXLockMutex);
mbed_official 0:f4db29eb9e47 551 #endif
mbed_official 0:f4db29eb9e47 552 }
mbed_official 0:f4db29eb9e47 553
mbed_official 0:f4db29eb9e47 554 /** \brief User call for freeingTX buffers that are complete
mbed_official 0:f4db29eb9e47 555 *
mbed_official 0:f4db29eb9e47 556 * \param[in] netif the lwip network interface structure for this lpc_enetif
mbed_official 0:f4db29eb9e47 557 */
mbed_official 0:f4db29eb9e47 558 void lpc_tx_reclaim(struct netif *netif)
mbed_official 0:f4db29eb9e47 559 {
mbed_official 0:f4db29eb9e47 560 lpc_tx_reclaim_st((struct lpc_enetdata *) netif->state,
mbed_official 0:f4db29eb9e47 561 LPC_EMAC->TxConsumeIndex);
mbed_official 0:f4db29eb9e47 562 }
mbed_official 0:f4db29eb9e47 563
mbed_official 0:f4db29eb9e47 564 /** \brief Polls if an available TX descriptor is ready. Can be used to
mbed_official 0:f4db29eb9e47 565 * determine if the low level transmit function will block.
mbed_official 0:f4db29eb9e47 566 *
mbed_official 0:f4db29eb9e47 567 * \param[in] netif the lwip network interface structure for this lpc_enetif
mbed_official 0:f4db29eb9e47 568 * \return 0 if no descriptors are read, or >0
mbed_official 0:f4db29eb9e47 569 */
mbed_official 0:f4db29eb9e47 570 s32_t lpc_tx_ready(struct netif *netif)
mbed_official 0:f4db29eb9e47 571 {
mbed_official 0:f4db29eb9e47 572 s32_t fb;
mbed_official 0:f4db29eb9e47 573 u32_t idx, cidx;
mbed_official 0:f4db29eb9e47 574
mbed_official 0:f4db29eb9e47 575 cidx = LPC_EMAC->TxConsumeIndex;
mbed_official 0:f4db29eb9e47 576 idx = LPC_EMAC->TxProduceIndex;
mbed_official 0:f4db29eb9e47 577
mbed_official 0:f4db29eb9e47 578 /* Determine number of free buffers */
mbed_official 0:f4db29eb9e47 579 if (idx == cidx)
mbed_official 0:f4db29eb9e47 580 fb = LPC_NUM_BUFF_TXDESCS;
mbed_official 0:f4db29eb9e47 581 else if (cidx > idx)
mbed_official 0:f4db29eb9e47 582 fb = (LPC_NUM_BUFF_TXDESCS - 1) -
mbed_official 0:f4db29eb9e47 583 ((idx + LPC_NUM_BUFF_TXDESCS) - cidx);
mbed_official 0:f4db29eb9e47 584 else
mbed_official 0:f4db29eb9e47 585 fb = (LPC_NUM_BUFF_TXDESCS - 1) - (cidx - idx);
mbed_official 0:f4db29eb9e47 586
mbed_official 0:f4db29eb9e47 587 return fb;
mbed_official 0:f4db29eb9e47 588 }
mbed_official 0:f4db29eb9e47 589
mbed_official 0:f4db29eb9e47 590 /** \brief Low level output of a packet. Never call this from an
mbed_official 0:f4db29eb9e47 591 * interrupt context, as it may block until TX descriptors
mbed_official 0:f4db29eb9e47 592 * become available.
mbed_official 0:f4db29eb9e47 593 *
mbed_official 0:f4db29eb9e47 594 * \param[in] netif the lwip network interface structure for this lpc_enetif
mbed_official 0:f4db29eb9e47 595 * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type)
mbed_official 0:f4db29eb9e47 596 * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent
mbed_official 0:f4db29eb9e47 597 */
mbed_official 0:f4db29eb9e47 598 static err_t lpc_low_level_output(struct netif *netif, struct pbuf *p)
mbed_official 0:f4db29eb9e47 599 {
mbed_official 0:f4db29eb9e47 600 struct lpc_enetdata *lpc_enetif = netif->state;
mbed_official 0:f4db29eb9e47 601 struct pbuf *q;
mbed_official 0:f4db29eb9e47 602 u8_t *dst;
mbed_official 0:f4db29eb9e47 603 u32_t idx, sz = 0;
mbed_official 0:f4db29eb9e47 604 err_t err = ERR_OK;
mbed_official 0:f4db29eb9e47 605 struct pbuf *np;
mbed_official 0:f4db29eb9e47 606 u32_t dn, notdmasafe = 0;
mbed_official 0:f4db29eb9e47 607
mbed_official 0:f4db29eb9e47 608 /* Zero-copy TX buffers may be fragmented across mutliple payload
mbed_official 0:f4db29eb9e47 609 chains. Determine the number of descriptors needed for the
mbed_official 0:f4db29eb9e47 610 transfer. The pbuf chaining can be a mess! */
mbed_official 0:f4db29eb9e47 611 dn = (u32_t) pbuf_clen(p);
mbed_official 0:f4db29eb9e47 612
mbed_official 0:f4db29eb9e47 613 /* Test to make sure packet addresses are DMA safe. A DMA safe
mbed_official 0:f4db29eb9e47 614 address is once that uses external memory or periphheral RAM.
mbed_official 0:f4db29eb9e47 615 IRAM and FLASH are not safe! */
mbed_official 0:f4db29eb9e47 616 for (q = p; q != NULL; q = q->next)
mbed_official 0:f4db29eb9e47 617 notdmasafe += lpc_packet_addr_notsafe(q->payload);
mbed_official 0:f4db29eb9e47 618
mbed_official 0:f4db29eb9e47 619 #if LPC_TX_PBUF_BOUNCE_EN==1
mbed_official 0:f4db29eb9e47 620 /* If the pbuf is not DMA safe, a new bounce buffer (pbuf) will be
mbed_official 0:f4db29eb9e47 621 created that will be used instead. This requires an copy from the
mbed_official 0:f4db29eb9e47 622 non-safe DMA region to the new pbuf */
mbed_official 0:f4db29eb9e47 623 if (notdmasafe) {
mbed_official 0:f4db29eb9e47 624 /* Allocate a pbuf in DMA memory */
mbed_official 0:f4db29eb9e47 625 np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
mbed_official 0:f4db29eb9e47 626 if (np == NULL)
mbed_official 0:f4db29eb9e47 627 return ERR_MEM;
mbed_official 0:f4db29eb9e47 628
mbed_official 0:f4db29eb9e47 629 /* This buffer better be contiguous! */
mbed_official 0:f4db29eb9e47 630 LWIP_ASSERT("lpc_low_level_output: New transmit pbuf is chained",
mbed_official 0:f4db29eb9e47 631 (pbuf_clen(np) == 1));
mbed_official 0:f4db29eb9e47 632
mbed_official 0:f4db29eb9e47 633 /* Copy to DMA safe pbuf */
mbed_official 0:f4db29eb9e47 634 dst = (u8_t *) np->payload;
mbed_official 0:f4db29eb9e47 635 for(q = p; q != NULL; q = q->next) {
mbed_official 0:f4db29eb9e47 636 /* Copy the buffer to the descriptor's buffer */
mbed_official 0:f4db29eb9e47 637 MEMCPY(dst, (u8_t *) q->payload, q->len);
mbed_official 0:f4db29eb9e47 638 dst += q->len;
mbed_official 0:f4db29eb9e47 639 }
mbed_official 0:f4db29eb9e47 640 np->len = p->tot_len;
mbed_official 0:f4db29eb9e47 641
mbed_official 0:f4db29eb9e47 642 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 0:f4db29eb9e47 643 ("lpc_low_level_output: Switched to DMA safe buffer, old=%p, new=%p\n",
mbed_official 0:f4db29eb9e47 644 q, np));
mbed_official 0:f4db29eb9e47 645
mbed_official 0:f4db29eb9e47 646 /* use the new buffer for descrptor queueing. The original pbuf will
mbed_official 0:f4db29eb9e47 647 be de-allocated outsuide this driver. */
mbed_official 0:f4db29eb9e47 648 p = np;
mbed_official 0:f4db29eb9e47 649 dn = 1;
mbed_official 0:f4db29eb9e47 650 }
mbed_official 0:f4db29eb9e47 651 #else
mbed_official 0:f4db29eb9e47 652 if (notdmasafe)
mbed_official 0:f4db29eb9e47 653 LWIP_ASSERT("lpc_low_level_output: Not a DMA safe pbuf",
mbed_official 0:f4db29eb9e47 654 (notdmasafe == 0));
mbed_official 0:f4db29eb9e47 655 #endif
mbed_official 0:f4db29eb9e47 656
mbed_official 0:f4db29eb9e47 657 /* Wait until enough descriptors are available for the transfer. */
mbed_official 0:f4db29eb9e47 658 /* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */
mbed_official 0:f4db29eb9e47 659 while (dn > lpc_tx_ready(netif))
mbed_official 0:f4db29eb9e47 660 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 661 xSemaphoreTake(lpc_enetif->xTXDCountSem, 0);
mbed_official 0:f4db29eb9e47 662 #else
mbed_official 0:f4db29eb9e47 663 msDelay(1);
mbed_official 0:f4db29eb9e47 664 #endif
mbed_official 0:f4db29eb9e47 665
mbed_official 0:f4db29eb9e47 666 /* Get free TX buffer index */
mbed_official 0:f4db29eb9e47 667 idx = LPC_EMAC->TxProduceIndex;
mbed_official 0:f4db29eb9e47 668
mbed_official 0:f4db29eb9e47 669 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 670 /* Get exclusive access */
mbed_official 0:f4db29eb9e47 671 sys_mutex_lock(&lpc_enetif->TXLockMutex);
mbed_official 0:f4db29eb9e47 672 #endif
mbed_official 0:f4db29eb9e47 673
mbed_official 0:f4db29eb9e47 674 /* Prevent LWIP from de-allocating this pbuf. The driver will
mbed_official 0:f4db29eb9e47 675 free it once it's been transmitted. */
mbed_official 0:f4db29eb9e47 676 if (!notdmasafe)
mbed_official 0:f4db29eb9e47 677 pbuf_ref(p);
mbed_official 0:f4db29eb9e47 678
mbed_official 0:f4db29eb9e47 679 /* Setup transfers */
mbed_official 0:f4db29eb9e47 680 q = p;
mbed_official 0:f4db29eb9e47 681 while (dn > 0) {
mbed_official 0:f4db29eb9e47 682 dn--;
mbed_official 0:f4db29eb9e47 683
mbed_official 0:f4db29eb9e47 684 /* Only save pointer to free on last descriptor */
mbed_official 0:f4db29eb9e47 685 if (dn == 0) {
mbed_official 0:f4db29eb9e47 686 /* Save size of packet and signal it's ready */
mbed_official 0:f4db29eb9e47 687 lpc_enetif->ptxd[idx].control = (q->len - 1) | EMAC_TCTRL_INT |
mbed_official 0:f4db29eb9e47 688 EMAC_TCTRL_LAST;
mbed_official 0:f4db29eb9e47 689 lpc_enetif->txb[idx] = p;
mbed_official 0:f4db29eb9e47 690 }
mbed_official 0:f4db29eb9e47 691 else {
mbed_official 0:f4db29eb9e47 692 /* Save size of packet, descriptor is not last */
mbed_official 0:f4db29eb9e47 693 lpc_enetif->ptxd[idx].control = (q->len - 1) | EMAC_TCTRL_INT;
mbed_official 0:f4db29eb9e47 694 lpc_enetif->txb[idx] = NULL;
mbed_official 0:f4db29eb9e47 695 }
mbed_official 0:f4db29eb9e47 696
mbed_official 0:f4db29eb9e47 697 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 0:f4db29eb9e47 698 ("lpc_low_level_output: pbuf packet(%p) sent, chain#=%d,"
mbed_official 0:f4db29eb9e47 699 " size = %d (index=%d)\n", q->payload, dn, q->len, idx));
mbed_official 0:f4db29eb9e47 700
mbed_official 0:f4db29eb9e47 701 lpc_enetif->ptxd[idx].packet = (u32_t) q->payload;
mbed_official 0:f4db29eb9e47 702
mbed_official 0:f4db29eb9e47 703 q = q->next;
mbed_official 0:f4db29eb9e47 704
mbed_official 0:f4db29eb9e47 705 idx++;
mbed_official 0:f4db29eb9e47 706 if (idx >= LPC_NUM_BUFF_TXDESCS)
mbed_official 0:f4db29eb9e47 707 idx = 0;
mbed_official 0:f4db29eb9e47 708 }
mbed_official 0:f4db29eb9e47 709
mbed_official 0:f4db29eb9e47 710 LPC_EMAC->TxProduceIndex = idx;
mbed_official 0:f4db29eb9e47 711
mbed_official 0:f4db29eb9e47 712 LINK_STATS_INC(link.xmit);
mbed_official 0:f4db29eb9e47 713
mbed_official 0:f4db29eb9e47 714 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 715 /* Restore access */
mbed_official 0:f4db29eb9e47 716 sys_mutex_unlock(&lpc_enetif->TXLockMutex);
mbed_official 0:f4db29eb9e47 717 #endif
mbed_official 0:f4db29eb9e47 718
mbed_official 0:f4db29eb9e47 719 return ERR_OK;
mbed_official 0:f4db29eb9e47 720 }
mbed_official 0:f4db29eb9e47 721
mbed_official 0:f4db29eb9e47 722 /** \brief LPC EMAC interrupt handler.
mbed_official 0:f4db29eb9e47 723 *
mbed_official 0:f4db29eb9e47 724 * This function handles the transmit, receive, and error interrupt of
mbed_official 0:f4db29eb9e47 725 * the LPC177x_8x. This is meant to be used when NO_SYS=0.
mbed_official 0:f4db29eb9e47 726 */
mbed_official 0:f4db29eb9e47 727 void ENET_IRQHandler(void)
mbed_official 0:f4db29eb9e47 728 {
mbed_official 0:f4db29eb9e47 729 #if NO_SYS == 1
mbed_official 0:f4db29eb9e47 730 /* Interrupts are not used without an RTOS */
mbed_official 0:f4db29eb9e47 731 NVIC_DisableIRQ(ENET_IRQn);
mbed_official 0:f4db29eb9e47 732 #else
mbed_official 0:f4db29eb9e47 733 signed portBASE_TYPE xRecTaskWoken = pdFALSE, XTXTaskWoken = pdFALSE;
mbed_official 0:f4db29eb9e47 734 uint32_t ints;
mbed_official 0:f4db29eb9e47 735
mbed_official 0:f4db29eb9e47 736 /* Interrupts are of 2 groups - transmit or receive. Based on the
mbed_official 0:f4db29eb9e47 737 interrupt, kick off the receive or transmit (cleanup) task */
mbed_official 0:f4db29eb9e47 738
mbed_official 0:f4db29eb9e47 739 /* Get pending interrupts */
mbed_official 0:f4db29eb9e47 740 ints = LPC_EMAC->IntStatus;
mbed_official 0:f4db29eb9e47 741
mbed_official 0:f4db29eb9e47 742 if (ints & RXINTGROUP) {
mbed_official 0:f4db29eb9e47 743 /* RX group interrupt(s) */
mbed_official 0:f4db29eb9e47 744 /* Give semaphore to wakeup RX receive task. Note the FreeRTOS
mbed_official 0:f4db29eb9e47 745 method is used instead of the LWIP arch method. */
mbed_official 0:f4db29eb9e47 746 xSemaphoreGiveFromISR(lpc_enetdata.RxSem, &xRecTaskWoken);
mbed_official 0:f4db29eb9e47 747 }
mbed_official 0:f4db29eb9e47 748
mbed_official 0:f4db29eb9e47 749 if (ints & TXINTGROUP) {
mbed_official 0:f4db29eb9e47 750 /* TX group interrupt(s) */
mbed_official 0:f4db29eb9e47 751 /* Give semaphore to wakeup TX cleanup task. Note the FreeRTOS
mbed_official 0:f4db29eb9e47 752 method is used instead of the LWIP arch method. */
mbed_official 0:f4db29eb9e47 753 xSemaphoreGiveFromISR(lpc_enetdata.TxCleanSem, &XTXTaskWoken);
mbed_official 0:f4db29eb9e47 754 }
mbed_official 0:f4db29eb9e47 755
mbed_official 0:f4db29eb9e47 756 /* Clear pending interrupts */
mbed_official 0:f4db29eb9e47 757 LPC_EMAC->IntClear = ints;
mbed_official 0:f4db29eb9e47 758
mbed_official 0:f4db29eb9e47 759 /* Context switch needed? */
mbed_official 0:f4db29eb9e47 760 portEND_SWITCHING_ISR( xRecTaskWoken || XTXTaskWoken );
mbed_official 0:f4db29eb9e47 761 #endif
mbed_official 0:f4db29eb9e47 762 }
mbed_official 0:f4db29eb9e47 763
mbed_official 0:f4db29eb9e47 764 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 765 /** \brief Packet reception task
mbed_official 0:f4db29eb9e47 766 *
mbed_official 0:f4db29eb9e47 767 * This task is called when a packet is received. It will
mbed_official 0:f4db29eb9e47 768 * pass the packet to the LWIP core.
mbed_official 0:f4db29eb9e47 769 *
mbed_official 0:f4db29eb9e47 770 * \param[in] pvParameters Not used yet
mbed_official 0:f4db29eb9e47 771 */
mbed_official 0:f4db29eb9e47 772 static portTASK_FUNCTION( vPacketReceiveTask, pvParameters )
mbed_official 0:f4db29eb9e47 773 {
mbed_official 0:f4db29eb9e47 774 struct lpc_enetdata *lpc_enetif = pvParameters;
mbed_official 0:f4db29eb9e47 775
mbed_official 0:f4db29eb9e47 776 while (1) {
mbed_official 0:f4db29eb9e47 777 /* Wait for receive task to wakeup */
mbed_official 0:f4db29eb9e47 778 sys_arch_sem_wait(&lpc_enetif->RxSem, 0);
mbed_official 0:f4db29eb9e47 779
mbed_official 0:f4db29eb9e47 780 /* Process packets until all empty */
mbed_official 0:f4db29eb9e47 781 while (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex)
mbed_official 0:f4db29eb9e47 782 lpc_enetif_input(lpc_enetif->netif);
mbed_official 0:f4db29eb9e47 783 }
mbed_official 0:f4db29eb9e47 784 }
mbed_official 0:f4db29eb9e47 785
mbed_official 0:f4db29eb9e47 786 /** \brief Transmit cleanup task
mbed_official 0:f4db29eb9e47 787 *
mbed_official 0:f4db29eb9e47 788 * This task is called when a transmit interrupt occurs and
mbed_official 0:f4db29eb9e47 789 * reclaims the pbuf and descriptor used for the packet once
mbed_official 0:f4db29eb9e47 790 * the packet has been transferred.
mbed_official 0:f4db29eb9e47 791 *
mbed_official 0:f4db29eb9e47 792 * \param[in] pvParameters Not used yet
mbed_official 0:f4db29eb9e47 793 */
mbed_official 0:f4db29eb9e47 794 static portTASK_FUNCTION( vTransmitCleanupTask, pvParameters )
mbed_official 0:f4db29eb9e47 795 {
mbed_official 0:f4db29eb9e47 796 struct lpc_enetdata *lpc_enetif = pvParameters;
mbed_official 0:f4db29eb9e47 797 s32_t idx;
mbed_official 0:f4db29eb9e47 798
mbed_official 0:f4db29eb9e47 799 while (1) {
mbed_official 0:f4db29eb9e47 800 /* Wait for transmit cleanup task to wakeup */
mbed_official 0:f4db29eb9e47 801 sys_arch_sem_wait(&lpc_enetif->TxCleanSem, 0);
mbed_official 0:f4db29eb9e47 802
mbed_official 0:f4db29eb9e47 803 /* Error handling for TX underruns. This should never happen unless
mbed_official 0:f4db29eb9e47 804 something is holding the bus or the clocks are going too slow. It
mbed_official 0:f4db29eb9e47 805 can probably be safely removed. */
mbed_official 0:f4db29eb9e47 806 if (LPC_EMAC->IntStatus & EMAC_INT_TX_UNDERRUN) {
mbed_official 0:f4db29eb9e47 807 LINK_STATS_INC(link.err);
mbed_official 0:f4db29eb9e47 808 LINK_STATS_INC(link.drop);
mbed_official 0:f4db29eb9e47 809
mbed_official 0:f4db29eb9e47 810 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 811 /* Get exclusive access */
mbed_official 0:f4db29eb9e47 812 sys_mutex_lock(&lpc_enetif->TXLockMutex);
mbed_official 0:f4db29eb9e47 813 #endif
mbed_official 0:f4db29eb9e47 814 /* Reset the TX side */
mbed_official 0:f4db29eb9e47 815 LPC_EMAC->MAC1 |= EMAC_MAC1_RES_TX;
mbed_official 0:f4db29eb9e47 816 LPC_EMAC->IntClear = EMAC_INT_TX_UNDERRUN;
mbed_official 0:f4db29eb9e47 817
mbed_official 0:f4db29eb9e47 818 /* De-allocate all queued TX pbufs */
mbed_official 0:f4db29eb9e47 819 for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) {
mbed_official 0:f4db29eb9e47 820 if (lpc_enetif->txb[idx] != NULL) {
mbed_official 0:f4db29eb9e47 821 pbuf_free(lpc_enetif->txb[idx]);
mbed_official 0:f4db29eb9e47 822 lpc_enetif->txb[idx] = NULL;
mbed_official 0:f4db29eb9e47 823 }
mbed_official 0:f4db29eb9e47 824 }
mbed_official 0:f4db29eb9e47 825
mbed_official 0:f4db29eb9e47 826 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 827 /* Restore access */
mbed_official 0:f4db29eb9e47 828 sys_mutex_unlock(&lpc_enetif->TXLockMutex);
mbed_official 0:f4db29eb9e47 829 #endif
mbed_official 0:f4db29eb9e47 830 /* Start TX side again */
mbed_official 0:f4db29eb9e47 831 lpc_tx_setup(lpc_enetif);
mbed_official 0:f4db29eb9e47 832 } else {
mbed_official 0:f4db29eb9e47 833 /* Free TX buffers that are done sending */
mbed_official 0:f4db29eb9e47 834 lpc_tx_reclaim(lpc_enetdata.netif);
mbed_official 0:f4db29eb9e47 835 }
mbed_official 0:f4db29eb9e47 836 }
mbed_official 0:f4db29eb9e47 837 }
mbed_official 0:f4db29eb9e47 838 #endif
mbed_official 0:f4db29eb9e47 839
mbed_official 0:f4db29eb9e47 840 /** \brief Low level init of the MAC and PHY.
mbed_official 0:f4db29eb9e47 841 *
mbed_official 0:f4db29eb9e47 842 * \param[in] netif Pointer to LWIP netif structure
mbed_official 0:f4db29eb9e47 843 */
mbed_official 0:f4db29eb9e47 844 static err_t low_level_init(struct netif *netif)
mbed_official 0:f4db29eb9e47 845 {
mbed_official 0:f4db29eb9e47 846 struct lpc_enetdata *lpc_enetif = netif->state;
mbed_official 0:f4db29eb9e47 847 err_t err = ERR_OK;
mbed_official 0:f4db29eb9e47 848
mbed_official 0:f4db29eb9e47 849 /* Enable MII clocking */
mbed_official 0:f4db29eb9e47 850 CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCENET, ENABLE);
mbed_official 0:f4db29eb9e47 851
mbed_official 0:f4db29eb9e47 852 /* Reset all MAC logic */
mbed_official 0:f4db29eb9e47 853 LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX |
mbed_official 0:f4db29eb9e47 854 EMAC_MAC1_RES_RX | EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES |
mbed_official 0:f4db29eb9e47 855 EMAC_MAC1_SOFT_RES;
mbed_official 0:f4db29eb9e47 856 LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES |
mbed_official 0:f4db29eb9e47 857 EMAC_CR_PASS_RUNT_FRM;
mbed_official 0:f4db29eb9e47 858 msDelay(10);
mbed_official 0:f4db29eb9e47 859
mbed_official 0:f4db29eb9e47 860 /* Initial MAC initialization */
mbed_official 0:f4db29eb9e47 861 LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
mbed_official 0:f4db29eb9e47 862 LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN |
mbed_official 0:f4db29eb9e47 863 EMAC_MAC2_VLAN_PAD_EN;
mbed_official 0:f4db29eb9e47 864 LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
mbed_official 0:f4db29eb9e47 865
mbed_official 0:f4db29eb9e47 866 /* Set RMII management clock rate to lowest speed */
mbed_official 0:f4db29eb9e47 867 LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(11) | EMAC_MCFG_RES_MII;
mbed_official 0:f4db29eb9e47 868 LPC_EMAC->MCFG &= ~EMAC_MCFG_RES_MII;
mbed_official 0:f4db29eb9e47 869
mbed_official 0:f4db29eb9e47 870 /* Maximum number of retries, 0x37 collision window, gap */
mbed_official 0:f4db29eb9e47 871 LPC_EMAC->CLRT = EMAC_CLRT_DEF;
mbed_official 0:f4db29eb9e47 872 LPC_EMAC->IPGR = EMAC_IPGR_P1_DEF | EMAC_IPGR_P2_DEF;
mbed_official 0:f4db29eb9e47 873
mbed_official 0:f4db29eb9e47 874 #if LPC_EMAC_RMII
mbed_official 0:f4db29eb9e47 875 /* RMII setup */
mbed_official 0:f4db29eb9e47 876 LPC_EMAC->Command = EMAC_CR_PASS_RUNT_FRM | EMAC_CR_RMII;
mbed_official 0:f4db29eb9e47 877 #else
mbed_official 0:f4db29eb9e47 878 /* MII setup */
mbed_official 0:f4db29eb9e47 879 LPC_EMAC->CR = EMAC_CR_PASS_RUNT_FRM;
mbed_official 0:f4db29eb9e47 880 #endif
mbed_official 0:f4db29eb9e47 881
mbed_official 0:f4db29eb9e47 882 /* Initialize the PHY and reset */
mbed_official 0:f4db29eb9e47 883 err = lpc_phy_init(netif, LPC_EMAC_RMII);
mbed_official 0:f4db29eb9e47 884 if (err != ERR_OK)
mbed_official 0:f4db29eb9e47 885 return err;
mbed_official 0:f4db29eb9e47 886
mbed_official 0:f4db29eb9e47 887 /* Save station address */
mbed_official 0:f4db29eb9e47 888 LPC_EMAC->SA2 = (u32_t) netif->hwaddr[0] |
mbed_official 0:f4db29eb9e47 889 (((u32_t) netif->hwaddr[1]) << 8);
mbed_official 0:f4db29eb9e47 890 LPC_EMAC->SA1 = (u32_t) netif->hwaddr[2] |
mbed_official 0:f4db29eb9e47 891 (((u32_t) netif->hwaddr[3]) << 8);
mbed_official 0:f4db29eb9e47 892 LPC_EMAC->SA0 = (u32_t) netif->hwaddr[4] |
mbed_official 0:f4db29eb9e47 893 (((u32_t) netif->hwaddr[5]) << 8);
mbed_official 0:f4db29eb9e47 894
mbed_official 0:f4db29eb9e47 895 /* Setup transmit and receive descriptors */
mbed_official 0:f4db29eb9e47 896 if (lpc_tx_setup(lpc_enetif) != ERR_OK)
mbed_official 0:f4db29eb9e47 897 return ERR_BUF;
mbed_official 0:f4db29eb9e47 898 if (lpc_rx_setup(lpc_enetif) != ERR_OK)
mbed_official 0:f4db29eb9e47 899 return ERR_BUF;
mbed_official 0:f4db29eb9e47 900
mbed_official 0:f4db29eb9e47 901 /* Enable packet reception */
mbed_official 0:f4db29eb9e47 902 #if IP_SOF_BROADCAST_RECV
mbed_official 0:f4db29eb9e47 903 LPC_EMAC->RxFilterCtrl = EMAC_RFC_PERFECT_EN | EMAC_RFC_BCAST_EN;
mbed_official 0:f4db29eb9e47 904 #else
mbed_official 0:f4db29eb9e47 905 LPC_EMAC->RxFilterCtrl = EMAC_RFC_PERFECT_EN;
mbed_official 0:f4db29eb9e47 906 #endif
mbed_official 0:f4db29eb9e47 907
mbed_official 0:f4db29eb9e47 908 /* Clear and enable rx/tx interrupts */
mbed_official 0:f4db29eb9e47 909 LPC_EMAC->IntClear = 0xFFFF;
mbed_official 0:f4db29eb9e47 910 LPC_EMAC->IntEnable = RXINTGROUP | TXINTGROUP;
mbed_official 0:f4db29eb9e47 911
mbed_official 0:f4db29eb9e47 912 /* Enable RX and TX */
mbed_official 0:f4db29eb9e47 913 LPC_EMAC->Command |= EMAC_CR_RX_EN | EMAC_CR_TX_EN;
mbed_official 0:f4db29eb9e47 914 LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;
mbed_official 0:f4db29eb9e47 915
mbed_official 0:f4db29eb9e47 916 return err;
mbed_official 0:f4db29eb9e47 917 }
mbed_official 0:f4db29eb9e47 918
mbed_official 0:f4db29eb9e47 919 /* This function provides a method for the PHY to setup the EMAC
mbed_official 0:f4db29eb9e47 920 for the PHY negotiated duplex mode */
mbed_official 0:f4db29eb9e47 921 void lpc_emac_set_duplex(int full_duplex)
mbed_official 0:f4db29eb9e47 922 {
mbed_official 0:f4db29eb9e47 923 if (full_duplex) {
mbed_official 0:f4db29eb9e47 924 LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
mbed_official 0:f4db29eb9e47 925 LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
mbed_official 0:f4db29eb9e47 926 LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
mbed_official 0:f4db29eb9e47 927 } else {
mbed_official 0:f4db29eb9e47 928 LPC_EMAC->MAC2 &= ~EMAC_MAC2_FULL_DUP;
mbed_official 0:f4db29eb9e47 929 LPC_EMAC->Command &= ~EMAC_CR_FULL_DUP;
mbed_official 0:f4db29eb9e47 930 LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
mbed_official 0:f4db29eb9e47 931 }
mbed_official 0:f4db29eb9e47 932 }
mbed_official 0:f4db29eb9e47 933
mbed_official 0:f4db29eb9e47 934 /* This function provides a method for the PHY to setup the EMAC
mbed_official 0:f4db29eb9e47 935 for the PHY negotiated bit rate */
mbed_official 0:f4db29eb9e47 936 void lpc_emac_set_speed(int mbs_100)
mbed_official 0:f4db29eb9e47 937 {
mbed_official 0:f4db29eb9e47 938 if (mbs_100)
mbed_official 0:f4db29eb9e47 939 LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
mbed_official 0:f4db29eb9e47 940 else
mbed_official 0:f4db29eb9e47 941 LPC_EMAC->SUPP = 0;
mbed_official 0:f4db29eb9e47 942 }
mbed_official 0:f4db29eb9e47 943
mbed_official 0:f4db29eb9e47 944 /**
mbed_official 0:f4db29eb9e47 945 * This function is the ethernet packet send function. It calls
mbed_official 0:f4db29eb9e47 946 * etharp_output after checking link status.
mbed_official 0:f4db29eb9e47 947 *
mbed_official 0:f4db29eb9e47 948 * \param[in] netif the lwip network interface structure for this lpc_enetif
mbed_official 0:f4db29eb9e47 949 * \param[in] q Pointer to pbug to send
mbed_official 0:f4db29eb9e47 950 * \param[in] ipaddr IP address
mbed_official 0:f4db29eb9e47 951 * \return ERR_OK or error code
mbed_official 0:f4db29eb9e47 952 */
mbed_official 0:f4db29eb9e47 953 err_t lpc_etharp_output(struct netif *netif, struct pbuf *q,
mbed_official 0:f4db29eb9e47 954 ip_addr_t *ipaddr)
mbed_official 0:f4db29eb9e47 955 {
mbed_official 0:f4db29eb9e47 956 /* Only send packet is link is up */
mbed_official 0:f4db29eb9e47 957 if (netif->flags & NETIF_FLAG_LINK_UP)
mbed_official 0:f4db29eb9e47 958 return etharp_output(netif, q, ipaddr);
mbed_official 0:f4db29eb9e47 959
mbed_official 0:f4db29eb9e47 960 return ERR_CONN;
mbed_official 0:f4db29eb9e47 961 }
mbed_official 0:f4db29eb9e47 962
mbed_official 0:f4db29eb9e47 963 /**
mbed_official 0:f4db29eb9e47 964 * Should be called at the beginning of the program to set up the
mbed_official 0:f4db29eb9e47 965 * network interface.
mbed_official 0:f4db29eb9e47 966 *
mbed_official 0:f4db29eb9e47 967 * This function should be passed as a parameter to netif_add().
mbed_official 0:f4db29eb9e47 968 *
mbed_official 0:f4db29eb9e47 969 * @param[in] netif the lwip network interface structure for this lpc_enetif
mbed_official 0:f4db29eb9e47 970 * @return ERR_OK if the loopif is initialized
mbed_official 0:f4db29eb9e47 971 * ERR_MEM if private data couldn't be allocated
mbed_official 0:f4db29eb9e47 972 * any other err_t on error
mbed_official 0:f4db29eb9e47 973 */
mbed_official 0:f4db29eb9e47 974 err_t lpc_enetif_init(struct netif *netif)
mbed_official 0:f4db29eb9e47 975 {
mbed_official 0:f4db29eb9e47 976 err_t err;
mbed_official 0:f4db29eb9e47 977
mbed_official 0:f4db29eb9e47 978 LWIP_ASSERT("netif != NULL", (netif != NULL));
mbed_official 0:f4db29eb9e47 979
mbed_official 0:f4db29eb9e47 980 lpc_enetdata.netif = netif;
mbed_official 0:f4db29eb9e47 981
mbed_official 0:f4db29eb9e47 982 /* set MAC hardware address */
mbed_official 0:f4db29eb9e47 983 board_get_macaddr(netif->hwaddr);
mbed_official 0:f4db29eb9e47 984 netif->hwaddr_len = ETHARP_HWADDR_LEN;
mbed_official 0:f4db29eb9e47 985
mbed_official 0:f4db29eb9e47 986 /* maximum transfer unit */
mbed_official 0:f4db29eb9e47 987 netif->mtu = 1500;
mbed_official 0:f4db29eb9e47 988
mbed_official 0:f4db29eb9e47 989 /* device capabilities */
mbed_official 0:f4db29eb9e47 990 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_UP |
mbed_official 0:f4db29eb9e47 991 NETIF_FLAG_ETHERNET;
mbed_official 0:f4db29eb9e47 992
mbed_official 0:f4db29eb9e47 993 /* Initialize the hardware */
mbed_official 0:f4db29eb9e47 994 netif->state = &lpc_enetdata;
mbed_official 0:f4db29eb9e47 995 err = low_level_init(netif);
mbed_official 0:f4db29eb9e47 996 if (err != ERR_OK)
mbed_official 0:f4db29eb9e47 997 return err;
mbed_official 0:f4db29eb9e47 998
mbed_official 0:f4db29eb9e47 999 #if LWIP_NETIF_HOSTNAME
mbed_official 0:f4db29eb9e47 1000 /* Initialize interface hostname */
mbed_official 0:f4db29eb9e47 1001 netif->hostname = "lwiplpc";
mbed_official 0:f4db29eb9e47 1002 #endif /* LWIP_NETIF_HOSTNAME */
mbed_official 0:f4db29eb9e47 1003
mbed_official 0:f4db29eb9e47 1004 netif->name[0] = 'e';
mbed_official 0:f4db29eb9e47 1005 netif->name[1] = 'n';
mbed_official 0:f4db29eb9e47 1006
mbed_official 0:f4db29eb9e47 1007 netif->output = lpc_etharp_output;
mbed_official 0:f4db29eb9e47 1008 netif->linkoutput = lpc_low_level_output;
mbed_official 0:f4db29eb9e47 1009
mbed_official 0:f4db29eb9e47 1010 /* For FreeRTOS, start tasks */
mbed_official 0:f4db29eb9e47 1011 #if NO_SYS == 0
mbed_official 0:f4db29eb9e47 1012 lpc_enetdata.xTXDCountSem = xSemaphoreCreateCounting(LPC_NUM_BUFF_TXDESCS,
mbed_official 0:f4db29eb9e47 1013 LPC_NUM_BUFF_TXDESCS);
mbed_official 0:f4db29eb9e47 1014 LWIP_ASSERT("xTXDCountSem creation error",
mbed_official 0:f4db29eb9e47 1015 (lpc_enetdata.xTXDCountSem != NULL));
mbed_official 0:f4db29eb9e47 1016
mbed_official 0:f4db29eb9e47 1017 err = sys_mutex_new(&lpc_enetdata.TXLockMutex);
mbed_official 0:f4db29eb9e47 1018 LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK));
mbed_official 0:f4db29eb9e47 1019
mbed_official 0:f4db29eb9e47 1020 /* Packet receive task */
mbed_official 0:f4db29eb9e47 1021 err = sys_sem_new(&lpc_enetdata.RxSem, 0);
mbed_official 0:f4db29eb9e47 1022 LWIP_ASSERT("RxSem creation error", (err == ERR_OK));
mbed_official 0:f4db29eb9e47 1023 sys_thread_new("receive_thread", vPacketReceiveTask, netif->state,
mbed_official 0:f4db29eb9e47 1024 DEFAULT_THREAD_STACKSIZE, tskRECPKT_PRIORITY);
mbed_official 0:f4db29eb9e47 1025
mbed_official 0:f4db29eb9e47 1026 /* Transmit cleanup task */
mbed_official 0:f4db29eb9e47 1027 err = sys_sem_new(&lpc_enetdata.TxCleanSem, 0);
mbed_official 0:f4db29eb9e47 1028 LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK));
mbed_official 0:f4db29eb9e47 1029 sys_thread_new("txclean_thread", vTransmitCleanupTask, netif->state,
mbed_official 0:f4db29eb9e47 1030 DEFAULT_THREAD_STACKSIZE, tskTXCLEAN_PRIORITY);
mbed_official 0:f4db29eb9e47 1031 #endif
mbed_official 0:f4db29eb9e47 1032
mbed_official 0:f4db29eb9e47 1033 return ERR_OK;
mbed_official 0:f4db29eb9e47 1034 }
mbed_official 0:f4db29eb9e47 1035
mbed_official 0:f4db29eb9e47 1036 /**
mbed_official 0:f4db29eb9e47 1037 * @}
mbed_official 0:f4db29eb9e47 1038 */
mbed_official 0:f4db29eb9e47 1039
mbed_official 0:f4db29eb9e47 1040 /* --------------------------------- End Of File ------------------------------ */