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