fm4_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file fm4_eth_driver.c
3  * @brief Cypress FM4 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 "mcu.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 Fm4TxDmaDesc *txCurDmaDesc;
79 //Pointer to the current RX DMA descriptor
80 static Fm4RxDmaDesc *rxCurDmaDesc;
81 
82 
83 /**
84  * @brief FM4 Ethernet MAC driver
85  **/
86 
88 {
90  ETH_MTU,
91  fm4EthInit,
92  fm4EthTick,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief FM4 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 FM4 Ethernet MAC...\r\n");
120 
121  //Save underlying network interface
122  nicDriverInterface = interface;
123 
124  //GPIO configuration
125  fm4EthInitGpio(interface);
126 
127  //Enable Ethernet MAC clock
128  FM4_ETHERNET_CONTROL->ETH_CLKG_f.MACEN = 1;
129 
130  //Reset Ethernet MAC peripheral
131  FM4_ETHERNET_CONTROL->ETH_MODE_f.RST0 = 1;
132  FM4_ETHERNET_CONTROL->ETH_MODE_f.RST0 = 0;
133 
134  //Perform a software reset
135  FM4_ETHERNET_MAC0->BMR_f.SWR = 1;
136  //Wait for the reset to complete
137  while(FM4_ETHERNET_MAC0->BMR_f.SWR)
138  {
139  }
140 
141  //Ensure that on-going AHB transactions are complete
142  while(FM4_ETHERNET_MAC0->AHBSR_f.AHBS)
143  {
144  }
145 
146  //Adjust MDC clock range depending on HCLK frequency
147  FM4_ETHERNET_MAC0->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  FM4_ETHERNET_MAC0->MCR = 0;
174  FM4_ETHERNET_MAC0->MCR_f.PS = 1;
175  FM4_ETHERNET_MAC0->MCR_f.DO = 1;
176 
177  //Set the MAC address of the station
178  FM4_ETHERNET_MAC0->MAR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
179  FM4_ETHERNET_MAC0->MAR0H = interface->macAddr.w[2];
180 
181  //Initialize hash table
182  FM4_ETHERNET_MAC0->MHTRL = 0;
183  FM4_ETHERNET_MAC0->MHTRH = 0;
184 
185  //Configure the receive filter
186  FM4_ETHERNET_MAC0->MFFR = 0;
187  FM4_ETHERNET_MAC0->MFFR_f.HPF = 1;
188  FM4_ETHERNET_MAC0->MFFR_f.HMC = 1;
189 
190  //Disable flow control
191  FM4_ETHERNET_MAC0->FCR = 0;
192 
193  //Enable store and forward mode
194  FM4_ETHERNET_MAC0->OMR = 0;
195  FM4_ETHERNET_MAC0->OMR_f.RSF = 1;
196  FM4_ETHERNET_MAC0->OMR_f.TSF = 1;
197 
198  //Configure DMA bus mode
199  FM4_ETHERNET_MAC0->BMR = 0;
200  FM4_ETHERNET_MAC0->BMR_f.TXPR = 0;
201  FM4_ETHERNET_MAC0->BMR_f.MB = 1;
202  FM4_ETHERNET_MAC0->BMR_f.AAL = 0;
203  FM4_ETHERNET_MAC0->BMR_f._8XPBL = 0;
204  FM4_ETHERNET_MAC0->BMR_f.USP = 1;
205  FM4_ETHERNET_MAC0->BMR_f.RPBL = 32;
206  FM4_ETHERNET_MAC0->BMR_f.FB = 0;
207  FM4_ETHERNET_MAC0->BMR_f.PR = 0;
208  FM4_ETHERNET_MAC0->BMR_f.PBL = 32;
209  FM4_ETHERNET_MAC0->BMR_f.ATDS = 1;
210  FM4_ETHERNET_MAC0->BMR_f.DSL = 0;
211  FM4_ETHERNET_MAC0->BMR_f.DA = 0;
212 
213  //Initialize DMA descriptor lists
214  fm4EthInitDmaDesc(interface);
215 
216  //Prevent interrupts from being generated when statistic counters reach
217  //half their maximum value
218  FM4_ETHERNET_MAC0->MMC_INTR_MASK_TX = 0xFFFFFFFF;
219  FM4_ETHERNET_MAC0->MMC_INTR_MASK_RX = 0xFFFFFFFF;
220  FM4_ETHERNET_MAC0->MMC_IPC_INTR_MASK_RX = 0xFFFFFFFF;
221 
222  //Disable MAC interrupts
223  bFM4_ETHERNET_MAC0_IMR_LPIIM = 1;
224  bFM4_ETHERNET_MAC0_IMR_TSIM = 1;
225  bFM4_ETHERNET_MAC0_IMR_PIM = 1;
226  bFM4_ETHERNET_MAC0_IMR_RGIM = 1;
227 
228  //Enable the desired DMA interrupts
229  bFM4_ETHERNET_MAC0_IER_TIE = 1;
230  bFM4_ETHERNET_MAC0_IER_RIE = 1;
231  bFM4_ETHERNET_MAC0_IER_NIE = 1;
232 
233  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
234  NVIC_SetPriorityGrouping(FM4_ETH_IRQ_PRIORITY_GROUPING);
235 
236  //Configure Ethernet interrupt priority
237  NVIC_SetPriority(ETHER0_IRQn, NVIC_EncodePriority(FM4_ETH_IRQ_PRIORITY_GROUPING,
239 
240  //Enable MAC transmission and reception
241  bFM4_ETHERNET_MAC0_MCR_TE = 1;
242  bFM4_ETHERNET_MAC0_MCR_RE = 1;
243 
244  //Enable DMA transmission and reception
245  bFM4_ETHERNET_MAC0_OMR_ST = 1;
246  bFM4_ETHERNET_MAC0_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 fm4EthInitGpio(NetInterface *interface)
262 {
263 //SK-FM4-176L-S6E2CC-ETH or SK-FM4-176L-S6E2GM evaluation board?
264 #if defined(USE_SK_FM4_176L_S6E2CC_ETH) || defined(USE_SK_FM4_176L_S6E2GM)
265  //Select MII interface mode
266  FM4_ETHERNET_CONTROL->ETH_MODE_f.IFMODE = 0;
267 
268  //Configure E_RXER (PC0)
269  FM4_GPIO->PFRC_f.P0 = 1;
270  //Configure E_RX03 (PC1)
271  FM4_GPIO->PFRC_f.P1 = 1;
272  //Configure E_RX02 (PC2)
273  FM4_GPIO->PFRC_f.P2 = 1;
274  //Configure E_RX01 (PC3)
275  FM4_GPIO->PFRC_f.P3 = 1;
276  //Configure E_RX00 (PC4)
277  FM4_GPIO->PFRC_f.P4 = 1;
278  //Configure E_RXDV (PC5)
279  FM4_GPIO->PFRC_f.P5 = 1;
280  //Configure E_MDIO (PC6)
281  FM4_GPIO->PFRC_f.P6 = 1;
282  //Configure E_MDC (PC7)
283  FM4_GPIO->PFRC_f.P7 = 1;
284  //Configure E_RXCK_REFCK (PC8)
285  FM4_GPIO->PFRC_f.P8 = 1;
286  //Configure E_COL (PC9)
287  FM4_GPIO->PFRC_f.P9 = 1;
288  //Configure E_CRS (PCA)
289  FM4_GPIO->PFRC_f.PA = 1;
290  //Configure E_TCK (PCC)
291  FM4_GPIO->PFRC_f.PC = 1;
292  //Configure E_TXER (PCD)
293  FM4_GPIO->PFRC_f.PD = 1;
294  //Configure E_TX03 (PCE)
295  FM4_GPIO->PFRC_f.PE = 1;
296  //Configure E_TX02 (PCF)
297  FM4_GPIO->PFRC_f.PF = 1;
298  //Configure E_TX01 (PD0)
299  FM4_GPIO->PFRD_f.P0 = 1;
300  //Configure E_TX00 (PD1)
301  FM4_GPIO->PFRD_f.P1 = 1;
302  //Configure E_TXEN (PD2)
303  FM4_GPIO->PFRD_f.P2 = 1;
304 
305  //Peripheral assignment
306  FM4_GPIO->EPFR14_f.E_TD0E = 1;
307  FM4_GPIO->EPFR14_f.E_TD1E = 1;
308  FM4_GPIO->EPFR14_f.E_TE0E = 1;
309  FM4_GPIO->EPFR14_f.E_TE1E = 1;
310  FM4_GPIO->EPFR14_f.E_MC0E = 1;
311  FM4_GPIO->EPFR14_f.E_MC1B = 1;
312  FM4_GPIO->EPFR14_f.E_MD0B = 1;
313  FM4_GPIO->EPFR14_f.E_MD1B = 1;
314  FM4_GPIO->EPFR14_f.E_SPLC = 1;
315 
316  //Configure PHY_RST as an output
317  FM4_GPIO->PFR6_f.P5 = 0;
318  FM4_GPIO->DDR6_f.P5 = 1;
319 
320  //Reset PHY transceiver
321  FM4_GPIO->PDOR6_f.P5 = 0;
322  sleep(10);
323  FM4_GPIO->PDOR6_f.P5 = 1;
324  sleep(10);
325 #endif
326 }
327 
328 
329 /**
330  * @brief Initialize DMA descriptor lists
331  * @param[in] interface Underlying network interface
332  **/
333 
335 {
336  uint_t i;
337 
338  //Initialize TX DMA descriptor list
339  for(i = 0; i < FM4_ETH_TX_BUFFER_COUNT; i++)
340  {
341  //Use chain structure rather than ring structure
342  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
343  //Initialize transmit buffer size
344  txDmaDesc[i].tdes1 = 0;
345  //Transmit buffer address
346  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
347  //Next descriptor address
348  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
349  //Reserved fields
350  txDmaDesc[i].tdes4 = 0;
351  txDmaDesc[i].tdes5 = 0;
352  //Transmit frame time stamp
353  txDmaDesc[i].tdes6 = 0;
354  txDmaDesc[i].tdes7 = 0;
355  }
356 
357  //The last descriptor is chained to the first entry
358  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
359  //Point to the very first descriptor
360  txCurDmaDesc = &txDmaDesc[0];
361 
362  //Initialize RX DMA descriptor list
363  for(i = 0; i < FM4_ETH_RX_BUFFER_COUNT; i++)
364  {
365  //The descriptor is initially owned by the DMA
366  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
367  //Use chain structure rather than ring structure
369  //Receive buffer address
370  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
371  //Next descriptor address
372  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
373  //Extended status
374  rxDmaDesc[i].rdes4 = 0;
375  //Reserved field
376  rxDmaDesc[i].rdes5 = 0;
377  //Receive frame time stamp
378  rxDmaDesc[i].rdes6 = 0;
379  rxDmaDesc[i].rdes7 = 0;
380  }
381 
382  //The last descriptor is chained to the first entry
383  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
384  //Point to the very first descriptor
385  rxCurDmaDesc = &rxDmaDesc[0];
386 
387  //Start location of the TX descriptor list
388  FM4_ETHERNET_MAC0->TDLAR = (uint32_t) txDmaDesc;
389  //Start location of the RX descriptor list
390  FM4_ETHERNET_MAC0->RDLAR = (uint32_t) rxDmaDesc;
391 }
392 
393 
394 /**
395  * @brief FM4 Ethernet MAC timer handler
396  *
397  * This routine is periodically called by the TCP/IP stack to handle periodic
398  * operations such as polling the link state
399  *
400  * @param[in] interface Underlying network interface
401  **/
402 
403 void fm4EthTick(NetInterface *interface)
404 {
405  //Valid Ethernet PHY or switch driver?
406  if(interface->phyDriver != NULL)
407  {
408  //Handle periodic operations
409  interface->phyDriver->tick(interface);
410  }
411  else if(interface->switchDriver != NULL)
412  {
413  //Handle periodic operations
414  interface->switchDriver->tick(interface);
415  }
416  else
417  {
418  //Just for sanity
419  }
420 }
421 
422 
423 /**
424  * @brief Enable interrupts
425  * @param[in] interface Underlying network interface
426  **/
427 
429 {
430  //Enable Ethernet MAC interrupts
431  NVIC_EnableIRQ(ETHER0_IRQn);
432 
433  //Valid Ethernet PHY or switch driver?
434  if(interface->phyDriver != NULL)
435  {
436  //Enable Ethernet PHY interrupts
437  interface->phyDriver->enableIrq(interface);
438  }
439  else if(interface->switchDriver != NULL)
440  {
441  //Enable Ethernet switch interrupts
442  interface->switchDriver->enableIrq(interface);
443  }
444  else
445  {
446  //Just for sanity
447  }
448 }
449 
450 
451 /**
452  * @brief Disable interrupts
453  * @param[in] interface Underlying network interface
454  **/
455 
457 {
458  //Disable Ethernet MAC interrupts
459  NVIC_DisableIRQ(ETHER0_IRQn);
460 
461  //Valid Ethernet PHY or switch driver?
462  if(interface->phyDriver != NULL)
463  {
464  //Disable Ethernet PHY interrupts
465  interface->phyDriver->disableIrq(interface);
466  }
467  else if(interface->switchDriver != NULL)
468  {
469  //Disable Ethernet switch interrupts
470  interface->switchDriver->disableIrq(interface);
471  }
472  else
473  {
474  //Just for sanity
475  }
476 }
477 
478 
479 /**
480  * @brief FM4 Ethernet MAC interrupt service routine
481  **/
482 
484 {
485  bool_t flag;
486  uint32_t status;
487 
488  //Interrupt service routine prologue
489  osEnterIsr();
490 
491  //This flag will be set if a higher priority task must be woken
492  flag = FALSE;
493 
494  //Read DMA status register
495  status = FM4_ETHERNET_MAC0->SR;
496 
497  //Packet transmitted?
498  if((status & ETH_SR_TI) != 0)
499  {
500  //Clear TI interrupt flag
501  FM4_ETHERNET_MAC0->SR = ETH_SR_TI;
502 
503  //Check whether the TX buffer is available for writing
504  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
505  {
506  //Notify the TCP/IP stack that the transmitter is ready to send
507  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
508  }
509  }
510 
511  //Packet received?
512  if((status & ETH_SR_RI) != 0)
513  {
514  //Clear RI interrupt flag
515  FM4_ETHERNET_MAC0->SR = ETH_SR_RI;
516 
517  //Set event flag
518  nicDriverInterface->nicEvent = TRUE;
519  //Notify the TCP/IP stack of the event
520  flag |= osSetEventFromIsr(&netEvent);
521  }
522 
523  //Clear NIS interrupt flag
524  FM4_ETHERNET_MAC0->SR = ETH_SR_NIS;
525 
526  //Interrupt service routine epilogue
527  osExitIsr(flag);
528 }
529 
530 
531 /**
532  * @brief FM4 Ethernet MAC event handler
533  * @param[in] interface Underlying network interface
534  **/
535 
537 {
538  error_t error;
539 
540  //Process all pending packets
541  do
542  {
543  //Read incoming packet
544  error = fm4EthReceivePacket(interface);
545 
546  //No more data in the receive buffer?
547  } while(error != ERROR_BUFFER_EMPTY);
548 }
549 
550 
551 /**
552  * @brief Send a packet
553  * @param[in] interface Underlying network interface
554  * @param[in] buffer Multi-part buffer containing the data to send
555  * @param[in] offset Offset to the first data byte
556  * @param[in] ancillary Additional options passed to the stack along with
557  * the packet
558  * @return Error code
559  **/
560 
562  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
563 {
564  size_t length;
565 
566  //Retrieve the length of the packet
567  length = netBufferGetLength(buffer) - offset;
568 
569  //Check the frame length
571  {
572  //The transmitter can accept another packet
573  osSetEvent(&interface->nicTxEvent);
574  //Report an error
575  return ERROR_INVALID_LENGTH;
576  }
577 
578  //Make sure the current buffer is available for writing
579  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) != 0)
580  {
581  return ERROR_FAILURE;
582  }
583 
584  //Copy user data to the transmit buffer
585  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
586 
587  //Write the number of bytes to send
588  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
589  //Set LS and FS flags as the data fits in a single buffer
590  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
591  //Give the ownership of the descriptor to the DMA
592  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
593 
594  //Clear TU flag to resume processing
595  FM4_ETHERNET_MAC0->SR = ETH_SR_TU;
596  //Instruct the DMA to poll the transmit descriptor list
597  FM4_ETHERNET_MAC0->TPDR = 0;
598 
599  //Point to the next descriptor in the list
600  txCurDmaDesc = (Fm4TxDmaDesc *) txCurDmaDesc->tdes3;
601 
602  //Check whether the next buffer is available for writing
603  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
604  {
605  //The transmitter can accept another packet
606  osSetEvent(&interface->nicTxEvent);
607  }
608 
609  //Data successfully written
610  return NO_ERROR;
611 }
612 
613 
614 /**
615  * @brief Receive a packet
616  * @param[in] interface Underlying network interface
617  * @return Error code
618  **/
619 
621 {
622  error_t error;
623  size_t n;
624  NetRxAncillary ancillary;
625 
626  //Current buffer available for reading?
627  if((rxCurDmaDesc->rdes0 & ETH_RDES0_OWN) == 0)
628  {
629  //FS and LS flags should be set
630  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) != 0 &&
631  (rxCurDmaDesc->rdes0 & ETH_RDES0_LS) != 0)
632  {
633  //Make sure no error occurred
634  if((rxCurDmaDesc->rdes0 & ETH_RDES0_ES) == 0)
635  {
636  //Retrieve the length of the frame
637  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
638  //Limit the number of data to read
640 
641  //Additional options can be passed to the stack along with the packet
642  ancillary = NET_DEFAULT_RX_ANCILLARY;
643 
644  //Pass the packet to the upper layer
645  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
646  &ancillary);
647 
648  //Valid packet received
649  error = NO_ERROR;
650  }
651  else
652  {
653  //The received packet contains an error
654  error = ERROR_INVALID_PACKET;
655  }
656  }
657  else
658  {
659  //The packet is not valid
660  error = ERROR_INVALID_PACKET;
661  }
662 
663  //Give the ownership of the descriptor back to the DMA
664  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
665  //Point to the next descriptor in the list
666  rxCurDmaDesc = (Fm4RxDmaDesc *) rxCurDmaDesc->rdes3;
667  }
668  else
669  {
670  //No more data in the receive buffer
671  error = ERROR_BUFFER_EMPTY;
672  }
673 
674  //Clear RU flag to resume processing
675  FM4_ETHERNET_MAC0->SR = ETH_SR_RU;
676  //Instruct the DMA to poll the receive descriptor list
677  FM4_ETHERNET_MAC0->RPDR = 0;
678 
679  //Return status code
680  return error;
681 }
682 
683 
684 /**
685  * @brief Configure MAC address filtering
686  * @param[in] interface Underlying network interface
687  * @return Error code
688  **/
689 
691 {
692  uint_t i;
693  uint_t k;
694  uint32_t crc;
695  uint32_t hashTable[2];
696  MacFilterEntry *entry;
697 
698  //Debug message
699  TRACE_DEBUG("Updating MAC filter...\r\n");
700 
701  //Set the MAC address of the station
702  FM4_ETHERNET_MAC0->MAR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
703  FM4_ETHERNET_MAC0->MAR0H = interface->macAddr.w[2];
704 
705  //Clear hash table
706  hashTable[0] = 0;
707  hashTable[1] = 0;
708 
709  //The MAC address filter contains the list of MAC addresses to accept
710  //when receiving an Ethernet frame
711  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
712  {
713  //Point to the current entry
714  entry = &interface->macAddrFilter[i];
715 
716  //Valid entry?
717  if(entry->refCount > 0)
718  {
719  //Compute CRC over the current MAC address
720  crc = fm4EthCalcCrc(&entry->addr, sizeof(MacAddr));
721 
722  //The upper 6 bits in the CRC register are used to index the
723  //contents of the hash table
724  k = (crc >> 26) & 0x3F;
725 
726  //Update hash table contents
727  hashTable[k / 32] |= (1 << (k % 32));
728  }
729  }
730 
731  //Write the hash table
732  FM4_ETHERNET_MAC0->MHTRL = hashTable[0];
733  FM4_ETHERNET_MAC0->MHTRH = hashTable[1];
734 
735  //Debug message
736  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", FM4_ETHERNET_MAC0->MHTRL);
737  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", FM4_ETHERNET_MAC0->MHTRH);
738 
739  //Successful processing
740  return NO_ERROR;
741 }
742 
743 
744 /**
745  * @brief Adjust MAC configuration parameters for proper operation
746  * @param[in] interface Underlying network interface
747  * @return Error code
748  **/
749 
751 {
752  stc_ethernet_mac_mcr_field_t config;
753 
754  //Read current MAC configuration
755  config = FM4_ETHERNET_MAC0->MCR_f;
756 
757  //10BASE-T or 100BASE-TX operation mode?
758  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
759  {
760  config.FES = 1;
761  }
762  else
763  {
764  config.FES = 0;
765  }
766 
767  //Half-duplex or full-duplex mode?
768  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
769  {
770  config.DM = 1;
771  }
772  else
773  {
774  config.DM = 0;
775  }
776 
777  //Update MAC configuration register
778  FM4_ETHERNET_MAC0->MCR_f = config;
779 
780  //Successful processing
781  return NO_ERROR;
782 }
783 
784 
785 /**
786  * @brief Write PHY register
787  * @param[in] opcode Access type (2 bits)
788  * @param[in] phyAddr PHY address (5 bits)
789  * @param[in] regAddr Register address (5 bits)
790  * @param[in] data Register value
791  **/
792 
793 void fm4EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
794  uint8_t regAddr, uint16_t data)
795 {
796  //Valid opcode?
797  if(opcode == SMI_OPCODE_WRITE)
798  {
799  //Set up a write operation
800  FM4_ETHERNET_MAC0->GAR_f.GW = 1;
801  //PHY address
802  FM4_ETHERNET_MAC0->GAR_f.PA = phyAddr;
803  //Register address
804  FM4_ETHERNET_MAC0->GAR_f.GR = regAddr;
805 
806  //Data to be written in the PHY register
807  FM4_ETHERNET_MAC0->GDR_f.GD = data;
808 
809  //Start a write operation
810  FM4_ETHERNET_MAC0->GAR_f.GB = 1;
811  //Wait for the write to complete
812  while(FM4_ETHERNET_MAC0->GAR_f.GB)
813  {
814  }
815  }
816  else
817  {
818  //The MAC peripheral only supports standard Clause 22 opcodes
819  }
820 }
821 
822 
823 /**
824  * @brief Read PHY register
825  * @param[in] opcode Access type (2 bits)
826  * @param[in] phyAddr PHY address (5 bits)
827  * @param[in] regAddr Register address (5 bits)
828  * @return Register value
829  **/
830 
831 uint16_t fm4EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
832  uint8_t regAddr)
833 {
834  uint16_t data;
835 
836  //Valid opcode?
837  if(opcode == SMI_OPCODE_READ)
838  {
839  //Set up a read operation
840  FM4_ETHERNET_MAC0->GAR_f.GW = 0;
841  //PHY address
842  FM4_ETHERNET_MAC0->GAR_f.PA = phyAddr;
843  //Register address
844  FM4_ETHERNET_MAC0->GAR_f.GR = regAddr;
845 
846  //Start a read operation
847  FM4_ETHERNET_MAC0->GAR_f.GB = 1;
848  //Wait for the read to complete
849  while(FM4_ETHERNET_MAC0->GAR_f.GB)
850  {
851  }
852 
853  //Get register value
854  data = FM4_ETHERNET_MAC0->GDR_f.GD;
855  }
856  else
857  {
858  //The MAC peripheral only supports standard Clause 22 opcodes
859  data = 0;
860  }
861 
862  //Return the value of the PHY register
863  return data;
864 }
865 
866 
867 /**
868  * @brief CRC calculation
869  * @param[in] data Pointer to the data over which to calculate the CRC
870  * @param[in] length Number of bytes to process
871  * @return Resulting CRC value
872  **/
873 
874 uint32_t fm4EthCalcCrc(const void *data, size_t length)
875 {
876  uint_t i;
877  uint_t j;
878  uint32_t crc;
879  const uint8_t *p;
880 
881  //Point to the data over which to calculate the CRC
882  p = (uint8_t *) data;
883  //CRC preset value
884  crc = 0xFFFFFFFF;
885 
886  //Loop through data
887  for(i = 0; i < length; i++)
888  {
889  //The message is processed bit by bit
890  for(j = 0; j < 8; j++)
891  {
892  //Update CRC value
893  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
894  {
895  crc = (crc << 1) ^ 0x04C11DB7;
896  }
897  else
898  {
899  crc = crc << 1;
900  }
901  }
902  }
903 
904  //Return CRC value
905  return ~crc;
906 }
#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
void fm4EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
error_t fm4EthReceivePacket(NetInterface *interface)
Receive a packet.
error_t fm4EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void fm4EthTick(NetInterface *interface)
FM4 Ethernet MAC timer handler.
void fm4EthEnableIrq(NetInterface *interface)
Enable interrupts.
void fm4EthDisableIrq(NetInterface *interface)
Disable interrupts.
uint16_t fm4EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
error_t fm4EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
__weak_func void fm4EthInitGpio(NetInterface *interface)
GPIO configuration.
error_t fm4EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
void fm4EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t fm4EthInit(NetInterface *interface)
FM4 Ethernet MAC initialization.
void fm4EthEventHandler(NetInterface *interface)
FM4 Ethernet MAC event handler.
uint32_t fm4EthCalcCrc(const void *data, size_t length)
CRC calculation.
void ETHER0_IRQHandler(void)
FM4 Ethernet MAC interrupt service routine.
const NicDriver fm4EthDriver
FM4 Ethernet MAC driver.
Cypress FM4 Ethernet MAC driver.
#define FM4_ETH_RX_BUFFER_SIZE
#define FM4_ETH_IRQ_SUB_PRIORITY
#define FM4_ETH_RX_BUFFER_COUNT
#define FM4_ETH_IRQ_PRIORITY_GROUPING
#define FM4_ETH_IRQ_GROUP_PRIORITY
#define FM4_ETH_TX_BUFFER_SIZE
#define FM4_ETH_TX_BUFFER_COUNT
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.
uint32_t rdes2
uint32_t rdes0
uint32_t rdes3
Enhanced TX DMA descriptor.
uint32_t tdes1
uint32_t tdes2
uint32_t tdes3
uint32_t tdes0
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