pic32mx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file pic32mx_eth_driver.c
3  * @brief PIC32MX Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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 2.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <p32xxxx.h>
36 #include <sys/kmem.h>
37 #include "core/net.h"
39 #include "debug.h"
40 
41 //Underlying network interface
42 static NetInterface *nicDriverInterface;
43 
44 //Transmit buffer
46  __attribute__((coherent, aligned(4)));
47 //Receive buffer
49  __attribute__((coherent, aligned(4)));
50 //Transmit buffer descriptors
52  __attribute__((coherent, aligned(4)));
53 //Receive buffer descriptors
55  __attribute__((coherent, aligned(4)));
56 
57 //Pointer to the current TX buffer descriptor
58 static Pic32mxTxBufferDesc *txCurBufferDesc;
59 //Pointer to the current RX buffer descriptor
60 static Pic32mxRxBufferDesc *rxCurBufferDesc;
61 
62 
63 /**
64  * @brief PIC32MX Ethernet MAC driver
65  **/
66 
68 {
70  ETH_MTU,
81  TRUE,
82  TRUE,
83  TRUE,
84  FALSE
85 };
86 
87 
88 /**
89  * @brief PIC32MX Ethernet MAC initialization
90  * @param[in] interface Underlying network interface
91  * @return Error code
92  **/
93 
95 {
96  error_t error;
97 
98  //Debug message
99  TRACE_INFO("Initializing PIC32MX Ethernet MAC...\r\n");
100 
101  //Save underlying network interface
102  nicDriverInterface = interface;
103 
104  //GPIO configuration
105  pic32mxEthInitGpio(interface);
106 
107  //Disable Ethernet interrupts
108  IEC1CLR = _IEC1_ETHIE_MASK;
109  //Turn the Ethernet controller off
110  ETHCON1CLR = _ETHCON1_ON_MASK | _ETHCON1_TXRTS_POSITION | _ETHCON1_RXEN_MASK;
111 
112  //Wait activity abort by polling the ETHBUSY bit
113  while((ETHSTAT & _ETHSTAT_ETHBUSY_MASK) != 0)
114  {
115  }
116 
117  //Enable the Ethernet controller by setting the ON bit
118  ETHCON1SET = _ETHCON1_ON_MASK;
119  //Clear Ethernet interrupt flag
120  IFS1CLR = _IFS1_ETHIF_MASK;
121 
122  //Disable any Ethernet controller interrupt generation
123  ETHIEN = 0;
124  ETHIRQ = 0;
125 
126  //Clear the TX and RX start addresses
127  ETHTXST = 0;
128  ETHRXST = 0;
129 
130  //Reset the MAC using SOFTRESET
131  EMAC1CFG1SET = _EMAC1CFG1_SOFTRESET_MASK;
132  EMAC1CFG1CLR = _EMAC1CFG1_SOFTRESET_MASK;
133 
134  //Reset the RMII module
135  EMAC1SUPPSET = _EMAC1SUPP_RESETRMII_MASK;
136  EMAC1SUPPCLR = _EMAC1SUPP_RESETRMII_MASK;
137 
138  //Issue an MIIM block reset by setting the RESETMGMT bit
139  EMAC1MCFGSET = _EMAC1MCFG_RESETMGMT_MASK;
140  EMAC1MCFGCLR = _EMAC1MCFG_RESETMGMT_MASK;
141 
142  //Select the proper divider for the MDC clock
143  EMAC1MCFG = _EMAC1MCFG_CLKSEL_DIV40;
144 
145  //Valid Ethernet PHY or switch driver?
146  if(interface->phyDriver != NULL)
147  {
148  //Ethernet PHY initialization
149  error = interface->phyDriver->init(interface);
150  }
151  else if(interface->switchDriver != NULL)
152  {
153  //Ethernet switch initialization
154  error = interface->switchDriver->init(interface);
155  }
156  else
157  {
158  //The interface is not properly configured
159  error = ERROR_FAILURE;
160  }
161 
162  //Any error to report?
163  if(error)
164  {
165  return error;
166  }
167 
168  //Optionally set the station MAC address
169  if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
170  {
171  //Use the factory preprogrammed station address
172  interface->macAddr.w[0] = EMAC1SA2;
173  interface->macAddr.w[1] = EMAC1SA1;
174  interface->macAddr.w[2] = EMAC1SA0;
175 
176  //Generate the 64-bit interface identifier
177  macAddrToEui64(&interface->macAddr, &interface->eui64);
178  }
179  else
180  {
181  //Override the factory preprogrammed address
182  EMAC1SA0 = interface->macAddr.w[2];
183  EMAC1SA1 = interface->macAddr.w[1];
184  EMAC1SA2 = interface->macAddr.w[0];
185  }
186 
187  //Initialize hash table
188  ETHHT0 = 0;
189  ETHHT1 = 0;
190 
191  //Configure the receive filter
192  ETHRXFC = _ETHRXFC_HTEN_MASK | _ETHRXFC_CRCOKEN_MASK |
193  _ETHRXFC_RUNTEN_MASK | _ETHRXFC_UCEN_MASK | _ETHRXFC_BCEN_MASK;
194 
195  //Disable flow control
196  EMAC1CFG1 = _EMAC1CFG1_RXENABLE_MASK;
197  //Automatic padding and CRC generation
198  EMAC1CFG2 = _EMAC1CFG2_PADENABLE_MASK | _EMAC1CFG2_CRCENABLE_MASK;
199  //Set the maximum frame length
200  EMAC1MAXF = PIC32MX_ETH_RX_BUFFER_SIZE;
201 
202  //Initialize DMA descriptor lists
203  pic32mxEthInitBufferDesc(interface);
204 
205  //Enable desired interrupts
206  ETHIENSET = _ETHIEN_PKTPENDIE_MASK | _ETHIEN_TXDONEIE_MASK;
207 
208  //Set interrupt priority
209  IPC12CLR = _IPC12_ETHIP_MASK;
210  IPC12SET = (PIC32MX_ETH_IRQ_PRIORITY << _IPC12_ETHIP_POSITION);
211  //Set interrupt subpriority
212  IPC12CLR = _IPC12_ETHIS_MASK;
213  IPC12SET = (PIC32MX_ETH_IRQ_SUB_PRIORITY << _IPC12_ETHIS_POSITION);
214 
215  //Enable the reception by setting the RXEN bit
216  ETHCON1SET = _ETHCON1_RXEN_MASK;
217 
218  //Accept any packets from the upper layer
219  osSetEvent(&interface->nicTxEvent);
220 
221  //Successful initialization
222  return NO_ERROR;
223 }
224 
225 
226 /**
227  * @brief GPIO configuration
228  * @param[in] interface Underlying network interface
229  **/
230 
231 __weak_func void pic32mxEthInitGpio(NetInterface *interface)
232 {
233 }
234 
235 
236 /**
237  * @brief Initialize DMA descriptor lists
238  * @param[in] interface Underlying network interface
239  **/
240 
242 {
243  uint_t i;
244 
245  //Initialize TX descriptor list
246  for(i = 0; i < PIC32MX_ETH_TX_BUFFER_COUNT; i++)
247  {
248  //Point to the current descriptor
249  txCurBufferDesc = &txBufferDesc[i];
250 
251  //Use linked list rather than linear list
252  txCurBufferDesc->control = ETH_TX_CTRL_NPV;
253  //Transmit buffer address
254  txCurBufferDesc->address = KVA_TO_PA(txBuffer[i]);
255  //Transmit status vector
256  txCurBufferDesc->status1 = 0;
257  txCurBufferDesc->status2 = 0;
258  //Next descriptor address
259  txCurBufferDesc->next = KVA_TO_PA(&txBufferDesc[i + 1]);
260  }
261 
262  //The last descriptor is chained to the first entry
263  txCurBufferDesc->next = KVA_TO_PA(&txBufferDesc[0]);
264  //Point to the very first descriptor
265  txCurBufferDesc = &txBufferDesc[0];
266 
267  //Initialize RX descriptor list
268  for(i = 0; i < PIC32MX_ETH_RX_BUFFER_COUNT; i++)
269  {
270  //Point to the current descriptor
271  rxCurBufferDesc = &rxBufferDesc[i];
272 
273  //The descriptor is initially owned by the DMA
274  rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
275  //Receive buffer address
276  rxCurBufferDesc->address = KVA_TO_PA(rxBuffer[i]);
277  //Receive status vector
278  rxCurBufferDesc->status1 = 0;
279  rxCurBufferDesc->status2 = 0;
280  //Next descriptor address
281  rxCurBufferDesc->next = KVA_TO_PA(&rxBufferDesc[i + 1]);
282  }
283 
284  //The last descriptor is chained to the first entry
285  rxCurBufferDesc->next = KVA_TO_PA(&rxBufferDesc[0]);
286  //Point to the very first descriptor
287  rxCurBufferDesc = &rxBufferDesc[0];
288 
289  //Starting address of TX descriptor table
290  ETHTXST = KVA_TO_PA(&txBufferDesc[0]);
291  //Starting address of RX descriptor table
292  ETHRXST = KVA_TO_PA(&rxBufferDesc[0]);
293  //Set receive buffer size
294  ETHCON2 = PIC32MX_ETH_RX_BUFFER_SIZE;
295 }
296 
297 
298 /**
299  * @brief PIC32MX Ethernet MAC timer handler
300  *
301  * This routine is periodically called by the TCP/IP stack to handle periodic
302  * operations such as polling the link state
303  *
304  * @param[in] interface Underlying network interface
305  **/
306 
307 void pic32mxEthTick(NetInterface *interface)
308 {
309  //Valid Ethernet PHY or switch driver?
310  if(interface->phyDriver != NULL)
311  {
312  //Handle periodic operations
313  interface->phyDriver->tick(interface);
314  }
315  else if(interface->switchDriver != NULL)
316  {
317  //Handle periodic operations
318  interface->switchDriver->tick(interface);
319  }
320  else
321  {
322  //Just for sanity
323  }
324 }
325 
326 
327 /**
328  * @brief Enable interrupts
329  * @param[in] interface Underlying network interface
330  **/
331 
333 {
334  //Enable Ethernet MAC interrupts
335  IEC1SET = _IEC1_ETHIE_MASK;
336 
337  //Valid Ethernet PHY or switch driver?
338  if(interface->phyDriver != NULL)
339  {
340  //Enable Ethernet PHY interrupts
341  interface->phyDriver->enableIrq(interface);
342  }
343  else if(interface->switchDriver != NULL)
344  {
345  //Enable Ethernet switch interrupts
346  interface->switchDriver->enableIrq(interface);
347  }
348  else
349  {
350  //Just for sanity
351  }
352 }
353 
354 
355 /**
356  * @brief Disable interrupts
357  * @param[in] interface Underlying network interface
358  **/
359 
361 {
362  //Disable Ethernet MAC interrupts
363  IEC1CLR = _IEC1_ETHIE_MASK;
364 
365  //Valid Ethernet PHY or switch driver?
366  if(interface->phyDriver != NULL)
367  {
368  //Disable Ethernet PHY interrupts
369  interface->phyDriver->disableIrq(interface);
370  }
371  else if(interface->switchDriver != NULL)
372  {
373  //Disable Ethernet switch interrupts
374  interface->switchDriver->disableIrq(interface);
375  }
376  else
377  {
378  //Just for sanity
379  }
380 }
381 
382 
383 /**
384  * @brief PIC32MX Ethernet MAC interrupt service routine
385  **/
386 
388 {
389  bool_t flag;
390  uint32_t status;
391 
392  //Interrupt service routine prologue
393  osEnterIsr();
394 
395  //This flag will be set if a higher priority task must be woken
396  flag = FALSE;
397 
398  //Read interrupt status register
399  status = ETHIRQ;
400 
401  //Packet transmitted?
402  if((status & _ETHIRQ_TXDONE_MASK) != 0)
403  {
404  //Clear TXDONE interrupt flag
405  ETHIRQCLR = _ETHIRQ_TXDONE_MASK;
406 
407  //Check whether the TX buffer is available for writing
408  if((txCurBufferDesc->control & ETH_TX_CTRL_EOWN) == 0)
409  {
410  //Notify the TCP/IP stack that the transmitter is ready to send
411  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
412  }
413  }
414 
415  //Packet received?
416  if((status & _ETHIRQ_PKTPEND_MASK) != 0)
417  {
418  //Disable PKTPEND interrupt
419  ETHIENCLR = _ETHIEN_PKTPENDIE_MASK;
420 
421  //Set event flag
422  nicDriverInterface->nicEvent = TRUE;
423  //Notify the TCP/IP stack of the event
424  flag |= osSetEventFromIsr(&netEvent);
425  }
426 
427  //Clear ETHIF interrupt flag before exiting the service routine
428  IFS1CLR = _IFS1_ETHIF_MASK;
429 
430  //Interrupt service routine epilogue
431  osExitIsr(flag);
432 }
433 
434 
435 /**
436  * @brief PIC32MX Ethernet MAC event handler
437  * @param[in] interface Underlying network interface
438  **/
439 
441 {
442  error_t error;
443 
444  //Packet received?
445  if((ETHIRQ & _ETHIRQ_PKTPEND_MASK) != 0)
446  {
447  //Process all pending packets
448  do
449  {
450  //Read incoming packet
451  error = pic32mxEthReceivePacket(interface);
452 
453  //No more data in the receive buffer?
454  } while(error != ERROR_BUFFER_EMPTY);
455  }
456 
457  //Re-enable PKTPEND interrupt
458  ETHIENSET = _ETHIEN_PKTPENDIE_MASK;
459 }
460 
461 
462 /**
463  * @brief Send a packet
464  * @param[in] interface Underlying network interface
465  * @param[in] buffer Multi-part buffer containing the data to send
466  * @param[in] offset Offset to the first data byte
467  * @param[in] ancillary Additional options passed to the stack along with
468  * the packet
469  * @return Error code
470  **/
471 
473  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
474 {
475  size_t length;
476  uint32_t value;
477 
478  //Retrieve the length of the packet
479  length = netBufferGetLength(buffer) - offset;
480 
481  //Check the frame length
483  {
484  //The transmitter can accept another packet
485  osSetEvent(&interface->nicTxEvent);
486  //Report an error
487  return ERROR_INVALID_LENGTH;
488  }
489 
490  //Make sure the current buffer is available for writing
491  if((txCurBufferDesc->control & ETH_TX_CTRL_EOWN) != 0)
492  {
493  return ERROR_FAILURE;
494  }
495 
496  //Copy user data to the transmit buffer
497  netBufferRead(PA_TO_KVA1(txCurBufferDesc->address), buffer, offset, length);
498 
499  //Write the number of bytes to send
500  value = (length << 16) & ETH_TX_CTRL_BYTE_COUNT;
501  //Set SOP and EOP flags since the data fits in a single buffer
503  //Give the ownership of the descriptor to the DMA
504  txCurBufferDesc->control = value | ETH_TX_CTRL_EOWN;
505 
506  //Set TXRTS bit to start the transmission
507  ETHCON1SET = _ETHCON1_TXRTS_MASK;
508 
509  //Point to the next descriptor in the list
510  txCurBufferDesc = PA_TO_KVA1(txCurBufferDesc->next);
511 
512  //Check whether the next buffer is available for writing
513  if((txCurBufferDesc->control & ETH_TX_CTRL_EOWN) == 0)
514  {
515  //The transmitter can accept another packet
516  osSetEvent(&interface->nicTxEvent);
517  }
518 
519  //Data successfully written
520  return NO_ERROR;
521 }
522 
523 
524 /**
525  * @brief Receive a packet
526  * @param[in] interface Underlying network interface
527  * @return Error code
528  **/
529 
531 {
532  static uint32_t temp[PIC32MX_ETH_RX_BUFFER_SIZE / 4];
533  error_t error;
534  size_t n;
535  NetRxAncillary ancillary;
536 
537  //Current buffer available for reading?
538  if((rxCurBufferDesc->control & ETH_RX_CTRL_EOWN) == 0)
539  {
540  //SOP and EOP flags should be set
541  if((rxCurBufferDesc->control & ETH_RX_CTRL_SOP) != 0 &&
542  (rxCurBufferDesc->control & ETH_RX_CTRL_EOP) != 0)
543  {
544  //Make sure no error occurred
545  if((rxCurBufferDesc->status2 & ETH_RX_STATUS2_OK) != 0)
546  {
547  //Retrieve the length of the frame
548  n = (rxCurBufferDesc->control & ETH_RX_CTRL_BYTE_COUNT) >> 16;
549  //Limit the number of data to read
551 
552  //Copy data from the receive buffer
553  osMemcpy(temp, PA_TO_KVA1(rxCurBufferDesc->address), n);
554 
555  //Additional options can be passed to the stack along with the packet
556  ancillary = NET_DEFAULT_RX_ANCILLARY;
557 
558  //Pass the packet to the upper layer
559  nicProcessPacket(interface, (uint8_t *) temp, n, &ancillary);
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  //Give the ownership of the descriptor back to the DMA
577  rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
578 
579  //Point to the next descriptor in the list
580  rxCurBufferDesc = PA_TO_KVA1(rxCurBufferDesc->next);
581 
582  //Once software processes a received packet, it should write the BUFCDEC
583  //bit in order to decrement the packet buffer count BUFCNT
584  ETHCON1SET = _ETHCON1_BUFCDEC_MASK;
585  }
586  else
587  {
588  //No more data in the receive buffer
589  error = ERROR_BUFFER_EMPTY;
590  }
591 
592  //Return status code
593  return error;
594 }
595 
596 
597 /**
598  * @brief Configure MAC address filtering
599  * @param[in] interface Underlying network interface
600  * @return Error code
601  **/
602 
604 {
605  uint_t i;
606  uint_t k;
607  uint32_t crc;
608  uint32_t hashTable[2];
609  MacFilterEntry *entry;
610 
611  //Debug message
612  TRACE_DEBUG("Updating MAC filter...\r\n");
613 
614  //Clear hash table
615  hashTable[0] = 0;
616  hashTable[1] = 0;
617 
618  //The MAC address filter contains the list of MAC addresses to accept
619  //when receiving an Ethernet frame
620  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
621  {
622  //Point to the current entry
623  entry = &interface->macAddrFilter[i];
624 
625  //Valid entry?
626  if(entry->refCount > 0)
627  {
628  //Compute CRC over the current MAC address
629  crc = pic32mxEthCalcCrc(&entry->addr, sizeof(MacAddr));
630  //Calculate the corresponding index in the table
631  k = (crc >> 23) & 0x3F;
632  //Update hash table contents
633  hashTable[k / 32] |= (1 << (k % 32));
634  }
635  }
636 
637  //Write the hash table
638  ETHHT0 = hashTable[0];
639  ETHHT1 = hashTable[1];
640 
641  //Debug message
642  TRACE_DEBUG(" ETHHT0 = %08" PRIX32 "\r\n", ETHHT0);
643  TRACE_DEBUG(" ETHHT1 = %08" PRIX32 "\r\n", ETHHT1);
644 
645  //Successful processing
646  return NO_ERROR;
647 }
648 
649 
650 /**
651  * @brief Adjust MAC configuration parameters for proper operation
652  * @param[in] interface Underlying network interface
653  * @return Error code
654  **/
655 
657 {
658  //Check current operating speed
659  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
660  {
661  //100BASE-TX operation mode
662  EMAC1SUPPSET = _EMAC1SUPP_SPEEDRMII_MASK;
663  }
664  else
665  {
666  //10BASE-T operation mode
667  EMAC1SUPPCLR = _EMAC1SUPP_SPEEDRMII_MASK;
668  }
669 
670  //Half-duplex or full-duplex mode?
671  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
672  {
673  //Configure FULLDPLX bit to match the current duplex mode
674  EMAC1CFG2SET = _EMAC1CFG2_FULLDPLX_MASK;
675  //Configure the Back-to-Back Inter-Packet Gap register
676  EMAC1IPGT = 0x15;
677  }
678  else
679  {
680  //Configure FULLDPLX bit to match the current duplex mode
681  EMAC1CFG2CLR = _EMAC1CFG2_FULLDPLX_MASK;
682  //Configure the Back-to-Back Inter-Packet Gap register
683  EMAC1IPGT = 0x12;
684  }
685 
686  //Successful processing
687  return NO_ERROR;
688 }
689 
690 
691 /**
692  * @brief Write PHY register
693  * @param[in] opcode Access type (2 bits)
694  * @param[in] phyAddr PHY address (5 bits)
695  * @param[in] regAddr Register address (5 bits)
696  * @param[in] data Register value
697  **/
698 
699 void pic32mxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
700  uint8_t regAddr, uint16_t data)
701 {
702  //Valid opcode?
703  if(opcode == SMI_OPCODE_WRITE)
704  {
705  //Set PHY address and register address
706  EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
707  //Start a write operation
708  EMAC1MWTD = data & _EMAC1MWTD_MWTD_MASK;
709 
710  //Wait for busy bit to be set
711  __asm__ __volatile__ ("nop;");
712  __asm__ __volatile__ ("nop;");
713  __asm__ __volatile__ ("nop;");
714 
715  //Wait for the write to complete
716  while((EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK) != 0)
717  {
718  }
719  }
720  else
721  {
722  //The MAC peripheral only supports standard Clause 22 opcodes
723  }
724 }
725 
726 
727 /**
728  * @brief Read PHY register
729  * @param[in] opcode Access type (2 bits)
730  * @param[in] phyAddr PHY address (5 bits)
731  * @param[in] regAddr Register address (5 bits)
732  * @return Register value
733  **/
734 
735 uint16_t pic32mxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
736  uint8_t regAddr)
737 {
738  uint16_t data;
739 
740  //Valid opcode?
741  if(opcode == SMI_OPCODE_READ)
742  {
743  //Set PHY address and register address
744  EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
745  //Start a read operation
746  EMAC1MCMD = _EMAC1MCMD_READ_MASK;
747 
748  //Wait for busy bit to be set
749  __asm__ __volatile__ ("nop;");
750  __asm__ __volatile__ ("nop;");
751  __asm__ __volatile__ ("nop;");
752 
753  //Wait for the read to complete
754  while((EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK) != 0)
755  {
756  }
757 
758  //Clear command register
759  EMAC1MCMD = 0;
760  //Get register value
761  data = EMAC1MRDD & _EMAC1MRDD_MRDD_MASK;
762  }
763  else
764  {
765  //The MAC peripheral only supports standard Clause 22 opcodes
766  data = 0;
767  }
768 
769  //Return the value of the PHY register
770  return data;
771 }
772 
773 
774 /**
775  * @brief CRC calculation
776  * @param[in] data Pointer to the data over which to calculate the CRC
777  * @param[in] length Number of bytes to process
778  * @return Resulting CRC value
779  **/
780 
781 uint32_t pic32mxEthCalcCrc(const void *data, size_t length)
782 {
783  uint_t i;
784  uint_t j;
785  uint32_t crc;
786  const uint8_t *p;
787 
788  //Point to the data over which to calculate the CRC
789  p = (uint8_t *) data;
790  //CRC preset value
791  crc = 0xFFFFFFFF;
792 
793  //Loop through data
794  for(i = 0; i < length; i++)
795  {
796  //The message is processed bit by bit
797  for(j = 0; j < 8; j++)
798  {
799  //Update CRC value
800  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
801  {
802  crc = (crc << 1) ^ 0x04C11DB7;
803  }
804  else
805  {
806  crc = crc << 1;
807  }
808  }
809  }
810 
811  //Return CRC value
812  return crc;
813 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define ETH_TX_CTRL_BYTE_COUNT
#define PIC32MX_ETH_RX_BUFFER_COUNT
#define PIC32MX_ETH_RX_BUFFER_SIZE
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:61
#define netEvent
Definition: net_legacy.h:196
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
error_t pic32mxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Map a MAC address to the IPv6 modified EUI-64 identifier.
Definition: ethernet.c:946
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:690
#define ETH_RX_CTRL_SOP
#define ETH_RX_CTRL_NPV
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
error_t pic32mxEthInit(NetInterface *interface)
PIC32MX Ethernet MAC initialization.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
void pic32mxEthInitBufferDesc(NetInterface *interface)
Initialize DMA descriptor lists.
error_t pic32mxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:392
#define osExitIsr(flag)
#define ETH_RX_CTRL_EOP
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define PIC32MX_ETH_IRQ_PRIORITY
void pic32mxEthTick(NetInterface *interface)
PIC32MX Ethernet MAC timer handler.
#define ETH_TX_CTRL_EOP
uint16_t pic32mxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define ETH_TX_CTRL_SOP
#define FALSE
Definition: os_port.h:46
#define ETH_RX_CTRL_EOWN
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
void pic32mxEthIrqHandler(void)
PIC32MX Ethernet MAC interrupt service routine.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:105
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define PIC32MX_ETH_IRQ_SUB_PRIORITY
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:36
#define PIC32MX_ETH_TX_BUFFER_COUNT
MacAddr addr
MAC address.
Definition: ethernet.h:263
#define ETH_TX_CTRL_NPV
@ ERROR_INVALID_LENGTH
Definition: error.h:111
PIC32MX Ethernet MAC driver.
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
__weak_func void pic32mxEthInitGpio(NetInterface *interface)
GPIO configuration.
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
error_t pic32mxEthReceivePacket(NetInterface *interface)
Receive a packet.
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define PIC32MX_ETH_TX_BUFFER_SIZE
#define MIN(a, b)
Definition: os_port.h:63
#define rxBuffer
MacAddr
Definition: ethernet.h:195
uint32_t pic32mxEthCalcCrc(const void *data, size_t length)
CRC calculation.
#define TRACE_DEBUG(...)
Definition: debug.h:119
void pic32mxEthEventHandler(NetInterface *interface)
PIC32MX Ethernet MAC event handler.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:262
#define osEnterIsr()
uint8_t value[]
Definition: tcp.h:376
RX buffer descriptor.
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
void pic32mxEthEnableIrq(NetInterface *interface)
Enable interrupts.
error_t pic32mxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
TX buffer descriptor.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define ETH_RX_CTRL_BYTE_COUNT
unsigned int uint_t
Definition: compiler_port.h:57
#define ETH_TX_CTRL_EOWN
TCP/IP stack core.
void pic32mxEthDisableIrq(NetInterface *interface)
Disable interrupts.
NIC driver.
Definition: nic.h:286
const NicDriver pic32mxEthDriver
PIC32MX Ethernet MAC driver.
void pic32mxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
#define ETH_RX_STATUS2_OK
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define _EMAC1MCFG_CLKSEL_DIV40