mcimx6ul_eth1_driver.c
Go to the documentation of this file.
1 /**
2  * @file mcimx6ul_eth1_driver.c
3  * @brief NXP i.MX6UL Ethernet MAC driver (ENET1 instance)
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 "fsl_device_registers.h"
36 #include "fsl_gpio.h"
37 #include "fsl_iomuxc.h"
38 #include "core/net.h"
40 #include "debug.h"
41 
42 //Underlying network interface
43 static NetInterface *nicDriverInterface;
44 
45 //IAR EWARM compiler?
46 #if defined(__ICCARM__)
47 
48 //TX buffer
49 #pragma data_alignment = 64
50 #pragma location = MCIMX6UL_ETH1_RAM_SECTION
52 //RX buffer
53 #pragma data_alignment = 64
54 #pragma location = MCIMX6UL_ETH1_RAM_SECTION
56 //TX buffer descriptors
57 #pragma data_alignment = 64
58 #pragma location = MCIMX6UL_ETH1_RAM_SECTION
59 static uint32_t txBufferDesc[MCIMX6UL_ETH1_TX_BUFFER_COUNT][8];
60 //RX buffer descriptors
61 #pragma data_alignment = 64
62 #pragma location = MCIMX6UL_ETH1_RAM_SECTION
63 static uint32_t rxBufferDesc[MCIMX6UL_ETH1_RX_BUFFER_COUNT][8];
64 
65 //ARM or GCC compiler?
66 #else
67 
68 //TX buffer
70  __attribute__((aligned(64), __section__(MCIMX6UL_ETH1_RAM_SECTION)));
71 //RX buffer
73  __attribute__((aligned(64), __section__(MCIMX6UL_ETH1_RAM_SECTION)));
74 //TX buffer descriptors
75 static uint32_t txBufferDesc[MCIMX6UL_ETH1_TX_BUFFER_COUNT][8]
76  __attribute__((aligned(64), __section__(MCIMX6UL_ETH1_RAM_SECTION)));
77 //RX buffer descriptors
78 static uint32_t rxBufferDesc[MCIMX6UL_ETH1_RX_BUFFER_COUNT][8]
79  __attribute__((aligned(64), __section__(MCIMX6UL_ETH1_RAM_SECTION)));
80 
81 #endif
82 
83 //TX buffer index
84 static uint_t txBufferIndex;
85 //RX buffer index
86 static uint_t rxBufferIndex;
87 
88 
89 /**
90  * @brief i.MX6UL Ethernet MAC driver (ENET1 instance)
91  **/
92 
94 {
96  ETH_MTU,
107  TRUE,
108  TRUE,
109  TRUE,
110  FALSE
111 };
112 
113 
114 /**
115  * @brief i.MX6UL Ethernet MAC initialization
116  * @param[in] interface Underlying network interface
117  * @return Error code
118  **/
119 
121 {
122  error_t error;
123  uint32_t value;
124 
125  //Debug message
126  TRACE_INFO("Initializing i.MX6UL Ethernet MAC (ENET1)...\r\n");
127 
128  //Save underlying network interface
129  nicDriverInterface = interface;
130 
131  //Enable ENET peripheral clock
132  CLOCK_EnableClock(kCLOCK_Enet);
133 
134  //GPIO configuration
135  mcimx6ulEth1InitGpio(interface);
136 
137  //Reset ENET1 module
138  ENET1->ECR = ENET_ECR_RESET_MASK;
139  //Wait for the reset to complete
140  while((ENET1->ECR & ENET_ECR_RESET_MASK) != 0)
141  {
142  }
143 
144  //Receive control register
145  ENET1->RCR = ENET_RCR_MAX_FL(MCIMX6UL_ETH1_RX_BUFFER_SIZE) |
146  ENET_RCR_RMII_MODE_MASK | ENET_RCR_MII_MODE_MASK;
147 
148  //Transmit control register
149  ENET1->TCR = 0;
150  //Configure MDC clock frequency
151  ENET1->MSCR = ENET_MSCR_HOLDTIME(10) | ENET_MSCR_MII_SPEED(120);
152 
153  //Valid Ethernet PHY or switch driver?
154  if(interface->phyDriver != NULL)
155  {
156  //Ethernet PHY initialization
157  error = interface->phyDriver->init(interface);
158  }
159  else if(interface->switchDriver != NULL)
160  {
161  //Ethernet switch initialization
162  error = interface->switchDriver->init(interface);
163  }
164  else
165  {
166  //The interface is not properly configured
167  error = ERROR_FAILURE;
168  }
169 
170  //Any error to report?
171  if(error)
172  {
173  return error;
174  }
175 
176  //Set the MAC address of the station (upper 16 bits)
177  value = interface->macAddr.b[5];
178  value |= (interface->macAddr.b[4] << 8);
179  ENET1->PAUR = ENET_PAUR_PADDR2(value) | ENET_PAUR_TYPE(0x8808);
180 
181  //Set the MAC address of the station (lower 32 bits)
182  value = interface->macAddr.b[3];
183  value |= (interface->macAddr.b[2] << 8);
184  value |= (interface->macAddr.b[1] << 16);
185  value |= (interface->macAddr.b[0] << 24);
186  ENET1->PALR = ENET_PALR_PADDR1(value);
187 
188  //Hash table for unicast address filtering
189  ENET1->IALR = 0;
190  ENET1->IAUR = 0;
191  //Hash table for multicast address filtering
192  ENET1->GALR = 0;
193  ENET1->GAUR = 0;
194 
195  //Disable transmit accelerator functions
196  ENET1->TACC = 0;
197  //Disable receive accelerator functions
198  ENET1->RACC = 0;
199 
200  //Use enhanced buffer descriptors
201  ENET1->ECR = ENET_ECR_DBSWP_MASK | ENET_ECR_EN1588_MASK;
202 
203  //Reset statistics counters
204  ENET1->MIBC = ENET_MIBC_MIB_CLEAR_MASK;
205  ENET1->MIBC = 0;
206 
207  //Initialize buffer descriptors
208  mcimx6ulEth1InitBufferDesc(interface);
209 
210  //Clear any pending interrupts
211  ENET1->EIR = 0xFFFFFFFF;
212  //Enable desired interrupts
213  ENET1->EIMR = ENET_EIMR_TXF_MASK | ENET_EIMR_RXF_MASK | ENET_EIMR_EBERR_MASK;
214 
215  //Configure ENET1 interrupt priority
216  GIC_SetPriority(ENET1_IRQn, MCIMX6UL_ETH1_IRQ_PRIORITY);
217 
218  //Enable Ethernet MAC
219  ENET1->ECR |= ENET_ECR_ETHEREN_MASK;
220  //Instruct the DMA to poll the receive descriptor list
221  ENET1->RDAR = ENET_RDAR_RDAR_MASK;
222 
223  //Accept any packets from the upper layer
224  osSetEvent(&interface->nicTxEvent);
225 
226  //Successful initialization
227  return NO_ERROR;
228 }
229 
230 
231 /**
232  * @brief GPIO configuration
233  * @param[in] interface Underlying network interface
234  **/
235 
236 __weak_func void mcimx6ulEth1InitGpio(NetInterface *interface)
237 {
238 //MCIMX6UL-EVKB or MCIMX6ULL-EVK evaluation board?
239 #if defined(USE_MCIMX6UL_EVKB) || defined(USE_MCIMX6ULL_EVK)
240  gpio_pin_config_t pinConfig;
241  clock_enet_pll_config_t pllConfig;
242 
243  //Configure ENET PLL (50MHz)
244  pllConfig.enableClkOutput0 = true;
245  pllConfig.enableClkOutput1 = true;
246  pllConfig.enableClkOutput2 = false;
247  pllConfig.loopDivider0 = 1;
248  pllConfig.loopDivider1 = 1;
249  CLOCK_InitEnetPll(&pllConfig);
250 
251  //Enable ENET1_TX_CLK output driver
252  IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_ENET1_TX_CLK_DIR(1);
253 
254  //Enable IOMUXC clock
255  CLOCK_EnableClock(kCLOCK_Iomuxc);
256 
257  //Configure ENET1_TX_CLK pin as ENET1_REF_CLK1
258  IOMUXC_SetPinMux(IOMUXC_ENET1_TX_CLK_ENET1_REF_CLK1, 1);
259 
260  //Set ENET1_TX_CLK pad properties
261  IOMUXC_SetPinConfig(IOMUXC_ENET1_TX_CLK_ENET1_REF_CLK1,
262  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
263  IOMUXC_SW_PAD_CTL_PAD_PUS(0) |
264  IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
265  IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
266  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
267  IOMUXC_SW_PAD_CTL_PAD_SPEED(3) |
268  IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
269  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
270 
271  //Configure ENET1_TX_EN pin as ENET1_TX_EN
272  IOMUXC_SetPinMux(IOMUXC_ENET1_TX_EN_ENET1_TX_EN, 0);
273 
274  //Set ENET1_TX_EN pad properties
275  IOMUXC_SetPinConfig(IOMUXC_ENET1_TX_EN_ENET1_TX_EN,
276  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
277  IOMUXC_SW_PAD_CTL_PAD_PUS(0) |
278  IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
279  IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
280  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
281  IOMUXC_SW_PAD_CTL_PAD_SPEED(3) |
282  IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
283  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
284 
285  //Configure ENET1_TX_DATA0 pin as ENET1_TDATA00
286  IOMUXC_SetPinMux(IOMUXC_ENET1_TX_DATA0_ENET1_TDATA00, 0);
287 
288  //Set ENET1_TX_DATA0 pad properties
289  IOMUXC_SetPinConfig(IOMUXC_ENET1_TX_DATA0_ENET1_TDATA00,
290  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
291  IOMUXC_SW_PAD_CTL_PAD_PUS(0) |
292  IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
293  IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
294  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
295  IOMUXC_SW_PAD_CTL_PAD_SPEED(3) |
296  IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
297  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
298 
299  //Configure ENET1_TX_DATA1 pin as ENET1_TDATA01
300  IOMUXC_SetPinMux(IOMUXC_ENET1_TX_DATA1_ENET1_TDATA01, 0);
301 
302  //Set ENET1_TX_DATA1 pad properties
303  IOMUXC_SetPinConfig(IOMUXC_ENET1_TX_DATA1_ENET1_TDATA01,
304  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
305  IOMUXC_SW_PAD_CTL_PAD_PUS(0) |
306  IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
307  IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
308  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
309  IOMUXC_SW_PAD_CTL_PAD_SPEED(3) |
310  IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
311  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
312 
313  //Configure ENET1_RX_EN pin as ENET1_RX_EN
314  IOMUXC_SetPinMux(IOMUXC_ENET1_RX_EN_ENET1_RX_EN, 0);
315 
316  //Set ENET1_RX_EN pad properties
317  IOMUXC_SetPinConfig(IOMUXC_ENET1_RX_EN_ENET1_RX_EN,
318  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
319  IOMUXC_SW_PAD_CTL_PAD_PUS(0) |
320  IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
321  IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
322  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
323  IOMUXC_SW_PAD_CTL_PAD_SPEED(3) |
324  IOMUXC_SW_PAD_CTL_PAD_DSE(0) |
325  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
326 
327  //Configure ENET1_RX_ER pin as ENET1_RX_ER
328  IOMUXC_SetPinMux(IOMUXC_ENET1_RX_ER_ENET1_RX_ER, 0);
329 
330  //Set ENET1_RX_ER pad properties
331  IOMUXC_SetPinConfig(IOMUXC_ENET1_RX_ER_ENET1_RX_ER,
332  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
333  IOMUXC_SW_PAD_CTL_PAD_PUS(0) |
334  IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
335  IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
336  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
337  IOMUXC_SW_PAD_CTL_PAD_SPEED(3) |
338  IOMUXC_SW_PAD_CTL_PAD_DSE(0) |
339  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
340 
341  //Configure ENET1_RX_DATA0 pin as ENET1_RDATA00
342  IOMUXC_SetPinMux(IOMUXC_ENET1_RX_DATA0_ENET1_RDATA00, 0);
343 
344  //Set ENET1_RX_DATA0 pad properties
345  IOMUXC_SetPinConfig(IOMUXC_ENET1_RX_DATA0_ENET1_RDATA00,
346  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
347  IOMUXC_SW_PAD_CTL_PAD_PUS(0) |
348  IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
349  IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
350  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
351  IOMUXC_SW_PAD_CTL_PAD_SPEED(3) |
352  IOMUXC_SW_PAD_CTL_PAD_DSE(0) |
353  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
354 
355  //Configure ENET1_RX_DATA1 pin as ENET1_RDATA01
356  IOMUXC_SetPinMux(IOMUXC_ENET1_RX_DATA1_ENET1_RDATA01, 0);
357 
358  //Set ENET1_RX_DATA1 pad properties
359  IOMUXC_SetPinConfig(IOMUXC_ENET1_RX_DATA1_ENET1_RDATA01,
360  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
361  IOMUXC_SW_PAD_CTL_PAD_PUS(0) |
362  IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
363  IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
364  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
365  IOMUXC_SW_PAD_CTL_PAD_SPEED(3) |
366  IOMUXC_SW_PAD_CTL_PAD_DSE(0) |
367  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
368 
369  //Configure GPIO1_IO06 pin as ENET1_MDIO
370  IOMUXC_SetPinMux(IOMUXC_GPIO1_IO06_ENET1_MDIO, 0);
371 
372  //Set GPIO1_IO06 pad properties
373  IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO06_ENET1_MDIO,
374  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
375  IOMUXC_SW_PAD_CTL_PAD_PUS(2) |
376  IOMUXC_SW_PAD_CTL_PAD_PUE(1) |
377  IOMUXC_SW_PAD_CTL_PAD_PKE(1) |
378  IOMUXC_SW_PAD_CTL_PAD_ODE(1) |
379  IOMUXC_SW_PAD_CTL_PAD_SPEED(0) |
380  IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
381  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
382 
383  //Configure GPIO1_IO07 pin as ENET1_MDC
384  IOMUXC_SetPinMux(IOMUXC_GPIO1_IO07_ENET1_MDC, 0);
385 
386  //Set GPIO1_IO07 pad properties
387  IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO07_ENET1_MDC,
388  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
389  IOMUXC_SW_PAD_CTL_PAD_PUS(0) |
390  IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
391  IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
392  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
393  IOMUXC_SW_PAD_CTL_PAD_SPEED(0) |
394  IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
395  IOMUXC_SW_PAD_CTL_PAD_SRE(1));
396 
397 #if defined(USE_MCIMX6UL_EVKB)
398  //Configure SNVS_TAMPER5 pin as GPIO5_IO05
399  IOMUXC_SetPinMux(IOMUXC_SNVS_TAMPER5_GPIO5_IO05, 0);
400 
401  //Set SNVS_TAMPER5 pad properties
402  IOMUXC_SetPinConfig(IOMUXC_SNVS_TAMPER5_GPIO5_IO05,
403  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
404  IOMUXC_SW_PAD_CTL_PAD_PUS(2) |
405  IOMUXC_SW_PAD_CTL_PAD_PUE(1) |
406  IOMUXC_SW_PAD_CTL_PAD_PKE(1) |
407  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
408  IOMUXC_SW_PAD_CTL_PAD_SPEED(0) |
409  IOMUXC_SW_PAD_CTL_PAD_DSE(0) |
410  IOMUXC_SW_PAD_CTL_PAD_SRE(0));
411 
412 #elif defined(USE_MCIMX6ULL_EVK)
413  //Configure SNVS_TAMPER5 pin as GPIO5_IO05
414  IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER5_GPIO5_IO05, 0);
415 
416  //Set SNVS_TAMPER5 pad properties
417  IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER5_GPIO5_IO05,
418  IOMUXC_SW_PAD_CTL_PAD_HYS(0) |
419  IOMUXC_SW_PAD_CTL_PAD_PUS(2) |
420  IOMUXC_SW_PAD_CTL_PAD_PUE(1) |
421  IOMUXC_SW_PAD_CTL_PAD_PKE(1) |
422  IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
423  IOMUXC_SW_PAD_CTL_PAD_SPEED(0) |
424  IOMUXC_SW_PAD_CTL_PAD_DSE(0) |
425  IOMUXC_SW_PAD_CTL_PAD_SRE(0));
426 #endif
427 
428  //Configure ENET1_INT as an input
429  pinConfig.direction = kGPIO_DigitalInput;
430  pinConfig.outputLogic = 0;
431  pinConfig.interruptMode = kGPIO_NoIntmode;
432  GPIO_PinInit(GPIO5, 5, &pinConfig);
433 #endif
434 }
435 
436 
437 /**
438  * @brief Initialize buffer descriptors
439  * @param[in] interface Underlying network interface
440  **/
441 
443 {
444  uint_t i;
445  uint32_t address;
446 
447  //Clear TX and RX buffer descriptors
448  osMemset(txBufferDesc, 0, sizeof(txBufferDesc));
449  osMemset(rxBufferDesc, 0, sizeof(rxBufferDesc));
450 
451  //Initialize TX buffer descriptors
452  for(i = 0; i < MCIMX6UL_ETH1_TX_BUFFER_COUNT; i++)
453  {
454  //Calculate the address of the current TX buffer
455  address = (uint32_t) txBuffer[i];
456  //Transmit buffer address
457  txBufferDesc[i][1] = address;
458  //Generate interrupts
459  txBufferDesc[i][2] = ENET_TBD2_INT;
460  }
461 
462  //Mark the last descriptor entry with the wrap flag
463  txBufferDesc[i - 1][0] |= ENET_TBD0_W;
464  //Initialize TX buffer index
465  txBufferIndex = 0;
466 
467  //Initialize RX buffer descriptors
468  for(i = 0; i < MCIMX6UL_ETH1_RX_BUFFER_COUNT; i++)
469  {
470  //Calculate the address of the current RX buffer
471  address = (uint32_t) rxBuffer[i];
472  //The descriptor is initially owned by the DMA
473  rxBufferDesc[i][0] = ENET_RBD0_E;
474  //Receive buffer address
475  rxBufferDesc[i][1] = address;
476  //Generate interrupts
477  rxBufferDesc[i][2] = ENET_RBD2_INT;
478  }
479 
480  //Mark the last descriptor entry with the wrap flag
481  rxBufferDesc[i - 1][0] |= ENET_RBD0_W;
482  //Initialize RX buffer index
483  rxBufferIndex = 0;
484 
485  //Start location of the TX descriptor list
486  ENET1->TDSR = (uint32_t) txBufferDesc;
487  //Start location of the RX descriptor list
488  ENET1->RDSR = (uint32_t) rxBufferDesc;
489  //Maximum receive buffer size
490  ENET1->MRBR = MCIMX6UL_ETH1_RX_BUFFER_SIZE;
491 }
492 
493 
494 /**
495  * @brief i.MX6UL Ethernet MAC timer handler
496  *
497  * This routine is periodically called by the TCP/IP stack to handle periodic
498  * operations such as polling the link state
499  *
500  * @param[in] interface Underlying network interface
501  **/
502 
504 {
505  //Valid Ethernet PHY or switch driver?
506  if(interface->phyDriver != NULL)
507  {
508  //Handle periodic operations
509  interface->phyDriver->tick(interface);
510  }
511  else if(interface->switchDriver != NULL)
512  {
513  //Handle periodic operations
514  interface->switchDriver->tick(interface);
515  }
516  else
517  {
518  //Just for sanity
519  }
520 }
521 
522 
523 /**
524  * @brief Enable interrupts
525  * @param[in] interface Underlying network interface
526  **/
527 
529 {
530  //Enable Ethernet MAC interrupts
531  GIC_EnableIRQ(ENET1_IRQn);
532 
533  //Valid Ethernet PHY or switch driver?
534  if(interface->phyDriver != NULL)
535  {
536  //Enable Ethernet PHY interrupts
537  interface->phyDriver->enableIrq(interface);
538  }
539  else if(interface->switchDriver != NULL)
540  {
541  //Enable Ethernet switch interrupts
542  interface->switchDriver->enableIrq(interface);
543  }
544  else
545  {
546  //Just for sanity
547  }
548 }
549 
550 
551 /**
552  * @brief Disable interrupts
553  * @param[in] interface Underlying network interface
554  **/
555 
557 {
558  //Disable Ethernet MAC interrupts
559  GIC_DisableIRQ(ENET1_IRQn);
560 
561  //Valid Ethernet PHY or switch driver?
562  if(interface->phyDriver != NULL)
563  {
564  //Disable Ethernet PHY interrupts
565  interface->phyDriver->disableIrq(interface);
566  }
567  else if(interface->switchDriver != NULL)
568  {
569  //Disable Ethernet switch interrupts
570  interface->switchDriver->disableIrq(interface);
571  }
572  else
573  {
574  //Just for sanity
575  }
576 }
577 
578 
579 /**
580  * @brief Ethernet MAC interrupt (ENET1 instance)
581  * @param[in] giccIar Value of the GICC_IAR register
582  * @param[in] userParam User parameter
583  **/
584 
585 void ENET1_DriverIRQHandler(uint32_t giccIar, void *userParam)
586 {
587  bool_t flag;
588  uint32_t events;
589 
590  //Interrupt service routine prologue
591  osEnterIsr();
592 
593  //This flag will be set if a higher priority task must be woken
594  flag = FALSE;
595  //Read interrupt event register
596  events = ENET1->EIR;
597 
598  //Packet transmitted?
599  if((events & ENET_EIR_TXF_MASK) != 0)
600  {
601  //Clear TXF interrupt flag
602  ENET1->EIR = ENET_EIR_TXF_MASK;
603 
604  //Check whether the TX buffer is available for writing
605  if((txBufferDesc[txBufferIndex][0] & ENET_TBD0_R) == 0)
606  {
607  //Notify the TCP/IP stack that the transmitter is ready to send
608  flag = osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
609  }
610 
611  //Instruct the DMA to poll the transmit descriptor list
612  ENET1->TDAR = ENET_TDAR_TDAR_MASK;
613  }
614 
615  //Packet received?
616  if((events & ENET_EIR_RXF_MASK) != 0)
617  {
618  //Disable RXF interrupt
619  ENET1->EIMR &= ~ENET_EIMR_RXF_MASK;
620 
621  //Set event flag
622  nicDriverInterface->nicEvent = TRUE;
623  //Notify the TCP/IP stack of the event
624  flag = osSetEventFromIsr(&netEvent);
625  }
626 
627  //System bus error?
628  if((events & ENET_EIR_EBERR_MASK) != 0)
629  {
630  //Disable EBERR interrupt
631  ENET1->EIMR &= ~ENET_EIMR_EBERR_MASK;
632 
633  //Set event flag
634  nicDriverInterface->nicEvent = TRUE;
635  //Notify the TCP/IP stack of the event
636  flag |= osSetEventFromIsr(&netEvent);
637  }
638 
639  //Interrupt service routine epilogue
640  osExitIsr(flag);
641 }
642 
643 
644 /**
645  * @brief i.MX6UL Ethernet MAC event handler
646  * @param[in] interface Underlying network interface
647  **/
648 
650 {
651  error_t error;
652  uint32_t status;
653 
654  //Read interrupt event register
655  status = ENET1->EIR;
656 
657  //Packet received?
658  if((status & ENET_EIR_RXF_MASK) != 0)
659  {
660  //Clear RXF interrupt flag
661  ENET1->EIR = ENET_EIR_RXF_MASK;
662 
663  //Process all pending packets
664  do
665  {
666  //Read incoming packet
667  error = mcimx6ulEth1ReceivePacket(interface);
668 
669  //No more data in the receive buffer?
670  } while(error != ERROR_BUFFER_EMPTY);
671  }
672 
673  //System bus error?
674  if((status & ENET_EIR_EBERR_MASK) != 0)
675  {
676  //Clear EBERR interrupt flag
677  ENET1->EIR = ENET_EIR_EBERR_MASK;
678 
679  //Disable Ethernet MAC
680  ENET1->ECR &= ~ENET_ECR_ETHEREN_MASK;
681  //Reset buffer descriptors
682  mcimx6ulEth1InitBufferDesc(interface);
683  //Resume normal operation
684  ENET1->ECR |= ENET_ECR_ETHEREN_MASK;
685  //Instruct the DMA to poll the receive descriptor list
686  ENET1->RDAR = ENET_RDAR_RDAR_MASK;
687  }
688 
689  //Re-enable Ethernet MAC interrupts
690  ENET1->EIMR = ENET_EIMR_TXF_MASK | ENET_EIMR_RXF_MASK | ENET_EIMR_EBERR_MASK;
691 }
692 
693 
694 /**
695  * @brief Send a packet
696  * @param[in] interface Underlying network interface
697  * @param[in] buffer Multi-part buffer containing the data to send
698  * @param[in] offset Offset to the first data byte
699  * @param[in] ancillary Additional options passed to the stack along with
700  * the packet
701  * @return Error code
702  **/
703 
705  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
706 {
707  static uint32_t temp[MCIMX6UL_ETH1_TX_BUFFER_SIZE / 4];
708  size_t length;
709 
710  //Retrieve the length of the packet
711  length = netBufferGetLength(buffer) - offset;
712 
713  //Check the frame length
715  {
716  //The transmitter can accept another packet
717  osSetEvent(&interface->nicTxEvent);
718  //Report an error
719  return ERROR_INVALID_LENGTH;
720  }
721 
722  //Make sure the current buffer is available for writing
723  if((txBufferDesc[txBufferIndex][0] & ENET_TBD0_R) != 0)
724  {
725  return ERROR_FAILURE;
726  }
727 
728  //Copy user data to the transmit buffer
729  netBufferRead(temp, buffer, offset, length);
730  osMemcpy(txBuffer[txBufferIndex], temp, (length + 3) & ~3UL);
731 
732  //Clear BDU flag
733  txBufferDesc[txBufferIndex][4] = 0;
734 
735  //Check current index
736  if(txBufferIndex < (MCIMX6UL_ETH1_TX_BUFFER_COUNT - 1))
737  {
738  //Give the ownership of the descriptor to the DMA engine
739  txBufferDesc[txBufferIndex][0] = ENET_TBD0_R | ENET_TBD0_L |
741 
742  //Point to the next buffer
743  txBufferIndex++;
744  }
745  else
746  {
747  //Give the ownership of the descriptor to the DMA engine
748  txBufferDesc[txBufferIndex][0] = ENET_TBD0_R | ENET_TBD0_W |
750 
751  //Wrap around
752  txBufferIndex = 0;
753  }
754 
755  //Data synchronization barrier
756  __DSB();
757 
758  //Instruct the DMA to poll the transmit descriptor list
759  ENET1->TDAR = ENET_TDAR_TDAR_MASK;
760 
761  //Check whether the next buffer is available for writing
762  if((txBufferDesc[txBufferIndex][0] & ENET_TBD0_R) == 0)
763  {
764  //The transmitter can accept another packet
765  osSetEvent(&interface->nicTxEvent);
766  }
767 
768  //Successful processing
769  return NO_ERROR;
770 }
771 
772 
773 /**
774  * @brief Receive a packet
775  * @param[in] interface Underlying network interface
776  * @return Error code
777  **/
778 
780 {
781  static uint32_t temp[MCIMX6UL_ETH1_RX_BUFFER_SIZE / 4];
782  error_t error;
783  size_t n;
784  NetRxAncillary ancillary;
785 
786  //Current buffer available for reading?
787  if((rxBufferDesc[rxBufferIndex][0] & ENET_RBD0_E) == 0)
788  {
789  //The frame should not span multiple buffers
790  if((rxBufferDesc[rxBufferIndex][0] & ENET_RBD0_L) != 0)
791  {
792  //Check whether an error occurred
793  if((rxBufferDesc[rxBufferIndex][0] & (ENET_RBD0_LG | ENET_RBD0_NO |
795  {
796  //Retrieve the length of the frame
797  n = rxBufferDesc[rxBufferIndex][0] & ENET_RBD0_DATA_LENGTH;
798  //Limit the number of data to read
800 
801  //Copy data from the receive buffer
802  osMemcpy(temp, rxBuffer[rxBufferIndex], (n + 3) & ~3UL);
803 
804  //Additional options can be passed to the stack along with the packet
805  ancillary = NET_DEFAULT_RX_ANCILLARY;
806 
807  //Pass the packet to the upper layer
808  nicProcessPacket(interface, (uint8_t *) temp, n, &ancillary);
809 
810  //Valid packet received
811  error = NO_ERROR;
812  }
813  else
814  {
815  //The received packet contains an error
816  error = ERROR_INVALID_PACKET;
817  }
818  }
819  else
820  {
821  //The packet is not valid
822  error = ERROR_INVALID_PACKET;
823  }
824 
825  //Clear BDU flag
826  rxBufferDesc[rxBufferIndex][4] = 0;
827 
828  //Check current index
829  if(rxBufferIndex < (MCIMX6UL_ETH1_RX_BUFFER_COUNT - 1))
830  {
831  //Give the ownership of the descriptor back to the DMA engine
832  rxBufferDesc[rxBufferIndex][0] = ENET_RBD0_E;
833  //Point to the next buffer
834  rxBufferIndex++;
835  }
836  else
837  {
838  //Give the ownership of the descriptor back to the DMA engine
839  rxBufferDesc[rxBufferIndex][0] = ENET_RBD0_E | ENET_RBD0_W;
840  //Wrap around
841  rxBufferIndex = 0;
842  }
843 
844  //Instruct the DMA to poll the receive descriptor list
845  ENET1->RDAR = ENET_RDAR_RDAR_MASK;
846  }
847  else
848  {
849  //No more data in the receive buffer
850  error = ERROR_BUFFER_EMPTY;
851  }
852 
853  //Return status code
854  return error;
855 }
856 
857 
858 /**
859  * @brief Configure MAC address filtering
860  * @param[in] interface Underlying network interface
861  * @return Error code
862  **/
863 
865 {
866  uint_t i;
867  uint_t k;
868  uint32_t crc;
869  uint32_t value;
870  uint32_t unicastHashTable[2];
871  uint32_t multicastHashTable[2];
872  MacFilterEntry *entry;
873 
874  //Debug message
875  TRACE_DEBUG("Updating MAC filter...\r\n");
876 
877  //Set the MAC address of the station (upper 16 bits)
878  value = interface->macAddr.b[5];
879  value |= (interface->macAddr.b[4] << 8);
880  ENET1->PAUR = ENET_PAUR_PADDR2(value) | ENET_PAUR_TYPE(0x8808);
881 
882  //Set the MAC address of the station (lower 32 bits)
883  value = interface->macAddr.b[3];
884  value |= (interface->macAddr.b[2] << 8);
885  value |= (interface->macAddr.b[1] << 16);
886  value |= (interface->macAddr.b[0] << 24);
887  ENET1->PALR = ENET_PALR_PADDR1(value);
888 
889  //Clear hash table (unicast address filtering)
890  unicastHashTable[0] = 0;
891  unicastHashTable[1] = 0;
892 
893  //Clear hash table (multicast address filtering)
894  multicastHashTable[0] = 0;
895  multicastHashTable[1] = 0;
896 
897  //The MAC address filter contains the list of MAC addresses to accept
898  //when receiving an Ethernet frame
899  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
900  {
901  //Point to the current entry
902  entry = &interface->macAddrFilter[i];
903 
904  //Valid entry?
905  if(entry->refCount > 0)
906  {
907  //Compute CRC over the current MAC address
908  crc = mcimx6ulEth1CalcCrc(&entry->addr, sizeof(MacAddr));
909 
910  //The upper 6 bits in the CRC register are used to index the
911  //contents of the hash table
912  k = (crc >> 26) & 0x3F;
913 
914  //Multicast address?
915  if(macIsMulticastAddr(&entry->addr))
916  {
917  //Update the multicast hash table
918  multicastHashTable[k / 32] |= (1 << (k % 32));
919  }
920  else
921  {
922  //Update the unicast hash table
923  unicastHashTable[k / 32] |= (1 << (k % 32));
924  }
925  }
926  }
927 
928  //Write the hash table (unicast address filtering)
929  ENET1->IALR = unicastHashTable[0];
930  ENET1->IAUR = unicastHashTable[1];
931 
932  //Write the hash table (multicast address filtering)
933  ENET1->GALR = multicastHashTable[0];
934  ENET1->GAUR = multicastHashTable[1];
935 
936  //Debug message
937  TRACE_DEBUG(" IALR = %08" PRIX32 "\r\n", ENET1->IALR);
938  TRACE_DEBUG(" IAUR = %08" PRIX32 "\r\n", ENET1->IAUR);
939  TRACE_DEBUG(" GALR = %08" PRIX32 "\r\n", ENET1->GALR);
940  TRACE_DEBUG(" GAUR = %08" PRIX32 "\r\n", ENET1->GAUR);
941 
942  //Successful processing
943  return NO_ERROR;
944 }
945 
946 
947 /**
948  * @brief Adjust MAC configuration parameters for proper operation
949  * @param[in] interface Underlying network interface
950  * @return Error code
951  **/
952 
954 {
955  //Disable Ethernet MAC while modifying configuration registers
956  ENET1->ECR &= ~ENET_ECR_ETHEREN_MASK;
957 
958  //10BASE-T or 100BASE-TX operation mode?
959  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
960  {
961  //100 Mbps operation
962  ENET1->RCR &= ~ENET_RCR_RMII_10T_MASK;
963  }
964  else
965  {
966  //10 Mbps operation
967  ENET1->RCR |= ENET_RCR_RMII_10T_MASK;
968  }
969 
970  //Half-duplex or full-duplex mode?
971  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
972  {
973  //Full-duplex mode
974  ENET1->TCR |= ENET_TCR_FDEN_MASK;
975  //Receive path operates independently of transmit
976  ENET1->RCR &= ~ENET_RCR_DRT_MASK;
977  }
978  else
979  {
980  //Half-duplex mode
981  ENET1->TCR &= ~ENET_TCR_FDEN_MASK;
982  //Disable reception of frames while transmitting
983  ENET1->RCR |= ENET_RCR_DRT_MASK;
984  }
985 
986  //Reset buffer descriptors
987  mcimx6ulEth1InitBufferDesc(interface);
988 
989  //Re-enable Ethernet MAC
990  ENET1->ECR |= ENET_ECR_ETHEREN_MASK;
991  //Instruct the DMA to poll the receive descriptor list
992  ENET1->RDAR = ENET_RDAR_RDAR_MASK;
993 
994  //Successful processing
995  return NO_ERROR;
996 }
997 
998 
999 /**
1000  * @brief Write PHY register
1001  * @param[in] opcode Access type (2 bits)
1002  * @param[in] phyAddr PHY address (5 bits)
1003  * @param[in] regAddr Register address (5 bits)
1004  * @param[in] data Register value
1005  **/
1006 
1007 void mcimx6ulEth1WritePhyReg(uint8_t opcode, uint8_t phyAddr,
1008  uint8_t regAddr, uint16_t data)
1009 {
1010  uint32_t temp;
1011 
1012  //Valid opcode?
1013  if(opcode == SMI_OPCODE_WRITE)
1014  {
1015  //Set up a write operation
1016  temp = ENET_MMFR_ST(1) | ENET_MMFR_OP(1) | ENET_MMFR_TA(2);
1017  //PHY address
1018  temp |= ENET_MMFR_PA(phyAddr);
1019  //Register address
1020  temp |= ENET_MMFR_RA(regAddr);
1021  //Register value
1022  temp |= ENET_MMFR_DATA(data);
1023 
1024  //Clear MII interrupt flag
1025  ENET1->EIR = ENET_EIR_MII_MASK;
1026  //Start a write operation
1027  ENET1->MMFR = temp;
1028 
1029  //Wait for the write to complete
1030  while((ENET1->EIR & ENET_EIR_MII_MASK) == 0)
1031  {
1032  }
1033  }
1034  else
1035  {
1036  //The MAC peripheral only supports standard Clause 22 opcodes
1037  }
1038 }
1039 
1040 
1041 /**
1042  * @brief Read PHY register
1043  * @param[in] opcode Access type (2 bits)
1044  * @param[in] phyAddr PHY address (5 bits)
1045  * @param[in] regAddr Register address (5 bits)
1046  * @return Register value
1047  **/
1048 
1049 uint16_t mcimx6ulEth1ReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1050  uint8_t regAddr)
1051 {
1052  uint16_t data;
1053  uint32_t temp;
1054 
1055  //Valid opcode?
1056  if(opcode == SMI_OPCODE_READ)
1057  {
1058  //Set up a read operation
1059  temp = ENET_MMFR_ST(1) | ENET_MMFR_OP(2) | ENET_MMFR_TA(2);
1060  //PHY address
1061  temp |= ENET_MMFR_PA(phyAddr);
1062  //Register address
1063  temp |= ENET_MMFR_RA(regAddr);
1064 
1065  //Clear MII interrupt flag
1066  ENET1->EIR = ENET_EIR_MII_MASK;
1067  //Start a read operation
1068  ENET1->MMFR = temp;
1069 
1070  //Wait for the read to complete
1071  while((ENET1->EIR & ENET_EIR_MII_MASK) == 0)
1072  {
1073  }
1074 
1075  //Get register value
1076  data = ENET1->MMFR & ENET_MMFR_DATA_MASK;
1077  }
1078  else
1079  {
1080  //The MAC peripheral only supports standard Clause 22 opcodes
1081  data = 0;
1082  }
1083 
1084  //Return the value of the PHY register
1085  return data;
1086 }
1087 
1088 
1089 /**
1090  * @brief CRC calculation
1091  * @param[in] data Pointer to the data over which to calculate the CRC
1092  * @param[in] length Number of bytes to process
1093  * @return Resulting CRC value
1094  **/
1095 
1096 uint32_t mcimx6ulEth1CalcCrc(const void *data, size_t length)
1097 {
1098  uint_t i;
1099  uint_t j;
1100  uint32_t crc;
1101  const uint8_t *p;
1102 
1103  //Point to the data over which to calculate the CRC
1104  p = (uint8_t *) data;
1105  //CRC preset value
1106  crc = 0xFFFFFFFF;
1107 
1108  //Loop through data
1109  for(i = 0; i < length; i++)
1110  {
1111  //Update CRC value
1112  crc ^= p[i];
1113 
1114  //The message is processed bit by bit
1115  for(j = 0; j < 8; j++)
1116  {
1117  if((crc & 0x01) != 0)
1118  {
1119  crc = (crc >> 1) ^ 0xEDB88320;
1120  }
1121  else
1122  {
1123  crc = crc >> 1;
1124  }
1125  }
1126  }
1127 
1128  //Return CRC value
1129  return crc;
1130 }
#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
error_t
Error codes.
Definition: error.h:43
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PACKET
Definition: error.h:140
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
MacAddr
Definition: ethernet.h:195
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
Ipv6Addr address[]
Definition: ipv6.h:316
error_t mcimx6ulEth1SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
uint32_t mcimx6ulEth1CalcCrc(const void *data, size_t length)
CRC calculation.
error_t mcimx6ulEth1Init(NetInterface *interface)
i.MX6UL Ethernet MAC initialization
void mcimx6ulEth1DisableIrq(NetInterface *interface)
Disable interrupts.
__weak_func void mcimx6ulEth1InitGpio(NetInterface *interface)
GPIO configuration.
error_t mcimx6ulEth1UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
error_t mcimx6ulEth1ReceivePacket(NetInterface *interface)
Receive a packet.
const NicDriver mcimx6ulEth1Driver
i.MX6UL Ethernet MAC driver (ENET1 instance)
void ENET1_DriverIRQHandler(uint32_t giccIar, void *userParam)
Ethernet MAC interrupt (ENET1 instance)
void mcimx6ulEth1InitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
void mcimx6ulEth1Tick(NetInterface *interface)
i.MX6UL Ethernet MAC timer handler
uint16_t mcimx6ulEth1ReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
void mcimx6ulEth1EventHandler(NetInterface *interface)
i.MX6UL Ethernet MAC event handler
void mcimx6ulEth1EnableIrq(NetInterface *interface)
Enable interrupts.
error_t mcimx6ulEth1UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void mcimx6ulEth1WritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
NXP i.MX6UL Ethernet MAC driver (ENET1 instance)
#define ENET_RBD0_E
#define ENET_RBD0_DATA_LENGTH
#define ENET_TBD2_INT
#define ENET_TBD0_W
#define ENET_TBD0_R
#define ENET_RBD0_L
#define ENET_RBD0_NO
#define MCIMX6UL_ETH1_IRQ_PRIORITY
#define ENET_RBD0_W
#define ENET_RBD0_LG
#define ENET_TBD0_DATA_LENGTH
#define ENET_RBD2_INT
#define MCIMX6UL_ETH1_RX_BUFFER_SIZE
#define ENET_RBD0_OV
#define MCIMX6UL_ETH1_RX_BUFFER_COUNT
#define ENET_TBD0_TC
#define MCIMX6UL_ETH1_TX_BUFFER_SIZE
#define ENET_RBD0_CR
#define ENET_TBD0_L
#define MCIMX6UL_ETH1_TX_BUFFER_COUNT
#define ENET_RBD0_TR
#define MCIMX6UL_ETH1_RAM_SECTION
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
#define osMemset(p, value, length)
Definition: os_port.h:135
#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
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)
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
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369