NXP LPC1768 Ethernet driver for lwip and CMSIS-RTOS

Dependents:   EthernetInterface EthernetInterface EthernetInterface_RSF EthernetInterface ... more

Legacy Networking Libraries

This is an mbed 2 networking library. For mbed 5, the networking libraries have been revised to better support additional network stacks and thread safety here.

This library is based on the code of the NXP LPC port of the Lightweight TCP/IP Stack

Copyright(C) 2011, NXP Semiconductor
All rights reserved.

Software that is described herein is for illustrative purposes only
which provides customers with programming information regarding the
products. This software is supplied "AS IS" without any warranties.
NXP Semiconductors assumes no responsibility or liability for the
use of the software, conveys no license or title under any patent,
copyright, or mask work right to the product. NXP Semiconductors
reserves the right to make changes in the software without
notification. NXP Semiconductors also make no representation or
warranty that such application will be suitable for the specified
use without further testing or modification.
Committer:
mbed_official
Date:
Wed May 21 23:15:24 2014 +0100
Revision:
12:8722e4b223d8
Parent:
11:fd39ffab9527
Child:
15:82aaaa2f4d5c
Synchronized with git revision 3c2119fab6f21f7d8fdce8bd96665bbaf8e5beec

Full URL: https://github.com/mbedmicro/mbed/commit/3c2119fab6f21f7d8fdce8bd96665bbaf8e5beec/

Signed-off-by: Sergio Scaglia <sergio.scaglia@arm.com>

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 10:ab9330955226 1 #include "lwip/opt.h"
mbed_official 10:ab9330955226 2 #include "lwip/sys.h"
mbed_official 10:ab9330955226 3 #include "lwip/def.h"
mbed_official 10:ab9330955226 4 #include "lwip/mem.h"
mbed_official 10:ab9330955226 5 #include "lwip/pbuf.h"
mbed_official 10:ab9330955226 6 #include "lwip/stats.h"
mbed_official 10:ab9330955226 7 #include "lwip/snmp.h"
mbed_official 10:ab9330955226 8 #include "lwip/tcpip.h"
mbed_official 10:ab9330955226 9 #include "netif/etharp.h"
mbed_official 10:ab9330955226 10 #include "netif/ppp_oe.h"
mbed_official 10:ab9330955226 11
mbed_official 10:ab9330955226 12 #include "eth_arch.h"
mbed_official 10:ab9330955226 13 #include "sys_arch.h"
mbed_official 10:ab9330955226 14
mbed_official 10:ab9330955226 15 #include "fsl_enet_driver.h"
mbed_official 10:ab9330955226 16 #include "fsl_enet_hal.h"
mbed_official 10:ab9330955226 17 #include "fsl_device_registers.h"
mbed_official 10:ab9330955226 18 #include "fsl_phy_driver.h"
mbed_official 10:ab9330955226 19 #include "fsl_interrupt_manager.h"
mbed_official 10:ab9330955226 20 #include "k64f_emac_config.h"
mbed_official 10:ab9330955226 21 #include <ctype.h>
mbed_official 10:ab9330955226 22 #include <stdio.h>
mbed_official 10:ab9330955226 23 #include <string.h>
mbed_official 10:ab9330955226 24 #include <stdlib.h>
mbed_official 10:ab9330955226 25
mbed_official 10:ab9330955226 26 #include "mbed_interface.h"
mbed_official 10:ab9330955226 27
mbed_official 10:ab9330955226 28 extern IRQn_Type enet_irq_ids[HW_ENET_INSTANCE_COUNT][FSL_FEATURE_ENET_INTERRUPT_COUNT];
mbed_official 10:ab9330955226 29 extern uint8_t enetIntMap[kEnetIntNum];
mbed_official 10:ab9330955226 30
mbed_official 10:ab9330955226 31 /********************************************************************************
mbed_official 10:ab9330955226 32 * Internal data
mbed_official 10:ab9330955226 33 ********************************************************************************/
mbed_official 10:ab9330955226 34
mbed_official 10:ab9330955226 35 extern void k64f_init_eth_hardware(void);
mbed_official 10:ab9330955226 36
mbed_official 10:ab9330955226 37 /* K64F EMAC driver data structure */
mbed_official 10:ab9330955226 38 struct k64f_enetdata {
mbed_official 10:ab9330955226 39 struct netif *netif; /**< Reference back to LWIP parent netif */
mbed_official 10:ab9330955226 40 sys_sem_t RxReadySem; /**< RX packet ready semaphore */
mbed_official 10:ab9330955226 41 sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */
mbed_official 10:ab9330955226 42 sys_mutex_t TXLockMutex; /**< TX critical section mutex */
mbed_official 10:ab9330955226 43 sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */
mbed_official 10:ab9330955226 44 volatile u32_t rx_free_descs; /**< Count of free RX descriptors */
mbed_official 10:ab9330955226 45 struct pbuf *rxb[ENET_RX_RING_LEN]; /**< RX pbuf pointer list, zero-copy mode */
mbed_official 10:ab9330955226 46 uint8_t *rx_desc_start_addr; /**< RX descriptor start address */
mbed_official 10:ab9330955226 47 uint8_t *tx_desc_start_addr; /**< TX descriptor start address */
mbed_official 10:ab9330955226 48 uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */
mbed_official 10:ab9330955226 49 uint8_t rx_fill_index; /**< RX ring fill index */
mbed_official 10:ab9330955226 50 struct pbuf *txb[ENET_TX_RING_LEN]; /**< TX pbuf pointer list, zero-copy mode */
mbed_official 10:ab9330955226 51 void *txb_aligned[ENET_TX_RING_LEN]; /**< TX aligned buffers (if needed) */
mbed_official 10:ab9330955226 52 };
mbed_official 10:ab9330955226 53
mbed_official 10:ab9330955226 54 static struct k64f_enetdata k64f_enetdata;
mbed_official 10:ab9330955226 55
mbed_official 10:ab9330955226 56 static enet_dev_if_t enetDevIf[HW_ENET_INSTANCE_COUNT];
mbed_official 10:ab9330955226 57 static enet_mac_config_t g_enetMacCfg[HW_ENET_INSTANCE_COUNT] =
mbed_official 10:ab9330955226 58 {
mbed_official 10:ab9330955226 59 {
mbed_official 10:ab9330955226 60 ENET_ETH_MAX_FLEN , /*!< enet receive buffer size*/
mbed_official 10:ab9330955226 61 ENET_RX_LARGE_BUFFER_NUM, /*!< enet large receive buffer number*/
mbed_official 10:ab9330955226 62 ENET_RX_RING_LEN, /*!< enet receive bd number*/
mbed_official 10:ab9330955226 63 ENET_TX_RING_LEN, /*!< enet transmit bd number*/
mbed_official 10:ab9330955226 64 {0}, /*!< enet mac address*/
mbed_official 10:ab9330955226 65 kEnetCfgRmii, /*!< enet rmii interface*/
mbed_official 10:ab9330955226 66 kEnetCfgSpeed100M, /*!< enet rmii 100M*/
mbed_official 10:ab9330955226 67 kEnetCfgFullDuplex, /*!< enet rmii Full- duplex*/
mbed_official 10:ab9330955226 68 /*!< enet mac control flag recommended to use enet_mac_control_flag_t
mbed_official 10:ab9330955226 69 we send frame with crc so receive crc forward for data length check test*/
mbed_official 10:ab9330955226 70 kEnetRxCrcFwdEnable | kEnetRxFlowControlEnable,
mbed_official 10:ab9330955226 71 true, /*!< enet txaccelerator enabled*/
mbed_official 10:ab9330955226 72 true, /*!< enet rxaccelerator enabled*/
mbed_official 10:ab9330955226 73 false, /*!< enet store and forward*/
mbed_official 10:ab9330955226 74 {false, false, true, false, true}, /*!< enet rxaccelerator config*/
mbed_official 10:ab9330955226 75 {false, false, true}, /*!< enet txaccelerator config*/
mbed_official 10:ab9330955226 76 true, /*!< vlan frame support*/
mbed_official 10:ab9330955226 77 true, /*!< phy auto discover*/
mbed_official 10:ab9330955226 78 ENET_MII_CLOCK, /*!< enet MDC clock*/
mbed_official 10:ab9330955226 79 },
mbed_official 10:ab9330955226 80 };
mbed_official 10:ab9330955226 81
mbed_official 10:ab9330955226 82 static enet_phy_config_t g_enetPhyCfg[HW_ENET_INSTANCE_COUNT] =
mbed_official 10:ab9330955226 83 {
mbed_official 10:ab9330955226 84 {0, false}
mbed_official 10:ab9330955226 85 };
mbed_official 10:ab9330955226 86
mbed_official 10:ab9330955226 87 /** \brief Driver transmit and receive thread priorities
mbed_official 10:ab9330955226 88 *
mbed_official 10:ab9330955226 89 * Thread priorities for receive thread and TX cleanup thread. Alter
mbed_official 10:ab9330955226 90 * to prioritize receive or transmit bandwidth. In a heavily loaded
mbed_official 10:ab9330955226 91 * system or with LEIP_DEBUG enabled, the priorities might be better
mbed_official 10:ab9330955226 92 * the same. */
mbed_official 10:ab9330955226 93 #define RX_PRIORITY (osPriorityNormal)
mbed_official 10:ab9330955226 94 #define TX_PRIORITY (osPriorityNormal)
mbed_official 10:ab9330955226 95 #define PHY_PRIORITY (osPriorityNormal)
mbed_official 10:ab9330955226 96
mbed_official 10:ab9330955226 97 /** \brief Debug output formatter lock define
mbed_official 10:ab9330955226 98 *
mbed_official 10:ab9330955226 99 * When using FreeRTOS and with LWIP_DEBUG enabled, enabling this
mbed_official 10:ab9330955226 100 * define will allow RX debug messages to not interleave with the
mbed_official 10:ab9330955226 101 * TX messages (so they are actually readable). Not enabling this
mbed_official 10:ab9330955226 102 * define when the system is under load will cause the output to
mbed_official 10:ab9330955226 103 * be unreadable. There is a small tradeoff in performance for this
mbed_official 10:ab9330955226 104 * so use it only for debug. */
mbed_official 10:ab9330955226 105 //#define LOCK_RX_THREAD
mbed_official 10:ab9330955226 106
mbed_official 10:ab9330955226 107 /** \brief Signal used for ethernet ISR to signal packet_rx() thread.
mbed_official 10:ab9330955226 108 */
mbed_official 10:ab9330955226 109 #define RX_SIGNAL 1
mbed_official 10:ab9330955226 110
mbed_official 10:ab9330955226 111 // K64F-specific macros
mbed_official 10:ab9330955226 112 #define RX_PBUF_AUTO_INDEX (-1)
mbed_official 10:ab9330955226 113
mbed_official 10:ab9330955226 114 /********************************************************************************
mbed_official 10:ab9330955226 115 * Buffer management
mbed_official 10:ab9330955226 116 ********************************************************************************/
mbed_official 10:ab9330955226 117
mbed_official 10:ab9330955226 118 /** \brief Queues a pbuf into the RX descriptor list
mbed_official 10:ab9330955226 119 *
mbed_official 10:ab9330955226 120 * \param[in] k64f_enet Pointer to the drvier data structure
mbed_official 10:ab9330955226 121 * \param[in] p Pointer to pbuf to queue
mbed_official 10:ab9330955226 122 * \param[in] bidx Index to queue into
mbed_official 10:ab9330955226 123 */
mbed_official 10:ab9330955226 124 static void k64f_rxqueue_pbuf(struct k64f_enetdata *k64f_enet, struct pbuf *p, int bidx)
mbed_official 10:ab9330955226 125 {
mbed_official 10:ab9330955226 126 enet_bd_struct_t *start = (enet_bd_struct_t *)k64f_enet->rx_desc_start_addr;
mbed_official 10:ab9330955226 127 int idx;
mbed_official 10:ab9330955226 128
mbed_official 10:ab9330955226 129 /* Get next free descriptor index */
mbed_official 10:ab9330955226 130 if (bidx == RX_PBUF_AUTO_INDEX)
mbed_official 10:ab9330955226 131 idx = k64f_enet->rx_fill_index;
mbed_official 10:ab9330955226 132 else
mbed_official 10:ab9330955226 133 idx = bidx;
mbed_official 10:ab9330955226 134
mbed_official 10:ab9330955226 135 /* Setup descriptor and clear statuses */
mbed_official 10:ab9330955226 136 enet_hal_init_rxbds(start + idx, (uint8_t*)p->payload, idx == ENET_RX_RING_LEN - 1);
mbed_official 10:ab9330955226 137
mbed_official 10:ab9330955226 138 /* Save pbuf pointer for push to network layer later */
mbed_official 10:ab9330955226 139 k64f_enet->rxb[idx] = p;
mbed_official 10:ab9330955226 140
mbed_official 10:ab9330955226 141 /* Wrap at end of descriptor list */
mbed_official 10:ab9330955226 142 idx = (idx + 1) % ENET_RX_RING_LEN;
mbed_official 10:ab9330955226 143
mbed_official 10:ab9330955226 144 /* Queue descriptor(s) */
mbed_official 10:ab9330955226 145 k64f_enet->rx_free_descs -= 1;
mbed_official 10:ab9330955226 146
mbed_official 10:ab9330955226 147 if (bidx == RX_PBUF_AUTO_INDEX)
mbed_official 10:ab9330955226 148 k64f_enet->rx_fill_index = idx;
mbed_official 10:ab9330955226 149
mbed_official 10:ab9330955226 150 enet_hal_active_rxbd(BOARD_DEBUG_ENET_INSTANCE);
mbed_official 10:ab9330955226 151
mbed_official 10:ab9330955226 152 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 10:ab9330955226 153 ("k64f_rxqueue_pbuf: pbuf packet queued: %p (free desc=%d)\n", p,
mbed_official 10:ab9330955226 154 k64f_enet->rx_free_descs));
mbed_official 10:ab9330955226 155 }
mbed_official 10:ab9330955226 156
mbed_official 10:ab9330955226 157 /** \brief Attempt to allocate and requeue a new pbuf for RX
mbed_official 10:ab9330955226 158 *
mbed_official 10:ab9330955226 159 * \param[in] netif Pointer to the netif structure
mbed_official 10:ab9330955226 160 * \returns number of queued packets
mbed_official 10:ab9330955226 161 */
mbed_official 10:ab9330955226 162 s32_t k64f_rx_queue(struct netif *netif, int idx)
mbed_official 10:ab9330955226 163 {
mbed_official 10:ab9330955226 164 struct k64f_enetdata *k64f_enet = netif->state;
mbed_official 10:ab9330955226 165 enet_dev_if_t *enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
mbed_official 10:ab9330955226 166 struct pbuf *p;
mbed_official 10:ab9330955226 167 int queued = 0;
mbed_official 10:ab9330955226 168
mbed_official 10:ab9330955226 169 /* Attempt to requeue as many packets as possible */
mbed_official 10:ab9330955226 170 while (k64f_enet->rx_free_descs > 0) {
mbed_official 10:ab9330955226 171 /* Allocate a pbuf from the pool. We need to allocate at the
mbed_official 10:ab9330955226 172 maximum size as we don't know the size of the yet to be
mbed_official 10:ab9330955226 173 received packet. */
mbed_official 10:ab9330955226 174 p = pbuf_alloc(PBUF_RAW, enetIfPtr->macCfgPtr->rxBufferSize + RX_BUF_ALIGNMENT, PBUF_RAM);
mbed_official 10:ab9330955226 175 if (p == NULL) {
mbed_official 10:ab9330955226 176 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 10:ab9330955226 177 ("k64_rx_queue: could not allocate RX pbuf (free desc=%d)\n",
mbed_official 10:ab9330955226 178 k64f_enet->rx_free_descs));
mbed_official 10:ab9330955226 179 return queued;
mbed_official 10:ab9330955226 180 }
mbed_official 10:ab9330955226 181 /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F
mbed_official 10:ab9330955226 182 RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing
mbed_official 10:ab9330955226 183 a data structure which is internal to lwIP. This might not prove to be a good idea
mbed_official 10:ab9330955226 184 in the long run, but a better fix would probably involve modifying lwIP itself */
mbed_official 10:ab9330955226 185 p->payload = (void*)ENET_ALIGN((uint32_t)p->payload, RX_BUF_ALIGNMENT);
mbed_official 10:ab9330955226 186
mbed_official 10:ab9330955226 187 /* pbufs allocated from the RAM pool should be non-chained. */
mbed_official 10:ab9330955226 188 LWIP_ASSERT("k64f_rx_queue: pbuf is not contiguous (chained)", pbuf_clen(p) <= 1);
mbed_official 10:ab9330955226 189
mbed_official 10:ab9330955226 190 /* Queue packet */
mbed_official 10:ab9330955226 191 k64f_rxqueue_pbuf(k64f_enet, p, idx);
mbed_official 10:ab9330955226 192 queued++;
mbed_official 10:ab9330955226 193 }
mbed_official 10:ab9330955226 194
mbed_official 10:ab9330955226 195 return queued;
mbed_official 10:ab9330955226 196 }
mbed_official 10:ab9330955226 197
mbed_official 10:ab9330955226 198 /** \brief Sets up the RX descriptor ring buffers.
mbed_official 10:ab9330955226 199 *
mbed_official 10:ab9330955226 200 * This function sets up the descriptor list used for receive packets.
mbed_official 10:ab9330955226 201 *
mbed_official 10:ab9330955226 202 * \param[in] netif Pointer to driver data structure
mbed_official 10:ab9330955226 203 * \returns ERR_MEM if out of memory, ERR_OK otherwise
mbed_official 10:ab9330955226 204 */
mbed_official 10:ab9330955226 205 static err_t k64f_rx_setup(struct netif *netif, enet_rxbd_config_t *rxbdCfg) {
mbed_official 10:ab9330955226 206 struct k64f_enetdata *k64f_enet = netif->state;
mbed_official 10:ab9330955226 207 enet_dev_if_t *enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
mbed_official 10:ab9330955226 208 uint8_t *rxBdPtr;
mbed_official 10:ab9330955226 209 uint32_t rxBufferSizeAligned;
mbed_official 10:ab9330955226 210
mbed_official 10:ab9330955226 211 // Allocate RX descriptors
mbed_official 10:ab9330955226 212 rxBdPtr = (uint8_t *)calloc(1, enet_hal_get_bd_size() * enetIfPtr->macCfgPtr->rxBdNumber + ENET_BD_ALIGNMENT);
mbed_official 10:ab9330955226 213 if(!rxBdPtr)
mbed_official 10:ab9330955226 214 return ERR_MEM;
mbed_official 10:ab9330955226 215 k64f_enet->rx_desc_start_addr = (uint8_t *)ENET_ALIGN((uint32_t)rxBdPtr, ENET_BD_ALIGNMENT);
mbed_official 10:ab9330955226 216 k64f_enet->rx_free_descs = enetIfPtr->macCfgPtr->rxBdNumber;
mbed_official 10:ab9330955226 217 k64f_enet->rx_fill_index = 0;
mbed_official 10:ab9330955226 218
mbed_official 10:ab9330955226 219 rxBufferSizeAligned = ENET_ALIGN(enetIfPtr->macCfgPtr->rxBufferSize, ENET_RX_BUFFER_ALIGNMENT);
mbed_official 10:ab9330955226 220 enetIfPtr->macContextPtr->rxBufferSizeAligned = rxBufferSizeAligned;
mbed_official 10:ab9330955226 221 rxbdCfg->rxBdPtrAlign = k64f_enet->rx_desc_start_addr;
mbed_official 10:ab9330955226 222 rxbdCfg->rxBdNum = enetIfPtr->macCfgPtr->rxBdNumber;
mbed_official 10:ab9330955226 223 rxbdCfg->rxBufferNum = enetIfPtr->macCfgPtr->rxBdNumber;
mbed_official 10:ab9330955226 224
mbed_official 10:ab9330955226 225 k64f_rx_queue(netif, RX_PBUF_AUTO_INDEX);
mbed_official 10:ab9330955226 226 return ERR_OK;
mbed_official 10:ab9330955226 227 }
mbed_official 10:ab9330955226 228
mbed_official 10:ab9330955226 229 /** \brief Sets up the TX descriptor ring buffers.
mbed_official 10:ab9330955226 230 *
mbed_official 10:ab9330955226 231 * This function sets up the descriptor list used for transmit packets.
mbed_official 10:ab9330955226 232 *
mbed_official 10:ab9330955226 233 * \param[in] netif Pointer to driver data structure
mbed_official 10:ab9330955226 234 * \returns ERR_MEM if out of memory, ERR_OK otherwise
mbed_official 10:ab9330955226 235 */
mbed_official 10:ab9330955226 236 static err_t k64f_tx_setup(struct netif *netif, enet_txbd_config_t *txbdCfg) {
mbed_official 10:ab9330955226 237 struct k64f_enetdata *k64f_enet = netif->state;
mbed_official 10:ab9330955226 238 enet_dev_if_t *enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
mbed_official 10:ab9330955226 239 uint8_t *txBdPtr;
mbed_official 10:ab9330955226 240
mbed_official 10:ab9330955226 241 // Allocate TX descriptors
mbed_official 10:ab9330955226 242 txBdPtr = (uint8_t *)calloc(1, enet_hal_get_bd_size() * enetIfPtr->macCfgPtr->txBdNumber + ENET_BD_ALIGNMENT);
mbed_official 10:ab9330955226 243 if(!txBdPtr)
mbed_official 10:ab9330955226 244 return ERR_MEM;
mbed_official 10:ab9330955226 245
mbed_official 10:ab9330955226 246 k64f_enet->tx_desc_start_addr = (uint8_t *)ENET_ALIGN((uint32_t)txBdPtr, ENET_BD_ALIGNMENT);
mbed_official 10:ab9330955226 247 k64f_enet->tx_consume_index = k64f_enet->tx_produce_index = 0;
mbed_official 10:ab9330955226 248
mbed_official 10:ab9330955226 249 txbdCfg->txBdPtrAlign = k64f_enet->tx_desc_start_addr;
mbed_official 10:ab9330955226 250 txbdCfg->txBufferNum = enetIfPtr->macCfgPtr->txBdNumber;
mbed_official 10:ab9330955226 251 txbdCfg->txBufferSizeAlign = ENET_ALIGN(enetIfPtr->maxFrameSize, ENET_TX_BUFFER_ALIGNMENT);
mbed_official 10:ab9330955226 252
mbed_official 10:ab9330955226 253 // Make the TX descriptor ring circular
mbed_official 10:ab9330955226 254 enet_hal_init_txbds(k64f_enet->tx_desc_start_addr + enet_hal_get_bd_size() * (ENET_TX_RING_LEN - 1), 1);
mbed_official 10:ab9330955226 255
mbed_official 10:ab9330955226 256 return ERR_OK;
mbed_official 10:ab9330955226 257 }
mbed_official 10:ab9330955226 258
mbed_official 10:ab9330955226 259 /** \brief Free TX buffers that are complete
mbed_official 10:ab9330955226 260 *
mbed_official 10:ab9330955226 261 * \param[in] k64f_enet Pointer to driver data structure
mbed_official 10:ab9330955226 262 */
mbed_official 10:ab9330955226 263 static void k64f_tx_reclaim(struct k64f_enetdata *k64f_enet)
mbed_official 10:ab9330955226 264 {
mbed_official 10:ab9330955226 265 uint8_t i;
mbed_official 10:ab9330955226 266 volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t *)k64f_enet->tx_desc_start_addr;
mbed_official 10:ab9330955226 267
mbed_official 10:ab9330955226 268 /* Get exclusive access */
mbed_official 10:ab9330955226 269 sys_mutex_lock(&k64f_enet->TXLockMutex);
mbed_official 10:ab9330955226 270
mbed_official 10:ab9330955226 271 // Traverse all descriptors, looking for the ones modified by the uDMA
mbed_official 10:ab9330955226 272 i = k64f_enet->tx_consume_index;
mbed_official 10:ab9330955226 273 while(i != k64f_enet->tx_produce_index) {
mbed_official 10:ab9330955226 274 if (bdPtr[i].controlExtend2 & TX_DESC_UPDATED_MASK) { // descriptor updated by uDMA
mbed_official 10:ab9330955226 275 if (k64f_enet->txb_aligned[i]) {
mbed_official 10:ab9330955226 276 free(k64f_enet->txb_aligned[i]);
mbed_official 10:ab9330955226 277 k64f_enet->txb_aligned[i] = NULL;
mbed_official 10:ab9330955226 278 } else if (k64f_enet->txb[i]) {
mbed_official 10:ab9330955226 279 pbuf_free(k64f_enet->txb[i]);
mbed_official 10:ab9330955226 280 k64f_enet->txb[i] = NULL;
mbed_official 10:ab9330955226 281 }
mbed_official 10:ab9330955226 282 osSemaphoreRelease(k64f_enet->xTXDCountSem.id);
mbed_official 10:ab9330955226 283 bdPtr[i].controlExtend2 &= ~TX_DESC_UPDATED_MASK;
mbed_official 10:ab9330955226 284 }
mbed_official 10:ab9330955226 285 i = (i + 1) % ENET_TX_RING_LEN;
mbed_official 10:ab9330955226 286 }
mbed_official 10:ab9330955226 287 k64f_enet->tx_consume_index = i;
mbed_official 10:ab9330955226 288
mbed_official 10:ab9330955226 289 /* Restore access */
mbed_official 10:ab9330955226 290 sys_mutex_unlock(&k64f_enet->TXLockMutex);
mbed_official 10:ab9330955226 291 }
mbed_official 10:ab9330955226 292
mbed_official 10:ab9330955226 293 /** \brief Low level init of the MAC and PHY.
mbed_official 10:ab9330955226 294 *
mbed_official 10:ab9330955226 295 * \param[in] netif Pointer to LWIP netif structure
mbed_official 10:ab9330955226 296 */
mbed_official 10:ab9330955226 297 static err_t low_level_init(struct netif *netif)
mbed_official 10:ab9330955226 298 {
mbed_official 10:ab9330955226 299 enet_dev_if_t * enetIfPtr;
mbed_official 10:ab9330955226 300 uint32_t device = BOARD_DEBUG_ENET_INSTANCE;
mbed_official 10:ab9330955226 301 enet_rxbd_config_t rxbdCfg;
mbed_official 10:ab9330955226 302 enet_txbd_config_t txbdCfg;
mbed_official 10:ab9330955226 303 enet_phy_speed_t phy_speed;
mbed_official 10:ab9330955226 304 enet_phy_duplex_t phy_duplex;
mbed_official 10:ab9330955226 305
mbed_official 10:ab9330955226 306 k64f_init_eth_hardware();
mbed_official 10:ab9330955226 307
mbed_official 10:ab9330955226 308 /* Initialize device*/
mbed_official 10:ab9330955226 309 enetIfPtr = (enet_dev_if_t *)&enetDevIf[device];
mbed_official 10:ab9330955226 310 enetIfPtr->deviceNumber = device;
mbed_official 10:ab9330955226 311 enetIfPtr->macCfgPtr = &g_enetMacCfg[device];
mbed_official 10:ab9330955226 312 enetIfPtr->phyCfgPtr = &g_enetPhyCfg[device];
mbed_official 10:ab9330955226 313 enetIfPtr->macApiPtr = &g_enetMacApi;
mbed_official 10:ab9330955226 314 enetIfPtr->phyApiPtr = (void *)&g_enetPhyApi;
mbed_official 10:ab9330955226 315 memcpy(enetIfPtr->macCfgPtr->macAddr, (char*)netif->hwaddr, kEnetMacAddrLen);
mbed_official 10:ab9330955226 316
mbed_official 10:ab9330955226 317 /* Allocate buffer for ENET mac context*/
mbed_official 10:ab9330955226 318 enetIfPtr->macContextPtr = (enet_mac_context_t *)calloc(1, sizeof(enet_mac_context_t));
mbed_official 10:ab9330955226 319 if (!enetIfPtr->macContextPtr) {
mbed_official 10:ab9330955226 320 return ERR_BUF;
mbed_official 10:ab9330955226 321 }
mbed_official 10:ab9330955226 322
mbed_official 10:ab9330955226 323 /* Initialize enet buffers*/
mbed_official 10:ab9330955226 324 if(k64f_rx_setup(netif, &rxbdCfg) != ERR_OK) {
mbed_official 10:ab9330955226 325 return ERR_BUF;
mbed_official 10:ab9330955226 326 }
mbed_official 10:ab9330955226 327 /* Initialize enet buffers*/
mbed_official 10:ab9330955226 328 if(k64f_tx_setup(netif, &txbdCfg) != ERR_OK) {
mbed_official 10:ab9330955226 329 return ERR_BUF;
mbed_official 10:ab9330955226 330 }
mbed_official 10:ab9330955226 331 /* Initialize enet module*/
mbed_official 10:ab9330955226 332 if (enet_mac_init(enetIfPtr, &rxbdCfg, &txbdCfg) == kStatus_ENET_Success)
mbed_official 10:ab9330955226 333 {
mbed_official 10:ab9330955226 334 /* Initialize PHY*/
mbed_official 10:ab9330955226 335 if (enetIfPtr->macCfgPtr->isPhyAutoDiscover) {
mbed_official 10:ab9330955226 336 if (((enet_phy_api_t *)(enetIfPtr->phyApiPtr))->phy_auto_discover(enetIfPtr) != kStatus_PHY_Success)
mbed_official 10:ab9330955226 337 return ERR_IF;
mbed_official 10:ab9330955226 338 }
mbed_official 10:ab9330955226 339 if (((enet_phy_api_t *)(enetIfPtr->phyApiPtr))->phy_init(enetIfPtr) != kStatus_PHY_Success)
mbed_official 10:ab9330955226 340 return ERR_IF;
mbed_official 10:ab9330955226 341
mbed_official 10:ab9330955226 342 enetIfPtr->isInitialized = true;
mbed_official 10:ab9330955226 343 }
mbed_official 10:ab9330955226 344 else
mbed_official 10:ab9330955226 345 {
mbed_official 10:ab9330955226 346 // TODOETH: cleanup memory
mbed_official 10:ab9330955226 347 return ERR_IF;
mbed_official 10:ab9330955226 348 }
mbed_official 10:ab9330955226 349
mbed_official 10:ab9330955226 350 /* Get link information from PHY */
mbed_official 10:ab9330955226 351 phy_get_link_speed(enetIfPtr, &phy_speed);
mbed_official 10:ab9330955226 352 phy_get_link_duplex(enetIfPtr, &phy_duplex);
mbed_official 10:ab9330955226 353 BW_ENET_RCR_RMII_10T(enetIfPtr->deviceNumber, phy_speed == kEnetSpeed10M ? kEnetCfgSpeed10M : kEnetCfgSpeed100M);
mbed_official 10:ab9330955226 354 BW_ENET_TCR_FDEN(enetIfPtr->deviceNumber, phy_duplex == kEnetFullDuplex ? kEnetCfgFullDuplex : kEnetCfgHalfDuplex);
mbed_official 10:ab9330955226 355
mbed_official 10:ab9330955226 356 /* Enable Ethernet module*/
mbed_official 10:ab9330955226 357 enet_hal_config_ethernet(device, true, true);
mbed_official 10:ab9330955226 358
mbed_official 10:ab9330955226 359 /* Active Receive buffer descriptor must be done after module enable*/
mbed_official 10:ab9330955226 360 enet_hal_active_rxbd(enetIfPtr->deviceNumber);
mbed_official 10:ab9330955226 361
mbed_official 10:ab9330955226 362 return ERR_OK;
mbed_official 10:ab9330955226 363 }
mbed_official 10:ab9330955226 364
mbed_official 10:ab9330955226 365 /********************************************************************************
mbed_official 10:ab9330955226 366 * LWIP port
mbed_official 10:ab9330955226 367 ********************************************************************************/
mbed_official 10:ab9330955226 368
mbed_official 10:ab9330955226 369 /** \brief Ethernet receive interrupt handler
mbed_official 10:ab9330955226 370 *
mbed_official 10:ab9330955226 371 * This function handles the receive interrupt of K64F.
mbed_official 10:ab9330955226 372 */
mbed_official 10:ab9330955226 373 void enet_mac_rx_isr(void *enetIfPtr)
mbed_official 10:ab9330955226 374 {
mbed_official 10:ab9330955226 375 /* Clear interrupt */
mbed_official 10:ab9330955226 376 enet_hal_clear_interrupt(((enet_dev_if_t *)enetIfPtr)->deviceNumber, kEnetRxFrameInterrupt);
mbed_official 10:ab9330955226 377 sys_sem_signal(&k64f_enetdata.RxReadySem);
mbed_official 10:ab9330955226 378 }
mbed_official 10:ab9330955226 379
mbed_official 10:ab9330955226 380 void enet_mac_tx_isr(void *enetIfPtr)
mbed_official 10:ab9330955226 381 {
mbed_official 10:ab9330955226 382 /*Clear interrupt*/
mbed_official 10:ab9330955226 383 enet_hal_clear_interrupt(((enet_dev_if_t *)enetIfPtr)->deviceNumber, kEnetTxFrameInterrupt);
mbed_official 10:ab9330955226 384 sys_sem_signal(&k64f_enetdata.TxCleanSem);
mbed_official 10:ab9330955226 385 }
mbed_official 10:ab9330955226 386
mbed_official 10:ab9330955226 387 /**
mbed_official 10:ab9330955226 388 * This function is the ethernet packet send function. It calls
mbed_official 10:ab9330955226 389 * etharp_output after checking link status.
mbed_official 10:ab9330955226 390 *
mbed_official 10:ab9330955226 391 * \param[in] netif the lwip network interface structure for this enetif
mbed_official 10:ab9330955226 392 * \param[in] q Pointer to pbug to send
mbed_official 10:ab9330955226 393 * \param[in] ipaddr IP address
mbed_official 10:ab9330955226 394 * \return ERR_OK or error code
mbed_official 10:ab9330955226 395 */
mbed_official 10:ab9330955226 396 err_t k64f_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
mbed_official 10:ab9330955226 397 {
mbed_official 10:ab9330955226 398 /* Only send packet is link is up */
mbed_official 10:ab9330955226 399 if (netif->flags & NETIF_FLAG_LINK_UP)
mbed_official 10:ab9330955226 400 return etharp_output(netif, q, ipaddr);
mbed_official 10:ab9330955226 401
mbed_official 10:ab9330955226 402 return ERR_CONN;
mbed_official 10:ab9330955226 403 }
mbed_official 10:ab9330955226 404
mbed_official 10:ab9330955226 405 /** \brief Allocates a pbuf and returns the data from the incoming packet.
mbed_official 10:ab9330955226 406 *
mbed_official 10:ab9330955226 407 * \param[in] netif the lwip network interface structure
mbed_official 10:ab9330955226 408 * \param[in] idx index of packet to be read
mbed_official 10:ab9330955226 409 * \return a pbuf filled with the received packet (including MAC header)
mbed_official 10:ab9330955226 410 */
mbed_official 10:ab9330955226 411 static struct pbuf *k64f_low_level_input(struct netif *netif, int idx)
mbed_official 10:ab9330955226 412 {
mbed_official 10:ab9330955226 413 struct k64f_enetdata *k64f_enet = netif->state;
mbed_official 10:ab9330955226 414 enet_bd_struct_t * bdPtr = (enet_bd_struct_t*)k64f_enet->rx_desc_start_addr;
mbed_official 10:ab9330955226 415 struct pbuf *p = NULL;
mbed_official 10:ab9330955226 416 u32_t length = 0, orig_length;
mbed_official 10:ab9330955226 417 const u16_t err_mask = kEnetRxBdTrunc | kEnetRxBdCrc | kEnetRxBdNoOctet | kEnetRxBdLengthViolation;
mbed_official 10:ab9330955226 418
mbed_official 10:ab9330955226 419 #ifdef LOCK_RX_THREAD
mbed_official 10:ab9330955226 420 /* Get exclusive access */
mbed_official 10:ab9330955226 421 sys_mutex_lock(&k64f_enet->TXLockMutex);
mbed_official 10:ab9330955226 422 #endif
mbed_official 10:ab9330955226 423
mbed_official 10:ab9330955226 424 /* Determine if a frame has been received */
mbed_official 10:ab9330955226 425 if ((bdPtr[idx].control & err_mask) != 0) {
mbed_official 10:ab9330955226 426 #if LINK_STATS
mbed_official 10:ab9330955226 427 if ((bdPtr[idx].control & kEnetRxBdLengthViolation) != 0)
mbed_official 10:ab9330955226 428 LINK_STATS_INC(link.lenerr);
mbed_official 10:ab9330955226 429 else
mbed_official 10:ab9330955226 430 LINK_STATS_INC(link.chkerr);
mbed_official 10:ab9330955226 431 #endif
mbed_official 10:ab9330955226 432 LINK_STATS_INC(link.drop);
mbed_official 10:ab9330955226 433
mbed_official 10:ab9330955226 434 /* Re-queue the same buffer */
mbed_official 10:ab9330955226 435 k64f_enet->rx_free_descs++;
mbed_official 10:ab9330955226 436 p = k64f_enet->rxb[idx];
mbed_official 10:ab9330955226 437 k64f_enet->rxb[idx] = NULL;
mbed_official 10:ab9330955226 438 k64f_rxqueue_pbuf(k64f_enet, p, idx);
mbed_official 10:ab9330955226 439 p = NULL;
mbed_official 10:ab9330955226 440 } else {
mbed_official 10:ab9330955226 441 /* A packet is waiting, get length */
mbed_official 10:ab9330955226 442 length = enet_hal_get_bd_length(bdPtr + idx);
mbed_official 10:ab9330955226 443
mbed_official 10:ab9330955226 444 /* Zero-copy */
mbed_official 10:ab9330955226 445 p = k64f_enet->rxb[idx];
mbed_official 10:ab9330955226 446 orig_length = p->len;
mbed_official 10:ab9330955226 447 p->len = (u16_t) length;
mbed_official 10:ab9330955226 448
mbed_official 10:ab9330955226 449 /* Free pbuf from descriptor */
mbed_official 10:ab9330955226 450 k64f_enet->rxb[idx] = NULL;
mbed_official 10:ab9330955226 451 k64f_enet->rx_free_descs++;
mbed_official 10:ab9330955226 452
mbed_official 10:ab9330955226 453 /* Attempt to queue new buffer */
mbed_official 10:ab9330955226 454 if (k64f_rx_queue(netif, idx) == 0) {
mbed_official 10:ab9330955226 455 /* Drop frame (out of memory) */
mbed_official 10:ab9330955226 456 LINK_STATS_INC(link.drop);
mbed_official 10:ab9330955226 457
mbed_official 10:ab9330955226 458 /* Re-queue the same buffer */
mbed_official 10:ab9330955226 459 p->len = orig_length;
mbed_official 10:ab9330955226 460 k64f_rxqueue_pbuf(k64f_enet, p, idx);
mbed_official 10:ab9330955226 461
mbed_official 10:ab9330955226 462 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 10:ab9330955226 463 ("k64f_low_level_input: Packet index %d dropped for OOM\n",
mbed_official 10:ab9330955226 464 idx));
mbed_official 10:ab9330955226 465 #ifdef LOCK_RX_THREAD
mbed_official 10:ab9330955226 466 sys_mutex_unlock(&k64f_enet->TXLockMutex);
mbed_official 10:ab9330955226 467 #endif
mbed_official 10:ab9330955226 468
mbed_official 10:ab9330955226 469 return NULL;
mbed_official 10:ab9330955226 470 }
mbed_official 10:ab9330955226 471
mbed_official 10:ab9330955226 472 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 10:ab9330955226 473 ("k64f_low_level_input: Packet received: %p, size %d (index=%d)\n",
mbed_official 10:ab9330955226 474 p, length, idx));
mbed_official 10:ab9330955226 475
mbed_official 10:ab9330955226 476 /* Save size */
mbed_official 10:ab9330955226 477 p->tot_len = (u16_t) length;
mbed_official 10:ab9330955226 478 LINK_STATS_INC(link.recv);
mbed_official 10:ab9330955226 479 }
mbed_official 10:ab9330955226 480
mbed_official 10:ab9330955226 481 #ifdef LOCK_RX_THREAD
mbed_official 10:ab9330955226 482 sys_mutex_unlock(&k64f_enet->TXLockMutex);
mbed_official 10:ab9330955226 483 #endif
mbed_official 10:ab9330955226 484
mbed_official 10:ab9330955226 485 return p;
mbed_official 10:ab9330955226 486 }
mbed_official 10:ab9330955226 487
mbed_official 10:ab9330955226 488 /** \brief Attempt to read a packet from the EMAC interface.
mbed_official 10:ab9330955226 489 *
mbed_official 10:ab9330955226 490 * \param[in] netif the lwip network interface structure
mbed_official 10:ab9330955226 491 * \param[in] idx index of packet to be read
mbed_official 10:ab9330955226 492 */
mbed_official 10:ab9330955226 493 void k64f_enetif_input(struct netif *netif, int idx)
mbed_official 10:ab9330955226 494 {
mbed_official 10:ab9330955226 495 struct eth_hdr *ethhdr;
mbed_official 10:ab9330955226 496 struct pbuf *p;
mbed_official 10:ab9330955226 497
mbed_official 10:ab9330955226 498 /* move received packet into a new pbuf */
mbed_official 10:ab9330955226 499 p = k64f_low_level_input(netif, idx);
mbed_official 10:ab9330955226 500 if (p == NULL)
mbed_official 10:ab9330955226 501 return;
mbed_official 10:ab9330955226 502
mbed_official 10:ab9330955226 503 /* points to packet payload, which starts with an Ethernet header */
mbed_official 10:ab9330955226 504 ethhdr = (struct eth_hdr*)p->payload;
mbed_official 10:ab9330955226 505
mbed_official 10:ab9330955226 506 switch (htons(ethhdr->type)) {
mbed_official 10:ab9330955226 507 case ETHTYPE_IP:
mbed_official 10:ab9330955226 508 case ETHTYPE_ARP:
mbed_official 10:ab9330955226 509 #if PPPOE_SUPPORT
mbed_official 10:ab9330955226 510 case ETHTYPE_PPPOEDISC:
mbed_official 10:ab9330955226 511 case ETHTYPE_PPPOE:
mbed_official 10:ab9330955226 512 #endif /* PPPOE_SUPPORT */
mbed_official 10:ab9330955226 513 /* full packet send to tcpip_thread to process */
mbed_official 10:ab9330955226 514 if (netif->input(p, netif) != ERR_OK) {
mbed_official 10:ab9330955226 515 LWIP_DEBUGF(NETIF_DEBUG, ("k64f_enetif_input: IP input error\n"));
mbed_official 10:ab9330955226 516 /* Free buffer */
mbed_official 10:ab9330955226 517 pbuf_free(p);
mbed_official 10:ab9330955226 518 }
mbed_official 10:ab9330955226 519 break;
mbed_official 10:ab9330955226 520
mbed_official 10:ab9330955226 521 default:
mbed_official 10:ab9330955226 522 /* Return buffer */
mbed_official 10:ab9330955226 523 pbuf_free(p);
mbed_official 10:ab9330955226 524 break;
mbed_official 10:ab9330955226 525 }
mbed_official 10:ab9330955226 526 }
mbed_official 10:ab9330955226 527
mbed_official 10:ab9330955226 528 /** \brief Packet reception task
mbed_official 10:ab9330955226 529 *
mbed_official 10:ab9330955226 530 * This task is called when a packet is received. It will
mbed_official 10:ab9330955226 531 * pass the packet to the LWIP core.
mbed_official 10:ab9330955226 532 *
mbed_official 10:ab9330955226 533 * \param[in] pvParameters pointer to the interface data
mbed_official 10:ab9330955226 534 */
mbed_official 10:ab9330955226 535 static void packet_rx(void* pvParameters) {
mbed_official 10:ab9330955226 536 struct k64f_enetdata *k64f_enet = pvParameters;
mbed_official 10:ab9330955226 537 volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t*)k64f_enet->rx_desc_start_addr;
mbed_official 10:ab9330955226 538 int idx = 0;
mbed_official 10:ab9330955226 539
mbed_official 10:ab9330955226 540 while (1) {
mbed_official 10:ab9330955226 541 /* Wait for receive task to wakeup */
mbed_official 10:ab9330955226 542 sys_arch_sem_wait(&k64f_enet->RxReadySem, 0);
mbed_official 10:ab9330955226 543
mbed_official 10:ab9330955226 544 if ((bdPtr[idx].control & kEnetRxBdEmpty) == 0) {
mbed_official 10:ab9330955226 545 k64f_enetif_input(k64f_enet->netif, idx);
mbed_official 10:ab9330955226 546 idx = (idx + 1) % ENET_RX_RING_LEN;
mbed_official 10:ab9330955226 547 }
mbed_official 10:ab9330955226 548 }
mbed_official 10:ab9330955226 549 }
mbed_official 10:ab9330955226 550
mbed_official 10:ab9330955226 551 /** \brief Transmit cleanup task
mbed_official 10:ab9330955226 552 *
mbed_official 10:ab9330955226 553 * This task is called when a transmit interrupt occurs and
mbed_official 10:ab9330955226 554 * reclaims the pbuf and descriptor used for the packet once
mbed_official 10:ab9330955226 555 * the packet has been transferred.
mbed_official 10:ab9330955226 556 *
mbed_official 10:ab9330955226 557 * \param[in] pvParameters pointer to the interface data
mbed_official 10:ab9330955226 558 */
mbed_official 10:ab9330955226 559 static void packet_tx(void* pvParameters) {
mbed_official 10:ab9330955226 560 struct k64f_enetdata *k64f_enet = pvParameters;
mbed_official 10:ab9330955226 561
mbed_official 10:ab9330955226 562 while (1) {
mbed_official 10:ab9330955226 563 /* Wait for transmit cleanup task to wakeup */
mbed_official 10:ab9330955226 564 sys_arch_sem_wait(&k64f_enet->TxCleanSem, 0);
mbed_official 10:ab9330955226 565 // TODOETH: handle TX underrun?
mbed_official 10:ab9330955226 566 k64f_tx_reclaim(k64f_enet);
mbed_official 10:ab9330955226 567 }
mbed_official 10:ab9330955226 568 }
mbed_official 10:ab9330955226 569
mbed_official 10:ab9330955226 570 /** \brief Polls if an available TX descriptor is ready. Can be used to
mbed_official 10:ab9330955226 571 * determine if the low level transmit function will block.
mbed_official 10:ab9330955226 572 *
mbed_official 10:ab9330955226 573 * \param[in] netif the lwip network interface structure
mbed_official 10:ab9330955226 574 * \return 0 if no descriptors are read, or >0
mbed_official 10:ab9330955226 575 */
mbed_official 10:ab9330955226 576 s32_t k64f_tx_ready(struct netif *netif)
mbed_official 10:ab9330955226 577 {
mbed_official 10:ab9330955226 578 struct k64f_enetdata *k64f_enet = netif->state;
mbed_official 10:ab9330955226 579 s32_t fb;
mbed_official 10:ab9330955226 580 u32_t idx, cidx;
mbed_official 10:ab9330955226 581
mbed_official 10:ab9330955226 582 cidx = k64f_enet->tx_consume_index;
mbed_official 10:ab9330955226 583 idx = k64f_enet->tx_produce_index;
mbed_official 10:ab9330955226 584
mbed_official 10:ab9330955226 585 /* Determine number of free buffers */
mbed_official 10:ab9330955226 586 if (idx == cidx)
mbed_official 10:ab9330955226 587 fb = ENET_TX_RING_LEN;
mbed_official 10:ab9330955226 588 else if (cidx > idx)
mbed_official 10:ab9330955226 589 fb = (ENET_TX_RING_LEN - 1) -
mbed_official 10:ab9330955226 590 ((idx + ENET_TX_RING_LEN) - cidx);
mbed_official 10:ab9330955226 591 else
mbed_official 10:ab9330955226 592 fb = (ENET_TX_RING_LEN - 1) - (cidx - idx);
mbed_official 10:ab9330955226 593
mbed_official 10:ab9330955226 594 return fb;
mbed_official 10:ab9330955226 595 }
mbed_official 10:ab9330955226 596
mbed_official 10:ab9330955226 597 /*FUNCTION****************************************************************
mbed_official 10:ab9330955226 598 *
mbed_official 10:ab9330955226 599 * Function Name: enet_hal_update_txbds
mbed_official 10:ab9330955226 600 * Description: Update ENET transmit buffer descriptors.
mbed_official 10:ab9330955226 601 *END*********************************************************************/
mbed_official 10:ab9330955226 602 void k64f_update_txbds(struct k64f_enetdata *k64f_enet, int idx, uint8_t *buffer, uint16_t length, bool isLast)
mbed_official 10:ab9330955226 603 {
mbed_official 10:ab9330955226 604 volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t *)(k64f_enet->tx_desc_start_addr + idx * enet_hal_get_bd_size());
mbed_official 10:ab9330955226 605
mbed_official 10:ab9330955226 606 bdPtr->length = HTONS(length); /* Set data length*/
mbed_official 10:ab9330955226 607 bdPtr->buffer = (uint8_t *)HTONL((uint32_t)buffer); /* Set data buffer*/
mbed_official 10:ab9330955226 608 if (isLast)
mbed_official 10:ab9330955226 609 bdPtr->control |= kEnetTxBdLast;
mbed_official 10:ab9330955226 610 else
mbed_official 10:ab9330955226 611 bdPtr->control &= ~kEnetTxBdLast;
mbed_official 10:ab9330955226 612 bdPtr->controlExtend1 |= kEnetTxBdTxInterrupt;
mbed_official 10:ab9330955226 613 bdPtr->controlExtend2 &= ~TX_DESC_UPDATED_MASK; // descriptor not updated by DMA
mbed_official 10:ab9330955226 614 bdPtr->control |= kEnetTxBdTransmitCrc | kEnetTxBdReady;
mbed_official 10:ab9330955226 615 }
mbed_official 10:ab9330955226 616
mbed_official 10:ab9330955226 617 /** \brief Low level output of a packet. Never call this from an
mbed_official 10:ab9330955226 618 * interrupt context, as it may block until TX descriptors
mbed_official 10:ab9330955226 619 * become available.
mbed_official 10:ab9330955226 620 *
mbed_official 10:ab9330955226 621 * \param[in] netif the lwip network interface structure for this netif
mbed_official 10:ab9330955226 622 * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type)
mbed_official 10:ab9330955226 623 * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent
mbed_official 10:ab9330955226 624 */
mbed_official 10:ab9330955226 625 static err_t k64f_low_level_output(struct netif *netif, struct pbuf *p)
mbed_official 10:ab9330955226 626 {
mbed_official 10:ab9330955226 627 struct k64f_enetdata *k64f_enet = netif->state;
mbed_official 10:ab9330955226 628 struct pbuf *q;
mbed_official 10:ab9330955226 629 u32_t idx;
mbed_official 10:ab9330955226 630 s32_t dn;
mbed_official 10:ab9330955226 631 uint8_t *psend = NULL, *dst;
mbed_official 10:ab9330955226 632
mbed_official 10:ab9330955226 633 /* Get free TX buffer index */
mbed_official 10:ab9330955226 634 idx = k64f_enet->tx_produce_index;
mbed_official 10:ab9330955226 635
mbed_official 10:ab9330955226 636 /* Check the pbuf chain for payloads that are not 8-byte aligned.
mbed_official 10:ab9330955226 637 If found, a new properly aligned buffer needs to be allocated
mbed_official 10:ab9330955226 638 and the data copied there */
mbed_official 10:ab9330955226 639 for (q = p; q != NULL; q = q->next)
mbed_official 10:ab9330955226 640 if (((u32_t)q->payload & (TX_BUF_ALIGNMENT - 1)) != 0)
mbed_official 10:ab9330955226 641 break;
mbed_official 10:ab9330955226 642 if (q != NULL) {
mbed_official 10:ab9330955226 643 // Allocate properly aligned buffer
mbed_official 10:ab9330955226 644 psend = (uint8_t*)malloc(p->tot_len);
mbed_official 10:ab9330955226 645 if (NULL == psend)
mbed_official 10:ab9330955226 646 return ERR_MEM;
mbed_official 10:ab9330955226 647 LWIP_ASSERT("k64f_low_level_output: buffer not properly aligned", ((u32_t)psend & (TX_BUF_ALIGNMENT - 1)) == 0);
mbed_official 10:ab9330955226 648 for (q = p, dst = psend; q != NULL; q = q->next) {
mbed_official 10:ab9330955226 649 MEMCPY(dst, q->payload, q->len);
mbed_official 10:ab9330955226 650 dst += q->len;
mbed_official 10:ab9330955226 651 }
mbed_official 10:ab9330955226 652 k64f_enet->txb_aligned[idx] = psend;
mbed_official 10:ab9330955226 653 dn = 1;
mbed_official 10:ab9330955226 654 } else {
mbed_official 10:ab9330955226 655 k64f_enet->txb_aligned[idx] = NULL;
mbed_official 10:ab9330955226 656 dn = (s32_t) pbuf_clen(p);
mbed_official 10:ab9330955226 657 pbuf_ref(p);
mbed_official 10:ab9330955226 658 }
mbed_official 10:ab9330955226 659
mbed_official 10:ab9330955226 660 /* Wait until enough descriptors are available for the transfer. */
mbed_official 10:ab9330955226 661 /* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */
mbed_official 10:ab9330955226 662 while (dn > k64f_tx_ready(netif))
mbed_official 10:ab9330955226 663 osSemaphoreWait(k64f_enet->xTXDCountSem.id, osWaitForever);
mbed_official 10:ab9330955226 664
mbed_official 10:ab9330955226 665 /* Get exclusive access */
mbed_official 10:ab9330955226 666 sys_mutex_lock(&k64f_enet->TXLockMutex);
mbed_official 10:ab9330955226 667
mbed_official 10:ab9330955226 668 /* Setup transfers */
mbed_official 10:ab9330955226 669 q = p;
mbed_official 10:ab9330955226 670 while (dn > 0) {
mbed_official 10:ab9330955226 671 dn--;
mbed_official 10:ab9330955226 672 if (psend != NULL) {
mbed_official 10:ab9330955226 673 k64f_update_txbds(k64f_enet, idx, psend, p->tot_len, 1);
mbed_official 10:ab9330955226 674 k64f_enet->txb[idx] = NULL;
mbed_official 10:ab9330955226 675
mbed_official 10:ab9330955226 676 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 10:ab9330955226 677 ("k64f_low_level_output: aligned packet(%p) sent"
mbed_official 10:ab9330955226 678 " size = %d (index=%d)\n", psend, p->tot_len, idx));
mbed_official 10:ab9330955226 679 } else {
mbed_official 10:ab9330955226 680 LWIP_ASSERT("k64f_low_level_output: buffer not properly aligned", ((u32_t)q->payload & 0x07) == 0);
mbed_official 10:ab9330955226 681
mbed_official 10:ab9330955226 682 /* Only save pointer to free on last descriptor */
mbed_official 10:ab9330955226 683 if (dn == 0) {
mbed_official 10:ab9330955226 684 /* Save size of packet and signal it's ready */
mbed_official 10:ab9330955226 685 k64f_update_txbds(k64f_enet, idx, q->payload, q->len, 1);
mbed_official 10:ab9330955226 686 k64f_enet->txb[idx] = p;
mbed_official 10:ab9330955226 687 }
mbed_official 10:ab9330955226 688 else {
mbed_official 10:ab9330955226 689 /* Save size of packet, descriptor is not last */
mbed_official 10:ab9330955226 690 k64f_update_txbds(k64f_enet, idx, q->payload, q->len, 0);
mbed_official 10:ab9330955226 691 k64f_enet->txb[idx] = NULL;
mbed_official 10:ab9330955226 692 }
mbed_official 10:ab9330955226 693
mbed_official 10:ab9330955226 694 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
mbed_official 10:ab9330955226 695 ("k64f_low_level_output: pbuf packet(%p) sent, chain#=%d,"
mbed_official 10:ab9330955226 696 " size = %d (index=%d)\n", q->payload, dn, q->len, idx));
mbed_official 10:ab9330955226 697 }
mbed_official 10:ab9330955226 698
mbed_official 10:ab9330955226 699 q = q->next;
mbed_official 10:ab9330955226 700
mbed_official 10:ab9330955226 701 idx = (idx + 1) % ENET_TX_RING_LEN;
mbed_official 10:ab9330955226 702 }
mbed_official 10:ab9330955226 703
mbed_official 10:ab9330955226 704 k64f_enet->tx_produce_index = idx;
mbed_official 10:ab9330955226 705 enet_hal_active_txbd(BOARD_DEBUG_ENET_INSTANCE);
mbed_official 10:ab9330955226 706 LINK_STATS_INC(link.xmit);
mbed_official 10:ab9330955226 707
mbed_official 10:ab9330955226 708 /* Restore access */
mbed_official 10:ab9330955226 709 sys_mutex_unlock(&k64f_enet->TXLockMutex);
mbed_official 10:ab9330955226 710
mbed_official 10:ab9330955226 711 return ERR_OK;
mbed_official 10:ab9330955226 712 }
mbed_official 10:ab9330955226 713
mbed_official 10:ab9330955226 714 /*******************************************************************************
mbed_official 10:ab9330955226 715 * PHY task: monitor link
mbed_official 10:ab9330955226 716 *******************************************************************************/
mbed_official 10:ab9330955226 717
mbed_official 10:ab9330955226 718 #define PHY_TASK_PERIOD_MS 200
mbed_official 10:ab9330955226 719 #define STATE_UNKNOWN (-1)
mbed_official 10:ab9330955226 720
mbed_official 10:ab9330955226 721 typedef struct {
mbed_official 10:ab9330955226 722 int connected;
mbed_official 10:ab9330955226 723 enet_phy_speed_t speed;
mbed_official 10:ab9330955226 724 enet_phy_duplex_t duplex;
mbed_official 10:ab9330955226 725 } PHY_STATE;
mbed_official 10:ab9330955226 726
mbed_official 10:ab9330955226 727 static void k64f_phy_task(void *data) {
mbed_official 10:ab9330955226 728 struct netif *netif = (struct netif*)data;
mbed_official 10:ab9330955226 729 bool connection_status;
mbed_official 10:ab9330955226 730 enet_dev_if_t * enetIfPtr = (enet_dev_if_t*)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
mbed_official 10:ab9330955226 731 PHY_STATE crt_state = {STATE_UNKNOWN, (enet_phy_speed_t)STATE_UNKNOWN, (enet_phy_duplex_t)STATE_UNKNOWN};
mbed_official 10:ab9330955226 732 PHY_STATE prev_state;
mbed_official 10:ab9330955226 733
mbed_official 10:ab9330955226 734 prev_state = crt_state;
mbed_official 10:ab9330955226 735 while (true) {
mbed_official 10:ab9330955226 736 // Get current status
mbed_official 10:ab9330955226 737 phy_get_link_status(enetIfPtr, &connection_status);
mbed_official 10:ab9330955226 738 crt_state.connected = connection_status ? 1 : 0;
mbed_official 10:ab9330955226 739 phy_get_link_speed(enetIfPtr, &crt_state.speed);
mbed_official 10:ab9330955226 740 phy_get_link_duplex(enetIfPtr, &crt_state.duplex);
mbed_official 10:ab9330955226 741
mbed_official 10:ab9330955226 742 // Compare with previous state
mbed_official 10:ab9330955226 743 if (crt_state.connected != prev_state.connected) {
mbed_official 10:ab9330955226 744 if (crt_state.connected)
mbed_official 10:ab9330955226 745 tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
mbed_official 10:ab9330955226 746 else
mbed_official 10:ab9330955226 747 tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
mbed_official 10:ab9330955226 748 }
mbed_official 10:ab9330955226 749
mbed_official 10:ab9330955226 750 if (crt_state.speed != prev_state.speed)
mbed_official 10:ab9330955226 751 BW_ENET_RCR_RMII_10T(enetIfPtr->deviceNumber, crt_state.speed == kEnetSpeed10M ? kEnetCfgSpeed10M : kEnetCfgSpeed100M);
mbed_official 10:ab9330955226 752
mbed_official 10:ab9330955226 753 // TODO: duplex change requires disable/enable of Ethernet interface, to be implemented
mbed_official 10:ab9330955226 754
mbed_official 10:ab9330955226 755 prev_state = crt_state;
mbed_official 10:ab9330955226 756 osDelay(PHY_TASK_PERIOD_MS);
mbed_official 10:ab9330955226 757 }
mbed_official 10:ab9330955226 758 }
mbed_official 10:ab9330955226 759
mbed_official 10:ab9330955226 760 /**
mbed_official 10:ab9330955226 761 * Should be called at the beginning of the program to set up the
mbed_official 10:ab9330955226 762 * network interface.
mbed_official 10:ab9330955226 763 *
mbed_official 10:ab9330955226 764 * This function should be passed as a parameter to netif_add().
mbed_official 10:ab9330955226 765 *
mbed_official 10:ab9330955226 766 * @param[in] netif the lwip network interface structure for this netif
mbed_official 10:ab9330955226 767 * @return ERR_OK if the loopif is initialized
mbed_official 10:ab9330955226 768 * ERR_MEM if private data couldn't be allocated
mbed_official 10:ab9330955226 769 * any other err_t on error
mbed_official 10:ab9330955226 770 */
mbed_official 10:ab9330955226 771 err_t eth_arch_enetif_init(struct netif *netif)
mbed_official 10:ab9330955226 772 {
mbed_official 10:ab9330955226 773 err_t err;
mbed_official 10:ab9330955226 774
mbed_official 10:ab9330955226 775 LWIP_ASSERT("netif != NULL", (netif != NULL));
mbed_official 10:ab9330955226 776
mbed_official 10:ab9330955226 777 k64f_enetdata.netif = netif;
mbed_official 10:ab9330955226 778
mbed_official 10:ab9330955226 779 /* set MAC hardware address */
mbed_official 10:ab9330955226 780 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
mbed_official 10:ab9330955226 781 netif->hwaddr[0] = MBED_MAC_ADDR_0;
mbed_official 10:ab9330955226 782 netif->hwaddr[1] = MBED_MAC_ADDR_1;
mbed_official 10:ab9330955226 783 netif->hwaddr[2] = MBED_MAC_ADDR_2;
mbed_official 10:ab9330955226 784 netif->hwaddr[3] = MBED_MAC_ADDR_3;
mbed_official 10:ab9330955226 785 netif->hwaddr[4] = MBED_MAC_ADDR_4;
mbed_official 10:ab9330955226 786 netif->hwaddr[5] = MBED_MAC_ADDR_5;
mbed_official 10:ab9330955226 787 #else
mbed_official 10:ab9330955226 788 mbed_mac_address((char *)netif->hwaddr);
mbed_official 10:ab9330955226 789 #endif
mbed_official 10:ab9330955226 790 netif->hwaddr_len = ETHARP_HWADDR_LEN;
mbed_official 10:ab9330955226 791
mbed_official 10:ab9330955226 792 /* maximum transfer unit */
mbed_official 10:ab9330955226 793 netif->mtu = 1500;
mbed_official 10:ab9330955226 794
mbed_official 10:ab9330955226 795 /* device capabilities */
mbed_official 10:ab9330955226 796 // TODOETH: check if the flags are correct below
mbed_official 10:ab9330955226 797 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
mbed_official 10:ab9330955226 798
mbed_official 10:ab9330955226 799 /* Initialize the hardware */
mbed_official 10:ab9330955226 800 netif->state = &k64f_enetdata;
mbed_official 10:ab9330955226 801 err = low_level_init(netif);
mbed_official 10:ab9330955226 802 if (err != ERR_OK)
mbed_official 10:ab9330955226 803 return err;
mbed_official 10:ab9330955226 804
mbed_official 10:ab9330955226 805 #if LWIP_NETIF_HOSTNAME
mbed_official 10:ab9330955226 806 /* Initialize interface hostname */
mbed_official 10:ab9330955226 807 netif->hostname = "lwipk64f";
mbed_official 10:ab9330955226 808 #endif /* LWIP_NETIF_HOSTNAME */
mbed_official 10:ab9330955226 809
mbed_official 10:ab9330955226 810 netif->name[0] = 'e';
mbed_official 10:ab9330955226 811 netif->name[1] = 'n';
mbed_official 10:ab9330955226 812
mbed_official 10:ab9330955226 813 netif->output = k64f_etharp_output;
mbed_official 10:ab9330955226 814 netif->linkoutput = k64f_low_level_output;
mbed_official 10:ab9330955226 815
mbed_official 10:ab9330955226 816 /* CMSIS-RTOS, start tasks */
mbed_official 10:ab9330955226 817 #ifdef CMSIS_OS_RTX
mbed_official 10:ab9330955226 818 memset(k64f_enetdata.xTXDCountSem.data, 0, sizeof(k64f_enetdata.xTXDCountSem.data));
mbed_official 10:ab9330955226 819 k64f_enetdata.xTXDCountSem.def.semaphore = k64f_enetdata.xTXDCountSem.data;
mbed_official 10:ab9330955226 820 #endif
mbed_official 10:ab9330955226 821 k64f_enetdata.xTXDCountSem.id = osSemaphoreCreate(&k64f_enetdata.xTXDCountSem.def, ENET_TX_RING_LEN);
mbed_official 10:ab9330955226 822
mbed_official 10:ab9330955226 823 LWIP_ASSERT("xTXDCountSem creation error", (k64f_enetdata.xTXDCountSem.id != NULL));
mbed_official 10:ab9330955226 824
mbed_official 10:ab9330955226 825 err = sys_mutex_new(&k64f_enetdata.TXLockMutex);
mbed_official 10:ab9330955226 826 LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK));
mbed_official 10:ab9330955226 827
mbed_official 10:ab9330955226 828 /* Packet receive task */
mbed_official 10:ab9330955226 829 err = sys_sem_new(&k64f_enetdata.RxReadySem, 0);
mbed_official 10:ab9330955226 830 LWIP_ASSERT("RxReadySem creation error", (err == ERR_OK));
mbed_official 10:ab9330955226 831 sys_thread_new("receive_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY);
mbed_official 10:ab9330955226 832
mbed_official 10:ab9330955226 833 /* Transmit cleanup task */
mbed_official 10:ab9330955226 834 err = sys_sem_new(&k64f_enetdata.TxCleanSem, 0);
mbed_official 10:ab9330955226 835 LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK));
mbed_official 10:ab9330955226 836 sys_thread_new("txclean_thread", packet_tx, netif->state, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY);
mbed_official 10:ab9330955226 837
mbed_official 10:ab9330955226 838 /* PHY monitoring task */
mbed_official 10:ab9330955226 839 sys_thread_new("phy_thread", k64f_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY);
mbed_official 10:ab9330955226 840
mbed_official 10:ab9330955226 841 /* Allow the PHY task to detect the initial link state and set up the proper flags */
mbed_official 10:ab9330955226 842 osDelay(10);
mbed_official 10:ab9330955226 843
mbed_official 10:ab9330955226 844 return ERR_OK;
mbed_official 10:ab9330955226 845 }
mbed_official 10:ab9330955226 846
mbed_official 10:ab9330955226 847 void eth_arch_enable_interrupts(void) {
mbed_official 10:ab9330955226 848 enet_hal_config_interrupt(BOARD_DEBUG_ENET_INSTANCE, (kEnetTxFrameInterrupt | kEnetRxFrameInterrupt), true);
mbed_official 10:ab9330955226 849 interrupt_enable(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetRxfInt]]);
mbed_official 10:ab9330955226 850 interrupt_enable(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetTxfInt]]);
mbed_official 10:ab9330955226 851 }
mbed_official 10:ab9330955226 852
mbed_official 10:ab9330955226 853 void eth_arch_disable_interrupts(void) {
mbed_official 10:ab9330955226 854 interrupt_disable(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetRxfInt]]);
mbed_official 10:ab9330955226 855 interrupt_disable(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetTxfInt]]);
mbed_official 10:ab9330955226 856 }
mbed_official 10:ab9330955226 857
mbed_official 10:ab9330955226 858 /**
mbed_official 10:ab9330955226 859 * @}
mbed_official 10:ab9330955226 860 */
mbed_official 10:ab9330955226 861
mbed_official 10:ab9330955226 862 /* --------------------------------- End Of File ------------------------------ */
mbed_official 10:ab9330955226 863