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