pic32mz_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file pic32mz_eth_driver.c
3  * @brief PIC32MZ 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 Pic32mzTxBufferDesc *txCurBufferDesc;
59 //Pointer to the current RX buffer descriptor
60 static Pic32mzRxBufferDesc *rxCurBufferDesc;
61 
62 
63 /**
64  * @brief PIC32MZ Ethernet MAC driver
65  **/
66 
68 {
70  ETH_MTU,
81  TRUE,
82  TRUE,
83  TRUE,
84  FALSE
85 };
86 
87 
88 /**
89  * @brief PIC32MZ 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 PIC32MZ Ethernet MAC...\r\n");
100 
101  //Save underlying network interface
102  nicDriverInterface = interface;
103 
104  //GPIO configuration
105  pic32mzEthInitGpio(interface);
106 
107  //Disable Ethernet interrupts
108  ETH_CLEAR_ETHIE();
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  ETH_CLEAR_ETHIF();
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_DIV50;
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 = PIC32MZ_ETH_RX_BUFFER_SIZE;
201 
202  //Initialize DMA descriptor lists
203  pic32mzEthInitBufferDesc(interface);
204 
205  //Enable desired interrupts
206  ETHIENSET = _ETHIEN_PKTPENDIE_MASK | _ETHIEN_TXDONEIE_MASK;
207 
208  //Set interrupt priority
210  //Set interrupt subpriority
212 
213  //Enable the reception by setting the RXEN bit
214  ETHCON1SET = _ETHCON1_RXEN_MASK;
215 
216  //Accept any packets from the upper layer
217  osSetEvent(&interface->nicTxEvent);
218 
219  //Successful initialization
220  return NO_ERROR;
221 }
222 
223 
224 /**
225  * @brief GPIO configuration
226  * @param[in] interface Underlying network interface
227  **/
228 
229 __weak_func void pic32mzEthInitGpio(NetInterface *interface)
230 {
231 //PIC32MZ EC Starter Kit?
232 #if defined(USE_PIC32MZ_EC_STARTER_KIT)
233  //Disable analog pad on ETXD0 (AN35/RJ8)
234  ANSELJCLR = _ANSELJ_ANSJ8_MASK;
235  //Disable analog pad on ETXD1 (AN36/RJ9)
236  ANSELJCLR = _ANSELJ_ANSJ9_MASK;
237  //Disable analog pad on EREFCLK (AN37/RJ11)
238  ANSELJCLR = _ANSELJ_ANSJ11_MASK;
239  //Disable analog pad on ERXERR (AN40/RH4)
240  ANSELHCLR = _ANSELH_ANSH4_MASK;
241  //Disable analog pad on ERXD1 (AN41/RH5)
242  ANSELHCLR = _ANSELH_ANSH5_MASK;
243 
244 //PIC32MZ EF Starter Kit?
245 #elif defined(USE_PIC32MZ_EF_STARTER_KIT)
246  //Disable analog pad on ETXD0 (AN35/RJ8)
247  ANSELJCLR = _ANSELJ_ANSJ8_MASK;
248  //Disable analog pad on ETXD1 (AN36/RJ9)
249  ANSELJCLR = _ANSELJ_ANSJ9_MASK;
250  //Disable analog pad on EREFCLK (AN37/RJ11)
251  ANSELJCLR = _ANSELJ_ANSJ11_MASK;
252  //Disable analog pad on ERXERR (AN40/RH4)
253  ANSELHCLR = _ANSELH_ANSH4_MASK;
254  //Disable analog pad on ERXD1 (AN41/RH5)
255  ANSELHCLR = _ANSELH_ANSH5_MASK;
256 
257  //Configure PHY_RST (RH11)
258  TRISHCLR = _TRISH_TRISH11_MASK;
259 
260  //Reset PHY transceiver (hard reset)
261  LATHCLR = _LATH_LATH11_MASK;
262  sleep(10);
263  LATHSET = _LATH_LATH11_MASK;
264  sleep(10);
265 
266 //PIC32MZ DA Starter Kit?
267 #elif defined(USE_PIC32MZ_DA_STARTER_KIT)
268  //Configure PHY_RST (RJ15)
269  TRISJCLR = _TRISJ_TRISJ15_MASK;
270 
271  //Reset PHY transceiver (hard reset)
272  LATJCLR = _LATJ_LATJ15_MASK;
273  sleep(10);
274  LATJSET = _LATJ_LATJ15_MASK;
275  sleep(10);
276 
277 //PIC32MZ EF Curiosity?
278 #elif defined(USE_PIC32MZ_EF_CURIOSITY)
279  //Disable analog pad on ERXERR (AN6/RB11)
280  ANSELBCLR = _ANSELB_ANSB11_MASK;
281  //Disable analog pad on ERXD0 (AN7/RB12)
282  ANSELBCLR = _ANSELB_ANSB12_MASK;
283  //Disable analog pad on ERXD1 (AN8/RB13)
284  ANSELBCLR = _ANSELB_ANSB13_MASK;
285  //Disable analog pad on ERXDV (AN12/RG8)
286  ANSELGCLR = _ANSELG_ANSG8_MASK;
287  //Disable analog pad on EREFCLK (AN11/RG9)
288  ANSELGCLR = _ANSELG_ANSG9_MASK;
289 
290  //Configure PHY_RST (AN23/RG15)
291  TRISGCLR = _TRISG_TRISG15_MASK;
292  //Disable analog pad
293  ANSELGCLR = _ANSELG_ANSG15_MASK;
294 
295  //Reset PHY transceiver (hard reset)
296  LATGCLR = _LATG_LATG15_MASK;
297  sleep(10);
298  LATGSET = _LATG_LATG15_MASK;
299  sleep(10);
300 
301 //PIC32MZ EF Curiosity 2.0?
302 #elif defined(USE_PIC32MZ_EF_CURIOSITY_2)
303  //Disable analog pad on ETXD0 (AN35/RJ8)
304  ANSELJCLR = _ANSELJ_ANSJ8_MASK;
305  //Disable analog pad on ETXD1 (AN36/RJ9)
306  ANSELJCLR = _ANSELJ_ANSJ9_MASK;
307  //Disable analog pad on EREFCLK (AN37/RJ11)
308  ANSELJCLR = _ANSELJ_ANSJ11_MASK;
309  //Disable analog pad on ERXERR (AN40/RH4)
310  ANSELHCLR = _ANSELH_ANSH4_MASK;
311  //Disable analog pad on ERXD1 (AN41/RH5)
312  ANSELHCLR = _ANSELH_ANSH5_MASK;
313 
314 //PIC32MZ DA Curiosity?
315 #elif defined(USE_PIC32MZ_DA_CURIOSITY)
316  //Configure PHY_RST (AN39/RE1)
317  TRISECLR = _TRISE_TRISE1_MASK;
318  //Disable analog pad
319  ANSELECLR = _ANSELE_ANSE1_MASK;
320 
321  //Reset PHY transceiver (hard reset)
322  LATECLR = _LATE_LATE1_MASK;
323  sleep(10);
324  LATESET = _LATE_LATE1_MASK;
325  sleep(10);
326 
327 //IoT Ethernet Kit?
328 #elif defined(USE_IOT_ETHERNET_KIT)
329  //Disable analog pad on ERXERR (AN18/RE4)
330  ANSELECLR = _ANSELE_ANSE4_MASK;
331  //Disable analog pad on ETXEN (AN17/RE5)
332  ANSELECLR = _ANSELE_ANSE5_MASK;
333  //Disable analog pad on ETXD0 (AN16/RE6)
334  ANSELECLR = _ANSELE_ANSE6_MASK;
335  //Disable analog pad on ETXD1 (AN15/RE7)
336  ANSELECLR = _ANSELE_ANSE7_MASK;
337 
338  //Configure PHY_RST (AN9/RB14)
339  TRISBCLR = _TRISB_TRISB14_MASK;
340  //Disable analog pad
341  ANSELBCLR = _ANSELB_ANSB14_MASK;
342 
343  //Reset PHY transceiver (hard reset)
344  LATBCLR = _LATB_LATB14_MASK;
345  sleep(10);
346  LATBSET = _LATB_LATB14_MASK;
347  sleep(10);
348 #endif
349 }
350 
351 
352 /**
353  * @brief Initialize DMA descriptor lists
354  * @param[in] interface Underlying network interface
355  **/
356 
358 {
359  uint_t i;
360 
361  //Initialize TX descriptor list
362  for(i = 0; i < PIC32MZ_ETH_TX_BUFFER_COUNT; i++)
363  {
364  //Point to the current descriptor
365  txCurBufferDesc = &txBufferDesc[i];
366 
367  //Use linked list rather than linear list
368  txCurBufferDesc->control = ETH_TX_CTRL_NPV;
369  //Transmit buffer address
370  txCurBufferDesc->address = KVA_TO_PA(txBuffer[i]);
371  //Transmit status vector
372  txCurBufferDesc->status1 = 0;
373  txCurBufferDesc->status2 = 0;
374  //Next descriptor address
375  txCurBufferDesc->next = KVA_TO_PA(&txBufferDesc[i + 1]);
376  }
377 
378  //The last descriptor is chained to the first entry
379  txCurBufferDesc->next = KVA_TO_PA(&txBufferDesc[0]);
380  //Point to the very first descriptor
381  txCurBufferDesc = &txBufferDesc[0];
382 
383  //Initialize RX descriptor list
384  for(i = 0; i < PIC32MZ_ETH_RX_BUFFER_COUNT; i++)
385  {
386  //Point to the current descriptor
387  rxCurBufferDesc = &rxBufferDesc[i];
388 
389  //The descriptor is initially owned by the DMA
390  rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
391  //Receive buffer address
392  rxCurBufferDesc->address = KVA_TO_PA(rxBuffer[i]);
393  //Receive status vector
394  rxCurBufferDesc->status1 = 0;
395  rxCurBufferDesc->status2 = 0;
396  //Next descriptor address
397  rxCurBufferDesc->next = KVA_TO_PA(&rxBufferDesc[i + 1]);
398  }
399 
400  //The last descriptor is chained to the first entry
401  rxCurBufferDesc->next = KVA_TO_PA(&rxBufferDesc[0]);
402  //Point to the very first descriptor
403  rxCurBufferDesc = &rxBufferDesc[0];
404 
405  //Starting address of TX descriptor table
406  ETHTXST = KVA_TO_PA(&txBufferDesc[0]);
407  //Starting address of RX descriptor table
408  ETHRXST = KVA_TO_PA(&rxBufferDesc[0]);
409  //Set receive buffer size
410  ETHCON2 = PIC32MZ_ETH_RX_BUFFER_SIZE;
411 }
412 
413 
414 /**
415  * @brief PIC32MZ Ethernet MAC timer handler
416  *
417  * This routine is periodically called by the TCP/IP stack to handle periodic
418  * operations such as polling the link state
419  *
420  * @param[in] interface Underlying network interface
421  **/
422 
423 void pic32mzEthTick(NetInterface *interface)
424 {
425  //Valid Ethernet PHY or switch driver?
426  if(interface->phyDriver != NULL)
427  {
428  //Handle periodic operations
429  interface->phyDriver->tick(interface);
430  }
431  else if(interface->switchDriver != NULL)
432  {
433  //Handle periodic operations
434  interface->switchDriver->tick(interface);
435  }
436  else
437  {
438  //Just for sanity
439  }
440 }
441 
442 
443 /**
444  * @brief Enable interrupts
445  * @param[in] interface Underlying network interface
446  **/
447 
449 {
450  //Enable Ethernet MAC interrupts
451  ETH_SET_ETHIE();
452 
453  //Valid Ethernet PHY or switch driver?
454  if(interface->phyDriver != NULL)
455  {
456  //Enable Ethernet PHY interrupts
457  interface->phyDriver->enableIrq(interface);
458  }
459  else if(interface->switchDriver != NULL)
460  {
461  //Enable Ethernet switch interrupts
462  interface->switchDriver->enableIrq(interface);
463  }
464  else
465  {
466  //Just for sanity
467  }
468 }
469 
470 
471 /**
472  * @brief Disable interrupts
473  * @param[in] interface Underlying network interface
474  **/
475 
477 {
478  //Disable Ethernet MAC interrupts
479  ETH_CLEAR_ETHIE();
480 
481  //Valid Ethernet PHY or switch driver?
482  if(interface->phyDriver != NULL)
483  {
484  //Disable Ethernet PHY interrupts
485  interface->phyDriver->disableIrq(interface);
486  }
487  else if(interface->switchDriver != NULL)
488  {
489  //Disable Ethernet switch interrupts
490  interface->switchDriver->disableIrq(interface);
491  }
492  else
493  {
494  //Just for sanity
495  }
496 }
497 
498 
499 /**
500  * @brief PIC32MZ Ethernet MAC interrupt service routine
501  **/
502 
504 {
505  bool_t flag;
506  uint32_t status;
507 
508  //Interrupt service routine prologue
509  osEnterIsr();
510 
511  //This flag will be set if a higher priority task must be woken
512  flag = FALSE;
513 
514  //Read interrupt status register
515  status = ETHIRQ;
516 
517  //Packet transmitted?
518  if((status & _ETHIRQ_TXDONE_MASK) != 0)
519  {
520  //Clear TXDONE interrupt flag
521  ETHIRQCLR = _ETHIRQ_TXDONE_MASK;
522 
523  //Check whether the TX buffer is available for writing
524  if((txCurBufferDesc->control & ETH_TX_CTRL_EOWN) == 0)
525  {
526  //Notify the TCP/IP stack that the transmitter is ready to send
527  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
528  }
529  }
530 
531  //Packet received?
532  if((status & _ETHIRQ_PKTPEND_MASK) != 0)
533  {
534  //Disable PKTPEND interrupt
535  ETHIENCLR = _ETHIEN_PKTPENDIE_MASK;
536 
537  //Set event flag
538  nicDriverInterface->nicEvent = TRUE;
539  //Notify the TCP/IP stack of the event
540  flag |= osSetEventFromIsr(&netEvent);
541  }
542 
543  //Clear ETHIF interrupt flag before exiting the service routine
544  ETH_CLEAR_ETHIF();
545 
546  //Interrupt service routine epilogue
547  osExitIsr(flag);
548 }
549 
550 
551 /**
552  * @brief PIC32MZ Ethernet MAC event handler
553  * @param[in] interface Underlying network interface
554  **/
555 
557 {
558  error_t error;
559 
560  //Packet received?
561  if((ETHIRQ & _ETHIRQ_PKTPEND_MASK) != 0)
562  {
563  //Process all pending packets
564  do
565  {
566  //Read incoming packet
567  error = pic32mzEthReceivePacket(interface);
568 
569  //No more data in the receive buffer?
570  } while(error != ERROR_BUFFER_EMPTY);
571  }
572 
573  //Re-enable PKTPEND interrupt
574  ETHIENSET = _ETHIEN_PKTPENDIE_MASK;
575 }
576 
577 
578 /**
579  * @brief Send a packet
580  * @param[in] interface Underlying network interface
581  * @param[in] buffer Multi-part buffer containing the data to send
582  * @param[in] offset Offset to the first data byte
583  * @param[in] ancillary Additional options passed to the stack along with
584  * the packet
585  * @return Error code
586  **/
587 
589  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
590 {
591  size_t length;
592  uint32_t value;
593 
594  //Retrieve the length of the packet
595  length = netBufferGetLength(buffer) - offset;
596 
597  //Check the frame length
599  {
600  //The transmitter can accept another packet
601  osSetEvent(&interface->nicTxEvent);
602  //Report an error
603  return ERROR_INVALID_LENGTH;
604  }
605 
606  //Make sure the current buffer is available for writing
607  if((txCurBufferDesc->control & ETH_TX_CTRL_EOWN) != 0)
608  {
609  return ERROR_FAILURE;
610  }
611 
612  //Copy user data to the transmit buffer
613  netBufferRead(PA_TO_KVA1(txCurBufferDesc->address), buffer, offset, length);
614 
615  //Write the number of bytes to send
616  value = (length << 16) & ETH_TX_CTRL_BYTE_COUNT;
617  //Set SOP and EOP flags since the data fits in a single buffer
619  //Give the ownership of the descriptor to the DMA
620  txCurBufferDesc->control = value | ETH_TX_CTRL_EOWN;
621 
622  //Set TXRTS bit to start the transmission
623  ETHCON1SET = _ETHCON1_TXRTS_MASK;
624 
625  //Point to the next descriptor in the list
626  txCurBufferDesc = PA_TO_KVA1(txCurBufferDesc->next);
627 
628  //Check whether the next buffer is available for writing
629  if((txCurBufferDesc->control & ETH_TX_CTRL_EOWN) == 0)
630  {
631  //The transmitter can accept another packet
632  osSetEvent(&interface->nicTxEvent);
633  }
634 
635  //Data successfully written
636  return NO_ERROR;
637 }
638 
639 
640 /**
641  * @brief Receive a packet
642  * @param[in] interface Underlying network interface
643  * @return Error code
644  **/
645 
647 {
648  static uint32_t temp[PIC32MZ_ETH_RX_BUFFER_SIZE / 4];
649  error_t error;
650  size_t n;
651  NetRxAncillary ancillary;
652 
653  //Current buffer available for reading?
654  if((rxCurBufferDesc->control & ETH_RX_CTRL_EOWN) == 0)
655  {
656  //SOP and EOP flags should be set
657  if((rxCurBufferDesc->control & ETH_RX_CTRL_SOP) != 0 &&
658  (rxCurBufferDesc->control & ETH_RX_CTRL_EOP) != 0)
659  {
660  //Make sure no error occurred
661  if((rxCurBufferDesc->status2 & ETH_RX_STATUS2_OK) != 0)
662  {
663  //Retrieve the length of the frame
664  n = (rxCurBufferDesc->control & ETH_RX_CTRL_BYTE_COUNT) >> 16;
665  //Limit the number of data to read
667 
668  //Copy data from the receive buffer
669  osMemcpy(temp, PA_TO_KVA1(rxCurBufferDesc->address), n);
670 
671  //Additional options can be passed to the stack along with the packet
672  ancillary = NET_DEFAULT_RX_ANCILLARY;
673 
674  //Pass the packet to the upper layer
675  nicProcessPacket(interface, (uint8_t *) temp, n, &ancillary);
676 
677  //Valid packet received
678  error = NO_ERROR;
679  }
680  else
681  {
682  //The received packet contains an error
683  error = ERROR_INVALID_PACKET;
684  }
685  }
686  else
687  {
688  //The packet is not valid
689  error = ERROR_INVALID_PACKET;
690  }
691 
692  //Give the ownership of the descriptor back to the DMA
693  rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
694 
695  //Point to the next descriptor in the list
696  rxCurBufferDesc = PA_TO_KVA1(rxCurBufferDesc->next);
697 
698  //Once software processes a received packet, it should write the BUFCDEC
699  //bit in order to decrement the packet buffer count BUFCNT
700  ETHCON1SET = _ETHCON1_BUFCDEC_MASK;
701  }
702  else
703  {
704  //No more data in the receive buffer
705  error = ERROR_BUFFER_EMPTY;
706  }
707 
708  //Return status code
709  return error;
710 }
711 
712 
713 /**
714  * @brief Configure MAC address filtering
715  * @param[in] interface Underlying network interface
716  * @return Error code
717  **/
718 
720 {
721  uint_t i;
722  uint_t k;
723  uint32_t crc;
724  uint32_t hashTable[2];
725  MacFilterEntry *entry;
726 
727  //Debug message
728  TRACE_DEBUG("Updating MAC filter...\r\n");
729 
730  //Clear hash table
731  hashTable[0] = 0;
732  hashTable[1] = 0;
733 
734  //The MAC address filter contains the list of MAC addresses to accept
735  //when receiving an Ethernet frame
736  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
737  {
738  //Point to the current entry
739  entry = &interface->macAddrFilter[i];
740 
741  //Valid entry?
742  if(entry->refCount > 0)
743  {
744  //Compute CRC over the current MAC address
745  crc = pic32mzEthCalcCrc(&entry->addr, sizeof(MacAddr));
746  //Calculate the corresponding index in the table
747  k = (crc >> 23) & 0x3F;
748  //Update hash table contents
749  hashTable[k / 32] |= (1 << (k % 32));
750  }
751  }
752 
753  //Write the hash table
754  ETHHT0 = hashTable[0];
755  ETHHT1 = hashTable[1];
756 
757  //Debug message
758  TRACE_DEBUG(" ETHHT0 = %08" PRIX32 "\r\n", ETHHT0);
759  TRACE_DEBUG(" ETHHT1 = %08" PRIX32 "\r\n", ETHHT1);
760 
761  //Successful processing
762  return NO_ERROR;
763 }
764 
765 
766 /**
767  * @brief Adjust MAC configuration parameters for proper operation
768  * @param[in] interface Underlying network interface
769  * @return Error code
770  **/
771 
773 {
774  //Check current operating speed
775  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
776  {
777  //100BASE-TX operation mode
778  EMAC1SUPPSET = _EMAC1SUPP_SPEEDRMII_MASK;
779  }
780  else
781  {
782  //10BASE-T operation mode
783  EMAC1SUPPCLR = _EMAC1SUPP_SPEEDRMII_MASK;
784  }
785 
786  //Half-duplex or full-duplex mode?
787  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
788  {
789  //Configure FULLDPLX bit to match the current duplex mode
790  EMAC1CFG2SET = _EMAC1CFG2_FULLDPLX_MASK;
791  //Configure the Back-to-Back Inter-Packet Gap register
792  EMAC1IPGT = 0x15;
793  }
794  else
795  {
796  //Configure FULLDPLX bit to match the current duplex mode
797  EMAC1CFG2CLR = _EMAC1CFG2_FULLDPLX_MASK;
798  //Configure the Back-to-Back Inter-Packet Gap register
799  EMAC1IPGT = 0x12;
800  }
801 
802  //Successful processing
803  return NO_ERROR;
804 }
805 
806 
807 /**
808  * @brief Write PHY register
809  * @param[in] opcode Access type (2 bits)
810  * @param[in] phyAddr PHY address (5 bits)
811  * @param[in] regAddr Register address (5 bits)
812  * @param[in] data Register value
813  **/
814 
815 void pic32mzEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
816  uint8_t regAddr, uint16_t data)
817 {
818  uint_t i;
819 
820  //Valid opcode?
821  if(opcode == SMI_OPCODE_WRITE)
822  {
823  //Set PHY address and register address
824  EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
825  //Start a write operation
826  EMAC1MWTD = data & _EMAC1MWTD_MWTD_MASK;
827 
828  //Wait for busy bit to be set
829  for(i = 0; i < 16; i++)
830  {
831  __asm__ __volatile__ ("nop;");
832  }
833 
834  //Wait for the write to complete
835  while((EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK) != 0)
836  {
837  }
838  }
839  else
840  {
841  //The MAC peripheral only supports standard Clause 22 opcodes
842  }
843 }
844 
845 
846 /**
847  * @brief Read PHY register
848  * @param[in] opcode Access type (2 bits)
849  * @param[in] phyAddr PHY address (5 bits)
850  * @param[in] regAddr Register address (5 bits)
851  * @return Register value
852  **/
853 
854 uint16_t pic32mzEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
855  uint8_t regAddr)
856 {
857  uint_t i;
858  uint16_t data;
859 
860  //Valid opcode?
861  if(opcode == SMI_OPCODE_READ)
862  {
863  //Set PHY address and register address
864  EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
865  //Start a read operation
866  EMAC1MCMD = _EMAC1MCMD_READ_MASK;
867 
868  //Wait for busy bit to be set
869  for(i = 0; i < 16; i++)
870  {
871  __asm__ __volatile__ ("nop;");
872  }
873 
874  //Wait for the read to complete
875  while((EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK) != 0)
876  {
877  }
878 
879  //Clear command register
880  EMAC1MCMD = 0;
881  //Get register value
882  data = EMAC1MRDD & _EMAC1MRDD_MRDD_MASK;
883  }
884  else
885  {
886  //The MAC peripheral only supports standard Clause 22 opcodes
887  data = 0;
888  }
889 
890  //Return the value of the PHY register
891  return data;
892 }
893 
894 
895 /**
896  * @brief CRC calculation
897  * @param[in] data Pointer to the data over which to calculate the CRC
898  * @param[in] length Number of bytes to process
899  * @return Resulting CRC value
900  **/
901 
902 uint32_t pic32mzEthCalcCrc(const void *data, size_t length)
903 {
904  uint_t i;
905  uint_t j;
906  uint32_t crc;
907  const uint8_t *p;
908 
909  //Point to the data over which to calculate the CRC
910  p = (uint8_t *) data;
911  //CRC preset value
912  crc = 0xFFFFFFFF;
913 
914  //Loop through data
915  for(i = 0; i < length; i++)
916  {
917  //The message is processed bit by bit
918  for(j = 0; j < 8; j++)
919  {
920  //Update CRC value
921  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
922  {
923  crc = (crc << 1) ^ 0x04C11DB7;
924  }
925  else
926  {
927  crc = crc << 1;
928  }
929  }
930  }
931 
932  //Return CRC value
933  return crc;
934 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define ETH_TX_CTRL_BYTE_COUNT
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:61
#define netEvent
Definition: net_legacy.h:196
#define PIC32MZ_ETH_IRQ_PRIORITY
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
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
#define sleep(delay)
Definition: os_port.h:310
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
void pic32mzEthTick(NetInterface *interface)
PIC32MZ Ethernet MAC timer handler.
#define ETH_SET_ETHIP(n)
#define ETH_CLEAR_ETHIE()
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 PIC32MZ_ETH_RX_BUFFER_COUNT
#define ETH_RX_CTRL_EOP
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define PIC32MZ_ETH_TX_BUFFER_COUNT
PIC32MZ Ethernet MAC driver.
__weak_func void pic32mzEthInitGpio(NetInterface *interface)
GPIO configuration.
#define ETH_TX_CTRL_EOP
#define ETH_TX_CTRL_SOP
#define FALSE
Definition: os_port.h:46
#define ETH_RX_CTRL_EOWN
uint32_t pic32mzEthCalcCrc(const void *data, size_t length)
CRC calculation.
error_t pic32mzEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
void pic32mzEthIrqHandler(void)
PIC32MZ 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 txBuffer
void pic32mzEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
void pic32mzEthEventHandler(NetInterface *interface)
PIC32MZ Ethernet MAC event handler.
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:36
#define _EMAC1MCFG_CLKSEL_DIV50
MacAddr addr
MAC address.
Definition: ethernet.h:263
#define ETH_TX_CTRL_NPV
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
#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 ETH_SET_ETHIS(n)
#define MIN(a, b)
Definition: os_port.h:63
#define rxBuffer
error_t pic32mzEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
MacAddr
Definition: ethernet.h:195
uint16_t pic32mzEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define TRACE_DEBUG(...)
Definition: debug.h:119
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
#define PIC32MZ_ETH_TX_BUFFER_SIZE
MAC filter table entry.
Definition: ethernet.h:262
#define ETH_SET_ETHIE()
RX buffer descriptor.
#define osEnterIsr()
error_t pic32mzEthReceivePacket(NetInterface *interface)
Receive a packet.
uint8_t value[]
Definition: tcp.h:376
#define PIC32MZ_ETH_IRQ_SUB_PRIORITY
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
void pic32mzEthEnableIrq(NetInterface *interface)
Enable interrupts.
#define PIC32MZ_ETH_RX_BUFFER_SIZE
TX buffer descriptor.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t pic32mzEthInit(NetInterface *interface)
PIC32MZ Ethernet MAC initialization.
#define ETH_CLEAR_ETHIF()
@ 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.
NIC driver.
Definition: nic.h:286
void pic32mzEthInitBufferDesc(NetInterface *interface)
Initialize DMA descriptor lists.
error_t pic32mzEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
const NicDriver pic32mzEthDriver
PIC32MZ Ethernet MAC driver.
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.
void pic32mzEthDisableIrq(NetInterface *interface)
Disable interrupts.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83