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:
Mon Jun 09 15:00:19 2014 +0100
Revision:
14:578727b0a909
Parent:
10:ab9330955226
Child:
24:f274b521b211
Synchronized with git revision 6f498028bb40cc59185deef7578fe6788008b3ca

Full URL: https://github.com/mbedmicro/mbed/commit/6f498028bb40cc59185deef7578fe6788008b3ca/

[LPC4088] GCC: corrected alignment problem when setting up memory region...

Who changed what in which revision?

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