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