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-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 "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 = 1;
206  FM4_ETHERNET_MAC0->BMR_f.FB = 0;
207  FM4_ETHERNET_MAC0->BMR_f.PR = 0;
208  FM4_ETHERNET_MAC0->BMR_f.PBL = 1;
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_NIE = 1;
230  bFM4_ETHERNET_MAC0_IER_RIE = 1;
231  bFM4_ETHERNET_MAC0_IER_TIE = 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 //SK-FM4-176L-S6E2CC-ETH or SK-FM4-176L-S6E2GM evaluation board?
257 #if defined(USE_SK_FM4_176L_S6E2CC_ETH) || defined(USE_SK_FM4_176L_S6E2GM)
258 
259 /**
260  * @brief GPIO configuration
261  * @param[in] interface Underlying network interface
262  **/
263 
264 void fm4EthInitGpio(NetInterface *interface)
265 {
266  //Select MII interface mode
267  FM4_ETHERNET_CONTROL->ETH_MODE_f.IFMODE = 0;
268 
269  //Configure E_RXER (PC0)
270  FM4_GPIO->PFRC_f.P0 = 1;
271  //Configure E_RX03 (PC1)
272  FM4_GPIO->PFRC_f.P1 = 1;
273  //Configure E_RX02 (PC2)
274  FM4_GPIO->PFRC_f.P2 = 1;
275  //Configure E_RX01 (PC3)
276  FM4_GPIO->PFRC_f.P3 = 1;
277  //Configure E_RX00 (PC4)
278  FM4_GPIO->PFRC_f.P4 = 1;
279  //Configure E_RXDV (PC5)
280  FM4_GPIO->PFRC_f.P5 = 1;
281  //Configure E_MDIO (PC6)
282  FM4_GPIO->PFRC_f.P6 = 1;
283  //Configure E_MDC (PC7)
284  FM4_GPIO->PFRC_f.P7 = 1;
285  //Configure E_RXCK_REFCK (PC8)
286  FM4_GPIO->PFRC_f.P8 = 1;
287  //Configure E_COL (PC9)
288  FM4_GPIO->PFRC_f.P9 = 1;
289  //Configure E_CRS (PCA)
290  FM4_GPIO->PFRC_f.PA = 1;
291  //Configure E_TCK (PCC)
292  FM4_GPIO->PFRC_f.PC = 1;
293  //Configure E_TXER (PCD)
294  FM4_GPIO->PFRC_f.PD = 1;
295  //Configure E_TX03 (PCE)
296  FM4_GPIO->PFRC_f.PE = 1;
297  //Configure E_TX02 (PCF)
298  FM4_GPIO->PFRC_f.PF = 1;
299  //Configure E_TX01 (PD0)
300  FM4_GPIO->PFRD_f.P0 = 1;
301  //Configure E_TX00 (PD1)
302  FM4_GPIO->PFRD_f.P1 = 1;
303  //Configure E_TXEN (PD2)
304  FM4_GPIO->PFRD_f.P2 = 1;
305 
306  //Peripheral assignment
307  FM4_GPIO->EPFR14_f.E_TD0E = 1;
308  FM4_GPIO->EPFR14_f.E_TD1E = 1;
309  FM4_GPIO->EPFR14_f.E_TE0E = 1;
310  FM4_GPIO->EPFR14_f.E_TE1E = 1;
311  FM4_GPIO->EPFR14_f.E_MC0E = 1;
312  FM4_GPIO->EPFR14_f.E_MC1B = 1;
313  FM4_GPIO->EPFR14_f.E_MD0B = 1;
314  FM4_GPIO->EPFR14_f.E_MD1B = 1;
315  FM4_GPIO->EPFR14_f.E_SPLC = 1;
316 
317  //Configure PHY_RST as an output
318  FM4_GPIO->PFR6_f.P5 = 0;
319  FM4_GPIO->DDR6_f.P5 = 1;
320 
321  //Reset PHY transceiver
322  FM4_GPIO->PDOR6_f.P5 = 0;
323  sleep(10);
324  FM4_GPIO->PDOR6_f.P5 = 1;
325  sleep(10);
326 }
327 
328 #endif
329 
330 
331 /**
332  * @brief Initialize DMA descriptor lists
333  * @param[in] interface Underlying network interface
334  **/
335 
337 {
338  uint_t i;
339 
340  //Initialize TX DMA descriptor list
341  for(i = 0; i < FM4_ETH_TX_BUFFER_COUNT; i++)
342  {
343  //Use chain structure rather than ring structure
344  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
345  //Initialize transmit buffer size
346  txDmaDesc[i].tdes1 = 0;
347  //Transmit buffer address
348  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
349  //Next descriptor address
350  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
351  //Reserved fields
352  txDmaDesc[i].tdes4 = 0;
353  txDmaDesc[i].tdes5 = 0;
354  //Transmit frame time stamp
355  txDmaDesc[i].tdes6 = 0;
356  txDmaDesc[i].tdes7 = 0;
357  }
358 
359  //The last descriptor is chained to the first entry
360  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
361  //Point to the very first descriptor
362  txCurDmaDesc = &txDmaDesc[0];
363 
364  //Initialize RX DMA descriptor list
365  for(i = 0; i < FM4_ETH_RX_BUFFER_COUNT; i++)
366  {
367  //The descriptor is initially owned by the DMA
368  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
369  //Use chain structure rather than ring structure
371  //Receive buffer address
372  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
373  //Next descriptor address
374  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
375  //Extended status
376  rxDmaDesc[i].rdes4 = 0;
377  //Reserved field
378  rxDmaDesc[i].rdes5 = 0;
379  //Receive frame time stamp
380  rxDmaDesc[i].rdes6 = 0;
381  rxDmaDesc[i].rdes7 = 0;
382  }
383 
384  //The last descriptor is chained to the first entry
385  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
386  //Point to the very first descriptor
387  rxCurDmaDesc = &rxDmaDesc[0];
388 
389  //Start location of the TX descriptor list
390  FM4_ETHERNET_MAC0->TDLAR = (uint32_t) txDmaDesc;
391  //Start location of the RX descriptor list
392  FM4_ETHERNET_MAC0->RDLAR = (uint32_t) rxDmaDesc;
393 }
394 
395 
396 /**
397  * @brief FM4 Ethernet MAC timer handler
398  *
399  * This routine is periodically called by the TCP/IP stack to handle periodic
400  * operations such as polling the link state
401  *
402  * @param[in] interface Underlying network interface
403  **/
404 
405 void fm4EthTick(NetInterface *interface)
406 {
407  //Valid Ethernet PHY or switch driver?
408  if(interface->phyDriver != NULL)
409  {
410  //Handle periodic operations
411  interface->phyDriver->tick(interface);
412  }
413  else if(interface->switchDriver != NULL)
414  {
415  //Handle periodic operations
416  interface->switchDriver->tick(interface);
417  }
418  else
419  {
420  //Just for sanity
421  }
422 }
423 
424 
425 /**
426  * @brief Enable interrupts
427  * @param[in] interface Underlying network interface
428  **/
429 
431 {
432  //Enable Ethernet MAC interrupts
433  NVIC_EnableIRQ(ETHER0_IRQn);
434 
435  //Valid Ethernet PHY or switch driver?
436  if(interface->phyDriver != NULL)
437  {
438  //Enable Ethernet PHY interrupts
439  interface->phyDriver->enableIrq(interface);
440  }
441  else if(interface->switchDriver != NULL)
442  {
443  //Enable Ethernet switch interrupts
444  interface->switchDriver->enableIrq(interface);
445  }
446  else
447  {
448  //Just for sanity
449  }
450 }
451 
452 
453 /**
454  * @brief Disable interrupts
455  * @param[in] interface Underlying network interface
456  **/
457 
459 {
460  //Disable Ethernet MAC interrupts
461  NVIC_DisableIRQ(ETHER0_IRQn);
462 
463  //Valid Ethernet PHY or switch driver?
464  if(interface->phyDriver != NULL)
465  {
466  //Disable Ethernet PHY interrupts
467  interface->phyDriver->disableIrq(interface);
468  }
469  else if(interface->switchDriver != NULL)
470  {
471  //Disable Ethernet switch interrupts
472  interface->switchDriver->disableIrq(interface);
473  }
474  else
475  {
476  //Just for sanity
477  }
478 }
479 
480 
481 /**
482  * @brief FM4 Ethernet MAC interrupt service routine
483  **/
484 
486 {
487  bool_t flag;
488 
489  //Interrupt service routine prologue
490  osEnterIsr();
491 
492  //This flag will be set if a higher priority task must be woken
493  flag = FALSE;
494 
495  //Packet transmitted?
496  if(bFM4_ETHERNET_MAC0_SR_TI)
497  {
498  //Clear TI interrupt flag
499  bFM4_ETHERNET_MAC0_SR_TI = 1;
500 
501  //Check whether the TX buffer is available for writing
502  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
503  {
504  //Notify the TCP/IP stack that the transmitter is ready to send
505  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
506  }
507  }
508 
509  //Packet received?
510  if(bFM4_ETHERNET_MAC0_SR_RI)
511  {
512  //Disable RIE interrupt
513  bFM4_ETHERNET_MAC0_IER_RIE = 0;
514 
515  //Set event flag
516  nicDriverInterface->nicEvent = TRUE;
517  //Notify the TCP/IP stack of the event
518  flag |= osSetEventFromIsr(&netEvent);
519  }
520 
521  //Clear NIS interrupt flag
522  bFM4_ETHERNET_MAC0_SR_NIS = 1;
523 
524  //Interrupt service routine epilogue
525  osExitIsr(flag);
526 }
527 
528 
529 /**
530  * @brief FM4 Ethernet MAC event handler
531  * @param[in] interface Underlying network interface
532  **/
533 
535 {
536  error_t error;
537 
538  //Packet received?
539  if(bFM4_ETHERNET_MAC0_SR_RI)
540  {
541  //Clear interrupt flag
542  bFM4_ETHERNET_MAC0_SR_RI = 1;
543 
544  //Process all pending packets
545  do
546  {
547  //Read incoming packet
548  error = fm4EthReceivePacket(interface);
549 
550  //No more data in the receive buffer?
551  } while(error != ERROR_BUFFER_EMPTY);
552  }
553 
554  //Re-enable DMA interrupts
555  bFM4_ETHERNET_MAC0_IER_NIE = 1;
556  bFM4_ETHERNET_MAC0_IER_RIE = 1;
557  bFM4_ETHERNET_MAC0_IER_TIE = 1;
558 }
559 
560 
561 /**
562  * @brief Send a packet
563  * @param[in] interface Underlying network interface
564  * @param[in] buffer Multi-part buffer containing the data to send
565  * @param[in] offset Offset to the first data byte
566  * @param[in] ancillary Additional options passed to the stack along with
567  * the packet
568  * @return Error code
569  **/
570 
572  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
573 {
574  size_t length;
575 
576  //Retrieve the length of the packet
577  length = netBufferGetLength(buffer) - offset;
578 
579  //Check the frame length
581  {
582  //The transmitter can accept another packet
583  osSetEvent(&interface->nicTxEvent);
584  //Report an error
585  return ERROR_INVALID_LENGTH;
586  }
587 
588  //Make sure the current buffer is available for writing
589  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) != 0)
590  {
591  return ERROR_FAILURE;
592  }
593 
594  //Copy user data to the transmit buffer
595  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
596 
597  //Write the number of bytes to send
598  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
599  //Set LS and FS flags as the data fits in a single buffer
600  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
601  //Give the ownership of the descriptor to the DMA
602  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
603 
604  //Clear TU flag to resume processing
605  bFM4_ETHERNET_MAC0_SR_TU = 1;
606  //Instruct the DMA to poll the transmit descriptor list
607  FM4_ETHERNET_MAC0->TPDR = 0;
608 
609  //Point to the next descriptor in the list
610  txCurDmaDesc = (Fm4TxDmaDesc *) txCurDmaDesc->tdes3;
611 
612  //Check whether the next buffer is available for writing
613  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
614  {
615  //The transmitter can accept another packet
616  osSetEvent(&interface->nicTxEvent);
617  }
618 
619  //Data successfully written
620  return NO_ERROR;
621 }
622 
623 
624 /**
625  * @brief Receive a packet
626  * @param[in] interface Underlying network interface
627  * @return Error code
628  **/
629 
631 {
632  error_t error;
633  size_t n;
634  NetRxAncillary ancillary;
635 
636  //The current buffer is available for reading?
637  if((rxCurDmaDesc->rdes0 & ETH_RDES0_OWN) == 0)
638  {
639  //FS and LS flags should be set
640  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) != 0 &&
641  (rxCurDmaDesc->rdes0 & ETH_RDES0_LS) != 0)
642  {
643  //Make sure no error occurred
644  if((rxCurDmaDesc->rdes0 & ETH_RDES0_ES) == 0)
645  {
646  //Retrieve the length of the frame
647  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
648  //Limit the number of data to read
650 
651  //Additional options can be passed to the stack along with the packet
652  ancillary = NET_DEFAULT_RX_ANCILLARY;
653 
654  //Pass the packet to the upper layer
655  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
656  &ancillary);
657 
658  //Valid packet received
659  error = NO_ERROR;
660  }
661  else
662  {
663  //The received packet contains an error
664  error = ERROR_INVALID_PACKET;
665  }
666  }
667  else
668  {
669  //The packet is not valid
670  error = ERROR_INVALID_PACKET;
671  }
672 
673  //Give the ownership of the descriptor back to the DMA
674  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
675  //Point to the next descriptor in the list
676  rxCurDmaDesc = (Fm4RxDmaDesc *) rxCurDmaDesc->rdes3;
677  }
678  else
679  {
680  //No more data in the receive buffer
681  error = ERROR_BUFFER_EMPTY;
682  }
683 
684  //Clear RU flag to resume processing
685  bFM4_ETHERNET_MAC0_SR_RU = 1;
686  //Instruct the DMA to poll the receive descriptor list
687  FM4_ETHERNET_MAC0->RPDR = 0;
688 
689  //Return status code
690  return error;
691 }
692 
693 
694 /**
695  * @brief Configure MAC address filtering
696  * @param[in] interface Underlying network interface
697  * @return Error code
698  **/
699 
701 {
702  uint_t i;
703  uint_t k;
704  uint32_t crc;
705  uint32_t hashTable[2];
706  MacFilterEntry *entry;
707 
708  //Debug message
709  TRACE_DEBUG("Updating MAC filter...\r\n");
710 
711  //Set the MAC address of the station
712  FM4_ETHERNET_MAC0->MAR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
713  FM4_ETHERNET_MAC0->MAR0H = interface->macAddr.w[2];
714 
715  //Clear hash table
716  hashTable[0] = 0;
717  hashTable[1] = 0;
718 
719  //The MAC address filter contains the list of MAC addresses to accept
720  //when receiving an Ethernet frame
721  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
722  {
723  //Point to the current entry
724  entry = &interface->macAddrFilter[i];
725 
726  //Valid entry?
727  if(entry->refCount > 0)
728  {
729  //Compute CRC over the current MAC address
730  crc = fm4EthCalcCrc(&entry->addr, sizeof(MacAddr));
731 
732  //The upper 6 bits in the CRC register are used to index the
733  //contents of the hash table
734  k = (crc >> 26) & 0x3F;
735 
736  //Update hash table contents
737  hashTable[k / 32] |= (1 << (k % 32));
738  }
739  }
740 
741  //Write the hash table
742  FM4_ETHERNET_MAC0->MHTRL = hashTable[0];
743  FM4_ETHERNET_MAC0->MHTRH = hashTable[1];
744 
745  //Debug message
746  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", FM4_ETHERNET_MAC0->MHTRL);
747  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", FM4_ETHERNET_MAC0->MHTRH);
748 
749  //Successful processing
750  return NO_ERROR;
751 }
752 
753 
754 /**
755  * @brief Adjust MAC configuration parameters for proper operation
756  * @param[in] interface Underlying network interface
757  * @return Error code
758  **/
759 
761 {
762  //10BASE-T or 100BASE-TX operation mode?
763  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
764  {
765  bFM4_ETHERNET_MAC0_MCR_FES = 1;
766  }
767  else
768  {
769  bFM4_ETHERNET_MAC0_MCR_FES = 0;
770  }
771 
772  //Half-duplex or full-duplex mode?
773  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
774  {
775  bFM4_ETHERNET_MAC0_MCR_DM = 1;
776  }
777  else
778  {
779  bFM4_ETHERNET_MAC0_MCR_DM = 0;
780  }
781 
782  //Successful processing
783  return NO_ERROR;
784 }
785 
786 
787 /**
788  * @brief Write PHY register
789  * @param[in] opcode Access type (2 bits)
790  * @param[in] phyAddr PHY address (5 bits)
791  * @param[in] regAddr Register address (5 bits)
792  * @param[in] data Register value
793  **/
794 
795 void fm4EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
796  uint8_t regAddr, uint16_t data)
797 {
798  //Valid opcode?
799  if(opcode == SMI_OPCODE_WRITE)
800  {
801  //Set up a write operation
802  FM4_ETHERNET_MAC0->GAR_f.GW = 1;
803  //PHY address
804  FM4_ETHERNET_MAC0->GAR_f.PA = phyAddr;
805  //Register address
806  FM4_ETHERNET_MAC0->GAR_f.GR = regAddr;
807 
808  //Data to be written in the PHY register
809  FM4_ETHERNET_MAC0->GDR_f.GD = data;
810 
811  //Start a write operation
812  FM4_ETHERNET_MAC0->GAR_f.GB = 1;
813  //Wait for the write to complete
814  while(FM4_ETHERNET_MAC0->GAR_f.GB)
815  {
816  }
817  }
818  else
819  {
820  //The MAC peripheral only supports standard Clause 22 opcodes
821  }
822 }
823 
824 
825 /**
826  * @brief Read PHY register
827  * @param[in] opcode Access type (2 bits)
828  * @param[in] phyAddr PHY address (5 bits)
829  * @param[in] regAddr Register address (5 bits)
830  * @return Register value
831  **/
832 
833 uint16_t fm4EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
834  uint8_t regAddr)
835 {
836  uint16_t data;
837 
838  //Valid opcode?
839  if(opcode == SMI_OPCODE_READ)
840  {
841  //Set up a read operation
842  FM4_ETHERNET_MAC0->GAR_f.GW = 0;
843  //PHY address
844  FM4_ETHERNET_MAC0->GAR_f.PA = phyAddr;
845  //Register address
846  FM4_ETHERNET_MAC0->GAR_f.GR = regAddr;
847 
848  //Start a read operation
849  FM4_ETHERNET_MAC0->GAR_f.GB = 1;
850  //Wait for the read to complete
851  while(FM4_ETHERNET_MAC0->GAR_f.GB)
852  {
853  }
854 
855  //Get register value
856  data = FM4_ETHERNET_MAC0->GDR_f.GD;
857  }
858  else
859  {
860  //The MAC peripheral only supports standard Clause 22 opcodes
861  data = 0;
862  }
863 
864  //Return the value of the PHY register
865  return data;
866 }
867 
868 
869 /**
870  * @brief CRC calculation
871  * @param[in] data Pointer to the data over which to calculate the CRC
872  * @param[in] length Number of bytes to process
873  * @return Resulting CRC value
874  **/
875 
876 uint32_t fm4EthCalcCrc(const void *data, size_t length)
877 {
878  uint_t i;
879  uint_t j;
880  uint32_t crc;
881  const uint8_t *p;
882 
883  //Point to the data over which to calculate the CRC
884  p = (uint8_t *) data;
885  //CRC preset value
886  crc = 0xFFFFFFFF;
887 
888  //Loop through data
889  for(i = 0; i < length; i++)
890  {
891  //The message is processed bit by bit
892  for(j = 0; j < 8; j++)
893  {
894  //Update CRC value
895  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
896  {
897  crc = (crc << 1) ^ 0x04C11DB7;
898  }
899  else
900  {
901  crc = crc << 1;
902  }
903  }
904  }
905 
906  //Return CRC value
907  return ~crc;
908 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
uint8_t length
Definition: coap_common.h:190
error_t fm4EthInit(NetInterface *interface)
FM4 Ethernet MAC initialization.
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
#define ETH_TDES0_IC
#define netEvent
Definition: net_legacy.h:267
uint16_t fm4EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
error_t fm4EthReceivePacket(NetInterface *interface)
Receive a packet.
uint8_t data[]
Definition: ethernet.h:209
Enhanced RX DMA descriptor.
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_TDES0_TCH
error_t fm4EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void fm4EthTick(NetInterface *interface)
FM4 Ethernet MAC timer handler.
uint8_t p
Definition: ndp.h:298
error_t fm4EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
error_t fm4EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:88
#define TRUE
Definition: os_port.h:50
#define sleep(delay)
Definition: os_port.h:251
__start_packed struct @5 MacAddr
MAC address.
#define FM4_ETH_IRQ_SUB_PRIORITY
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:249
void fm4EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define FM4_ETH_IRQ_PRIORITY_GROUPING
#define FM4_ETH_TX_BUFFER_SIZE
#define ETH_RDES0_OWN
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 SMI_OPCODE_WRITE
Definition: nic.h:65
uint32_t rdes2
uint32_t rdes0
#define FALSE
Definition: os_port.h:46
#define ETH_RDES1_RBS1
#define FM4_ETH_RX_BUFFER_SIZE
error_t
Error codes.
Definition: error.h:42
const NicDriver fm4EthDriver
FM4 Ethernet MAC driver.
uint32_t tdes3
#define ETH_RDES0_FL
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:96
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:248
void ETHER0_IRQHandler(void)
FM4 Ethernet MAC interrupt service routine.
uint32_t tdes1
#define ETH_RDES0_LS
#define NetTxAncillary
Definition: net_misc.h:36
#define FM4_ETH_IRQ_GROUP_PRIORITY
#define SMI_OPCODE_READ
Definition: nic.h:66
void fm4EthEventHandler(NetInterface *interface)
FM4 Ethernet MAC event handler.
#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
void fm4EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define rxBuffer
#define ETH_RDES1_RCH
void fm4EthInitGpio(NetInterface *interface)
void fm4EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:105
uint8_t n
MAC filter table entry.
Definition: ethernet.h:246
#define ETH_TDES0_LS
#define osEnterIsr()
uint32_t fm4EthCalcCrc(const void *data, size_t length)
CRC calculation.
uint32_t tdes0
#define rxDmaDesc
uint32_t tdes2
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define ETH_TDES0_FS
#define txDmaDesc
void fm4EthDisableIrq(NetInterface *interface)
Disable interrupts.
uint32_t rdes3
#define ETH_RDES0_ES
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
#define FM4_ETH_TX_BUFFER_COUNT
Enhanced TX DMA descriptor.
NIC driver.
Definition: nic.h:257
#define ETH_TDES0_OWN
#define FM4_ETH_RX_BUFFER_COUNT
Cypress FM4 Ethernet MAC driver.
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define ETH_TDES1_TBS1
#define ETH_RDES0_FS
Ethernet interface.
Definition: nic.h:82