pic32ck_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file pic32ck_eth_driver.c
3  * @brief PIC32CK GC01/SG01 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 <limits.h>
36 #include "pic32c.h"
37 #include "core/net.h"
39 #include "debug.h"
40 
41 //Underlying network interface
42 static NetInterface *nicDriverInterface;
43 
44 //IAR EWARM compiler?
45 #if defined(__ICCARM__)
46 
47 //TX buffer
48 #pragma data_alignment = 8
50 //RX buffer
51 #pragma data_alignment = 8
53 //TX buffer descriptors
54 #pragma data_alignment = 8
56 //RX buffer descriptors
57 #pragma data_alignment = 8
59 
60 //Keil MDK-ARM or GCC compiler?
61 #else
62 
63 //TX buffer
65  __attribute__((aligned(8)));
66 //RX buffer
68  __attribute__((aligned(8)));
69 //TX buffer descriptors
71  __attribute__((aligned(8)));
72 //RX buffer descriptors
74  __attribute__((aligned(8)));
75 
76 #endif
77 
78 //TX buffer index
79 static uint_t txBufferIndex;
80 //RX buffer index
81 static uint_t rxBufferIndex;
82 
83 
84 /**
85  * @brief PIC32CK Ethernet MAC driver
86  **/
87 
89 {
91  ETH_MTU,
102  TRUE,
103  TRUE,
104  TRUE,
105  FALSE
106 };
107 
108 
109 /**
110  * @brief PIC32CK Ethernet MAC initialization
111  * @param[in] interface Underlying network interface
112  * @return Error code
113  **/
114 
116 {
117  error_t error;
118  volatile uint32_t status;
119 
120  //Debug message
121  TRACE_INFO("Initializing PIC32CK Ethernet MAC...\r\n");
122 
123  //Save underlying network interface
124  nicDriverInterface = interface;
125 
126  //Enable CLK_ETH_TX core clock
127  GCLK_REGS->GCLK_PCHCTRL[ETH_GCLK_ID_TX] = GCLK_PCHCTRL_GEN_GCLK0 |
128  GCLK_PCHCTRL_CHEN_Msk;
129 
130  //Wait for synchronization
131  while((GCLK_REGS->GCLK_PCHCTRL[ETH_GCLK_ID_TX] & GCLK_PCHCTRL_CHEN_Msk) == 0)
132  {
133  }
134 
135  //Enable CLK_ETH_TSU core clock
136  GCLK_REGS->GCLK_PCHCTRL[ETH_GCLK_ID_TSU] = GCLK_PCHCTRL_GEN_GCLK0 |
137  GCLK_PCHCTRL_CHEN_Msk;
138 
139  //Wait for synchronization
140  while((GCLK_REGS->GCLK_PCHCTRL[ETH_GCLK_ID_TSU] & GCLK_PCHCTRL_CHEN_Msk) == 0)
141  {
142  }
143 
144  //Enable ETH bus clocks (CLK_ETH_APB and CLK_ETH_AHB)
145  MCLK_REGS->MCLK_CLKMSK[ETH_MCLK_ID_APB / 32] |= (1U << (ETH_MCLK_ID_APB % 32));
146  MCLK_REGS->MCLK_CLKMSK[ETH_MCLK_ID_AHB / 32] |= (1U << (ETH_MCLK_ID_AHB % 32));
147 
148  //Enable ETH module
149  ETH_REGS->ETH_CTRLA = ETH_CTRLA_ENABLE_Msk;
150 
151  //Wait for synchronization
152  while(ETH_REGS->ETH_SYNCB != 0)
153  {
154  }
155 
156  //Disable transmit and receive circuits
157  ETH_REGS->ETH_NCR = 0;
158 
159  //GPIO configuration
160  pic32ckEthInitGpio(interface);
161 
162  //Configure MDC clock speed
163  ETH_REGS->ETH_NCFGR = ETH_NCFGR_DBW(1) | ETH_NCFGR_CLK(5);
164  //Enable management port (MDC and MDIO)
165  ETH_REGS->ETH_NCR |= ETH_NCR_MPE_Msk;
166 
167  //Valid Ethernet PHY or switch driver?
168  if(interface->phyDriver != NULL)
169  {
170  //Ethernet PHY initialization
171  error = interface->phyDriver->init(interface);
172  }
173  else if(interface->switchDriver != NULL)
174  {
175  //Ethernet switch initialization
176  error = interface->switchDriver->init(interface);
177  }
178  else
179  {
180  //The interface is not properly configured
181  error = ERROR_FAILURE;
182  }
183 
184  //Any error to report?
185  if(error)
186  {
187  return error;
188  }
189 
190  //Set the MAC address of the station
191  ETH_REGS->SA[0].ETH_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
192  ETH_REGS->SA[0].ETH_SAT = interface->macAddr.w[2];
193 
194  //The MAC supports 3 additional addresses for unicast perfect filtering
195  ETH_REGS->SA[1].ETH_SAB = 0;
196  ETH_REGS->SA[2].ETH_SAB = 0;
197  ETH_REGS->SA[3].ETH_SAB = 0;
198 
199  //Initialize hash table
200  ETH_REGS->ETH_HRB = 0;
201  ETH_REGS->ETH_HRT = 0;
202 
203  //Configure the receive filter
204  ETH_REGS->ETH_NCFGR |= ETH_NCFGR_MAXFS_Msk | ETH_NCFGR_MTIHEN_Msk;
205 
206  //Initialize buffer descriptors
207  pic32ckEthInitBufferDesc(interface);
208 
209  //Clear transmit status register
210  ETH_REGS->ETH_TSR = ETH_TSR_HRESP_Msk | ETH_TSR_UND_Msk |
211  ETH_TSR_TXCOMP_Msk | ETH_TSR_TFC_Msk | ETH_TSR_TXGO_Msk |
212  ETH_TSR_RLE_Msk | ETH_TSR_COL_Msk | ETH_TSR_UBR_Msk;
213 
214  //Clear receive status register
215  ETH_REGS->ETH_RSR = ETH_RSR_HNO_Msk | ETH_RSR_RXOVR_Msk |
216  ETH_RSR_REC_Msk | ETH_RSR_BNA_Msk;
217 
218  //First disable all ETH interrupts
219  ETH_REGS->ETH_IDR = 0xFFFFFFFF;
220 
221  //Only the desired ones are enabled
222  ETH_REGS->ETH_IER = ETH_IER_HRESP_Msk | ETH_IER_ROVR_Msk |
223  ETH_IER_TCOMP_Msk | ETH_IER_TFC_Msk | ETH_IER_RLEX_Msk |
224  ETH_IER_TUR_Msk | ETH_IER_RXUBR_Msk | ETH_IER_RCOMP_Msk;
225 
226  //Read ETH_ISR register to clear any pending interrupt
227  status = ETH_REGS->ETH_ISR;
228  (void) status;
229 
230  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
231  NVIC_SetPriorityGrouping(PIC32CK_ETH_IRQ_PRIORITY_GROUPING);
232 
233  //Configure ETH interrupt priority
234  NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(PIC32CK_ETH_IRQ_PRIORITY_GROUPING,
236 
237  //Enable the ETH to transmit and receive data
238  ETH_REGS->ETH_NCR |= ETH_NCR_TXEN_Msk | ETH_NCR_RXEN_Msk;
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 /**
249  * @brief GPIO configuration
250  * @param[in] interface Underlying network interface
251  **/
252 
253 __weak_func void pic32ckEthInitGpio(NetInterface *interface)
254 {
255 //PIC32CK GC01/SG01 Curiosity Ultra evaluation board?
256 #if defined(USE_PIC32CK_GC01_CURIOSITY_ULTRA) || \
257  defined(USE_PIC32CK_SG01_CURIOSITY_ULTRA)
258  uint32_t temp;
259 
260  //Enable PORT bus clock (CLK_PORT_APB)
261  MCLK_REGS->MCLK_CLKMSK[PORT_MCLK_ID_APB / 32] |= (1U << (PORT_MCLK_ID_APB % 32));
262 
263  //Configure ETH_REF_CLK (PC0)
264  PORT_REGS->GROUP[2].PORT_PINCFG[0] |= PORT_PINCFG_PMUXEN_Msk;
265  temp = PORT_REGS->GROUP[2].PORT_PMUX[0] & ~PORT_PMUX_PMUXE_Msk;
266  PORT_REGS->GROUP[2].PORT_PMUX[0] = temp | PORT_PMUX_PMUXE(MUX_PC00L_ETH_REF_CLK);
267 
268  //Configure ETH_MDC (PC3)
269  PORT_REGS->GROUP[2].PORT_PINCFG[3] |= PORT_PINCFG_PMUXEN_Msk;
270  temp = PORT_REGS->GROUP[2].PORT_PMUX[1] & ~PORT_PMUX_PMUXO_Msk;
271  PORT_REGS->GROUP[2].PORT_PMUX[1] = temp | PORT_PMUX_PMUXO(MUX_PC03L_ETH_MDC);
272 
273  //Configure ETH_MDIO (PC4)
274  PORT_REGS->GROUP[2].PORT_PINCFG[4] |= PORT_PINCFG_PMUXEN_Msk;
275  temp = PORT_REGS->GROUP[2].PORT_PMUX[2] & ~PORT_PMUX_PMUXE_Msk;
276  PORT_REGS->GROUP[2].PORT_PMUX[2] = temp | PORT_PMUX_PMUXE(MUX_PC04L_ETH_MDIO);
277 
278  //Configure ETH_RXD1 (PC6)
279  PORT_REGS->GROUP[2].PORT_PINCFG[6] |= PORT_PINCFG_PMUXEN_Msk;
280  temp = PORT_REGS->GROUP[2].PORT_PMUX[3] & ~PORT_PMUX_PMUXE_Msk;
281  PORT_REGS->GROUP[2].PORT_PMUX[3] = temp | PORT_PMUX_PMUXE(MUX_PC06L_ETH_RXD1);
282 
283  //Configure ETH_RXD0 (PC7)
284  PORT_REGS->GROUP[2].PORT_PINCFG[7] |= PORT_PINCFG_PMUXEN_Msk;
285  temp = PORT_REGS->GROUP[2].PORT_PMUX[3] & ~PORT_PMUX_PMUXO_Msk;
286  PORT_REGS->GROUP[2].PORT_PMUX[3] = temp | PORT_PMUX_PMUXO(MUX_PC07L_ETH_RXD0);
287 
288  //Configure ETH_RXER (PC9)
289  PORT_REGS->GROUP[2].PORT_PINCFG[9] |= PORT_PINCFG_PMUXEN_Msk;
290  temp = PORT_REGS->GROUP[2].PORT_PMUX[4] & ~PORT_PMUX_PMUXO_Msk;
291  PORT_REGS->GROUP[2].PORT_PMUX[4] = temp | PORT_PMUX_PMUXO(MUX_PC09L_ETH_RXER);
292 
293  //Configure ETH_RXDV (PC10)
294  PORT_REGS->GROUP[2].PORT_PINCFG[10] |= PORT_PINCFG_PMUXEN_Msk;
295  temp = PORT_REGS->GROUP[2].PORT_PMUX[5] & ~PORT_PMUX_PMUXE_Msk;
296  PORT_REGS->GROUP[2].PORT_PMUX[5] = temp | PORT_PMUX_PMUXE(MUX_PC10L_ETH_RXDV);
297 
298  //Configure ETH_TXEN (PC11)
299  PORT_REGS->GROUP[2].PORT_PINCFG[11] |= PORT_PINCFG_PMUXEN_Msk;
300  temp = PORT_REGS->GROUP[2].PORT_PMUX[5] & ~PORT_PMUX_PMUXO_Msk;
301  PORT_REGS->GROUP[2].PORT_PMUX[5] = temp | PORT_PMUX_PMUXO(MUX_PC11L_ETH_TXEN);
302 
303  //Configure ETH_TXD0 (PC12)
304  PORT_REGS->GROUP[2].PORT_PINCFG[12] |= PORT_PINCFG_PMUXEN_Msk;
305  temp = PORT_REGS->GROUP[2].PORT_PMUX[6] & ~PORT_PMUX_PMUXE_Msk;
306  PORT_REGS->GROUP[2].PORT_PMUX[6] = temp | PORT_PMUX_PMUXE(MUX_PC12L_ETH_TXD0);
307 
308  //Configure ETH_TXD1 (PC13)
309  PORT_REGS->GROUP[2].PORT_PINCFG[13] |= PORT_PINCFG_PMUXEN_Msk;
310  temp = PORT_REGS->GROUP[2].PORT_PMUX[6] & ~PORT_PMUX_PMUXO_Msk;
311  PORT_REGS->GROUP[2].PORT_PMUX[6] = temp | PORT_PMUX_PMUXO(MUX_PC13L_ETH_TXD1);
312 
313  //Select RMII operation mode
314  ETH_REGS->ETH_UR &= ~ETH_UR_MII_Msk;
315 
316  //Configure PHY_RESET (PD21) as an output
317  PORT_REGS->GROUP[3].PORT_DIRSET = PORT_PD21;
318 
319  //Reset PHY transceiver
320  PORT_REGS->GROUP[3].PORT_OUTCLR = PORT_PD21;
321  sleep(10);
322  PORT_REGS->GROUP[3].PORT_OUTSET = PORT_PD21;
323  sleep(10);
324 #endif
325 }
326 
327 
328 /**
329  * @brief Initialize buffer descriptors
330  * @param[in] interface Underlying network interface
331  **/
332 
334 {
335  uint_t i;
336  uint32_t address;
337 
338  //Initialize TX buffer descriptors
339  for(i = 0; i < PIC32CK_ETH_TX_BUFFER_COUNT; i++)
340  {
341  //Calculate the address of the current TX buffer
342  address = (uint32_t) txBuffer[i];
343  //Write the address to the descriptor entry
344  txBufferDesc[i].address = address;
345  //Initialize status field
346  txBufferDesc[i].status = ETH_TX_USED;
347  }
348 
349  //Mark the last descriptor entry with the wrap flag
350  txBufferDesc[i - 1].status |= ETH_TX_WRAP;
351  //Initialize TX buffer index
352  txBufferIndex = 0;
353 
354  //Initialize RX buffer descriptors
355  for(i = 0; i < PIC32CK_ETH_RX_BUFFER_COUNT; i++)
356  {
357  //Calculate the address of the current RX buffer
358  address = (uint32_t) rxBuffer[i];
359  //Write the address to the descriptor entry
360  rxBufferDesc[i].address = address & ETH_RX_ADDRESS;
361  //Clear status field
362  rxBufferDesc[i].status = 0;
363  }
364 
365  //Mark the last descriptor entry with the wrap flag
366  rxBufferDesc[i - 1].address |= ETH_RX_WRAP;
367  //Initialize RX buffer index
368  rxBufferIndex = 0;
369 
370  //Start location of the TX descriptor list
371  ETH_REGS->ETH_TBQB = (uint32_t) txBufferDesc;
372  //Start location of the RX descriptor list
373  ETH_REGS->ETH_RBQB = (uint32_t) rxBufferDesc;
374 }
375 
376 
377 /**
378  * @brief PIC32CK Ethernet MAC timer handler
379  *
380  * This routine is periodically called by the TCP/IP stack to handle periodic
381  * operations such as polling the link state
382  *
383  * @param[in] interface Underlying network interface
384  **/
385 
386 void pic32ckEthTick(NetInterface *interface)
387 {
388  //Valid Ethernet PHY or switch driver?
389  if(interface->phyDriver != NULL)
390  {
391  //Handle periodic operations
392  interface->phyDriver->tick(interface);
393  }
394  else if(interface->switchDriver != NULL)
395  {
396  //Handle periodic operations
397  interface->switchDriver->tick(interface);
398  }
399  else
400  {
401  //Just for sanity
402  }
403 }
404 
405 
406 /**
407  * @brief Enable interrupts
408  * @param[in] interface Underlying network interface
409  **/
410 
412 {
413  //Enable Ethernet MAC interrupts
414  NVIC_EnableIRQ(ETH_IRQn);
415 
416  //Valid Ethernet PHY or switch driver?
417  if(interface->phyDriver != NULL)
418  {
419  //Enable Ethernet PHY interrupts
420  interface->phyDriver->enableIrq(interface);
421  }
422  else if(interface->switchDriver != NULL)
423  {
424  //Enable Ethernet switch interrupts
425  interface->switchDriver->enableIrq(interface);
426  }
427  else
428  {
429  //Just for sanity
430  }
431 }
432 
433 
434 /**
435  * @brief Disable interrupts
436  * @param[in] interface Underlying network interface
437  **/
438 
440 {
441  //Disable Ethernet MAC interrupts
442  NVIC_DisableIRQ(ETH_IRQn);
443 
444  //Valid Ethernet PHY or switch driver?
445  if(interface->phyDriver != NULL)
446  {
447  //Disable Ethernet PHY interrupts
448  interface->phyDriver->disableIrq(interface);
449  }
450  else if(interface->switchDriver != NULL)
451  {
452  //Disable Ethernet switch interrupts
453  interface->switchDriver->disableIrq(interface);
454  }
455  else
456  {
457  //Just for sanity
458  }
459 }
460 
461 
462 /**
463  * @brief PIC32CK Ethernet MAC interrupt service routine
464  **/
465 
466 void ETH_Handler(void)
467 {
468  bool_t flag;
469  volatile uint32_t isr;
470  volatile uint32_t tsr;
471  volatile uint32_t rsr;
472 
473  //Interrupt service routine prologue
474  osEnterIsr();
475 
476  //This flag will be set if a higher priority task must be woken
477  flag = FALSE;
478 
479  //Each time the software reads ETH_ISR, it has to check the contents
480  //of ETH_TSR, ETH_RSR and ETH_NSR
481  isr = ETH_REGS->ETH_ISR;
482  tsr = ETH_REGS->ETH_TSR;
483  rsr = ETH_REGS->ETH_RSR;
484 
485  //Clear interrupt flags
486  ETH_REGS->ETH_ISR = isr;
487 
488  //Packet transmitted?
489  if((tsr & (ETH_TSR_HRESP_Msk | ETH_TSR_UND_Msk |
490  ETH_TSR_TXCOMP_Msk | ETH_TSR_TFC_Msk | ETH_TSR_TXGO_Msk |
491  ETH_TSR_RLE_Msk | ETH_TSR_COL_Msk | ETH_TSR_UBR_Msk)) != 0)
492  {
493  //Only clear TSR flags that are currently set
494  ETH_REGS->ETH_TSR = tsr;
495 
496  //Check whether the TX buffer is available for writing
497  if((txBufferDesc[txBufferIndex].status & ETH_TX_USED) != 0)
498  {
499  //Notify the TCP/IP stack that the transmitter is ready to send
500  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
501  }
502  }
503 
504  //Packet received?
505  if((rsr & (ETH_RSR_HNO_Msk | ETH_RSR_RXOVR_Msk | ETH_RSR_REC_Msk |
506  ETH_RSR_BNA_Msk)) != 0)
507  {
508  //Set event flag
509  nicDriverInterface->nicEvent = TRUE;
510  //Notify the TCP/IP stack of the event
511  flag |= osSetEventFromIsr(&netEvent);
512  }
513 
514  //Interrupt service routine epilogue
515  osExitIsr(flag);
516 }
517 
518 
519 /**
520  * @brief PIC32CK Ethernet MAC event handler
521  * @param[in] interface Underlying network interface
522  **/
523 
525 {
526  error_t error;
527  uint32_t rsr;
528 
529  //Read receive status
530  rsr = ETH_REGS->ETH_RSR;
531 
532  //Packet received?
533  if((rsr & (ETH_RSR_HNO_Msk | ETH_RSR_RXOVR_Msk | ETH_RSR_REC_Msk |
534  ETH_RSR_BNA_Msk)) != 0)
535  {
536  //Only clear RSR flags that are currently set
537  ETH_REGS->ETH_RSR = rsr;
538 
539  //Process all pending packets
540  do
541  {
542  //Read incoming packet
543  error = pic32ckEthReceivePacket(interface);
544 
545  //No more data in the receive buffer?
546  } while(error != ERROR_BUFFER_EMPTY);
547  }
548 }
549 
550 
551 /**
552  * @brief Send a packet
553  * @param[in] interface Underlying network interface
554  * @param[in] buffer Multi-part buffer containing the data to send
555  * @param[in] offset Offset to the first data byte
556  * @param[in] ancillary Additional options passed to the stack along with
557  * the packet
558  * @return Error code
559  **/
560 
562  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
563 {
564  size_t length;
565 
566  //Retrieve the length of the packet
567  length = netBufferGetLength(buffer) - offset;
568 
569  //Check the frame length
571  {
572  //The transmitter can accept another packet
573  osSetEvent(&interface->nicTxEvent);
574  //Report an error
575  return ERROR_INVALID_LENGTH;
576  }
577 
578  //Make sure the current buffer is available for writing
579  if((txBufferDesc[txBufferIndex].status & ETH_TX_USED) == 0)
580  {
581  return ERROR_FAILURE;
582  }
583 
584  //Copy user data to the transmit buffer
585  netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
586 
587  //Set the necessary flags in the descriptor entry
588  if(txBufferIndex < (PIC32CK_ETH_TX_BUFFER_COUNT - 1))
589  {
590  //Write the status word
591  txBufferDesc[txBufferIndex].status = ETH_TX_LAST |
592  (length & ETH_TX_LENGTH);
593 
594  //Point to the next buffer
595  txBufferIndex++;
596  }
597  else
598  {
599  //Write the status word
600  txBufferDesc[txBufferIndex].status = ETH_TX_WRAP | ETH_TX_LAST |
601  (length & ETH_TX_LENGTH);
602 
603  //Wrap around
604  txBufferIndex = 0;
605  }
606 
607  //Data synchronization barrier
608  __DSB();
609 
610  //Set the TSTART bit to initiate transmission
611  ETH_REGS->ETH_NCR |= ETH_NCR_TSTART_Msk;
612 
613  //Check whether the next buffer is available for writing
614  if((txBufferDesc[txBufferIndex].status & ETH_TX_USED) != 0)
615  {
616  //The transmitter can accept another packet
617  osSetEvent(&interface->nicTxEvent);
618  }
619 
620  //Successful processing
621  return NO_ERROR;
622 }
623 
624 
625 /**
626  * @brief Receive a packet
627  * @param[in] interface Underlying network interface
628  * @return Error code
629  **/
630 
632 {
633  static uint32_t temp[ETH_MAX_FRAME_SIZE / 4];
634  error_t error;
635  uint_t i;
636  uint_t j;
637  uint_t sofIndex;
638  uint_t eofIndex;
639  size_t n;
640  size_t size;
641  size_t length;
642 
643  //Initialize variables
644  size = 0;
645  sofIndex = UINT_MAX;
646  eofIndex = UINT_MAX;
647 
648  //Search for SOF and EOF flags
649  for(i = 0; i < PIC32CK_ETH_RX_BUFFER_COUNT; i++)
650  {
651  //Point to the current entry
652  j = rxBufferIndex + i;
653 
654  //Wrap around to the beginning of the buffer if necessary
656  {
658  }
659 
660  //No more entries to process?
661  if((rxBufferDesc[j].address & ETH_RX_OWNERSHIP) == 0)
662  {
663  //Stop processing
664  break;
665  }
666 
667  //A valid SOF has been found?
668  if((rxBufferDesc[j].status & ETH_RX_SOF) != 0)
669  {
670  //Save the position of the SOF
671  sofIndex = i;
672  }
673 
674  //A valid EOF has been found?
675  if((rxBufferDesc[j].status & ETH_RX_EOF) != 0 && sofIndex != UINT_MAX)
676  {
677  //Save the position of the EOF
678  eofIndex = i;
679  //Retrieve the length of the frame
680  size = rxBufferDesc[j].status & ETH_RX_LENGTH;
681  //Limit the number of data to read
682  size = MIN(size, ETH_MAX_FRAME_SIZE);
683  //Stop processing since we have reached the end of the frame
684  break;
685  }
686  }
687 
688  //Determine the number of entries to process
689  if(eofIndex != UINT_MAX)
690  {
691  j = eofIndex + 1;
692  }
693  else if(sofIndex != UINT_MAX)
694  {
695  j = sofIndex;
696  }
697  else
698  {
699  j = i;
700  }
701 
702  //Total number of bytes that have been copied from the receive buffer
703  length = 0;
704 
705  //Process incoming frame
706  for(i = 0; i < j; i++)
707  {
708  //Any data to copy from current buffer?
709  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
710  {
711  //Calculate the number of bytes to read at a time
713  //Copy data from receive buffer
714  osMemcpy((uint8_t *) temp + length, rxBuffer[rxBufferIndex], n);
715  //Update byte counters
716  length += n;
717  size -= n;
718  }
719 
720  //Mark the current buffer as free
721  rxBufferDesc[rxBufferIndex].address &= ~ETH_RX_OWNERSHIP;
722 
723  //Point to the following entry
724  rxBufferIndex++;
725 
726  //Wrap around to the beginning of the buffer if necessary
727  if(rxBufferIndex >= PIC32CK_ETH_RX_BUFFER_COUNT)
728  {
729  rxBufferIndex = 0;
730  }
731  }
732 
733  //Any packet to process?
734  if(length > 0)
735  {
736  NetRxAncillary ancillary;
737 
738  //Additional options can be passed to the stack along with the packet
739  ancillary = NET_DEFAULT_RX_ANCILLARY;
740 
741  //Pass the packet to the upper layer
742  nicProcessPacket(interface, (uint8_t *) temp, length, &ancillary);
743  //Valid packet received
744  error = NO_ERROR;
745  }
746  else
747  {
748  //No more data in the receive buffer
749  error = ERROR_BUFFER_EMPTY;
750  }
751 
752  //Return status code
753  return error;
754 }
755 
756 
757 /**
758  * @brief Configure MAC address filtering
759  * @param[in] interface Underlying network interface
760  * @return Error code
761  **/
762 
764 {
765  uint_t i;
766  uint_t j;
767  uint_t k;
768  uint8_t *p;
769  uint32_t hashTable[2];
770  MacAddr unicastMacAddr[3];
771  MacFilterEntry *entry;
772 
773  //Debug message
774  TRACE_DEBUG("Updating MAC filter...\r\n");
775 
776  //Set the MAC address of the station
777  ETH_REGS->SA[0].ETH_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
778  ETH_REGS->SA[0].ETH_SAT = interface->macAddr.w[2];
779 
780  //The MAC supports 3 additional addresses for unicast perfect filtering
781  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
782  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
783  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
784 
785  //The hash table is used for multicast address filtering
786  hashTable[0] = 0;
787  hashTable[1] = 0;
788 
789  //The MAC address filter contains the list of MAC addresses to accept
790  //when receiving an Ethernet frame
791  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
792  {
793  //Point to the current entry
794  entry = &interface->macAddrFilter[i];
795 
796  //Valid entry?
797  if(entry->refCount > 0)
798  {
799  //Multicast address?
800  if(macIsMulticastAddr(&entry->addr))
801  {
802  //Point to the MAC address
803  p = entry->addr.b;
804 
805  //Apply the hash function
806  k = (p[0] >> 6) ^ p[0];
807  k ^= (p[1] >> 4) ^ (p[1] << 2);
808  k ^= (p[2] >> 2) ^ (p[2] << 4);
809  k ^= (p[3] >> 6) ^ p[3];
810  k ^= (p[4] >> 4) ^ (p[4] << 2);
811  k ^= (p[5] >> 2) ^ (p[5] << 4);
812 
813  //The hash value is reduced to a 6-bit index
814  k &= 0x3F;
815 
816  //Update hash table contents
817  hashTable[k / 32] |= (1 << (k % 32));
818  }
819  else
820  {
821  //Up to 3 additional MAC addresses can be specified
822  if(j < 3)
823  {
824  //Save the unicast address
825  unicastMacAddr[j++] = entry->addr;
826  }
827  }
828  }
829  }
830 
831  //Configure the first unicast address filter
832  if(j >= 1)
833  {
834  //The address is activated when SAT register is written
835  ETH_REGS->SA[1].ETH_SAB = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
836  ETH_REGS->SA[1].ETH_SAT = unicastMacAddr[0].w[2];
837  }
838  else
839  {
840  //The address is deactivated when SAB register is written
841  ETH_REGS->SA[1].ETH_SAB = 0;
842  }
843 
844  //Configure the second unicast address filter
845  if(j >= 2)
846  {
847  //The address is activated when SAT register is written
848  ETH_REGS->SA[2].ETH_SAB = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
849  ETH_REGS->SA[2].ETH_SAT = unicastMacAddr[1].w[2];
850  }
851  else
852  {
853  //The address is deactivated when SAB register is written
854  ETH_REGS->SA[2].ETH_SAB = 0;
855  }
856 
857  //Configure the third unicast address filter
858  if(j >= 3)
859  {
860  //The address is activated when SAT register is written
861  ETH_REGS->SA[3].ETH_SAB = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
862  ETH_REGS->SA[3].ETH_SAT = unicastMacAddr[2].w[2];
863  }
864  else
865  {
866  //The address is deactivated when SAB register is written
867  ETH_REGS->SA[3].ETH_SAB = 0;
868  }
869 
870  //Configure the multicast hash table
871  ETH_REGS->ETH_HRB = hashTable[0];
872  ETH_REGS->ETH_HRT = hashTable[1];
873 
874  //Debug message
875  TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", ETH_REGS->ETH_HRB);
876  TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", ETH_REGS->ETH_HRT);
877 
878  //Successful processing
879  return NO_ERROR;
880 }
881 
882 
883 /**
884  * @brief Adjust MAC configuration parameters for proper operation
885  * @param[in] interface Underlying network interface
886  * @return Error code
887  **/
888 
890 {
891  uint32_t config;
892 
893  //Read network configuration register
894  config = ETH_REGS->ETH_NCFGR;
895 
896  //10BASE-T or 100BASE-TX operation mode?
897  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
898  {
899  config |= ETH_NCFGR_SPD_Msk;
900  }
901  else
902  {
903  config &= ~ETH_NCFGR_SPD_Msk;
904  }
905 
906  //Half-duplex or full-duplex mode?
907  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
908  {
909  config |= ETH_NCFGR_FD_Msk;
910  }
911  else
912  {
913  config &= ~ETH_NCFGR_FD_Msk;
914  }
915 
916  //Write configuration value back to NCFGR register
917  ETH_REGS->ETH_NCFGR = config;
918 
919  //Successful processing
920  return NO_ERROR;
921 }
922 
923 
924 /**
925  * @brief Write PHY register
926  * @param[in] opcode Access type (2 bits)
927  * @param[in] phyAddr PHY address (5 bits)
928  * @param[in] regAddr Register address (5 bits)
929  * @param[in] data Register value
930  **/
931 
932 void pic32ckEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
933  uint8_t regAddr, uint16_t data)
934 {
935  uint32_t temp;
936 
937  //Valid opcode?
938  if(opcode == SMI_OPCODE_WRITE)
939  {
940  //Set up a write operation
941  temp = ETH_MAN_CLTTO_Msk | ETH_MAN_OP(1) | ETH_MAN_WTN(2);
942  //PHY address
943  temp |= ETH_MAN_PHYA(phyAddr);
944  //Register address
945  temp |= ETH_MAN_REGA(regAddr);
946  //Register value
947  temp |= ETH_MAN_DATA(data);
948 
949  //Start a write operation
950  ETH_REGS->ETH_MAN = temp;
951  //Wait for the write to complete
952  while((ETH_REGS->ETH_NSR & ETH_NSR_IDLE_Msk) == 0)
953  {
954  }
955  }
956  else
957  {
958  //The MAC peripheral only supports standard Clause 22 opcodes
959  }
960 }
961 
962 
963 /**
964  * @brief Read PHY register
965  * @param[in] opcode Access type (2 bits)
966  * @param[in] phyAddr PHY address (5 bits)
967  * @param[in] regAddr Register address (5 bits)
968  * @return Register value
969  **/
970 
971 uint16_t pic32ckEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
972  uint8_t regAddr)
973 {
974  uint16_t data;
975  uint32_t temp;
976 
977  //Valid opcode?
978  if(opcode == SMI_OPCODE_READ)
979  {
980  //Set up a read operation
981  temp = ETH_MAN_CLTTO_Msk | ETH_MAN_OP(2) | ETH_MAN_WTN(2);
982  //PHY address
983  temp |= ETH_MAN_PHYA(phyAddr);
984  //Register address
985  temp |= ETH_MAN_REGA(regAddr);
986 
987  //Start a read operation
988  ETH_REGS->ETH_MAN = temp;
989  //Wait for the read to complete
990  while((ETH_REGS->ETH_NSR & ETH_NSR_IDLE_Msk) == 0)
991  {
992  }
993 
994  //Get register value
995  data = ETH_REGS->ETH_MAN & ETH_MAN_DATA_Msk;
996  }
997  else
998  {
999  //The MAC peripheral only supports standard Clause 22 opcodes
1000  data = 0;
1001  }
1002 
1003  //Return the value of the PHY register
1004  return data;
1005 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:53
#define netEvent
Definition: net_legacy.h:196
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define ETH_RX_WRAP
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
uint16_t pic32ckEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
uint8_t p
Definition: ndp.h:300
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 ETH_MAX_FRAME_SIZE
Definition: ethernet.h:110
PIC32CK GC01/SG01 Ethernet MAC driver.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
error_t pic32ckEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define PIC32CK_ETH_RX_BUFFER_COUNT
void pic32ckEthDisableIrq(NetInterface *interface)
Disable interrupts.
error_t pic32ckEthInit(NetInterface *interface)
PIC32CK Ethernet MAC initialization.
const NicDriver pic32ckEthDriver
PIC32CK Ethernet MAC driver.
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)
void ETH_Handler(void)
PIC32CK Ethernet MAC interrupt service routine.
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define PIC32CK_ETH_IRQ_SUB_PRIORITY
error_t pic32ckEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define ETH_RX_OWNERSHIP
#define PIC32CK_ETH_TX_BUFFER_COUNT
#define PIC32CK_ETH_RX_BUFFER_SIZE
#define FALSE
Definition: os_port.h:46
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
#define ETH_TX_WRAP
#define PIC32CK_ETH_IRQ_PRIORITY_GROUPING
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define ETH_UR_MII_Msk
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:263
void pic32ckEthEventHandler(NetInterface *interface)
PIC32CK Ethernet MAC event handler.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
__weak_func void pic32ckEthInitGpio(NetInterface *interface)
GPIO configuration.
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
void pic32ckEthEnableIrq(NetInterface *interface)
Enable interrupts.
#define NetTxAncillary
Definition: net_misc.h:36
#define PIC32CK_ETH_TX_BUFFER_SIZE
#define SMI_OPCODE_READ
Definition: nic.h:67
Receive buffer descriptor.
void pic32ckEthTick(NetInterface *interface)
PIC32CK Ethernet MAC timer handler.
#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 MIN(a, b)
Definition: os_port.h:63
#define rxBuffer
MacAddr
Definition: ethernet.h:195
#define ETH_TX_USED
Transmit buffer descriptor.
void pic32ckEthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define ETH_RX_SOF
uint16_t regAddr
error_t pic32ckEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:262
Ipv6Addr address[]
Definition: ipv6.h:325
#define ETH_TX_LENGTH
#define osEnterIsr()
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define PIC32CK_ETH_IRQ_GROUP_PRIORITY
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
#define ETH_RX_ADDRESS
void pic32ckEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
NIC driver.
Definition: nic.h:286
#define ETH_TX_LAST
error_t pic32ckEthReceivePacket(NetInterface *interface)
Receive a packet.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define ETH_RX_EOF
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define ETH_RX_LENGTH