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