tm4c129_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file tm4c129_eth_driver.c
3  * @brief Tiva TM4C129 Ethernet controller
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL NIC_TRACE_LEVEL
31 
32 //TM4C1294NCPDT device?
33 #if defined(PART_TM4C1294NCPDT)
34  #include "tm4c1294ncpdt.h"
35 //TM4C129XNCZAD device?
36 #elif defined(PART_TM4C129XNCZAD)
37  #include "tm4c129xnczad.h"
38 #endif
39 
40 //Dependencies
41 #include <stdint.h>
42 #include <stdbool.h>
43 #include "inc/hw_emac.h"
44 #include "inc/hw_memmap.h"
45 #include "inc/hw_types.h"
46 #include "driverlib/gpio.h"
47 #include "driverlib/interrupt.h"
48 #include "driverlib/pin_map.h"
49 #include "driverlib/sysctl.h"
50 #include "core/net.h"
52 #include "debug.h"
53 
54 //Underlying network interface
55 static NetInterface *nicDriverInterface;
56 
57 //IAR EWARM compiler?
58 #if defined(__ICCARM__)
59 
60 //Transmit buffer
61 #pragma data_alignment = 4
63 //Receive buffer
64 #pragma data_alignment = 4
66 //Transmit DMA descriptors
67 #pragma data_alignment = 4
69 //Receive DMA descriptors
70 #pragma data_alignment = 4
72 
73 //Keil MDK-ARM or GCC compiler?
74 #else
75 
76 //Transmit buffer
78  __attribute__((aligned(4)));
79 //Receive buffer
81  __attribute__((aligned(4)));
82 //Transmit DMA descriptors
84  __attribute__((aligned(4)));
85 //Receive DMA descriptors
87  __attribute__((aligned(4)));
88 
89 #endif
90 
91 //Pointer to the current TX DMA descriptor
92 static Tm4c129TxDmaDesc *txCurDmaDesc;
93 //Pointer to the current RX DMA descriptor
94 static Tm4c129RxDmaDesc *rxCurDmaDesc;
95 
96 
97 /**
98  * @brief Tiva TM4C129 Ethernet MAC driver
99  **/
100 
102 {
104  ETH_MTU,
112  NULL,
113  NULL,
114  NULL,
115  TRUE,
116  TRUE,
117  TRUE,
118  FALSE
119 };
120 
121 
122 /**
123  * @brief Tiva TM4C129 Ethernet MAC initialization
124  * @param[in] interface Underlying network interface
125  * @return Error code
126  **/
127 
129 {
130  //Debug message
131  TRACE_INFO("Initializing Tiva TM4C129 Ethernet controller...\r\n");
132 
133  //Save underlying network interface
134  nicDriverInterface = interface;
135 
136  //Enable Ethernet controller clock
137  SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
138  //Reset Ethernet controller
139  SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
140  //Wait for the reset to complete
141  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0));
142 
143  //Enable internal PHY clock
144  SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
145  //Reset internal PHY
146  SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
147  //Wait for the reset to complete
148  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0));
149 
150  //GPIO configuration
151  tm4c129EthInitGpio(interface);
152 
153  //Perform a software reset
154  EMAC0_DMABUSMOD_R |= EMAC_DMABUSMOD_SWR;
155  //Wait for the reset to complete
156  while(EMAC0_DMABUSMOD_R & EMAC_DMABUSMOD_SWR);
157 
158  //Adjust MDC clock range depending on SYSCLK frequency
159  EMAC0_MIIADDR_R = EMAC_MIIADDR_CR_100_150;
160 
161  //Reset PHY transceiver
162  tm4c129EthWritePhyReg(EPHY_BMCR, EPHY_BMCR_MIIRESET);
163  //Wait for the reset to complete
164  while(tm4c129EthReadPhyReg(EPHY_BMCR) & EPHY_BMCR_MIIRESET);
165 
166  //Dump PHY registers for debugging purpose
168 
169  //Configure LED0, LED1 and LED2
170  tm4c129EthWritePhyReg(EPHY_LEDCFG, EPHY_LEDCFG_LED0_TX |
171  EPHY_LEDCFG_LED1_RX | EPHY_LEDCFG_LED2_LINK);
172 
173  //Configure PHY interrupts as desired
174  tm4c129EthWritePhyReg(EPHY_MISR1, EPHY_MISR1_LINKSTATEN);
175  //Enable PHY interrupts
176  tm4c129EthWritePhyReg(EPHY_SCR, EPHY_SCR_INTEN);
177 
178  //Use default MAC configuration
179  EMAC0_CFG_R = EMAC_CFG_DRO;
180 
181  //Set the MAC address
182  EMAC0_ADDR0L_R = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
183  EMAC0_ADDR0H_R = interface->macAddr.w[2];
184 
185  //Initialize hash table
186  EMAC0_HASHTBLL_R = 0;
187  EMAC0_HASHTBLH_R = 0;
188 
189  //Configure the receive filter
190  EMAC0_FRAMEFLTR_R = EMAC_FRAMEFLTR_HPF | EMAC_FRAMEFLTR_HMC;
191  //Disable flow control
192  EMAC0_FLOWCTL_R = 0;
193  //Enable store and forward mode
194  EMAC0_DMAOPMODE_R = EMAC_DMAOPMODE_RSF | EMAC_DMAOPMODE_TSF;
195 
196  //Configure DMA bus mode
197  EMAC0_DMABUSMOD_R = EMAC_DMABUSMOD_AAL | EMAC_DMABUSMOD_USP | EMAC_DMABUSMOD_RPBL_1 |
198  EMAC_DMABUSMOD_PR_1_1 | EMAC_DMABUSMOD_PBL_1 | EMAC_DMABUSMOD_ATDS;
199 
200  //Initialize DMA descriptor lists
201  tm4c129EthInitDmaDesc(interface);
202 
203  //Prevent interrupts from being generated when the transmit statistic
204  //counters reach half their maximum value
205  EMAC0_MMCTXIM_R = EMAC_MMCTXIM_OCTCNT | EMAC_MMCTXIM_MCOLLGF |
206  EMAC_MMCTXIM_SCOLLGF | EMAC_MMCTXIM_GBF;
207 
208  //Prevent interrupts from being generated when the receive statistic
209  //counters reach half their maximum value
210  EMAC0_MMCRXIM_R = EMAC_MMCRXIM_UCGF | EMAC_MMCRXIM_ALGNERR |
211  EMAC_MMCRXIM_CRCERR | EMAC_MMCRXIM_GBF;
212 
213  //Disable MAC interrupts
214  EMAC0_IM_R = EMAC_IM_TSI | EMAC_IM_PMT;
215  //Enable the desired DMA interrupts
216  EMAC0_DMAIM_R = EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
217  //Enable PHY interrupts
218  EMAC0_EPHYIM_R = EMAC_EPHYIM_INT;
219 
220  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
221  IntPriorityGroupingSet(TM4C129_ETH_IRQ_PRIORITY_GROUPING);
222  //Configure Ethernet interrupt priority
223  IntPrioritySet(INT_EMAC0, TM4C129_ETH_IRQ_PRIORITY);
224 
225  //Enable MAC transmission and reception
226  EMAC0_CFG_R |= EMAC_CFG_TE | EMAC_CFG_RE;
227  //Enable DMA transmission and reception
228  EMAC0_DMAOPMODE_R |= EMAC_DMAOPMODE_ST | EMAC_DMAOPMODE_SR;
229 
230  //Accept any packets from the upper layer
231  osSetEvent(&interface->nicTxEvent);
232 
233  //Successful initialization
234  return NO_ERROR;
235 }
236 
237 
238 //DK-TM4C129X or EK-TM4C1294XL evaluation board?
239 #if defined(USE_DK_TM4C129X) || defined(USE_EK_TM4C1294XL)
240 
241 /**
242  * @brief GPIO configuration
243  * @param[in] interface Underlying network interface
244  **/
245 
246 void tm4c129EthInitGpio(NetInterface *interface)
247 {
248 //DK-TM4C129X evaluation board?
249 #if defined(USE_DK_TM4C129X)
250  //Enable GPIO clocks
251  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
252  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
253 
254  //Select the relevant alternate function for PF1, PK4 and PK6
255  GPIOPinConfigure(GPIO_PF1_EN0LED2);
256  GPIOPinConfigure(GPIO_PK4_EN0LED0);
257  GPIOPinConfigure(GPIO_PK6_EN0LED1);
258 
259  //Configure Ethernet LED pins for proper operation
260  GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_1);
261  GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_4 | GPIO_PIN_6);
262 
263 //EK-TM4C1294XL evaluation board?
264 #elif defined(USE_EK_TM4C1294XL)
265  //Enable GPIO clock
266  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
267 
268  //Select the relevant alternate function for PF0 and PF4
269  GPIOPinConfigure(GPIO_PF0_EN0LED0);
270  GPIOPinConfigure(GPIO_PF4_EN0LED1);
271 
272  //Configure Ethernet LED pins for proper operation
273  GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);
274 #endif
275 }
276 
277 #endif
278 
279 
280 /**
281  * @brief Initialize DMA descriptor lists
282  * @param[in] interface Underlying network interface
283  **/
284 
286 {
287  uint_t i;
288 
289  //Initialize TX DMA descriptor list
290  for(i = 0; i < TM4C129_ETH_TX_BUFFER_COUNT; i++)
291  {
292  //Use chain structure rather than ring structure
294  //Initialize transmit buffer size
295  txDmaDesc[i].tdes1 = 0;
296  //Transmit buffer address
297  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
298  //Next descriptor address
299  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
300  //Reserved fields
301  txDmaDesc[i].tdes4 = 0;
302  txDmaDesc[i].tdes5 = 0;
303  //Transmit frame time stamp
304  txDmaDesc[i].tdes6 = 0;
305  txDmaDesc[i].tdes7 = 0;
306  }
307 
308  //The last descriptor is chained to the first entry
309  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
310  //Point to the very first descriptor
311  txCurDmaDesc = &txDmaDesc[0];
312 
313  //Initialize RX DMA descriptor list
314  for(i = 0; i < TM4C129_ETH_RX_BUFFER_COUNT; i++)
315  {
316  //The descriptor is initially owned by the DMA
317  rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
318  //Use chain structure rather than ring structure
320  //Receive buffer address
321  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
322  //Next descriptor address
323  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
324  //Extended status
325  rxDmaDesc[i].rdes4 = 0;
326  //Reserved field
327  rxDmaDesc[i].rdes5 = 0;
328  //Receive frame time stamp
329  rxDmaDesc[i].rdes6 = 0;
330  rxDmaDesc[i].rdes7 = 0;
331  }
332 
333  //The last descriptor is chained to the first entry
334  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
335  //Point to the very first descriptor
336  rxCurDmaDesc = &rxDmaDesc[0];
337 
338  //Start location of the TX descriptor list
339  EMAC0_TXDLADDR_R = (uint32_t) txDmaDesc;
340  //Start location of the RX descriptor list
341  EMAC0_RXDLADDR_R = (uint32_t) rxDmaDesc;
342 }
343 
344 
345 /**
346  * @brief TM4C129 Ethernet MAC timer handler
347  *
348  * This routine is periodically called by the TCP/IP stack to
349  * handle periodic operations such as polling the link state
350  *
351  * @param[in] interface Underlying network interface
352  **/
353 
354 void tm4c129EthTick(NetInterface *interface)
355 {
356 }
357 
358 
359 /**
360  * @brief Enable interrupts
361  * @param[in] interface Underlying network interface
362  **/
363 
365 {
366  //Enable Ethernet MAC interrupts
367  IntEnable(INT_EMAC0);
368 }
369 
370 
371 /**
372  * @brief Disable interrupts
373  * @param[in] interface Underlying network interface
374  **/
375 
377 {
378  //Disable Ethernet MAC interrupts
379  IntDisable(INT_EMAC0);
380 }
381 
382 
383 /**
384  * @brief TM4C129 Ethernet MAC interrupt service routine
385  **/
386 
387 void EMAC0_Handler(void)
388 {
389  bool_t flag;
390  uint32_t status;
391 
392  //Enter interrupt service routine
393  osEnterIsr();
394 
395  //This flag will be set if a higher priority task must be woken
396  flag = FALSE;
397 
398  //Read PHY status register
399  status = EMAC0_EPHYRIS_R;
400 
401  //PHY interrupt?
402  if(status & EMAC_EPHYRIS_INT)
403  {
404  //Disable PHY interrupt
405  EMAC0_EPHYIM_R &= ~EMAC_EPHYIM_INT;
406 
407  //Set event flag
408  nicDriverInterface->nicEvent = TRUE;
409  //Notify the TCP/IP stack of the event
410  flag |= osSetEventFromIsr(&netEvent);
411  }
412 
413  //Read DMA status register
414  status = EMAC0_DMARIS_R;
415 
416  //A packet has been transmitted?
417  if(status & EMAC_DMARIS_TI)
418  {
419  //Clear TI interrupt flag
420  EMAC0_DMARIS_R = EMAC_DMARIS_TI;
421 
422  //Check whether the TX buffer is available for writing
423  if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
424  {
425  //Notify the TCP/IP stack that the transmitter is ready to send
426  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
427  }
428  }
429 
430  //A packet has been received?
431  if(status & EMAC_DMARIS_RI)
432  {
433  //Disable RIE interrupt
434  EMAC0_DMAIM_R &= ~EMAC_DMAIM_RIE;
435 
436  //Set event flag
437  nicDriverInterface->nicEvent = TRUE;
438  //Notify the TCP/IP stack of the event
439  flag |= osSetEventFromIsr(&netEvent);
440  }
441 
442  //Clear NIS interrupt flag
443  EMAC0_DMARIS_R = EMAC_DMARIS_NIS;
444 
445  //Leave interrupt service routine
446  osExitIsr(flag);
447 }
448 
449 
450 /**
451  * @brief TM4C129 Ethernet MAC event handler
452  * @param[in] interface Underlying network interface
453  **/
454 
456 {
457  error_t error;
458  uint32_t status;
459 
460  //PHY interrupt?
461  if(EMAC0_EPHYRIS_R & EMAC_EPHYRIS_INT)
462  {
463  //Clear PHY interrupt flag
464  EMAC0_EPHYMISC_R = EMAC_EPHYMISC_INT;
465  //Read PHY interrupt status register
466  status = tm4c129EthReadPhyReg(EPHY_MISR1);
467 
468  //Check whether the link state has changed?
469  if(status & EPHY_MISR1_LINKSTAT)
470  {
471  //Read BMSR register
472  status = tm4c129EthReadPhyReg(EPHY_BMSR);
473 
474  //Check whether the link is up
475  if(status & EPHY_BMSR_LINKSTAT)
476  {
477  //Read PHY status register
478  status = tm4c129EthReadPhyReg(EPHY_STS);
479 
480  //Check current speed
481  if(status & EPHY_STS_SPEED)
482  {
483  //10BASE-T operation
484  interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
485  //Update MAC configuration
486  EMAC0_CFG_R &= ~EMAC_CFG_FES;
487  }
488  else
489  {
490  //100BASE-TX operation
491  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
492  //Update MAC configuration
493  EMAC0_CFG_R |= EMAC_CFG_FES;
494  }
495 
496  //Check current duplex mode
497  if(status & EPHY_STS_DUPLEX)
498  {
499  //Full-Duplex mode
500  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
501  //Update MAC configuration
502  EMAC0_CFG_R |= EMAC_CFG_DUPM;
503  }
504  else
505  {
506  //Half-Duplex mode
507  interface->duplexMode = NIC_HALF_DUPLEX_MODE;
508  //Update MAC configuration
509  EMAC0_CFG_R &= ~EMAC_CFG_DUPM;
510  }
511 
512  //Update link state
513  interface->linkState = TRUE;
514  }
515  else
516  {
517  //Update link state
518  interface->linkState = FALSE;
519  }
520 
521  //Process link state change event
522  nicNotifyLinkChange(interface);
523  }
524  }
525 
526  //Packet received?
527  if(EMAC0_DMARIS_R & EMAC_DMARIS_RI)
528  {
529  //Clear interrupt flag
530  EMAC0_DMARIS_R = EMAC_DMARIS_RI;
531 
532  //Process all pending packets
533  do
534  {
535  //Read incoming packet
536  error = tm4c129EthReceivePacket(interface);
537 
538  //No more data in the receive buffer?
539  } while(error != ERROR_BUFFER_EMPTY);
540  }
541 
542  //Re-enable DMA interrupts
543  EMAC0_DMAIM_R |= EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
544  //Re-enable PHY interrupts
545  EMAC0_EPHYIM_R |= EMAC_EPHYIM_INT;
546 }
547 
548 
549 /**
550  * @brief Send a packet
551  * @param[in] interface Underlying network interface
552  * @param[in] buffer Multi-part buffer containing the data to send
553  * @param[in] offset Offset to the first data byte
554  * @return Error code
555  **/
556 
558  const NetBuffer *buffer, size_t offset)
559 {
560  size_t length;
561 
562  //Retrieve the length of the packet
563  length = netBufferGetLength(buffer) - offset;
564 
565  //Check the frame length
567  {
568  //The transmitter can accept another packet
569  osSetEvent(&interface->nicTxEvent);
570  //Report an error
571  return ERROR_INVALID_LENGTH;
572  }
573 
574  //Make sure the current buffer is available for writing
575  if(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN)
576  return ERROR_FAILURE;
577 
578  //Copy user data to the transmit buffer
579  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
580 
581  //Write the number of bytes to send
582  txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
583  //Set LS and FS flags as the data fits in a single buffer
584  txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
585  //Give the ownership of the descriptor to the DMA
586  txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
587 
588  //Clear TU flag to resume processing
589  EMAC0_DMARIS_R = EMAC_DMARIS_TU;
590  //Instruct the DMA to poll the transmit descriptor list
591  EMAC0_TXPOLLD_R = 0;
592 
593  //Point to the next descriptor in the list
594  txCurDmaDesc = (Tm4c129TxDmaDesc *) txCurDmaDesc->tdes3;
595 
596  //Check whether the next buffer is available for writing
597  if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
598  {
599  //The transmitter can accept another packet
600  osSetEvent(&interface->nicTxEvent);
601  }
602 
603  //Data successfully written
604  return NO_ERROR;
605 }
606 
607 
608 /**
609  * @brief Receive a packet
610  * @param[in] interface Underlying network interface
611  * @return Error code
612  **/
613 
615 {
616  error_t error;
617  size_t n;
618 
619  //The current buffer is available for reading?
620  if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN))
621  {
622  //FS and LS flags should be set
623  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) && (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS))
624  {
625  //Make sure no error occurred
626  if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_ES))
627  {
628  //Retrieve the length of the frame
629  n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
630  //Limit the number of data to read
632 
633  //Pass the packet to the upper layer
634  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
635 
636  //Valid packet received
637  error = NO_ERROR;
638  }
639  else
640  {
641  //The received packet contains an error
642  error = ERROR_INVALID_PACKET;
643  }
644  }
645  else
646  {
647  //The packet is not valid
648  error = ERROR_INVALID_PACKET;
649  }
650 
651  //Give the ownership of the descriptor back to the DMA
652  rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
653  //Point to the next descriptor in the list
654  rxCurDmaDesc = (Tm4c129RxDmaDesc *) rxCurDmaDesc->rdes3;
655  }
656  else
657  {
658  //No more data in the receive buffer
659  error = ERROR_BUFFER_EMPTY;
660  }
661 
662  //Clear RU flag to resume processing
663  EMAC0_DMARIS_R = EMAC_DMARIS_RU;
664  //Instruct the DMA to poll the receive descriptor list
665  EMAC0_RXPOLLD_R = 0;
666 
667  //Return status code
668  return error;
669 }
670 
671 
672 /**
673  * @brief Configure MAC address filtering
674  * @param[in] interface Underlying network interface
675  * @return Error code
676  **/
677 
679 {
680  uint_t i;
681  uint_t k;
682  uint32_t crc;
683  uint32_t hashTable[2];
684  MacFilterEntry *entry;
685 
686  //Debug message
687  TRACE_DEBUG("Updating Tiva TM4C129 hash table...\r\n");
688 
689  //Clear hash table
690  hashTable[0] = 0;
691  hashTable[1] = 0;
692 
693  //The MAC address filter contains the list of MAC addresses to accept
694  //when receiving an Ethernet frame
695  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
696  {
697  //Point to the current entry
698  entry = &interface->macAddrFilter[i];
699 
700  //Valid entry?
701  if(entry->refCount > 0)
702  {
703  //Compute CRC over the current MAC address
704  crc = tm4c129EthCalcCrc(&entry->addr, sizeof(MacAddr));
705 
706  //The upper 6 bits in the CRC register are used to index the
707  //contents of the hash table
708  k = (crc >> 26) & 0x3F;
709 
710  //Update hash table contents
711  hashTable[k / 32] |= (1 << (k % 32));
712  }
713  }
714 
715  //Write the hash table
716  EMAC0_HASHTBLL_R = hashTable[0];
717  EMAC0_HASHTBLH_R = hashTable[1];
718 
719  //Debug message
720  TRACE_DEBUG(" HASHTBLL = %08" PRIX32 "\r\n", EMAC0_HASHTBLL_R);
721  TRACE_DEBUG(" HASHTBLH = %08" PRIX32 "\r\n", EMAC0_HASHTBLH_R);
722 
723  //Successful processing
724  return NO_ERROR;
725 }
726 
727 
728 /**
729  * @brief Write PHY register
730  * @param[in] regAddr Register address
731  * @param[in] data Register value
732  **/
733 
734 void tm4c129EthWritePhyReg(uint8_t regAddr, uint16_t data)
735 {
736  uint32_t value;
737 
738  //Take care not to alter MDC clock configuration
739  value = EMAC0_MIIADDR_R & EMAC_MIIADDR_CR_M;
740  //Set up a write operation
741  value |= EMAC_MIIADDR_MIIW | EMAC_MIIADDR_MIIB;
742  //The address of the integrated PHY is 0
743  value |= (0 << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
744  //Register address
745  value |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
746 
747  //Data to be written in the PHY register
748  EMAC0_MIIDATA_R = data & EMAC_MIIDATA_DATA_M;
749 
750  //Start a write operation
751  EMAC0_MIIADDR_R = value;
752  //Wait for the write to complete
753  while(EMAC0_MIIADDR_R & EMAC_MIIADDR_MIIB);
754 }
755 
756 
757 /**
758  * @brief Read PHY register
759  * @param[in] regAddr Register address
760  * @return Register value
761  **/
762 
763 uint16_t tm4c129EthReadPhyReg(uint8_t regAddr)
764 {
765  uint32_t value;
766 
767  //Take care not to alter MDC clock configuration
768  value = EMAC0_MIIADDR_R & EMAC_MIIADDR_CR_M;
769  //Set up a read operation
770  value |= EMAC_MIIADDR_MIIB;
771  //The address of the integrated PHY is 0
772  value |= (0 << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
773  //Register address
774  value |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
775 
776  //Start a read operation
777  EMAC0_MIIADDR_R = value;
778  //Wait for the read to complete
779  while(EMAC0_MIIADDR_R & EMAC_MIIADDR_MIIB);
780 
781  //Return PHY register contents
782  return EMAC0_MIIDATA_R & EMAC_MIIDATA_DATA_M;
783 }
784 
785 
786 /**
787  * @brief Dump PHY registers for debugging purpose
788  **/
789 
791 {
792  uint8_t i;
793 
794  //Loop through PHY registers
795  for(i = 0; i < 32; i++)
796  {
797  //Display current PHY register
798  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, tm4c129EthReadPhyReg(i));
799  }
800 
801  //Terminate with a line feed
802  TRACE_DEBUG("\r\n");
803 }
804 
805 
806 /**
807  * @brief CRC calculation
808  * @param[in] data Pointer to the data over which to calculate the CRC
809  * @param[in] length Number of bytes to process
810  * @return Resulting CRC value
811  **/
812 
813 uint32_t tm4c129EthCalcCrc(const void *data, size_t length)
814 {
815  uint_t i;
816  uint_t j;
817 
818  //Point to the data over which to calculate the CRC
819  const uint8_t *p = (uint8_t *) data;
820  //CRC preset value
821  uint32_t crc = 0xFFFFFFFF;
822 
823  //Loop through data
824  for(i = 0; i < length; i++)
825  {
826  //The message is processed bit by bit
827  for(j = 0; j < 8; j++)
828  {
829  //Update CRC value
830  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
831  crc = (crc << 1) ^ 0x04C11DB7;
832  else
833  crc = crc << 1;
834  }
835  }
836 
837  //Return CRC value
838  return ~crc;
839 }
#define txDmaDesc
MacAddr addr
MAC address.
Definition: ethernet.h:210
void tm4c129EthTick(NetInterface *interface)
TM4C129 Ethernet MAC timer handler.
void nicNotifyLinkChange(NetInterface *interface)
Process link state change event.
Definition: nic.c:298
#define EMAC_RDES1_RCH
TCP/IP stack core.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
Generic error code.
Definition: error.h:43
error_t tm4c129EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
error_t tm4c129EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define rxDmaDesc
#define EMAC_RDES0_OWN
#define TM4C129_ETH_RX_BUFFER_COUNT
#define txBuffer
#define EMAC_TDES1_TBS1
#define EMAC_DMABUSMOD_PBL_1
#define TM4C129_ETH_TX_BUFFER_SIZE
#define EMAC_DMABUSMOD_PR_1_1
#define EMAC_RDES0_LS
void tm4c129EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define TRUE
Definition: os_port.h:48
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
void tm4c129EthEventHandler(NetInterface *interface)
TM4C129 Ethernet MAC event handler.
#define TM4C129_ETH_TX_BUFFER_COUNT
void tm4c129EthInitGpio(NetInterface *interface)
void tm4c129EthWritePhyReg(uint8_t regAddr, uint16_t data)
Write PHY register.
void tm4c129EthDumpPhyReg(void)
Dump PHY registers for debugging purpose.
void tm4c129EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define EMAC_RDES0_ES
#define EMAC_RDES1_RBS1
Tiva TM4C129 Ethernet controller.
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:670
NIC driver.
Definition: nic.h:161
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
#define MIN(a, b)
Definition: os_port.h:60
#define EMAC_TDES0_OWN
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
error_t tm4c129EthInit(NetInterface *interface)
Tiva TM4C129 Ethernet MAC initialization.
const NicDriver tm4c129EthDriver
Tiva TM4C129 Ethernet MAC driver.
#define TRACE_INFO(...)
Definition: debug.h:86
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:82
Ethernet interface.
Definition: nic.h:69
Success.
Definition: error.h:42
#define rxBuffer
OsEvent netEvent
Definition: net.c:72
#define EMAC_RDES0_FL
void nicProcessPacket(NetInterface *interface, void *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:239
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:211
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
#define EMAC_RDES0_FS
#define EMAC_TDES0_FS
__start_packed struct @112 MacAddr
MAC address.
#define EMAC_DMABUSMOD_RPBL_1
uint8_t data[]
Definition: dtls_misc.h:167
#define TM4C129_ETH_RX_BUFFER_SIZE
#define NetInterface
Definition: net.h:34
Enhanced RX DMA descriptor.
void tm4c129EthDisableIrq(NetInterface *interface)
Disable interrupts.
uint8_t value[]
Definition: dtls_misc.h:141
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
#define EMAC_TDES0_TCH
#define osExitIsr(flag)
#define EMAC_TDES0_LS
#define osEnterIsr()
#define EMAC_TDES0_IC
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
uint16_t tm4c129EthReadPhyReg(uint8_t regAddr)
Read PHY register.
Enhanced TX DMA descriptor.
uint32_t tm4c129EthCalcCrc(const void *data, size_t length)
CRC calculation.
#define FALSE
Definition: os_port.h:44
error_t tm4c129EthReceivePacket(NetInterface *interface)
Receive a packet.
int bool_t
Definition: compiler_port.h:47
#define TM4C129_ETH_IRQ_PRIORITY_GROUPING
void EMAC0_Handler(void)
TM4C129 Ethernet MAC interrupt service routine.
MAC filter table entry.
Definition: ethernet.h:208
#define TRACE_DEBUG(...)
Definition: debug.h:98
#define TM4C129_ETH_IRQ_PRIORITY