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.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
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  size_t length;
773 
774  //Retrieve the length of the packet
775  length = netBufferGetLength(buffer) - offset;
776 
777  //Check the frame length
779  {
780  //The transmitter can accept another packet
781  osSetEvent(&interface->nicTxEvent);
782  //Report an error
783  return ERROR_INVALID_LENGTH;
784  }
785 
786  //Make sure the current buffer is available for writing
787  if((txBufferDesc[txBufferIndex].status & ETH_TX_USED) == 0)
788  {
789  return ERROR_FAILURE;
790  }
791 
792  //Copy user data to the transmit buffer
793  netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
794 
795  //Set the necessary flags in the descriptor entry
796  if(txBufferIndex < (PIC32CZ_ETH_TX_BUFFER_COUNT - 1))
797  {
798  //Write the status word
799  txBufferDesc[txBufferIndex].status = ETH_TX_LAST |
800  (length & ETH_TX_LENGTH);
801 
802  //Point to the next buffer
803  txBufferIndex++;
804  }
805  else
806  {
807  //Write the status word
808  txBufferDesc[txBufferIndex].status = ETH_TX_WRAP | ETH_TX_LAST |
809  (length & ETH_TX_LENGTH);
810 
811  //Wrap around
812  txBufferIndex = 0;
813  }
814 
815  //Data synchronization barrier
816  __DSB();
817 
818  //Set the TSTART bit to initiate transmission
819  ETH_REGS->ETH_NCR |= ETH_NCR_TSTART_Msk;
820 
821  //Check whether the next buffer is available for writing
822  if((txBufferDesc[txBufferIndex].status & ETH_TX_USED) != 0)
823  {
824  //The transmitter can accept another packet
825  osSetEvent(&interface->nicTxEvent);
826  }
827 
828  //Successful processing
829  return NO_ERROR;
830 }
831 
832 
833 /**
834  * @brief Receive a packet
835  * @param[in] interface Underlying network interface
836  * @return Error code
837  **/
838 
840 {
841  static uint32_t temp[ETH_MAX_FRAME_SIZE / 4];
842  error_t error;
843  uint_t i;
844  uint_t j;
845  uint_t sofIndex;
846  uint_t eofIndex;
847  size_t n;
848  size_t size;
849  size_t length;
850 
851  //Initialize variables
852  size = 0;
853  sofIndex = UINT_MAX;
854  eofIndex = UINT_MAX;
855 
856  //Search for SOF and EOF flags
857  for(i = 0; i < PIC32CZ_ETH_RX_BUFFER_COUNT; i++)
858  {
859  //Point to the current entry
860  j = rxBufferIndex + i;
861 
862  //Wrap around to the beginning of the buffer if necessary
864  {
866  }
867 
868  //No more entries to process?
869  if((rxBufferDesc[j].address & ETH_RX_OWNERSHIP) == 0)
870  {
871  //Stop processing
872  break;
873  }
874 
875  //A valid SOF has been found?
876  if((rxBufferDesc[j].status & ETH_RX_SOF) != 0)
877  {
878  //Save the position of the SOF
879  sofIndex = i;
880  }
881 
882  //A valid EOF has been found?
883  if((rxBufferDesc[j].status & ETH_RX_EOF) != 0 && sofIndex != UINT_MAX)
884  {
885  //Save the position of the EOF
886  eofIndex = i;
887  //Retrieve the length of the frame
888  size = rxBufferDesc[j].status & ETH_RX_LENGTH;
889  //Limit the number of data to read
890  size = MIN(size, ETH_MAX_FRAME_SIZE);
891  //Stop processing since we have reached the end of the frame
892  break;
893  }
894  }
895 
896  //Determine the number of entries to process
897  if(eofIndex != UINT_MAX)
898  {
899  j = eofIndex + 1;
900  }
901  else if(sofIndex != UINT_MAX)
902  {
903  j = sofIndex;
904  }
905  else
906  {
907  j = i;
908  }
909 
910  //Total number of bytes that have been copied from the receive buffer
911  length = 0;
912 
913  //Process incoming frame
914  for(i = 0; i < j; i++)
915  {
916  //Any data to copy from current buffer?
917  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
918  {
919  //Calculate the number of bytes to read at a time
921  //Copy data from receive buffer
922  osMemcpy((uint8_t *) temp + length, rxBuffer[rxBufferIndex], n);
923  //Update byte counters
924  length += n;
925  size -= n;
926  }
927 
928  //Mark the current buffer as free
929  rxBufferDesc[rxBufferIndex].address &= ~ETH_RX_OWNERSHIP;
930 
931  //Point to the following entry
932  rxBufferIndex++;
933 
934  //Wrap around to the beginning of the buffer if necessary
935  if(rxBufferIndex >= PIC32CZ_ETH_RX_BUFFER_COUNT)
936  {
937  rxBufferIndex = 0;
938  }
939  }
940 
941  //Any packet to process?
942  if(length > 0)
943  {
944  NetRxAncillary ancillary;
945 
946  //Additional options can be passed to the stack along with the packet
947  ancillary = NET_DEFAULT_RX_ANCILLARY;
948 
949  //Pass the packet to the upper layer
950  nicProcessPacket(interface, (uint8_t *) temp, length, &ancillary);
951  //Valid packet received
952  error = NO_ERROR;
953  }
954  else
955  {
956  //No more data in the receive buffer
957  error = ERROR_BUFFER_EMPTY;
958  }
959 
960  //Return status code
961  return error;
962 }
963 
964 
965 /**
966  * @brief Configure MAC address filtering
967  * @param[in] interface Underlying network interface
968  * @return Error code
969  **/
970 
972 {
973  uint_t i;
974  uint_t j;
975  uint_t k;
976  uint8_t *p;
977  uint32_t hashTable[2];
978  MacAddr unicastMacAddr[3];
979  MacFilterEntry *entry;
980 
981  //Debug message
982  TRACE_DEBUG("Updating MAC filter...\r\n");
983 
984  //Set the MAC address of the station
985  ETH_REGS->SA[0].ETH_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
986  ETH_REGS->SA[0].ETH_SAT = interface->macAddr.w[2];
987 
988  //The MAC supports 3 additional addresses for unicast perfect filtering
989  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
990  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
991  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
992 
993  //The hash table is used for multicast address filtering
994  hashTable[0] = 0;
995  hashTable[1] = 0;
996 
997  //The MAC address filter contains the list of MAC addresses to accept
998  //when receiving an Ethernet frame
999  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
1000  {
1001  //Point to the current entry
1002  entry = &interface->macAddrFilter[i];
1003 
1004  //Valid entry?
1005  if(entry->refCount > 0)
1006  {
1007  //Multicast address?
1008  if(macIsMulticastAddr(&entry->addr))
1009  {
1010  //Point to the MAC address
1011  p = entry->addr.b;
1012 
1013  //Apply the hash function
1014  k = (p[0] >> 6) ^ p[0];
1015  k ^= (p[1] >> 4) ^ (p[1] << 2);
1016  k ^= (p[2] >> 2) ^ (p[2] << 4);
1017  k ^= (p[3] >> 6) ^ p[3];
1018  k ^= (p[4] >> 4) ^ (p[4] << 2);
1019  k ^= (p[5] >> 2) ^ (p[5] << 4);
1020 
1021  //The hash value is reduced to a 6-bit index
1022  k &= 0x3F;
1023 
1024  //Update hash table contents
1025  hashTable[k / 32] |= (1 << (k % 32));
1026  }
1027  else
1028  {
1029  //Up to 3 additional MAC addresses can be specified
1030  if(j < 3)
1031  {
1032  //Save the unicast address
1033  unicastMacAddr[j] = entry->addr;
1034  }
1035  else
1036  {
1037  //Point to the MAC address
1038  p = entry->addr.b;
1039 
1040  //Apply the hash function
1041  k = (p[0] >> 6) ^ p[0];
1042  k ^= (p[1] >> 4) ^ (p[1] << 2);
1043  k ^= (p[2] >> 2) ^ (p[2] << 4);
1044  k ^= (p[3] >> 6) ^ p[3];
1045  k ^= (p[4] >> 4) ^ (p[4] << 2);
1046  k ^= (p[5] >> 2) ^ (p[5] << 4);
1047 
1048  //The hash value is reduced to a 6-bit index
1049  k &= 0x3F;
1050 
1051  //Update hash table contents
1052  hashTable[k / 32] |= (1 << (k % 32));
1053  }
1054 
1055  //Increment the number of unicast addresses
1056  j++;
1057  }
1058  }
1059  }
1060 
1061  //Configure the first unicast address filter
1062  if(j >= 1)
1063  {
1064  //The address is activated when SAT register is written
1065  ETH_REGS->SA[1].ETH_SAB = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
1066  ETH_REGS->SA[1].ETH_SAT = unicastMacAddr[0].w[2];
1067  }
1068  else
1069  {
1070  //The address is deactivated when SAB register is written
1071  ETH_REGS->SA[1].ETH_SAB = 0;
1072  }
1073 
1074  //Configure the second unicast address filter
1075  if(j >= 2)
1076  {
1077  //The address is activated when SAT register is written
1078  ETH_REGS->SA[2].ETH_SAB = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
1079  ETH_REGS->SA[2].ETH_SAT = unicastMacAddr[1].w[2];
1080  }
1081  else
1082  {
1083  //The address is deactivated when SAB register is written
1084  ETH_REGS->SA[2].ETH_SAB = 0;
1085  }
1086 
1087  //Configure the third unicast address filter
1088  if(j >= 3)
1089  {
1090  //The address is activated when SAT register is written
1091  ETH_REGS->SA[3].ETH_SAB = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
1092  ETH_REGS->SA[3].ETH_SAT = unicastMacAddr[2].w[2];
1093  }
1094  else
1095  {
1096  //The address is deactivated when SAB register is written
1097  ETH_REGS->SA[3].ETH_SAB = 0;
1098  }
1099 
1100  //The perfect MAC filter supports only 3 unicast addresses
1101  if(j >= 4)
1102  {
1103  ETH_REGS->ETH_NCFGR |= ETH_NCFGR_UNIHEN_Msk;
1104  }
1105  else
1106  {
1107  ETH_REGS->ETH_NCFGR &= ~ETH_NCFGR_UNIHEN_Msk;
1108  }
1109 
1110  //Configure the multicast hash table
1111  ETH_REGS->ETH_HRB = hashTable[0];
1112  ETH_REGS->ETH_HRT = hashTable[1];
1113 
1114  //Debug message
1115  TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", ETH_REGS->ETH_HRB);
1116  TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", ETH_REGS->ETH_HRT);
1117 
1118  //Successful processing
1119  return NO_ERROR;
1120 }
1121 
1122 
1123 /**
1124  * @brief Adjust MAC configuration parameters for proper operation
1125  * @param[in] interface Underlying network interface
1126  * @return Error code
1127  **/
1128 
1130 {
1131  uint32_t config;
1132 
1133  //Read network configuration register
1134  config = ETH_REGS->ETH_NCFGR;
1135 
1136  //1000BASE-T operation mode?
1137  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
1138  {
1139  config |= ETH_NCFGR_GIGE_Msk;
1140  config &= ~ETH_NCFGR_SPD_Msk;
1141  }
1142  //100BASE-TX operation mode?
1143  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
1144  {
1145  config &= ~ETH_NCFGR_GIGE_Msk;
1146  config |= ETH_NCFGR_SPD_Msk;
1147  }
1148  //10BASE-T operation mode?
1149  else
1150  {
1151  config &= ~ETH_NCFGR_GIGE_Msk;
1152  config &= ~ETH_NCFGR_SPD_Msk;
1153  }
1154 
1155  //Half-duplex or full-duplex mode?
1156  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
1157  {
1158  config |= ETH_NCFGR_FD_Msk;
1159  }
1160  else
1161  {
1162  config &= ~ETH_NCFGR_FD_Msk;
1163  }
1164 
1165  //Write configuration value back to NCFGR register
1166  ETH_REGS->ETH_NCFGR = config;
1167 
1168  //Successful processing
1169  return NO_ERROR;
1170 }
1171 
1172 
1173 /**
1174  * @brief Write PHY register
1175  * @param[in] opcode Access type (2 bits)
1176  * @param[in] phyAddr PHY address (5 bits)
1177  * @param[in] regAddr Register address (5 bits)
1178  * @param[in] data Register value
1179  **/
1180 
1181 void pic32czEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
1182  uint8_t regAddr, uint16_t data)
1183 {
1184  uint32_t temp;
1185 
1186  //Valid opcode?
1187  if(opcode == SMI_OPCODE_WRITE)
1188  {
1189  //Set up a write operation
1190  temp = ETH_MAN_CLTTO_Msk | ETH_MAN_OP(1) | ETH_MAN_WTN(2);
1191  //PHY address
1192  temp |= ETH_MAN_PHYA(phyAddr);
1193  //Register address
1194  temp |= ETH_MAN_REGA(regAddr);
1195  //Register value
1196  temp |= ETH_MAN_DATA(data);
1197 
1198  //Start a write operation
1199  ETH_REGS->ETH_MAN = temp;
1200  //Wait for the write to complete
1201  while((ETH_REGS->ETH_NSR & ETH_NSR_IDLE_Msk) == 0)
1202  {
1203  }
1204  }
1205  else
1206  {
1207  //The MAC peripheral only supports standard Clause 22 opcodes
1208  }
1209 }
1210 
1211 
1212 /**
1213  * @brief Read PHY register
1214  * @param[in] opcode Access type (2 bits)
1215  * @param[in] phyAddr PHY address (5 bits)
1216  * @param[in] regAddr Register address (5 bits)
1217  * @return Register value
1218  **/
1219 
1220 uint16_t pic32czEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1221  uint8_t regAddr)
1222 {
1223  uint16_t data;
1224  uint32_t temp;
1225 
1226  //Valid opcode?
1227  if(opcode == SMI_OPCODE_READ)
1228  {
1229  //Set up a read operation
1230  temp = ETH_MAN_CLTTO_Msk | ETH_MAN_OP(2) | ETH_MAN_WTN(2);
1231  //PHY address
1232  temp |= ETH_MAN_PHYA(phyAddr);
1233  //Register address
1234  temp |= ETH_MAN_REGA(regAddr);
1235 
1236  //Start a read operation
1237  ETH_REGS->ETH_MAN = temp;
1238  //Wait for the read to complete
1239  while((ETH_REGS->ETH_NSR & ETH_NSR_IDLE_Msk) == 0)
1240  {
1241  }
1242 
1243  //Get register value
1244  data = ETH_REGS->ETH_MAN & ETH_MAN_DATA_Msk;
1245  }
1246  else
1247  {
1248  //The MAC peripheral only supports standard Clause 22 opcodes
1249  data = 0;
1250  }
1251 
1252  //Return the value of the PHY register
1253  return data;
1254 }
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
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
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
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
void pic32czEthEnableIrq(NetInterface *interface)
Enable interrupts.
PIC32CZ CA80/CA90 Gigabit Ethernet MAC driver.
void pic32czEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define PIC32CZ_ETH_DUMMY_BUFFER_SIZE
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)
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define ETH_RX_OWNERSHIP
#define PIC32CZ_ETH_DUMMY_BUFFER_COUNT
#define PIC32CZ_ETH_RX_BUFFER_COUNT
#define FALSE
Definition: os_port.h:46
#define PIC32CZ_ETH_TX_BUFFER_SIZE
#define PIC32CZ_ETH_RX_BUFFER_SIZE
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
#define ETH_TX_WRAP
uint16_t pic32czEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
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
MacAddr addr
MAC address.
Definition: ethernet.h:263
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
error_t pic32czEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
error_t pic32czEthInit(NetInterface *interface)
PIC32CZ Ethernet MAC initialization.
#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
Receive buffer descriptor.
#define ETH_TX_USED
void pic32czEthTick(NetInterface *interface)
PIC32CZ Ethernet MAC timer handler.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define ETH_RX_SOF
__weak_func void pic32czEthInitGpio(NetInterface *interface)
GPIO configuration.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
#define PIC32CZ_ETH_TX_BUFFER_COUNT
MAC filter table entry.
Definition: ethernet.h:262
Transmit buffer descriptor.
Ipv6Addr address[]
Definition: ipv6.h:325
error_t pic32czEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define ETH_TX_LENGTH
#define osEnterIsr()
#define PIC32CZ_ETH_RAM_SECTION
error_t pic32czEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define PIC32CZ_ETH_IRQ_GROUP_PRIORITY
void ETH_PRI_Q_0_Handler(void)
PIC32CZ Ethernet MAC interrupt service routine.
void pic32czEthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define PIC32CZ_ETH_IRQ_SUB_PRIORITY
unsigned int uint_t
Definition: compiler_port.h:50
void pic32czEthEventHandler(NetInterface *interface)
PIC32CZ Ethernet MAC event handler.
TCP/IP stack core.
#define ETH_RX_ADDRESS
NIC driver.
Definition: nic.h:286
#define ETH_TX_LAST
#define PIC32CZ_ETH_IRQ_PRIORITY_GROUPING
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