fm3_eth2_driver.c
Go to the documentation of this file.
1 /**
2  * @file fm3_eth2_driver.c
3  * @brief Cypress FM3 Ethernet MAC driver (ETHER1 instance)
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 "mb9bd10t.h"
36 #include "core/net.h"
38 #include "debug.h"
39 
40 //Underlying network interface
41 static NetInterface *nicDriverInterface;
42 
43 //IAR EWARM compiler?
44 #if defined(__ICCARM__)
45 
46 //Transmit buffer
47 #pragma data_alignment = 4
49 //Receive buffer
50 #pragma data_alignment = 4
52 //Transmit DMA descriptors
53 #pragma data_alignment = 4
55 //Receive DMA descriptors
56 #pragma data_alignment = 4
58 
59 //Keil MDK-ARM or GCC compiler?
60 #else
61 
62 //Transmit buffer
64  __attribute__((aligned(4)));
65 //Receive buffer
67  __attribute__((aligned(4)));
68 //Transmit DMA descriptors
70  __attribute__((aligned(4)));
71 //Receive DMA descriptors
73  __attribute__((aligned(4)));
74 
75 #endif
76 
77 //Pointer to the current TX DMA descriptor
78 static Fm3Eth2TxDmaDesc *txCurDmaDesc;
79 //Pointer to the current RX DMA descriptor
80 static Fm3Eth2RxDmaDesc *rxCurDmaDesc;
81 
82 
83 /**
84  * @brief FM3 Ethernet MAC driver (ETHER1 instance)
85  **/
86 
88 {
90  ETH_MTU,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief FM3 Ethernet MAC initialization
110  * @param[in] interface Underlying network interface
111  * @return Error code
112  **/
113 
115 {
116  error_t error;
117 
118  //Debug message
119  TRACE_INFO("Initializing FM3 Ethernet MAC (ETHER1)...\r\n");
120 
121  //Save underlying network interface
122  nicDriverInterface = interface;
123 
124  //GPIO configuration
125  fm3Eth2InitGpio(interface);
126 
127  //Enable Ethernet MAC1 clock
128  FM3_ETHERNET_CONTROL->ETH_CLKG_f.MACEN1 = 1;
129 
130  //Reset Ethernet MAC1 peripheral
131  FM3_ETHERNET_CONTROL->ETH_MODE_f.RST1 = 1;
132  FM3_ETHERNET_CONTROL->ETH_MODE_f.RST1 = 0;
133 
134  //Perform a software reset
135  FM3_ETHERNET_MAC1->BMR_f.SWR = 1;
136  //Wait for the reset to complete
137  while(FM3_ETHERNET_MAC1->BMR_f.SWR)
138  {
139  }
140 
141  //Ensure that on-going AHB transactions are complete
142  while(FM3_ETHERNET_MAC1->AHBSR_f.AHBS)
143  {
144  }
145 
146  //Adjust MDC clock range depending on HCLK frequency
147  FM3_ETHERNET_MAC1->GAR_f.CR = 5;
148 
149  //Valid Ethernet PHY or switch driver?
150  if(interface->phyDriver != NULL)
151  {
152  //Ethernet PHY initialization
153  error = interface->phyDriver->init(interface);
154  }
155  else if(interface->switchDriver != NULL)
156  {
157  //Ethernet switch initialization
158  error = interface->switchDriver->init(interface);
159  }
160  else
161  {
162  //The interface is not properly configured
163  error = ERROR_FAILURE;
164  }
165 
166  //Any error to report?
167  if(error)
168  {
169  return error;
170  }
171 
172  //Use default MAC configuration
173  FM3_ETHERNET_MAC1->MCR = 0;
174  FM3_ETHERNET_MAC1->MCR_f.PS = 1;
175  FM3_ETHERNET_MAC1->MCR_f.DO = 1;
176 
177  //Set the MAC address of the station
178  FM3_ETHERNET_MAC1->MAR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
179  FM3_ETHERNET_MAC1->MAR0H = interface->macAddr.w[2];
180 
181  //Initialize hash table
182  FM3_ETHERNET_MAC1->MHTRL = 0;
183  FM3_ETHERNET_MAC1->MHTRH = 0;
184 
185  //Configure the receive filter
186  FM3_ETHERNET_MAC1->MFFR = 0;
187  FM3_ETHERNET_MAC1->MFFR_f.HPF = 1;
188  FM3_ETHERNET_MAC1->MFFR_f.HMC = 1;
189 
190  //Disable flow control
191  FM3_ETHERNET_MAC1->FCR = 0;
192 
193  //Enable store and forward mode
194  FM3_ETHERNET_MAC1->OMR = 0;
195  FM3_ETHERNET_MAC1->OMR_f.RSF = 1;
196  FM3_ETHERNET_MAC1->OMR_f.TSF = 1;
197 
198  //Configure DMA bus mode
199  FM3_ETHERNET_MAC1->BMR = 0;
200  FM3_ETHERNET_MAC1->BMR_f.TXPR = 0;
201  FM3_ETHERNET_MAC1->BMR_f.MB = 1;
202  FM3_ETHERNET_MAC1->BMR_f.AAL = 0;
203  FM3_ETHERNET_MAC1->BMR_f._8XPBL = 0;
204  FM3_ETHERNET_MAC1->BMR_f.USP = 1;
205  FM3_ETHERNET_MAC1->BMR_f.RPBL = 32;
206  FM3_ETHERNET_MAC1->BMR_f.FB = 0;
207  FM3_ETHERNET_MAC1->BMR_f.PR = 0;
208  FM3_ETHERNET_MAC1->BMR_f.PBL = 32;
209  FM3_ETHERNET_MAC1->BMR_f.ATDS = 1;
210  FM3_ETHERNET_MAC1->BMR_f.DSL = 0;
211  FM3_ETHERNET_MAC1->BMR_f.DA = 0;
212 
213  //Initialize DMA descriptor lists
214  fm3Eth2InitDmaDesc(interface);
215 
216  //Prevent interrupts from being generated when statistic counters reach
217  //half their maximum value
218  FM3_ETHERNET_MAC1->mmc_intr_mask_tx = 0xFFFFFFFF;
219  FM3_ETHERNET_MAC1->mmc_intr_mask_rx = 0xFFFFFFFF;
220  FM3_ETHERNET_MAC1->mmc_ipc_intr_mask_rx = 0xFFFFFFFF;
221 
222  //Disable MAC interrupts
223  bFM3_ETHERNET_MAC1_IMR_LPIIM = 1;
224  bFM3_ETHERNET_MAC1_IMR_TSIM = 1;
225  bFM3_ETHERNET_MAC1_IMR_PIM = 1;
226  bFM3_ETHERNET_MAC1_IMR_RGIM = 1;
227 
228  //Enable the desired DMA interrupts
229  bFM3_ETHERNET_MAC1_IER_TIE = 1;
230  bFM3_ETHERNET_MAC1_IER_RIE = 1;
231  bFM3_ETHERNET_MAC1_IER_NIE = 1;
232 
233  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
234  NVIC_SetPriorityGrouping(FM3_ETH2_IRQ_PRIORITY_GROUPING);
235 
236  //Configure Ethernet interrupt priority
237  NVIC_SetPriority(ETHER1_CAN1_IRQn, NVIC_EncodePriority(FM3_ETH2_IRQ_PRIORITY_GROUPING,
239 
240  //Enable MAC transmission and reception
241  bFM3_ETHERNET_MAC1_MCR_TE = 1;
242  bFM3_ETHERNET_MAC1_MCR_RE = 1;
243 
244  //Enable DMA transmission and reception
245  bFM3_ETHERNET_MAC1_OMR_ST = 1;
246  bFM3_ETHERNET_MAC1_OMR_SR = 1;
247 
248  //Accept any packets from the upper layer
249  osSetEvent(&interface->nicTxEvent);
250 
251  //Successful initialization
252  return NO_ERROR;
253 }
254 
255 
256 /**
257  * @brief GPIO configuration
258  * @param[in] interface Underlying network interface
259  **/
260 
261 __weak_func void fm3Eth2InitGpio(NetInterface *interface)
262 {
263 //SK-FM3-176PMC-ETH evaluation board?
264 #if defined(USE_SK_FM3_176PMC_ETH)
265  //Select RMII interface mode
266  FM3_ETHERNET_CONTROL->ETH_MODE_f.IFMODE = 1;
267 
268  //Configure E_RXDV1 (PC0)
269  FM3_GPIO->PFRC_f.P0 = 1;
270  //Configure E_RX11 (PC1)
271  FM3_GPIO->PFRC_f.P1 = 1;
272  //Configure E_RX10 (PC2)
273  FM3_GPIO->PFRC_f.P2 = 1;
274  //Configure E_RXCK0_REFCK (PC8)
275  FM3_GPIO->PFRC_f.P8 = 1;
276  //Configure E_MDIO1 (PCC)
277  FM3_GPIO->PFRC_f.PC = 1;
278  //Configure E_MDC1 (PCD)
279  FM3_GPIO->PFRC_f.PD = 1;
280  //Configure E_TXEN1 (PCE)
281  FM3_GPIO->PFRC_f.PE = 1;
282  //Configure E_TX11 (PCF)
283  FM3_GPIO->PFRC_f.PF = 1;
284  //Configure E_TX10 (PD0)
285  FM3_GPIO->PFRD_f.P0 = 1;
286 
287  //Peripheral assignment
288  FM3_GPIO->EPFR14_f.E_TD1E = 1;
289  FM3_GPIO->EPFR14_f.E_TE1E = 1;
290  FM3_GPIO->EPFR14_f.E_MC1B = 1;
291  FM3_GPIO->EPFR14_f.E_MD1B = 1;
292  FM3_GPIO->EPFR14_f.E_SPLC0 = 0;
293  FM3_GPIO->EPFR14_f.E_SPLC1 = 1;
294 
295  //Configure PHY_RST as an output
296  FM3_GPIO->PFR4_f.P4 = 0;
297  FM3_GPIO->DDR4_f.P4 = 1;
298 
299  //Reset PHY transceiver
300  FM3_GPIO->PDOR4_f.P4 = 0;
301  sleep(10);
302  FM3_GPIO->PDOR4_f.P4 = 1;
303  sleep(10);
304 #endif
305 }
306 
307 
308 /**
309  * @brief Initialize DMA descriptor lists
310  * @param[in] interface Underlying network interface
311  **/
312 
314 {
315  uint_t i;
316 
317  //Initialize TX DMA descriptor list
318  for(i = 0; i < FM3_ETH2_TX_BUFFER_COUNT; i++)
319  {
320  //Use chain structure rather than ring structure
321  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
322  //Initialize transmit buffer size
323  txDmaDesc[i].tdes1 = 0;
324  //Transmit buffer address
325  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
326  //Next descriptor address
327  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
328  //Reserved fields
329  txDmaDesc[i].tdes4 = 0;
330  txDmaDesc[i].tdes5 = 0;
331  //Transmit frame time stamp
332  txDmaDesc[i].tdes6 = 0;
333  txDmaDesc[i].tdes7 = 0;
334  }
335 
336  //The last descriptor is chained to the first entry
337  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
338  //Point to the very first descriptor
339  txCurDmaDesc = &txDmaDesc[0];
340 
341  //Initialize RX DMA descriptor list
342  for(i = 0; i < FM3_ETH2_RX_BUFFER_COUNT; i++)
343  {
344  //The descriptor is initially owned by the DMA
345  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
346  //Use chain structure rather than ring structure
348  //Receive buffer address
349  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
350  //Next descriptor address
351  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
352  //Extended status
353  rxDmaDesc[i].rdes4 = 0;
354  //Reserved field
355  rxDmaDesc[i].rdes5 = 0;
356  //Receive frame time stamp
357  rxDmaDesc[i].rdes6 = 0;
358  rxDmaDesc[i].rdes7 = 0;
359  }
360 
361  //The last descriptor is chained to the first entry
362  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
363  //Point to the very first descriptor
364  rxCurDmaDesc = &rxDmaDesc[0];
365 
366  //Start location of the TX descriptor list
367  FM3_ETHERNET_MAC1->TDLAR = (uint32_t) txDmaDesc;
368  //Start location of the RX descriptor list
369  FM3_ETHERNET_MAC1->RDLAR = (uint32_t) rxDmaDesc;
370 }
371 
372 
373 /**
374  * @brief FM3 Ethernet MAC timer handler
375  *
376  * This routine is periodically called by the TCP/IP stack to handle periodic
377  * operations such as polling the link state
378  *
379  * @param[in] interface Underlying network interface
380  **/
381 
382 void fm3Eth2Tick(NetInterface *interface)
383 {
384  //Valid Ethernet PHY or switch driver?
385  if(interface->phyDriver != NULL)
386  {
387  //Handle periodic operations
388  interface->phyDriver->tick(interface);
389  }
390  else if(interface->switchDriver != NULL)
391  {
392  //Handle periodic operations
393  interface->switchDriver->tick(interface);
394  }
395  else
396  {
397  //Just for sanity
398  }
399 }
400 
401 
402 /**
403  * @brief Enable interrupts
404  * @param[in] interface Underlying network interface
405  **/
406 
408 {
409  //Enable Ethernet MAC interrupts
410  NVIC_EnableIRQ(ETHER1_CAN1_IRQn);
411 
412  //Valid Ethernet PHY or switch driver?
413  if(interface->phyDriver != NULL)
414  {
415  //Enable Ethernet PHY interrupts
416  interface->phyDriver->enableIrq(interface);
417  }
418  else if(interface->switchDriver != NULL)
419  {
420  //Enable Ethernet switch interrupts
421  interface->switchDriver->enableIrq(interface);
422  }
423  else
424  {
425  //Just for sanity
426  }
427 }
428 
429 
430 /**
431  * @brief Disable interrupts
432  * @param[in] interface Underlying network interface
433  **/
434 
436 {
437  //Disable Ethernet MAC interrupts
438  NVIC_DisableIRQ(ETHER1_CAN1_IRQn);
439 
440  //Valid Ethernet PHY or switch driver?
441  if(interface->phyDriver != NULL)
442  {
443  //Disable Ethernet PHY interrupts
444  interface->phyDriver->disableIrq(interface);
445  }
446  else if(interface->switchDriver != NULL)
447  {
448  //Disable Ethernet switch interrupts
449  interface->switchDriver->disableIrq(interface);
450  }
451  else
452  {
453  //Just for sanity
454  }
455 }
456 
457 
458 /**
459  * @brief FM3 Ethernet MAC interrupt service routine
460  **/
461 
463 {
464  bool_t flag;
465  uint32_t status;
466 
467  //Interrupt service routine prologue
468  osEnterIsr();
469 
470  //This flag will be set if a higher priority task must be woken
471  flag = FALSE;
472 
473  //Read DMA status register
474  status = FM3_ETHERNET_MAC1->SR;
475 
476  //Packet transmitted?
477  if((status & ETH_SR_TI) != 0)
478  {
479  //Clear TI interrupt flag
480  FM3_ETHERNET_MAC1->SR = ETH_SR_TI;
481 
482  //Check whether the TX buffer is available for writing
483  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
484  {
485  //Notify the TCP/IP stack that the transmitter is ready to send
486  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
487  }
488  }
489 
490  //Packet received?
491  if((status & ETH_SR_RI) != 0)
492  {
493  //Clear RI interrupt flag
494  FM3_ETHERNET_MAC1->SR = ETH_SR_RI;
495 
496  //Set event flag
497  nicDriverInterface->nicEvent = TRUE;
498  //Notify the TCP/IP stack of the event
499  flag |= osSetEventFromIsr(&netEvent);
500  }
501 
502  //Clear NIS interrupt flag
503  FM3_ETHERNET_MAC1->SR = ETH_SR_NIS;
504 
505  //Interrupt service routine epilogue
506  osExitIsr(flag);
507 }
508 
509 
510 /**
511  * @brief FM3 Ethernet MAC event handler
512  * @param[in] interface Underlying network interface
513  **/
514 
516 {
517  error_t error;
518 
519  //Process all pending packets
520  do
521  {
522  //Read incoming packet
523  error = fm3Eth2ReceivePacket(interface);
524 
525  //No more data in the receive buffer?
526  } while(error != ERROR_BUFFER_EMPTY);
527 }
528 
529 
530 /**
531  * @brief Send a packet
532  * @param[in] interface Underlying network interface
533  * @param[in] buffer Multi-part buffer containing the data to send
534  * @param[in] offset Offset to the first data byte
535  * @param[in] ancillary Additional options passed to the stack along with
536  * the packet
537  * @return Error code
538  **/
539 
541  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
542 {
543  size_t length;
544 
545  //Retrieve the length of the packet
546  length = netBufferGetLength(buffer) - offset;
547 
548  //Check the frame length
550  {
551  //The transmitter can accept another packet
552  osSetEvent(&interface->nicTxEvent);
553  //Report an error
554  return ERROR_INVALID_LENGTH;
555  }
556 
557  //Make sure the current buffer is available for writing
558  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) != 0)
559  {
560  return ERROR_FAILURE;
561  }
562 
563  //Copy user data to the transmit buffer
564  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
565 
566  //Write the number of bytes to send
567  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
568  //Set LS and FS flags as the data fits in a single buffer
569  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
570  //Give the ownership of the descriptor to the DMA
571  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
572 
573  //Clear TU flag to resume processing
574  FM3_ETHERNET_MAC1->SR = ETH_SR_TU;
575  //Instruct the DMA to poll the transmit descriptor list
576  FM3_ETHERNET_MAC1->TPDR = 0;
577 
578  //Point to the next descriptor in the list
579  txCurDmaDesc = (Fm3Eth2TxDmaDesc *) txCurDmaDesc->tdes3;
580 
581  //Check whether the next buffer is available for writing
582  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
583  {
584  //The transmitter can accept another packet
585  osSetEvent(&interface->nicTxEvent);
586  }
587 
588  //Data successfully written
589  return NO_ERROR;
590 }
591 
592 
593 /**
594  * @brief Receive a packet
595  * @param[in] interface Underlying network interface
596  * @return Error code
597  **/
598 
600 {
601  error_t error;
602  size_t n;
603  NetRxAncillary ancillary;
604 
605  //Current buffer available for reading?
606  if((rxCurDmaDesc->rdes0 & ETH_RDES0_OWN) == 0)
607  {
608  //FS and LS flags should be set
609  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) != 0 &&
610  (rxCurDmaDesc->rdes0 & ETH_RDES0_LS) != 0)
611  {
612  //Make sure no error occurred
613  if((rxCurDmaDesc->rdes0 & ETH_RDES0_ES) == 0)
614  {
615  //Retrieve the length of the frame
616  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
617  //Limit the number of data to read
619 
620  //Additional options can be passed to the stack along with the packet
621  ancillary = NET_DEFAULT_RX_ANCILLARY;
622 
623  //Pass the packet to the upper layer
624  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
625  &ancillary);
626 
627  //Valid packet received
628  error = NO_ERROR;
629  }
630  else
631  {
632  //The received packet contains an error
633  error = ERROR_INVALID_PACKET;
634  }
635  }
636  else
637  {
638  //The packet is not valid
639  error = ERROR_INVALID_PACKET;
640  }
641 
642  //Give the ownership of the descriptor back to the DMA
643  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
644  //Point to the next descriptor in the list
645  rxCurDmaDesc = (Fm3Eth2RxDmaDesc *) rxCurDmaDesc->rdes3;
646  }
647  else
648  {
649  //No more data in the receive buffer
650  error = ERROR_BUFFER_EMPTY;
651  }
652 
653  //Clear RU flag to resume processing
654  FM3_ETHERNET_MAC1->SR = ETH_SR_RU;
655  //Instruct the DMA to poll the receive descriptor list
656  FM3_ETHERNET_MAC1->RPDR = 0;
657 
658  //Return status code
659  return error;
660 }
661 
662 
663 /**
664  * @brief Configure MAC address filtering
665  * @param[in] interface Underlying network interface
666  * @return Error code
667  **/
668 
670 {
671  uint_t i;
672  uint_t k;
673  uint32_t crc;
674  uint32_t hashTable[2];
675  MacFilterEntry *entry;
676 
677  //Debug message
678  TRACE_DEBUG("Updating MAC filter...\r\n");
679 
680  //Set the MAC address of the station
681  FM3_ETHERNET_MAC1->MAR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
682  FM3_ETHERNET_MAC1->MAR0H = interface->macAddr.w[2];
683 
684  //Clear hash table
685  hashTable[0] = 0;
686  hashTable[1] = 0;
687 
688  //The MAC address filter contains the list of MAC addresses to accept
689  //when receiving an Ethernet frame
690  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
691  {
692  //Point to the current entry
693  entry = &interface->macAddrFilter[i];
694 
695  //Valid entry?
696  if(entry->refCount > 0)
697  {
698  //Compute CRC over the current MAC address
699  crc = fm3Eth2CalcCrc(&entry->addr, sizeof(MacAddr));
700 
701  //The upper 6 bits in the CRC register are used to index the
702  //contents of the hash table
703  k = (crc >> 26) & 0x3F;
704 
705  //Update hash table contents
706  hashTable[k / 32] |= (1 << (k % 32));
707  }
708  }
709 
710  //Write the hash table
711  FM3_ETHERNET_MAC1->MHTRL = hashTable[0];
712  FM3_ETHERNET_MAC1->MHTRH = hashTable[1];
713 
714  //Debug message
715  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", FM3_ETHERNET_MAC1->MHTRL);
716  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", FM3_ETHERNET_MAC1->MHTRH);
717 
718  //Successful processing
719  return NO_ERROR;
720 }
721 
722 
723 /**
724  * @brief Adjust MAC configuration parameters for proper operation
725  * @param[in] interface Underlying network interface
726  * @return Error code
727  **/
728 
730 {
731  stc_ethernet_mac_mcr_field_t config;
732 
733  //Read current MAC configuration
734  config = FM3_ETHERNET_MAC1->MCR_f;
735 
736  //10BASE-T or 100BASE-TX operation mode?
737  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
738  {
739  config.FES = 1;
740  }
741  else
742  {
743  config.FES = 0;
744  }
745 
746  //Half-duplex or full-duplex mode?
747  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
748  {
749  config.DM = 1;
750  }
751  else
752  {
753  config.DM = 0;
754  }
755 
756  //Update MAC configuration register
757  FM3_ETHERNET_MAC1->MCR_f = config;
758 
759  //Successful processing
760  return NO_ERROR;
761 }
762 
763 
764 /**
765  * @brief Write PHY register
766  * @param[in] opcode Access type (2 bits)
767  * @param[in] phyAddr PHY address (5 bits)
768  * @param[in] regAddr Register address (5 bits)
769  * @param[in] data Register value
770  **/
771 
772 void fm3Eth2WritePhyReg(uint8_t opcode, uint8_t phyAddr,
773  uint8_t regAddr, uint16_t data)
774 {
775  //Valid opcode?
776  if(opcode == SMI_OPCODE_WRITE)
777  {
778  //Set up a write operation
779  FM3_ETHERNET_MAC1->GAR_f.GW = 1;
780  //PHY address
781  FM3_ETHERNET_MAC1->GAR_f.PA = phyAddr;
782  //Register address
783  FM3_ETHERNET_MAC1->GAR_f.GR = regAddr;
784 
785  //Data to be written in the PHY register
786  FM3_ETHERNET_MAC1->GDR_f.GD = data;
787 
788  //Start a write operation
789  FM3_ETHERNET_MAC1->GAR_f.GB = 1;
790  //Wait for the write to complete
791  while(FM3_ETHERNET_MAC1->GAR_f.GB)
792  {
793  }
794  }
795  else
796  {
797  //The MAC peripheral only supports standard Clause 22 opcodes
798  }
799 }
800 
801 
802 /**
803  * @brief Read PHY register
804  * @param[in] opcode Access type (2 bits)
805  * @param[in] phyAddr PHY address (5 bits)
806  * @param[in] regAddr Register address (5 bits)
807  * @return Register value
808  **/
809 
810 uint16_t fm3Eth2ReadPhyReg(uint8_t opcode, uint8_t phyAddr,
811  uint8_t regAddr)
812 {
813  uint16_t data;
814 
815  //Valid opcode?
816  if(opcode == SMI_OPCODE_READ)
817  {
818  //Set up a read operation
819  FM3_ETHERNET_MAC1->GAR_f.GW = 0;
820  //PHY address
821  FM3_ETHERNET_MAC1->GAR_f.PA = phyAddr;
822  //Register address
823  FM3_ETHERNET_MAC1->GAR_f.GR = regAddr;
824 
825  //Start a read operation
826  FM3_ETHERNET_MAC1->GAR_f.GB = 1;
827  //Wait for the read to complete
828  while(FM3_ETHERNET_MAC1->GAR_f.GB)
829  {
830  }
831 
832  //Get register value
833  data = FM3_ETHERNET_MAC1->GDR_f.GD;
834  }
835  else
836  {
837  //The MAC peripheral only supports standard Clause 22 opcodes
838  data = 0;
839  }
840 
841  //Return the value of the PHY register
842  return data;
843 }
844 
845 
846 /**
847  * @brief CRC calculation
848  * @param[in] data Pointer to the data over which to calculate the CRC
849  * @param[in] length Number of bytes to process
850  * @return Resulting CRC value
851  **/
852 
853 uint32_t fm3Eth2CalcCrc(const void *data, size_t length)
854 {
855  uint_t i;
856  uint_t j;
857  uint32_t crc;
858  const uint8_t *p;
859 
860  //Point to the data over which to calculate the CRC
861  p = (uint8_t *) data;
862  //CRC preset value
863  crc = 0xFFFFFFFF;
864 
865  //Loop through data
866  for(i = 0; i < length; i++)
867  {
868  //The message is processed bit by bit
869  for(j = 0; j < 8; j++)
870  {
871  //Update CRC value
872  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
873  {
874  crc = (crc << 1) ^ 0x04C11DB7;
875  }
876  else
877  {
878  crc = crc << 1;
879  }
880  }
881  }
882 
883  //Return CRC value
884  return ~crc;
885 }
#define txDmaDesc
#define rxBuffer
#define txBuffer
#define rxDmaDesc
__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
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
MacAddr
Definition: ethernet.h:195
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define ETH_TDES0_OWN
#define ETH_SR_TU
#define ETH_RDES0_FS
#define ETH_TDES0_IC
#define ETH_RDES1_RCH
#define ETH_RDES0_OWN
#define ETH_RDES0_LS
#define ETH_RDES0_FL
#define ETH_SR_NIS
#define ETH_RDES0_ES
#define ETH_TDES0_LS
#define ETH_SR_RI
#define ETH_SR_TI
#define ETH_RDES1_RBS1
#define ETH_SR_RU
#define ETH_TDES0_TCH
#define ETH_TDES0_FS
#define ETH_TDES1_TBS1
error_t fm3Eth2UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
const NicDriver fm3Eth2Driver
FM3 Ethernet MAC driver (ETHER1 instance)
void ETHER1_CAN1_IRQHandler(void)
FM3 Ethernet MAC interrupt service routine.
error_t fm3Eth2SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
void fm3Eth2DisableIrq(NetInterface *interface)
Disable interrupts.
error_t fm3Eth2UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void fm3Eth2EnableIrq(NetInterface *interface)
Enable interrupts.
uint16_t fm3Eth2ReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
void fm3Eth2Tick(NetInterface *interface)
FM3 Ethernet MAC timer handler.
__weak_func void fm3Eth2InitGpio(NetInterface *interface)
GPIO configuration.
error_t fm3Eth2ReceivePacket(NetInterface *interface)
Receive a packet.
void fm3Eth2InitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
void fm3Eth2WritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
uint32_t fm3Eth2CalcCrc(const void *data, size_t length)
CRC calculation.
void fm3Eth2EventHandler(NetInterface *interface)
FM3 Ethernet MAC event handler.
error_t fm3Eth2Init(NetInterface *interface)
FM3 Ethernet MAC initialization.
Cypress FM3 Ethernet MAC driver (ETHER1 instance)
#define FM3_ETH2_IRQ_GROUP_PRIORITY
#define FM3_ETH2_RX_BUFFER_COUNT
#define FM3_ETH2_IRQ_PRIORITY_GROUPING
#define FM3_ETH2_TX_BUFFER_SIZE
#define FM3_ETH2_RX_BUFFER_SIZE
#define FM3_ETH2_TX_BUFFER_COUNT
#define FM3_ETH2_IRQ_SUB_PRIORITY
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 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)
Enhanced RX DMA descriptor.
Enhanced TX DMA descriptor.
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
uint8_t length
Definition: tcp.h:368