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