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-2026 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.6.0
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/types.h"
39 #include "driverlib/gpio.h"
40 #include "driverlib/interrupt.h"
41 #include "driverlib/pin_map.h"
42 #include "driverlib/sysctl.h"
43 #include "core/net.h"
45 #include "debug.h"
46 
47 //Underlying network interface
48 static NetInterface *nicDriverInterface;
49 
50 //IAR EWARM compiler?
51 #if defined(__ICCARM__)
52 
53 //Transmit buffer
54 #pragma data_alignment = 4
56 //Receive buffer
57 #pragma data_alignment = 4
59 //Transmit DMA descriptors
60 #pragma data_alignment = 4
62 //Receive DMA descriptors
63 #pragma data_alignment = 4
65 
66 //Keil MDK-ARM or GCC compiler?
67 #else
68 
69 //Transmit buffer
71  __attribute__((aligned(4)));
72 //Receive buffer
74  __attribute__((aligned(4)));
75 //Transmit DMA descriptors
77  __attribute__((aligned(4)));
78 //Receive DMA descriptors
80  __attribute__((aligned(4)));
81 
82 #endif
83 
84 //Pointer to the current TX DMA descriptor
85 static Msp432e4TxDmaDesc *txCurDmaDesc;
86 //Pointer to the current RX DMA descriptor
87 static Msp432e4RxDmaDesc *rxCurDmaDesc;
88 
89 
90 /**
91  * @brief MSP432E4 Ethernet MAC driver
92  **/
93 
95 {
97  ETH_MTU,
108  TRUE,
109  TRUE,
110  TRUE,
111  FALSE
112 };
113 
114 
115 /**
116  * @brief MSP432E4 Ethernet MAC initialization
117  * @param[in] interface Underlying network interface
118  * @return Error code
119  **/
120 
122 {
123  error_t error;
124 #ifdef ti_sysbios_BIOS___VERS
125  Hwi_Params hwiParams;
126 #endif
127 
128  //Debug message
129  TRACE_INFO("Initializing MSP432E4 Ethernet controller...\r\n");
130 
131  //Save underlying network interface
132  nicDriverInterface = interface;
133 
134  //Enable and reset EMAC peripheral
135  SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
136  SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
137 
138  //Wait for the EMAC peripheral to be ready
139  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
140  {
141  }
142 
143  //Enable and reset PHY peripheral
144  SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
145  SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
146 
147  //Wait for the PHY peripheral to be ready
148  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0))
149  {
150  }
151 
152  //GPIO configuration
153  msp432e4EthInitGpio(interface);
154 
155  //Perform a software reset
156  EMAC0_DMABUSMOD_R |= EMAC_DMABUSMOD_SWR;
157  //Wait for the reset to complete
158  while((EMAC0_DMABUSMOD_R & EMAC_DMABUSMOD_SWR) != 0)
159  {
160  }
161 
162  //Adjust MDC clock range depending on SYSCLK frequency
163  EMAC0_MIIADDR_R = EMAC_MIIADDR_CR_100_150;
164 
165  //Internal or external Ethernet PHY?
166  if(interface->phyDriver != NULL)
167  {
168  //Ethernet PHY initialization
169  error = interface->phyDriver->init(interface);
170  }
171  else if(interface->switchDriver != NULL)
172  {
173  //Ethernet switch initialization
174  error = interface->switchDriver->init(interface);
175  }
176  else
177  {
178  //Reset internal PHY transceiver
180  EPHY_BMCR_MIIRESET);
181 
182  //Wait for the reset to complete
183  while(msp432e4EthReadPhyReg(SMI_OPCODE_READ, 0, EPHY_BMCR) &
184  EPHY_BMCR_MIIRESET)
185  {
186  }
187 
188  //Dump PHY registers for debugging purpose
190 
191  //Configure LED0, LED1 and LED2
193  EPHY_LEDCFG_LED0_TX | EPHY_LEDCFG_LED1_RX | EPHY_LEDCFG_LED2_LINK);
194 
195  //Configure PHY interrupts as desired
197  EPHY_MISR1_LINKSTATEN);
198 
199  //Enable PHY interrupts
200  msp432e4EthWritePhyReg(SMI_OPCODE_WRITE, 0, EPHY_SCR, EPHY_SCR_INTEN);
201 
202  //The internal Ethernet PHY is initialized
203  error = NO_ERROR;
204  }
205 
206  //Any error to report?
207  if(error)
208  {
209  return error;
210  }
211 
212  //Use default MAC configuration
213  EMAC0_CFG_R = EMAC_CFG_DRO;
214 
215  //Configure MAC address filtering
217 
218  //Disable flow control
219  EMAC0_FLOWCTL_R = 0;
220  //Enable store and forward mode
221  EMAC0_DMAOPMODE_R = EMAC_DMAOPMODE_RSF | EMAC_DMAOPMODE_TSF;
222 
223  //Configure DMA bus mode
224  EMAC0_DMABUSMOD_R = EMAC_DMABUSMOD_AAL | EMAC_DMABUSMOD_USP |
226  EMAC_DMABUSMOD_ATDS;
227 
228  //Initialize DMA descriptor lists
229  msp432e4EthInitDmaDesc(interface);
230 
231  //Prevent interrupts from being generated when the transmit statistic
232  //counters reach half their maximum value
233  EMAC0_MMCTXIM_R = EMAC_MMCTXIM_OCTCNT | EMAC_MMCTXIM_MCOLLGF |
234  EMAC_MMCTXIM_SCOLLGF | EMAC_MMCTXIM_GBF;
235 
236  //Prevent interrupts from being generated when the receive statistic
237  //counters reach half their maximum value
238  EMAC0_MMCRXIM_R = EMAC_MMCRXIM_UCGF | EMAC_MMCRXIM_ALGNERR |
239  EMAC_MMCRXIM_CRCERR | EMAC_MMCRXIM_GBF;
240 
241  //Disable MAC interrupts
242  EMAC0_IM_R = EMAC_IM_TSI | EMAC_IM_PMT;
243  //Enable the desired DMA interrupts
244  EMAC0_DMAIM_R = EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
245  //Enable PHY interrupts
246  EMAC0_EPHYIM_R = EMAC_EPHYIM_INT;
247 
248 #ifdef ti_sysbios_BIOS___VERS
249  //Configure Ethernet interrupt
250  Hwi_Params_init(&hwiParams);
251  hwiParams.enableInt = FALSE;
252  hwiParams.priority = MSP432E4_ETH_IRQ_PRIORITY;
253 
254  //Register interrupt handler
255  Hwi_create(INT_EMAC0, (Hwi_FuncPtr) msp432e4EthIrqHandler, &hwiParams, NULL);
256 #else
257  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
258  IntPriorityGroupingSet(MSP432E4_ETH_IRQ_PRIORITY_GROUPING);
259  //Configure Ethernet interrupt priority
260  IntPrioritySet(INT_EMAC0, MSP432E4_ETH_IRQ_PRIORITY);
261 #endif
262 
263  //Enable MAC transmission and reception
264  EMAC0_CFG_R |= EMAC_CFG_TE | EMAC_CFG_RE;
265  //Enable DMA transmission and reception
266  EMAC0_DMAOPMODE_R |= EMAC_DMAOPMODE_ST | EMAC_DMAOPMODE_SR;
267 
268  //Accept any packets from the upper layer
269  osSetEvent(&interface->nicTxEvent);
270 
271  //Successful initialization
272  return NO_ERROR;
273 }
274 
275 
276 /**
277  * @brief GPIO configuration
278  * @param[in] interface Underlying network interface
279  **/
280 
281 __weak_func void msp432e4EthInitGpio(NetInterface *interface)
282 {
283 //MSP-EXP432E401Y evaluation board?
284 #if defined(USE_MSP_EXP432E401Y)
285  //Enable GPIO clock
286  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
287 
288  //Select the relevant alternate function for PF0 and PF4
289  GPIOPinConfigure(GPIO_PF0_EN0LED0);
290  GPIOPinConfigure(GPIO_PF4_EN0LED1);
291 
292  //Configure Ethernet LED pins for proper operation
293  GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);
294 #endif
295 }
296 
297 
298 /**
299  * @brief Initialize DMA descriptor lists
300  * @param[in] interface Underlying network interface
301  **/
302 
304 {
305  uint_t i;
306 
307  //Initialize TX DMA descriptor list
308  for(i = 0; i < MSP432E4_ETH_TX_BUFFER_COUNT; i++)
309  {
310  //Use chain structure rather than ring structure
312  //Initialize transmit buffer size
313  txDmaDesc[i].tdes1 = 0;
314  //Transmit buffer address
315  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
316  //Next descriptor address
317  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
318  //Reserved fields
319  txDmaDesc[i].tdes4 = 0;
320  txDmaDesc[i].tdes5 = 0;
321  //Transmit frame time stamp
322  txDmaDesc[i].tdes6 = 0;
323  txDmaDesc[i].tdes7 = 0;
324  }
325 
326  //The last descriptor is chained to the first entry
327  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
328  //Point to the very first descriptor
329  txCurDmaDesc = &txDmaDesc[0];
330 
331  //Initialize RX DMA descriptor list
332  for(i = 0; i < MSP432E4_ETH_RX_BUFFER_COUNT; i++)
333  {
334  //The descriptor is initially owned by the DMA
335  rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
336  //Use chain structure rather than ring structure
338  //Receive buffer address
339  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
340  //Next descriptor address
341  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
342  //Extended status
343  rxDmaDesc[i].rdes4 = 0;
344  //Reserved field
345  rxDmaDesc[i].rdes5 = 0;
346  //Receive frame time stamp
347  rxDmaDesc[i].rdes6 = 0;
348  rxDmaDesc[i].rdes7 = 0;
349  }
350 
351  //The last descriptor is chained to the first entry
352  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
353  //Point to the very first descriptor
354  rxCurDmaDesc = &rxDmaDesc[0];
355 
356  //Start location of the TX descriptor list
357  EMAC0_TXDLADDR_R = (uint32_t) txDmaDesc;
358  //Start location of the RX descriptor list
359  EMAC0_RXDLADDR_R = (uint32_t) rxDmaDesc;
360 }
361 
362 
363 /**
364  * @brief MSP432E4 Ethernet MAC timer handler
365  *
366  * This routine is periodically called by the TCP/IP stack to handle periodic
367  * operations such as polling the link state
368  *
369  * @param[in] interface Underlying network interface
370  **/
371 
373 {
374  //Valid Ethernet PHY or switch driver?
375  if(interface->phyDriver != NULL)
376  {
377  //Handle periodic operations
378  interface->phyDriver->tick(interface);
379  }
380  else if(interface->switchDriver != NULL)
381  {
382  //Handle periodic operations
383  interface->switchDriver->tick(interface);
384  }
385  else
386  {
387  //Just for sanity
388  }
389 }
390 
391 
392 /**
393  * @brief Enable interrupts
394  * @param[in] interface Underlying network interface
395  **/
396 
398 {
399 #ifdef ti_sysbios_BIOS___VERS
400  //Enable Ethernet MAC interrupts
401  Hwi_enableInterrupt(INT_EMAC0);
402 #else
403  //Enable Ethernet MAC interrupts
404  IntEnable(INT_EMAC0);
405 #endif
406 
407  //Valid Ethernet PHY or switch driver?
408  if(interface->phyDriver != NULL)
409  {
410  //Enable Ethernet PHY interrupts
411  interface->phyDriver->enableIrq(interface);
412  }
413  else if(interface->switchDriver != NULL)
414  {
415  //Enable Ethernet switch interrupts
416  interface->switchDriver->enableIrq(interface);
417  }
418  else
419  {
420  //Just for sanity
421  }
422 }
423 
424 
425 /**
426  * @brief Disable interrupts
427  * @param[in] interface Underlying network interface
428  **/
429 
431 {
432 #ifdef ti_sysbios_BIOS___VERS
433  //Disable Ethernet MAC interrupts
434  Hwi_disableInterrupt(INT_EMAC0);
435 #else
436  //Disable Ethernet MAC interrupts
437  IntDisable(INT_EMAC0);
438 #endif
439 
440  //Valid Ethernet PHY or switch driver?
441  if(interface->phyDriver != NULL)
442  {
443  //Disable Ethernet PHY interrupts
444  interface->phyDriver->disableIrq(interface);
445  }
446  else if(interface->switchDriver != NULL)
447  {
448  //Disable Ethernet switch interrupts
449  interface->switchDriver->disableIrq(interface);
450  }
451  else
452  {
453  //Just for sanity
454  }
455 }
456 
457 
458 /**
459  * @brief MSP432E4 Ethernet MAC interrupt service routine
460  **/
461 
463 {
464  bool_t flag;
465  uint32_t status;
466 
467  //Interrupt service routine prologue
468  osEnterIsr();
469 
470  //This flag will be set if a higher priority task must be woken
471  flag = FALSE;
472 
473  //Read PHY status register
474  status = EMAC0_EPHYRIS_R;
475 
476  //PHY interrupt?
477  if((status & EMAC_EPHYRIS_INT) != 0)
478  {
479  //Disable PHY interrupt
480  EMAC0_EPHYIM_R &= ~EMAC_EPHYIM_INT;
481 
482  //Set event flag
483  nicDriverInterface->nicEvent = TRUE;
484  //Notify the TCP/IP stack of the event
485  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
486  }
487 
488  //Read DMA status register
489  status = EMAC0_DMARIS_R;
490 
491  //Packet transmitted?
492  if((status & EMAC_DMARIS_TI) != 0)
493  {
494  //Clear TI interrupt flag
495  EMAC0_DMARIS_R = EMAC_DMARIS_TI;
496 
497  //Check whether the TX buffer is available for writing
498  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
499  {
500  //Notify the TCP/IP stack that the transmitter is ready to send
501  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
502  }
503  }
504 
505  //Packet received?
506  if((status & EMAC_DMARIS_RI) != 0)
507  {
508  //Disable RIE interrupt
509  EMAC0_DMAIM_R &= ~EMAC_DMAIM_RIE;
510 
511  //Set event flag
512  nicDriverInterface->nicEvent = TRUE;
513  //Notify the TCP/IP stack of the event
514  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
515  }
516 
517  //Clear NIS interrupt flag
518  EMAC0_DMARIS_R = EMAC_DMARIS_NIS;
519 
520  //Interrupt service routine epilogue
521  osExitIsr(flag);
522 }
523 
524 
525 /**
526  * @brief MSP432E4 Ethernet MAC event handler
527  * @param[in] interface Underlying network interface
528  **/
529 
531 {
532  error_t error;
533  uint32_t status;
534 
535  //PHY interrupt?
536  if((EMAC0_EPHYRIS_R & EMAC_EPHYRIS_INT) != 0)
537  {
538  //Clear PHY interrupt flag
539  EMAC0_EPHYMISC_R = EMAC_EPHYMISC_INT;
540 
541  //Internal or external Ethernet PHY?
542  if(interface->phyDriver != NULL)
543  {
544  //Handle events
545  interface->phyDriver->eventHandler(interface);
546  }
547  else if(interface->switchDriver != NULL)
548  {
549  //Handle events
550  interface->switchDriver->eventHandler(interface);
551  }
552  else
553  {
554  //Read PHY interrupt status register
555  status = msp432e4EthReadPhyReg(SMI_OPCODE_READ, 0, EPHY_MISR1);
556 
557  //Check whether the link state has changed?
558  if((status & EPHY_MISR1_LINKSTAT) != 0)
559  {
560  //Read BMSR register
561  status = msp432e4EthReadPhyReg(SMI_OPCODE_READ, 0, EPHY_BMSR);
562 
563  //Check whether the link is up
564  if((status & EPHY_BMSR_LINKSTAT) != 0)
565  {
566  //Read PHY status register
567  status = msp432e4EthReadPhyReg(SMI_OPCODE_READ, 0, EPHY_STS);
568 
569  //Check current speed
570  if((status & EPHY_STS_SPEED) != 0)
571  {
572  interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
573  }
574  else
575  {
576  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
577  }
578 
579  //Check duplex mode
580  if((status & EPHY_STS_DUPLEX) != 0)
581  {
582  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
583  }
584  else
585  {
586  interface->duplexMode = NIC_HALF_DUPLEX_MODE;
587  }
588 
589  //Update link state
590  interface->linkState = TRUE;
591 
592  //Adjust MAC configuration parameters for proper operation
593  msp432e4EthUpdateMacConfig(interface);
594  }
595  else
596  {
597  //Update link state
598  interface->linkState = FALSE;
599  }
600 
601  //Process link state change event
602  nicNotifyLinkChange(interface);
603  }
604  }
605  }
606 
607  //Packet received?
608  if((EMAC0_DMARIS_R & EMAC_DMARIS_RI) != 0)
609  {
610  //Clear interrupt flag
611  EMAC0_DMARIS_R = EMAC_DMARIS_RI;
612 
613  //Process all pending packets
614  do
615  {
616  //Read incoming packet
617  error = msp432e4EthReceivePacket(interface);
618 
619  //No more data in the receive buffer?
620  } while(error != ERROR_BUFFER_EMPTY);
621  }
622 
623  //Re-enable DMA interrupts
624  EMAC0_DMAIM_R = EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
625  //Re-enable PHY interrupts
626  EMAC0_EPHYIM_R = EMAC_EPHYIM_INT;
627 }
628 
629 
630 /**
631  * @brief Send a packet
632  * @param[in] interface Underlying network interface
633  * @param[in] buffer Multi-part buffer containing the data to send
634  * @param[in] offset Offset to the first data byte
635  * @param[in] ancillary Additional options passed to the stack along with
636  * the packet
637  * @return Error code
638  **/
639 
641  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
642 {
643  size_t length;
644 
645  //Retrieve the length of the packet
646  length = netBufferGetLength(buffer) - offset;
647 
648  //Check the frame length
650  {
651  //The transmitter can accept another packet
652  osSetEvent(&interface->nicTxEvent);
653  //Report an error
654  return ERROR_INVALID_LENGTH;
655  }
656 
657  //Make sure the current buffer is available for writing
658  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) != 0)
659  {
660  return ERROR_FAILURE;
661  }
662 
663  //Copy user data to the transmit buffer
664  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
665 
666  //Write the number of bytes to send
667  txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
668  //Set LS and FS flags as the data fits in a single buffer
669  txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
670  //Give the ownership of the descriptor to the DMA
671  txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
672 
673  //Clear TU flag to resume processing
674  EMAC0_DMARIS_R = EMAC_DMARIS_TU;
675  //Instruct the DMA to poll the transmit descriptor list
676  EMAC0_TXPOLLD_R = 0;
677 
678  //Point to the next descriptor in the list
679  txCurDmaDesc = (Msp432e4TxDmaDesc *) txCurDmaDesc->tdes3;
680 
681  //Check whether the next buffer is available for writing
682  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
683  {
684  //The transmitter can accept another packet
685  osSetEvent(&interface->nicTxEvent);
686  }
687 
688  //Data successfully written
689  return NO_ERROR;
690 }
691 
692 
693 /**
694  * @brief Receive a packet
695  * @param[in] interface Underlying network interface
696  * @return Error code
697  **/
698 
700 {
701  error_t error;
702  size_t n;
703  NetRxAncillary ancillary;
704 
705  //Current buffer available for reading?
706  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN) == 0)
707  {
708  //FS and LS flags should be set
709  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) != 0 &&
710  (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS) != 0)
711  {
712  //Make sure no error occurred
713  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_ES) == 0)
714  {
715  //Retrieve the length of the frame
716  n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
717  //Limit the number of data to read
719 
720  //Additional options can be passed to the stack along with the packet
721  ancillary = NET_DEFAULT_RX_ANCILLARY;
722 
723  //Pass the packet to the upper layer
724  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
725  &ancillary);
726 
727  //Valid packet received
728  error = NO_ERROR;
729  }
730  else
731  {
732  //The received packet contains an error
733  error = ERROR_INVALID_PACKET;
734  }
735  }
736  else
737  {
738  //The packet is not valid
739  error = ERROR_INVALID_PACKET;
740  }
741 
742  //Give the ownership of the descriptor back to the DMA
743  rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
744  //Point to the next descriptor in the list
745  rxCurDmaDesc = (Msp432e4RxDmaDesc *) rxCurDmaDesc->rdes3;
746  }
747  else
748  {
749  //No more data in the receive buffer
750  error = ERROR_BUFFER_EMPTY;
751  }
752 
753  //Clear RU flag to resume processing
754  EMAC0_DMARIS_R = EMAC_DMARIS_RU;
755  //Instruct the DMA to poll the receive descriptor list
756  EMAC0_RXPOLLD_R = 0;
757 
758  //Return status code
759  return error;
760 }
761 
762 
763 /**
764  * @brief Configure MAC address filtering
765  * @param[in] interface Underlying network interface
766  * @return Error code
767  **/
768 
770 {
771  uint_t i;
772  uint_t j;
773  uint_t k;
774  uint32_t crc;
775  uint32_t hashTable[2];
776  MacAddr unicastMacAddr[3];
777  MacFilterEntry *entry;
778 
779  //Debug message
780  TRACE_DEBUG("Updating MAC filter...\r\n");
781 
782  //Promiscuous mode?
783  if(interface->promiscuous)
784  {
785  //Pass all incoming frames regardless of their destination address
786  EMAC0_FRAMEFLTR_R = EMAC_FRAMEFLTR_PR;
787  }
788  else
789  {
790  //Set the MAC address of the station
791  EMAC0_ADDR0L_R = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
792  EMAC0_ADDR0H_R = interface->macAddr.w[2];
793 
794  //The MAC supports 3 additional addresses for unicast perfect filtering
795  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
796  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
797  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
798 
799  //The hash table is used for multicast address filtering
800  hashTable[0] = 0;
801  hashTable[1] = 0;
802 
803  //The MAC address filter contains the list of MAC addresses to accept
804  //when receiving an Ethernet frame
805  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
806  {
807  //Point to the current entry
808  entry = &interface->macAddrFilter[i];
809 
810  //Valid entry?
811  if(entry->refCount > 0)
812  {
813  //Multicast address?
814  if(macIsMulticastAddr(&entry->addr))
815  {
816  //Compute CRC over the current MAC address
817  crc = msp432e4EthCalcCrc(&entry->addr, sizeof(MacAddr));
818 
819  //The upper 6 bits in the CRC register are used to index the
820  //contents of the hash table
821  k = (crc >> 26) & 0x3F;
822 
823  //Update hash table contents
824  hashTable[k / 32] |= (1 << (k % 32));
825  }
826  else
827  {
828  //Up to 3 additional MAC addresses can be specified
829  if(j < 3)
830  {
831  //Save the unicast address
832  unicastMacAddr[j++] = entry->addr;
833  }
834  }
835  }
836  }
837 
838  //Configure the first unicast address filter
839  if(j >= 1)
840  {
841  //When the AE bit is set, the entry is used for perfect filtering
842  EMAC0_ADDR1L_R = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
843  EMAC0_ADDR1H_R = unicastMacAddr[0].w[2] | EMAC_ADDR1H_AE;
844  }
845  else
846  {
847  //When the AE bit is cleared, the entry is ignored
848  EMAC0_ADDR1L_R = 0;
849  EMAC0_ADDR1H_R = 0;
850  }
851 
852  //Configure the second unicast address filter
853  if(j >= 2)
854  {
855  //When the AE bit is set, the entry is used for perfect filtering
856  EMAC0_ADDR2L_R = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
857  EMAC0_ADDR2H_R = unicastMacAddr[1].w[2] | EMAC_ADDR2H_AE;
858  }
859  else
860  {
861  //When the AE bit is cleared, the entry is ignored
862  EMAC0_ADDR2L_R = 0;
863  EMAC0_ADDR2H_R = 0;
864  }
865 
866  //Configure the third unicast address filter
867  if(j >= 3)
868  {
869  //When the AE bit is set, the entry is used for perfect filtering
870  EMAC0_ADDR3L_R = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
871  EMAC0_ADDR3H_R = unicastMacAddr[2].w[2] | EMAC_ADDR3H_AE;
872  }
873  else
874  {
875  //When the AE bit is cleared, the entry is ignored
876  EMAC0_ADDR3L_R = 0;
877  EMAC0_ADDR3H_R = 0;
878  }
879 
880  //Check whether frames with a multicast destination address should be
881  //accepted
882  if(interface->acceptAllMulticast)
883  {
884  //Configure the receive filter
885  EMAC0_FRAMEFLTR_R = EMAC_FRAMEFLTR_HPF | EMAC_FRAMEFLTR_PM;
886  }
887  else
888  {
889  //Configure the receive filter
890  EMAC0_FRAMEFLTR_R = EMAC_FRAMEFLTR_HPF | EMAC_FRAMEFLTR_HMC;
891 
892  //Configure the multicast hash table
893  EMAC0_HASHTBLL_R = hashTable[0];
894  EMAC0_HASHTBLH_R = hashTable[1];
895 
896  //Debug message
897  TRACE_DEBUG(" HASHTBLL = 0x%08" PRIX32 "\r\n", EMAC0_HASHTBLL_R);
898  TRACE_DEBUG(" HASHTBLH = 0x%08" PRIX32 "\r\n", EMAC0_HASHTBLH_R);
899  }
900  }
901 
902  //Successful processing
903  return NO_ERROR;
904 }
905 
906 
907 /**
908  * @brief Adjust MAC configuration parameters for proper operation
909  * @param[in] interface Underlying network interface
910  * @return Error code
911  **/
912 
914 {
915  uint32_t config;
916 
917  //Read current MAC configuration
918  config = EMAC0_CFG_R;
919 
920  //10BASE-T or 100BASE-TX operation mode?
921  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
922  {
923  config |= EMAC_CFG_FES;
924  }
925  else
926  {
927  config &= ~EMAC_CFG_FES;
928  }
929 
930  //Half-duplex or full-duplex mode?
931  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
932  {
933  config |= EMAC_CFG_DUPM;
934  }
935  else
936  {
937  config &= ~EMAC_CFG_DUPM;
938  }
939 
940  //Update MAC configuration register
941  EMAC0_CFG_R = config;
942 
943  //Successful processing
944  return NO_ERROR;
945 }
946 
947 
948 /**
949  * @brief Write PHY register
950  * @param[in] opcode Access type (2 bits)
951  * @param[in] phyAddr PHY address (5 bits)
952  * @param[in] regAddr Register address (5 bits)
953  * @param[in] data Register value
954  **/
955 
956 void msp432e4EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
957  uint8_t regAddr, uint16_t data)
958 {
959  uint32_t temp;
960 
961  //Valid opcode?
962  if(opcode == SMI_OPCODE_WRITE)
963  {
964  //Take care not to alter MDC clock configuration
965  temp = EMAC0_MIIADDR_R & EMAC_MIIADDR_CR_M;
966  //Set up a write operation
967  temp |= EMAC_MIIADDR_MIIW | EMAC_MIIADDR_MIIB;
968  //PHY address
969  temp |= (phyAddr << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
970  //Register address
971  temp |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
972 
973  //Data to be written in the PHY register
974  EMAC0_MIIDATA_R = data & EMAC_MIIDATA_DATA_M;
975 
976  //Start a write operation
977  EMAC0_MIIADDR_R = temp;
978  //Wait for the write to complete
979  while((EMAC0_MIIADDR_R & EMAC_MIIADDR_MIIB) != 0)
980  {
981  }
982  }
983  else
984  {
985  //The MAC peripheral only supports standard Clause 22 opcodes
986  }
987 }
988 
989 
990 /**
991  * @brief Read PHY register
992  * @param[in] opcode Access type (2 bits)
993  * @param[in] phyAddr PHY address (5 bits)
994  * @param[in] regAddr Register address (5 bits)
995  * @return Register value
996  **/
997 
998 uint16_t msp432e4EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
999  uint8_t regAddr)
1000 {
1001  uint16_t data;
1002  uint32_t temp;
1003 
1004  //Valid opcode?
1005  if(opcode == SMI_OPCODE_READ)
1006  {
1007  //Take care not to alter MDC clock configuration
1008  temp = EMAC0_MIIADDR_R & EMAC_MIIADDR_CR_M;
1009  //Set up a read operation
1010  temp |= EMAC_MIIADDR_MIIB;
1011  //PHY address
1012  temp |= (phyAddr << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
1013  //Register address
1014  temp |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
1015 
1016  //Start a read operation
1017  EMAC0_MIIADDR_R = temp;
1018  //Wait for the read to complete
1019  while((EMAC0_MIIADDR_R & EMAC_MIIADDR_MIIB) != 0)
1020  {
1021  }
1022 
1023  //Get register value
1024  data = EMAC0_MIIDATA_R & EMAC_MIIDATA_DATA_M;
1025  }
1026  else
1027  {
1028  //The MAC peripheral only supports standard Clause 22 opcodes
1029  data = 0;
1030  }
1031 
1032  //Return the value of the PHY register
1033  return data;
1034 }
1035 
1036 
1037 /**
1038  * @brief Dump PHY registers for debugging purpose
1039  **/
1040 
1042 {
1043  uint8_t i;
1044 
1045  //Loop through PHY registers
1046  for(i = 0; i < 32; i++)
1047  {
1048  //Display current PHY register
1049  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1051  }
1052 
1053  //Terminate with a line feed
1054  TRACE_DEBUG("\r\n");
1055 }
1056 
1057 
1058 /**
1059  * @brief CRC calculation
1060  * @param[in] data Pointer to the data over which to calculate the CRC
1061  * @param[in] length Number of bytes to process
1062  * @return Resulting CRC value
1063  **/
1064 
1065 uint32_t msp432e4EthCalcCrc(const void *data, size_t length)
1066 {
1067  uint_t i;
1068  uint_t j;
1069  uint32_t crc;
1070  const uint8_t *p;
1071 
1072  //Point to the data over which to calculate the CRC
1073  p = (uint8_t *) data;
1074  //CRC preset value
1075  crc = 0xFFFFFFFF;
1076 
1077  //Loop through data
1078  for(i = 0; i < length; i++)
1079  {
1080  //The message is processed bit by bit
1081  for(j = 0; j < 8; j++)
1082  {
1083  //Update CRC value
1084  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
1085  {
1086  crc = (crc << 1) ^ 0x04C11DB7;
1087  }
1088  else
1089  {
1090  crc = crc << 1;
1091  }
1092  }
1093  }
1094 
1095  //Return CRC value
1096  return ~crc;
1097 }
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:601
#define EMAC_RDES1_RBS1
#define EMAC0_EPHYMISC_R
#define MSP432E4_ETH_RX_BUFFER_SIZE
uint8_t opcode
Definition: dns_common.h:191
error_t msp432e4EthReceivePacket(NetInterface *interface)
Receive a packet.
int bool_t
Definition: compiler_port.h:63
@ 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 EMAC_TDES0_OWN
#define EMAC0_DMABUSMOD_R
#define MSP432E4_ETH_TX_BUFFER_COUNT
uint8_t p
Definition: ndp.h:300
#define EMAC_DMABUSMOD_RPBL_32
#define EMAC_RDES0_ES
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
#define EMAC0_ADDR1H_R
uint8_t data[]
Definition: ethernet.h:224
#define EMAC0_HASHTBLH_R
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
#define EMAC_TDES0_IC
#define EMAC0_TXDLADDR_R
#define EMAC0_ADDR2H_R
MSP432E4 Ethernet controller.
void msp432e4EthEnableIrq(NetInterface *interface)
Enable interrupts.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:418
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define EMAC0_ADDR1L_R
#define osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define EMAC0_IM_R
const NicDriver msp432e4EthDriver
MSP432E4 Ethernet MAC driver.
#define FALSE
Definition: os_port.h:46
#define EMAC_RDES1_RCH
#define EMAC_TDES1_TBS1
error_t msp432e4EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
error_t msp432e4EthInit(NetInterface *interface)
MSP432E4 Ethernet MAC initialization.
#define EMAC_RDES0_LS
#define EMAC0_ADDR0L_R
error_t
Error codes.
Definition: error.h:43
#define EMAC0_ADDR2L_R
void msp432e4EthIrqHandler(void)
MSP432E4 Ethernet MAC interrupt service routine.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
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 EMAC0_MMCTXIM_R
#define txBuffer
#define EMAC0_CFG_R
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
MacAddr addr
MAC address.
Definition: ethernet.h:265
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define EMAC0_ADDR3L_R
#define EMAC0_ADDR3H_R
#define NetTxAncillary
Definition: net_misc.h:36
#define EMAC0_ADDR0H_R
#define EMAC0_RXPOLLD_R
#define SMI_OPCODE_READ
Definition: nic.h:67
#define EMAC0_FLOWCTL_R
#define EMAC0_FRAMEFLTR_R
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
Enhanced TX DMA descriptor.
error_t msp432e4EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define MIN(a, b)
Definition: os_port.h:63
#define EMAC_TDES0_LS
#define rxBuffer
#define EMAC0_TXPOLLD_R
__weak_func void msp432e4EthInitGpio(NetInterface *interface)
GPIO configuration.
#define EMAC0_MMCRXIM_R
MacAddr
Definition: ethernet.h:197
#define EMAC_TDES0_TCH
#define MSP432E4_ETH_RX_BUFFER_COUNT
#define MSP432E4_ETH_IRQ_PRIORITY
#define EMAC_RDES0_FL
#define TRACE_DEBUG(...)
Definition: debug.h:119
void msp432e4EthTick(NetInterface *interface)
MSP432E4 Ethernet MAC timer handler.
uint16_t regAddr
void msp432e4EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t msp432e4EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:264
#define EMAC0_RXDLADDR_R
#define osEnterIsr()
Enhanced RX DMA descriptor.
uint16_t msp432e4EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
#define EMAC0_DMARIS_R
#define EMAC_DMABUSMOD_PR_1_1
#define EMAC_DMABUSMOD_PBL_32
#define EMAC0_MIIADDR_R
#define MSP432E4_ETH_TX_BUFFER_SIZE
#define EMAC0_MIIDATA_R
#define EMAC0_EPHYIM_R
#define EMAC_TDES0_FS
#define rxDmaDesc
void msp432e4EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define EMAC0_DMAOPMODE_R
#define EMAC0_DMAIM_R
#define EMAC0_EPHYRIS_R
#define txDmaDesc
void msp432e4EthDumpPhyReg(void)
Dump PHY registers for debugging purpose.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
void msp432e4EthDisableIrq(NetInterface *interface)
Disable interrupts.
#define MSP432E4_ETH_IRQ_PRIORITY_GROUPING
NIC driver.
Definition: nic.h:286
#define EMAC_RDES0_OWN
#define EMAC0_HASHTBLL_R
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:51
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define EMAC_RDES0_FS