pic32cz_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file pic32cz_eth_driver.c
3  * @brief PIC32CZ CA70/CA80/CA90 Gigabit Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.0
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
49 #pragma location = PIC32CZ_ETH_RAM_SECTION
51 //RX buffer
52 #pragma data_alignment = 8
53 #pragma location = PIC32CZ_ETH_RAM_SECTION
55 //TX buffer descriptors
56 #pragma data_alignment = 8
57 #pragma location = PIC32CZ_ETH_RAM_SECTION
59 //RX buffer descriptors
60 #pragma data_alignment = 8
61 #pragma location = PIC32CZ_ETH_RAM_SECTION
63 
64 //Dummy TX buffer
65 #pragma data_alignment = 8
66 #pragma location = PIC32CZ_ETH_RAM_SECTION
68 //Dummy RX buffer
69 #pragma data_alignment = 8
70 #pragma location = PIC32CZ_ETH_RAM_SECTION
72 //Dummy TX buffer descriptors
73 #pragma data_alignment = 8
74 #pragma location = PIC32CZ_ETH_RAM_SECTION
75 static Pic32czTxBufferDesc dummyTxBufferDesc[PIC32CZ_ETH_DUMMY_BUFFER_COUNT];
76 //Dummy RX buffer descriptors
77 #pragma data_alignment = 8
78 #pragma location = PIC32CZ_ETH_RAM_SECTION
79 static Pic32czRxBufferDesc dummyRxBufferDesc[PIC32CZ_ETH_DUMMY_BUFFER_COUNT];
80 
81 //Keil MDK-ARM or GCC compiler?
82 #else
83 
84 //TX buffer
86  __attribute__((aligned(8), __section__(PIC32CZ_ETH_RAM_SECTION)));
87 //RX buffer
89  __attribute__((aligned(8), __section__(PIC32CZ_ETH_RAM_SECTION)));
90 //TX buffer descriptors
92  __attribute__((aligned(4), __section__(PIC32CZ_ETH_RAM_SECTION)));
93 //RX buffer descriptors
95  __attribute__((aligned(4), __section__(PIC32CZ_ETH_RAM_SECTION)));
96 
97 //Dummy TX buffer
99  __attribute__((aligned(8), __section__(PIC32CZ_ETH_RAM_SECTION)));
100 //Dummy RX buffer
102  __attribute__((aligned(8), __section__(PIC32CZ_ETH_RAM_SECTION)));
103 //Dummy TX buffer descriptors
104 static Pic32czTxBufferDesc dummyTxBufferDesc[PIC32CZ_ETH_DUMMY_BUFFER_COUNT]
105  __attribute__((aligned(4), __section__(PIC32CZ_ETH_RAM_SECTION)));
106 //Dummy RX buffer descriptors
107 static Pic32czRxBufferDesc dummyRxBufferDesc[PIC32CZ_ETH_DUMMY_BUFFER_COUNT]
108  __attribute__((aligned(4), __section__(PIC32CZ_ETH_RAM_SECTION)));
109 
110 #endif
111 
112 //TX buffer index
113 static uint_t txBufferIndex;
114 //RX buffer index
115 static uint_t rxBufferIndex;
116 
117 
118 /**
119  * @brief PIC32CZ Ethernet MAC driver
120  **/
121 
123 {
125  ETH_MTU,
136  TRUE,
137  TRUE,
138  TRUE,
139  FALSE
140 };
141 
142 
143 /**
144  * @brief PIC32CZ Ethernet MAC initialization
145  * @param[in] interface Underlying network interface
146  * @return Error code
147  **/
148 
150 {
151  error_t error;
152  volatile uint32_t status;
153 
154  //Debug message
155  TRACE_INFO("Initializing PIC32CZ Ethernet MAC...\r\n");
156 
157  //Save underlying network interface
158  nicDriverInterface = interface;
159 
160 #if defined(__PIC32CZ2051CA70064__) || defined(__PIC32CZ2051CA70100__) || \
161  defined(__PIC32CZ2051CA70144__)
162  //Enable GMAC peripheral clock
163  PMC_REGS->PMC_PCER1 = (1 << (ID_GMAC - 32));
164 #else
165  //Enable CLK_GMAC_TX core clock
166  GCLK_REGS->GCLK_PCHCTRL[ETH_GCLK_ID_TX] = GCLK_PCHCTRL_GEN_GCLK2 |
167  GCLK_PCHCTRL_CHEN_Msk;
168 
169  //Wait for synchronization
170  while((GCLK_REGS->GCLK_PCHCTRL[ETH_GCLK_ID_TX] & GCLK_PCHCTRL_CHEN_Msk) == 0)
171  {
172  }
173 
174  //Enable CLK_GMAC_TSU core clock
175  GCLK_REGS->GCLK_PCHCTRL[ETH_GCLK_ID_TSU] = GCLK_PCHCTRL_GEN_GCLK2 |
176  GCLK_PCHCTRL_CHEN_Msk;
177 
178  //Wait for synchronization
179  while((GCLK_REGS->GCLK_PCHCTRL[ETH_GCLK_ID_TSU] & GCLK_PCHCTRL_CHEN_Msk) == 0)
180  {
181  }
182 
183  //Enable ETH bus clocks (CLK_GMAC_APB and CLK_GMAC_AXI)
184  MCLK_REGS->MCLK_CLKMSK[ETH_MCLK_ID_APB / 32] |= (1U << (ETH_MCLK_ID_APB % 32));
185  MCLK_REGS->MCLK_CLKMSK[ETH_MCLK_ID_AXI / 32] |= (1U << (ETH_MCLK_ID_AXI % 32));
186 
187  //Enable ETH module
188  ETH_REGS->ETH_CTRLA = ETH_CTRLA_ENABLE_Msk;
189 
190  //Wait for synchronization
191  while(ETH_REGS->ETH_SYNCB != 0)
192  {
193  }
194 #endif
195 
196  //Disable transmit and receive circuits
197  GMAC_REGS->GMAC_NCR = 0;
198 
199  //GPIO configuration
200  pic32czEthInitGpio(interface);
201 
202  //Configure MDC clock speed
203  GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_DBW(1) | GMAC_NCFGR_CLK(6);
204  //Enable management port (MDC and MDIO)
205  GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk;
206 
207  //Valid Ethernet PHY or switch driver?
208  if(interface->phyDriver != NULL)
209  {
210  //Ethernet PHY initialization
211  error = interface->phyDriver->init(interface);
212  }
213  else if(interface->switchDriver != NULL)
214  {
215  //Ethernet switch initialization
216  error = interface->switchDriver->init(interface);
217  }
218  else
219  {
220  //The interface is not properly configured
221  error = ERROR_FAILURE;
222  }
223 
224  //Any error to report?
225  if(error)
226  {
227  return error;
228  }
229 
230  //Set the MAC address of the station
231  GMAC_REGS->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
232  GMAC_REGS->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2];
233 
234  //The MAC supports 3 additional addresses for unicast perfect filtering
235  GMAC_REGS->GMAC_SA[1].GMAC_SAB = 0;
236  GMAC_REGS->GMAC_SA[2].GMAC_SAB = 0;
237  GMAC_REGS->GMAC_SA[3].GMAC_SAB = 0;
238 
239  //Initialize hash table
240  GMAC_REGS->GMAC_HRB = 0;
241  GMAC_REGS->GMAC_HRT = 0;
242 
243  //Configure the receive filter
245 
246  //DMA configuration
249 
255 
256  //Initialize buffer descriptors
257  pic32czEthInitBufferDesc(interface);
258 
259  //Clear transmit status register
263 
264  //Clear receive status register
267 
268  //First disable all GMAC interrupts
269  GMAC_REGS->GMAC_IDR = 0xFFFFFFFF;
270  GMAC_REGS->GMAC_IDRPQ[0] = 0xFFFFFFFF;
271  GMAC_REGS->GMAC_IDRPQ[1] = 0xFFFFFFFF;
272  GMAC_REGS->GMAC_IDRPQ[2] = 0xFFFFFFFF;
273  GMAC_REGS->GMAC_IDRPQ[3] = 0xFFFFFFFF;
274  GMAC_REGS->GMAC_IDRPQ[4] = 0xFFFFFFFF;
275 
276  //Only the desired ones are enabled
280 
281  //Read GMAC_ISR register to clear any pending interrupt
282  status = GMAC_REGS->GMAC_ISR;
283  status = GMAC_REGS->GMAC_ISRPQ[0];
284  status = GMAC_REGS->GMAC_ISRPQ[1];
285  status = GMAC_REGS->GMAC_ISRPQ[2];
286  status = GMAC_REGS->GMAC_ISRPQ[3];
287  status = GMAC_REGS->GMAC_ISRPQ[4];
288  (void) status;
289 
290  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
291  NVIC_SetPriorityGrouping(PIC32CZ_ETH_IRQ_PRIORITY_GROUPING);
292 
293  //Configure GMAC interrupt priority
294  NVIC_SetPriority(GMAC_IRQn, NVIC_EncodePriority(PIC32CZ_ETH_IRQ_PRIORITY_GROUPING,
296 
297  //Enable the GMAC to transmit and receive data
299 
300  //Accept any packets from the upper layer
301  osSetEvent(&interface->nicTxEvent);
302 
303  //Successful initialization
304  return NO_ERROR;
305 }
306 
307 
308 /**
309  * @brief GPIO configuration
310  * @param[in] interface Underlying network interface
311  **/
312 
313 __weak_func void pic32czEthInitGpio(NetInterface *interface)
314 {
315 //PIC32CZ CA70 Curiosity Ultra evaluation board?
316 #if defined(USE_PIC32CZ_CA70_CURIOSITY_ULTRA)
317  uint32_t mask;
318 
319  //Enable PIO peripheral clocks
320  PMC_REGS->PMC_PCER0 = (1 << ID_PIOC) | (1 << ID_PIOD);
321 
322  //Configure RMII pins
323  mask = PIO_PD9A_GMAC_GMDIO | PIO_PD8A_GMAC_GMDC |
324  PIO_PD7A_GMAC_GRXER | PIO_PD6A_GMAC_GRX1 | PIO_PD5A_GMAC_GRX0 |
325  PIO_PD4A_GMAC_GRXDV | PIO_PD3A_GMAC_GTX1 | PIO_PD2A_GMAC_GTX0 |
326  PIO_PD1A_GMAC_GTXEN | PIO_PD0A_GMAC_GTXCK;
327 
328  //Disable pull-up resistors on RMII pins
329  PIOD_REGS->PIO_PUDR = mask;
330  //Disable interrupts-on-change
331  PIOD_REGS->PIO_IDR = mask;
332  //Assign RMII pins to peripheral A function
333  PIOD_REGS->PIO_ABCDSR[0] &= ~mask;
334  PIOD_REGS->PIO_ABCDSR[1] &= ~mask;
335  //Disable the PIO from controlling the corresponding pins
336  PIOD_REGS->PIO_PDR = mask;
337 
338  //Select RMII operation mode
339  GMAC_REGS->GMAC_UR &= ~GMAC_UR_RMII_Msk;
340 
341  //Configure PHY_RESET as an output
342  PIOC_REGS->PIO_PER = PIO_PC10;
343  PIOC_REGS->PIO_OER = PIO_PC10;
344 
345  //Reset PHY transceiver
346  PIOC_REGS->PIO_CODR = PIO_PC10;
347  sleep(10);
348  PIOC_REGS->PIO_SODR = PIO_PC10;
349  sleep(10);
350 
351 //PIC32CZ CA80/CA90 Curiosity Ultra evaluation board?
352 #elif defined(USE_PIC32CZ_CA80_CURIOSITY_ULTRA) || \
353  defined(USE_PIC32CZ_CA90_CURIOSITY_ULTRA)
354  uint32_t temp;
355 
356  //Enable PORT bus clocks (CLK_PORT_APB and CLK_PORT_AHB)
357  MCLK_REGS->MCLK_CLKMSK[PORT_MCLK_ID_APB / 32] |= (1U << (PORT_MCLK_ID_APB % 32));
358  MCLK_REGS->MCLK_CLKMSK[PORT_MCLK_ID_AHB / 32] |= (1U << (PORT_MCLK_ID_AHB % 32));
359 
360  //Configure GTX1 (PA0)
361  PORT_REGS->GROUP[0].PORT_PINCFG[0] |= PORT_PINCFG_PMUXEN_Msk;
362  temp = PORT_REGS->GROUP[0].PORT_PMUX[0] & ~PORT_PMUX_PMUXE_Msk;
363  PORT_REGS->GROUP[0].PORT_PMUX[0] = temp | PORT_PMUX_PMUXE(MUX_PA00K_ETH_TXD1);
364 
365  //Configure GTX0 (PA1)
366  PORT_REGS->GROUP[0].PORT_PINCFG[1] |= PORT_PINCFG_PMUXEN_Msk;
367  temp = PORT_REGS->GROUP[0].PORT_PMUX[0] & ~PORT_PMUX_PMUXO_Msk;
368  PORT_REGS->GROUP[0].PORT_PMUX[0] = temp | PORT_PMUX_PMUXO(MUX_PA01K_ETH_TXD0);
369 
370  //Configure GTXEN (PA2)
371  PORT_REGS->GROUP[0].PORT_PINCFG[2] |= PORT_PINCFG_PMUXEN_Msk;
372  temp = PORT_REGS->GROUP[0].PORT_PMUX[1] & ~PORT_PMUX_PMUXE_Msk;
373  PORT_REGS->GROUP[0].PORT_PMUX[1] = temp | PORT_PMUX_PMUXE(MUX_PA02K_ETH_TXEN);
374 
375  //Configure GMDC (PA3)
376  PORT_REGS->GROUP[0].PORT_PINCFG[3] |= PORT_PINCFG_PMUXEN_Msk;
377  temp = PORT_REGS->GROUP[0].PORT_PMUX[1] & ~PORT_PMUX_PMUXO_Msk;
378  PORT_REGS->GROUP[0].PORT_PMUX[1] = temp | PORT_PMUX_PMUXO(MUX_PA03K_ETH_MDC);
379 
380  //Configure GMDIO (PA4)
381  PORT_REGS->GROUP[0].PORT_PINCFG[4] |= PORT_PINCFG_PMUXEN_Msk;
382  temp = PORT_REGS->GROUP[0].PORT_PMUX[2] & ~PORT_PMUX_PMUXE_Msk;
383  PORT_REGS->GROUP[0].PORT_PMUX[2] = temp | PORT_PMUX_PMUXE(MUX_PA04K_ETH_MDIO);
384 
385  //Configure GRXDV (PA5)
386  PORT_REGS->GROUP[0].PORT_PINCFG[5] |= PORT_PINCFG_PMUXEN_Msk;
387  temp = PORT_REGS->GROUP[0].PORT_PMUX[2] & ~PORT_PMUX_PMUXO_Msk;
388  PORT_REGS->GROUP[0].PORT_PMUX[2] = temp | PORT_PMUX_PMUXO(MUX_PA05K_ETH_RXDV);
389 
390  //Configure GRXER (PA6)
391  PORT_REGS->GROUP[0].PORT_PINCFG[6] |= PORT_PINCFG_PMUXEN_Msk;
392  temp = PORT_REGS->GROUP[0].PORT_PMUX[3] & ~PORT_PMUX_PMUXE_Msk;
393  PORT_REGS->GROUP[0].PORT_PMUX[3] = temp | PORT_PMUX_PMUXE(MUX_PA06K_ETH_RXER);
394 
395  //Configure TXCK (PA21)
396  PORT_REGS->GROUP[0].PORT_PINCFG[21] |= PORT_PINCFG_PMUXEN_Msk;
397  temp = PORT_REGS->GROUP[0].PORT_PMUX[10] & ~PORT_PMUX_PMUXO_Msk;
398  PORT_REGS->GROUP[0].PORT_PMUX[10] = temp | PORT_PMUX_PMUXO(MUX_PA21K_ETH_TX_CLK);
399 
400  //Configure GTXER (PD2)
401  PORT_REGS->GROUP[3].PORT_PINCFG[2] |= PORT_PINCFG_PMUXEN_Msk;
402  temp = PORT_REGS->GROUP[3].PORT_PMUX[1] & ~PORT_PMUX_PMUXE_Msk;
403  PORT_REGS->GROUP[3].PORT_PMUX[1] = temp | PORT_PMUX_PMUXE(MUX_PD02K_ETH_TXER);
404 
405  //Configure GTX3 (PD3)
406  PORT_REGS->GROUP[3].PORT_PINCFG[3] |= PORT_PINCFG_PMUXEN_Msk;
407  temp = PORT_REGS->GROUP[3].PORT_PMUX[1] & ~PORT_PMUX_PMUXO_Msk;
408  PORT_REGS->GROUP[3].PORT_PMUX[1] = temp | PORT_PMUX_PMUXO(MUX_PD03K_ETH_TXD3);
409 
410  //Configure GTX2 (PD4)
411  PORT_REGS->GROUP[3].PORT_PINCFG[4] |= PORT_PINCFG_PMUXEN_Msk;
412  temp = PORT_REGS->GROUP[3].PORT_PMUX[2] & ~PORT_PMUX_PMUXE_Msk;
413  PORT_REGS->GROUP[3].PORT_PMUX[2] = temp | PORT_PMUX_PMUXE(MUX_PD04K_ETH_TXD2);
414 
415  //Configure GTXCK (PD5)
416  PORT_REGS->GROUP[3].PORT_PINCFG[5] |= PORT_PINCFG_PMUXEN_Msk;
417  temp = PORT_REGS->GROUP[3].PORT_PMUX[2] & ~PORT_PMUX_PMUXO_Msk;
418  PORT_REGS->GROUP[3].PORT_PMUX[2] = temp | PORT_PMUX_PMUXO(MUX_PD05L_ETH_GTX_CLK);
419 
420  //Configure GRX3 (PD6)
421  PORT_REGS->GROUP[3].PORT_PINCFG[6] |= PORT_PINCFG_PMUXEN_Msk;
422  temp = PORT_REGS->GROUP[3].PORT_PMUX[3] & ~PORT_PMUX_PMUXE_Msk;
423  PORT_REGS->GROUP[3].PORT_PMUX[3] = temp | PORT_PMUX_PMUXE(MUX_PD06K_ETH_RXD3);
424 
425  //Configure GRX2 (PD7)
426  PORT_REGS->GROUP[3].PORT_PINCFG[7] |= PORT_PINCFG_PMUXEN_Msk;
427  temp = PORT_REGS->GROUP[3].PORT_PMUX[3] & ~PORT_PMUX_PMUXO_Msk;
428  PORT_REGS->GROUP[3].PORT_PMUX[3] = temp | PORT_PMUX_PMUXO(MUX_PD07K_ETH_RXD2);
429 
430  //Configure GCOL (PD8)
431  PORT_REGS->GROUP[3].PORT_PINCFG[8] |= PORT_PINCFG_PMUXEN_Msk;
432  temp = PORT_REGS->GROUP[3].PORT_PMUX[4] & ~PORT_PMUX_PMUXE_Msk;
433  PORT_REGS->GROUP[3].PORT_PMUX[4] = temp | PORT_PMUX_PMUXE(MUX_PD08K_ETH_COL);
434 
435  //Configure GCRS (PD9)
436  PORT_REGS->GROUP[3].PORT_PINCFG[9] |= PORT_PINCFG_PMUXEN_Msk;
437  temp = PORT_REGS->GROUP[3].PORT_PMUX[4] & ~PORT_PMUX_PMUXO_Msk;
438  PORT_REGS->GROUP[3].PORT_PMUX[4] = temp | PORT_PMUX_PMUXO(MUX_PD09K_ETH_CRS);
439 
440  //Configure GCOL (PD10)
441  PORT_REGS->GROUP[3].PORT_PINCFG[10] |= PORT_PINCFG_PMUXEN_Msk;
442  temp = PORT_REGS->GROUP[3].PORT_PMUX[5] & ~PORT_PMUX_PMUXE_Msk;
443  PORT_REGS->GROUP[3].PORT_PMUX[5] = temp | PORT_PMUX_PMUXE(MUX_PD10K_ETH_RXD1);
444 
445  //Configure GCRS (PD11)
446  PORT_REGS->GROUP[3].PORT_PINCFG[11] |= PORT_PINCFG_PMUXEN_Msk;
447  temp = PORT_REGS->GROUP[3].PORT_PMUX[5] & ~PORT_PMUX_PMUXO_Msk;
448  PORT_REGS->GROUP[3].PORT_PMUX[5] = temp | PORT_PMUX_PMUXO(MUX_PD11K_ETH_RXD0);
449 
450  //Configure GRXCK (PD12)
451  PORT_REGS->GROUP[3].PORT_PINCFG[12] |= PORT_PINCFG_PMUXEN_Msk;
452  temp = PORT_REGS->GROUP[3].PORT_PMUX[6] & ~PORT_PMUX_PMUXE_Msk;
453  PORT_REGS->GROUP[3].PORT_PMUX[6] = temp | PORT_PMUX_PMUXE(MUX_PD12L_ETH_RX_CLK);
454 
455  //Configure GTX7 (PD14)
456  PORT_REGS->GROUP[3].PORT_PINCFG[14] |= PORT_PINCFG_PMUXEN_Msk;
457  temp = PORT_REGS->GROUP[3].PORT_PMUX[7] & ~PORT_PMUX_PMUXE_Msk;
458  PORT_REGS->GROUP[3].PORT_PMUX[7] = temp | PORT_PMUX_PMUXE(MUX_PD14K_ETH_TXD7);
459 
460  //Configure GTX6 (PD15)
461  PORT_REGS->GROUP[3].PORT_PINCFG[15] |= PORT_PINCFG_PMUXEN_Msk;
462  temp = PORT_REGS->GROUP[3].PORT_PMUX[7] & ~PORT_PMUX_PMUXO_Msk;
463  PORT_REGS->GROUP[3].PORT_PMUX[7] = temp | PORT_PMUX_PMUXO(MUX_PD15K_ETH_TXD6);
464 
465  //Configure GTX5 (PD16)
466  PORT_REGS->GROUP[3].PORT_PINCFG[16] |= PORT_PINCFG_PMUXEN_Msk;
467  temp = PORT_REGS->GROUP[3].PORT_PMUX[8] & ~PORT_PMUX_PMUXE_Msk;
468  PORT_REGS->GROUP[3].PORT_PMUX[8] = temp | PORT_PMUX_PMUXE(MUX_PD16K_ETH_TXD5);
469 
470  //Configure GTX4 (PD17)
471  PORT_REGS->GROUP[3].PORT_PINCFG[17] |= PORT_PINCFG_PMUXEN_Msk;
472  temp = PORT_REGS->GROUP[3].PORT_PMUX[8] & ~PORT_PMUX_PMUXO_Msk;
473  PORT_REGS->GROUP[3].PORT_PMUX[8] = temp | PORT_PMUX_PMUXO(MUX_PD17K_ETH_TXD4);
474 
475  //Configure GRX7 (PD18)
476  PORT_REGS->GROUP[3].PORT_PINCFG[18] |= PORT_PINCFG_PMUXEN_Msk;
477  temp = PORT_REGS->GROUP[3].PORT_PMUX[9] & ~PORT_PMUX_PMUXE_Msk;
478  PORT_REGS->GROUP[3].PORT_PMUX[9] = temp | PORT_PMUX_PMUXE(MUX_PD18K_ETH_RXD7);
479 
480  //Configure GRX6 (PD19)
481  PORT_REGS->GROUP[3].PORT_PINCFG[19] |= PORT_PINCFG_PMUXEN_Msk;
482  temp = PORT_REGS->GROUP[3].PORT_PMUX[9] & ~PORT_PMUX_PMUXO_Msk;
483  PORT_REGS->GROUP[3].PORT_PMUX[9] = temp | PORT_PMUX_PMUXO(MUX_PD19K_ETH_RXD6);
484 
485  //Configure GRX4 (PD20)
486  PORT_REGS->GROUP[3].PORT_PINCFG[20] |= PORT_PINCFG_PMUXEN_Msk;
487  temp = PORT_REGS->GROUP[3].PORT_PMUX[10] & ~PORT_PMUX_PMUXE_Msk;
488  PORT_REGS->GROUP[3].PORT_PMUX[10] = temp | PORT_PMUX_PMUXE(MUX_PD20K_ETH_RXD4);
489 
490  //Configure GRX5 (PD21)
491  PORT_REGS->GROUP[3].PORT_PINCFG[21] |= PORT_PINCFG_PMUXEN_Msk;
492  temp = PORT_REGS->GROUP[3].PORT_PMUX[10] & ~PORT_PMUX_PMUXO_Msk;
493  PORT_REGS->GROUP[3].PORT_PMUX[10] = temp | PORT_PMUX_PMUXO(MUX_PD21K_ETH_RXD5);
494 
495  //Select GMII operation mode
496  ETH_REGS->ETH_CTRLB |= ETH_CTRLB_GMIIEN_Msk | ETH_CTRLB_GBITCLKREQ_Msk;
497 
498  //Wait for synchronization
499  while(ETH_REGS->ETH_SYNCB != 0)
500  {
501  }
502 
503  //Configure CLK125_EN strapping pin
504  PORT_REGS->GROUP[0].PORT_PINCFG[5] |= PORT_PINCFG_PULLEN_Msk;
505  PORT_REGS->GROUP[0].PORT_OUTCLR = PORT_PA05;
506 
507  //Configure MODE3 strapping pin
508  PORT_REGS->GROUP[3].PORT_PINCFG[6] |= PORT_PINCFG_PULLEN_Msk;
509  PORT_REGS->GROUP[3].PORT_OUTCLR = PORT_PD06;
510 
511  //Configure MODE2 strapping pin
512  PORT_REGS->GROUP[3].PORT_PINCFG[7] |= PORT_PINCFG_PULLEN_Msk;
513  PORT_REGS->GROUP[3].PORT_OUTCLR = PORT_PD07;
514 
515  //Configure MODE1 strapping pin
516  PORT_REGS->GROUP[3].PORT_PINCFG[10] |= PORT_PINCFG_PULLEN_Msk;
517  PORT_REGS->GROUP[3].PORT_OUTCLR = PORT_PD10;
518 
519  //Configure MODE0 strapping pin
520  PORT_REGS->GROUP[3].PORT_PINCFG[11] |= PORT_PINCFG_PULLEN_Msk;
521  PORT_REGS->GROUP[3].PORT_OUTSET = PORT_PD11;
522 
523  //Configure PHYAD2 strapping pin
524  PORT_REGS->GROUP[3].PORT_PINCFG[12] |= PORT_PINCFG_PULLEN_Msk;
525  PORT_REGS->GROUP[3].PORT_OUTSET = PORT_PD12;
526 
527  //Configure PHY_RESET (PB23) as an output
528  PORT_REGS->GROUP[1].PORT_DIRSET = PORT_PB23;
529 
530  //Reset PHY transceiver
531  PORT_REGS->GROUP[1].PORT_OUTCLR = PORT_PB23;
532  sleep(10);
533  PORT_REGS->GROUP[1].PORT_OUTSET = PORT_PB23;
534  sleep(10);
535 #endif
536 }
537 
538 
539 /**
540  * @brief Initialize buffer descriptors
541  * @param[in] interface Underlying network interface
542  **/
543 
545 {
546  uint_t i;
547  uint32_t address;
548 
549  //Initialize TX buffer descriptors
550  for(i = 0; i < PIC32CZ_ETH_TX_BUFFER_COUNT; i++)
551  {
552  //Calculate the address of the current TX buffer
553  address = (uint32_t) txBuffer[i];
554  //Write the address to the descriptor entry
555  txBufferDesc[i].address = address;
556  //Initialize status field
557  txBufferDesc[i].status = GMAC_TX_USED;
558  }
559 
560  //Mark the last descriptor entry with the wrap flag
561  txBufferDesc[i - 1].status |= GMAC_TX_WRAP;
562  //Initialize TX buffer index
563  txBufferIndex = 0;
564 
565  //Initialize RX buffer descriptors
566  for(i = 0; i < PIC32CZ_ETH_RX_BUFFER_COUNT; i++)
567  {
568  //Calculate the address of the current RX buffer
569  address = (uint32_t) rxBuffer[i];
570  //Write the address to the descriptor entry
571  rxBufferDesc[i].address = address & GMAC_RX_ADDRESS;
572  //Clear status field
573  rxBufferDesc[i].status = 0;
574  }
575 
576  //Mark the last descriptor entry with the wrap flag
577  rxBufferDesc[i - 1].address |= GMAC_RX_WRAP;
578  //Initialize RX buffer index
579  rxBufferIndex = 0;
580 
581  //Initialize dummy TX buffer descriptors
582  for(i = 0; i < PIC32CZ_ETH_DUMMY_BUFFER_COUNT; i++)
583  {
584  //Calculate the address of the current TX buffer
585  address = (uint32_t) dummyTxBuffer[i];
586  //Write the address to the descriptor entry
587  dummyTxBufferDesc[i].address = address;
588  //Initialize status field
589  dummyTxBufferDesc[i].status = GMAC_TX_USED;
590  }
591 
592  //Mark the last descriptor entry with the wrap flag
593  dummyTxBufferDesc[i - 1].status |= GMAC_TX_WRAP;
594 
595  //Initialize dummy RX buffer descriptors
596  for(i = 0; i < PIC32CZ_ETH_DUMMY_BUFFER_COUNT; i++)
597  {
598  //Calculate the address of the current RX buffer
599  address = (uint32_t) dummyRxBuffer[i];
600  //Write the address to the descriptor entry
601  dummyRxBufferDesc[i].address = (address & GMAC_RX_ADDRESS) | GMAC_RX_OWNERSHIP;
602  //Clear status field
603  dummyRxBufferDesc[i].status = 0;
604  }
605 
606  //Mark the last descriptor entry with the wrap flag
607  dummyRxBufferDesc[i - 1].address |= GMAC_RX_WRAP;
608 
609  //Start location of the TX descriptor list
610  GMAC_REGS->GMAC_TBQB = (uint32_t) txBufferDesc;
611  GMAC_REGS->GMAC_TBQBAPQ[0] = (uint32_t) dummyTxBufferDesc;
612  GMAC_REGS->GMAC_TBQBAPQ[1] = (uint32_t) dummyTxBufferDesc;
613  GMAC_REGS->GMAC_TBQBAPQ[2] = (uint32_t) dummyTxBufferDesc;
614  GMAC_REGS->GMAC_TBQBAPQ[3] = (uint32_t) dummyTxBufferDesc;
615  GMAC_REGS->GMAC_TBQBAPQ[4] = (uint32_t) dummyTxBufferDesc;
616 
617  //Start location of the RX descriptor list
618  GMAC_REGS->GMAC_RBQB = (uint32_t) rxBufferDesc;
619  GMAC_REGS->GMAC_RBQBAPQ[0] = (uint32_t) dummyRxBufferDesc;
620  GMAC_REGS->GMAC_RBQBAPQ[1] = (uint32_t) dummyRxBufferDesc;
621  GMAC_REGS->GMAC_RBQBAPQ[2] = (uint32_t) dummyRxBufferDesc;
622  GMAC_REGS->GMAC_RBQBAPQ[3] = (uint32_t) dummyRxBufferDesc;
623  GMAC_REGS->GMAC_RBQBAPQ[4] = (uint32_t) dummyRxBufferDesc;
624 }
625 
626 
627 /**
628  * @brief PIC32CZ Ethernet MAC timer handler
629  *
630  * This routine is periodically called by the TCP/IP stack to handle periodic
631  * operations such as polling the link state
632  *
633  * @param[in] interface Underlying network interface
634  **/
635 
636 void pic32czEthTick(NetInterface *interface)
637 {
638  //Valid Ethernet PHY or switch driver?
639  if(interface->phyDriver != NULL)
640  {
641  //Handle periodic operations
642  interface->phyDriver->tick(interface);
643  }
644  else if(interface->switchDriver != NULL)
645  {
646  //Handle periodic operations
647  interface->switchDriver->tick(interface);
648  }
649  else
650  {
651  //Just for sanity
652  }
653 }
654 
655 
656 /**
657  * @brief Enable interrupts
658  * @param[in] interface Underlying network interface
659  **/
660 
662 {
663  //Enable Ethernet MAC interrupts
664  NVIC_EnableIRQ(GMAC_IRQn);
665 
666  //Valid Ethernet PHY or switch driver?
667  if(interface->phyDriver != NULL)
668  {
669  //Enable Ethernet PHY interrupts
670  interface->phyDriver->enableIrq(interface);
671  }
672  else if(interface->switchDriver != NULL)
673  {
674  //Enable Ethernet switch interrupts
675  interface->switchDriver->enableIrq(interface);
676  }
677  else
678  {
679  //Just for sanity
680  }
681 }
682 
683 
684 /**
685  * @brief Disable interrupts
686  * @param[in] interface Underlying network interface
687  **/
688 
690 {
691  //Disable Ethernet MAC interrupts
692  NVIC_DisableIRQ(GMAC_IRQn);
693 
694  //Valid Ethernet PHY or switch driver?
695  if(interface->phyDriver != NULL)
696  {
697  //Disable Ethernet PHY interrupts
698  interface->phyDriver->disableIrq(interface);
699  }
700  else if(interface->switchDriver != NULL)
701  {
702  //Disable Ethernet switch interrupts
703  interface->switchDriver->disableIrq(interface);
704  }
705  else
706  {
707  //Just for sanity
708  }
709 }
710 
711 
712 /**
713  * @brief PIC32CZ Ethernet MAC interrupt service routine
714  **/
715 
716 void GMAC_Handler(void)
717 {
718  bool_t flag;
719  volatile uint32_t isr;
720  volatile uint32_t tsr;
721  volatile uint32_t rsr;
722 
723  //Interrupt service routine prologue
724  osEnterIsr();
725 
726  //This flag will be set if a higher priority task must be woken
727  flag = FALSE;
728 
729 #if defined(__PIC32CZ2051CA70064__) || defined(__PIC32CZ2051CA70100__) || \
730  defined(__PIC32CZ2051CA70144__)
731  //Each time the software reads GMAC_ISR, it has to check the contents
732  //of GMAC_TSR, GMAC_RSR and GMAC_NSR
733  isr = GMAC_REGS->GMAC_ISRPQ[0];
734  isr = GMAC_REGS->GMAC_ISRPQ[1];
735  isr = GMAC_REGS->GMAC_ISRPQ[2];
736  isr = GMAC_REGS->GMAC_ISRPQ[3];
737  isr = GMAC_REGS->GMAC_ISRPQ[4];
738  isr = GMAC_REGS->GMAC_ISR;
739  tsr = GMAC_REGS->GMAC_TSR;
740  rsr = GMAC_REGS->GMAC_RSR;
741  (void) isr;
742 #else
743  //Each time the software reads GMAC_ISR, it has to check the contents
744  //of GMAC_TSR, GMAC_RSR and GMAC_NSR
745  isr = GMAC_REGS->GMAC_ISR;
746  tsr = GMAC_REGS->GMAC_TSR;
747  rsr = GMAC_REGS->GMAC_RSR;
748 
749  //Clear interrupt flags
750  GMAC_REGS->GMAC_ISR = isr;
751 #endif
752 
753  //Packet transmitted?
754  if((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk |
757  {
758  //Only clear TSR flags that are currently set
759  GMAC_REGS->GMAC_TSR = tsr;
760 
761  //Check whether the TX buffer is available for writing
762  if((txBufferDesc[txBufferIndex].status & GMAC_TX_USED) != 0)
763  {
764  //Notify the TCP/IP stack that the transmitter is ready to send
765  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
766  }
767  }
768 
769  //Packet received?
771  GMAC_RSR_BNA_Msk)) != 0)
772  {
773  //Set event flag
774  nicDriverInterface->nicEvent = TRUE;
775  //Notify the TCP/IP stack of the event
776  flag |= osSetEventFromIsr(&netEvent);
777  }
778 
779  //Interrupt service routine epilogue
780  osExitIsr(flag);
781 }
782 
783 
784 /**
785  * @brief PIC32CZ Ethernet MAC event handler
786  * @param[in] interface Underlying network interface
787  **/
788 
790 {
791  error_t error;
792  uint32_t rsr;
793 
794  //Read receive status
795  rsr = GMAC_REGS->GMAC_RSR;
796 
797  //Packet received?
799  GMAC_RSR_BNA_Msk)) != 0)
800  {
801  //Only clear RSR flags that are currently set
802  GMAC_REGS->GMAC_RSR = rsr;
803 
804  //Process all pending packets
805  do
806  {
807  //Read incoming packet
808  error = pic32czEthReceivePacket(interface);
809 
810  //No more data in the receive buffer?
811  } while(error != ERROR_BUFFER_EMPTY);
812  }
813 }
814 
815 
816 /**
817  * @brief Send a packet
818  * @param[in] interface Underlying network interface
819  * @param[in] buffer Multi-part buffer containing the data to send
820  * @param[in] offset Offset to the first data byte
821  * @param[in] ancillary Additional options passed to the stack along with
822  * the packet
823  * @return Error code
824  **/
825 
827  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
828 {
829  size_t length;
830 
831  //Retrieve the length of the packet
832  length = netBufferGetLength(buffer) - offset;
833 
834  //Check the frame length
836  {
837  //The transmitter can accept another packet
838  osSetEvent(&interface->nicTxEvent);
839  //Report an error
840  return ERROR_INVALID_LENGTH;
841  }
842 
843  //Make sure the current buffer is available for writing
844  if((txBufferDesc[txBufferIndex].status & GMAC_TX_USED) == 0)
845  {
846  return ERROR_FAILURE;
847  }
848 
849  //Copy user data to the transmit buffer
850  netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
851 
852  //Set the necessary flags in the descriptor entry
853  if(txBufferIndex < (PIC32CZ_ETH_TX_BUFFER_COUNT - 1))
854  {
855  //Write the status word
856  txBufferDesc[txBufferIndex].status = GMAC_TX_LAST |
858 
859  //Point to the next buffer
860  txBufferIndex++;
861  }
862  else
863  {
864  //Write the status word
865  txBufferDesc[txBufferIndex].status = GMAC_TX_WRAP | GMAC_TX_LAST |
867 
868  //Wrap around
869  txBufferIndex = 0;
870  }
871 
872  //Data synchronization barrier
873  __DSB();
874 
875  //Set the TSTART bit to initiate transmission
876  GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk;
877 
878  //Check whether the next buffer is available for writing
879  if((txBufferDesc[txBufferIndex].status & GMAC_TX_USED) != 0)
880  {
881  //The transmitter can accept another packet
882  osSetEvent(&interface->nicTxEvent);
883  }
884 
885  //Successful processing
886  return NO_ERROR;
887 }
888 
889 
890 /**
891  * @brief Receive a packet
892  * @param[in] interface Underlying network interface
893  * @return Error code
894  **/
895 
897 {
898  static uint32_t temp[ETH_MAX_FRAME_SIZE / 4];
899  error_t error;
900  uint_t i;
901  uint_t j;
902  uint_t sofIndex;
903  uint_t eofIndex;
904  size_t n;
905  size_t size;
906  size_t length;
907 
908  //Initialize variables
909  size = 0;
910  sofIndex = UINT_MAX;
911  eofIndex = UINT_MAX;
912 
913  //Search for SOF and EOF flags
914  for(i = 0; i < PIC32CZ_ETH_RX_BUFFER_COUNT; i++)
915  {
916  //Point to the current entry
917  j = rxBufferIndex + i;
918 
919  //Wrap around to the beginning of the buffer if necessary
921  {
923  }
924 
925  //No more entries to process?
926  if((rxBufferDesc[j].address & GMAC_RX_OWNERSHIP) == 0)
927  {
928  //Stop processing
929  break;
930  }
931 
932  //A valid SOF has been found?
933  if((rxBufferDesc[j].status & GMAC_RX_SOF) != 0)
934  {
935  //Save the position of the SOF
936  sofIndex = i;
937  }
938 
939  //A valid EOF has been found?
940  if((rxBufferDesc[j].status & GMAC_RX_EOF) != 0 && sofIndex != UINT_MAX)
941  {
942  //Save the position of the EOF
943  eofIndex = i;
944  //Retrieve the length of the frame
945  size = rxBufferDesc[j].status & GMAC_RX_LENGTH;
946  //Limit the number of data to read
947  size = MIN(size, ETH_MAX_FRAME_SIZE);
948  //Stop processing since we have reached the end of the frame
949  break;
950  }
951  }
952 
953  //Determine the number of entries to process
954  if(eofIndex != UINT_MAX)
955  {
956  j = eofIndex + 1;
957  }
958  else if(sofIndex != UINT_MAX)
959  {
960  j = sofIndex;
961  }
962  else
963  {
964  j = i;
965  }
966 
967  //Total number of bytes that have been copied from the receive buffer
968  length = 0;
969 
970  //Process incoming frame
971  for(i = 0; i < j; i++)
972  {
973  //Any data to copy from current buffer?
974  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
975  {
976  //Calculate the number of bytes to read at a time
978  //Copy data from receive buffer
979  osMemcpy((uint8_t *) temp + length, rxBuffer[rxBufferIndex], n);
980  //Update byte counters
981  length += n;
982  size -= n;
983  }
984 
985  //Mark the current buffer as free
986  rxBufferDesc[rxBufferIndex].address &= ~GMAC_RX_OWNERSHIP;
987 
988  //Point to the following entry
989  rxBufferIndex++;
990 
991  //Wrap around to the beginning of the buffer if necessary
992  if(rxBufferIndex >= PIC32CZ_ETH_RX_BUFFER_COUNT)
993  {
994  rxBufferIndex = 0;
995  }
996  }
997 
998  //Any packet to process?
999  if(length > 0)
1000  {
1001  NetRxAncillary ancillary;
1002 
1003  //Additional options can be passed to the stack along with the packet
1004  ancillary = NET_DEFAULT_RX_ANCILLARY;
1005 
1006  //Pass the packet to the upper layer
1007  nicProcessPacket(interface, (uint8_t *) temp, length, &ancillary);
1008  //Valid packet received
1009  error = NO_ERROR;
1010  }
1011  else
1012  {
1013  //No more data in the receive buffer
1014  error = ERROR_BUFFER_EMPTY;
1015  }
1016 
1017  //Return status code
1018  return error;
1019 }
1020 
1021 
1022 /**
1023  * @brief Configure MAC address filtering
1024  * @param[in] interface Underlying network interface
1025  * @return Error code
1026  **/
1027 
1029 {
1030  uint_t i;
1031  uint_t j;
1032  uint_t k;
1033  uint8_t *p;
1034  uint32_t hashTable[2];
1035  MacAddr unicastMacAddr[3];
1036  MacFilterEntry *entry;
1037 
1038  //Debug message
1039  TRACE_DEBUG("Updating MAC filter...\r\n");
1040 
1041  //Set the MAC address of the station
1042  GMAC_REGS->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
1043  GMAC_REGS->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2];
1044 
1045  //The MAC supports 3 additional addresses for unicast perfect filtering
1046  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
1047  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
1048  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
1049 
1050  //The hash table is used for multicast address filtering
1051  hashTable[0] = 0;
1052  hashTable[1] = 0;
1053 
1054  //The MAC address filter contains the list of MAC addresses to accept
1055  //when receiving an Ethernet frame
1056  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
1057  {
1058  //Point to the current entry
1059  entry = &interface->macAddrFilter[i];
1060 
1061  //Valid entry?
1062  if(entry->refCount > 0)
1063  {
1064  //Multicast address?
1065  if(macIsMulticastAddr(&entry->addr))
1066  {
1067  //Point to the MAC address
1068  p = entry->addr.b;
1069 
1070  //Apply the hash function
1071  k = (p[0] >> 6) ^ p[0];
1072  k ^= (p[1] >> 4) ^ (p[1] << 2);
1073  k ^= (p[2] >> 2) ^ (p[2] << 4);
1074  k ^= (p[3] >> 6) ^ p[3];
1075  k ^= (p[4] >> 4) ^ (p[4] << 2);
1076  k ^= (p[5] >> 2) ^ (p[5] << 4);
1077 
1078  //The hash value is reduced to a 6-bit index
1079  k &= 0x3F;
1080 
1081  //Update hash table contents
1082  hashTable[k / 32] |= (1 << (k % 32));
1083  }
1084  else
1085  {
1086  //Up to 3 additional MAC addresses can be specified
1087  if(j < 3)
1088  {
1089  //Save the unicast address
1090  unicastMacAddr[j] = entry->addr;
1091  }
1092  else
1093  {
1094  //Point to the MAC address
1095  p = entry->addr.b;
1096 
1097  //Apply the hash function
1098  k = (p[0] >> 6) ^ p[0];
1099  k ^= (p[1] >> 4) ^ (p[1] << 2);
1100  k ^= (p[2] >> 2) ^ (p[2] << 4);
1101  k ^= (p[3] >> 6) ^ p[3];
1102  k ^= (p[4] >> 4) ^ (p[4] << 2);
1103  k ^= (p[5] >> 2) ^ (p[5] << 4);
1104 
1105  //The hash value is reduced to a 6-bit index
1106  k &= 0x3F;
1107 
1108  //Update hash table contents
1109  hashTable[k / 32] |= (1 << (k % 32));
1110  }
1111 
1112  //Increment the number of unicast addresses
1113  j++;
1114  }
1115  }
1116  }
1117 
1118  //Configure the first unicast address filter
1119  if(j >= 1)
1120  {
1121  //The address is activated when SAT register is written
1122  GMAC_REGS->GMAC_SA[1].GMAC_SAB = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
1123  GMAC_REGS->GMAC_SA[1].GMAC_SAT = unicastMacAddr[0].w[2];
1124  }
1125  else
1126  {
1127  //The address is deactivated when SAB register is written
1128  GMAC_REGS->GMAC_SA[1].GMAC_SAB = 0;
1129  }
1130 
1131  //Configure the second unicast address filter
1132  if(j >= 2)
1133  {
1134  //The address is activated when SAT register is written
1135  GMAC_REGS->GMAC_SA[2].GMAC_SAB = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
1136  GMAC_REGS->GMAC_SA[2].GMAC_SAT = unicastMacAddr[1].w[2];
1137  }
1138  else
1139  {
1140  //The address is deactivated when SAB register is written
1141  GMAC_REGS->GMAC_SA[2].GMAC_SAB = 0;
1142  }
1143 
1144  //Configure the third unicast address filter
1145  if(j >= 3)
1146  {
1147  //The address is activated when SAT register is written
1148  GMAC_REGS->GMAC_SA[3].GMAC_SAB = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
1149  GMAC_REGS->GMAC_SA[3].GMAC_SAT = unicastMacAddr[2].w[2];
1150  }
1151  else
1152  {
1153  //The address is deactivated when SAB register is written
1154  GMAC_REGS->GMAC_SA[3].GMAC_SAB = 0;
1155  }
1156 
1157  //The perfect MAC filter supports only 3 unicast addresses
1158  if(j >= 4)
1159  {
1160  GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN_Msk;
1161  }
1162  else
1163  {
1164  GMAC_REGS->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN_Msk;
1165  }
1166 
1167  //Configure the multicast hash table
1168  GMAC_REGS->GMAC_HRB = hashTable[0];
1169  GMAC_REGS->GMAC_HRT = hashTable[1];
1170 
1171  //Debug message
1172  TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", GMAC_REGS->GMAC_HRB);
1173  TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", GMAC_REGS->GMAC_HRT);
1174 
1175  //Successful processing
1176  return NO_ERROR;
1177 }
1178 
1179 
1180 /**
1181  * @brief Adjust MAC configuration parameters for proper operation
1182  * @param[in] interface Underlying network interface
1183  * @return Error code
1184  **/
1185 
1187 {
1188  uint32_t config;
1189 
1190  //Read network configuration register
1191  config = GMAC_REGS->GMAC_NCFGR;
1192 
1193 #if defined(__PIC32CZ2051CA70064__) || defined(__PIC32CZ2051CA70100__) || \
1194  defined(__PIC32CZ2051CA70144__)
1195  //10BASE-T or 100BASE-TX operation mode?
1196  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
1197  {
1198  config |= GMAC_NCFGR_SPD_Msk;
1199  }
1200  else
1201  {
1202  config &= ~GMAC_NCFGR_SPD_Msk;
1203  }
1204 #else
1205  //1000BASE-T operation mode?
1206  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
1207  {
1208  config |= GMAC_NCFGR_GIGE_Msk;
1209  config &= ~GMAC_NCFGR_SPD_Msk;
1210  }
1211  //100BASE-TX operation mode?
1212  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
1213  {
1214  config &= ~GMAC_NCFGR_GIGE_Msk;
1215  config |= GMAC_NCFGR_SPD_Msk;
1216  }
1217  //10BASE-T operation mode?
1218  else
1219  {
1220  config &= ~GMAC_NCFGR_GIGE_Msk;
1221  config &= ~GMAC_NCFGR_SPD_Msk;
1222  }
1223 #endif
1224 
1225  //Half-duplex or full-duplex mode?
1226  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
1227  {
1228  config |= GMAC_NCFGR_FD_Msk;
1229  }
1230  else
1231  {
1232  config &= ~GMAC_NCFGR_FD_Msk;
1233  }
1234 
1235  //Write configuration value back to NCFGR register
1236  GMAC_REGS->GMAC_NCFGR = config;
1237 
1238  //Successful processing
1239  return NO_ERROR;
1240 }
1241 
1242 
1243 /**
1244  * @brief Write PHY register
1245  * @param[in] opcode Access type (2 bits)
1246  * @param[in] phyAddr PHY address (5 bits)
1247  * @param[in] regAddr Register address (5 bits)
1248  * @param[in] data Register value
1249  **/
1250 
1251 void pic32czEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
1252  uint8_t regAddr, uint16_t data)
1253 {
1254  uint32_t temp;
1255 
1256  //Valid opcode?
1257  if(opcode == SMI_OPCODE_WRITE)
1258  {
1259  //Set up a write operation
1260  temp = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | GMAC_MAN_WTN(2);
1261  //PHY address
1262  temp |= GMAC_MAN_PHYA(phyAddr);
1263  //Register address
1264  temp |= GMAC_MAN_REGA(regAddr);
1265  //Register value
1266  temp |= GMAC_MAN_DATA(data);
1267 
1268  //Start a write operation
1269  GMAC_REGS->GMAC_MAN = temp;
1270  //Wait for the write to complete
1271  while((GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk) == 0)
1272  {
1273  }
1274  }
1275  else
1276  {
1277  //The MAC peripheral only supports standard Clause 22 opcodes
1278  }
1279 }
1280 
1281 
1282 /**
1283  * @brief Read PHY register
1284  * @param[in] opcode Access type (2 bits)
1285  * @param[in] phyAddr PHY address (5 bits)
1286  * @param[in] regAddr Register address (5 bits)
1287  * @return Register value
1288  **/
1289 
1290 uint16_t pic32czEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1291  uint8_t regAddr)
1292 {
1293  uint16_t data;
1294  uint32_t temp;
1295 
1296  //Valid opcode?
1297  if(opcode == SMI_OPCODE_READ)
1298  {
1299  //Set up a read operation
1300  temp = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | GMAC_MAN_WTN(2);
1301  //PHY address
1302  temp |= GMAC_MAN_PHYA(phyAddr);
1303  //Register address
1304  temp |= GMAC_MAN_REGA(regAddr);
1305 
1306  //Start a read operation
1307  GMAC_REGS->GMAC_MAN = temp;
1308  //Wait for the read to complete
1309  while((GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk) == 0)
1310  {
1311  }
1312 
1313  //Get register value
1314  data = GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk;
1315  }
1316  else
1317  {
1318  //The MAC peripheral only supports standard Clause 22 opcodes
1319  data = 0;
1320  }
1321 
1322  //Return the value of the PHY register
1323  return data;
1324 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
const NicDriver pic32czEthDriver
PIC32CZ Ethernet MAC driver.
void pic32czEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define GMAC_NCFGR_MTIHEN_Msk
#define GMAC_NCFGR_CLK
#define GMAC_IER_RLEX_Msk
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:61
#define GMAC_TX_LENGTH
#define netEvent
Definition: net_legacy.h:196
#define GMAC_NCFGR_DBW
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define GMAC_IER_HRESP_Msk
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 GMAC_NSR_IDLE_Msk
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:310
#define GMAC_NCR_RXEN_Msk
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:110
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
#define GMAC_TSR_RLE_Msk
void pic32czEthEnableIrq(NetInterface *interface)
Enable interrupts.
PIC32CZ CA70/CA80/CA90 Gigabit Ethernet MAC driver.
#define GMAC_RX_WRAP
#define GMAC_TSR_UND_Msk
void pic32czEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define PIC32CZ_ETH_DUMMY_BUFFER_SIZE
#define GMAC_MAN_PHYA
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 GMAC_TSR_TFC_Msk
#define osExitIsr(flag)
#define GMAC_NCFGR_GIGE_Msk
#define GMAC_RX_EOF
#define GMAC_MAN_DATA
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define PIC32CZ_ETH_DUMMY_BUFFER_COUNT
#define GMAC_NCFGR_UNIHEN_Msk
#define PIC32CZ_ETH_RX_BUFFER_COUNT
#define GMAC_TSR_HRESP_Msk
#define GMAC_TX_USED
#define GMAC_MAN_OP
#define FALSE
Definition: os_port.h:46
#define PIC32CZ_ETH_TX_BUFFER_SIZE
#define GMAC_IRQn
#define GMAC_NCFGR_SPD_Msk
#define PIC32CZ_ETH_RX_BUFFER_SIZE
#define GMAC_TSR_TXGO_Msk
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
#define GMAC_IER_RCOMP_Msk
#define GMAC_RX_ADDRESS
uint16_t pic32czEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define GMAC_DCFGR_RXBMS
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:105
error_t pic32czEthReceivePacket(NetInterface *interface)
Receive a packet.
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
#define GMAC_RBSRPQ_RBS
MacAddr addr
MAC address.
Definition: ethernet.h:263
#define GMAC_NCR_MPE_Msk
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define GMAC_DCFGR_FBLDO
#define GMAC_TSR_TXCOMP_Msk
error_t pic32czEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define NetTxAncillary
Definition: net_misc.h:36
uint8_t mask
Definition: web_socket.h:319
#define GMAC_NCFGR_FD_Msk
#define SMI_OPCODE_READ
Definition: nic.h:67
#define GMAC_NCR_TXEN_Msk
error_t pic32czEthInit(NetInterface *interface)
PIC32CZ Ethernet MAC initialization.
#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
#define MIN(a, b)
Definition: os_port.h:63
#define GMAC_RSR_BNA_Msk
#define rxBuffer
#define GMAC_RX_SOF
#define GMAC_TSR_UBR_Msk
MacAddr
Definition: ethernet.h:195
Receive buffer descriptor.
#define GMAC_NCR_TSTART_Msk
#define GMAC_DCFGR_TXPBMS_Msk
void pic32czEthTick(NetInterface *interface)
PIC32CZ Ethernet MAC timer handler.
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define GMAC_IER_TUR_Msk
#define GMAC_REGS
__weak_func void pic32czEthInitGpio(NetInterface *interface)
GPIO configuration.
uint16_t regAddr
#define GMAC_RX_LENGTH
#define ETH_MTU
Definition: ethernet.h:116
#define GMAC_TX_LAST
uint8_t n
#define PIC32CZ_ETH_TX_BUFFER_COUNT
MAC filter table entry.
Definition: ethernet.h:262
Transmit buffer descriptor.
#define GMAC_DCFGR_DRBS
Ipv6Addr address[]
Definition: ipv6.h:325
error_t pic32czEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define osEnterIsr()
#define GMAC_IER_TFC_Msk
#define PIC32CZ_ETH_RAM_SECTION
#define GMAC_IER_ROVR_Msk
error_t pic32czEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define GMAC_MAN_WTN
#define GMAC_RSR_HNO_Msk
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define GMAC_RSR_RXOVR_Msk
#define PIC32CZ_ETH_IRQ_GROUP_PRIORITY
void pic32czEthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
#define GMAC_IER_TCOMP_Msk
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define PIC32CZ_ETH_IRQ_SUB_PRIORITY
unsigned int uint_t
Definition: compiler_port.h:57
void pic32czEthEventHandler(NetInterface *interface)
PIC32CZ Ethernet MAC event handler.
TCP/IP stack core.
#define GMAC_RSR_REC_Msk
NIC driver.
Definition: nic.h:286
#define GMAC_RX_OWNERSHIP
#define GMAC_MAN_REGA
#define GMAC_NCFGR_MAXFS_Msk
void GMAC_Handler(void)
PIC32CZ Ethernet MAC interrupt service routine.
#define PIC32CZ_ETH_IRQ_PRIORITY_GROUPING
#define GMAC_TSR_COL_Msk
#define GMAC_IER_RXUBR_Msk
#define GMAC_MAN_CLTTO_Msk
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
#define GMAC_MAN_DATA_Msk
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define GMAC_TX_WRAP
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83