fdsf

Dependents:   sisk_proj_stat MQTT Hello_FXOS8700Q WireFSHandControl ... more

Committer:
grzemich
Date:
Wed Dec 07 23:47:50 2016 +0000
Revision:
0:d7bd7384a37c
dgd

Who changed what in which revision?

UserRevisionLine numberNew contents of line
grzemich 0:d7bd7384a37c 1 #include "lwip/opt.h"
grzemich 0:d7bd7384a37c 2 #include "lwip/sys.h"
grzemich 0:d7bd7384a37c 3 #include "lwip/def.h"
grzemich 0:d7bd7384a37c 4 #include "lwip/mem.h"
grzemich 0:d7bd7384a37c 5 #include "lwip/pbuf.h"
grzemich 0:d7bd7384a37c 6 #include "lwip/stats.h"
grzemich 0:d7bd7384a37c 7 #include "lwip/snmp.h"
grzemich 0:d7bd7384a37c 8 #include "lwip/tcpip.h"
grzemich 0:d7bd7384a37c 9 #include "netif/etharp.h"
grzemich 0:d7bd7384a37c 10 #include "netif/ppp_oe.h"
grzemich 0:d7bd7384a37c 11
grzemich 0:d7bd7384a37c 12 #include "eth_arch.h"
grzemich 0:d7bd7384a37c 13 #include "sys_arch.h"
grzemich 0:d7bd7384a37c 14
grzemich 0:d7bd7384a37c 15 #include "fsl_phy.h"
grzemich 0:d7bd7384a37c 16 #include "k64f_emac_config.h"
grzemich 0:d7bd7384a37c 17 #include <ctype.h>
grzemich 0:d7bd7384a37c 18 #include <stdio.h>
grzemich 0:d7bd7384a37c 19 #include <string.h>
grzemich 0:d7bd7384a37c 20 #include <stdlib.h>
grzemich 0:d7bd7384a37c 21
grzemich 0:d7bd7384a37c 22 #include "mbed_interface.h"
grzemich 0:d7bd7384a37c 23
grzemich 0:d7bd7384a37c 24 enet_handle_t g_handle;
grzemich 0:d7bd7384a37c 25 // TX Buffer descriptors
grzemich 0:d7bd7384a37c 26 uint8_t *tx_desc_start_addr;
grzemich 0:d7bd7384a37c 27 // RX Buffer descriptors
grzemich 0:d7bd7384a37c 28 uint8_t *rx_desc_start_addr;
grzemich 0:d7bd7384a37c 29 // RX packet buffer pointers
grzemich 0:d7bd7384a37c 30 struct pbuf *rx_buff[ENET_RX_RING_LEN];
grzemich 0:d7bd7384a37c 31 // TX packet buffer pointers
grzemich 0:d7bd7384a37c 32 struct pbuf *tx_buff[ENET_RX_RING_LEN];
grzemich 0:d7bd7384a37c 33 // RX packet payload pointers
grzemich 0:d7bd7384a37c 34 uint32_t *rx_ptr[ENET_RX_RING_LEN];
grzemich 0:d7bd7384a37c 35
grzemich 0:d7bd7384a37c 36 /********************************************************************************
grzemich 0:d7bd7384a37c 37 * Internal data
grzemich 0:d7bd7384a37c 38 ********************************************************************************/
grzemich 0:d7bd7384a37c 39 #define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT)
grzemich 0:d7bd7384a37c 40 #define ENET_ALIGN(x,align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)- 1)))
grzemich 0:d7bd7384a37c 41 extern void k64f_init_eth_hardware(void);
grzemich 0:d7bd7384a37c 42
grzemich 0:d7bd7384a37c 43 /* K64F EMAC driver data structure */
grzemich 0:d7bd7384a37c 44 struct k64f_enetdata {
grzemich 0:d7bd7384a37c 45 struct netif *netif; /**< Reference back to LWIP parent netif */
grzemich 0:d7bd7384a37c 46 sys_sem_t RxReadySem; /**< RX packet ready semaphore */
grzemich 0:d7bd7384a37c 47 sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */
grzemich 0:d7bd7384a37c 48 sys_mutex_t TXLockMutex; /**< TX critical section mutex */
grzemich 0:d7bd7384a37c 49 sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */
grzemich 0:d7bd7384a37c 50 uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */
grzemich 0:d7bd7384a37c 51 };
grzemich 0:d7bd7384a37c 52
grzemich 0:d7bd7384a37c 53 static struct k64f_enetdata k64f_enetdata;
grzemich 0:d7bd7384a37c 54
grzemich 0:d7bd7384a37c 55 /** \brief Driver transmit and receive thread priorities
grzemich 0:d7bd7384a37c 56 *
grzemich 0:d7bd7384a37c 57 * Thread priorities for receive thread and TX cleanup thread. Alter
grzemich 0:d7bd7384a37c 58 * to prioritize receive or transmit bandwidth. In a heavily loaded
grzemich 0:d7bd7384a37c 59 * system or with LEIP_DEBUG enabled, the priorities might be better
grzemich 0:d7bd7384a37c 60 * the same. */
grzemich 0:d7bd7384a37c 61 #define RX_PRIORITY (osPriorityNormal)
grzemich 0:d7bd7384a37c 62 #define TX_PRIORITY (osPriorityNormal)
grzemich 0:d7bd7384a37c 63 #define PHY_PRIORITY (osPriorityNormal)
grzemich 0:d7bd7384a37c 64
grzemich 0:d7bd7384a37c 65 /********************************************************************************
grzemich 0:d7bd7384a37c 66 * Buffer management
grzemich 0:d7bd7384a37c 67 ********************************************************************************/
grzemich 0:d7bd7384a37c 68 /*
grzemich 0:d7bd7384a37c 69 * This function will queue a new receive buffer
grzemich 0:d7bd7384a37c 70 */
grzemich 0:d7bd7384a37c 71 static void update_read_buffer(uint8_t *buf)
grzemich 0:d7bd7384a37c 72 {
grzemich 0:d7bd7384a37c 73 if (buf != NULL) {
grzemich 0:d7bd7384a37c 74 g_handle.rxBdCurrent->buffer = buf;
grzemich 0:d7bd7384a37c 75 }
grzemich 0:d7bd7384a37c 76
grzemich 0:d7bd7384a37c 77 /* Clears status. */
grzemich 0:d7bd7384a37c 78 g_handle.rxBdCurrent->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK;
grzemich 0:d7bd7384a37c 79
grzemich 0:d7bd7384a37c 80 /* Sets the receive buffer descriptor with the empty flag. */
grzemich 0:d7bd7384a37c 81 g_handle.rxBdCurrent->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK;
grzemich 0:d7bd7384a37c 82
grzemich 0:d7bd7384a37c 83 /* Increases the buffer descriptor to the next one. */
grzemich 0:d7bd7384a37c 84 if (g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) {
grzemich 0:d7bd7384a37c 85 g_handle.rxBdCurrent = g_handle.rxBdBase;
grzemich 0:d7bd7384a37c 86 g_handle.rxBdDirty = g_handle.rxBdBase;
grzemich 0:d7bd7384a37c 87 } else {
grzemich 0:d7bd7384a37c 88 g_handle.rxBdCurrent++;
grzemich 0:d7bd7384a37c 89 g_handle.rxBdDirty++;
grzemich 0:d7bd7384a37c 90 }
grzemich 0:d7bd7384a37c 91
grzemich 0:d7bd7384a37c 92 /* Actives the receive buffer descriptor. */
grzemich 0:d7bd7384a37c 93 ENET->RDAR = ENET_RDAR_RDAR_MASK;
grzemich 0:d7bd7384a37c 94 }
grzemich 0:d7bd7384a37c 95
grzemich 0:d7bd7384a37c 96 /** \brief Free TX buffers that are complete
grzemich 0:d7bd7384a37c 97 *
grzemich 0:d7bd7384a37c 98 * \param[in] k64f_enet Pointer to driver data structure
grzemich 0:d7bd7384a37c 99 */
grzemich 0:d7bd7384a37c 100 static void k64f_tx_reclaim(struct k64f_enetdata *k64f_enet)
grzemich 0:d7bd7384a37c 101 {
grzemich 0:d7bd7384a37c 102 uint8_t i = 0 ;
grzemich 0:d7bd7384a37c 103
grzemich 0:d7bd7384a37c 104 /* Get exclusive access */
grzemich 0:d7bd7384a37c 105 sys_mutex_lock(&k64f_enet->TXLockMutex);
grzemich 0:d7bd7384a37c 106
grzemich 0:d7bd7384a37c 107 i = k64f_enet->tx_consume_index;
grzemich 0:d7bd7384a37c 108 // Traverse all descriptors, looking for the ones modified by the uDMA
grzemich 0:d7bd7384a37c 109 while((i != k64f_enet->tx_produce_index) && (!(g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK))) {
grzemich 0:d7bd7384a37c 110 pbuf_free(tx_buff[i]);
grzemich 0:d7bd7384a37c 111 if (g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK)
grzemich 0:d7bd7384a37c 112 g_handle.txBdDirty = g_handle.txBdBase;
grzemich 0:d7bd7384a37c 113 else
grzemich 0:d7bd7384a37c 114 g_handle.txBdDirty++;
grzemich 0:d7bd7384a37c 115
grzemich 0:d7bd7384a37c 116 i = (i + 1) % ENET_TX_RING_LEN;
grzemich 0:d7bd7384a37c 117 }
grzemich 0:d7bd7384a37c 118
grzemich 0:d7bd7384a37c 119 k64f_enet->tx_consume_index = i;
grzemich 0:d7bd7384a37c 120 /* Restore access */
grzemich 0:d7bd7384a37c 121 sys_mutex_unlock(&k64f_enet->TXLockMutex);
grzemich 0:d7bd7384a37c 122 }
grzemich 0:d7bd7384a37c 123
grzemich 0:d7bd7384a37c 124 /** \brief Ethernet receive interrupt handler
grzemich 0:d7bd7384a37c 125 *
grzemich 0:d7bd7384a37c 126 * This function handles the receive interrupt of K64F.
grzemich 0:d7bd7384a37c 127 */
grzemich 0:d7bd7384a37c 128 void enet_mac_rx_isr()
grzemich 0:d7bd7384a37c 129 {
grzemich 0:d7bd7384a37c 130 sys_sem_signal(&k64f_enetdata.RxReadySem);
grzemich 0:d7bd7384a37c 131 }
grzemich 0:d7bd7384a37c 132
grzemich 0:d7bd7384a37c 133 void enet_mac_tx_isr()
grzemich 0:d7bd7384a37c 134 {
grzemich 0:d7bd7384a37c 135 sys_sem_signal(&k64f_enetdata.TxCleanSem);
grzemich 0:d7bd7384a37c 136 }
grzemich 0:d7bd7384a37c 137
grzemich 0:d7bd7384a37c 138 void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param)
grzemich 0:d7bd7384a37c 139 {
grzemich 0:d7bd7384a37c 140 switch (event)
grzemich 0:d7bd7384a37c 141 {
grzemich 0:d7bd7384a37c 142 case kENET_RxEvent:
grzemich 0:d7bd7384a37c 143 enet_mac_rx_isr();
grzemich 0:d7bd7384a37c 144 break;
grzemich 0:d7bd7384a37c 145 case kENET_TxEvent:
grzemich 0:d7bd7384a37c 146 enet_mac_tx_isr();
grzemich 0:d7bd7384a37c 147 break;
grzemich 0:d7bd7384a37c 148 default:
grzemich 0:d7bd7384a37c 149 break;
grzemich 0:d7bd7384a37c 150 }
grzemich 0:d7bd7384a37c 151 }
grzemich 0:d7bd7384a37c 152
grzemich 0:d7bd7384a37c 153 /** \brief Low level init of the MAC and PHY.
grzemich 0:d7bd7384a37c 154 *
grzemich 0:d7bd7384a37c 155 * \param[in] netif Pointer to LWIP netif structure
grzemich 0:d7bd7384a37c 156 */
grzemich 0:d7bd7384a37c 157 static err_t low_level_init(struct netif *netif)
grzemich 0:d7bd7384a37c 158 {
grzemich 0:d7bd7384a37c 159 struct k64f_enetdata *k64f_enet = netif->state;
grzemich 0:d7bd7384a37c 160 uint8_t i;
grzemich 0:d7bd7384a37c 161 uint32_t sysClock;
grzemich 0:d7bd7384a37c 162 phy_speed_t phy_speed;
grzemich 0:d7bd7384a37c 163 phy_duplex_t phy_duplex;
grzemich 0:d7bd7384a37c 164 uint32_t phyAddr = 0;
grzemich 0:d7bd7384a37c 165 bool link = false;
grzemich 0:d7bd7384a37c 166 enet_config_t config;
grzemich 0:d7bd7384a37c 167
grzemich 0:d7bd7384a37c 168 // Allocate RX descriptors
grzemich 0:d7bd7384a37c 169 rx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_rx_bd_struct_t) * ENET_RX_RING_LEN + ENET_BUFF_ALIGNMENT);
grzemich 0:d7bd7384a37c 170 if(!rx_desc_start_addr)
grzemich 0:d7bd7384a37c 171 return ERR_MEM;
grzemich 0:d7bd7384a37c 172
grzemich 0:d7bd7384a37c 173 // Allocate TX descriptors
grzemich 0:d7bd7384a37c 174 tx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_tx_bd_struct_t) * ENET_TX_RING_LEN + ENET_BUFF_ALIGNMENT);
grzemich 0:d7bd7384a37c 175 if(!tx_desc_start_addr)
grzemich 0:d7bd7384a37c 176 return ERR_MEM;
grzemich 0:d7bd7384a37c 177
grzemich 0:d7bd7384a37c 178 rx_desc_start_addr = (uint8_t *)ENET_ALIGN(rx_desc_start_addr, ENET_BUFF_ALIGNMENT);
grzemich 0:d7bd7384a37c 179 tx_desc_start_addr = (uint8_t *)ENET_ALIGN(tx_desc_start_addr, ENET_BUFF_ALIGNMENT);
grzemich 0:d7bd7384a37c 180
grzemich 0:d7bd7384a37c 181 /* Create buffers for each receive BD */
grzemich 0:d7bd7384a37c 182 for (i = 0; i < ENET_RX_RING_LEN; i++) {
grzemich 0:d7bd7384a37c 183 rx_buff[i] = pbuf_alloc(PBUF_RAW, ENET_ETH_MAX_FLEN + ENET_BUFF_ALIGNMENT, PBUF_RAM);
grzemich 0:d7bd7384a37c 184 if (NULL == rx_buff[i])
grzemich 0:d7bd7384a37c 185 return ERR_MEM;
grzemich 0:d7bd7384a37c 186
grzemich 0:d7bd7384a37c 187 /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F
grzemich 0:d7bd7384a37c 188 RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing
grzemich 0:d7bd7384a37c 189 a data structure which is internal to lwIP. This might not prove to be a good idea
grzemich 0:d7bd7384a37c 190 in the long run, but a better fix would probably involve modifying lwIP itself */
grzemich 0:d7bd7384a37c 191 rx_buff[i]->payload = (void*)ENET_ALIGN((uint32_t)rx_buff[i]->payload, ENET_BUFF_ALIGNMENT);
grzemich 0:d7bd7384a37c 192 rx_ptr[i] = rx_buff[i]->payload;
grzemich 0:d7bd7384a37c 193 }
grzemich 0:d7bd7384a37c 194
grzemich 0:d7bd7384a37c 195 k64f_enet->tx_consume_index = k64f_enet->tx_produce_index = 0;
grzemich 0:d7bd7384a37c 196
grzemich 0:d7bd7384a37c 197 /* prepare the buffer configuration. */
grzemich 0:d7bd7384a37c 198 enet_buffer_config_t buffCfg = {
grzemich 0:d7bd7384a37c 199 ENET_RX_RING_LEN,
grzemich 0:d7bd7384a37c 200 ENET_TX_RING_LEN,
grzemich 0:d7bd7384a37c 201 ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT),
grzemich 0:d7bd7384a37c 202 0,
grzemich 0:d7bd7384a37c 203 (volatile enet_rx_bd_struct_t *)rx_desc_start_addr,
grzemich 0:d7bd7384a37c 204 (volatile enet_tx_bd_struct_t *)tx_desc_start_addr,
grzemich 0:d7bd7384a37c 205 (uint8_t *)&rx_ptr,
grzemich 0:d7bd7384a37c 206 NULL,
grzemich 0:d7bd7384a37c 207 };
grzemich 0:d7bd7384a37c 208
grzemich 0:d7bd7384a37c 209 k64f_init_eth_hardware();
grzemich 0:d7bd7384a37c 210
grzemich 0:d7bd7384a37c 211 sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk);
grzemich 0:d7bd7384a37c 212
grzemich 0:d7bd7384a37c 213 ENET_GetDefaultConfig(&config);
grzemich 0:d7bd7384a37c 214
grzemich 0:d7bd7384a37c 215 PHY_Init(ENET, 0, sysClock);
grzemich 0:d7bd7384a37c 216 PHY_GetLinkStatus(ENET, phyAddr, &link);
grzemich 0:d7bd7384a37c 217 if (link)
grzemich 0:d7bd7384a37c 218 {
grzemich 0:d7bd7384a37c 219 /* Get link information from PHY */
grzemich 0:d7bd7384a37c 220 PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex);
grzemich 0:d7bd7384a37c 221 /* Change the MII speed and duplex for actual link status. */
grzemich 0:d7bd7384a37c 222 config.miiSpeed = (enet_mii_speed_t)phy_speed;
grzemich 0:d7bd7384a37c 223 config.miiDuplex = (enet_mii_duplex_t)phy_duplex;
grzemich 0:d7bd7384a37c 224 config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt;
grzemich 0:d7bd7384a37c 225 }
grzemich 0:d7bd7384a37c 226 config.rxMaxFrameLen = ENET_ETH_MAX_FLEN;
grzemich 0:d7bd7384a37c 227 config.macSpecialConfig = kENET_ControlFlowControlEnable;
grzemich 0:d7bd7384a37c 228 config.txAccelerConfig = kENET_TxAccelIsShift16Enabled;
grzemich 0:d7bd7384a37c 229 config.rxAccelerConfig = kENET_RxAccelisShift16Enabled | kENET_RxAccelMacCheckEnabled;
grzemich 0:d7bd7384a37c 230 ENET_Init(ENET, &g_handle, &config, &buffCfg, netif->hwaddr, sysClock);
grzemich 0:d7bd7384a37c 231 ENET_SetCallback(&g_handle, ethernet_callback, netif);
grzemich 0:d7bd7384a37c 232 ENET_ActiveRead(ENET);
grzemich 0:d7bd7384a37c 233
grzemich 0:d7bd7384a37c 234 return ERR_OK;
grzemich 0:d7bd7384a37c 235 }
grzemich 0:d7bd7384a37c 236
grzemich 0:d7bd7384a37c 237
grzemich 0:d7bd7384a37c 238 /**
grzemich 0:d7bd7384a37c 239 * This function is the ethernet packet send function. It calls
grzemich 0:d7bd7384a37c 240 * etharp_output after checking link status.
grzemich 0:d7bd7384a37c 241 *
grzemich 0:d7bd7384a37c 242 * \param[in] netif the lwip network interface structure for this enetif
grzemich 0:d7bd7384a37c 243 * \param[in] q Pointer to pbug to send
grzemich 0:d7bd7384a37c 244 * \param[in] ipaddr IP address
grzemich 0:d7bd7384a37c 245 * \return ERR_OK or error code
grzemich 0:d7bd7384a37c 246 */
grzemich 0:d7bd7384a37c 247 err_t k64f_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
grzemich 0:d7bd7384a37c 248 {
grzemich 0:d7bd7384a37c 249 /* Only send packet is link is up */
grzemich 0:d7bd7384a37c 250 if (netif->flags & NETIF_FLAG_LINK_UP)
grzemich 0:d7bd7384a37c 251 return etharp_output(netif, q, ipaddr);
grzemich 0:d7bd7384a37c 252
grzemich 0:d7bd7384a37c 253 return ERR_CONN;
grzemich 0:d7bd7384a37c 254 }
grzemich 0:d7bd7384a37c 255
grzemich 0:d7bd7384a37c 256 /** \brief Allocates a pbuf and returns the data from the incoming packet.
grzemich 0:d7bd7384a37c 257 *
grzemich 0:d7bd7384a37c 258 * \param[in] netif the lwip network interface structure
grzemich 0:d7bd7384a37c 259 * \param[in] idx index of packet to be read
grzemich 0:d7bd7384a37c 260 * \return a pbuf filled with the received packet (including MAC header)
grzemich 0:d7bd7384a37c 261 */
grzemich 0:d7bd7384a37c 262 static struct pbuf *k64f_low_level_input(struct netif *netif, int idx)
grzemich 0:d7bd7384a37c 263 {
grzemich 0:d7bd7384a37c 264 volatile enet_rx_bd_struct_t *bdPtr = g_handle.rxBdCurrent;
grzemich 0:d7bd7384a37c 265 struct pbuf *p = NULL;
grzemich 0:d7bd7384a37c 266 struct pbuf *temp_rxbuf = NULL;
grzemich 0:d7bd7384a37c 267 u32_t length = 0;
grzemich 0:d7bd7384a37c 268 const u16_t err_mask = ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK | ENET_BUFFDESCRIPTOR_RX_CRC_MASK |
grzemich 0:d7bd7384a37c 269 ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK | ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK;
grzemich 0:d7bd7384a37c 270
grzemich 0:d7bd7384a37c 271
grzemich 0:d7bd7384a37c 272 #ifdef LOCK_RX_THREAD
grzemich 0:d7bd7384a37c 273 /* Get exclusive access */
grzemich 0:d7bd7384a37c 274 sys_mutex_lock(&k64f_enet->TXLockMutex);
grzemich 0:d7bd7384a37c 275 #endif
grzemich 0:d7bd7384a37c 276
grzemich 0:d7bd7384a37c 277 /* Determine if a frame has been received */
grzemich 0:d7bd7384a37c 278 if ((bdPtr->control & err_mask) != 0) {
grzemich 0:d7bd7384a37c 279 #if LINK_STATS
grzemich 0:d7bd7384a37c 280 if ((bdPtr->control & ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK) != 0)
grzemich 0:d7bd7384a37c 281 LINK_STATS_INC(link.lenerr);
grzemich 0:d7bd7384a37c 282 else
grzemich 0:d7bd7384a37c 283 LINK_STATS_INC(link.chkerr);
grzemich 0:d7bd7384a37c 284 #endif
grzemich 0:d7bd7384a37c 285 LINK_STATS_INC(link.drop);
grzemich 0:d7bd7384a37c 286 /* Re-use the same buffer in case of error */
grzemich 0:d7bd7384a37c 287 update_read_buffer(NULL);
grzemich 0:d7bd7384a37c 288 } else {
grzemich 0:d7bd7384a37c 289 /* A packet is waiting, get length */
grzemich 0:d7bd7384a37c 290 length = bdPtr->length;
grzemich 0:d7bd7384a37c 291
grzemich 0:d7bd7384a37c 292 /* Zero-copy */
grzemich 0:d7bd7384a37c 293 p = rx_buff[idx];
grzemich 0:d7bd7384a37c 294 p->len = length;
grzemich 0:d7bd7384a37c 295
grzemich 0:d7bd7384a37c 296 /* Attempt to queue new buffer */
grzemich 0:d7bd7384a37c 297 temp_rxbuf = pbuf_alloc(PBUF_RAW, ENET_ETH_MAX_FLEN + ENET_BUFF_ALIGNMENT, PBUF_RAM);
grzemich 0:d7bd7384a37c 298 if (NULL == temp_rxbuf) {
grzemich 0:d7bd7384a37c 299 /* Drop frame (out of memory) */
grzemich 0:d7bd7384a37c 300 LINK_STATS_INC(link.drop);
grzemich 0:d7bd7384a37c 301
grzemich 0:d7bd7384a37c 302 /* Re-queue the same buffer */
grzemich 0:d7bd7384a37c 303 update_read_buffer(NULL);
grzemich 0:d7bd7384a37c 304
grzemich 0:d7bd7384a37c 305 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
grzemich 0:d7bd7384a37c 306 ("k64f_low_level_input: Packet index %d dropped for OOM\n",
grzemich 0:d7bd7384a37c 307 idx));
grzemich 0:d7bd7384a37c 308 #ifdef LOCK_RX_THREAD
grzemich 0:d7bd7384a37c 309 sys_mutex_unlock(&k64f_enet->TXLockMutex);
grzemich 0:d7bd7384a37c 310 #endif
grzemich 0:d7bd7384a37c 311
grzemich 0:d7bd7384a37c 312 return NULL;
grzemich 0:d7bd7384a37c 313 }
grzemich 0:d7bd7384a37c 314
grzemich 0:d7bd7384a37c 315 rx_buff[idx] = temp_rxbuf;
grzemich 0:d7bd7384a37c 316 /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F
grzemich 0:d7bd7384a37c 317 RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing
grzemich 0:d7bd7384a37c 318 a data structure which is internal to lwIP. This might not prove to be a good idea
grzemich 0:d7bd7384a37c 319 in the long run, but a better fix would probably involve modifying lwIP itself */
grzemich 0:d7bd7384a37c 320 rx_buff[idx]->payload = (void*)ENET_ALIGN((uint32_t)rx_buff[idx]->payload, ENET_BUFF_ALIGNMENT);
grzemich 0:d7bd7384a37c 321 rx_ptr[idx] = rx_buff[idx]->payload;
grzemich 0:d7bd7384a37c 322
grzemich 0:d7bd7384a37c 323 update_read_buffer(rx_buff[idx]->payload);
grzemich 0:d7bd7384a37c 324 LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
grzemich 0:d7bd7384a37c 325 ("k64f_low_level_input: Packet received: %p, size %d (index=%d)\n",
grzemich 0:d7bd7384a37c 326 p, length, idx));
grzemich 0:d7bd7384a37c 327
grzemich 0:d7bd7384a37c 328 /* Save size */
grzemich 0:d7bd7384a37c 329 p->tot_len = (u16_t) length;
grzemich 0:d7bd7384a37c 330 LINK_STATS_INC(link.recv);
grzemich 0:d7bd7384a37c 331 }
grzemich 0:d7bd7384a37c 332
grzemich 0:d7bd7384a37c 333 #ifdef LOCK_RX_THREAD
grzemich 0:d7bd7384a37c 334 sys_mutex_unlock(&k64f_enet->TXLockMutex);
grzemich 0:d7bd7384a37c 335 #endif
grzemich 0:d7bd7384a37c 336
grzemich 0:d7bd7384a37c 337 return p;
grzemich 0:d7bd7384a37c 338 }
grzemich 0:d7bd7384a37c 339
grzemich 0:d7bd7384a37c 340 /** \brief Attempt to read a packet from the EMAC interface.
grzemich 0:d7bd7384a37c 341 *
grzemich 0:d7bd7384a37c 342 * \param[in] netif the lwip network interface structure
grzemich 0:d7bd7384a37c 343 * \param[in] idx index of packet to be read
grzemich 0:d7bd7384a37c 344 */
grzemich 0:d7bd7384a37c 345 void k64f_enetif_input(struct netif *netif, int idx)
grzemich 0:d7bd7384a37c 346 {
grzemich 0:d7bd7384a37c 347 struct eth_hdr *ethhdr;
grzemich 0:d7bd7384a37c 348 struct pbuf *p;
grzemich 0:d7bd7384a37c 349
grzemich 0:d7bd7384a37c 350 /* move received packet into a new pbuf */
grzemich 0:d7bd7384a37c 351 p = k64f_low_level_input(netif, idx);
grzemich 0:d7bd7384a37c 352 if (p == NULL)
grzemich 0:d7bd7384a37c 353 return;
grzemich 0:d7bd7384a37c 354
grzemich 0:d7bd7384a37c 355 /* points to packet payload, which starts with an Ethernet header */
grzemich 0:d7bd7384a37c 356 ethhdr = (struct eth_hdr*)p->payload;
grzemich 0:d7bd7384a37c 357
grzemich 0:d7bd7384a37c 358 switch (htons(ethhdr->type)) {
grzemich 0:d7bd7384a37c 359 case ETHTYPE_IP:
grzemich 0:d7bd7384a37c 360 case ETHTYPE_ARP:
grzemich 0:d7bd7384a37c 361 #if PPPOE_SUPPORT
grzemich 0:d7bd7384a37c 362 case ETHTYPE_PPPOEDISC:
grzemich 0:d7bd7384a37c 363 case ETHTYPE_PPPOE:
grzemich 0:d7bd7384a37c 364 #endif /* PPPOE_SUPPORT */
grzemich 0:d7bd7384a37c 365 /* full packet send to tcpip_thread to process */
grzemich 0:d7bd7384a37c 366 if (netif->input(p, netif) != ERR_OK) {
grzemich 0:d7bd7384a37c 367 LWIP_DEBUGF(NETIF_DEBUG, ("k64f_enetif_input: IP input error\n"));
grzemich 0:d7bd7384a37c 368 /* Free buffer */
grzemich 0:d7bd7384a37c 369 pbuf_free(p);
grzemich 0:d7bd7384a37c 370 }
grzemich 0:d7bd7384a37c 371 break;
grzemich 0:d7bd7384a37c 372
grzemich 0:d7bd7384a37c 373 default:
grzemich 0:d7bd7384a37c 374 /* Return buffer */
grzemich 0:d7bd7384a37c 375 pbuf_free(p);
grzemich 0:d7bd7384a37c 376 break;
grzemich 0:d7bd7384a37c 377 }
grzemich 0:d7bd7384a37c 378 }
grzemich 0:d7bd7384a37c 379
grzemich 0:d7bd7384a37c 380 /** \brief Packet reception task
grzemich 0:d7bd7384a37c 381 *
grzemich 0:d7bd7384a37c 382 * This task is called when a packet is received. It will
grzemich 0:d7bd7384a37c 383 * pass the packet to the LWIP core.
grzemich 0:d7bd7384a37c 384 *
grzemich 0:d7bd7384a37c 385 * \param[in] pvParameters pointer to the interface data
grzemich 0:d7bd7384a37c 386 */
grzemich 0:d7bd7384a37c 387 static void packet_rx(void* pvParameters) {
grzemich 0:d7bd7384a37c 388 struct k64f_enetdata *k64f_enet = pvParameters;
grzemich 0:d7bd7384a37c 389 int idx = 0;
grzemich 0:d7bd7384a37c 390
grzemich 0:d7bd7384a37c 391 while (1) {
grzemich 0:d7bd7384a37c 392 /* Wait for receive task to wakeup */
grzemich 0:d7bd7384a37c 393 sys_arch_sem_wait(&k64f_enet->RxReadySem, 0);
grzemich 0:d7bd7384a37c 394
grzemich 0:d7bd7384a37c 395 while ((g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0) {
grzemich 0:d7bd7384a37c 396 k64f_enetif_input(k64f_enet->netif, idx);
grzemich 0:d7bd7384a37c 397 idx = (idx + 1) % ENET_RX_RING_LEN;
grzemich 0:d7bd7384a37c 398 }
grzemich 0:d7bd7384a37c 399 }
grzemich 0:d7bd7384a37c 400 }
grzemich 0:d7bd7384a37c 401
grzemich 0:d7bd7384a37c 402 /** \brief Transmit cleanup task
grzemich 0:d7bd7384a37c 403 *
grzemich 0:d7bd7384a37c 404 * This task is called when a transmit interrupt occurs and
grzemich 0:d7bd7384a37c 405 * reclaims the pbuf and descriptor used for the packet once
grzemich 0:d7bd7384a37c 406 * the packet has been transferred.
grzemich 0:d7bd7384a37c 407 *
grzemich 0:d7bd7384a37c 408 * \param[in] pvParameters pointer to the interface data
grzemich 0:d7bd7384a37c 409 */
grzemich 0:d7bd7384a37c 410 static void packet_tx(void* pvParameters) {
grzemich 0:d7bd7384a37c 411 struct k64f_enetdata *k64f_enet = pvParameters;
grzemich 0:d7bd7384a37c 412
grzemich 0:d7bd7384a37c 413 while (1) {
grzemich 0:d7bd7384a37c 414 /* Wait for transmit cleanup task to wakeup */
grzemich 0:d7bd7384a37c 415 sys_arch_sem_wait(&k64f_enet->TxCleanSem, 0);
grzemich 0:d7bd7384a37c 416 k64f_tx_reclaim(k64f_enet);
grzemich 0:d7bd7384a37c 417 }
grzemich 0:d7bd7384a37c 418 }
grzemich 0:d7bd7384a37c 419
grzemich 0:d7bd7384a37c 420 /** \brief Low level output of a packet. Never call this from an
grzemich 0:d7bd7384a37c 421 * interrupt context, as it may block until TX descriptors
grzemich 0:d7bd7384a37c 422 * become available.
grzemich 0:d7bd7384a37c 423 *
grzemich 0:d7bd7384a37c 424 * \param[in] netif the lwip network interface structure for this netif
grzemich 0:d7bd7384a37c 425 * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type)
grzemich 0:d7bd7384a37c 426 * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent
grzemich 0:d7bd7384a37c 427 */
grzemich 0:d7bd7384a37c 428 static err_t k64f_low_level_output(struct netif *netif, struct pbuf *p)
grzemich 0:d7bd7384a37c 429 {
grzemich 0:d7bd7384a37c 430 struct k64f_enetdata *k64f_enet = netif->state;
grzemich 0:d7bd7384a37c 431 struct pbuf *q;
grzemich 0:d7bd7384a37c 432 struct pbuf *temp_pbuf;
grzemich 0:d7bd7384a37c 433 uint8_t *psend = NULL, *dst;
grzemich 0:d7bd7384a37c 434
grzemich 0:d7bd7384a37c 435
grzemich 0:d7bd7384a37c 436 temp_pbuf = pbuf_alloc(PBUF_RAW, p->tot_len + ENET_BUFF_ALIGNMENT, PBUF_RAM);
grzemich 0:d7bd7384a37c 437 if (NULL == temp_pbuf)
grzemich 0:d7bd7384a37c 438 return ERR_MEM;
grzemich 0:d7bd7384a37c 439
grzemich 0:d7bd7384a37c 440 /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F
grzemich 0:d7bd7384a37c 441 RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing
grzemich 0:d7bd7384a37c 442 a data structure which is internal to lwIP. This might not prove to be a good idea
grzemich 0:d7bd7384a37c 443 in the long run, but a better fix would probably involve modifying lwIP itself */
grzemich 0:d7bd7384a37c 444 psend = (uint8_t *)ENET_ALIGN((uint32_t)temp_pbuf->payload, ENET_BUFF_ALIGNMENT);
grzemich 0:d7bd7384a37c 445
grzemich 0:d7bd7384a37c 446 for (q = p, dst = psend; q != NULL; q = q->next) {
grzemich 0:d7bd7384a37c 447 MEMCPY(dst, q->payload, q->len);
grzemich 0:d7bd7384a37c 448 dst += q->len;
grzemich 0:d7bd7384a37c 449 }
grzemich 0:d7bd7384a37c 450
grzemich 0:d7bd7384a37c 451 /* Wait until a descriptor is available for the transfer. */
grzemich 0:d7bd7384a37c 452 /* THIS WILL BLOCK UNTIL THERE ARE A DESCRIPTOR AVAILABLE */
grzemich 0:d7bd7384a37c 453 while (g_handle.txBdCurrent->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK)
grzemich 0:d7bd7384a37c 454 osSemaphoreWait(k64f_enet->xTXDCountSem.id, osWaitForever);
grzemich 0:d7bd7384a37c 455
grzemich 0:d7bd7384a37c 456 /* Get exclusive access */
grzemich 0:d7bd7384a37c 457 sys_mutex_lock(&k64f_enet->TXLockMutex);
grzemich 0:d7bd7384a37c 458
grzemich 0:d7bd7384a37c 459 /* Save the buffer so that it can be freed when transmit is done */
grzemich 0:d7bd7384a37c 460 tx_buff[k64f_enet->tx_produce_index] = temp_pbuf;
grzemich 0:d7bd7384a37c 461 k64f_enet->tx_produce_index = (k64f_enet->tx_produce_index + 1) % ENET_TX_RING_LEN;
grzemich 0:d7bd7384a37c 462
grzemich 0:d7bd7384a37c 463 /* Setup transfers */
grzemich 0:d7bd7384a37c 464 g_handle.txBdCurrent->buffer = psend;
grzemich 0:d7bd7384a37c 465 g_handle.txBdCurrent->length = p->tot_len;
grzemich 0:d7bd7384a37c 466 g_handle.txBdCurrent->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK);
grzemich 0:d7bd7384a37c 467
grzemich 0:d7bd7384a37c 468 /* Increase the buffer descriptor address. */
grzemich 0:d7bd7384a37c 469 if (g_handle.txBdCurrent->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK)
grzemich 0:d7bd7384a37c 470 g_handle.txBdCurrent = g_handle.txBdBase;
grzemich 0:d7bd7384a37c 471 else
grzemich 0:d7bd7384a37c 472 g_handle.txBdCurrent++;
grzemich 0:d7bd7384a37c 473
grzemich 0:d7bd7384a37c 474 /* Active the transmit buffer descriptor. */
grzemich 0:d7bd7384a37c 475 ENET->TDAR = ENET_TDAR_TDAR_MASK;
grzemich 0:d7bd7384a37c 476
grzemich 0:d7bd7384a37c 477 LINK_STATS_INC(link.xmit);
grzemich 0:d7bd7384a37c 478
grzemich 0:d7bd7384a37c 479 /* Restore access */
grzemich 0:d7bd7384a37c 480 sys_mutex_unlock(&k64f_enet->TXLockMutex);
grzemich 0:d7bd7384a37c 481
grzemich 0:d7bd7384a37c 482 return ERR_OK;
grzemich 0:d7bd7384a37c 483 }
grzemich 0:d7bd7384a37c 484
grzemich 0:d7bd7384a37c 485 /*******************************************************************************
grzemich 0:d7bd7384a37c 486 * PHY task: monitor link
grzemich 0:d7bd7384a37c 487 *******************************************************************************/
grzemich 0:d7bd7384a37c 488
grzemich 0:d7bd7384a37c 489 #define PHY_TASK_PERIOD_MS 200
grzemich 0:d7bd7384a37c 490 #define STATE_UNKNOWN (-1)
grzemich 0:d7bd7384a37c 491
grzemich 0:d7bd7384a37c 492 typedef struct {
grzemich 0:d7bd7384a37c 493 int connected;
grzemich 0:d7bd7384a37c 494 phy_speed_t speed;
grzemich 0:d7bd7384a37c 495 phy_duplex_t duplex;
grzemich 0:d7bd7384a37c 496 } PHY_STATE;
grzemich 0:d7bd7384a37c 497
grzemich 0:d7bd7384a37c 498 int phy_link_status() {
grzemich 0:d7bd7384a37c 499 bool connection_status;
grzemich 0:d7bd7384a37c 500 uint32_t phyAddr = 0;
grzemich 0:d7bd7384a37c 501
grzemich 0:d7bd7384a37c 502 PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
grzemich 0:d7bd7384a37c 503 return (int)connection_status;
grzemich 0:d7bd7384a37c 504 }
grzemich 0:d7bd7384a37c 505
grzemich 0:d7bd7384a37c 506 int phy_get_duplex() {
grzemich 0:d7bd7384a37c 507 bool connection_status;
grzemich 0:d7bd7384a37c 508 PHY_STATE crt_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN};
grzemich 0:d7bd7384a37c 509 uint32_t phyAddr = 0;
grzemich 0:d7bd7384a37c 510
grzemich 0:d7bd7384a37c 511 PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
grzemich 0:d7bd7384a37c 512 crt_state.connected = connection_status ? 1 : 0;
grzemich 0:d7bd7384a37c 513 PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex);
grzemich 0:d7bd7384a37c 514
grzemich 0:d7bd7384a37c 515 return (int)crt_state.duplex;
grzemich 0:d7bd7384a37c 516 }
grzemich 0:d7bd7384a37c 517
grzemich 0:d7bd7384a37c 518 int phy_get_speed() {
grzemich 0:d7bd7384a37c 519 bool connection_status;
grzemich 0:d7bd7384a37c 520 PHY_STATE crt_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN};
grzemich 0:d7bd7384a37c 521 uint32_t phyAddr = 0;
grzemich 0:d7bd7384a37c 522
grzemich 0:d7bd7384a37c 523 PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
grzemich 0:d7bd7384a37c 524 crt_state.connected = connection_status ? 1 : 0;
grzemich 0:d7bd7384a37c 525 PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex);
grzemich 0:d7bd7384a37c 526
grzemich 0:d7bd7384a37c 527 return (int)crt_state.speed;
grzemich 0:d7bd7384a37c 528 }
grzemich 0:d7bd7384a37c 529
grzemich 0:d7bd7384a37c 530 static void k64f_phy_task(void *data) {
grzemich 0:d7bd7384a37c 531 struct netif *netif = (struct netif*)data;
grzemich 0:d7bd7384a37c 532 bool connection_status;
grzemich 0:d7bd7384a37c 533 PHY_STATE crt_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN};
grzemich 0:d7bd7384a37c 534 PHY_STATE prev_state;
grzemich 0:d7bd7384a37c 535 uint32_t phyAddr = 0;
grzemich 0:d7bd7384a37c 536 uint32_t rcr = 0;
grzemich 0:d7bd7384a37c 537
grzemich 0:d7bd7384a37c 538
grzemich 0:d7bd7384a37c 539 prev_state = crt_state;
grzemich 0:d7bd7384a37c 540 while (true) {
grzemich 0:d7bd7384a37c 541 // Get current status
grzemich 0:d7bd7384a37c 542 PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
grzemich 0:d7bd7384a37c 543 crt_state.connected = connection_status ? 1 : 0;
grzemich 0:d7bd7384a37c 544 // Get the actual PHY link speed
grzemich 0:d7bd7384a37c 545 PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex);
grzemich 0:d7bd7384a37c 546 //printf("Speed: %d\n", crt_state.speed);
grzemich 0:d7bd7384a37c 547 //printf("Duplex: %d\n", crt_state.duplex);
grzemich 0:d7bd7384a37c 548 // Compare with previous state
grzemich 0:d7bd7384a37c 549 if (crt_state.connected != prev_state.connected) {
grzemich 0:d7bd7384a37c 550 if (crt_state.connected)
grzemich 0:d7bd7384a37c 551 tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
grzemich 0:d7bd7384a37c 552 else
grzemich 0:d7bd7384a37c 553 tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
grzemich 0:d7bd7384a37c 554 }
grzemich 0:d7bd7384a37c 555
grzemich 0:d7bd7384a37c 556 if (crt_state.speed != prev_state.speed) {
grzemich 0:d7bd7384a37c 557 rcr = ENET->RCR;
grzemich 0:d7bd7384a37c 558 rcr &= ~ENET_RCR_RMII_10T_MASK;
grzemich 0:d7bd7384a37c 559 rcr |= ENET_RCR_RMII_10T(!crt_state.speed);
grzemich 0:d7bd7384a37c 560 ENET->RCR = rcr;
grzemich 0:d7bd7384a37c 561 }
grzemich 0:d7bd7384a37c 562
grzemich 0:d7bd7384a37c 563 prev_state = crt_state;
grzemich 0:d7bd7384a37c 564 osDelay(PHY_TASK_PERIOD_MS);
grzemich 0:d7bd7384a37c 565 }
grzemich 0:d7bd7384a37c 566 }
grzemich 0:d7bd7384a37c 567
grzemich 0:d7bd7384a37c 568 /**
grzemich 0:d7bd7384a37c 569 * Should be called at the beginning of the program to set up the
grzemich 0:d7bd7384a37c 570 * network interface.
grzemich 0:d7bd7384a37c 571 *
grzemich 0:d7bd7384a37c 572 * This function should be passed as a parameter to netif_add().
grzemich 0:d7bd7384a37c 573 *
grzemich 0:d7bd7384a37c 574 * @param[in] netif the lwip network interface structure for this netif
grzemich 0:d7bd7384a37c 575 * @return ERR_OK if the loopif is initialized
grzemich 0:d7bd7384a37c 576 * ERR_MEM if private data couldn't be allocated
grzemich 0:d7bd7384a37c 577 * any other err_t on error
grzemich 0:d7bd7384a37c 578 */
grzemich 0:d7bd7384a37c 579 err_t eth_arch_enetif_init(struct netif *netif)
grzemich 0:d7bd7384a37c 580 {
grzemich 0:d7bd7384a37c 581 err_t err;
grzemich 0:d7bd7384a37c 582
grzemich 0:d7bd7384a37c 583 LWIP_ASSERT("netif != NULL", (netif != NULL));
grzemich 0:d7bd7384a37c 584
grzemich 0:d7bd7384a37c 585 k64f_enetdata.netif = netif;
grzemich 0:d7bd7384a37c 586
grzemich 0:d7bd7384a37c 587 /* set MAC hardware address */
grzemich 0:d7bd7384a37c 588 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
grzemich 0:d7bd7384a37c 589 netif->hwaddr[0] = MBED_MAC_ADDR_0;
grzemich 0:d7bd7384a37c 590 netif->hwaddr[1] = MBED_MAC_ADDR_1;
grzemich 0:d7bd7384a37c 591 netif->hwaddr[2] = MBED_MAC_ADDR_2;
grzemich 0:d7bd7384a37c 592 netif->hwaddr[3] = MBED_MAC_ADDR_3;
grzemich 0:d7bd7384a37c 593 netif->hwaddr[4] = MBED_MAC_ADDR_4;
grzemich 0:d7bd7384a37c 594 netif->hwaddr[5] = MBED_MAC_ADDR_5;
grzemich 0:d7bd7384a37c 595 #else
grzemich 0:d7bd7384a37c 596 mbed_mac_address((char *)netif->hwaddr);
grzemich 0:d7bd7384a37c 597 #endif
grzemich 0:d7bd7384a37c 598 netif->hwaddr_len = ETHARP_HWADDR_LEN;
grzemich 0:d7bd7384a37c 599
grzemich 0:d7bd7384a37c 600 /* maximum transfer unit */
grzemich 0:d7bd7384a37c 601 netif->mtu = 1500;
grzemich 0:d7bd7384a37c 602
grzemich 0:d7bd7384a37c 603 /* device capabilities */
grzemich 0:d7bd7384a37c 604 // TODOETH: check if the flags are correct below
grzemich 0:d7bd7384a37c 605 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
grzemich 0:d7bd7384a37c 606
grzemich 0:d7bd7384a37c 607 /* Initialize the hardware */
grzemich 0:d7bd7384a37c 608 netif->state = &k64f_enetdata;
grzemich 0:d7bd7384a37c 609 err = low_level_init(netif);
grzemich 0:d7bd7384a37c 610 if (err != ERR_OK)
grzemich 0:d7bd7384a37c 611 return err;
grzemich 0:d7bd7384a37c 612
grzemich 0:d7bd7384a37c 613 #if LWIP_NETIF_HOSTNAME
grzemich 0:d7bd7384a37c 614 /* Initialize interface hostname */
grzemich 0:d7bd7384a37c 615 netif->hostname = "lwipk64f";
grzemich 0:d7bd7384a37c 616 #endif /* LWIP_NETIF_HOSTNAME */
grzemich 0:d7bd7384a37c 617
grzemich 0:d7bd7384a37c 618 netif->name[0] = 'e';
grzemich 0:d7bd7384a37c 619 netif->name[1] = 'n';
grzemich 0:d7bd7384a37c 620
grzemich 0:d7bd7384a37c 621 netif->output = k64f_etharp_output;
grzemich 0:d7bd7384a37c 622 netif->linkoutput = k64f_low_level_output;
grzemich 0:d7bd7384a37c 623
grzemich 0:d7bd7384a37c 624 /* CMSIS-RTOS, start tasks */
grzemich 0:d7bd7384a37c 625 #ifdef CMSIS_OS_RTX
grzemich 0:d7bd7384a37c 626 memset(k64f_enetdata.xTXDCountSem.data, 0, sizeof(k64f_enetdata.xTXDCountSem.data));
grzemich 0:d7bd7384a37c 627 k64f_enetdata.xTXDCountSem.def.semaphore = k64f_enetdata.xTXDCountSem.data;
grzemich 0:d7bd7384a37c 628 #endif
grzemich 0:d7bd7384a37c 629 k64f_enetdata.xTXDCountSem.id = osSemaphoreCreate(&k64f_enetdata.xTXDCountSem.def, ENET_TX_RING_LEN);
grzemich 0:d7bd7384a37c 630
grzemich 0:d7bd7384a37c 631 LWIP_ASSERT("xTXDCountSem creation error", (k64f_enetdata.xTXDCountSem.id != NULL));
grzemich 0:d7bd7384a37c 632
grzemich 0:d7bd7384a37c 633 err = sys_mutex_new(&k64f_enetdata.TXLockMutex);
grzemich 0:d7bd7384a37c 634 LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK));
grzemich 0:d7bd7384a37c 635
grzemich 0:d7bd7384a37c 636 /* Packet receive task */
grzemich 0:d7bd7384a37c 637 err = sys_sem_new(&k64f_enetdata.RxReadySem, 0);
grzemich 0:d7bd7384a37c 638 LWIP_ASSERT("RxReadySem creation error", (err == ERR_OK));
grzemich 0:d7bd7384a37c 639 sys_thread_new("receive_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY);
grzemich 0:d7bd7384a37c 640
grzemich 0:d7bd7384a37c 641 /* Transmit cleanup task */
grzemich 0:d7bd7384a37c 642 err = sys_sem_new(&k64f_enetdata.TxCleanSem, 0);
grzemich 0:d7bd7384a37c 643 LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK));
grzemich 0:d7bd7384a37c 644 sys_thread_new("txclean_thread", packet_tx, netif->state, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY);
grzemich 0:d7bd7384a37c 645
grzemich 0:d7bd7384a37c 646 /* PHY monitoring task */
grzemich 0:d7bd7384a37c 647 sys_thread_new("phy_thread", k64f_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY);
grzemich 0:d7bd7384a37c 648
grzemich 0:d7bd7384a37c 649 /* Allow the PHY task to detect the initial link state and set up the proper flags */
grzemich 0:d7bd7384a37c 650 osDelay(10);
grzemich 0:d7bd7384a37c 651
grzemich 0:d7bd7384a37c 652 return ERR_OK;
grzemich 0:d7bd7384a37c 653 }
grzemich 0:d7bd7384a37c 654
grzemich 0:d7bd7384a37c 655 void eth_arch_enable_interrupts(void) {
grzemich 0:d7bd7384a37c 656 //NVIC_SetPriority(ENET_Receive_IRQn, 6U);
grzemich 0:d7bd7384a37c 657 //NVIC_SetPriority(ENET_Transmit_IRQn, 6U);
grzemich 0:d7bd7384a37c 658 }
grzemich 0:d7bd7384a37c 659
grzemich 0:d7bd7384a37c 660 void eth_arch_disable_interrupts(void) {
grzemich 0:d7bd7384a37c 661
grzemich 0:d7bd7384a37c 662 }
grzemich 0:d7bd7384a37c 663
grzemich 0:d7bd7384a37c 664 /**
grzemich 0:d7bd7384a37c 665 * @}
grzemich 0:d7bd7384a37c 666 */
grzemich 0:d7bd7384a37c 667
grzemich 0:d7bd7384a37c 668 /* --------------------------------- End Of File ------------------------------ */
grzemich 0:d7bd7384a37c 669