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:
Mon Jun 15 07:15:45 2015 +0100
Revision:
27:fde88aaaea28
Parent:
21:10cdd9fe0509
Child:
31:da93f0f73711
Synchronized with git revision 77a973c00943e35b25c7aa34590de6e06de2ccef

Full URL: https://github.com/mbedmicro/mbed/commit/77a973c00943e35b25c7aa34590de6e06de2ccef/

Update k64f_emac.c

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