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:
Thu May 26 09:00:26 2016 +0100
Revision:
33:9de8bd8ca1c8
Synchronized with git revision 745ebbf4557f0f3964f73063c1d88ddbcda0ed22

Full URL: https://github.com/mbedmicro/mbed/commit/745ebbf4557f0f3964f73063c1d88ddbcda0ed22/

Synch - fix lwip-eth path

Who changed what in which revision?

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