lpc546xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file lpc546xx_eth_driver.c
3  * @brief LPC54608/LPC54618/LPC54628 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 "fsl_device_registers.h"
36 #include "fsl_power.h"
37 #include "fsl_reset.h"
38 #include "fsl_clock.h"
39 #include "fsl_iocon.h"
40 #include "fsl_gpio.h"
41 #include "core/net.h"
43 #include "debug.h"
44 
45 //Underlying network interface
46 static NetInterface *nicDriverInterface;
47 
48 //IAR EWARM compiler?
49 #if defined(__ICCARM__)
50 
51 //Transmit buffer
52 #pragma data_alignment = 4
54 //Receive buffer
55 #pragma data_alignment = 4
57 //Transmit DMA descriptors
58 #pragma data_alignment = 4
60 //Receive DMA descriptors
61 #pragma data_alignment = 4
63 
64 //Keil MDK-ARM or GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4)));
70 //Receive buffer
72  __attribute__((aligned(4)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(4)));
76 //Receive DMA descriptors
78  __attribute__((aligned(4)));
79 
80 #endif
81 
82 //Current transmit descriptor
83 static uint_t txIndex;
84 //Current receive descriptor
85 static uint_t rxIndex;
86 
87 
88 /**
89  * @brief LPC546xx Ethernet MAC driver
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief LPC546xx Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122 
123  //Debug message
124  TRACE_INFO("Initializing LPC546xx Ethernet MAC...\r\n");
125 
126  //Save underlying network interface
127  nicDriverInterface = interface;
128 
129  //Enable ENET peripheral clock
130  CLOCK_EnableClock(kCLOCK_Eth);
131  //Reset ENET module
132  RESET_PeripheralReset(kETH_RST_SHIFT_RSTn);
133 
134  //GPIO configuration
135  lpc546xxEthInitGpio(interface);
136 
137  //Perform a software reset
138  ENET->DMA_MODE |= ENET_DMA_MODE_SWR_MASK;
139  //Wait for the reset to complete
140  while(ENET->DMA_MODE & ENET_DMA_MODE_SWR_MASK)
141  {
142  }
143 
144  //Adjust MDC clock range depending on CSR frequency
145  ENET->MAC_MDIO_ADDR = ENET_MAC_MDIO_ADDR_CR(4);
146 
147  //PHY transceiver initialization
148  error = interface->phyDriver->init(interface);
149  //Failed to initialize PHY transceiver?
150  if(error)
151  return error;
152 
153  //Use default MAC configuration
154  ENET->MAC_CONFIG = ENET_MAC_CONFIG_PS_MASK | ENET_MAC_CONFIG_DO_MASK;
155 
156  //Set the MAC address of the station
157  ENET->MAC_ADDR_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
158  ENET->MAC_ADDR_HIGH = interface->macAddr.w[2];
159 
160  //Configure the receive filter
161  ENET->MAC_FRAME_FILTER = 0;
162 
163  //Disable flow control
164  ENET->MAC_TX_FLOW_CTRL_Q[0] = 0;
165  ENET->MAC_RX_FLOW_CTRL = 0;
166 
167  //Enable the first RX queue
168  ENET->MAC_RXQ_CTRL[0] = ENET_MAC_RXQ_CTRL_RXQ0EN(1);
169 
170  //Configure DMA operating mode
171  ENET->DMA_MODE = ENET_DMA_MODE_PR(0);
172  //Configure system bus mode
173  ENET->DMA_SYSBUS_MODE |= ENET_DMA_SYSBUS_MODE_AAL_MASK;
174 
175  //The DMA takes the descriptor table as contiguous
176  ENET->DMA_CH[0].DMA_CHX_CTRL = ENET_DMA_CH_DMA_CHX_CTRL_DSL(0);
177  //Configure TX features
178  ENET->DMA_CH[0].DMA_CHX_TX_CTRL = ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL(1);
179 
180  //Configure RX features
181  ENET->DMA_CH[0].DMA_CHX_RX_CTRL = ENET_DMA_CH_DMA_CHX_RX_CTRL_RxPBL(1) |
182  ENET_DMA_CH_DMA_CHX_RX_CTRL_RBSZ(LPC546XX_ETH_RX_BUFFER_SIZE / 4);
183 
184  //Enable store and forward mode for transmission
185  ENET->MTL_QUEUE[0].MTL_TXQX_OP_MODE |= ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TQS(7) |
186  ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TXQEN(2) |
187  ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TSF_MASK;
188 
189  //Enable store and forward mode for reception
190  ENET->MTL_QUEUE[0].MTL_RXQX_OP_MODE |= ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_RQS(7) |
191  ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_RSF_MASK;
192 
193  //Initialize DMA descriptor lists
194  lpc546xxEthInitDmaDesc(interface);
195 
196  //Disable MAC interrupts
197  ENET->MAC_INTR_EN = 0;
198 
199  //Enable the desired DMA interrupts
200  ENET->DMA_CH[0].DMA_CHX_INT_EN = ENET_DMA_CH_DMA_CHX_INT_EN_NIE_MASK |
201  ENET_DMA_CH_DMA_CHX_INT_EN_RIE_MASK | ENET_DMA_CH_DMA_CHX_INT_EN_TIE_MASK;
202 
203  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
204  NVIC_SetPriorityGrouping(LPC546XX_ETH_IRQ_PRIORITY_GROUPING);
205 
206  //Configure Ethernet interrupt priority
207  NVIC_SetPriority(ETHERNET_IRQn, NVIC_EncodePriority(LPC546XX_ETH_IRQ_PRIORITY_GROUPING,
209 
210  //Enable MAC transmission and reception
211  ENET->MAC_CONFIG |= ENET_MAC_CONFIG_TE_MASK | ENET_MAC_CONFIG_RE_MASK;
212 
213  //Enable DMA transmission and reception
214  ENET->DMA_CH[0].DMA_CHX_TX_CTRL |= ENET_DMA_CH_DMA_CHX_TX_CTRL_ST_MASK;
215  ENET->DMA_CH[0].DMA_CHX_RX_CTRL |= ENET_DMA_CH_DMA_CHX_RX_CTRL_SR_MASK;
216 
217  //Accept any packets from the upper layer
218  osSetEvent(&interface->nicTxEvent);
219 
220  //Successful initialization
221  return NO_ERROR;
222 }
223 
224 
225 //LPCXpresso54608 evaluation board?
226 #if defined(USE_LPCXPRESSO_54608)
227 
228 /**
229  * @brief GPIO configuration
230  * @param[in] interface Underlying network interface
231  **/
232 
233 void lpc546xxEthInitGpio(NetInterface *interface)
234 {
235  gpio_pin_config_t pinConfig;
236 
237  //Select RMII interface mode
238  SYSCON->ETHPHYSEL |= SYSCON_ETHPHYSEL_PHY_SEL_MASK;
239 
240  //Enable IOCON clock
241  CLOCK_EnableClock(kCLOCK_Iocon);
242 
243  //Enable GPIO clocks
244  CLOCK_EnableClock(kCLOCK_Gpio0);
245  CLOCK_EnableClock(kCLOCK_Gpio4);
246 
247  //Configure ENET_TXD1 (PA0_17)
248  IOCON_PinMuxSet(IOCON, 0, 17, IOCON_FUNC7 | IOCON_MODE_INACT |
249  IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
250 
251  //Configure ENET_TXD0 (PA4_8)
252  IOCON_PinMuxSet(IOCON, 4, 8, IOCON_FUNC1 | IOCON_MODE_INACT |
253  IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
254 
255  //Configure ENET_RX_DV (PA4_10)
256  IOCON_PinMuxSet(IOCON, 4, 10, IOCON_FUNC1 | IOCON_MODE_INACT |
257  IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
258 
259  //Configure ENET_RXD0 (PA4_11)
260  IOCON_PinMuxSet(IOCON, 4, 11, IOCON_FUNC1 | IOCON_MODE_INACT |
261  IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
262 
263  //Configure ENET_RXD1 (PA4_12)
264  IOCON_PinMuxSet(IOCON, 4, 12, IOCON_FUNC1 | IOCON_MODE_INACT |
265  IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
266 
267  //Configure ENET_TX_EN (PA4_13)
268  IOCON_PinMuxSet(IOCON, 4, 13, IOCON_FUNC1 | IOCON_MODE_INACT |
269  IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
270 
271  //Configure ENET_RX_CLK (PA4_14)
272  IOCON_PinMuxSet(IOCON, 4, 14, IOCON_FUNC1 | IOCON_MODE_INACT |
273  IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
274 
275  //Configure ENET_MDC (PA4_15)
276  IOCON_PinMuxSet(IOCON, 4, 15, IOCON_FUNC1 | IOCON_MODE_INACT |
277  IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
278 
279  //Configure ENET_MDIO (PA4_16)
280  IOCON_PinMuxSet(IOCON, 4, 16, IOCON_FUNC1 | IOCON_MODE_PULLUP |
281  IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
282 
283  //Configure ENET_RST as an output
284  pinConfig.pinDirection = kGPIO_DigitalOutput;
285  pinConfig.outputLogic = 0;
286  GPIO_PinInit(GPIO, 2, 26, &pinConfig);
287 
288  //Reset PHY transceiver (hard reset)
289  GPIO_WritePinOutput(GPIO, 2, 26, 0);
290  sleep(10);
291  GPIO_WritePinOutput(GPIO, 2, 26, 1);
292  sleep(10);
293 }
294 
295 #endif
296 
297 
298 /**
299  * @brief Initialize DMA descriptor lists
300  * @param[in] interface Underlying network interface
301  **/
302 
304 {
305  uint_t i;
306 
307  //Initialize TX DMA descriptor list
308  for(i = 0; i < LPC546XX_ETH_TX_BUFFER_COUNT; i++)
309  {
310  //The descriptor is initially owned by the application
311  txDmaDesc[i].tdes0 = 0;
312  txDmaDesc[i].tdes1 = 0;
313  txDmaDesc[i].tdes2 = 0;
314  txDmaDesc[i].tdes3 = 0;
315  }
316 
317  //Initialize TX descriptor index
318  txIndex = 0;
319 
320  //Initialize RX DMA descriptor list
321  for(i = 0; i < LPC546XX_ETH_RX_BUFFER_COUNT; i++)
322  {
323  //The descriptor is initially owned by the DMA
324  rxDmaDesc[i].rdes0 = (uint32_t) rxBuffer[i];
325  rxDmaDesc[i].rdes1 = 0;
326  rxDmaDesc[i].rdes2 = 0;
328  }
329 
330  //Initialize RX descriptor index
331  rxIndex = 0;
332 
333  //Start location of the TX descriptor list
334  ENET->DMA_CH[0].DMA_CHX_TXDESC_LIST_ADDR = (uint32_t) &txDmaDesc[0];
335  //Length of the transmit descriptor ring
336  ENET->DMA_CH[0].DMA_CHX_TXDESC_RING_LENGTH = LPC546XX_ETH_TX_BUFFER_COUNT - 1;
337 
338  //Start location of the RX descriptor list
339  ENET->DMA_CH[0].DMA_CHX_RXDESC_LIST_ADDR = (uint32_t) &rxDmaDesc[0];
340  //Length of the receive descriptor ring
341  ENET->DMA_CH[0].DMA_CHX_RXDESC_RING_LENGTH = LPC546XX_ETH_RX_BUFFER_COUNT - 1;
342 }
343 
344 
345 /**
346  * @brief LPC546xx Ethernet MAC timer handler
347  *
348  * This routine is periodically called by the TCP/IP stack to
349  * handle periodic operations such as polling the link state
350  *
351  * @param[in] interface Underlying network interface
352  **/
353 
355 {
356  //Handle periodic operations
357  interface->phyDriver->tick(interface);
358 }
359 
360 
361 /**
362  * @brief Enable interrupts
363  * @param[in] interface Underlying network interface
364  **/
365 
367 {
368  //Enable Ethernet MAC interrupts
369  NVIC_EnableIRQ(ETHERNET_IRQn);
370  //Enable Ethernet PHY interrupts
371  interface->phyDriver->enableIrq(interface);
372 }
373 
374 
375 /**
376  * @brief Disable interrupts
377  * @param[in] interface Underlying network interface
378  **/
379 
381 {
382  //Disable Ethernet MAC interrupts
383  NVIC_DisableIRQ(ETHERNET_IRQn);
384  //Disable Ethernet PHY interrupts
385  interface->phyDriver->disableIrq(interface);
386 }
387 
388 
389 /**
390  * @brief LPC546xx Ethernet MAC interrupt service routine
391  **/
392 
394 {
395  bool_t flag;
396  uint32_t status;
397 
398  //Interrupt service routine prologue
399  osEnterIsr();
400 
401  //This flag will be set if a higher priority task must be woken
402  flag = FALSE;
403 
404  //Read DMA status register
405  status = ENET->DMA_CH[0].DMA_CHX_STAT;
406 
407  //A packet has been transmitted?
408  if(status & ENET_DMA_CH_DMA_CHX_STAT_TI_MASK)
409  {
410  //Clear TI interrupt flag
411  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TI_MASK;
412 
413  //Check whether the TX buffer is available for writing
414  if(!(txDmaDesc[txIndex].tdes3 & ENET_TDES3_OWN))
415  {
416  //Notify the TCP/IP stack that the transmitter is ready to send
417  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
418  }
419  }
420 
421  //A packet has been received?
422  if(status & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK)
423  {
424  //Disable RIE interrupt
425  ENET->DMA_CH[0].DMA_CHX_INT_EN &= ~ENET_DMA_CH_DMA_CHX_INT_EN_RIE_MASK;
426 
427  //Set event flag
428  nicDriverInterface->nicEvent = TRUE;
429  //Notify the TCP/IP stack of the event
430  flag |= osSetEventFromIsr(&netEvent);
431  }
432 
433  //Clear NIS interrupt flag
434  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
435 
436  //Interrupt service routine epilogue
437  osExitIsr(flag);
438 }
439 
440 
441 /**
442  * @brief LPC546xx Ethernet MAC event handler
443  * @param[in] interface Underlying network interface
444  **/
445 
447 {
448  error_t error;
449 
450  //Packet received?
451  if(ENET->DMA_CH[0].DMA_CHX_STAT & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK)
452  {
453  //Clear interrupt flag
454  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RI_MASK;
455 
456  //Process all pending packets
457  do
458  {
459  //Read incoming packet
460  error = lpc546xxEthReceivePacket(interface);
461 
462  //No more data in the receive buffer?
463  } while(error != ERROR_BUFFER_EMPTY);
464  }
465 
466  //Re-enable DMA interrupts
467  ENET->DMA_CH[0].DMA_CHX_INT_EN = ENET_DMA_CH_DMA_CHX_INT_EN_NIE_MASK |
468  ENET_DMA_CH_DMA_CHX_INT_EN_RIE_MASK | ENET_DMA_CH_DMA_CHX_INT_EN_TIE_MASK;
469 }
470 
471 
472 /**
473  * @brief Send a packet
474  * @param[in] interface Underlying network interface
475  * @param[in] buffer Multi-part buffer containing the data to send
476  * @param[in] offset Offset to the first data byte
477  * @return Error code
478  **/
479 
481  const NetBuffer *buffer, size_t offset)
482 {
483  size_t length;
484 
485  //Retrieve the length of the packet
486  length = netBufferGetLength(buffer) - offset;
487 
488  //Check the frame length
490  {
491  //The transmitter can accept another packet
492  osSetEvent(&interface->nicTxEvent);
493  //Report an error
494  return ERROR_INVALID_LENGTH;
495  }
496 
497  //Make sure the current buffer is available for writing
498  if(txDmaDesc[txIndex].tdes3 & ENET_TDES3_OWN)
499  return ERROR_FAILURE;
500 
501  //Copy user data to the transmit buffer
502  netBufferRead(txBuffer[txIndex], buffer, offset, length);
503 
504  //Set the start address of the buffer
505  txDmaDesc[txIndex].tdes0 = (uint32_t) txBuffer[txIndex];
506  //Write the number of bytes to send
507  txDmaDesc[txIndex].tdes2 = ENET_TDES2_IOC | (length & ENET_TDES2_B1L);
508  //Give the ownership of the descriptor to the DMA
510 
511  //Clear TBU flag to resume processing
512  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TBU_MASK;
513  //Instruct the DMA to poll the transmit descriptor list
514  ENET->DMA_CH[0].DMA_CHX_TXDESC_TAIL_PTR = 0;
515 
516  //Increment index and wrap around if necessary
517  if(++txIndex >= LPC546XX_ETH_TX_BUFFER_COUNT)
518  txIndex = 0;
519 
520  //Check whether the next buffer is available for writing
521  if(!(txDmaDesc[txIndex].tdes3 & ENET_TDES3_OWN))
522  {
523  //The transmitter can accept another packet
524  osSetEvent(&interface->nicTxEvent);
525  }
526 
527  //Data successfully written
528  return NO_ERROR;
529 }
530 
531 
532 /**
533  * @brief Receive a packet
534  * @param[in] interface Underlying network interface
535  * @return Error code
536  **/
537 
539 {
540  error_t error;
541  size_t n;
542 
543  //The current buffer is available for reading?
544  if(!(rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_OWN))
545  {
546  //FD and LD flags should be set
547  if((rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_FD) &&
548  (rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_LD))
549  {
550  //Make sure no error occurred
551  if(!(rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_ES))
552  {
553  //Retrieve the length of the frame
554  n = rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_PL;
555  //Limit the number of data to read
557 
558  //Pass the packet to the upper layer
559  nicProcessPacket(interface, rxBuffer[rxIndex], n);
560 
561  //Valid packet received
562  error = NO_ERROR;
563  }
564  else
565  {
566  //The received packet contains an error
567  error = ERROR_INVALID_PACKET;
568  }
569  }
570  else
571  {
572  //The packet is not valid
573  error = ERROR_INVALID_PACKET;
574  }
575 
576  //Set the start address of the buffer
577  rxDmaDesc[rxIndex].rdes0 = (uint32_t) rxBuffer[rxIndex];
578  //Give the ownership of the descriptor back to the DMA
580 
581  //Increment index and wrap around if necessary
582  if(++rxIndex >= LPC546XX_ETH_RX_BUFFER_COUNT)
583  rxIndex = 0;
584  }
585  else
586  {
587  //No more data in the receive buffer
588  error = ERROR_BUFFER_EMPTY;
589  }
590 
591  //Clear RBU flag to resume processing
592  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RBU_MASK;
593  //Instruct the DMA to poll the receive descriptor list
594  ENET->DMA_CH[0].DMA_CHX_RXDESC_TAIL_PTR = 0;
595 
596  //Return status code
597  return error;
598 }
599 
600 
601 /**
602  * @brief Configure MAC address filtering
603  * @param[in] interface Underlying network interface
604  * @return Error code
605  **/
606 
608 {
609  uint_t i;
610  bool_t acceptMulticast;
611 
612  //Debug message
613  TRACE_DEBUG("Updating MAC filter...\r\n");
614 
615  //Set the MAC address of the station
616  ENET->MAC_ADDR_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
617  ENET->MAC_ADDR_HIGH = interface->macAddr.w[2];
618 
619  //This flag will be set if multicast addresses should be accepted
620  acceptMulticast = FALSE;
621 
622  //The MAC address filter contains the list of MAC addresses to accept
623  //when receiving an Ethernet frame
624  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
625  {
626  //Valid entry?
627  if(interface->macAddrFilter[i].refCount > 0)
628  {
629  //Accept multicast addresses
630  acceptMulticast = TRUE;
631  //We are done
632  break;
633  }
634  }
635 
636  //Enable the reception of multicast frames if necessary
637  if(acceptMulticast)
638  ENET->MAC_FRAME_FILTER |= ENET_MAC_FRAME_FILTER_PM_MASK;
639  else
640  ENET->MAC_FRAME_FILTER &= ~ENET_MAC_FRAME_FILTER_PM_MASK;
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 = ENET->MAC_CONFIG;
659 
660  //10BASE-T or 100BASE-TX operation mode?
661  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
662  config |= ENET_MAC_CONFIG_FES_MASK;
663  else
664  config &= ~ENET_MAC_CONFIG_FES_MASK;
665 
666  //Half-duplex or full-duplex mode?
667  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
668  config |= ENET_MAC_CONFIG_DM_MASK;
669  else
670  config &= ~ENET_MAC_CONFIG_DM_MASK;
671 
672  //Update MAC configuration register
673  ENET->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 lpc546xxEthWritePhyReg(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 = ENET->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_CR_MASK;
698  //Set up a write operation
699  temp |= ENET_MAC_MDIO_ADDR_MOC(1) | ENET_MAC_MDIO_ADDR_MB_MASK;
700  //PHY address
701  temp |= ENET_MAC_MDIO_ADDR_PA(phyAddr);
702  //Register address
703  temp |= ENET_MAC_MDIO_ADDR_RDA(regAddr);
704 
705  //Data to be written in the PHY register
706  ENET->MAC_MDIO_DATA = data & ENET_MAC_MDIO_DATA_MD_MASK;
707 
708  //Start a write operation
709  ENET->MAC_MDIO_ADDR = temp;
710  //Wait for the write to complete
711  while(ENET->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_MB_MASK)
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 lpc546xxEthReadPhyReg(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 = ENET->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_CR_MASK;
741  //Set up a read operation
742  temp |= ENET_MAC_MDIO_ADDR_MOC(3) | ENET_MAC_MDIO_ADDR_MB_MASK;
743  //PHY address
744  temp |= ENET_MAC_MDIO_ADDR_PA(phyAddr);
745  //Register address
746  temp |= ENET_MAC_MDIO_ADDR_RDA(regAddr);
747 
748  //Start a read operation
749  ENET->MAC_MDIO_ADDR = temp;
750  //Wait for the read to complete
751  while(ENET->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_MB_MASK)
752  {
753  }
754 
755  //Get register value
756  data = ENET->MAC_MDIO_DATA & ENET_MAC_MDIO_DATA_MD_MASK;
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 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
uint8_t length
Definition: dtls_misc.h:149
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
Receive descriptor.
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 ENET_RDES3_ES
void ETHERNET_IRQHandler(void)
LPC546xx Ethernet MAC interrupt service routine.
#define ENET_TDES2_IOC
LPC54608/LPC54618/LPC54628 Ethernet MAC controller.
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 MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
#define TRUE
Definition: os_port.h:50
#define sleep(delay)
Definition: os_port.h:131
#define ENET_RDES3_LD
error_t lpc546xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void lpc546xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
const NicDriver lpc546xxEthDriver
LPC546xx Ethernet MAC driver.
#define LPC546XX_ETH_IRQ_PRIORITY_GROUPING
error_t lpc546xxEthReceivePacket(NetInterface *interface)
Receive a packet.
#define ENET_RDES3_BUF1V
#define osExitIsr(flag)
Transmit descriptor.
uint16_t lpc546xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define SMI_OPCODE_WRITE
Definition: nic.h:62
void lpc546xxEthInitGpio(NetInterface *interface)
#define LPC546XX_ETH_IRQ_GROUP_PRIORITY
#define ENET_TDES3_FD
#define FALSE
Definition: os_port.h:46
#define ENET_RDES3_PL
error_t lpc546xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define LPC546XX_ETH_RX_BUFFER_SIZE
error_t
Error codes.
Definition: error.h:42
error_t lpc546xxEthInit(NetInterface *interface)
LPC546xx Ethernet MAC initialization.
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetInterface
Definition: net.h:36
#define ENET_RDES3_OWN
OsEvent netEvent
Definition: net.c:77
#define SMI_OPCODE_READ
Definition: nic.h:63
#define ENET_TDES2_B1L
#define LPC546XX_ETH_IRQ_SUB_PRIORITY
#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 MIN(a, b)
Definition: os_port.h:62
#define rxBuffer
void lpc546xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define TRACE_DEBUG(...)
Definition: debug.h:106
#define LPC546XX_ETH_RX_BUFFER_COUNT
#define ENET_RDES3_FD
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:91
#define ENET_TDES3_OWN
uint8_t n
void lpc546xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define osEnterIsr()
void lpc546xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define LPC546XX_ETH_TX_BUFFER_COUNT
#define txDmaDesc
#define LPC546XX_ETH_TX_BUFFER_SIZE
#define ENET_RDES3_IOC
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
void lpc546xxEthEventHandler(NetInterface *interface)
LPC546xx Ethernet MAC event handler.
NIC driver.
Definition: nic.h:179
error_t lpc546xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define ENET_TDES3_LD
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
void lpc546xxEthTick(NetInterface *interface)
LPC546xx Ethernet MAC timer handler.
Ethernet interface.
Definition: nic.h:79