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  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 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.6
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))
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))
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)
153  {
154  }
155 
156  //Adjust MDC clock range
157  LPC_ETHERNET->MAC_MII_ADDR = ETHERNET_MAC_MII_ADDR_CR_DIV62;
158 
159  //PHY transceiver initialization
160  error = interface->phyDriver->init(interface);
161  //Failed to initialize PHY transceiver?
162  if(error)
163  return error;
164 
165  //Use default MAC configuration
166  LPC_ETHERNET->MAC_CONFIG = ETHERNET_MAC_CONFIG_DO_Msk;
167 
168  //Set the MAC address of the station
169  LPC_ETHERNET->MAC_ADDR0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
170  LPC_ETHERNET->MAC_ADDR0_HIGH = interface->macAddr.w[2];
171 
172  //Initialize hash table
173  LPC_ETHERNET->MAC_HASHTABLE_LOW = 0;
174  LPC_ETHERNET->MAC_HASHTABLE_HIGH = 0;
175 
176  //Configure the receive filter
177  LPC_ETHERNET->MAC_FRAME_FILTER = ETHERNET_MAC_FRAME_FILTER_HPF_Msk |
178  ETHERNET_MAC_FRAME_FILTER_HMC_Msk;
179 
180  //Disable flow control
181  LPC_ETHERNET->MAC_FLOW_CTRL = 0;
182  //Set the threshold level of the transmit and receive FIFOs
183  LPC_ETHERNET->DMA_OP_MODE = ETHERNET_DMA_OP_MODE_TTC_64 | ETHERNET_DMA_OP_MODE_RTC_32;
184 
185  //Configure DMA bus mode
186  LPC_ETHERNET->DMA_BUS_MODE = ETHERNET_DMA_BUS_MODE_AAL_Msk | ETHERNET_DMA_BUS_MODE_USP_Msk |
188  ETHERNET_DMA_BUS_MODE_PBL_1 | ETHERNET_DMA_BUS_MODE_ATDS_Msk;
189 
190  //Initialize DMA descriptor lists
191  lpc43xxEthInitDmaDesc(interface);
192 
193  //Disable MAC interrupts
194  LPC_ETHERNET->MAC_INTR_MASK = ETHERNET_MAC_INTR_MASK_TSIM_Msk |
195  ETHERNET_MAC_INTR_MASK_PMTIM_Msk;
196 
197  //Enable the desired DMA interrupts
198  LPC_ETHERNET->DMA_INT_EN = ETHERNET_DMA_INT_EN_NIE_Msk |
199  ETHERNET_DMA_INT_EN_AIE_Msk | ETHERNET_DMA_INT_EN_RIE_Msk |
200  ETHERNET_DMA_INT_EN_OVE_Msk | ETHERNET_DMA_INT_EN_TIE_Msk |
201  ETHERNET_DMA_INT_EN_UNE_Msk;
202 
203  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
204  NVIC_SetPriorityGrouping(LPC43XX_ETH_IRQ_PRIORITY_GROUPING);
205 
206  //Configure Ethernet interrupt priority
207  NVIC_SetPriority(ETHERNET_IRQn, NVIC_EncodePriority(LPC43XX_ETH_IRQ_PRIORITY_GROUPING,
209 
210  //Enable MAC transmission and reception
211  LPC_ETHERNET->MAC_CONFIG |= ETHERNET_MAC_CONFIG_TE_Msk | ETHERNET_MAC_CONFIG_RE_Msk;
212  //Enable DMA transmission and reception
213  LPC_ETHERNET->DMA_OP_MODE |= ETHERNET_DMA_OP_MODE_ST_Msk | ETHERNET_DMA_OP_MODE_SR_Msk;
214 
215  //Accept any packets from the upper layer
216  osSetEvent(&interface->nicTxEvent);
217 
218  //Successful initialization
219  return NO_ERROR;
220 }
221 
222 
223 //LPC4330-Xplorer or LPCXpresso4337 evaluation board?
224 #if defined(USE_LPC4330_XPLORER) || defined(USE_LPCXPRESSO_4337)
225 
226 /**
227  * @brief GPIO configuration
228  * @param[in] interface Underlying network interface
229  **/
230 
231 void lpc43xxEthInitGpio(NetInterface *interface)
232 {
233  //Enable GPIO peripheral clock
234  LPC_CCU1->CLK_M4_GPIO_CFG |= CCU1_CLK_M4_GPIO_CFG_RUN_Msk;
235  //Wait for completion
236  while(!(LPC_CCU1->CLK_M4_GPIO_STAT & CCU1_CLK_M4_GPIO_STAT_RUN_Msk))
237  {
238  }
239 
240  //Select RMII operation mode
241  LPC_CREG->CREG6 &= ~CREG_CREG6_ETHMODE_Msk;
242  LPC_CREG->CREG6 |= CREG6_ETHMODE_RMII;
243 
244  //Configure P0.0 (ENET_RXD1)
245  LPC_SCU->SFSP0_0 = SCU_SFSP0_0_EZI_Msk | SCU_SFSP0_0_EHS_Msk | (2 & SCU_SFSP0_0_MODE_Msk);
246  //Configure P0.1 (ENET_TX_EN)
247  LPC_SCU->SFSP0_1 = SCU_SFSP0_1_EHS_Msk | (6 & SCU_SFSP0_1_MODE_Msk);
248 
249  //Configure P1.15 (ENET_RXD0)
250  LPC_SCU->SFSP1_15 = SCU_SFSP1_15_EZI_Msk | SCU_SFSP1_15_EHS_Msk | (3 & SCU_SFSP1_15_MODE_Msk);
251  //Configure P1.16 (ENET_RX_DV)
252  LPC_SCU->SFSP1_16 = SCU_SFSP1_16_EZI_Msk | SCU_SFSP1_16_EHS_Msk | (7 & SCU_SFSP1_16_MODE_Msk);
253  //Configure P1.17 (ENET_MDIO)
254  LPC_SCU->SFSP1_17 = SCU_SFSP1_17_EZI_Msk | (3 & SCU_SFSP1_17_MODE_Msk);
255  //Configure P1.18 (ENET_TXD0)
256  LPC_SCU->SFSP1_18 = SCU_SFSP1_18_EHS_Msk | (3 & SCU_SFSP1_18_MODE_Msk);
257  //Configure P1.19 (ENET_REF_CLK)
258  LPC_SCU->SFSP1_19 = SCU_SFSP1_19_EZI_Msk | SCU_SFSP1_19_EHS_Msk | (0 & SCU_SFSP1_19_MODE_Msk);
259  //Configure P1.20 (ENET_TXD1)
260  LPC_SCU->SFSP1_20 = SCU_SFSP1_20_EHS_Msk | (3 & SCU_SFSP1_20_MODE_Msk);
261 
262  //Configure P2.0 (ENET_MDC)
263  LPC_SCU->SFSP2_0 = (7 & SCU_SFSP2_0_MODE_Msk);
264 }
265 
266 #endif
267 
268 
269 /**
270  * @brief Initialize DMA descriptor lists
271  * @param[in] interface Underlying network interface
272  **/
273 
275 {
276  uint_t i;
277 
278  //Initialize TX DMA descriptor list
279  for(i = 0; i < LPC43XX_ETH_TX_BUFFER_COUNT; i++)
280  {
281  //Use chain structure rather than ring structure
282  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
283  //Initialize transmit buffer size
284  txDmaDesc[i].tdes1 = 0;
285  //Transmit buffer address
286  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
287  //Next descriptor address
288  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
289  //Reserved fields
290  txDmaDesc[i].tdes4 = 0;
291  txDmaDesc[i].tdes5 = 0;
292  //Transmit frame time stamp
293  txDmaDesc[i].tdes6 = 0;
294  txDmaDesc[i].tdes7 = 0;
295  }
296 
297  //The last descriptor is chained to the first entry
298  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
299  //Point to the very first descriptor
300  txCurDmaDesc = &txDmaDesc[0];
301 
302  //Initialize RX DMA descriptor list
303  for(i = 0; i < LPC43XX_ETH_RX_BUFFER_COUNT; i++)
304  {
305  //The descriptor is initially owned by the DMA
306  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
307  //Use chain structure rather than ring structure
309  //Receive buffer address
310  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
311  //Next descriptor address
312  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
313  //Extended status
314  rxDmaDesc[i].rdes4 = 0;
315  //Reserved field
316  rxDmaDesc[i].rdes5 = 0;
317  //Receive frame time stamp
318  rxDmaDesc[i].rdes6 = 0;
319  rxDmaDesc[i].rdes7 = 0;
320  }
321 
322  //The last descriptor is chained to the first entry
323  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
324  //Point to the very first descriptor
325  rxCurDmaDesc = &rxDmaDesc[0];
326 
327  //Start location of the TX descriptor list
328  LPC_ETHERNET->DMA_TRANS_DES_ADDR = (uint32_t) txDmaDesc;
329  //Start location of the RX descriptor list
330  LPC_ETHERNET->DMA_REC_DES_ADDR = (uint32_t) rxDmaDesc;
331 }
332 
333 
334 /**
335  * @brief LPC43xx Ethernet MAC timer handler
336  *
337  * This routine is periodically called by the TCP/IP stack to
338  * handle periodic operations such as polling the link state
339  *
340  * @param[in] interface Underlying network interface
341  **/
342 
343 void lpc43xxEthTick(NetInterface *interface)
344 {
345  //Handle periodic operations
346  interface->phyDriver->tick(interface);
347 }
348 
349 
350 /**
351  * @brief Enable interrupts
352  * @param[in] interface Underlying network interface
353  **/
354 
356 {
357  //Enable Ethernet MAC interrupts
358  NVIC_EnableIRQ(ETHERNET_IRQn);
359  //Enable Ethernet PHY interrupts
360  interface->phyDriver->enableIrq(interface);
361 }
362 
363 
364 /**
365  * @brief Disable interrupts
366  * @param[in] interface Underlying network interface
367  **/
368 
370 {
371  //Disable Ethernet MAC interrupts
372  NVIC_DisableIRQ(ETHERNET_IRQn);
373  //Disable Ethernet PHY interrupts
374  interface->phyDriver->disableIrq(interface);
375 }
376 
377 
378 /**
379  * @brief LPC43xx Ethernet MAC interrupt service routine
380  **/
381 
383 {
384  bool_t flag;
385  uint32_t status;
386 
387  //Interrupt service routine prologue
388  osEnterIsr();
389 
390  //This flag will be set if a higher priority task must be woken
391  flag = FALSE;
392 
393  //Read DMA status register
394  status = LPC_ETHERNET->DMA_STAT;
395 
396  //A packet has been transmitted?
397  if(status & (ETHERNET_DMA_STAT_TI_Msk | ETHERNET_DMA_STAT_UNF_Msk))
398  {
399  //Clear TI and UNF interrupt flags
400  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_TI_Msk | ETHERNET_DMA_STAT_UNF_Msk;
401 
402  //Check whether the TX buffer is available for writing
403  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
404  {
405  //Notify the TCP/IP stack that the transmitter is ready to send
406  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
407  }
408  }
409 
410  //A packet has been received?
411  if(status & (ETHERNET_DMA_STAT_RI_Msk | ETHERNET_DMA_STAT_OVF_Msk))
412  {
413  //Disable RIE and OVE interrupts
414  LPC_ETHERNET->DMA_INT_EN &= ~(ETHERNET_DMA_INT_EN_RIE_Msk |
415  ETHERNET_DMA_INT_EN_OVE_Msk);
416 
417  //Set event flag
418  nicDriverInterface->nicEvent = TRUE;
419  //Notify the TCP/IP stack of the event
420  flag |= osSetEventFromIsr(&netEvent);
421  }
422 
423  //Clear NIS and AIS interrupt flags
424  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_NIS_Msk | ETHERNET_DMA_STAT_AIE_Msk;
425 
426  //Interrupt service routine epilogue
427  osExitIsr(flag);
428 }
429 
430 
431 /**
432  * @brief LPC43xx Ethernet MAC event handler
433  * @param[in] interface Underlying network interface
434  **/
435 
437 {
438  error_t error;
439 
440  //Packet received?
441  if(LPC_ETHERNET->DMA_STAT & (ETHERNET_DMA_STAT_RI_Msk | ETHERNET_DMA_STAT_OVF_Msk))
442  {
443  //Clear RI and OVF interrupt flags
444  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_RI_Msk | ETHERNET_DMA_STAT_OVF_Msk;
445 
446  //Process all pending packets
447  do
448  {
449  //Read incoming packet
450  error = lpc43xxEthReceivePacket(interface);
451 
452  //No more data in the receive buffer?
453  } while(error != ERROR_BUFFER_EMPTY);
454  }
455 
456  //Re-enable DMA interrupts
457  LPC_ETHERNET->DMA_INT_EN = ETHERNET_DMA_INT_EN_NIE_Msk |
458  ETHERNET_DMA_INT_EN_AIE_Msk | ETHERNET_DMA_INT_EN_RIE_Msk |
459  ETHERNET_DMA_INT_EN_OVE_Msk | ETHERNET_DMA_INT_EN_TIE_Msk |
460  ETHERNET_DMA_INT_EN_UNE_Msk;
461 }
462 
463 
464 /**
465  * @brief Send a packet
466  * @param[in] interface Underlying network interface
467  * @param[in] buffer Multi-part buffer containing the data to send
468  * @param[in] offset Offset to the first data byte
469  * @return Error code
470  **/
471 
473  const NetBuffer *buffer, size_t offset)
474 {
475  size_t length;
476 
477  //Retrieve the length of the packet
478  length = netBufferGetLength(buffer) - offset;
479 
480  //Check the frame length
482  {
483  //The transmitter can accept another packet
484  osSetEvent(&interface->nicTxEvent);
485  //Report an error
486  return ERROR_INVALID_LENGTH;
487  }
488 
489  //Make sure the current buffer is available for writing
490  if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)
491  return ERROR_FAILURE;
492 
493  //Copy user data to the transmit buffer
494  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
495 
496  //Write the number of bytes to send
497  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
498  //Set LS and FS flags as the data fits in a single buffer
499  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
500  //Give the ownership of the descriptor to the DMA
501  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
502 
503  //Clear TU flag to resume processing
504  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_TU_Msk;
505  //Instruct the DMA to poll the transmit descriptor list
506  LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 0;
507 
508  //Point to the next descriptor in the list
509  txCurDmaDesc = (Lpc43xxTxDmaDesc *) txCurDmaDesc->tdes3;
510 
511  //Check whether the next buffer is available for writing
512  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
513  {
514  //The transmitter can accept another packet
515  osSetEvent(&interface->nicTxEvent);
516  }
517 
518  //Data successfully written
519  return NO_ERROR;
520 }
521 
522 
523 /**
524  * @brief Receive a packet
525  * @param[in] interface Underlying network interface
526  * @return Error code
527  **/
528 
530 {
531  error_t error;
532  size_t n;
533 
534  //The current buffer is available for reading?
535  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN))
536  {
537  //FS and LS flags should be set
538  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS))
539  {
540  //Make sure no error occurred
541  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES))
542  {
543  //Retrieve the length of the frame
544  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
545  //Limit the number of data to read
547 
548  //Pass the packet to the upper layer
549  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
550 
551  //Valid packet received
552  error = NO_ERROR;
553  }
554  else
555  {
556  //The received packet contains an error
557  error = ERROR_INVALID_PACKET;
558  }
559  }
560  else
561  {
562  //The packet is not valid
563  error = ERROR_INVALID_PACKET;
564  }
565 
566  //Give the ownership of the descriptor back to the DMA
567  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
568  //Point to the next descriptor in the list
569  rxCurDmaDesc = (Lpc43xxRxDmaDesc *) rxCurDmaDesc->rdes3;
570  }
571  else
572  {
573  //No more data in the receive buffer
574  error = ERROR_BUFFER_EMPTY;
575  }
576 
577  //Clear RU flag to resume processing
578  LPC_ETHERNET->DMA_STAT = ETHERNET_DMA_STAT_RU_Msk;
579  //Instruct the DMA to poll the receive descriptor list
580  LPC_ETHERNET->DMA_REC_POLL_DEMAND = 0;
581 
582  //Return status code
583  return error;
584 }
585 
586 
587 /**
588  * @brief Configure MAC address filtering
589  * @param[in] interface Underlying network interface
590  * @return Error code
591  **/
592 
594 {
595  uint_t i;
596  uint_t k;
597  uint32_t crc;
598  uint32_t hashTable[2];
599  MacFilterEntry *entry;
600 
601  //Debug message
602  TRACE_DEBUG("Updating MAC filter...\r\n");
603 
604  //Set the MAC address of the station
605  LPC_ETHERNET->MAC_ADDR0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
606  LPC_ETHERNET->MAC_ADDR0_HIGH = interface->macAddr.w[2];
607 
608  //Clear hash table
609  hashTable[0] = 0;
610  hashTable[1] = 0;
611 
612  //The MAC address filter contains the list of MAC addresses to accept
613  //when receiving an Ethernet frame
614  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
615  {
616  //Point to the current entry
617  entry = &interface->macAddrFilter[i];
618 
619  //Valid entry?
620  if(entry->refCount > 0)
621  {
622  //Compute CRC over the current MAC address
623  crc = lpc43xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
624 
625  //The upper 6 bits in the CRC register are used to index the
626  //contents of the hash table
627  k = (crc >> 26) & 0x3F;
628 
629  //Update hash table contents
630  hashTable[k / 32] |= (1 << (k % 32));
631  }
632  }
633 
634  //Write the hash table
635  LPC_ETHERNET->MAC_HASHTABLE_LOW = hashTable[0];
636  LPC_ETHERNET->MAC_HASHTABLE_HIGH = hashTable[1];
637 
638  //Debug message
639  TRACE_DEBUG(" MAC_HASHTABLE_LOW = %08" PRIX32 "\r\n", LPC_ETHERNET->MAC_HASHTABLE_LOW);
640  TRACE_DEBUG(" MAC_HASHTABLE_HIGH = %08" PRIX32 "\r\n", LPC_ETHERNET->MAC_HASHTABLE_HIGH);
641 
642  //Successful processing
643  return NO_ERROR;
644 }
645 
646 
647 /**
648  * @brief Adjust MAC configuration parameters for proper operation
649  * @param[in] interface Underlying network interface
650  * @return Error code
651  **/
652 
654 {
655  uint32_t config;
656 
657  //Read current MAC configuration
658  config = LPC_ETHERNET->MAC_CONFIG;
659 
660  //10BASE-T or 100BASE-TX operation mode?
661  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
662  config |= ETHERNET_MAC_CONFIG_FES_Msk;
663  else
664  config &= ~ETHERNET_MAC_CONFIG_FES_Msk;
665 
666  //Half-duplex or full-duplex mode?
667  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
668  config |= ETHERNET_MAC_CONFIG_DM_Msk;
669  else
670  config &= ~ETHERNET_MAC_CONFIG_DM_Msk;
671 
672  //Update MAC configuration register
673  LPC_ETHERNET->MAC_CONFIG = config;
674 
675  //Successful processing
676  return NO_ERROR;
677 }
678 
679 
680 /**
681  * @brief Write PHY register
682  * @param[in] opcode Access type (2 bits)
683  * @param[in] phyAddr PHY address (5 bits)
684  * @param[in] regAddr Register address (5 bits)
685  * @param[in] data Register value
686  **/
687 
688 void lpc43xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
689  uint8_t regAddr, uint16_t data)
690 {
691  uint32_t temp;
692 
693  //Valid opcode?
694  if(opcode == SMI_OPCODE_WRITE)
695  {
696  //Take care not to alter MDC clock configuration
697  temp = LPC_ETHERNET->MAC_MII_ADDR & ETHERNET_MAC_MII_ADDR_CR_Msk;
698  //Set up a write operation
699  temp |= ETHERNET_MAC_MII_ADDR_W_Msk | ETHERNET_MAC_MII_ADDR_GB_Msk;
700  //PHY address
701  temp |= (phyAddr << ETHERNET_MAC_MII_ADDR_PA_Pos) & ETHERNET_MAC_MII_ADDR_PA_Msk;
702  //Register address
703  temp |= (regAddr << ETHERNET_MAC_MII_ADDR_GR_Pos) & ETHERNET_MAC_MII_ADDR_GR_Msk;
704 
705  //Data to be written in the PHY register
706  LPC_ETHERNET->MAC_MII_DATA = data & ETHERNET_MAC_MII_DATA_GD_Msk;
707 
708  //Start a write operation
709  LPC_ETHERNET->MAC_MII_ADDR = temp;
710  //Wait for the write to complete
711  while(LPC_ETHERNET->MAC_MII_ADDR & ETHERNET_MAC_MII_ADDR_GB_Msk)
712  {
713  }
714  }
715  else
716  {
717  //The MAC peripheral only supports standard Clause 22 opcodes
718  }
719 }
720 
721 
722 /**
723  * @brief Read PHY register
724  * @param[in] opcode Access type (2 bits)
725  * @param[in] phyAddr PHY address (5 bits)
726  * @param[in] regAddr Register address (5 bits)
727  * @return Register value
728  **/
729 
730 uint16_t lpc43xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
731  uint8_t regAddr)
732 {
733  uint16_t data;
734  uint32_t temp;
735 
736  //Valid opcode?
737  if(opcode == SMI_OPCODE_READ)
738  {
739  //Take care not to alter MDC clock configuration
740  temp = LPC_ETHERNET->MAC_MII_ADDR & ETHERNET_MAC_MII_ADDR_CR_Msk;
741  //Set up a read operation
742  temp |= ETHERNET_MAC_MII_ADDR_GB_Msk;
743  //PHY address
744  temp |= (phyAddr << ETHERNET_MAC_MII_ADDR_PA_Pos) & ETHERNET_MAC_MII_ADDR_PA_Msk;
745  //Register address
746  temp |= (regAddr << ETHERNET_MAC_MII_ADDR_GR_Pos) & ETHERNET_MAC_MII_ADDR_GR_Msk;
747 
748  //Start a read operation
749  LPC_ETHERNET->MAC_MII_ADDR = temp;
750  //Wait for the read to complete
751  while(LPC_ETHERNET->MAC_MII_ADDR & ETHERNET_MAC_MII_ADDR_GB_Msk)
752  {
753  }
754 
755  //Get register value
756  data = LPC_ETHERNET->MAC_MII_DATA & ETHERNET_MAC_MII_DATA_GD_Msk;
757  }
758  else
759  {
760  //The MAC peripheral only supports standard Clause 22 opcodes
761  data = 0;
762  }
763 
764  //Return the value of the PHY register
765  return data;
766 }
767 
768 
769 /**
770  * @brief CRC calculation
771  * @param[in] data Pointer to the data over which to calculate the CRC
772  * @param[in] length Number of bytes to process
773  * @return Resulting CRC value
774  **/
775 
776 uint32_t lpc43xxEthCalcCrc(const void *data, size_t length)
777 {
778  uint_t i;
779  uint_t j;
780 
781  //Point to the data over which to calculate the CRC
782  const uint8_t *p = (uint8_t *) data;
783  //CRC preset value
784  uint32_t crc = 0xFFFFFFFF;
785 
786  //Loop through data
787  for(i = 0; i < length; i++)
788  {
789  //The message is processed bit by bit
790  for(j = 0; j < 8; j++)
791  {
792  //Update CRC value
793  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
794  crc = (crc << 1) ^ 0x04C11DB7;
795  else
796  crc = crc << 1;
797  }
798  }
799 
800  //Return CRC value
801  return ~crc;
802 }
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: dtls_misc.h:149
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
#define ETH_TDES0_IC
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:119
#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
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:383
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:74
#define TRUE
Definition: os_port.h:50
uint32_t lpc43xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:223
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
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:62
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 controller.
error_t
Error codes.
Definition: error.h:42
#define ETH_RDES0_FL
@ ERROR_FAILURE
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.
@ ERROR_INVALID_PACKET
Definition: error.h:138
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:222
void lpc43xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
@ ERROR_INVALID_LENGTH
Definition: error.h:109
@ ERROR_BUFFER_EMPTY
Definition: error.h:139
void lpc43xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define ETH_RDES0_LS
#define LPC43XX_ETH_IRQ_GROUP_PRIORITY
OsEvent netEvent
Definition: net.c:77
void lpc43xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define SMI_OPCODE_READ
Definition: nic.h:63
#define TRACE_INFO(...)
Definition: debug.h:94
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:106
Enhanced RX DMA descriptor.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:91
uint8_t n
MAC filter table entry.
Definition: ethernet.h:220
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.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:106
#define ETH_RDES0_ES
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
#define LPC43XX_ETH_RX_BUFFER_SIZE
NIC driver.
Definition: nic.h:179
#define ETH_TDES0_OWN
error_t lpc43xxEthReceivePacket(NetInterface *interface)
Receive a packet.
error_t lpc43xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
@ NO_ERROR
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
__start_packed struct @108 MacAddr
MAC address.
#define ETH_TDES1_TBS1
#define ETH_RDES0_FS
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:79