pic32mz_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file pic32mz_eth_driver.c
3  * @brief PIC32MZ Ethernet MAC controller
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <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)
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  //PHY transceiver initialization
145  error = interface->phyDriver->init(interface);
146  //Failed to initialize PHY transceiver?
147  if(error)
148  return error;
149 
150  //Optionally set the station MAC address
151  if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
152  {
153  //Use the factory preprogrammed station address
154  interface->macAddr.w[0] = EMAC1SA2;
155  interface->macAddr.w[1] = EMAC1SA1;
156  interface->macAddr.w[2] = EMAC1SA0;
157 
158  //Generate the 64-bit interface identifier
159  macAddrToEui64(&interface->macAddr, &interface->eui64);
160  }
161  else
162  {
163  //Override the factory preprogrammed address
164  EMAC1SA0 = interface->macAddr.w[2];
165  EMAC1SA1 = interface->macAddr.w[1];
166  EMAC1SA2 = interface->macAddr.w[0];
167  }
168 
169  //Initialize hash table
170  ETHHT0 = 0;
171  ETHHT1 = 0;
172 
173  //Configure the receive filter
174  ETHRXFC = _ETHRXFC_HTEN_MASK | _ETHRXFC_CRCOKEN_MASK |
175  _ETHRXFC_RUNTEN_MASK | _ETHRXFC_UCEN_MASK | _ETHRXFC_BCEN_MASK;
176 
177  //Disable flow control
178  EMAC1CFG1 = _EMAC1CFG1_RXENABLE_MASK;
179  //Automatic padding and CRC generation
180  EMAC1CFG2 = _EMAC1CFG2_PADENABLE_MASK | _EMAC1CFG2_CRCENABLE_MASK;
181  //Set the maximum frame length
182  EMAC1MAXF = PIC32MZ_ETH_RX_BUFFER_SIZE;
183 
184  //Initialize DMA descriptor lists
185  pic32mzEthInitBufferDesc(interface);
186 
187  //Enable desired interrupts
188  ETHIENSET = _ETHIEN_PKTPENDIE_MASK | _ETHIEN_TXDONEIE_MASK;
189 
190  //Set interrupt priority
191  IPC38CLR = _IPC38_ETHIP_MASK;
192  IPC38SET = (PIC32MZ_ETH_IRQ_PRIORITY << _IPC38_ETHIP_POSITION);
193  //Set interrupt subpriority
194  IPC38CLR = _IPC38_ETHIS_MASK;
195  IPC38SET = (PIC32MZ_ETH_IRQ_SUB_PRIORITY << _IPC38_ETHIS_POSITION);
196 
197  //Enable the reception by setting the RXEN bit
198  ETHCON1SET = _ETHCON1_RXEN_MASK;
199 
200  //Accept any packets from the upper layer
201  osSetEvent(&interface->nicTxEvent);
202 
203  //Successful initialization
204  return NO_ERROR;
205 }
206 
207 
208 //PIC32MZ EC Starter Kit, PIC32MZ EF Starter Kit, PIC32MZ EF Curiosity,
209 //PIC32MZ EF Curiosity 2.0 or IoT Ethernet Kit?
210 #if defined(USE_PIC32MZ_EC_STARTER_KIT) || defined(USE_PIC32MZ_EF_STARTER_KIT) || \
211  defined(USE_PIC32MZ_EF_CURIOSITY) || defined(USE_PIC32MZ_EF_CURIOSITY_2) || \
212  defined(USE_IOT_ETHERNET_KIT)
213 
214 /**
215  * @brief GPIO configuration
216  * @param[in] interface Underlying network interface
217  **/
218 
219 void pic32mzEthInitGpio(NetInterface *interface)
220 {
221 //PIC32MZ EC Starter Kit or PIC32MZ EF Starter Kit?
222 #if defined(USE_PIC32MZ_EC_STARTER_KIT) || defined(USE_PIC32MZ_EF_STARTER_KIT)
223  //Disable analog pad on ETXD0 (AN35/RJ8)
224  ANSELJCLR = _ANSELJ_ANSJ8_MASK;
225  //Disable analog pad on ETXD1 (AN36/RJ9)
226  ANSELJCLR = _ANSELJ_ANSJ9_MASK;
227  //Disable analog pad on EREFCLK (AN37/RJ11)
228  ANSELJCLR = _ANSELJ_ANSJ11_MASK;
229  //Disable analog pad on ERXERR (AN40/RH4)
230  ANSELHCLR = _ANSELH_ANSH4_MASK;
231  //Disable analog pad on ERXD1 (AN41/RH5)
232  ANSELHCLR = _ANSELH_ANSH5_MASK;
233 
234 //PIC32MZ EF Curiosity?
235 #elif defined(USE_PIC32MZ_EF_CURIOSITY)
236  //Disable analog pad on ERXERR (AN6/RB11)
237  ANSELBCLR = _ANSELB_ANSB11_MASK;
238  //Disable analog pad on ERXD0 (AN7/RB12)
239  ANSELBCLR = _ANSELB_ANSB12_MASK;
240  //Disable analog pad on ERXD1 (AN8/RB13)
241  ANSELBCLR = _ANSELB_ANSB13_MASK;
242  //Disable analog pad on ERXDV (AN12/RG8)
243  ANSELGCLR = _ANSELG_ANSG8_MASK;
244  //Disable analog pad on EREFCLK (AN11/RG9)
245  ANSELGCLR = _ANSELG_ANSG9_MASK;
246 
247 //PIC32MZ EF Curiosity 2.0?
248 #elif defined(USE_PIC32MZ_EF_CURIOSITY_2)
249  //Disable analog pad on ETXD0 (AN35/RJ8)
250  ANSELJCLR = _ANSELJ_ANSJ8_MASK;
251  //Disable analog pad on ETXD1 (AN36/RJ9)
252  ANSELJCLR = _ANSELJ_ANSJ9_MASK;
253  //Disable analog pad on EREFCLK (AN37/RJ11)
254  ANSELJCLR = _ANSELJ_ANSJ11_MASK;
255  //Disable analog pad on ERXERR (AN40/RH4)
256  ANSELHCLR = _ANSELH_ANSH4_MASK;
257  //Disable analog pad on ERXD1 (AN41/RH5)
258  ANSELHCLR = _ANSELH_ANSH5_MASK;
259 
260 //IoT Ethernet Kit?
261 #elif defined(USE_IOT_ETHERNET_KIT)
262  //Disable analog pad on ERXERR (AN18/RE4)
263  ANSELECLR = _ANSELE_ANSE4_MASK;
264  //Disable analog pad on ETXEN (AN17/RE5)
265  ANSELECLR = _ANSELE_ANSE5_MASK;
266  //Disable analog pad on ETXD0 (AN16/RE6)
267  ANSELECLR = _ANSELE_ANSE6_MASK;
268  //Disable analog pad on ETXD1 (AN15/RE7)
269  ANSELECLR = _ANSELE_ANSE7_MASK;
270 #endif
271 }
272 
273 #endif
274 
275 
276 /**
277  * @brief Initialize DMA descriptor lists
278  * @param[in] interface Underlying network interface
279  **/
280 
282 {
283  uint_t i;
284 
285  //Initialize TX descriptor list
286  for(i = 0; i < PIC32MZ_ETH_TX_BUFFER_COUNT; i++)
287  {
288  //Point to the current descriptor
289  txCurBufferDesc = &txBufferDesc[i];
290 
291  //Use linked list rather than linear list
292  txCurBufferDesc->control = ETH_TX_CTRL_NPV;
293  //Transmit buffer address
294  txCurBufferDesc->address = KVA_TO_PA(txBuffer[i]);
295  //Transmit status vector
296  txCurBufferDesc->status1 = 0;
297  txCurBufferDesc->status2 = 0;
298  //Next descriptor address
299  txCurBufferDesc->next = KVA_TO_PA(&txBufferDesc[i + 1]);
300  }
301 
302  //The last descriptor is chained to the first entry
303  txCurBufferDesc->next = KVA_TO_PA(&txBufferDesc[0]);
304  //Point to the very first descriptor
305  txCurBufferDesc = &txBufferDesc[0];
306 
307  //Initialize RX descriptor list
308  for(i = 0; i < PIC32MZ_ETH_RX_BUFFER_COUNT; i++)
309  {
310  //Point to the current descriptor
311  rxCurBufferDesc = &rxBufferDesc[i];
312 
313  //The descriptor is initially owned by the DMA
314  rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
315  //Receive buffer address
316  rxCurBufferDesc->address = KVA_TO_PA(rxBuffer[i]);
317  //Receive status vector
318  rxCurBufferDesc->status1 = 0;
319  rxCurBufferDesc->status2 = 0;
320  //Next descriptor address
321  rxCurBufferDesc->next = KVA_TO_PA(&rxBufferDesc[i + 1]);
322  }
323 
324  //The last descriptor is chained to the first entry
325  rxCurBufferDesc->next = KVA_TO_PA(&rxBufferDesc[0]);
326  //Point to the very first descriptor
327  rxCurBufferDesc = &rxBufferDesc[0];
328 
329  //Starting address of TX descriptor table
330  ETHTXST = KVA_TO_PA(&txBufferDesc[0]);
331  //Starting address of RX descriptor table
332  ETHRXST = KVA_TO_PA(&rxBufferDesc[0]);
333  //Set receive buffer size
334  ETHCON2 = PIC32MZ_ETH_RX_BUFFER_SIZE;
335 }
336 
337 
338 /**
339  * @brief PIC32MZ Ethernet MAC timer handler
340  *
341  * This routine is periodically called by the TCP/IP stack to
342  * handle periodic operations such as polling the link state
343  *
344  * @param[in] interface Underlying network interface
345  **/
346 
347 void pic32mzEthTick(NetInterface *interface)
348 {
349  //Handle periodic operations
350  interface->phyDriver->tick(interface);
351 }
352 
353 
354 /**
355  * @brief Enable interrupts
356  * @param[in] interface Underlying network interface
357  **/
358 
360 {
361  //Enable Ethernet MAC interrupts
362  IEC4SET = _IEC4_ETHIE_MASK;
363  //Enable Ethernet PHY interrupts
364  interface->phyDriver->enableIrq(interface);
365 }
366 
367 
368 /**
369  * @brief Disable interrupts
370  * @param[in] interface Underlying network interface
371  **/
372 
374 {
375  //Disable Ethernet MAC interrupts
376  IEC4CLR = _IEC4_ETHIE_MASK;
377  //Disable Ethernet PHY interrupts
378  interface->phyDriver->disableIrq(interface);
379 }
380 
381 
382 /**
383  * @brief PIC32MZ Ethernet MAC interrupt service routine
384  **/
385 
387 {
388  bool_t flag;
389  uint32_t status;
390 
391  //Interrupt service routine prologue
392  osEnterIsr();
393 
394  //This flag will be set if a higher priority task must be woken
395  flag = FALSE;
396 
397  //Read interrupt status register
398  status = ETHIRQ;
399 
400  //A packet has been transmitted?
401  if(status & _ETHIRQ_TXDONE_MASK)
402  {
403  //Clear TXDONE interrupt flag
404  ETHIRQCLR = _ETHIRQ_TXDONE_MASK;
405 
406  //Check whether the TX buffer is available for writing
407  if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN))
408  {
409  //Notify the TCP/IP stack that the transmitter is ready to send
410  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
411  }
412  }
413 
414  //A packet has been received?
415  if(status & _ETHIRQ_PKTPEND_MASK)
416  {
417  //Disable PKTPEND interrupt
418  ETHIENCLR = _ETHIEN_PKTPENDIE_MASK;
419 
420  //Set event flag
421  nicDriverInterface->nicEvent = TRUE;
422  //Notify the TCP/IP stack of the event
423  flag |= osSetEventFromIsr(&netEvent);
424  }
425 
426  //Clear ETHIF interrupt flag before exiting the service routine
427  IFS4CLR = _IFS4_ETHIF_MASK;
428 
429  //Interrupt service routine epilogue
430  osExitIsr(flag);
431 }
432 
433 
434 /**
435  * @brief PIC32MZ Ethernet MAC event handler
436  * @param[in] interface Underlying network interface
437  **/
438 
440 {
441  error_t error;
442 
443  //Packet received?
444  if(ETHIRQ & _ETHIRQ_PKTPEND_MASK)
445  {
446  //Process all pending packets
447  do
448  {
449  //Read incoming packet
450  error = pic32mzEthReceivePacket(interface);
451 
452  //No more data in the receive buffer?
453  } while(error != ERROR_BUFFER_EMPTY);
454  }
455 
456  //Re-enable PKTPEND interrupt
457  ETHIENSET = _ETHIEN_PKTPENDIE_MASK;
458 }
459 
460 
461 /**
462  * @brief Send a packet
463  * @param[in] interface Underlying network interface
464  * @param[in] buffer Multi-part buffer containing the data to send
465  * @param[in] offset Offset to the first data byte
466  * @return Error code
467  **/
468 
470  const NetBuffer *buffer, size_t offset)
471 {
472  size_t length;
473  uint32_t value;
474 
475  //Retrieve the length of the packet
476  length = netBufferGetLength(buffer) - offset;
477 
478  //Check the frame length
480  {
481  //The transmitter can accept another packet
482  osSetEvent(&interface->nicTxEvent);
483  //Report an error
484  return ERROR_INVALID_LENGTH;
485  }
486 
487  //Make sure the current buffer is available for writing
488  if(txCurBufferDesc->control & ETH_TX_CTRL_EOWN)
489  return ERROR_FAILURE;
490 
491  //Copy user data to the transmit buffer
492  netBufferRead(PA_TO_KVA1(txCurBufferDesc->address), buffer, offset, length);
493 
494  //Write the number of bytes to send
495  value = (length << 16) & ETH_TX_CTRL_BYTE_COUNT;
496  //Set SOP and EOP flags since the data fits in a single buffer
498  //Give the ownership of the descriptor to the DMA
499  txCurBufferDesc->control = value | ETH_TX_CTRL_EOWN;
500 
501  //Set TXRTS bit to start the transmission
502  ETHCON1SET = _ETHCON1_TXRTS_MASK;
503 
504  //Point to the next descriptor in the list
505  txCurBufferDesc = PA_TO_KVA1(txCurBufferDesc->next);
506 
507  //Check whether the next buffer is available for writing
508  if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN))
509  {
510  //The transmitter can accept another packet
511  osSetEvent(&interface->nicTxEvent);
512  }
513 
514  //Data successfully written
515  return NO_ERROR;
516 }
517 
518 
519 /**
520  * @brief Receive a packet
521  * @param[in] interface Underlying network interface
522  * @return Error code
523  **/
524 
526 {
527  static uint8_t temp[PIC32MZ_ETH_RX_BUFFER_SIZE];
528  error_t error;
529  size_t n;
530 
531  //The current buffer is available for reading?
532  if(!(rxCurBufferDesc->control & ETH_RX_CTRL_EOWN))
533  {
534  //SOP and EOP flags should be set
535  if((rxCurBufferDesc->control & ETH_RX_CTRL_SOP) &&
536  (rxCurBufferDesc->control & ETH_RX_CTRL_EOP))
537  {
538  //Make sure no error occurred
539  if(rxCurBufferDesc->status2 & ETH_RX_STATUS2_OK)
540  {
541  //Retrieve the length of the frame
542  n = (rxCurBufferDesc->control & ETH_RX_CTRL_BYTE_COUNT) >> 16;
543  //Limit the number of data to read
545 
546  //Copy data from the receive buffer
547  memcpy(temp, PA_TO_KVA1(rxCurBufferDesc->address), n);
548 
549  //Pass the packet to the upper layer
550  nicProcessPacket(interface, temp, n);
551 
552  //Valid packet received
553  error = NO_ERROR;
554  }
555  else
556  {
557  //The received packet contains an error
558  error = ERROR_INVALID_PACKET;
559  }
560  }
561  else
562  {
563  //The packet is not valid
564  error = ERROR_INVALID_PACKET;
565  }
566 
567  //Give the ownership of the descriptor back to the DMA
568  rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
569 
570  //Point to the next descriptor in the list
571  rxCurBufferDesc = PA_TO_KVA1(rxCurBufferDesc->next);
572 
573  //Decrement BUFCNT counter
574  ETHCON1SET = _ETHCON1_BUFCDEC_MASK;
575  }
576  else
577  {
578  //No more data in the receive buffer
579  error = ERROR_BUFFER_EMPTY;
580  }
581 
582  //Return status code
583  return error;
584 }
585 
586 
587 /**
588  * @brief Configure MAC address filtering
589  * @param[in] interface Underlying network interface
590  * @return Error code
591  **/
592 
594 {
595  uint_t i;
596  uint_t k;
597  uint32_t crc;
598  uint32_t hashTable[2];
599  MacFilterEntry *entry;
600 
601  //Debug message
602  TRACE_DEBUG("Updating MAC filter...\r\n");
603 
604  //Clear hash table
605  hashTable[0] = 0;
606  hashTable[1] = 0;
607 
608  //The MAC address filter contains the list of MAC addresses to accept
609  //when receiving an Ethernet frame
610  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
611  {
612  //Point to the current entry
613  entry = &interface->macAddrFilter[i];
614 
615  //Valid entry?
616  if(entry->refCount > 0)
617  {
618  //Compute CRC over the current MAC address
619  crc = pic32mzEthCalcCrc(&entry->addr, sizeof(MacAddr));
620  //Calculate the corresponding index in the table
621  k = (crc >> 23) & 0x3F;
622  //Update hash table contents
623  hashTable[k / 32] |= (1 << (k % 32));
624  }
625  }
626 
627  //Write the hash table
628  ETHHT0 = hashTable[0];
629  ETHHT1 = hashTable[1];
630 
631  //Debug message
632  TRACE_DEBUG(" ETHHT0 = %08" PRIX32 "\r\n", ETHHT0);
633  TRACE_DEBUG(" ETHHT1 = %08" PRIX32 "\r\n", ETHHT1);
634 
635  //Successful processing
636  return NO_ERROR;
637 }
638 
639 
640 /**
641  * @brief Adjust MAC configuration parameters for proper operation
642  * @param[in] interface Underlying network interface
643  * @return Error code
644  **/
645 
647 {
648  //Check current operating speed
649  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
650  {
651  //100BASE-TX operation mode
652  EMAC1SUPPSET = _EMAC1SUPP_SPEEDRMII_MASK;
653  }
654  else
655  {
656  //10BASE-T operation mode
657  EMAC1SUPPCLR = _EMAC1SUPP_SPEEDRMII_MASK;
658  }
659 
660  //Half-duplex or full-duplex mode?
661  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
662  {
663  //Configure FULLDPLX bit to match the current duplex mode
664  EMAC1CFG2SET = _EMAC1CFG2_FULLDPLX_MASK;
665  //Configure the Back-to-Back Inter-Packet Gap register
666  EMAC1IPGT = 0x15;
667  }
668  else
669  {
670  //Configure FULLDPLX bit to match the current duplex mode
671  EMAC1CFG2CLR = _EMAC1CFG2_FULLDPLX_MASK;
672  //Configure the Back-to-Back Inter-Packet Gap register
673  EMAC1IPGT = 0x12;
674  }
675 
676  //Successful processing
677  return NO_ERROR;
678 }
679 
680 
681 /**
682  * @brief Write PHY register
683  * @param[in] opcode Access type (2 bits)
684  * @param[in] phyAddr PHY address (5 bits)
685  * @param[in] regAddr Register address (5 bits)
686  * @param[in] data Register value
687  **/
688 
689 void pic32mzEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
690  uint8_t regAddr, uint16_t data)
691 {
692  uint_t i;
693 
694  //Valid opcode?
695  if(opcode == SMI_OPCODE_WRITE)
696  {
697  //Set PHY address and register address
698  EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
699  //Start a write operation
700  EMAC1MWTD = data & _EMAC1MWTD_MWTD_MASK;
701 
702  //Wait for busy bit to be set
703  for(i = 0; i < 16; i++)
704  {
705  __asm__ __volatile__ ("nop;");
706  }
707 
708  //Wait for the write to complete
709  while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK)
710  {
711  }
712  }
713  else
714  {
715  //The MAC peripheral only supports standard Clause 22 opcodes
716  }
717 }
718 
719 
720 /**
721  * @brief Read PHY register
722  * @param[in] opcode Access type (2 bits)
723  * @param[in] phyAddr PHY address (5 bits)
724  * @param[in] regAddr Register address (5 bits)
725  * @return Register value
726  **/
727 
728 uint16_t pic32mzEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
729  uint8_t regAddr)
730 {
731  uint_t i;
732  uint16_t data;
733 
734  //Valid opcode?
735  if(opcode == SMI_OPCODE_READ)
736  {
737  //Set PHY address and register address
738  EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
739  //Start a read operation
740  EMAC1MCMD = _EMAC1MCMD_READ_MASK;
741 
742  //Wait for busy bit to be set
743  for(i = 0; i < 16; i++)
744  {
745  __asm__ __volatile__ ("nop;");
746  }
747 
748  //Wait for the read to complete
749  while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK)
750  {
751  }
752 
753  //Clear command register
754  EMAC1MCMD = 0;
755  //Get register value
756  data = EMAC1MRDD & _EMAC1MRDD_MRDD_MASK;
757  }
758  else
759  {
760  //The MAC peripheral only supports standard Clause 22 opcodes
761  data = 0;
762  }
763 
764  //Return the value of the PHY register
765  return data;
766 }
767 
768 
769 /**
770  * @brief CRC calculation
771  * @param[in] data Pointer to the data over which to calculate the CRC
772  * @param[in] length Number of bytes to process
773  * @return Resulting CRC value
774  **/
775 
776 uint32_t pic32mzEthCalcCrc(const void *data, size_t length)
777 {
778  uint_t i;
779  uint_t j;
780 
781  //Point to the data over which to calculate the CRC
782  const uint8_t *p = (uint8_t *) data;
783  //CRC preset value
784  uint32_t crc = 0xFFFFFFFF;
785 
786  //Loop through data
787  for(i = 0; i < length; i++)
788  {
789  //The message is processed bit by bit
790  for(j = 0; j < 8; j++)
791  {
792  //Update CRC value
793  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
794  crc = (crc << 1) ^ 0x04C11DB7;
795  else
796  crc = crc << 1;
797  }
798  }
799 
800  //Return CRC value
801  return crc;
802 }
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: dtls_misc.h:149
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
#define PIC32MZ_ETH_IRQ_PRIORITY
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:119
void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Map a MAC address to the IPv6 modified EUI-64 identifier.
Definition: ethernet.c:800
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
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:383
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
#define TRUE
Definition: os_port.h:50
void pic32mzEthInitGpio(NetInterface *interface)
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:223
void pic32mzEthTick(NetInterface *interface)
PIC32MZ Ethernet MAC timer handler.
#define osExitIsr(flag)
#define PIC32MZ_ETH_RX_BUFFER_COUNT
#define ETH_RX_CTRL_EOP
#define SMI_OPCODE_WRITE
Definition: nic.h:62
#define PIC32MZ_ETH_TX_BUFFER_COUNT
PIC32MZ Ethernet MAC controller.
#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.
error_t
Error codes.
Definition: error.h:42
void pic32mzEthIrqHandler(void)
PIC32MZ Ethernet MAC interrupt service routine.
@ 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.
@ ERROR_INVALID_PACKET
Definition: error.h:138
#define NetInterface
Definition: net.h:36
#define _EMAC1MCFG_CLKSEL_DIV50
MacAddr addr
MAC address.
Definition: ethernet.h:222
#define ETH_TX_CTRL_NPV
@ ERROR_INVALID_LENGTH
Definition: error.h:109
@ ERROR_BUFFER_EMPTY
Definition: error.h:139
OsEvent netEvent
Definition: net.c:77
#define SMI_OPCODE_READ
Definition: nic.h:63
#define TRACE_INFO(...)
Definition: debug.h:94
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:62
#define rxBuffer
uint16_t pic32mzEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define TRACE_DEBUG(...)
Definition: debug.h:106
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:91
uint8_t n
#define PIC32MZ_ETH_TX_BUFFER_SIZE
MAC filter table entry.
Definition: ethernet.h:220
RX buffer descriptor.
#define osEnterIsr()
error_t pic32mzEthReceivePacket(NetInterface *interface)
Receive a packet.
error_t pic32mzEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define PIC32MZ_ETH_IRQ_SUB_PRIORITY
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:107
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.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:106
#define ETH_RX_CTRL_BYTE_COUNT
uint8_t value[]
Definition: dtls_misc.h:150
unsigned int uint_t
Definition: compiler_port.h:45
#define ETH_TX_CTRL_EOWN
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
NIC driver.
Definition: nic.h:179
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
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
__start_packed struct @108 MacAddr
MAC address.
void pic32mzEthDisableIrq(NetInterface *interface)
Disable interrupts.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:79