f2838x_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file f2838x_eth_driver.c
3  * @brief TMS320F2838xD 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.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "inc/hw_emac.h"
36 #include "inc/hw_emac_ss.h"
37 #include "inc/hw_ints.h"
38 #include "inc/hw_memmap.h"
39 #include "inc/hw_types.h"
40 #include "driverlib_cm/interrupt.h"
41 #include "driverlib_cm/sysctl.h"
42 #include "core/net.h"
44 #include "debug.h"
45 
46 //Underlying network interface
47 static NetInterface *nicDriverInterface;
48 
49 //IAR EWARM compiler?
50 #if defined(__ICCARM__)
51 
52 //Transmit buffer
53 #pragma data_alignment = 4
55 //Receive buffer
56 #pragma data_alignment = 4
58 //Transmit DMA descriptors
59 #pragma data_alignment = 4
61 //Receive DMA descriptors
62 #pragma data_alignment = 4
64 
65 //GCC compiler?
66 #else
67 
68 //Transmit buffer
70  __attribute__((aligned(4)));
71 //Receive buffer
73  __attribute__((aligned(4)));
74 //Transmit DMA descriptors
76  __attribute__((aligned(4)));
77 //Receive DMA descriptors
79  __attribute__((aligned(4)));
80 
81 #endif
82 
83 //Current transmit descriptor
84 static uint_t txIndex;
85 //Current receive descriptor
86 static uint_t rxIndex;
87 
88 
89 /**
90  * @brief TMS320F2838xD Ethernet MAC driver
91  **/
92 
94 {
96  ETH_MTU,
107  TRUE,
108  TRUE,
109  TRUE,
110  FALSE
111 };
112 
113 
114 /**
115  * @brief TMS320F2838xD Ethernet MAC initialization
116  * @param[in] interface Underlying network interface
117  * @return Error code
118  **/
119 
121 {
122  error_t error;
123  uint32_t temp;
124 #ifdef ti_sysbios_BIOS___VERS
125  Hwi_Params hwiParams;
126 #endif
127 
128  //Debug message
129  TRACE_INFO("Initializing TMS320F2838xD Ethernet MAC...\r\n");
130 
131  //Save underlying network interface
132  nicDriverInterface = interface;
133 
134  //Enable Ethernet peripheral clock
135  SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ENET);
136  //Reset Ethernet peripheral
137  SysCtl_resetPeripheral(SYSCTL_PERIPH_RES_ENET);
138 
139  //GPIO configuration
140  f2838xEthInitGpio(interface);
141 
142  //Perform a software reset
143  ETHERNET_DMA_MODE_R |= ETHERNET_DMA_MODE_SWR;
144  //Wait for the reset to complete
145  while((ETHERNET_DMA_MODE_R & ETHERNET_DMA_MODE_SWR) != 0)
146  {
147  }
148 
149  //Adjust MDC clock range depending on CSR frequency
150  ETHERNET_MAC_MDIO_ADDRESS_R = (4 << ETHERNET_MAC_MDIO_ADDRESS_CR_S);
151 
152  //Valid Ethernet PHY or switch driver?
153  if(interface->phyDriver != NULL)
154  {
155  //Ethernet PHY initialization
156  error = interface->phyDriver->init(interface);
157  }
158  else if(interface->switchDriver != NULL)
159  {
160  //Ethernet switch initialization
161  error = interface->switchDriver->init(interface);
162  }
163  else
164  {
165  //The interface is not properly configured
166  error = ERROR_FAILURE;
167  }
168 
169  //Any error to report?
170  if(error)
171  {
172  return error;
173  }
174 
175  //Startup delay
176  sleep(10);
177 
178  //Use default MAC configuration
179  ETHERNET_MAC_CONFIGURATION_R = ETHERNET_MAC_CONFIGURATION_GPSLCE |
180  ETHERNET_MAC_CONFIGURATION_PS | ETHERNET_MAC_CONFIGURATION_DO;
181 
182  //Set the maximum packet size that can be accepted
183  temp = ETHERNET_MAC_EXT_CONFIGURATION_R & ~ETHERNET_MAC_EXT_CONFIGURATION_GPSL_M;
185 
186  //Configure MAC address filtering
187  f2838xEthUpdateMacAddrFilter(interface);
188 
189  //Disable flow control
192 
193  //Enable the first RX queue
194  ETHERNET_MAC_RXQ_CTRL0_R = (2 << ETHERNET_MAC_RXQ_CTRL0_RXQ0EN_S);
195 
196  //Configure DMA operating mode
197  ETHERNET_DMA_MODE_R = (0 << ETHERNET_DMA_MODE_INTM_S) |
198  (0 << ETHERNET_DMA_MODE_PR_S);
199 
200  //Configure system bus mode
201  ETHERNET_DMA_SYSBUS_MODE_R |= ETHERNET_DMA_SYSBUS_MODE_AAL;
202 
203  //The DMA takes the descriptor table as contiguous
204  ETHERNET_DMA_CH0_CONTROL_R = (0 << ETHERNET_DMA_CH0_CONTROL_DSL_S);
205  //Configure TX features
206  ETHERNET_DMA_CH0_TX_CONTROL_R = (32 << ETHERNET_DMA_CH0_TX_CONTROL_TXPBL_S);
207 
208  //Configure RX features
209  ETHERNET_DMA_CH0_RX_CONTROL_R = (32 << ETHERNET_DMA_CH0_RX_CONTROL_RXPBL_S) |
210  ((F2838X_ETH_RX_BUFFER_SIZE / 4) << ETHERNET_DMA_CH0_RX_CONTROL_RBSZ_S);
211 
212  //Enable store and forward mode for transmission
213  ETHERNET_MTL_TXQ0_OPERATION_MODE_R |= (7 << ETHERNET_MTL_TXQ0_OPERATION_MODE_TQS_S) |
214  (2 << ETHERNET_MTL_TXQ0_OPERATION_MODE_TXQEN_S) |
215  ETHERNET_MTL_TXQ0_OPERATION_MODE_TSF;
216 
217  //Enable store and forward mode for reception
218  ETHERNET_MTL_RXQ0_OPERATION_MODE_R |= (7 << ETHERNET_MTL_RXQ0_OPERATION_MODE_RQS_S) |
219  ETHERNET_MTL_RXQ0_OPERATION_MODE_RSF;
220 
221  //Initialize DMA descriptor lists
222  f2838xEthInitDmaDesc(interface);
223 
224  //Prevent interrupts from being generated when statistic counters reach
225  //half their maximum value
229 
230  //Disable MAC interrupts
232 
233  //Enable the desired DMA interrupts
234  ETHERNET_DMA_CH0_INTERRUPT_ENABLE_R = ETHERNET_DMA_CH0_INTERRUPT_ENABLE_NIE |
235  ETHERNET_DMA_CH0_INTERRUPT_ENABLE_RIE | ETHERNET_DMA_CH0_INTERRUPT_ENABLE_TIE;
236 
237 #ifdef ti_sysbios_BIOS___VERS
238  //Configure Ethernet interrupt
239  Hwi_Params_init(&hwiParams);
240  hwiParams.enableInt = FALSE;
241  hwiParams.priority = F2838X_ETH_IRQ_PRIORITY;
242 
243  //Register interrupt handler
244  Hwi_create(INT_EMAC, (Hwi_FuncPtr) f2838xEthIrqHandler, &hwiParams, NULL);
245 #else
246  //Register interrupt handler
247  Interrupt_registerHandler(INT_EMAC, f2838xEthIrqHandler);
248  //Configure Ethernet interrupt priority
249  Interrupt_setPriority(INT_EMAC, F2838X_ETH_IRQ_PRIORITY);
250 #endif
251 
252  //Enable MAC transmission and reception
253  ETHERNET_MAC_CONFIGURATION_R |= ETHERNET_MAC_CONFIGURATION_TE |
254  ETHERNET_MAC_CONFIGURATION_RE;
255 
256  //Enable DMA transmission and reception
257  ETHERNET_DMA_CH0_TX_CONTROL_R |= ETHERNET_DMA_CH0_TX_CONTROL_ST;
258  ETHERNET_DMA_CH0_RX_CONTROL_R |= ETHERNET_DMA_CH0_RX_CONTROL_SR;
259 
260  //Accept any packets from the upper layer
261  osSetEvent(&interface->nicTxEvent);
262 
263  //Successful initialization
264  return NO_ERROR;
265 }
266 
267 
268 /**
269  * @brief GPIO configuration
270  * @param[in] interface Underlying network interface
271  **/
272 
273 __weak_func void f2838xEthInitGpio(NetInterface *interface)
274 {
275  //Select MII interface mode
276  ETHERNETSS_CTRLSTS_R = (0xA5U << ETHERNETSS_CTRLSTS_WRITE_KEY_S) |
277  (0 << ETHERNETSS_CTRLSTS_PHY_INTF_SEL_S);
278 }
279 
280 
281 /**
282  * @brief Initialize DMA descriptor lists
283  * @param[in] interface Underlying network interface
284  **/
285 
287 {
288  uint_t i;
289 
290  //Initialize TX DMA descriptor list
291  for(i = 0; i < F2838X_ETH_TX_BUFFER_COUNT; i++)
292  {
293  //The descriptor is initially owned by the application
294  txDmaDesc[i].tdes0 = 0;
295  txDmaDesc[i].tdes1 = 0;
296  txDmaDesc[i].tdes2 = 0;
297  txDmaDesc[i].tdes3 = 0;
298  }
299 
300  //Initialize TX descriptor index
301  txIndex = 0;
302 
303  //Initialize RX DMA descriptor list
304  for(i = 0; i < F2838X_ETH_RX_BUFFER_COUNT; i++)
305  {
306  //The descriptor is initially owned by the DMA
307  rxDmaDesc[i].rdes0 = (uint32_t) rxBuffer[i];
308  rxDmaDesc[i].rdes1 = 0;
309  rxDmaDesc[i].rdes2 = 0;
311  }
312 
313  //Initialize RX descriptor index
314  rxIndex = 0;
315 
316  //Start location of the TX descriptor list
318  //Length of the transmit descriptor ring
320 
321  //Start location of the RX descriptor list
323  //Length of the receive descriptor ring
325 }
326 
327 
328 /**
329  * @brief TMS320F2838xD Ethernet MAC timer handler
330  *
331  * This routine is periodically called by the TCP/IP stack to handle periodic
332  * operations such as polling the link state
333  *
334  * @param[in] interface Underlying network interface
335  **/
336 
337 void f2838xEthTick(NetInterface *interface)
338 {
339  //Valid Ethernet PHY or switch driver?
340  if(interface->phyDriver != NULL)
341  {
342  //Handle periodic operations
343  interface->phyDriver->tick(interface);
344  }
345  else if(interface->switchDriver != NULL)
346  {
347  //Handle periodic operations
348  interface->switchDriver->tick(interface);
349  }
350  else
351  {
352  //Just for sanity
353  }
354 }
355 
356 
357 /**
358  * @brief Enable interrupts
359  * @param[in] interface Underlying network interface
360  **/
361 
363 {
364 #ifdef ti_sysbios_BIOS___VERS
365  //Enable Ethernet MAC interrupts
366  Hwi_enableInterrupt(INT_EMAC);
367 #else
368  //Enable Ethernet MAC interrupts
369  Interrupt_enable(INT_EMAC);
370 #endif
371 
372  //Valid Ethernet PHY or switch driver?
373  if(interface->phyDriver != NULL)
374  {
375  //Enable Ethernet PHY interrupts
376  interface->phyDriver->enableIrq(interface);
377  }
378  else if(interface->switchDriver != NULL)
379  {
380  //Enable Ethernet switch interrupts
381  interface->switchDriver->enableIrq(interface);
382  }
383  else
384  {
385  //Just for sanity
386  }
387 }
388 
389 
390 /**
391  * @brief Disable interrupts
392  * @param[in] interface Underlying network interface
393  **/
394 
396 {
397 #ifdef ti_sysbios_BIOS___VERS
398  //Disable Ethernet MAC interrupts
399  Hwi_disableInterrupt(INT_EMAC);
400 #else
401  //Disable Ethernet MAC interrupts
402  Interrupt_disable(INT_EMAC);
403 #endif
404 
405  //Valid Ethernet PHY or switch driver?
406  if(interface->phyDriver != NULL)
407  {
408  //Disable Ethernet PHY interrupts
409  interface->phyDriver->disableIrq(interface);
410  }
411  else if(interface->switchDriver != NULL)
412  {
413  //Disable Ethernet switch interrupts
414  interface->switchDriver->disableIrq(interface);
415  }
416  else
417  {
418  //Just for sanity
419  }
420 }
421 
422 
423 /**
424  * @brief TMS320F2838xD Ethernet MAC interrupt service routine
425  **/
426 
427 __interrupt void f2838xEthIrqHandler(void)
428 {
429  bool_t flag;
430  uint32_t status;
431 
432  //Interrupt service routine prologue
433  osEnterIsr();
434 
435  //This flag will be set if a higher priority task must be woken
436  flag = FALSE;
437 
438  //Read DMA status register
439  status = ETHERNET_DMA_CH0_STATUS_R;
440 
441  //Packet transmitted?
442  if((status & ETHERNET_DMA_CH0_STATUS_TI) != 0)
443  {
444  //Clear TI interrupt flag
445  ETHERNET_DMA_CH0_STATUS_R = ETHERNET_DMA_CH0_STATUS_TI;
446 
447  //Check whether the TX buffer is available for writing
448  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
449  {
450  //Notify the TCP/IP stack that the transmitter is ready to send
451  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
452  }
453  }
454 
455  //Packet received?
456  if((status & ETHERNET_DMA_CH0_STATUS_RI) != 0)
457  {
458  //Clear RI interrupt flag
459  ETHERNET_DMA_CH0_STATUS_R = ETHERNET_DMA_CH0_STATUS_RI;
460 
461  //Set event flag
462  nicDriverInterface->nicEvent = TRUE;
463  //Notify the TCP/IP stack of the event
464  flag |= osSetEventFromIsr(&netEvent);
465  }
466 
467  //Clear NIS interrupt flag
468  ETHERNET_DMA_CH0_STATUS_R = ETHERNET_DMA_CH0_STATUS_NIS;
469 
470  //Interrupt service routine epilogue
471  osExitIsr(flag);
472 }
473 
474 
475 /**
476  * @brief TMS320F2838xD Ethernet MAC event handler
477  * @param[in] interface Underlying network interface
478  **/
479 
481 {
482  error_t error;
483 
484  //Process all pending packets
485  do
486  {
487  //Read incoming packet
488  error = f2838xEthReceivePacket(interface);
489 
490  //No more data in the receive buffer?
491  } while(error != ERROR_BUFFER_EMPTY);
492 }
493 
494 
495 /**
496  * @brief Send a packet
497  * @param[in] interface Underlying network interface
498  * @param[in] buffer Multi-part buffer containing the data to send
499  * @param[in] offset Offset to the first data byte
500  * @param[in] ancillary Additional options passed to the stack along with
501  * the packet
502  * @return Error code
503  **/
504 
506  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
507 {
508  size_t length;
509 
510  //Retrieve the length of the packet
511  length = netBufferGetLength(buffer) - offset;
512 
513  //Check the frame length
515  {
516  //The transmitter can accept another packet
517  osSetEvent(&interface->nicTxEvent);
518  //Report an error
519  return ERROR_INVALID_LENGTH;
520  }
521 
522  //Make sure the current buffer is available for writing
523  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) != 0)
524  {
525  return ERROR_FAILURE;
526  }
527 
528  //Copy user data to the transmit buffer
529  netBufferRead(txBuffer[txIndex], buffer, offset, length);
530 
531  //Set the start address of the buffer
532  txDmaDesc[txIndex].tdes0 = (uint32_t) txBuffer[txIndex];
533  //Write the number of bytes to send
534  txDmaDesc[txIndex].tdes2 = ETH_TDES2_IOC | (length & ETH_TDES2_B1L);
535  //Give the ownership of the descriptor to the DMA
536  txDmaDesc[txIndex].tdes3 = ETH_TDES3_OWN | ETH_TDES3_FD | ETH_TDES3_LD;
537 
538  //Clear TBU flag to resume processing
539  ETHERNET_DMA_CH0_STATUS_R = ETHERNET_DMA_CH0_STATUS_TBU;
540  //Instruct the DMA to poll the transmit descriptor list
542 
543  //Increment index and wrap around if necessary
544  if(++txIndex >= F2838X_ETH_TX_BUFFER_COUNT)
545  {
546  txIndex = 0;
547  }
548 
549  //Check whether the next buffer is available for writing
550  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
551  {
552  //The transmitter can accept another packet
553  osSetEvent(&interface->nicTxEvent);
554  }
555 
556  //Data successfully written
557  return NO_ERROR;
558 }
559 
560 
561 /**
562  * @brief Receive a packet
563  * @param[in] interface Underlying network interface
564  * @return Error code
565  **/
566 
568 {
569  error_t error;
570  size_t n;
571  NetRxAncillary ancillary;
572 
573  //Current buffer available for reading?
574  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_OWN) == 0)
575  {
576  //FD and LD flags should be set
577  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_FD) != 0 &&
578  (rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_LD) != 0)
579  {
580  //Make sure no error occurred
581  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_ES) == 0)
582  {
583  //Retrieve the length of the frame
584  n = rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_PL;
585  //Limit the number of data to read
587 
588  //Additional options can be passed to the stack along with the packet
589  ancillary = NET_DEFAULT_RX_ANCILLARY;
590 
591  //Pass the packet to the upper layer
592  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
593 
594  //Valid packet received
595  error = NO_ERROR;
596  }
597  else
598  {
599  //The received packet contains an error
600  error = ERROR_INVALID_PACKET;
601  }
602  }
603  else
604  {
605  //The packet is not valid
606  error = ERROR_INVALID_PACKET;
607  }
608 
609  //Set the start address of the buffer
610  rxDmaDesc[rxIndex].rdes0 = (uint32_t) rxBuffer[rxIndex];
611  //Give the ownership of the descriptor back to the DMA
613 
614  //Increment index and wrap around if necessary
615  if(++rxIndex >= F2838X_ETH_RX_BUFFER_COUNT)
616  {
617  rxIndex = 0;
618  }
619  }
620  else
621  {
622  //No more data in the receive buffer
623  error = ERROR_BUFFER_EMPTY;
624  }
625 
626  //Clear RBU flag to resume processing
627  ETHERNET_DMA_CH0_STATUS_R = ETHERNET_DMA_CH0_STATUS_RBU;
628  //Instruct the DMA to poll the receive descriptor list
630 
631  //Return status code
632  return error;
633 }
634 
635 
636 /**
637  * @brief Configure MAC address filtering
638  * @param[in] interface Underlying network interface
639  * @return Error code
640  **/
641 
643 {
644  uint_t i;
645  uint_t j;
646  uint_t k;
647  uint32_t crc;
648  uint32_t hashTable[2];
649  MacAddr unicastMacAddr[3];
650  MacFilterEntry *entry;
651 
652  //Debug message
653  TRACE_DEBUG("Updating MAC filter...\r\n");
654 
655  //Promiscuous mode?
656  if(interface->promiscuous)
657  {
658  //Pass all incoming frames regardless of their destination address
659  ETHERNET_MAC_PACKET_FILTER_R = ETHERNET_MAC_PACKET_FILTER_PR;
660  }
661  else
662  {
663  //Set the MAC address of the station
664  ETHERNET_MAC_ADDRESS0_LOW_R = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
665  ETHERNET_MAC_ADDRESS0_HIGH_R = interface->macAddr.w[2];
666 
667  //The MAC supports 7 additional addresses for unicast perfect filtering
668  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
669  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
670  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
671 
672  //The hash table is used for multicast address filtering
673  hashTable[0] = 0;
674  hashTable[1] = 0;
675 
676  //The MAC address filter contains the list of MAC addresses to accept
677  //when receiving an Ethernet frame
678  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
679  {
680  //Point to the current entry
681  entry = &interface->macAddrFilter[i];
682 
683  //Valid entry?
684  if(entry->refCount > 0)
685  {
686  //Multicast address?
687  if(macIsMulticastAddr(&entry->addr))
688  {
689  //Compute CRC over the current MAC address
690  crc = f2838xEthCalcCrc(&entry->addr, sizeof(MacAddr));
691 
692  //The upper 6 bits in the CRC register are used to index the
693  //contents of the hash table
694  k = (crc >> 26) & 0x3F;
695 
696  //Update hash table contents
697  hashTable[k / 32] |= (1 << (k % 32));
698  }
699  else
700  {
701  //Up to 3 additional MAC addresses can be specified
702  if(j < 3)
703  {
704  //Save the unicast address
705  unicastMacAddr[j++] = entry->addr;
706  }
707  }
708  }
709  }
710 
711  //Configure the first unicast address filter
712  if(j >= 1)
713  {
714  //When the AE bit is set, the entry is used for perfect filtering
715  ETHERNET_MAC_ADDRESS1_LOW_R = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
716  ETHERNET_MAC_ADDRESS1_HIGH_R = unicastMacAddr[0].w[2] | ETHERNET_MAC_ADDRESS1_HIGH_AE;
717  }
718  else
719  {
720  //When the AE bit is cleared, the entry is ignored
723  }
724 
725  //Configure the second unicast address filter
726  if(j >= 2)
727  {
728  //When the AE bit is set, the entry is used for perfect filtering
729  ETHERNET_MAC_ADDRESS2_LOW_R = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
730  ETHERNET_MAC_ADDRESS2_HIGH_R = unicastMacAddr[1].w[2] | ETHERNET_MAC_ADDRESS2_HIGH_AE;
731  }
732  else
733  {
734  //When the AE bit is cleared, the entry is ignored
737  }
738 
739  //Configure the third unicast address filter
740  if(j >= 3)
741  {
742  //When the AE bit is set, the entry is used for perfect filtering
743  ETHERNET_MAC_ADDRESS3_LOW_R = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
744  ETHERNET_MAC_ADDRESS3_HIGH_R = unicastMacAddr[2].w[2] | ETHERNET_MAC_ADDRESS3_HIGH_AE;
745  }
746  else
747  {
748  //When the AE bit is cleared, the entry is ignored
751  }
752 
753  //Check whether frames with a multicast destination address should be
754  //accepted
755  if(interface->acceptAllMulticast)
756  {
757  //Configure the receive filter
758  ETHERNET_MAC_PACKET_FILTER_R = ETHERNET_MAC_PACKET_FILTER_HPF |
759  ETHERNET_MAC_PACKET_FILTER_PM;
760  }
761  else
762  {
763  //Configure the receive filter
764  ETHERNET_MAC_PACKET_FILTER_R = ETHERNET_MAC_PACKET_FILTER_HPF |
765  ETHERNET_MAC_PACKET_FILTER_HMC;
766 
767  //Configure the multicast hash table
768  ETHERNET_MAC_HASH_TABLE_REG0_R = hashTable[0];
769  ETHERNET_MAC_HASH_TABLE_REG1_R = hashTable[1];
770 
771  //Debug message
772  TRACE_DEBUG(" MAC_HASH_TABLE_REG0 = %08" PRIX32 "\r\n", ETHERNET_MAC_HASH_TABLE_REG0_R);
773  TRACE_DEBUG(" MAC_HASH_TABLE_REG1 = %08" PRIX32 "\r\n", ETHERNET_MAC_HASH_TABLE_REG1_R);
774  }
775  }
776 
777  //Successful processing
778  return NO_ERROR;
779 }
780 
781 
782 /**
783  * @brief Adjust MAC configuration parameters for proper operation
784  * @param[in] interface Underlying network interface
785  * @return Error code
786  **/
787 
789 {
790  uint32_t config;
791 
792  //Read current MAC configuration
794 
795  //10BASE-T or 100BASE-TX operation mode?
796  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
797  {
798  config |= ETHERNET_MAC_CONFIGURATION_FES;
799  }
800  else
801  {
802  config &= ~ETHERNET_MAC_CONFIGURATION_FES;
803  }
804 
805  //Half-duplex or full-duplex mode?
806  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
807  {
808  config |= ETHERNET_MAC_CONFIGURATION_DM;
809  }
810  else
811  {
812  config &= ~ETHERNET_MAC_CONFIGURATION_DM;
813  }
814 
815  //Update MAC configuration register
817 
818  //Successful processing
819  return NO_ERROR;
820 }
821 
822 
823 /**
824  * @brief Write 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  * @param[in] data Register value
829  **/
830 
831 void f2838xEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
832  uint8_t regAddr, uint16_t data)
833 {
834  uint32_t temp;
835 
836  //Valid opcode?
837  if(opcode == SMI_OPCODE_WRITE)
838  {
839  //Take care not to alter MDC clock configuration
840  temp = ETHERNET_MAC_MDIO_ADDRESS_R & ETHERNET_MAC_MDIO_ADDRESS_CR_M;
841  //Set up a write operation
842  temp |= ETHERNET_MAC_MDIO_ADDRESS_GOC_0 | ETHERNET_MAC_MDIO_ADDRESS_GB;
843 
844  //PHY address
845  temp |= (phyAddr <<ETHERNET_MAC_MDIO_ADDRESS_PA_S) &
846  ETHERNET_MAC_MDIO_ADDRESS_PA_M;
847 
848  //Register address
849  temp |= (regAddr << ETHERNET_MAC_MDIO_ADDRESS_RDA_S) &
850  ETHERNET_MAC_MDIO_ADDRESS_RDA_M;
851 
852  //Data to be written in the PHY register
853  ETHERNET_MAC_MDIO_DATA_R = data & ETHERNET_MAC_MDIO_DATA_GD_M;
854 
855  //Start a write operation
857  //Wait for the write to complete
858  while((ETHERNET_MAC_MDIO_ADDRESS_R & ETHERNET_MAC_MDIO_ADDRESS_GB) != 0)
859  {
860  }
861  }
862  else
863  {
864  //The MAC peripheral only supports standard Clause 22 opcodes
865  }
866 }
867 
868 
869 /**
870  * @brief Read PHY register
871  * @param[in] opcode Access type (2 bits)
872  * @param[in] phyAddr PHY address (5 bits)
873  * @param[in] regAddr Register address (5 bits)
874  * @return Register value
875  **/
876 
877 uint16_t f2838xEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
878  uint8_t regAddr)
879 {
880  uint16_t data;
881  uint32_t temp;
882 
883  //Valid opcode?
884  if(opcode == SMI_OPCODE_READ)
885  {
886  //Take care not to alter MDC clock configuration
887  temp = ETHERNET_MAC_MDIO_ADDRESS_R & ETHERNET_MAC_MDIO_ADDRESS_CR_M;
888 
889  //Set up a read operation
890  temp |= ETHERNET_MAC_MDIO_ADDRESS_GOC_1 |
891  ETHERNET_MAC_MDIO_ADDRESS_GOC_0 | ETHERNET_MAC_MDIO_ADDRESS_GB;
892 
893  //PHY address
894  temp |= (phyAddr <<ETHERNET_MAC_MDIO_ADDRESS_PA_S) &
895  ETHERNET_MAC_MDIO_ADDRESS_PA_M;
896 
897  //Register address
898  temp |= (regAddr << ETHERNET_MAC_MDIO_ADDRESS_RDA_S) &
899  ETHERNET_MAC_MDIO_ADDRESS_RDA_M;
900 
901  //Start a read operation
903  //Wait for the read to complete
904  while((ETHERNET_MAC_MDIO_ADDRESS_R & ETHERNET_MAC_MDIO_ADDRESS_GB) != 0)
905  {
906  }
907 
908  //Get register value
909  data = ETHERNET_MAC_MDIO_DATA_R & ETHERNET_MAC_MDIO_DATA_GD_M;
910  }
911  else
912  {
913  //The MAC peripheral only supports standard Clause 22 opcodes
914  data = 0;
915  }
916 
917  //Return the value of the PHY register
918  return data;
919 }
920 
921 
922 /**
923  * @brief CRC calculation
924  * @param[in] data Pointer to the data over which to calculate the CRC
925  * @param[in] length Number of bytes to process
926  * @return Resulting CRC value
927  **/
928 
929 uint32_t f2838xEthCalcCrc(const void *data, size_t length)
930 {
931  uint_t i;
932  uint_t j;
933  uint32_t crc;
934  const uint8_t *p;
935 
936  //Point to the data over which to calculate the CRC
937  p = (uint8_t *) data;
938  //CRC preset value
939  crc = 0xFFFFFFFF;
940 
941  //Loop through data
942  for(i = 0; i < length; i++)
943  {
944  //The message is processed bit by bit
945  for(j = 0; j < 8; j++)
946  {
947  //Update CRC value
948  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
949  {
950  crc = (crc << 1) ^ 0x04C11DB7;
951  }
952  else
953  {
954  crc = crc << 1;
955  }
956  }
957  }
958 
959  //Return CRC value
960  return ~crc;
961 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void f2838xEthEnableIrq(NetInterface *interface)
Enable interrupts.
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:53
#define ETHERNET_MAC_ADDRESS3_LOW_R
#define netEvent
Definition: net_legacy.h:196
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
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:690
#define ETHERNET_DMA_CH0_TXDESC_TAIL_POINTER_R
#define ETH_RDES3_LD
#define F2838X_ETH_RX_BUFFER_SIZE
#define ETHERNET_MAC_PACKET_FILTER_R
uint8_t p
Definition: ndp.h:300
#define ETH_RDES3_ES
#define ETHERNET_DMA_CH0_TX_CONTROL_R
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
#define sleep(delay)
Definition: os_port.h:307
#define ETHERNET_MMC_TX_INTERRUPT_MASK_R
#define ETH_TDES3_LD
void f2838xEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
void f2838xEthTick(NetInterface *interface)
TMS320F2838xD Ethernet MAC timer handler.
error_t f2838xEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define ETHERNET_MAC_HASH_TABLE_REG0_R
#define F2838X_ETH_RX_BUFFER_COUNT
void f2838xEthEventHandler(NetInterface *interface)
TMS320F2838xD Ethernet MAC event handler.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:392
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
#define F2838X_ETH_TX_BUFFER_SIZE
#define ETHERNET_MAC_RX_FLOW_CTRL_R
#define ETHERNET_MAC_MDIO_ADDRESS_R
#define SMI_OPCODE_WRITE
Definition: nic.h:66
void f2838xEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define F2838X_ETH_TX_BUFFER_COUNT
#define ETHERNET_MMC_RX_INTERRUPT_MASK_R
#define ETHERNET_DMA_MODE_R
#define FALSE
Definition: os_port.h:46
error_t
Error codes.
Definition: error.h:43
#define ETH_TDES2_B1L
#define ETHERNET_DMA_CH0_TXDESC_RING_LENGTH_R
Receive descriptor.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
const NicDriver f2838xEthDriver
TMS320F2838xD Ethernet MAC driver.
#define ETHERNET_MTL_TXQ0_OPERATION_MODE_R
#define ETHERNET_DMA_CH0_TXDESC_LIST_ADDRESS_R
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:140
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:263
__interrupt void f2838xEthIrqHandler(void)
TMS320F2838xD Ethernet MAC interrupt service routine.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define ETHERNET_MAC_ADDRESS2_HIGH_R
#define ETHERNET_DMA_SYSBUS_MODE_R
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
#define NetTxAncillary
Definition: net_misc.h:36
#define ETHERNET_MMC_IPC_RX_INTERRUPT_MASK_R
uint32_t f2838xEthCalcCrc(const void *data, size_t length)
CRC calculation.
#define ETH_RDES3_BUF1V
#define SMI_OPCODE_READ
Definition: nic.h:67
#define ETH_TDES2_IOC
#define ETHERNET_MAC_INTERRUPT_ENABLE_R
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define ETHERNET_DMA_CH0_STATUS_R
error_t f2838xEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define MIN(a, b)
Definition: os_port.h:63
#define ETH_RDES3_OWN
#define ETHERNET_DMA_CH0_INTERRUPT_ENABLE_R
#define ETH_TDES3_OWN
#define rxBuffer
#define ETHERNET_MAC_ADDRESS0_HIGH_R
uint16_t f2838xEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
MacAddr
Definition: ethernet.h:195
#define ETHERNET_MAC_EXT_CONFIGURATION_R
Transmit descriptor.
#define ETHERNET_MAC_Q0_TX_FLOW_CTRL_R
#define ETHERNET_MAC_MDIO_DATA_R
#define ETHERNET_DMA_CH0_RXDESC_TAIL_POINTER_R
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define F2838X_ETH_IRQ_PRIORITY
error_t f2838xEthReceivePacket(NetInterface *interface)
Receive a packet.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
error_t f2838xEthInit(NetInterface *interface)
TMS320F2838xD Ethernet MAC initialization.
uint8_t n
#define ETHERNET_MAC_ADDRESS2_LOW_R
MAC filter table entry.
Definition: ethernet.h:262
#define ETHERNET_MAC_ADDRESS0_LOW_R
#define ETH_RDES3_FD
#define ETHERNET_DMA_CH0_RXDESC_RING_LENGTH_R
#define osEnterIsr()
#define ETHERNETSS_CTRLSTS_R
#define ETHERNET_MAC_RXQ_CTRL0_R
#define ETHERNET_MAC_CONFIGURATION_R
#define ETHERNET_MAC_ADDRESS3_HIGH_R
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define ETH_TDES3_FD
#define txDmaDesc
#define ETHERNET_DMA_CH0_RXDESC_LIST_ADDRESS_R
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define ETHERNET_DMA_CH0_CONTROL_R
__weak_func void f2838xEthInitGpio(NetInterface *interface)
GPIO configuration.
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
#define ETHERNET_MTL_RXQ0_OPERATION_MODE_R
#define ETHERNET_MAC_ADDRESS1_LOW_R
NIC driver.
Definition: nic.h:286
#define ETH_RDES3_IOC
TMS320F2838xD Ethernet MAC driver.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
@ NO_ERROR
Success.
Definition: error.h:44
#define ETHERNET_DMA_CH0_RX_CONTROL_R
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define ETHERNET_MAC_HASH_TABLE_REG1_R
#define ETH_RDES3_PL
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
error_t f2838xEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void f2838xEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define ETHERNET_MAC_ADDRESS1_HIGH_R