Adapted to Lora Semtech + Nucleo

Dependencies:   DebugLib

Dependents:   LoRaWAN-lmic-app LoRaWAN-lmic-app LoRaWAN-test-10secs LoRaPersonalizedDeviceForEverynet ... more

Fork of lwip_ppp_ethernet by Donatien Garnier

Committer:
pnysten
Date:
Fri Nov 20 12:30:58 2015 +0000
Revision:
3:a9e6ba815945
Parent:
2:1a87f74b8e3b
Adapted to Nucleo, LoRa Semtech

Who changed what in which revision?

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