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