lpc43xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file lpc43xx_eth_driver.c
3  * @brief LPC4300 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.8
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "lpc43xx.h"
36 #include "core/net.h"
38 #include "debug.h"
39 
40 //Underlying network interface
41 static NetInterface *nicDriverInterface;
42 
43 //IAR EWARM compiler?
44 #if defined(__ICCARM__)
45 
46 //Transmit buffer
47 #pragma data_alignment = 4
49 //Receive buffer
50 #pragma data_alignment = 4
52 //Transmit DMA descriptors
53 #pragma data_alignment = 4
55 //Receive DMA descriptors
56 #pragma data_alignment = 4
58 
59 //ARM or GCC compiler?
60 #else
61 
62 //Transmit buffer
64  __attribute__((aligned(4)));
65 //Receive buffer
67  __attribute__((aligned(4)));
68 //Transmit DMA descriptors
70  __attribute__((aligned(4)));
71 //Receive DMA descriptors
73  __attribute__((aligned(4)));
74 
75 #endif
76 
77 //Pointer to the current TX DMA descriptor
78 static Lpc43xxTxDmaDesc *txCurDmaDesc;
79 //Pointer to the current RX DMA descriptor
80 static Lpc43xxRxDmaDesc *rxCurDmaDesc;
81 
82 
83 /**
84  * @brief LPC43xx Ethernet MAC driver
85  **/
86 
88 {
90  ETH_MTU,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief LPC43xx Ethernet MAC initialization
110  * @param[in] interface Underlying network interface
111  * @return Error code
112  **/
113 
115 {
116  error_t error;
117 
118  //Debug message
119  TRACE_INFO("Initializing LPC43xx Ethernet MAC...\r\n");
120 
121  //Save underlying network interface
122  nicDriverInterface = interface;
123 
124  //Enable Ethernet peripheral clock
125  LPC_CCU1->CLK_M4_ETHERNET_CFG |= CCU1_CLK_M4_ETHERNET_CFG_RUN_Msk;
126  //Wait for completion
127  while((LPC_CCU1->CLK_M4_ETHERNET_STAT & CCU1_CLK_M4_ETHERNET_STAT_RUN_Msk) == 0)
128  {
129  }
130 
131  //Reset DMA
132  LPC_RGU->RESET_EXT_STAT19 |= RGU_RESET_EXT_STAT19_MASTER_RESET_Msk;
133  LPC_RGU->RESET_EXT_STAT19 &= ~RGU_RESET_EXT_STAT19_MASTER_RESET_Msk;
134 
135  //Reset Ethernet peripheral
136  LPC_RGU->RESET_EXT_STAT22 |= RGU_RESET_EXT_STAT22_MASTER_RESET_Msk;
137  LPC_RGU->RESET_EXT_STAT22 &= ~RGU_RESET_EXT_STAT22_MASTER_RESET_Msk;
138 
139  //GPIO configuration
140  lpc43xxEthInitGpio(interface);
141 
142  //Reset Ethernet peripheral
143  LPC_RGU->RESET_CTRL0 = RGU_RESET_CTRL0_ETHERNET_RST_Msk;
144  //Wait for the reset to complete
145  while((LPC_RGU->RESET_ACTIVE_STATUS0 & RGU_RESET_ACTIVE_STATUS0_ETHERNET_RST_Msk) == 0)
146  {
147  }
148 
149  //Perform a software reset
150  LPC_ETHERNET->DMA_BUS_MODE |= ETHERNET_DMA_BUS_MODE_SWR_Msk;
151  //Wait for the reset to complete
152  while((LPC_ETHERNET->DMA_BUS_MODE & ETHERNET_DMA_BUS_MODE_SWR_Msk) != 0)
153  {
154  }
155 
156  //Adjust MDC clock range
157  LPC_ETHERNET->MAC_MII_ADDR = ETHERNET_MAC_MII_ADDR_CR_DIV62;
158 
159  //Valid Ethernet PHY or switch driver?
160  if(interface->phyDriver != NULL)
161  {
162  //Ethernet PHY initialization
163  error = interface->phyDriver->init(interface);
164  }
165  else if(interface->switchDriver != NULL)
166  {
167  //Ethernet switch initialization
168  error = interface->switchDriver->init(interface);
169  }
170  else
171  {
172  //The interface is not properly configured
173  error = ERROR_FAILURE;
174  }
175 
176  //Any error to report?
177  if(error)
178  {
179  return error;
180  }
181 
182  //Use default MAC configuration
183  LPC_ETHERNET->MAC_CONFIG = ETHERNET_MAC_CONFIG_DO_Msk;
184 
185  //Set the MAC address of the station
186  LPC_ETHERNET->MAC_ADDR0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
187  LPC_ETHERNET->MAC_ADDR0_HIGH = interface->macAddr.w[2];
188 
189  //Initialize hash table
190  LPC_ETHERNET->MAC_HASHTABLE_LOW = 0;
191  LPC_ETHERNET->MAC_HASHTABLE_HIGH = 0;
192 
193  //Configure the receive filter
194  LPC_ETHERNET->MAC_FRAME_FILTER = ETHERNET_MAC_FRAME_FILTER_HPF_Msk |
195  ETHERNET_MAC_FRAME_FILTER_HMC_Msk;
196 
197  //Disable flow control
198  LPC_ETHERNET->MAC_FLOW_CTRL = 0;
199  //Set the threshold level of the transmit and receive FIFOs
200  LPC_ETHERNET->DMA_OP_MODE = ETHERNET_DMA_OP_MODE_TTC_64 | ETHERNET_DMA_OP_MODE_RTC_32;
201 
202  //Configure DMA bus mode
203  LPC_ETHERNET->DMA_BUS_MODE = ETHERNET_DMA_BUS_MODE_AAL_Msk | ETHERNET_DMA_BUS_MODE_USP_Msk |
205  ETHERNET_DMA_BUS_MODE_PBL_1 | ETHERNET_DMA_BUS_MODE_ATDS_Msk;
206 
207  //Initialize DMA descriptor lists
208  lpc43xxEthInitDmaDesc(interface);
209 
210  //Disable MAC interrupts
211  LPC_ETHERNET->MAC_INTR_MASK = ETHERNET_MAC_INTR_MASK_TSIM_Msk |
212  ETHERNET_MAC_INTR_MASK_PMTIM_Msk;
213 
214  //Enable the desired DMA interrupts
215  LPC_ETHERNET->DMA_INT_EN = ETHERNET_DMA_INT_EN_NIE_Msk |
216  ETHERNET_DMA_INT_EN_AIE_Msk | ETHERNET_DMA_INT_EN_RIE_Msk |
217  ETHERNET_DMA_INT_EN_OVE_Msk | ETHERNET_DMA_INT_EN_TIE_Msk |
218  ETHERNET_DMA_INT_EN_UNE_Msk;
219 
220  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
221  NVIC_SetPriorityGrouping(LPC43XX_ETH_IRQ_PRIORITY_GROUPING);
222 
223  //Configure Ethernet interrupt priority
224  NVIC_SetPriority(ETHERNET_IRQn, NVIC_EncodePriority(LPC43XX_ETH_IRQ_PRIORITY_GROUPING,
226 
227  //Enable MAC transmission and reception
228  LPC_ETHERNET->MAC_CONFIG |= ETHERNET_MAC_CONFIG_TE_Msk | ETHERNET_MAC_CONFIG_RE_Msk;
229  //Enable DMA transmission and reception
230  LPC_ETHERNET->DMA_OP_MODE |= ETHERNET_DMA_OP_MODE_ST_Msk | ETHERNET_DMA_OP_MODE_SR_Msk;
231 
232  //Accept any packets from the upper layer
233  osSetEvent(&interface->nicTxEvent);
234 
235  //Successful initialization
236  return NO_ERROR;
237 }
238 
239 
240 //LPC4330-Xplorer or LPCXpresso4337 evaluation board?
241 #if defined(USE_LPC4330_XPLORER) || defined(USE_LPCXPRESSO_4337)
242 
243 /**
244  * @brief GPIO configuration
245  * @param[in] interface Underlying network interface
246  **/
247 
248 void lpc43xxEthInitGpio(NetInterface *interface)
249 {
250  //Enable GPIO peripheral clock
251  LPC_CCU1->CLK_M4_GPIO_CFG |= CCU1_CLK_M4_GPIO_CFG_RUN_Msk;
252  //Wait for completion
253  while((LPC_CCU1->CLK_M4_GPIO_STAT & CCU1_CLK_M4_GPIO_STAT_RUN_Msk) == 0)
254  {
255  }
256 
257  //Select RMII operation mode
258  LPC_CREG->CREG6 &= ~CREG_CREG6_ETHMODE_Msk;
259  LPC_CREG->CREG6 |= CREG6_ETHMODE_RMII;
260 
261  //Configure P0.0 (ENET_RXD1)
262  LPC_SCU->SFSP0_0 = SCU_SFSP0_0_EZI_Msk | SCU_SFSP0_0_EHS_Msk | (2 & SCU_SFSP0_0_MODE_Msk);
263  //Configure P0.1 (ENET_TX_EN)
264  LPC_SCU->SFSP0_1 = SCU_SFSP0_1_EHS_Msk | (6 & SCU_SFSP0_1_MODE_Msk);
265 
266  //Configure P1.15 (ENET_RXD0)
267  LPC_SCU->SFSP1_15 = SCU_SFSP1_15_EZI_Msk | SCU_SFSP1_15_EHS_Msk | (3 & SCU_SFSP1_15_MODE_Msk);
268  //Configure P1.16 (ENET_RX_DV)
269  LPC_SCU->SFSP1_16 = SCU_SFSP1_16_EZI_Msk | SCU_SFSP1_16_EHS_Msk | (7 & SCU_SFSP1_16_MODE_Msk);
270  //Configure P1.17 (ENET_MDIO)
271  LPC_SCU->SFSP1_17 = SCU_SFSP1_17_EZI_Msk | (3 & SCU_SFSP1_17_MODE_Msk);
272  //Configure P1.18 (ENET_TXD0)
273  LPC_SCU->SFSP1_18 = SCU_SFSP1_18_EHS_Msk | (3 & SCU_SFSP1_18_MODE_Msk);
274  //Configure P1.19 (ENET_REF_CLK)
275  LPC_SCU->SFSP1_19 = SCU_SFSP1_19_EZI_Msk | SCU_SFSP1_19_EHS_Msk | (0 & SCU_SFSP1_19_MODE_Msk);
276  //Configure P1.20 (ENET_TXD1)
277  LPC_SCU->SFSP1_20 = SCU_SFSP1_20_EHS_Msk | (3 & SCU_SFSP1_20_MODE_Msk);
278 
279  //Configure P2.0 (ENET_MDC)
280  LPC_SCU->SFSP2_0 = (7 & SCU_SFSP2_0_MODE_Msk);
281 }
282 
283 #endif
284 
285 
286 /**
287  * @brief Initialize DMA descriptor lists
288  * @param[in] interface Underlying network interface
289  **/
290 
292 {
293  uint_t i;
294 
295  //Initialize TX DMA descriptor list
296  for(i = 0; i < LPC43XX_ETH_TX_BUFFER_COUNT; i++)
297  {
298  //Use chain structure rather than ring structure
299  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
300  //Initialize transmit buffer size
301  txDmaDesc[i].tdes1 = 0;
302  //Transmit buffer address
303  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
304  //Next descriptor address
305  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
306  //Reserved fields
307  txDmaDesc[i].tdes4 = 0;
308  txDmaDesc[i].tdes5 = 0;
309  //Transmit frame time stamp
310  txDmaDesc[i].tdes6 = 0;
311  txDmaDesc[i].tdes7 = 0;
312  }
313 
314  //The last descriptor is chained to the first entry
315  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
316  //Point to the very first descriptor
317  txCurDmaDesc = &txDmaDesc[0];
318 
319  //Initialize RX DMA descriptor list
320  for(i = 0; i < LPC43XX_ETH_RX_BUFFER_COUNT; i++)
321  {
322  //The descriptor is initially owned by the DMA
323  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
324  //Use chain structure rather than ring structure
326  //Receive buffer address
327  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
328  //Next descriptor address
329  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
330  //Extended status
331  rxDmaDesc[i].rdes4 = 0;
332  //Reserved field
333  rxDmaDesc[i].rdes5 = 0;
334  //Receive frame time stamp
335  rxDmaDesc[i].rdes6 = 0;
336  rxDmaDesc[i].rdes7 = 0;
337  }
338 
339  //The last descriptor is chained to the first entry
340  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
341  //Point to the very first descriptor
342  rxCurDmaDesc = &rxDmaDesc[0];
343 
344  //Start location of the TX descriptor list
345  LPC_ETHERNET->DMA_TRANS_DES_ADDR = (uint32_t) txDmaDesc;
346  //Start location of the RX descriptor list
347  LPC_ETHERNET->DMA_REC_DES_ADDR = (uint32_t) rxDmaDesc;
348 }
349 
350 
351 /**
352  * @brief LPC43xx Ethernet MAC timer handler
353  *
354  * This routine is periodically called by the TCP/IP stack to handle periodic
355  * operations such as polling the link state
356  *
357  * @param[in] interface Underlying network interface
358  **/
359 
360 void lpc43xxEthTick(NetInterface *interface)
361 {
362  //Valid Ethernet PHY or switch driver?
363  if(interface->phyDriver != NULL)
364  {
365  //Handle periodic operations
366  interface->phyDriver->tick(interface);
367  }
368  else if(interface->switchDriver != NULL)
369  {
370  //Handle periodic operations
371  interface->switchDriver->tick(interface);
372  }
373  else
374  {
375  //Just for sanity
376  }
377 }
378 
379 
380 /**
381  * @brief Enable interrupts
382  * @param[in] interface Underlying network interface
383  **/
384 
386 {
387  //Enable Ethernet MAC interrupts
388  NVIC_EnableIRQ(ETHERNET_IRQn);
389 
390  //Valid Ethernet PHY or switch driver?
391  if(interface->phyDriver != NULL)
392  {
393  //Enable Ethernet PHY interrupts
394  interface->phyDriver->enableIrq(interface);
395  }
396  else if(interface->switchDriver != NULL)
397  {
398  //Enable Ethernet switch interrupts
399  interface->switchDriver->enableIrq(interface);
400  }
401  else
402  {
403  //Just for sanity
404  }
405 }
406 
407 
408 /**
409  * @brief Disable interrupts
410  * @param[in] interface Underlying network interface
411  **/
412 
414 {
415  //Disable Ethernet MAC interrupts
416  NVIC_DisableIRQ(ETHERNET_IRQn);
417 
418  //Valid Ethernet PHY or switch driver?
419  if(interface->phyDriver != NULL)
420  {
421  //Disable Ethernet PHY interrupts
422  interface->phyDriver->disableIrq(interface);
423  }
424  else if(interface->switchDriver != NULL)
425  {
426  //Disable Ethernet switch interrupts
427  interface->switchDriver->disableIrq(interface);
428  }
429  else
430  {
431  //Just for sanity
432  }
433 }
434 
435 
436 /**
437  * @brief LPC43xx Ethernet MAC interrupt service routine
438  **/
439 
441 {
442  bool_t flag;
443  uint32_t status;
444 
445  //Interrupt service routine prologue
446  osEnterIsr();
447 
448  //This flag will be set if a higher priority task must be woken
449  flag = FALSE;
450 
451  //Read DMA status register
452  status = LPC_ETHERNET->DMA_STAT;
453 
454  //Packet transmitted?
455  if((status & (ETHERNET_DMA_STAT_TI_Msk | ETHERNET_DMA_STAT_UNF_Msk)) != 0)
456  {
457  //Clear TI and UNF interrupt flags
458  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_TI_Msk | ETHERNET_DMA_STAT_UNF_Msk;
459 
460  //Check whether the TX buffer is available for writing
461  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
462  {
463  //Notify the TCP/IP stack that the transmitter is ready to send
464  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
465  }
466  }
467 
468  //Packet received?
469  if((status & (ETHERNET_DMA_STAT_RI_Msk | ETHERNET_DMA_STAT_OVF_Msk)) != 0)
470  {
471  //Disable RIE and OVE interrupts
472  LPC_ETHERNET->DMA_INT_EN &= ~(ETHERNET_DMA_INT_EN_RIE_Msk |
473  ETHERNET_DMA_INT_EN_OVE_Msk);
474 
475  //Set event flag
476  nicDriverInterface->nicEvent = TRUE;
477  //Notify the TCP/IP stack of the event
478  flag |= osSetEventFromIsr(&netEvent);
479  }
480 
481  //Clear NIS and AIS interrupt flags
482  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_NIS_Msk | ETHERNET_DMA_STAT_AIE_Msk;
483 
484  //Interrupt service routine epilogue
485  osExitIsr(flag);
486 }
487 
488 
489 /**
490  * @brief LPC43xx Ethernet MAC event handler
491  * @param[in] interface Underlying network interface
492  **/
493 
495 {
496  error_t error;
497 
498  //Packet received?
499  if((LPC_ETHERNET->DMA_STAT & (ETHERNET_DMA_STAT_RI_Msk | ETHERNET_DMA_STAT_OVF_Msk)) != 0)
500  {
501  //Clear RI and OVF interrupt flags
502  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_RI_Msk | ETHERNET_DMA_STAT_OVF_Msk;
503 
504  //Process all pending packets
505  do
506  {
507  //Read incoming packet
508  error = lpc43xxEthReceivePacket(interface);
509 
510  //No more data in the receive buffer?
511  } while(error != ERROR_BUFFER_EMPTY);
512  }
513 
514  //Re-enable DMA interrupts
515  LPC_ETHERNET->DMA_INT_EN = ETHERNET_DMA_INT_EN_NIE_Msk |
516  ETHERNET_DMA_INT_EN_AIE_Msk | ETHERNET_DMA_INT_EN_RIE_Msk |
517  ETHERNET_DMA_INT_EN_OVE_Msk | ETHERNET_DMA_INT_EN_TIE_Msk |
518  ETHERNET_DMA_INT_EN_UNE_Msk;
519 }
520 
521 
522 /**
523  * @brief Send a packet
524  * @param[in] interface Underlying network interface
525  * @param[in] buffer Multi-part buffer containing the data to send
526  * @param[in] offset Offset to the first data byte
527  * @param[in] ancillary Additional options passed to the stack along with
528  * the packet
529  * @return Error code
530  **/
531 
533  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
534 {
535  size_t length;
536 
537  //Retrieve the length of the packet
538  length = netBufferGetLength(buffer) - offset;
539 
540  //Check the frame length
542  {
543  //The transmitter can accept another packet
544  osSetEvent(&interface->nicTxEvent);
545  //Report an error
546  return ERROR_INVALID_LENGTH;
547  }
548 
549  //Make sure the current buffer is available for writing
550  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) != 0)
551  {
552  return ERROR_FAILURE;
553  }
554 
555  //Copy user data to the transmit buffer
556  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
557 
558  //Write the number of bytes to send
559  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
560  //Set LS and FS flags as the data fits in a single buffer
561  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
562  //Give the ownership of the descriptor to the DMA
563  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
564 
565  //Clear TU flag to resume processing
566  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_TU_Msk;
567  //Instruct the DMA to poll the transmit descriptor list
568  LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 0;
569 
570  //Point to the next descriptor in the list
571  txCurDmaDesc = (Lpc43xxTxDmaDesc *) txCurDmaDesc->tdes3;
572 
573  //Check whether the next buffer is available for writing
574  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
575  {
576  //The transmitter can accept another packet
577  osSetEvent(&interface->nicTxEvent);
578  }
579 
580  //Data successfully written
581  return NO_ERROR;
582 }
583 
584 
585 /**
586  * @brief Receive a packet
587  * @param[in] interface Underlying network interface
588  * @return Error code
589  **/
590 
592 {
593  error_t error;
594  size_t n;
595  NetRxAncillary ancillary;
596 
597  //The current buffer is available for reading?
598  if((rxCurDmaDesc->rdes0 & ETH_RDES0_OWN) == 0)
599  {
600  //FS and LS flags should be set
601  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) != 0 &&
602  (rxCurDmaDesc->rdes0 & ETH_RDES0_LS) != 0)
603  {
604  //Make sure no error occurred
605  if((rxCurDmaDesc->rdes0 & ETH_RDES0_ES) == 0)
606  {
607  //Retrieve the length of the frame
608  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
609  //Limit the number of data to read
611 
612  //Additional options can be passed to the stack along with the packet
613  ancillary = NET_DEFAULT_RX_ANCILLARY;
614 
615  //Pass the packet to the upper layer
616  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
617  &ancillary);
618 
619  //Valid packet received
620  error = NO_ERROR;
621  }
622  else
623  {
624  //The received packet contains an error
625  error = ERROR_INVALID_PACKET;
626  }
627  }
628  else
629  {
630  //The packet is not valid
631  error = ERROR_INVALID_PACKET;
632  }
633 
634  //Give the ownership of the descriptor back to the DMA
635  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
636  //Point to the next descriptor in the list
637  rxCurDmaDesc = (Lpc43xxRxDmaDesc *) rxCurDmaDesc->rdes3;
638  }
639  else
640  {
641  //No more data in the receive buffer
642  error = ERROR_BUFFER_EMPTY;
643  }
644 
645  //Clear RU flag to resume processing
646  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_RU_Msk;
647  //Instruct the DMA to poll the receive descriptor list
648  LPC_ETHERNET->DMA_REC_POLL_DEMAND = 0;
649 
650  //Return status code
651  return error;
652 }
653 
654 
655 /**
656  * @brief Configure MAC address filtering
657  * @param[in] interface Underlying network interface
658  * @return Error code
659  **/
660 
662 {
663  uint_t i;
664  uint_t k;
665  uint32_t crc;
666  uint32_t hashTable[2];
667  MacFilterEntry *entry;
668 
669  //Debug message
670  TRACE_DEBUG("Updating MAC filter...\r\n");
671 
672  //Set the MAC address of the station
673  LPC_ETHERNET->MAC_ADDR0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
674  LPC_ETHERNET->MAC_ADDR0_HIGH = interface->macAddr.w[2];
675 
676  //Clear hash table
677  hashTable[0] = 0;
678  hashTable[1] = 0;
679 
680  //The MAC address filter contains the list of MAC addresses to accept
681  //when receiving an Ethernet frame
682  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
683  {
684  //Point to the current entry
685  entry = &interface->macAddrFilter[i];
686 
687  //Valid entry?
688  if(entry->refCount > 0)
689  {
690  //Compute CRC over the current MAC address
691  crc = lpc43xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
692 
693  //The upper 6 bits in the CRC register are used to index the
694  //contents of the hash table
695  k = (crc >> 26) & 0x3F;
696 
697  //Update hash table contents
698  hashTable[k / 32] |= (1 << (k % 32));
699  }
700  }
701 
702  //Write the hash table
703  LPC_ETHERNET->MAC_HASHTABLE_LOW = hashTable[0];
704  LPC_ETHERNET->MAC_HASHTABLE_HIGH = hashTable[1];
705 
706  //Debug message
707  TRACE_DEBUG(" MAC_HASHTABLE_LOW = %08" PRIX32 "\r\n", LPC_ETHERNET->MAC_HASHTABLE_LOW);
708  TRACE_DEBUG(" MAC_HASHTABLE_HIGH = %08" PRIX32 "\r\n", LPC_ETHERNET->MAC_HASHTABLE_HIGH);
709 
710  //Successful processing
711  return NO_ERROR;
712 }
713 
714 
715 /**
716  * @brief Adjust MAC configuration parameters for proper operation
717  * @param[in] interface Underlying network interface
718  * @return Error code
719  **/
720 
722 {
723  uint32_t config;
724 
725  //Read current MAC configuration
726  config = LPC_ETHERNET->MAC_CONFIG;
727 
728  //10BASE-T or 100BASE-TX operation mode?
729  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
730  {
731  config |= ETHERNET_MAC_CONFIG_FES_Msk;
732  }
733  else
734  {
735  config &= ~ETHERNET_MAC_CONFIG_FES_Msk;
736  }
737 
738  //Half-duplex or full-duplex mode?
739  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
740  {
741  config |= ETHERNET_MAC_CONFIG_DM_Msk;
742  }
743  else
744  {
745  config &= ~ETHERNET_MAC_CONFIG_DM_Msk;
746  }
747 
748  //Update MAC configuration register
749  LPC_ETHERNET->MAC_CONFIG = config;
750 
751  //Successful processing
752  return NO_ERROR;
753 }
754 
755 
756 /**
757  * @brief Write PHY register
758  * @param[in] opcode Access type (2 bits)
759  * @param[in] phyAddr PHY address (5 bits)
760  * @param[in] regAddr Register address (5 bits)
761  * @param[in] data Register value
762  **/
763 
764 void lpc43xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
765  uint8_t regAddr, uint16_t data)
766 {
767  uint32_t temp;
768 
769  //Valid opcode?
770  if(opcode == SMI_OPCODE_WRITE)
771  {
772  //Take care not to alter MDC clock configuration
773  temp = LPC_ETHERNET->MAC_MII_ADDR & ETHERNET_MAC_MII_ADDR_CR_Msk;
774  //Set up a write operation
775  temp |= ETHERNET_MAC_MII_ADDR_W_Msk | ETHERNET_MAC_MII_ADDR_GB_Msk;
776  //PHY address
777  temp |= (phyAddr << ETHERNET_MAC_MII_ADDR_PA_Pos) & ETHERNET_MAC_MII_ADDR_PA_Msk;
778  //Register address
779  temp |= (regAddr << ETHERNET_MAC_MII_ADDR_GR_Pos) & ETHERNET_MAC_MII_ADDR_GR_Msk;
780 
781  //Data to be written in the PHY register
782  LPC_ETHERNET->MAC_MII_DATA = data & ETHERNET_MAC_MII_DATA_GD_Msk;
783 
784  //Start a write operation
785  LPC_ETHERNET->MAC_MII_ADDR = temp;
786  //Wait for the write to complete
787  while((LPC_ETHERNET->MAC_MII_ADDR & ETHERNET_MAC_MII_ADDR_GB_Msk) != 0)
788  {
789  }
790  }
791  else
792  {
793  //The MAC peripheral only supports standard Clause 22 opcodes
794  }
795 }
796 
797 
798 /**
799  * @brief Read PHY register
800  * @param[in] opcode Access type (2 bits)
801  * @param[in] phyAddr PHY address (5 bits)
802  * @param[in] regAddr Register address (5 bits)
803  * @return Register value
804  **/
805 
806 uint16_t lpc43xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
807  uint8_t regAddr)
808 {
809  uint16_t data;
810  uint32_t temp;
811 
812  //Valid opcode?
813  if(opcode == SMI_OPCODE_READ)
814  {
815  //Take care not to alter MDC clock configuration
816  temp = LPC_ETHERNET->MAC_MII_ADDR & ETHERNET_MAC_MII_ADDR_CR_Msk;
817  //Set up a read operation
818  temp |= ETHERNET_MAC_MII_ADDR_GB_Msk;
819  //PHY address
820  temp |= (phyAddr << ETHERNET_MAC_MII_ADDR_PA_Pos) & ETHERNET_MAC_MII_ADDR_PA_Msk;
821  //Register address
822  temp |= (regAddr << ETHERNET_MAC_MII_ADDR_GR_Pos) & ETHERNET_MAC_MII_ADDR_GR_Msk;
823 
824  //Start a read operation
825  LPC_ETHERNET->MAC_MII_ADDR = temp;
826  //Wait for the read to complete
827  while((LPC_ETHERNET->MAC_MII_ADDR & ETHERNET_MAC_MII_ADDR_GB_Msk) != 0)
828  {
829  }
830 
831  //Get register value
832  data = LPC_ETHERNET->MAC_MII_DATA & ETHERNET_MAC_MII_DATA_GD_Msk;
833  }
834  else
835  {
836  //The MAC peripheral only supports standard Clause 22 opcodes
837  data = 0;
838  }
839 
840  //Return the value of the PHY register
841  return data;
842 }
843 
844 
845 /**
846  * @brief CRC calculation
847  * @param[in] data Pointer to the data over which to calculate the CRC
848  * @param[in] length Number of bytes to process
849  * @return Resulting CRC value
850  **/
851 
852 uint32_t lpc43xxEthCalcCrc(const void *data, size_t length)
853 {
854  uint_t i;
855  uint_t j;
856  uint32_t crc;
857  const uint8_t *p;
858 
859  //Point to the data over which to calculate the CRC
860  p = (uint8_t *) data;
861  //CRC preset value
862  crc = 0xFFFFFFFF;
863 
864  //Loop through data
865  for(i = 0; i < length; i++)
866  {
867  //The message is processed bit by bit
868  for(j = 0; j < 8; j++)
869  {
870  //Update CRC value
871  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
872  {
873  crc = (crc << 1) ^ 0x04C11DB7;
874  }
875  else
876  {
877  crc = crc << 1;
878  }
879  }
880  }
881 
882  //Return CRC value
883  return ~crc;
884 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
error_t lpc43xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
uint8_t length
Definition: coap_common.h:190
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
#define ETH_TDES0_IC
#define netEvent
Definition: net_legacy.h:267
uint8_t data[]
Definition: ethernet.h:209
#define LPC43XX_ETH_RX_BUFFER_COUNT
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:672
#define ETH_TDES0_TCH
uint8_t p
Definition: ndp.h:298
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define CREG6_ETHMODE_RMII
#define LPC43XX_ETH_TX_BUFFER_COUNT
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:88
#define TRUE
Definition: os_port.h:50
__start_packed struct @5 MacAddr
MAC address.
uint32_t lpc43xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:249
error_t lpc43xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void lpc43xxEthInitGpio(NetInterface *interface)
#define ETHERNET_DMA_BUS_MODE_RPBL_1
#define ETH_RDES0_OWN
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:388
uint16_t lpc43xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:65
void lpc43xxEthEventHandler(NetInterface *interface)
LPC43xx Ethernet MAC event handler.
#define LPC43XX_ETH_TX_BUFFER_SIZE
#define FALSE
Definition: os_port.h:46
#define ETH_RDES1_RBS1
LPC4300 Ethernet MAC driver.
error_t
Error codes.
Definition: error.h:42
#define ETH_RDES0_FL
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:96
Generic error code.
Definition: error.h:45
#define ETHERNET_MAC_MII_ADDR_CR_DIV62
#define txBuffer
#define ETHERNET_DMA_BUS_MODE_PBL_1
void lpc43xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:248
void lpc43xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
void lpc43xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define ETH_RDES0_LS
#define NetTxAncillary
Definition: net_misc.h:36
#define LPC43XX_ETH_IRQ_GROUP_PRIORITY
void lpc43xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define SMI_OPCODE_READ
Definition: nic.h:66
#define TRACE_INFO(...)
Definition: debug.h:95
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define ETHERNET_DMA_OP_MODE_TTC_64
#define MIN(a, b)
Definition: os_port.h:62
#define rxBuffer
#define ETH_RDES1_RCH
#define TRACE_DEBUG(...)
Definition: debug.h:107
error_t lpc43xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
Enhanced RX DMA descriptor.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:105
uint8_t n
MAC filter table entry.
Definition: ethernet.h:246
void ETHERNET_IRQHandler(void)
LPC43xx Ethernet MAC interrupt service routine.
#define ETHERNET_DMA_OP_MODE_RTC_32
#define ETH_TDES0_LS
#define osEnterIsr()
#define LPC43XX_ETH_IRQ_SUB_PRIORITY
const NicDriver lpc43xxEthDriver
LPC43xx Ethernet MAC driver.
void lpc43xxEthTick(NetInterface *interface)
LPC43xx Ethernet MAC timer handler.
#define LPC43XX_ETH_IRQ_PRIORITY_GROUPING
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define ETH_TDES0_FS
#define txDmaDesc
Enhanced TX DMA descriptor.
#define ETH_RDES0_ES
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
#define LPC43XX_ETH_RX_BUFFER_SIZE
NIC driver.
Definition: nic.h:257
#define ETH_TDES0_OWN
error_t lpc43xxEthReceivePacket(NetInterface *interface)
Receive a packet.
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
error_t lpc43xxEthInit(NetInterface *interface)
LPC43xx Ethernet MAC initialization.
#define ETHERNET_DMA_BUS_MODE_PR_1_1
#define ETH_TDES1_TBS1
#define ETH_RDES0_FS
Ethernet interface.
Definition: nic.h:82