LwIP with PPP & Ethernet integration

Dependents:   NetworkingCoreLib

This is the mbed port of the LwIP stack: http://savannah.nongnu.org/projects/lwip/

It includes contributed content from NXP's port for LPCxxxx devices: http://www.lpcware.com/content/project/lightweight-ip-lwip-networking-stack

Licence

LwIP is licenced under the BSD licence:

Copyright (c) 2001-2004 Swedish Institute of Computer Science. 
All rights reserved. 
Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met: 
1. Redistributions of source code must retain the above copyright notice, 
this list of conditions and the following disclaimer. 
2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution. 
3. The name of the author may not be used to endorse or promote products 
derived from this software without specific prior written permission. 
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
donatien
Date:
Fri May 25 08:56:35 2012 +0000
Revision:
2:1a87f74b8e3b
Parent:
0:8e01dca41002
Removed compilation of EMAC driver when using PPP

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 ------------------------------ */