s32k344_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file s32k344_eth_driver.c
3  * @brief NXP S32K344 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "S32K344.h"
36 #include "core/net.h"
38 #include "debug.h"
39 
40 //Underlying network interface
41 static NetInterface *nicDriverInterface;
42 
43 //IAR EWARM compiler?
44 #if defined(__ICCARM__)
45 
46 //Transmit buffer
47 #pragma data_alignment = 4
48 #pragma location = S32K344_ETH_RAM_SECTION
50 //Receive buffer
51 #pragma data_alignment = 4
52 #pragma location = S32K344_ETH_RAM_SECTION
54 //Transmit DMA descriptors
55 #pragma data_alignment = 4
56 #pragma location = S32K344_ETH_RAM_SECTION
58 //Receive DMA descriptors
59 #pragma data_alignment = 4
60 #pragma location = S32K344_ETH_RAM_SECTION
62 
63 //Keil MDK-ARM or GCC compiler?
64 #else
65 
66 //Transmit buffer
68  __attribute__((aligned(4), __section__(S32K344_ETH_RAM_SECTION)));
69 //Receive buffer
71  __attribute__((aligned(4), __section__(S32K344_ETH_RAM_SECTION)));
72 //Transmit DMA descriptors
74  __attribute__((aligned(4), __section__(S32K344_ETH_RAM_SECTION)));
75 //Receive DMA descriptors
77  __attribute__((aligned(4), __section__(S32K344_ETH_RAM_SECTION)));
78 
79 #endif
80 
81 //Current transmit descriptor
82 static uint_t txIndex;
83 //Current receive descriptor
84 static uint_t rxIndex;
85 
86 
87 /**
88  * @brief S32K344 Ethernet MAC driver
89  **/
90 
92 {
94  ETH_MTU,
105  TRUE,
106  TRUE,
107  TRUE,
108  FALSE
109 };
110 
111 
112 /**
113  * @brief S32K344 Ethernet MAC initialization
114  * @param[in] interface Underlying network interface
115  * @return Error code
116  **/
117 
119 {
120  error_t error;
121  uint32_t temp;
122 
123  //Debug message
124  TRACE_INFO("Initializing S32K344 Ethernet MAC...\r\n");
125 
126  //Save underlying network interface
127  nicDriverInterface = interface;
128 
129  //GPIO configuration
130  s32k344EthInitGpio(interface);
131 
132  //Enable EMAC clock
133  IP_MC_ME->PRTN2_COFB1_CLKEN |= MC_ME_PRTN2_COFB1_CLKEN_REQ32_MASK;
134  IP_MC_ME->PRTN2_PCONF |= MC_ME_PRTN2_PCONF_PCE_MASK;
135  IP_MC_ME->PRTN2_PUPD |= MC_ME_PRTN2_PUPD_PCUD_MASK;
136  IP_MC_ME->CTL_KEY = MC_ME_CTL_KEY_KEY(0x5AF0);
137  IP_MC_ME->CTL_KEY = MC_ME_CTL_KEY_KEY(0xA50F);
138 
139  //Wait for the hardware update process to complete
140  while((IP_MC_ME->PRTN2_PUPD & MC_ME_PRTN2_PUPD_PCUD_MASK) != 0)
141  {
142  }
143 
144  //Perform a software reset
145  IP_EMAC->DMA_MODE |= EMAC_DMA_MODE_SWR_MASK;
146  //Wait for the reset to complete
147  while((IP_EMAC->DMA_MODE & EMAC_DMA_MODE_SWR_MASK) != 0)
148  {
149  }
150 
151  //Adjust MDC clock range depending on CSR frequency
152  IP_EMAC->MAC_MDIO_ADDRESS = EMAC_MAC_MDIO_ADDRESS_CR(4);
153 
154  //Valid Ethernet PHY or switch driver?
155  if(interface->phyDriver != NULL)
156  {
157  //Ethernet PHY initialization
158  error = interface->phyDriver->init(interface);
159  }
160  else if(interface->switchDriver != NULL)
161  {
162  //Ethernet switch initialization
163  error = interface->switchDriver->init(interface);
164  }
165  else
166  {
167  //The interface is not properly configured
168  error = ERROR_FAILURE;
169  }
170 
171  //Any error to report?
172  if(error)
173  {
174  return error;
175  }
176 
177  //Use default MAC configuration
178  IP_EMAC->MAC_CONFIGURATION = EMAC_MAC_CONFIGURATION_GPSLCE_MASK |
179  EMAC_MAC_CONFIGURATION_PS_MASK | EMAC_MAC_CONFIGURATION_DO_MASK;
180 
181  //Set the maximum packet size that can be accepted
182  temp = IP_EMAC->MAC_EXT_CONFIGURATION & ~EMAC_MAC_EXT_CONFIGURATION_GPSL_MASK;
183  IP_EMAC->MAC_EXT_CONFIGURATION = temp | S32K344_ETH_RX_BUFFER_SIZE;
184 
185  //Configure MAC address filtering
187 
188  //Disable flow control
189  IP_EMAC->MAC_Q0_TX_FLOW_CTRL = 0;
190  IP_EMAC->MAC_RX_FLOW_CTRL = 0;
191 
192  //Enable the first RX queue
193  IP_EMAC->MAC_RXQ_CTRL0 = EMAC_MAC_RXQ_CTRL0_RXQ0EN(2);
194 
195  //Configure DMA operating mode
196  IP_EMAC->DMA_MODE = EMAC_DMA_MODE_PR(0);
197  //Configure system bus mode
198  IP_EMAC->DMA_SYSBUS_MODE |= EMAC_DMA_SYSBUS_MODE_AAL_MASK;
199 
200  //The DMA takes the descriptor table as contiguous
201  IP_EMAC->DMA_CH0_CONTROL = EMAC_DMA_CH0_CONTROL_DSL(0);
202  //Configure TX features
203  IP_EMAC->DMA_CH0_TX_CONTROL = EMAC_DMA_CH0_TX_CONTROL_TxPBL(32);
204 
205  //Configure RX features
206  IP_EMAC->DMA_CH0_RX_CONTROL = EMAC_DMA_CH0_RX_CONTROL_RxPBL(32) |
207  EMAC_DMA_CH0_RX_CONTROL_RBSZ_13_y(S32K344_ETH_RX_BUFFER_SIZE / 4);
208 
209  //Enable store and forward mode for transmission
210  IP_EMAC->MTL_TXQ0_OPERATION_MODE |= EMAC_MTL_TXQ0_OPERATION_MODE_TQS(7) |
211  EMAC_MTL_TXQ0_OPERATION_MODE_TXQEN(2) | EMAC_MTL_TXQ0_OPERATION_MODE_TSF_MASK;
212 
213  //Enable store and forward mode for reception
214  IP_EMAC->MTL_RXQ0_OPERATION_MODE |= EMAC_MTL_RXQ0_OPERATION_MODE_RQS(7) |
215  EMAC_MTL_RXQ0_OPERATION_MODE_RSF_MASK;
216 
217  //Initialize DMA descriptor lists
218  s32k344EthInitDmaDesc(interface);
219 
220  //Prevent interrupts from being generated when statistic counters reach
221  //half their maximum value
222  IP_EMAC->MMC_TX_INTERRUPT_MASK = 0xFFFFFFFF;
223  IP_EMAC->MMC_RX_INTERRUPT_MASK = 0xFFFFFFFF;
224  IP_EMAC->MMC_FPE_TX_INTERRUPT_MASK = 0xFFFFFFFF;
225  IP_EMAC->MMC_FPE_RX_INTERRUPT_MASK = 0xFFFFFFFF;
226 
227  //Disable MAC interrupts
228  IP_EMAC->MAC_INTERRUPT_ENABLE = 0;
229 
230  //Enable the desired DMA interrupts
231  IP_EMAC->DMA_CH0_INTERRUPT_ENABLE = EMAC_DMA_CH0_INTERRUPT_ENABLE_NIE_MASK |
232  EMAC_DMA_CH0_INTERRUPT_ENABLE_RIE_MASK | EMAC_DMA_CH0_INTERRUPT_ENABLE_TIE_MASK;
233 
234  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
235  NVIC_SetPriorityGrouping(S32K344_ETH_IRQ_PRIORITY_GROUPING);
236 
237  //Configure Ethernet interrupt priority
238  NVIC_SetPriority(EMAC_0_IRQn, NVIC_EncodePriority(S32K344_ETH_IRQ_PRIORITY_GROUPING,
240 
241  //Enable MAC transmission and reception
242  IP_EMAC->MAC_CONFIGURATION |= EMAC_MAC_CONFIGURATION_TE_MASK |
243  EMAC_MAC_CONFIGURATION_RE_MASK;
244 
245  //Enable DMA transmission and reception
246  IP_EMAC->DMA_CH0_TX_CONTROL |= EMAC_DMA_CH0_TX_CONTROL_ST_MASK;
247  IP_EMAC->DMA_CH0_RX_CONTROL |= EMAC_DMA_CH0_RX_CONTROL_SR_MASK;
248 
249  //Accept any packets from the upper layer
250  osSetEvent(&interface->nicTxEvent);
251 
252  //Successful initialization
253  return NO_ERROR;
254 }
255 
256 
257 /**
258  * @brief GPIO configuration
259  * @param[in] interface Underlying network interface
260  **/
261 
262 __weak_func void s32k344EthInitGpio(NetInterface *interface)
263 {
264 //S32K344MINI-EVB evaluation board?
265 #if defined(USE_S32K344MINI_EVB)
266  //Select RMII interface mode
267  IP_DCM_GPR->DCMRWF1 |= DCM_GPR_DCMRWF1_RMII_MII_SEL_MASK;
268 
269  //Configure EMAC_MII_RMII_MDIO (PTD16)
270  IP_SIUL2->MSCR[112] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_IBE_MASK |
271  SIUL2_MSCR_PUS_MASK | SIUL2_MSCR_PUE_MASK | SIUL2_MSCR_SSS_2(0) |
272  SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(1);
273  IP_SIUL2->IMCR[291] = SIUL2_IMCR_SSS(2);
274 
275  //Configure EMAC_MII_RMII_MDC (PTD17)
276  IP_SIUL2->MSCR[113] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_SSS_2(0) |
277  SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(1);
278 
279  //Configure EMAC_MII_RMII_TX_CLK (PTC0)
280  IP_SIUL2->MSCR[64] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_IBE_MASK;
281  IP_SIUL2->IMCR[296] = SIUL2_IMCR_SSS(4);
282 
283  //Configure EMAC_MII_RMII_TX_EN (PTE9)
284  IP_SIUL2->MSCR[137] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
285  SIUL2_MSCR_SSS_2(1) | SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(0);
286 
287  //Configure EMAC_MII_RMII_TXD0 (PTB5)
288  IP_SIUL2->MSCR[37] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
289  SIUL2_MSCR_SSS_2(0) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
290 
291  //Configure EMAC_MII_RMII_TXD1 (PTB4)
292  IP_SIUL2->MSCR[36] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
293  SIUL2_MSCR_SSS_2(0) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
294 
295  //Configure EMAC_MII_RMII_RX_DV (PTC15)
296  IP_SIUL2->MSCR[79] = SIUL2_MSCR_IBE_MASK;
297  IP_SIUL2->IMCR[292] = SIUL2_IMCR_SSS(2);
298 
299  //Configure EMAC_MII_RMII_RXD0 (PTD9)
300  IP_SIUL2->MSCR[105] = SIUL2_MSCR_IBE_MASK;
301  IP_SIUL2->IMCR[294] = SIUL2_IMCR_SSS(3);
302 
303  //Configure EMAC_MII_RMII_RXD1 (PTD8)
304  IP_SIUL2->MSCR[104] = SIUL2_MSCR_IBE_MASK;
305  IP_SIUL2->IMCR[295] = SIUL2_IMCR_SSS(3);
306 
307  //Configure ENET_RESET (PTE21) as an output
308  IP_SIUL2->MSCR[149] = SIUL2_MSCR_OBE_MASK;
309 
310  //Reset PHY transceiver (hard reset)
311  IP_SIUL2->GPDO149 = 0;
312  sleep(10);
313  IP_SIUL2->GPDO149 = 1;
314  sleep(100);
315 
316  //Configure RMII clocks
318 
319 //S32K3X4EVB-Q172 evaluation board?
320 #elif defined(USE_S32K3X4EVB_Q172)
321  //Select RMII interface mode
322  IP_DCM_GPR->DCMRWF1 |= DCM_GPR_DCMRWF1_RMII_MII_SEL_MASK;
323 
324  //Configure EMAC_MII_RMII_MDIO (PTD16)
325  IP_SIUL2->MSCR[112] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_IBE_MASK |
326  SIUL2_MSCR_PUS_MASK | SIUL2_MSCR_PUE_MASK | SIUL2_MSCR_SSS_2(0) |
327  SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(1);
328  IP_SIUL2->IMCR[291] = SIUL2_IMCR_SSS(2);
329 
330  //Configure EMAC_MII_RMII_MDC (PTD17)
331  IP_SIUL2->MSCR[113] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_SSS_2(0) |
332  SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(1);
333 
334  //Configure EMAC_MII_RMII_TX_CLK (PTC0)
335  IP_SIUL2->MSCR[64] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_IBE_MASK;
336  IP_SIUL2->IMCR[296] = SIUL2_IMCR_SSS(4);
337 
338  //Configure EMAC_MII_RMII_TX_EN (PTE9)
339  IP_SIUL2->MSCR[137] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
340  SIUL2_MSCR_SSS_2(1) | SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(0);
341 
342  //Configure EMAC_MII_RMII_TXD0 (PTB5)
343  IP_SIUL2->MSCR[37] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
344  SIUL2_MSCR_SSS_2(0) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
345 
346  //Configure EMAC_MII_RMII_TXD1 (PTB4)
347  IP_SIUL2->MSCR[36] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
348  SIUL2_MSCR_SSS_2(0) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
349 
350  //Configure EMAC_MII_RMII_RX_DV (PTC17)
351  IP_SIUL2->MSCR[81] = SIUL2_MSCR_IBE_MASK;
352  IP_SIUL2->IMCR[292] = SIUL2_IMCR_SSS(1);
353 
354  //Configure EMAC_MII_RMII_RXD0 (PTD9)
355  IP_SIUL2->MSCR[105] = SIUL2_MSCR_IBE_MASK;
356  IP_SIUL2->IMCR[294] = SIUL2_IMCR_SSS(3);
357 
358  //Configure EMAC_MII_RMII_RXD1 (PTD8)
359  IP_SIUL2->MSCR[104] = SIUL2_MSCR_IBE_MASK;
360  IP_SIUL2->IMCR[295] = SIUL2_IMCR_SSS(3);
361 
362  //Configure ENET_RESET (PTE21) as an output
363  IP_SIUL2->MSCR[149] = SIUL2_MSCR_OBE_MASK;
364 
365  //Reset PHY transceiver (hard reset)
366  IP_SIUL2->GPDO149 = 0;
367  sleep(10);
368  IP_SIUL2->GPDO149 = 1;
369  sleep(100);
370 
371  //Configure RMII clocks
373 
374 //S32K3X4EVB-T172 evaluation board?
375 #elif defined(USE_S32K3X4EVB_T172)
376  //Select RMII interface mode
377  IP_DCM_GPR->DCMRWF1 |= DCM_GPR_DCMRWF1_RMII_MII_SEL_MASK;
378 
379  //Configure EMAC_MII_RMII_MDIO (PTB4)
380  IP_SIUL2->MSCR[36] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_IBE_MASK |
381  SIUL2_MSCR_PUS_MASK | SIUL2_MSCR_PUE_MASK | SIUL2_MSCR_SSS_2(1) |
382  SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
383  IP_SIUL2->IMCR[291] = SIUL2_IMCR_SSS(1);
384 
385  //Configure EMAC_MII_RMII_MDC (PTB5)
386  IP_SIUL2->MSCR[37] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_SSS_2(1) |
387  SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(1);
388 
389  //Configure EMAC_MII_RMII_TX_CLK (PTD11)
390  IP_SIUL2->MSCR[107] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_IBE_MASK;
391  IP_SIUL2->IMCR[296] = SIUL2_IMCR_SSS(1);
392 
393  //Configure EMAC_MII_RMII_TX_EN (PTD12)
394  IP_SIUL2->MSCR[108] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
395  SIUL2_MSCR_SSS_2(1) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
396 
397  //Configure EMAC_MII_RMII_TXD0 (PTC2)
398  IP_SIUL2->MSCR[66] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
399  SIUL2_MSCR_SSS_2(1) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
400 
401  //Configure EMAC_MII_RMII_TXD1 (PTD7)
402  IP_SIUL2->MSCR[103] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
403  SIUL2_MSCR_SSS_2(1) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
404 
405  //Configure EMAC_MII_RMII_RX_DV (PTC17)
406  IP_SIUL2->MSCR[81] = SIUL2_MSCR_IBE_MASK;
407  IP_SIUL2->IMCR[292] = SIUL2_IMCR_SSS(1);
408 
409  //Configure EMAC_MII_RMII_RX_ER (PTC16)
410  IP_SIUL2->MSCR[80] = SIUL2_MSCR_IBE_MASK;
411  IP_SIUL2->IMCR[293] = SIUL2_IMCR_SSS(1);
412 
413  //Configure EMAC_MII_RMII_RXD0 (PTC1)
414  IP_SIUL2->MSCR[65] = SIUL2_MSCR_IBE_MASK;
415  IP_SIUL2->IMCR[294] = SIUL2_IMCR_SSS(1);
416 
417  //Configure EMAC_MII_RMII_RXD1 (PTC0)
418  IP_SIUL2->MSCR[64] = SIUL2_MSCR_IBE_MASK;
419  IP_SIUL2->IMCR[295] = SIUL2_IMCR_SSS(1);
420 
421  //Configure ENET_RSTN (PTA28) as an output
422  IP_SIUL2->MSCR[28] = SIUL2_MSCR_OBE_MASK;
423 
424  //Reset PHY transceiver (hard reset)
425  IP_SIUL2->GPDO28 = 0;
426  sleep(10);
427  IP_SIUL2->GPDO28 = 1;
428  sleep(100);
429 
430  //Configure RMII clocks
432 
433 //S32K344-WB evaluation board?
434 #elif defined(USE_S32K344_WB)
435  //Select RMII interface mode
436  IP_DCM_GPR->DCMRWF1 |= DCM_GPR_DCMRWF1_RMII_MII_SEL_MASK;
437 
438  //Configure EMAC_MII_RMII_MDIO (PTD16)
439  IP_SIUL2->MSCR[112] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_IBE_MASK |
440  SIUL2_MSCR_PUS_MASK | SIUL2_MSCR_PUE_MASK | SIUL2_MSCR_SSS_2(0) |
441  SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(1);
442  IP_SIUL2->IMCR[291] = SIUL2_IMCR_SSS(2);
443 
444  //Configure EMAC_MII_RMII_MDC (PTE8)
445  IP_SIUL2->MSCR[136] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_SSS_2(1) |
446  SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
447 
448  //Configure EMAC_MII_RMII_TX_CLK (PTD6)
449  IP_SIUL2->MSCR[102] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_IBE_MASK;
450  IP_SIUL2->IMCR[296] = SIUL2_IMCR_SSS(2);
451 
452  //Configure EMAC_MII_RMII_TX_EN (PTE9)
453  IP_SIUL2->MSCR[137] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
454  SIUL2_MSCR_SSS_2(1) | SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(0);
455 
456  //Configure EMAC_MII_RMII_TXD0 (PTB5)
457  IP_SIUL2->MSCR[37] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
458  SIUL2_MSCR_SSS_2(0) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
459 
460  //Configure EMAC_MII_RMII_TXD1 (PTB4)
461  IP_SIUL2->MSCR[36] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
462  SIUL2_MSCR_SSS_2(0) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
463 
464  //Configure EMAC_MII_RMII_RX_DV (PTC17)
465  IP_SIUL2->MSCR[81] = SIUL2_MSCR_IBE_MASK;
466  IP_SIUL2->IMCR[292] = SIUL2_IMCR_SSS(1);
467 
468  //Configure EMAC_MII_RMII_RX_ER (PTC16)
469  IP_SIUL2->MSCR[80] = SIUL2_MSCR_IBE_MASK;
470  IP_SIUL2->IMCR[293] = SIUL2_IMCR_SSS(1);
471 
472  //Configure EMAC_MII_RMII_RXD0 (PTC0)
473  IP_SIUL2->MSCR[64] = SIUL2_MSCR_IBE_MASK;
474  IP_SIUL2->IMCR[294] = SIUL2_IMCR_SSS(2);
475 
476  //Configure EMAC_MII_RMII_RXD1 (PTC1)
477  IP_SIUL2->MSCR[65] = SIUL2_MSCR_IBE_MASK;
478  IP_SIUL2->IMCR[295] = SIUL2_IMCR_SSS(2);
479 
480  //Configure RMII clocks
482 
483 //MR-CANHUBK344 evaluation board?
484 #elif defined(USE_MR_CANHUBK344)
485  //Select RMII interface mode
486  IP_DCM_GPR->DCMRWF1 |= DCM_GPR_DCMRWF1_RMII_MII_SEL_MASK;
487 
488  //Configure EMAC_MII_RMII_MDIO (PTD16)
489  IP_SIUL2->MSCR[112] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_IBE_MASK |
490  SIUL2_MSCR_PUS_MASK | SIUL2_MSCR_PUE_MASK | SIUL2_MSCR_SSS_2(0) |
491  SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(1);
492  IP_SIUL2->IMCR[291] = SIUL2_IMCR_SSS(2);
493 
494  //Configure EMAC_MII_RMII_MDC (PTE8)
495  IP_SIUL2->MSCR[136] = SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_SSS_2(1) |
496  SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
497 
498  //Configure EMAC_MII_RMII_TX_CLK (PTD6)
499  IP_SIUL2->MSCR[102] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_IBE_MASK;
500  IP_SIUL2->IMCR[296] = SIUL2_IMCR_SSS(2);
501 
502  //Configure EMAC_MII_RMII_TX_EN (PTE9)
503  IP_SIUL2->MSCR[137] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
504  SIUL2_MSCR_SSS_2(1) | SIUL2_MSCR_SSS_1(1) | SIUL2_MSCR_SSS_0(0);
505 
506  //Configure EMAC_MII_RMII_TXD0 (PTB5)
507  IP_SIUL2->MSCR[37] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
508  SIUL2_MSCR_SSS_2(0) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
509 
510  //Configure EMAC_MII_RMII_TXD1 (PTB4)
511  IP_SIUL2->MSCR[36] = SIUL2_MSCR_SRC(1) | SIUL2_MSCR_OBE_MASK |
512  SIUL2_MSCR_SSS_2(0) | SIUL2_MSCR_SSS_1(0) | SIUL2_MSCR_SSS_0(1);
513 
514  //Configure EMAC_MII_RMII_RX_DV (PTC15)
515  IP_SIUL2->MSCR[79] = SIUL2_MSCR_IBE_MASK;
516  IP_SIUL2->IMCR[292] = SIUL2_IMCR_SSS(2);
517 
518  //Configure EMAC_MII_RMII_RX_ER (PTC14)
519  IP_SIUL2->MSCR[78] = SIUL2_MSCR_IBE_MASK;
520  IP_SIUL2->IMCR[293] = SIUL2_IMCR_SSS(2);
521 
522  //Configure EMAC_MII_RMII_RXD0 (PTC0)
523  IP_SIUL2->MSCR[64] = SIUL2_MSCR_IBE_MASK;
524  IP_SIUL2->IMCR[294] = SIUL2_IMCR_SSS(2);
525 
526  //Configure EMAC_MII_RMII_RXD1 (PTC1)
527  IP_SIUL2->MSCR[65] = SIUL2_MSCR_IBE_MASK;
528  IP_SIUL2->IMCR[295] = SIUL2_IMCR_SSS(2);
529 
530  //Configure ENET_RST_N (PTB22) as an output
531  IP_SIUL2->MSCR[54] = SIUL2_MSCR_OBE_MASK;
532 
533  //Reset PHY transceiver (hard reset)
534  IP_SIUL2->GPDO54 = 0;
535  sleep(10);
536  IP_SIUL2->GPDO54 = 1;
537  sleep(100);
538 
539  //Configure RMII clocks
541 #endif
542 }
543 
544 
545 /**
546  * @brief RMII clock configuration
547  * @param[in] interface Underlying network interface
548  **/
549 
551 {
552  //Configure clock mux 7 (EMAC_TX_CLK)
553  while((IP_MC_CGM->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWIP_MASK) != 0)
554  {
555  }
556 
557  //Set 1:2 clock divider for clock mux 7
558  IP_MC_CGM->MUX_7_DC_0 = MC_CGM_MUX_7_DC_0_DE_MASK | MC_CGM_MUX_7_DC_0_DIV(1);
559  //Wait until the divider configuration update is complete
560  while((IP_MC_CGM->MUX_7_DIV_UPD_STAT & MC_CGM_MUX_7_DIV_UPD_STAT_DIV_STAT_MASK) != 0)
561  {
562  }
563 
564  //Select EMAC_RMII_TX_CLK as source clock for clock mux 7
565  IP_MC_CGM->MUX_7_CSC = MC_CGM_MUX_7_CSC_SELCTL(24) | MC_CGM_MUX_7_CSC_CLK_SW_MASK;
566  //Wait until the CLK_SW bit is set in the status register
567  while((IP_MC_CGM->MUX_7_CSS & MC_CGM_MUX_7_CSS_CLK_SW_MASK) == 0)
568  {
569  }
570 
571  //Wait until the clock source switching is complete
572  while((IP_MC_CGM->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWIP_MASK) != 0)
573  {
574  }
575 
576  //Configure clock mux 8 (EMAC_RX_CLK)
577  while((IP_MC_CGM->MUX_8_CSS & MC_CGM_MUX_8_CSS_SWIP_MASK) != 0)
578  {
579  }
580 
581  //Set 1:2 clock divider for clock mux 8
582  IP_MC_CGM->MUX_8_DC_0 = MC_CGM_MUX_8_DC_0_DE_MASK | MC_CGM_MUX_8_DC_0_DIV(1);
583  //Wait until the divider configuration update is complete
584  while((IP_MC_CGM->MUX_8_DIV_UPD_STAT & MC_CGM_MUX_8_DIV_UPD_STAT_DIV_STAT_MASK) != 0)
585  {
586  }
587 
588  //Select EMAC_RMII_TX_CLK as source clock for clock mux 8
589  IP_MC_CGM->MUX_8_CSC = MC_CGM_MUX_8_CSC_SELCTL(24) | MC_CGM_MUX_8_CSC_CLK_SW_MASK;
590  //Wait until the CLK_SW bit is set in the status register
591  while((IP_MC_CGM->MUX_8_CSS & MC_CGM_MUX_8_CSS_CLK_SW_MASK) == 0)
592  {
593  }
594 
595  //Wait until the clock source switching is complete
596  while((IP_MC_CGM->MUX_8_CSS & MC_CGM_MUX_8_CSS_SWIP_MASK) != 0)
597  {
598  }
599 
600  //Configure clock mux 9 (EMAC_TS_CLK)
601  while((IP_MC_CGM->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWIP_MASK) != 0)
602  {
603  }
604 
605  //Set 1:1 clock divider for clock mux 9
606  IP_MC_CGM->MUX_9_DC_0 = MC_CGM_MUX_9_DC_0_DE_MASK | MC_CGM_MUX_9_DC_0_DIV(0);
607  //Wait until the divider configuration update is complete
608  while((IP_MC_CGM->MUX_9_DIV_UPD_STAT & MC_CGM_MUX_9_DIV_UPD_STAT_DIV_STAT_MASK) != 0)
609  {
610  }
611 
612  //Select EMAC_RMII_TX_CLK as source clock for clock mux 9
613  IP_MC_CGM->MUX_9_CSC = MC_CGM_MUX_9_CSC_SELCTL(24) | MC_CGM_MUX_9_CSC_CLK_SW_MASK;
614  //Wait until the CLK_SW bit is set in the status register
615  while((IP_MC_CGM->MUX_9_CSS & MC_CGM_MUX_9_CSS_CLK_SW_MASK) == 0)
616  {
617  }
618 
619  //Wait until the clock source switching is complete
620  while((IP_MC_CGM->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWIP_MASK) != 0)
621  {
622  }
623 }
624 
625 
626 /**
627  * @brief Initialize DMA descriptor lists
628  * @param[in] interface Underlying network interface
629  **/
630 
632 {
633  uint_t i;
634 
635  //Initialize TX DMA descriptor list
636  for(i = 0; i < S32K344_ETH_TX_BUFFER_COUNT; i++)
637  {
638  //The descriptor is initially owned by the application
639  txDmaDesc[i].tdes0 = 0;
640  txDmaDesc[i].tdes1 = 0;
641  txDmaDesc[i].tdes2 = 0;
642  txDmaDesc[i].tdes3 = 0;
643  }
644 
645  //Initialize TX descriptor index
646  txIndex = 0;
647 
648  //Initialize RX DMA descriptor list
649  for(i = 0; i < S32K344_ETH_RX_BUFFER_COUNT; i++)
650  {
651  //The descriptor is initially owned by the DMA
653  rxDmaDesc[i].rdes1 = 0;
654  rxDmaDesc[i].rdes2 = 0;
656  }
657 
658  //Initialize RX descriptor index
659  rxIndex = 0;
660 
661  //Start location of the TX descriptor list
662  IP_EMAC->DMA_CH0_TXDESC_LIST_ADDRESS = S32K344_ETH_REMAP_ADDR(&txDmaDesc[0]);
663  //Length of the transmit descriptor ring
664  IP_EMAC->DMA_CH0_TXDESC_RING_LENGTH = S32K344_ETH_TX_BUFFER_COUNT - 1;
665 
666  //Start location of the RX descriptor list
667  IP_EMAC->DMA_CH0_RXDESC_LIST_ADDRESS = S32K344_ETH_REMAP_ADDR(&rxDmaDesc[0]);
668  //Length of the receive descriptor ring
669  IP_EMAC->DMA_CH0_RXDESC_RING_LENGTH = S32K344_ETH_RX_BUFFER_COUNT - 1;
670 }
671 
672 
673 /**
674  * @brief S32K344 Ethernet MAC timer handler
675  *
676  * This routine is periodically called by the TCP/IP stack to handle periodic
677  * operations such as polling the link state
678  *
679  * @param[in] interface Underlying network interface
680  **/
681 
682 void s32k344EthTick(NetInterface *interface)
683 {
684  //Valid Ethernet PHY or switch driver?
685  if(interface->phyDriver != NULL)
686  {
687  //Handle periodic operations
688  interface->phyDriver->tick(interface);
689  }
690  else if(interface->switchDriver != NULL)
691  {
692  //Handle periodic operations
693  interface->switchDriver->tick(interface);
694  }
695  else
696  {
697  //Just for sanity
698  }
699 }
700 
701 
702 /**
703  * @brief Enable interrupts
704  * @param[in] interface Underlying network interface
705  **/
706 
708 {
709  //Enable Ethernet MAC interrupts
710  NVIC_EnableIRQ(EMAC_0_IRQn);
711 
712  //Valid Ethernet PHY or switch driver?
713  if(interface->phyDriver != NULL)
714  {
715  //Enable Ethernet PHY interrupts
716  interface->phyDriver->enableIrq(interface);
717  }
718  else if(interface->switchDriver != NULL)
719  {
720  //Enable Ethernet switch interrupts
721  interface->switchDriver->enableIrq(interface);
722  }
723  else
724  {
725  //Just for sanity
726  }
727 }
728 
729 
730 /**
731  * @brief Disable interrupts
732  * @param[in] interface Underlying network interface
733  **/
734 
736 {
737  //Disable Ethernet MAC interrupts
738  NVIC_DisableIRQ(EMAC_0_IRQn);
739 
740  //Valid Ethernet PHY or switch driver?
741  if(interface->phyDriver != NULL)
742  {
743  //Disable Ethernet PHY interrupts
744  interface->phyDriver->disableIrq(interface);
745  }
746  else if(interface->switchDriver != NULL)
747  {
748  //Disable Ethernet switch interrupts
749  interface->switchDriver->disableIrq(interface);
750  }
751  else
752  {
753  //Just for sanity
754  }
755 }
756 
757 
758 /**
759  * @brief S32K344 Ethernet MAC interrupt service routine
760  **/
761 
763 {
764  bool_t flag;
765  uint32_t status;
766 
767  //Interrupt service routine prologue
768  osEnterIsr();
769 
770  //This flag will be set if a higher priority task must be woken
771  flag = FALSE;
772 
773  //Read DMA status register
774  status = IP_EMAC->DMA_CH0_STATUS;
775 
776  //Packet transmitted?
777  if((status & EMAC_DMA_CH0_STATUS_TI_MASK) != 0)
778  {
779  //Clear TI interrupt flag
780  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_TI_MASK;
781 
782  //Check whether the TX buffer is available for writing
783  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
784  {
785  //Notify the TCP/IP stack that the transmitter is ready to send
786  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
787  }
788  }
789 
790  //Packet received?
791  if((status & EMAC_DMA_CH0_STATUS_RI_MASK) != 0)
792  {
793  //Clear RI interrupt flag
794  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_RI_MASK;
795 
796  //Set event flag
797  nicDriverInterface->nicEvent = TRUE;
798  //Notify the TCP/IP stack of the event
799  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
800  }
801 
802  //Clear NIS interrupt flag
803  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_NIS_MASK;
804 
805  //Interrupt service routine epilogue
806  osExitIsr(flag);
807 }
808 
809 
810 /**
811  * @brief S32K344 Ethernet MAC event handler
812  * @param[in] interface Underlying network interface
813  **/
814 
816 {
817  error_t error;
818 
819  //Process all pending packets
820  do
821  {
822  //Read incoming packet
823  error = s32k344EthReceivePacket(interface);
824 
825  //No more data in the receive buffer?
826  } while(error != ERROR_BUFFER_EMPTY);
827 }
828 
829 
830 /**
831  * @brief Send a packet
832  * @param[in] interface Underlying network interface
833  * @param[in] buffer Multi-part buffer containing the data to send
834  * @param[in] offset Offset to the first data byte
835  * @param[in] ancillary Additional options passed to the stack along with
836  * the packet
837  * @return Error code
838  **/
839 
841  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
842 {
843  size_t length;
844 
845  //Retrieve the length of the packet
846  length = netBufferGetLength(buffer) - offset;
847 
848  //Check the frame length
850  {
851  //The transmitter can accept another packet
852  osSetEvent(&interface->nicTxEvent);
853  //Report an error
854  return ERROR_INVALID_LENGTH;
855  }
856 
857  //Make sure the current buffer is available for writing
858  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) != 0)
859  {
860  return ERROR_FAILURE;
861  }
862 
863  //Copy user data to the transmit buffer
864  netBufferRead(txBuffer[txIndex], buffer, offset, length);
865 
866  //Set the start address of the buffer
867  txDmaDesc[txIndex].tdes0 = S32K344_ETH_REMAP_ADDR(txBuffer[txIndex]);
868  //Write the number of bytes to send
869  txDmaDesc[txIndex].tdes2 = EMAC_TDES2_IOC | (length & EMAC_TDES2_B1L);
870  //Give the ownership of the descriptor to the DMA
872 
873  //Data synchronization barrier
874  __DSB();
875 
876  //Clear TBU flag to resume processing
877  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_TBU_MASK;
878  //Instruct the DMA to poll the transmit descriptor list
879  IP_EMAC->DMA_CH0_TXDESC_TAIL_POINTER = 0;
880 
881  //Increment index and wrap around if necessary
882  if(++txIndex >= S32K344_ETH_TX_BUFFER_COUNT)
883  {
884  txIndex = 0;
885  }
886 
887  //Check whether the next buffer is available for writing
888  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
889  {
890  //The transmitter can accept another packet
891  osSetEvent(&interface->nicTxEvent);
892  }
893 
894  //Data successfully written
895  return NO_ERROR;
896 }
897 
898 
899 /**
900  * @brief Receive a packet
901  * @param[in] interface Underlying network interface
902  * @return Error code
903  **/
904 
906 {
907  error_t error;
908  size_t n;
909  NetRxAncillary ancillary;
910 
911  //Current buffer available for reading?
912  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_OWN) == 0)
913  {
914  //FD and LD flags should be set
915  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_FD) != 0 &&
916  (rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_LD) != 0)
917  {
918  //Make sure no error occurred
919  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_ES) == 0)
920  {
921  //Retrieve the length of the frame
922  n = rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_PL;
923  //Limit the number of data to read
925 
926  //Additional options can be passed to the stack along with the packet
927  ancillary = NET_DEFAULT_RX_ANCILLARY;
928 
929  //Pass the packet to the upper layer
930  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
931 
932  //Valid packet received
933  error = NO_ERROR;
934  }
935  else
936  {
937  //The received packet contains an error
938  error = ERROR_INVALID_PACKET;
939  }
940  }
941  else
942  {
943  //The packet is not valid
944  error = ERROR_INVALID_PACKET;
945  }
946 
947  //Set the start address of the buffer
948  rxDmaDesc[rxIndex].rdes0 = S32K344_ETH_REMAP_ADDR(rxBuffer[rxIndex]);
949  //Give the ownership of the descriptor back to the DMA
951 
952  //Increment index and wrap around if necessary
953  if(++rxIndex >= S32K344_ETH_RX_BUFFER_COUNT)
954  {
955  rxIndex = 0;
956  }
957  }
958  else
959  {
960  //No more data in the receive buffer
961  error = ERROR_BUFFER_EMPTY;
962  }
963 
964  //Clear RBU flag to resume processing
965  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_RBU_MASK;
966  //Instruct the DMA to poll the receive descriptor list
967  IP_EMAC->DMA_CH0_RXDESC_TAIL_POINTER = 0;
968 
969  //Return status code
970  return error;
971 }
972 
973 
974 /**
975  * @brief Configure MAC address filtering
976  * @param[in] interface Underlying network interface
977  * @return Error code
978  **/
979 
981 {
982  uint_t i;
983  uint_t j;
984  uint_t k;
985  uint32_t crc;
986  uint32_t hashTable[2];
987  MacAddr unicastMacAddr[2];
988  MacFilterEntry *entry;
989 
990  //Debug message
991  TRACE_DEBUG("Updating MAC filter...\r\n");
992 
993  //Promiscuous mode?
994  if(interface->promiscuous)
995  {
996  //Pass all incoming frames regardless of their destination address
997  IP_EMAC->MAC_PACKET_FILTER = EMAC_MAC_PACKET_FILTER_PR_MASK;
998  }
999  else
1000  {
1001  //Set the MAC address of the station
1002  IP_EMAC->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
1003  IP_EMAC->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];
1004 
1005  //The MAC supports 2 additional addresses for unicast perfect filtering
1006  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
1007  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
1008 
1009  //The hash table is used for multicast address filtering
1010  hashTable[0] = 0;
1011  hashTable[1] = 0;
1012 
1013  //The MAC address filter contains the list of MAC addresses to accept
1014  //when receiving an Ethernet frame
1015  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
1016  {
1017  //Point to the current entry
1018  entry = &interface->macAddrFilter[i];
1019 
1020  //Valid entry?
1021  if(entry->refCount > 0)
1022  {
1023  //Multicast address?
1024  if(macIsMulticastAddr(&entry->addr))
1025  {
1026  //Compute CRC over the current MAC address
1027  crc = s32k344EthCalcCrc(&entry->addr, sizeof(MacAddr));
1028 
1029  //The upper 6 bits in the CRC register are used to index the
1030  //contents of the hash table
1031  k = (crc >> 26) & 0x3F;
1032 
1033  //Update hash table contents
1034  hashTable[k / 32] |= (1 << (k % 32));
1035  }
1036  else
1037  {
1038  //Up to 2 additional MAC addresses can be specified
1039  if(j < 2)
1040  {
1041  //Save the unicast address
1042  unicastMacAddr[j++] = entry->addr;
1043  }
1044  }
1045  }
1046  }
1047 
1048  //Configure the first unicast address filter
1049  if(j >= 1)
1050  {
1051  //When the AE bit is set, the entry is used for perfect filtering
1052  IP_EMAC->MAC_ADDRESS1_LOW = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
1053  IP_EMAC->MAC_ADDRESS1_HIGH = unicastMacAddr[0].w[2] | EMAC_MAC_ADDRESS1_HIGH_AE_MASK;
1054  }
1055  else
1056  {
1057  //When the AE bit is cleared, the entry is ignored
1058  IP_EMAC->MAC_ADDRESS1_LOW = 0;
1059  IP_EMAC->MAC_ADDRESS1_HIGH = 0;
1060  }
1061 
1062  //Configure the second unicast address filter
1063  if(j >= 2)
1064  {
1065  //When the AE bit is set, the entry is used for perfect filtering
1066  IP_EMAC->MAC_ADDRESS2_LOW = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
1067  IP_EMAC->MAC_ADDRESS2_HIGH = unicastMacAddr[1].w[2] | EMAC_MAC_ADDRESS2_HIGH_AE_MASK;
1068  }
1069  else
1070  {
1071  //When the AE bit is cleared, the entry is ignored
1072  IP_EMAC->MAC_ADDRESS2_LOW = 0;
1073  IP_EMAC->MAC_ADDRESS2_HIGH = 0;
1074  }
1075 
1076  //Check whether frames with a multicast destination address should be
1077  //accepted
1078  if(interface->acceptAllMulticast)
1079  {
1080  //Configure the receive filter
1081  IP_EMAC->MAC_PACKET_FILTER = EMAC_MAC_PACKET_FILTER_HPF_MASK |
1082  EMAC_MAC_PACKET_FILTER_PM_MASK;
1083  }
1084  else
1085  {
1086  //Configure the receive filter
1087  IP_EMAC->MAC_PACKET_FILTER = EMAC_MAC_PACKET_FILTER_HPF_MASK |
1088  EMAC_MAC_PACKET_FILTER_HMC_MASK;
1089 
1090  //Configure the multicast hash table
1091  IP_EMAC->MAC_HASH_TABLE_REG0 = hashTable[0];
1092  IP_EMAC->MAC_HASH_TABLE_REG1 = hashTable[1];
1093 
1094  //Debug message
1095  TRACE_DEBUG(" MAC_HASH_TABLE_REG0 = 0x%08" PRIX32 "\r\n", IP_EMAC->MAC_HASH_TABLE_REG0);
1096  TRACE_DEBUG(" MAC_HASH_TABLE_REG1 = 0x%08" PRIX32 "\r\n", IP_EMAC->MAC_HASH_TABLE_REG1);
1097  }
1098  }
1099 
1100  //Successful processing
1101  return NO_ERROR;
1102 }
1103 
1104 
1105 /**
1106  * @brief Adjust MAC configuration parameters for proper operation
1107  * @param[in] interface Underlying network interface
1108  * @return Error code
1109  **/
1110 
1112 {
1113  uint32_t config;
1114 
1115  //Read current MAC configuration
1116  config = IP_EMAC->MAC_CONFIGURATION;
1117 
1118  //10BASE-T or 100BASE-TX operation mode?
1119  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
1120  {
1121  config |= EMAC_MAC_CONFIGURATION_FES_MASK;
1122  }
1123  else
1124  {
1125  config &= ~EMAC_MAC_CONFIGURATION_FES_MASK;
1126  }
1127 
1128  //Half-duplex or full-duplex mode?
1129  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
1130  {
1131  config |= EMAC_MAC_CONFIGURATION_DM_MASK;
1132  }
1133  else
1134  {
1135  config &= ~EMAC_MAC_CONFIGURATION_DM_MASK;
1136  }
1137 
1138  //Update MAC configuration register
1139  IP_EMAC->MAC_CONFIGURATION = config;
1140 
1141  //Successful processing
1142  return NO_ERROR;
1143 }
1144 
1145 
1146 /**
1147  * @brief Write PHY register
1148  * @param[in] opcode Access type (2 bits)
1149  * @param[in] phyAddr PHY address (5 bits)
1150  * @param[in] regAddr Register address (5 bits)
1151  * @param[in] data Register value
1152  **/
1153 
1154 void s32k344EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
1155  uint8_t regAddr, uint16_t data)
1156 {
1157  uint32_t temp;
1158 
1159  //Valid opcode?
1160  if(opcode == SMI_OPCODE_WRITE)
1161  {
1162  //Take care not to alter MDC clock configuration
1163  temp = IP_EMAC->MAC_MDIO_ADDRESS & EMAC_MAC_MDIO_ADDRESS_CR_MASK;
1164  //Set up a write operation
1165  temp |= EMAC_MAC_MDIO_ADDRESS_GOC_0_MASK | EMAC_MAC_MDIO_ADDRESS_GB_MASK;
1166 
1167  //PHY address
1168  temp |= EMAC_MAC_MDIO_ADDRESS_PA(phyAddr);
1169  //Register address
1170  temp |= EMAC_MAC_MDIO_ADDRESS_RDA(regAddr);
1171 
1172  //Data to be written in the PHY register
1173  IP_EMAC->MAC_MDIO_DATA = data & EMAC_MAC_MDIO_DATA_GD_MASK;
1174 
1175  //Start a write operation
1176  IP_EMAC->MAC_MDIO_ADDRESS = temp;
1177  //Wait for the write to complete
1178  while((IP_EMAC->MAC_MDIO_ADDRESS & EMAC_MAC_MDIO_ADDRESS_GB_MASK) != 0)
1179  {
1180  }
1181  }
1182  else
1183  {
1184  //The MAC peripheral only supports standard Clause 22 opcodes
1185  }
1186 }
1187 
1188 
1189 /**
1190  * @brief Read PHY register
1191  * @param[in] opcode Access type (2 bits)
1192  * @param[in] phyAddr PHY address (5 bits)
1193  * @param[in] regAddr Register address (5 bits)
1194  * @return Register value
1195  **/
1196 
1197 uint16_t s32k344EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1198  uint8_t regAddr)
1199 {
1200  uint16_t data;
1201  uint32_t temp;
1202 
1203  //Valid opcode?
1204  if(opcode == SMI_OPCODE_READ)
1205  {
1206  //Take care not to alter MDC clock configuration
1207  temp = IP_EMAC->MAC_MDIO_ADDRESS & EMAC_MAC_MDIO_ADDRESS_CR_MASK;
1208 
1209  //Set up a read operation
1210  temp |= EMAC_MAC_MDIO_ADDRESS_GOC_1_MASK |
1211  EMAC_MAC_MDIO_ADDRESS_GOC_0_MASK | EMAC_MAC_MDIO_ADDRESS_GB_MASK;
1212 
1213  //PHY address
1214  temp |= EMAC_MAC_MDIO_ADDRESS_PA(phyAddr);
1215  //Register address
1216  temp |= EMAC_MAC_MDIO_ADDRESS_RDA(regAddr);
1217 
1218  //Start a read operation
1219  IP_EMAC->MAC_MDIO_ADDRESS = temp;
1220  //Wait for the read to complete
1221  while((IP_EMAC->MAC_MDIO_ADDRESS & EMAC_MAC_MDIO_ADDRESS_GB_MASK) != 0)
1222  {
1223  }
1224 
1225  //Get register value
1226  data = IP_EMAC->MAC_MDIO_DATA & EMAC_MAC_MDIO_DATA_GD_MASK;
1227  }
1228  else
1229  {
1230  //The MAC peripheral only supports standard Clause 22 opcodes
1231  data = 0;
1232  }
1233 
1234  //Return the value of the PHY register
1235  return data;
1236 }
1237 
1238 
1239 /**
1240  * @brief CRC calculation
1241  * @param[in] data Pointer to the data over which to calculate the CRC
1242  * @param[in] length Number of bytes to process
1243  * @return Resulting CRC value
1244  **/
1245 
1246 uint32_t s32k344EthCalcCrc(const void *data, size_t length)
1247 {
1248  uint_t i;
1249  uint_t j;
1250  uint32_t crc;
1251  const uint8_t *p;
1252 
1253  //Point to the data over which to calculate the CRC
1254  p = (uint8_t *) data;
1255  //CRC preset value
1256  crc = 0xFFFFFFFF;
1257 
1258  //Loop through data
1259  for(i = 0; i < length; i++)
1260  {
1261  //The message is processed bit by bit
1262  for(j = 0; j < 8; j++)
1263  {
1264  //Update CRC value
1265  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
1266  {
1267  crc = (crc << 1) ^ 0x04C11DB7;
1268  }
1269  else
1270  {
1271  crc = crc << 1;
1272  }
1273  }
1274  }
1275 
1276  //Return CRC value
1277  return ~crc;
1278 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define S32K344_ETH_RX_BUFFER_COUNT
#define EMAC_TDES3_OWN
uint8_t opcode
Definition: dns_common.h:191
#define S32K344_ETH_TX_BUFFER_COUNT
int bool_t
Definition: compiler_port.h:63
error_t s32k344EthInit(NetInterface *interface)
S32K344 Ethernet MAC initialization.
error_t s32k344EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define EMAC_RDES3_PL
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define S32K344_ETH_RAM_SECTION
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 EMAC_RDES3_BUF1V
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
#define EMAC_RDES3_ES
uint8_t data[]
Definition: ethernet.h:224
#define sleep(delay)
Definition: os_port.h:310
void s32k344EthInitRmiiClock(void)
RMII clock configuration.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
#define S32K344_ETH_REMAP_ADDR(addr)
#define S32K344_ETH_TX_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:418
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
error_t s32k344EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define EMAC_TDES3_FD
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define FALSE
Definition: os_port.h:46
error_t
Error codes.
Definition: error.h:43
void s32k344EthDisableIrq(NetInterface *interface)
Disable interrupts.
#define EMAC_TDES3_LD
__weak_func void s32k344EthInitGpio(NetInterface *interface)
GPIO configuration.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void EMAC_0_IRQHandler(void)
S32K344 Ethernet MAC interrupt service routine.
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
MacAddr addr
MAC address.
Definition: ethernet.h:265
#define S32K344_ETH_IRQ_PRIORITY_GROUPING
@ ERROR_INVALID_LENGTH
Definition: error.h:111
void s32k344EthEnableIrq(NetInterface *interface)
Enable interrupts.
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
#define S32K344_ETH_RX_BUFFER_SIZE
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:63
void s32k344EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define rxBuffer
void s32k344EthTick(NetInterface *interface)
S32K344 Ethernet MAC timer handler.
Transmit descriptor.
error_t s32k344EthReceivePacket(NetInterface *interface)
Receive a packet.
error_t s32k344EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
MacAddr
Definition: ethernet.h:197
#define EMAC_RDES3_FD
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define EMAC_TDES2_IOC
uint16_t regAddr
uint16_t s32k344EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
const NicDriver s32k344EthDriver
S32K344 Ethernet MAC driver.
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:264
#define osEnterIsr()
NXP S32K344 Ethernet MAC driver.
void s32k344EthEventHandler(NetInterface *interface)
S32K344 Ethernet MAC event handler.
Receive descriptor.
#define EMAC_RDES3_LD
#define EMAC_RDES3_IOC
#define EMAC_RDES3_OWN
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
uint32_t s32k344EthCalcCrc(const void *data, size_t length)
CRC calculation.
#define EMAC_TDES2_B1L
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define S32K344_ETH_IRQ_GROUP_PRIORITY
#define S32K344_ETH_IRQ_SUB_PRIORITY
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:51
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
void s32k344EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83