msp432e4_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file msp432e4_eth_driver.c
3  * @brief MSP432E4 Ethernet 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 <stdint.h>
36 #include "msp432.h"
37 #include "inc/hw_emac.h"
38 #include "driverlib/gpio.h"
39 #include "driverlib/interrupt.h"
40 #include "driverlib/pin_map.h"
41 #include "driverlib/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 //Keil MDK-ARM or 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 //Pointer to the current TX DMA descriptor
84 static Tm4c129TxDmaDesc *txCurDmaDesc;
85 //Pointer to the current RX DMA descriptor
86 static Tm4c129RxDmaDesc *rxCurDmaDesc;
87 
88 
89 /**
90  * @brief MSP432E4 Ethernet MAC driver
91  **/
92 
94 {
96  ETH_MTU,
104  NULL,
105  NULL,
106  NULL,
107  TRUE,
108  TRUE,
109  TRUE,
110  FALSE
111 };
112 
113 
114 /**
115  * @brief MSP432E4 Ethernet MAC initialization
116  * @param[in] interface Underlying network interface
117  * @return Error code
118  **/
119 
121 {
122  //Debug message
123  TRACE_INFO("Initializing MSP432E4 Ethernet controller...\r\n");
124 
125  //Save underlying network interface
126  nicDriverInterface = interface;
127 
128  //Enable Ethernet controller clock
129  SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
130 
131  //Reset Ethernet controller
132  SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
133  //Wait for the reset to complete
134  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
135  {
136  }
137 
138  //Enable internal PHY clock
139  SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
140 
141  //Reset internal PHY
142  SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
143  //Wait for the reset to complete
144  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0))
145  {
146  }
147 
148  //GPIO configuration
149  msp432e4EthInitGpio(interface);
150 
151  //Perform a software reset
152  EMAC0->DMABUSMOD |= EMAC_DMABUSMOD_SWR;
153  //Wait for the reset to complete
154  while(EMAC0->DMABUSMOD & EMAC_DMABUSMOD_SWR)
155  {
156  }
157 
158  //Adjust MDC clock range depending on SYSCLK frequency
159  EMAC0->MIIADDR = EMAC_MIIADDR_CR_100_150;
160 
161  //Reset PHY transceiver
162  msp432e4EthWritePhyReg(EPHY_BMCR, EPHY_BMCR_MIIRESET);
163  //Wait for the reset to complete
164  while(msp432e4EthReadPhyReg(EPHY_BMCR) & EPHY_BMCR_MIIRESET)
165  {
166  }
167 
168  //Dump PHY registers for debugging purpose
170 
171  //Configure LED0, LED1 and LED2
172  msp432e4EthWritePhyReg(EPHY_LEDCFG, EPHY_LEDCFG_LED0_TX |
173  EPHY_LEDCFG_LED1_RX | EPHY_LEDCFG_LED2_LINK);
174 
175  //Configure PHY interrupts as desired
176  msp432e4EthWritePhyReg(EPHY_MISR1, EPHY_MISR1_LINKSTATEN);
177  //Enable PHY interrupts
178  msp432e4EthWritePhyReg(EPHY_SCR, EPHY_SCR_INTEN);
179 
180  //Use default MAC configuration
181  EMAC0->CFG = EMAC_CFG_DRO;
182 
183  //Set the MAC address of the station
184  EMAC0->ADDR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
185  EMAC0->ADDR0H = interface->macAddr.w[2];
186 
187  //The MAC supports 3 additional addresses for unicast perfect filtering
188  EMAC0->ADDR1L = 0;
189  EMAC0->ADDR1H = 0;
190  EMAC0->ADDR2L = 0;
191  EMAC0->ADDR2H = 0;
192  EMAC0->ADDR3L = 0;
193  EMAC0->ADDR3H = 0;
194 
195  //Initialize hash table
196  EMAC0->HASHTBLL = 0;
197  EMAC0->HASHTBLH = 0;
198 
199  //Configure the receive filter
200  EMAC0->FRAMEFLTR = EMAC_FRAMEFLTR_HPF | EMAC_FRAMEFLTR_HMC;
201  //Disable flow control
202  EMAC0->FLOWCTL = 0;
203  //Enable store and forward mode
204  EMAC0->DMAOPMODE = EMAC_DMAOPMODE_RSF | EMAC_DMAOPMODE_TSF;
205 
206  //Configure DMA bus mode
207  EMAC0->DMABUSMOD = EMAC_DMABUSMOD_AAL | EMAC_DMABUSMOD_USP | EMAC_DMABUSMOD_RPBL_1 |
208  EMAC_DMABUSMOD_PR_1_1 | EMAC_DMABUSMOD_PBL_1 | EMAC_DMABUSMOD_ATDS;
209 
210  //Initialize DMA descriptor lists
211  msp432e4EthInitDmaDesc(interface);
212 
213  //Prevent interrupts from being generated when the transmit statistic
214  //counters reach half their maximum value
215  EMAC0->MMCTXIM = EMAC_MMCTXIM_OCTCNT | EMAC_MMCTXIM_MCOLLGF |
216  EMAC_MMCTXIM_SCOLLGF | EMAC_MMCTXIM_GBF;
217 
218  //Prevent interrupts from being generated when the receive statistic
219  //counters reach half their maximum value
220  EMAC0->MMCRXIM = EMAC_MMCRXIM_UCGF | EMAC_MMCRXIM_ALGNERR |
221  EMAC_MMCRXIM_CRCERR | EMAC_MMCRXIM_GBF;
222 
223  //Disable MAC interrupts
224  EMAC0->IM = EMAC_IM_TSI | EMAC_IM_PMT;
225  //Enable the desired DMA interrupts
226  EMAC0->DMAIM = EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
227  //Enable PHY interrupts
228  EMAC0->EPHYIM = EMAC_EPHYIM_INT;
229 
230  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
231  IntPriorityGroupingSet(MSP432E4_ETH_IRQ_PRIORITY_GROUPING);
232  //Configure Ethernet interrupt priority
233  IntPrioritySet(INT_EMAC0, MSP432E4_ETH_IRQ_PRIORITY);
234 
235  //Enable MAC transmission and reception
236  EMAC0->CFG |= EMAC_CFG_TE | EMAC_CFG_RE;
237  //Enable DMA transmission and reception
238  EMAC0->DMAOPMODE |= EMAC_DMAOPMODE_ST | EMAC_DMAOPMODE_SR;
239 
240  //Accept any packets from the upper layer
241  osSetEvent(&interface->nicTxEvent);
242 
243  //Successful initialization
244  return NO_ERROR;
245 }
246 
247 
248 //MSP-EXP432E401Y evaluation board?
249 #if defined(USE_MSP_EXP432E401Y)
250 
251 /**
252  * @brief GPIO configuration
253  * @param[in] interface Underlying network interface
254  **/
255 
256 void msp432e4EthInitGpio(NetInterface *interface)
257 {
258  //Enable GPIO clock
259  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
260 
261  //Select the relevant alternate function for PF0 and PF4
262  GPIOPinConfigure(GPIO_PF0_EN0LED0);
263  GPIOPinConfigure(GPIO_PF4_EN0LED1);
264 
265  //Configure Ethernet LED pins for proper operation
266  GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);
267 }
268 
269 #endif
270 
271 
272 /**
273  * @brief Initialize DMA descriptor lists
274  * @param[in] interface Underlying network interface
275  **/
276 
278 {
279  uint_t i;
280 
281  //Initialize TX DMA descriptor list
282  for(i = 0; i < MSP432E4_ETH_TX_BUFFER_COUNT; i++)
283  {
284  //Use chain structure rather than ring structure
286  //Initialize transmit buffer size
287  txDmaDesc[i].tdes1 = 0;
288  //Transmit buffer address
289  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
290  //Next descriptor address
291  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
292  //Reserved fields
293  txDmaDesc[i].tdes4 = 0;
294  txDmaDesc[i].tdes5 = 0;
295  //Transmit frame time stamp
296  txDmaDesc[i].tdes6 = 0;
297  txDmaDesc[i].tdes7 = 0;
298  }
299 
300  //The last descriptor is chained to the first entry
301  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
302  //Point to the very first descriptor
303  txCurDmaDesc = &txDmaDesc[0];
304 
305  //Initialize RX DMA descriptor list
306  for(i = 0; i < MSP432E4_ETH_RX_BUFFER_COUNT; i++)
307  {
308  //The descriptor is initially owned by the DMA
309  rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
310  //Use chain structure rather than ring structure
312  //Receive buffer address
313  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
314  //Next descriptor address
315  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
316  //Extended status
317  rxDmaDesc[i].rdes4 = 0;
318  //Reserved field
319  rxDmaDesc[i].rdes5 = 0;
320  //Receive frame time stamp
321  rxDmaDesc[i].rdes6 = 0;
322  rxDmaDesc[i].rdes7 = 0;
323  }
324 
325  //The last descriptor is chained to the first entry
326  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
327  //Point to the very first descriptor
328  rxCurDmaDesc = &rxDmaDesc[0];
329 
330  //Start location of the TX descriptor list
331  EMAC0->TXDLADDR = (uint32_t) txDmaDesc;
332  //Start location of the RX descriptor list
333  EMAC0->RXDLADDR = (uint32_t) rxDmaDesc;
334 }
335 
336 
337 /**
338  * @brief MSP432E4 Ethernet MAC timer handler
339  *
340  * This routine is periodically called by the TCP/IP stack to
341  * handle periodic operations such as polling the link state
342  *
343  * @param[in] interface Underlying network interface
344  **/
345 
347 {
348 }
349 
350 
351 /**
352  * @brief Enable interrupts
353  * @param[in] interface Underlying network interface
354  **/
355 
357 {
358  //Enable Ethernet MAC interrupts
359  IntEnable(INT_EMAC0);
360 }
361 
362 
363 /**
364  * @brief Disable interrupts
365  * @param[in] interface Underlying network interface
366  **/
367 
369 {
370  //Disable Ethernet MAC interrupts
371  IntDisable(INT_EMAC0);
372 }
373 
374 
375 /**
376  * @brief MSP432E4 Ethernet MAC interrupt service routine
377  **/
378 
380 {
381  bool_t flag;
382  uint32_t status;
383 
384  //Interrupt service routine prologue
385  osEnterIsr();
386 
387  //This flag will be set if a higher priority task must be woken
388  flag = FALSE;
389 
390  //Read PHY status register
391  status = EMAC0->EPHYRIS;
392 
393  //PHY interrupt?
394  if(status & EMAC_EPHYRIS_INT)
395  {
396  //Disable PHY interrupt
397  EMAC0->EPHYIM &= ~EMAC_EPHYIM_INT;
398 
399  //Set event flag
400  nicDriverInterface->nicEvent = TRUE;
401  //Notify the TCP/IP stack of the event
402  flag |= osSetEventFromIsr(&netEvent);
403  }
404 
405  //Read DMA status register
406  status = EMAC0->DMARIS;
407 
408  //A packet has been transmitted?
409  if(status & EMAC_DMARIS_TI)
410  {
411  //Clear TI interrupt flag
412  EMAC0->DMARIS = EMAC_DMARIS_TI;
413 
414  //Check whether the TX buffer is available for writing
415  if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
416  {
417  //Notify the TCP/IP stack that the transmitter is ready to send
418  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
419  }
420  }
421 
422  //A packet has been received?
423  if(status & EMAC_DMARIS_RI)
424  {
425  //Disable RIE interrupt
426  EMAC0->DMAIM &= ~EMAC_DMAIM_RIE;
427 
428  //Set event flag
429  nicDriverInterface->nicEvent = TRUE;
430  //Notify the TCP/IP stack of the event
431  flag |= osSetEventFromIsr(&netEvent);
432  }
433 
434  //Clear NIS interrupt flag
435  EMAC0->DMARIS = EMAC_DMARIS_NIS;
436 
437  //Interrupt service routine epilogue
438  osExitIsr(flag);
439 }
440 
441 
442 /**
443  * @brief MSP432E4 Ethernet MAC event handler
444  * @param[in] interface Underlying network interface
445  **/
446 
448 {
449  error_t error;
450  uint32_t status;
451 
452  //PHY interrupt?
453  if(EMAC0->EPHYRIS & EMAC_EPHYRIS_INT)
454  {
455  //Clear PHY interrupt flag
456  EMAC0->EPHYMISC = EMAC_EPHYMISC_INT;
457  //Read PHY interrupt status register
458  status = msp432e4EthReadPhyReg(EPHY_MISR1);
459 
460  //Check whether the link state has changed?
461  if(status & EPHY_MISR1_LINKSTAT)
462  {
463  //Read BMSR register
464  status = msp432e4EthReadPhyReg(EPHY_BMSR);
465 
466  //Check whether the link is up
467  if(status & EPHY_BMSR_LINKSTAT)
468  {
469  //Read PHY status register
470  status = msp432e4EthReadPhyReg(EPHY_STS);
471 
472  //Check current speed
473  if(status & EPHY_STS_SPEED)
474  {
475  //10BASE-T operation
476  interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
477  //Update MAC configuration
478  EMAC0->CFG &= ~EMAC_CFG_FES;
479  }
480  else
481  {
482  //100BASE-TX operation
483  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
484  //Update MAC configuration
485  EMAC0->CFG |= EMAC_CFG_FES;
486  }
487 
488  //Check current duplex mode
489  if(status & EPHY_STS_DUPLEX)
490  {
491  //Full-Duplex mode
492  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
493  //Update MAC configuration
494  EMAC0->CFG |= EMAC_CFG_DUPM;
495  }
496  else
497  {
498  //Half-Duplex mode
499  interface->duplexMode = NIC_HALF_DUPLEX_MODE;
500  //Update MAC configuration
501  EMAC0->CFG &= ~EMAC_CFG_DUPM;
502  }
503 
504  //Update link state
505  interface->linkState = TRUE;
506  }
507  else
508  {
509  //Update link state
510  interface->linkState = FALSE;
511  }
512 
513  //Process link state change event
514  nicNotifyLinkChange(interface);
515  }
516  }
517 
518  //Packet received?
519  if(EMAC0->DMARIS & EMAC_DMARIS_RI)
520  {
521  //Clear interrupt flag
522  EMAC0->DMARIS = EMAC_DMARIS_RI;
523 
524  //Process all pending packets
525  do
526  {
527  //Read incoming packet
528  error = msp432e4EthReceivePacket(interface);
529 
530  //No more data in the receive buffer?
531  } while(error != ERROR_BUFFER_EMPTY);
532  }
533 
534  //Re-enable DMA interrupts
535  EMAC0->DMAIM = EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
536  //Re-enable PHY interrupts
537  EMAC0->EPHYIM = EMAC_EPHYIM_INT;
538 }
539 
540 
541 /**
542  * @brief Send a packet
543  * @param[in] interface Underlying network interface
544  * @param[in] buffer Multi-part buffer containing the data to send
545  * @param[in] offset Offset to the first data byte
546  * @return Error code
547  **/
548 
550  const NetBuffer *buffer, size_t offset)
551 {
552  size_t length;
553 
554  //Retrieve the length of the packet
555  length = netBufferGetLength(buffer) - offset;
556 
557  //Check the frame length
559  {
560  //The transmitter can accept another packet
561  osSetEvent(&interface->nicTxEvent);
562  //Report an error
563  return ERROR_INVALID_LENGTH;
564  }
565 
566  //Make sure the current buffer is available for writing
567  if(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN)
568  return ERROR_FAILURE;
569 
570  //Copy user data to the transmit buffer
571  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
572 
573  //Write the number of bytes to send
574  txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
575  //Set LS and FS flags as the data fits in a single buffer
576  txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
577  //Give the ownership of the descriptor to the DMA
578  txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
579 
580  //Clear TU flag to resume processing
581  EMAC0->DMARIS = EMAC_DMARIS_TU;
582  //Instruct the DMA to poll the transmit descriptor list
583  EMAC0->TXPOLLD = 0;
584 
585  //Point to the next descriptor in the list
586  txCurDmaDesc = (Tm4c129TxDmaDesc *) txCurDmaDesc->tdes3;
587 
588  //Check whether the next buffer is available for writing
589  if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
590  {
591  //The transmitter can accept another packet
592  osSetEvent(&interface->nicTxEvent);
593  }
594 
595  //Data successfully written
596  return NO_ERROR;
597 }
598 
599 
600 /**
601  * @brief Receive a packet
602  * @param[in] interface Underlying network interface
603  * @return Error code
604  **/
605 
607 {
608  error_t error;
609  size_t n;
610 
611  //The current buffer is available for reading?
612  if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN))
613  {
614  //FS and LS flags should be set
615  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) && (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS))
616  {
617  //Make sure no error occurred
618  if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_ES))
619  {
620  //Retrieve the length of the frame
621  n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
622  //Limit the number of data to read
624 
625  //Pass the packet to the upper layer
626  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
627 
628  //Valid packet received
629  error = NO_ERROR;
630  }
631  else
632  {
633  //The received packet contains an error
634  error = ERROR_INVALID_PACKET;
635  }
636  }
637  else
638  {
639  //The packet is not valid
640  error = ERROR_INVALID_PACKET;
641  }
642 
643  //Give the ownership of the descriptor back to the DMA
644  rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
645  //Point to the next descriptor in the list
646  rxCurDmaDesc = (Tm4c129RxDmaDesc *) rxCurDmaDesc->rdes3;
647  }
648  else
649  {
650  //No more data in the receive buffer
651  error = ERROR_BUFFER_EMPTY;
652  }
653 
654  //Clear RU flag to resume processing
655  EMAC0->DMARIS = EMAC_DMARIS_RU;
656  //Instruct the DMA to poll the receive descriptor list
657  EMAC0->RXPOLLD = 0;
658 
659  //Return status code
660  return error;
661 }
662 
663 
664 /**
665  * @brief Configure MAC address filtering
666  * @param[in] interface Underlying network interface
667  * @return Error code
668  **/
669 
671 {
672  uint_t i;
673  uint_t j;
674  uint_t k;
675  uint32_t crc;
676  uint32_t hashTable[2];
677  MacAddr unicastMacAddr[3];
678  MacFilterEntry *entry;
679 
680  //Debug message
681  TRACE_DEBUG("Updating MAC filter...\r\n");
682 
683  //Set the MAC address of the station
684  EMAC0->ADDR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
685  EMAC0->ADDR0H = interface->macAddr.w[2];
686 
687  //The MAC supports 3 additional addresses for unicast perfect filtering
688  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
689  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
690  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
691 
692  //The hash table is used for multicast address filtering
693  hashTable[0] = 0;
694  hashTable[1] = 0;
695 
696  //The MAC address filter contains the list of MAC addresses to accept
697  //when receiving an Ethernet frame
698  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
699  {
700  //Point to the current entry
701  entry = &interface->macAddrFilter[i];
702 
703  //Valid entry?
704  if(entry->refCount > 0)
705  {
706  //Multicast address?
707  if(macIsMulticastAddr(&entry->addr))
708  {
709  //Compute CRC over the current MAC address
710  crc = msp432e4EthCalcCrc(&entry->addr, sizeof(MacAddr));
711 
712  //The upper 6 bits in the CRC register are used to index the
713  //contents of the hash table
714  k = (crc >> 26) & 0x3F;
715 
716  //Update hash table contents
717  hashTable[k / 32] |= (1 << (k % 32));
718  }
719  else
720  {
721  //Up to 3 additional MAC addresses can be specified
722  if(j < 3)
723  {
724  //Save the unicast address
725  unicastMacAddr[j++] = entry->addr;
726  }
727  }
728  }
729  }
730 
731  //Configure the first unicast address filter
732  if(j >= 1)
733  {
734  //When the AE bit is set, the entry is used for perfect filtering
735  EMAC0->ADDR1L = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
736  EMAC0->ADDR1H = unicastMacAddr[0].w[2] | EMAC_ADDR1H_AE;
737  }
738  else
739  {
740  //When the AE bit is cleared, the entry is ignored
741  EMAC0->ADDR1L = 0;
742  EMAC0->ADDR1H = 0;
743  }
744 
745  //Configure the second unicast address filter
746  if(j >= 2)
747  {
748  //When the AE bit is set, the entry is used for perfect filtering
749  EMAC0->ADDR2L = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
750  EMAC0->ADDR2H = unicastMacAddr[1].w[2] | EMAC_ADDR2H_AE;
751  }
752  else
753  {
754  //When the AE bit is cleared, the entry is ignored
755  EMAC0->ADDR2L = 0;
756  EMAC0->ADDR2H = 0;
757  }
758 
759  //Configure the third unicast address filter
760  if(j >= 3)
761  {
762  //When the AE bit is set, the entry is used for perfect filtering
763  EMAC0->ADDR3L = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
764  EMAC0->ADDR3H = unicastMacAddr[2].w[2] | EMAC_ADDR3H_AE;
765  }
766  else
767  {
768  //When the AE bit is cleared, the entry is ignored
769  EMAC0->ADDR3L = 0;
770  EMAC0->ADDR3H = 0;
771  }
772 
773  //Configure the multicast address filter
774  EMAC0->HASHTBLL = hashTable[0];
775  EMAC0->HASHTBLH = hashTable[1];
776 
777  //Debug message
778  TRACE_DEBUG(" HASHTBLL = %08" PRIX32 "\r\n", EMAC0->HASHTBLL);
779  TRACE_DEBUG(" HASHTBLH = %08" PRIX32 "\r\n", EMAC0->HASHTBLH);
780 
781  //Successful processing
782  return NO_ERROR;
783 }
784 
785 
786 /**
787  * @brief Write PHY register
788  * @param[in] regAddr Register address
789  * @param[in] data Register value
790  **/
791 
792 void msp432e4EthWritePhyReg(uint8_t regAddr, uint16_t data)
793 {
794  uint32_t temp;
795 
796  //Take care not to alter MDC clock configuration
797  temp = EMAC0->MIIADDR & EMAC_MIIADDR_CR_M;
798  //Set up a write operation
799  temp |= EMAC_MIIADDR_MIIW | EMAC_MIIADDR_MIIB;
800  //The address of the integrated PHY is 0
801  temp |= (0 << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
802  //Register address
803  temp |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
804 
805  //Data to be written in the PHY register
806  EMAC0->MIIDATA = data & EMAC_MIIDATA_DATA_M;
807 
808  //Start a write operation
809  EMAC0->MIIADDR = temp;
810  //Wait for the write to complete
811  while(EMAC0->MIIADDR & EMAC_MIIADDR_MIIB)
812  {
813  }
814 }
815 
816 
817 /**
818  * @brief Read PHY register
819  * @param[in] regAddr Register address
820  * @return Register value
821  **/
822 
824 {
825  uint32_t temp;
826 
827  //Take care not to alter MDC clock configuration
828  temp = EMAC0->MIIADDR & EMAC_MIIADDR_CR_M;
829  //Set up a read operation
830  temp |= EMAC_MIIADDR_MIIB;
831  //The address of the integrated PHY is 0
832  temp |= (0 << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
833  //Register address
834  temp |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
835 
836  //Start a read operation
837  EMAC0->MIIADDR = temp;
838  //Wait for the read to complete
839  while(EMAC0->MIIADDR & EMAC_MIIADDR_MIIB)
840  {
841  }
842 
843  //Return PHY register contents
844  return EMAC0->MIIDATA & EMAC_MIIDATA_DATA_M;
845 }
846 
847 
848 /**
849  * @brief Dump PHY registers for debugging purpose
850  **/
851 
853 {
854  uint8_t i;
855 
856  //Loop through PHY registers
857  for(i = 0; i < 32; i++)
858  {
859  //Display current PHY register
860  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
862  }
863 
864  //Terminate with a line feed
865  TRACE_DEBUG("\r\n");
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 msp432e4EthCalcCrc(const void *data, size_t length)
877 {
878  uint_t i;
879  uint_t j;
880 
881  //Point to the data over which to calculate the CRC
882  const uint8_t *p = (uint8_t *) data;
883  //CRC preset value
884  uint32_t 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)
894  crc = (crc << 1) ^ 0x04C11DB7;
895  else
896  crc = crc << 1;
897  }
898  }
899 
900  //Return CRC value
901  return ~crc;
902 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:525
uint8_t length
Definition: dtls_misc.h:149
#define MSP432E4_ETH_RX_BUFFER_SIZE
#define EMAC_TDES0_OWN
error_t msp432e4EthReceivePacket(NetInterface *interface)
Receive a packet.
int bool_t
Definition: compiler_port.h:49
void msp432e4EthWritePhyReg(uint8_t regAddr, uint16_t data)
Write PHY register.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:119
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
Enhanced TX DMA descriptor.
#define MSP432E4_ETH_TX_BUFFER_COUNT
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
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
#define TRUE
Definition: os_port.h:50
#define EMAC_TDES0_TCH
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:223
error_t msp432e4EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define EMAC_RDES0_FL
MSP432E4 Ethernet controller.
#define EMAC_DMABUSMOD_RPBL_1
void msp432e4EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:110
#define osExitIsr(flag)
const NicDriver msp432e4EthDriver
MSP432E4 Ethernet MAC driver.
#define EMAC_RDES0_OWN
#define EMAC_TDES0_IC
#define FALSE
Definition: os_port.h:46
error_t msp432e4EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
error_t msp432e4EthInit(NetInterface *interface)
MSP432E4 Ethernet MAC initialization.
uint16_t msp432e4EthReadPhyReg(uint8_t regAddr)
Read PHY register.
#define EMAC_TDES0_FS
error_t
Error codes.
Definition: error.h:42
uint32_t msp432e4EthCalcCrc(const void *data, size_t length)
CRC calculation.
void msp432e4EthEventHandler(NetInterface *interface)
MSP432E4 Ethernet MAC event handler.
@ 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
#define EMAC_RDES0_FS
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:105
@ ERROR_INVALID_LENGTH
Definition: error.h:109
@ ERROR_BUFFER_EMPTY
Definition: error.h:139
OsEvent netEvent
Definition: net.c:77
#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
#define EMAC_TDES0_LS
#define rxBuffer
#define MSP432E4_ETH_RX_BUFFER_COUNT
#define EMAC_RDES0_LS
#define EMAC_TDES1_TBS1
#define MSP432E4_ETH_IRQ_PRIORITY
#define TRACE_DEBUG(...)
Definition: debug.h:106
void msp432e4EthTick(NetInterface *interface)
MSP432E4 Ethernet MAC timer handler.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:91
uint8_t n
#define EMAC_RDES1_RCH
MAC filter table entry.
Definition: ethernet.h:220
#define EMAC_DMABUSMOD_PBL_1
#define osEnterIsr()
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:118
#define EMAC_DMABUSMOD_PR_1_1
#define MSP432E4_ETH_TX_BUFFER_SIZE
#define rxDmaDesc
void msp432e4EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void msp432e4EthInitGpio(NetInterface *interface)
#define txDmaDesc
void msp432e4EthDumpPhyReg(void)
Dump PHY registers for debugging purpose.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:106
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
void msp432e4EthDisableIrq(NetInterface *interface)
Disable interrupts.
uint8_t data[]
Definition: dtls_misc.h:176
#define MSP432E4_ETH_IRQ_PRIORITY_GROUPING
NIC driver.
Definition: nic.h:179
Enhanced RX DMA descriptor.
#define EMAC_RDES0_ES
#define EMAC_RDES1_RBS1
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:56
@ NO_ERROR
Success.
Definition: error.h:44
void EMAC0_IRQHandler(void)
MSP432E4 Ethernet MAC interrupt service routine.
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
__start_packed struct @108 MacAddr
MAC address.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:79