| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lpc18xx_43xx_emac.c
Go to the documentation of this file.
1 /*
2 * @brief LPC18xx/43xx LWIP EMAC driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #include "lwip/opt.h"
33 #include "lwip/sys.h"
34 #include "lwip/def.h"
35 #include "lwip/mem.h"
36 #include "lwip/pbuf.h"
37 #include "lwip/stats.h"
38 #include "lwip/snmp.h"
39 #include "netif/etharp.h"
40 #include "netif/ppp_oe.h"
41
42 #include "lpc_18xx43xx_emac_config.h"
43 #include "lpc18xx_43xx_emac.h"
44
45 #include "chip.h"
46 #include "board.h"
47 #include "lpc_phy.h"
48
49 #include <string.h>
50
51 extern void msDelay(uint32_t ms);
52
53 #if LPC_NUM_BUFF_TXDESCS < 2
54 #error LPC_NUM_BUFF_TXDESCS must be at least 2
55 #endif
56
57 #if LPC_NUM_BUFF_RXDESCS < 3
58 #error LPC_NUM_BUFF_RXDESCS must be at least 3
59 #endif
60
61 #ifndef LPC_CHECK_SLOWMEM
62 #error LPC_CHECK_SLOWMEM must be 0 or 1
63 #endif
64
69 /*****************************************************************************
70 * Private types/enumerations/variables
71 ****************************************************************************/
72
73 #if NO_SYS == 0
74
80 #define tskTXCLEAN_PRIORITY (TCPIP_THREAD_PRIO - 1)
81 #define tskRECPKT_PRIORITY (TCPIP_THREAD_PRIO - 1)
82 #endif
83
91 // #define LOCK_RX_THREAD
92
93 /* LPC EMAC driver data structure */
94 struct lpc_enetdata {
95 struct netif *netif;
97 IP_ENET_001_ENHTXDESC_T ptdesc[LPC_NUM_BUFF_TXDESCS];
98 IP_ENET_001_ENHRXDESC_T prdesc[LPC_NUM_BUFF_RXDESCS];
99 struct pbuf *txpbufs[LPC_NUM_BUFF_TXDESCS];
101 volatile u32_t tx_free_descs;
102 u32_t tx_fill_idx;
103 u32_t tx_reclaim_idx;
104 struct pbuf *rxpbufs[LPC_NUM_BUFF_RXDESCS];
106 volatile u32_t rx_free_descs;
107 volatile u32_t rx_get_idx;
108 u32_t rx_next_idx;
109 #if NO_SYS == 0
110 sys_sem_t RxSem;
111 sys_sem_t TxCleanSem;
112 sys_mutex_t TXLockMutex;
113 xSemaphoreHandle xTXDCountSem;
114 #endif
115 };
116
117 /* LPC EMAC driver work data */
118 static struct lpc_enetdata lpc_enetdata;
119
120 static uint32_t intMask;
121
122 #if LPC_CHECK_SLOWMEM == 1
123 struct lpc_slowmem_array_t {
124 u32_t start;
125 u32_t end;
126 };
127
128 const static struct lpc_slowmem_array_t slmem[] = LPC_SLOWMEM_ARRAY;
129 #endif
130
131 /*****************************************************************************
132 * Public types/enumerations/variables
133 ****************************************************************************/
134
135 /*****************************************************************************
136 * Private functions
137 ****************************************************************************/
138
139 /* Queues a pbuf into a free RX descriptor */
140 static void lpc_rxqueue_pbuf(struct lpc_enetdata *lpc_netifdata,
141 struct pbuf *p)
142 {
143 u32_t idx = lpc_netifdata->rx_next_idx;
144
145 /* Save location of pbuf so we know what to pass to LWIP later */
146 lpc_netifdata->rxpbufs[idx] = p;
147
148 /* Buffer size and address for pbuf */
149 lpc_netifdata->prdesc[idx].CTRL = (u32_t) RDES_ENH_BS1(p->len) |
150 RDES_ENH_RCH;
151 if (idx == (LPC_NUM_BUFF_RXDESCS - 1)) {
152 lpc_netifdata->prdesc[idx].CTRL |= RDES_ENH_RER;
153 }
154 lpc_netifdata->prdesc[idx].B1ADD = (u32_t) p->payload;
155
156 /* Give descriptor to MAC/DMA */
157 lpc_netifdata->prdesc[idx].STATUS = RDES_OWN;
158
159 /* Update free count */
160 lpc_netifdata->rx_free_descs--;
161
162 LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
163 ("lpc_rxqueue_pbuf: Queueing packet %p at index %d, free %d\n",
164 p, idx, lpc_netifdata->rx_free_descs));
165
166 /* Update index for next pbuf */
167 idx++;
168 if (idx >= LPC_NUM_BUFF_RXDESCS) {
169 idx = 0;
170 }
171 lpc_netifdata->rx_next_idx = idx;
172 }
173
174 /* This function sets up the descriptor list used for receive packets */
175 static err_t lpc_rx_setup(struct lpc_enetdata *lpc_netifdata)
176 {
177 s32_t idx;
178
179 /* Set to start of list */
180 lpc_netifdata->rx_get_idx = 0;
181 lpc_netifdata->rx_next_idx = 0;
182 lpc_netifdata->rx_free_descs = LPC_NUM_BUFF_RXDESCS;
183
184 /* Clear initial RX descriptor list */
185 memset(lpc_netifdata->prdesc, 0, sizeof(lpc_netifdata->prdesc));
186
187 /* Setup buffer chaining before allocating pbufs for descriptors
188 just in case memory runs out. */
189 for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) {
190 lpc_netifdata->prdesc[idx].CTRL = RDES_ENH_RCH;
191 lpc_netifdata->prdesc[idx].B2ADD = (u32_t)
192 &lpc_netifdata->prdesc[idx + 1];
193 }
194 lpc_netifdata->prdesc[LPC_NUM_BUFF_RXDESCS - 1].CTRL =
195 RDES_ENH_RCH | RDES_ENH_RER;
196 lpc_netifdata->prdesc[LPC_NUM_BUFF_RXDESCS - 1].B2ADD =
197 (u32_t) &lpc_netifdata->prdesc[0];
198 LPC_ETHERNET->DMA_REC_DES_ADDR = (u32_t) lpc_netifdata->prdesc;
199
200 /* Setup up RX pbuf queue, but post a warning if not enough were
201 queued for all descriptors. */
202 if (lpc_rx_queue(lpc_netifdata->netif) != LPC_NUM_BUFF_RXDESCS) {
203 LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
204 ("lpc_rx_setup: Warning, not enough memory for RX pbufs\n"));
205 }
206
207 return ERR_OK;
208 }
209
210 /* Gets data from queue and forwards to LWIP */
211 static struct pbuf *lpc_low_level_input(struct netif *netif) {
212 struct lpc_enetdata *lpc_netifdata = netif->state;
213 u32_t status, ridx;
214 int rxerr = 0;
215 struct pbuf *p;
216
217 #ifdef LOCK_RX_THREAD
218 #if NO_SYS == 0
219 /* Get exclusive access */
220 sys_mutex_lock(&lpc_netifdata->TXLockMutex);
221 #endif
222 #endif
223
224 /* If there are no used descriptors, then this call was
225 not for a received packet, try to setup some descriptors now */
226 if (lpc_netifdata->rx_free_descs == LPC_NUM_BUFF_RXDESCS) {
227 lpc_rx_queue(netif);
228 #ifdef LOCK_RX_THREAD
229 #if NO_SYS == 0
230 sys_mutex_unlock(&lpc_netifdata->TXLockMutex);
231 #endif
232 #endif
233 return NULL;
234 }
235
236 /* Get index for next descriptor with data */
237 ridx = lpc_netifdata->rx_get_idx;
238
239 /* Return if descriptor is still owned by DMA */
240 if (lpc_netifdata->prdesc[ridx].STATUS & RDES_OWN) {
241 #ifdef LOCK_RX_THREAD
242 #if NO_SYS == 0
243 sys_mutex_unlock(&lpc_netifdata->TXLockMutex);
244 #endif
245 #endif
246 return NULL;
247 }
248
249 /* Get address of pbuf for this descriptor */
250 p = lpc_netifdata->rxpbufs[ridx];
251
252 /* Get receive packet status */
253 status = lpc_netifdata->prdesc[ridx].STATUS;
254
255 /* Check packet for errors */
256 if (status & RDES_ES) {
257 LINK_STATS_INC(link.drop);
258
259 /* Error conditions that cause a packet drop */
260 if (status & intMask) {
261 LINK_STATS_INC(link.err);
262 rxerr = 1;
263 }
264 else
265 /* Length error check needs qualification */
266 if ((status & (RDES_LE | RDES_FT)) == RDES_LE) {
267 LINK_STATS_INC(link.lenerr);
268 rxerr = 1;
269 }
270 else
271 /* CRC error check needs qualification */
272 if ((status & (RDES_CE | RDES_LS)) == (RDES_CE | RDES_LS)) {
273 LINK_STATS_INC(link.chkerr);
274 rxerr = 1;
275 }
276
277 /* Descriptor error check needs qualification */
278 if ((status & (RDES_DE | RDES_LS)) == (RDES_DE | RDES_LS)) {
279 LINK_STATS_INC(link.err);
280 rxerr = 1;
281 }
282 else
283 /* Dribble bit error only applies in half duplex mode */
284 if ((status & RDES_DE) &&
285 (!(LPC_ETHERNET->MAC_CONFIG & MAC_CFG_DM))) {
286 LINK_STATS_INC(link.err);
287 rxerr = 1;
288 }
289 }
290
291 /* Increment free descriptor count and next get index */
292 lpc_netifdata->rx_free_descs++;
293 ridx++;
294 if (ridx >= LPC_NUM_BUFF_RXDESCS) {
295 ridx = 0;
296 }
297 lpc_netifdata->rx_get_idx = ridx;
298
299 /* If an error occurred, just re-queue the pbuf */
300 if (rxerr) {
301 lpc_rxqueue_pbuf(lpc_netifdata, p);
302 p = NULL;
303
304 LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
305 ("lpc_low_level_input: RX error condition status 0x%08x\n",
306 status));
307 }
308 else {
309 /* Attempt to queue a new pbuf for the descriptor */
310 lpc_rx_queue(netif);
311
312 /* Get length of received packet */
313 p->len = p->tot_len = (u16_t) RDES_FLMSK(status);
314
315 LINK_STATS_INC(link.recv);
316
317 LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
318 ("lpc_low_level_input: Packet received, %d bytes, "
319 "status 0x%08x\n", p->len, status));
320 }
321
322 /* (Re)start receive polling */
323 LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;
324
325 #ifdef LOCK_RX_THREAD
326 #if NO_SYS == 0
327 /* Get exclusive access */
328 sys_mutex_unlock(&lpc_netifdata->TXLockMutex);
329 #endif
330 #endif
331
332 return p;
333 }
334
335 /* This function sets up the descriptor list used for transmit packets */
336 static err_t lpc_tx_setup(struct lpc_enetdata *lpc_netifdata)
337 {
338 s32_t idx;
339
340 /* Clear TX descriptors, will be queued with pbufs as needed */
341 memset((void *) &lpc_netifdata->ptdesc[0], 0, sizeof(lpc_netifdata->ptdesc));
342 lpc_netifdata->tx_free_descs = LPC_NUM_BUFF_TXDESCS;
343 lpc_netifdata->tx_fill_idx = 0;
344 lpc_netifdata->tx_reclaim_idx = 0;
345
346 /* Link/wrap descriptors */
347 for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) {
348 lpc_netifdata->ptdesc[idx].CTRLSTAT = TDES_ENH_TCH | TDES_ENH_CIC(3);
349 lpc_netifdata->ptdesc[idx].B2ADD =
350 (u32_t) &lpc_netifdata->ptdesc[idx + 1];
351 }
352 lpc_netifdata->ptdesc[LPC_NUM_BUFF_TXDESCS - 1].CTRLSTAT =
353 TDES_ENH_TCH | TDES_ENH_TER | TDES_ENH_CIC(3);
354 lpc_netifdata->ptdesc[LPC_NUM_BUFF_TXDESCS - 1].B2ADD =
355 (u32_t) &lpc_netifdata->ptdesc[0];
356
357 /* Setup pointer to TX descriptor table */
358 LPC_ETHERNET->DMA_TRANS_DES_ADDR = (u32_t) lpc_netifdata->ptdesc;
359
360 return ERR_OK;
361 }
362
363 /* Low level output of a packet. Never call this from an interrupt context,
364 as it may block until TX descriptors become available */
365 static err_t lpc_low_level_output(struct netif *netif, struct pbuf *sendp)
366 {
367 struct lpc_enetdata *lpc_netifdata = netif->state;
368 u32_t idx, fidx, dn;
369 struct pbuf *p = sendp;
370
371 #if LPC_CHECK_SLOWMEM == 1
372 struct pbuf *q, *wp;
373
374 u8_t *dst;
375 int pcopy = 0;
376
377 /* Check packet address to determine if it's in slow memory and
378 relocate if necessary */
379 for (q = p; ((q != NULL) && (pcopy == 0)); q = q->next) {
380 fidx = 0;
381 for (idx = 0; idx < sizeof(slmem);
382 idx += sizeof(struct lpc_slowmem_array_t)) {
383 if ((q->payload >= (void *) slmem[fidx].start) &&
384 (q->payload <= (void *) slmem[fidx].end)) {
385 /* Needs copy */
386 pcopy = 1;
387 }
388 }
389 }
390
391 if (pcopy) {
392 /* Create a new pbuf with the total pbuf size */
393 wp = pbuf_alloc(PBUF_RAW, (u16_t) EMAC_ETH_MAX_FLEN, PBUF_RAM);
394 if (!wp) {
395 /* Exit with error */
396 return ERR_MEM;
397 }
398
399 /* Copy pbuf */
400 dst = (u8_t *) wp->payload;
401 wp->tot_len = 0;
402 for (q = p; q != NULL; q = q->next) {
403 MEMCPY(dst, (u8_t *) q->payload, q->len);
404 dst += q->len;
405 wp->tot_len += q->len;
406 }
407 wp->len = wp->tot_len;
408
409 /* LWIP will free original pbuf on exit of function */
410
411 p = sendp = wp;
412 }
413 #endif
414
415 /* Zero-copy TX buffers may be fragmented across mutliple payload
416 chains. Determine the number of descriptors needed for the
417 transfer. The pbuf chaining can be a mess! */
418 dn = (u32_t) pbuf_clen(p);
419
420 /* Wait until enough descriptors are available for the transfer. */
421 /* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */
422 while (dn > lpc_tx_ready(netif))
423 #if NO_SYS == 0
424 {xSemaphoreTake(lpc_netifdata->xTXDCountSem, 0); }
425 #else
426 {msDelay(1); }
427 #endif
428
429 /* Get the next free descriptor index */
430 fidx = idx = lpc_netifdata->tx_fill_idx;
431
432 #if NO_SYS == 0
433 /* Get exclusive access */
434 sys_mutex_lock(&lpc_netifdata->TXLockMutex);
435 #endif
436
437 /* Fill in the next free descriptor(s) */
438 while (dn > 0) {
439 dn--;
440
441 /* Setup packet address and length */
442 lpc_netifdata->ptdesc[idx].B1ADD = (u32_t) p->payload;
443 lpc_netifdata->ptdesc[idx].BSIZE = (u32_t) TDES_ENH_BS1(p->len);
444
445 /* Save pointer to pbuf so we can reclain the memory for
446 the pbuf after the buffer has been sent. Only the first
447 pbuf in a chain is saved since the full chain doesn't
448 need to be freed. */
449 /* For first packet only, first flag */
450 lpc_netifdata->tx_free_descs--;
451 if (idx == fidx) {
452 lpc_netifdata->ptdesc[idx].CTRLSTAT |= TDES_ENH_FS;
453 #if LPC_CHECK_SLOWMEM == 1
454 /* If this is a copied pbuf, then avoid getting the extra reference
455 or the TX reclaim will be off by 1 */
456 if (!pcopy) {
457 pbuf_ref(p);
458 }
459 #else
460 /* Increment reference count on this packet so LWIP doesn't
461 attempt to free it on return from this call */
462 pbuf_ref(p);
463 #endif
464 }
465 else {
466 lpc_netifdata->ptdesc[idx].CTRLSTAT |= TDES_OWN;
467 }
468
469 /* Save address of pbuf, but make sure it's associated with the
470 first chained pbuf so it gets freed once all pbuf chains are
471 transferred. */
472 if (!dn) {
473 lpc_netifdata->txpbufs[idx] = sendp;
474 }
475 else {
476 lpc_netifdata->txpbufs[idx] = NULL;
477 }
478
479 /* For last packet only, interrupt and last flag */
480 if (dn == 0) {
481 lpc_netifdata->ptdesc[idx].CTRLSTAT |= TDES_ENH_LS |
482 TDES_ENH_IC;
483 }
484
485 /* IP checksumming requires full buffering in IP */
486 lpc_netifdata->ptdesc[idx].CTRLSTAT |= TDES_ENH_CIC(3);
487
488 LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
489 ("lpc_low_level_output: pbuf packet %p sent, chain %d,"
490 " size %d, index %d, free %d\n", p, dn, p->len, idx,
491 lpc_netifdata->tx_free_descs));
492
493 /* Update next available descriptor */
494 idx++;
495 if (idx >= LPC_NUM_BUFF_TXDESCS) {
496 idx = 0;
497 }
498
499 /* Next packet fragment */
500 p = p->next;
501 }
502
503 lpc_netifdata->tx_fill_idx = idx;
504
505 LINK_STATS_INC(link.xmit);
506
507 /* Give first descriptor to DMA to start transfer */
508 lpc_netifdata->ptdesc[fidx].CTRLSTAT |= TDES_OWN;
509
510 /* Tell DMA to poll descriptors to start transfer */
511 LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;
512
513 #if NO_SYS == 0
514 /* Restore access */
515 sys_mutex_unlock(&lpc_netifdata->TXLockMutex);
516 #endif
517
518 return ERR_OK;
519 }
520
521 /* This function is the ethernet packet send function. It calls
522 etharp_output after checking link status */
523 static err_t lpc_etharp_output(struct netif *netif, struct pbuf *q,
524 ip_addr_t *ipaddr)
525 {
526 /* Only send packet is link is up */
527 if (netif->flags & NETIF_FLAG_LINK_UP) {
528 return etharp_output(netif, q, ipaddr);
529 }
530
531 return ERR_CONN;
532 }
533
534 #if NO_SYS == 0
535 /* Packet reception task
536 This task is called when a packet is received. It will
537 pass the packet to the LWIP core */
538 static portTASK_FUNCTION(vPacketReceiveTask, pvParameters) {
539 struct lpc_enetdata *lpc_netifdata = pvParameters;
540
541 while (1) {
542 /* Wait for receive task to wakeup */
543 sys_arch_sem_wait(&lpc_netifdata->RxSem, 0);
544
545 /* Process receive packets */
546 while (!(lpc_netifdata->prdesc[lpc_netifdata->rx_get_idx].STATUS
547 & RDES_OWN)) {
548 lpc_enetif_input(lpc_netifdata->netif);
549 }
550 }
551 }
552
553 /* Transmit cleanup task
554 This task is called when a transmit interrupt occurs and
555 reclaims the pbuf and descriptor used for the packet once
556 the packet has been transferred */
557 static portTASK_FUNCTION(vTransmitCleanupTask, pvParameters) {
558 struct lpc_enetdata *lpc_netifdata = pvParameters;
559
560 while (1) {
561 /* Wait for transmit cleanup task to wakeup */
562 sys_arch_sem_wait(&lpc_netifdata->TxCleanSem, 0);
563
564 /* Free TX pbufs and descriptors that are done */
565 lpc_tx_reclaim(lpc_netifdata->netif);
566 }
567 }
568 #endif
569
570 /* Low level init of the MAC and PHY */
571 static err_t low_level_init(struct netif *netif)
572 {
573 struct lpc_enetdata *lpc_netifdata = netif->state;
574
575 /* Initialize via Chip ENET function */
576 Chip_ENET_Init(LPC_ETHERNET);
577
578 /* Save MAC address */
579 Chip_ENET_SetADDR(LPC_ETHERNET, netif->hwaddr);
580
581 /* Initial MAC configuration for checksum offload, full duplex,
582 100Mbps, disable receive own in half duplex, inter-frame gap
583 of 64-bits */
584 LPC_ETHERNET->MAC_CONFIG = MAC_CFG_BL(0) | MAC_CFG_IPC | MAC_CFG_DM |
585 MAC_CFG_DO | MAC_CFG_FES | MAC_CFG_PS | MAC_CFG_IFG(3);
586
587 /* Setup filter */
588 #if IP_SOF_BROADCAST_RECV
589 LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FF_PR | MAC_FF_RA;
590 #else
591 LPC_ETHERNET->MAC_FRAME_FILTER = 0; /* Only matching MAC address */
592 #endif
593
594 /* Initialize the PHY */
595 #if defined(USE_RMII)
596 if (lpc_phy_init(true, msDelay) != SUCCESS) {
597 return ERROR;
598 }
599
600 intMask = RDES_CE | RDES_DE | RDES_RE | RDES_RWT | RDES_LC | RDES_OE |
601 RDES_SAF | RDES_AFM;
602 #else
603 if (lpc_phy_init(false, msDelay) != SUCCESS) {
604 return ERROR;
605 }
606
607 intMask = RDES_CE | RDES_RE | RDES_RWT | RDES_LC | RDES_OE | RDES_SAF |
608 RDES_AFM;
609 #endif
610
611 /* Setup transmit and receive descriptors */
612 if (lpc_tx_setup(lpc_netifdata) != ERR_OK) {
613 return ERR_BUF;
614 }
615 if (lpc_rx_setup(lpc_netifdata) != ERR_OK) {
616 return ERR_BUF;
617 }
618
619 /* Flush transmit FIFO */
620 LPC_ETHERNET->DMA_OP_MODE = DMA_OM_FTF;
621
622 /* Setup DMA to flush receive FIFOs at 32 bytes, service TX FIFOs at
623 64 bytes */
624 LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_RTC(1) | DMA_OM_TTC(0);
625
626 /* Clear all MAC interrupts */
627 LPC_ETHERNET->DMA_STAT = DMA_ST_ALL;
628
629 /* Enable MAC interrupts */
630 LPC_ETHERNET->DMA_INT_EN =
631 #if NO_SYS == 1
632 0;
633 #else
634 DMA_IE_TIE | DMA_IE_OVE | DMA_IE_UNE | DMA_IE_RIE | DMA_IE_NIE |
635 DMA_IE_AIE | DMA_IE_TUE | DMA_IE_RUE;
636 #endif
637
638 /* Enable receive and transmit DMA processes */
639 LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_ST | DMA_OM_SR;
640
641 /* Enable packet reception */
642 LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE;
643
644 /* Start receive polling */
645 LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;
646
647 return ERR_OK;
648 }
649
650 /*****************************************************************************
651 * Public functions
652 ****************************************************************************/
653 /* Attempt to allocate and requeue a new pbuf for RX */
654 s32_t lpc_rx_queue(struct netif *netif)
655 {
656 struct lpc_enetdata *lpc_netifdata = netif->state;
657 struct pbuf *p;
658
659 s32_t queued = 0;
660
661 /* Attempt to requeue as many packets as possible */
662 while (lpc_netifdata->rx_free_descs > 0) {
663 /* Allocate a pbuf from the pool. We need to allocate at the
664 maximum size as we don't know the size of the yet to be
665 received packet. */
666 p = pbuf_alloc(PBUF_RAW, (u16_t) EMAC_ETH_MAX_FLEN, PBUF_RAM);
667 if (p == NULL) {
668 LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
669 ("lpc_rx_queue: could not allocate RX pbuf index %d, "
670 "free %d)\n", lpc_netifdata->rx_next_idx,
671 lpc_netifdata->rx_free_descs));
672 return queued;
673 }
674
675 /* pbufs allocated from the RAM pool should be non-chained (although
676 the hardware will allow chaining) */
677 LWIP_ASSERT("lpc_rx_queue: pbuf is not contiguous (chained)",
678 pbuf_clen(p) <= 1);
679
680 /* Queue packet */
681 lpc_rxqueue_pbuf(lpc_netifdata, p);
682
683 /* Update queued count */
684 queued++;
685 }
686
687 return queued;
688 }
689
690 /* Attempt to read a packet from the EMAC interface */
691 void lpc_enetif_input(struct netif *netif)
692 {
693 struct eth_hdr *ethhdr;
694
695 struct pbuf *p;
696
697 /* move received packet into a new pbuf */
698 p = lpc_low_level_input(netif);
699 if (p == NULL) {
700 return;
701 }
702
703 /* points to packet payload, which starts with an Ethernet header */
704 ethhdr = p->payload;
705
706 switch (htons(ethhdr->type)) {
707 case ETHTYPE_IP:
708 case ETHTYPE_ARP:
709 #if PPPOE_SUPPORT
710 case ETHTYPE_PPPOEDISC:
711 case ETHTYPE_PPPOE:
712 #endif /* PPPOE_SUPPORT */
713 /* full packet send to tcpip_thread to process */
714 if (netif->input(p, netif) != ERR_OK) {
715 LWIP_DEBUGF(NETIF_DEBUG,
716 ("lpc_enetif_input: IP input error\n"));
717 /* Free buffer */
718 pbuf_free(p);
719 }
720 break;
721
722 default:
723 /* Return buffer */
724 pbuf_free(p);
725 break;
726 }
727 }
728
729 /* Call for freeing TX buffers that are complete */
730 void lpc_tx_reclaim(struct netif *netif)
731 {
732 struct lpc_enetdata *lpc_netifdata = netif->state;
733 s32_t ridx;
734 u32_t status;
735
736 #if NO_SYS == 0
737 /* Get exclusive access */
738 sys_mutex_lock(&lpc_netifdata->TXLockMutex);
739 #endif
740
741 /* If a descriptor is available and is no longer owned by the
742 hardware, it can be reclaimed */
743 ridx = lpc_netifdata->tx_reclaim_idx;
744 while ((lpc_netifdata->tx_free_descs < LPC_NUM_BUFF_TXDESCS) &&
745 (!(lpc_netifdata->ptdesc[ridx].CTRLSTAT & TDES_OWN))) {
746 /* Peek at the status of the descriptor to determine if the
747 packet is good and any status information. */
748 status = lpc_netifdata->ptdesc[ridx].CTRLSTAT;
749
750 LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
751 ("lpc_tx_reclaim: Reclaiming sent packet %p, index %d\n",
752 lpc_netifdata->txpbufs[ridx], ridx));
753
754 /* Check TX error conditions */
755 if (status & TDES_ES) {
756 LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
757 ("lpc_tx_reclaim: TX error condition status 0x%x\n", status));
758 LINK_STATS_INC(link.err);
759
760 #if LINK_STATS == 1
761 /* Error conditions that cause a packet drop */
762 if (status & (TDES_UF | TDES_ED | TDES_EC | TDES_LC)) {
763 LINK_STATS_INC(link.drop);
764 }
765 #endif
766 }
767
768 /* Reset control for this descriptor */
769 if (ridx == (LPC_NUM_BUFF_TXDESCS - 1)) {
770 lpc_netifdata->ptdesc[ridx].CTRLSTAT = TDES_ENH_TCH |
771 TDES_ENH_TER;
772 }
773 else {
774 lpc_netifdata->ptdesc[ridx].CTRLSTAT = TDES_ENH_TCH;
775 }
776
777 /* Free the pbuf associate with this descriptor */
778 if (lpc_netifdata->txpbufs[ridx]) {
779 pbuf_free(lpc_netifdata->txpbufs[ridx]);
780 }
781
782 /* Reclaim this descriptor */
783 lpc_netifdata->tx_free_descs++;
784 #if NO_SYS == 0
785 xSemaphoreGive(lpc_netifdata->xTXDCountSem);
786 #endif
787 ridx++;
788 if (ridx >= LPC_NUM_BUFF_TXDESCS) {
789 ridx = 0;
790 }
791 }
792
793 lpc_netifdata->tx_reclaim_idx = ridx;
794
795 #if NO_SYS == 0
796 /* Restore access */
797 sys_mutex_unlock(&lpc_netifdata->TXLockMutex);
798 #endif
799 }
800
801 /* Polls if an available TX descriptor is ready */
802 s32_t lpc_tx_ready(struct netif *netif)
803 {
804 return ((struct lpc_enetdata *) netif->state)->tx_free_descs;
805 }
806
813 void ETH_IRQHandler(void)
814 {
815 #if NO_SYS == 1
816 /* Interrupts are not used without an RTOS */
817 NVIC_DisableIRQ((IRQn_Type) ETHERNET_IRQn);
818 #else
819 signed portBASE_TYPE xRecTaskWoken = pdFALSE, XTXTaskWoken = pdFALSE;
820 uint32_t ints;
821
822 /* Get pending interrupts */
823 ints = LPC_ETHERNET->DMA_STAT;
824
825 /* RX group interrupt(s) */
826 if (ints & (DMA_ST_RI | DMA_ST_OVF | DMA_ST_RU)) {
827 /* Give semaphore to wakeup RX receive task. Note the FreeRTOS
828 method is used instead of the LWIP arch method. */
829 xSemaphoreGiveFromISR(lpc_enetdata.RxSem, &xRecTaskWoken);
830 }
831
832 /* TX group interrupt(s) */
833 if (ints & (DMA_ST_TI | DMA_ST_UNF | DMA_ST_TU)) {
834 /* Give semaphore to wakeup TX cleanup task. Note the FreeRTOS
835 method is used instead of the LWIP arch method. */
836 xSemaphoreGiveFromISR(lpc_enetdata.TxCleanSem, &XTXTaskWoken);
837 }
838
839 /* Clear pending interrupts */
840 LPC_ETHERNET->DMA_STAT = ints;
841
842 /* Context switch needed? */
843 portEND_SWITCHING_ISR(xRecTaskWoken || XTXTaskWoken);
844 #endif
845 }
846
847 /* Set up the MAC interface duplex */
848 void lpc_emac_set_duplex(int full_duplex)
849 {
850 if (full_duplex) {
851 LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_DM;
852 }
853 else {
854 LPC_ETHERNET->MAC_CONFIG &= ~MAC_CFG_DM;
855 }
856 }
857
858 /* Set up the MAC interface speed */
859 void lpc_emac_set_speed(int mbs_100)
860 {
861 if (mbs_100) {
862 LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_FES;
863 }
864 else {
865 LPC_ETHERNET->MAC_CONFIG &= ~MAC_CFG_FES;
866 }
867 }
868
869 /* LWIP 18xx/43xx EMAC initialization function */
870 err_t lpc_enetif_init(struct netif *netif)
871 {
872 err_t err;
873 extern void Board_ENET_GetMacADDR(u8_t *mcaddr);
874
875 LWIP_ASSERT("netif != NULL", (netif != NULL));
876
877 lpc_enetdata.netif = netif;
878
879 /* set MAC hardware address */
880 Board_ENET_GetMacADDR(netif->hwaddr);
881 netif->hwaddr_len = ETHARP_HWADDR_LEN;
882
883 /* maximum transfer unit */
884 netif->mtu = 1500;
885
886 /* device capabilities */
887 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_UP |
888 NETIF_FLAG_ETHERNET;
889
890 /* Initialize the hardware */
891 netif->state = &lpc_enetdata;
892 err = low_level_init(netif);
893 if (err != ERR_OK) {
894 return err;
895 }
896
897 #if LWIP_NETIF_HOSTNAME
898 /* Initialize interface hostname */
899 netif->hostname = "lwiplpc";
900 #endif /* LWIP_NETIF_HOSTNAME */
901
902 netif->name[0] = 'e';
903 netif->name[1] = 'n';
904
905 netif->output = lpc_etharp_output;
906 netif->linkoutput = lpc_low_level_output;
907
908 /* For FreeRTOS, start tasks */
909 #if NO_SYS == 0
910 lpc_enetdata.xTXDCountSem = xSemaphoreCreateCounting(LPC_NUM_BUFF_TXDESCS,
911 LPC_NUM_BUFF_TXDESCS);
912 LWIP_ASSERT("xTXDCountSem creation error",
913 (lpc_enetdata.xTXDCountSem != NULL));
914
915 err = sys_mutex_new(&lpc_enetdata.TXLockMutex);
916 LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK));
917
918 /* Packet receive task */
919 err = sys_sem_new(&lpc_enetdata.RxSem, 0);
920 LWIP_ASSERT("RxSem creation error", (err == ERR_OK));
921 sys_thread_new("receive_thread", vPacketReceiveTask, netif->state,
922 DEFAULT_THREAD_STACKSIZE, tskRECPKT_PRIORITY);
923
924 /* Transmit cleanup task */
925 err = sys_sem_new(&lpc_enetdata.TxCleanSem, 0);
926 LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK));
927 sys_thread_new("txclean_thread", vTransmitCleanupTask, netif->state,
928 DEFAULT_THREAD_STACKSIZE, tskTXCLEAN_PRIORITY);
929 #endif
930
931 return ERR_OK;
932 }
933