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.2
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  **/
548 
550 {
551  //Configure clock mux 7 (EMAC_TX_CLK)
552  while((IP_MC_CGM->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWIP_MASK) != 0)
553  {
554  }
555 
556  //Set 1:2 clock divider for clock mux 7
557  IP_MC_CGM->MUX_7_DC_0 = MC_CGM_MUX_7_DC_0_DE_MASK | MC_CGM_MUX_7_DC_0_DIV(1);
558  //Wait until the divider configuration update is complete
559  while((IP_MC_CGM->MUX_7_DIV_UPD_STAT & MC_CGM_MUX_7_DIV_UPD_STAT_DIV_STAT_MASK) != 0)
560  {
561  }
562 
563  //Select EMAC_RMII_TX_CLK as source clock for clock mux 7
564  IP_MC_CGM->MUX_7_CSC = MC_CGM_MUX_7_CSC_SELCTL(24) | MC_CGM_MUX_7_CSC_CLK_SW_MASK;
565  //Wait until the CLK_SW bit is set in the status register
566  while((IP_MC_CGM->MUX_7_CSS & MC_CGM_MUX_7_CSS_CLK_SW_MASK) == 0)
567  {
568  }
569 
570  //Wait until the clock source switching is complete
571  while((IP_MC_CGM->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWIP_MASK) != 0)
572  {
573  }
574 
575  //Configure clock mux 8 (EMAC_RX_CLK)
576  while((IP_MC_CGM->MUX_8_CSS & MC_CGM_MUX_8_CSS_SWIP_MASK) != 0)
577  {
578  }
579 
580  //Set 1:2 clock divider for clock mux 8
581  IP_MC_CGM->MUX_8_DC_0 = MC_CGM_MUX_8_DC_0_DE_MASK | MC_CGM_MUX_8_DC_0_DIV(1);
582  //Wait until the divider configuration update is complete
583  while((IP_MC_CGM->MUX_8_DIV_UPD_STAT & MC_CGM_MUX_8_DIV_UPD_STAT_DIV_STAT_MASK) != 0)
584  {
585  }
586 
587  //Select EMAC_RMII_TX_CLK as source clock for clock mux 8
588  IP_MC_CGM->MUX_8_CSC = MC_CGM_MUX_8_CSC_SELCTL(24) | MC_CGM_MUX_8_CSC_CLK_SW_MASK;
589  //Wait until the CLK_SW bit is set in the status register
590  while((IP_MC_CGM->MUX_8_CSS & MC_CGM_MUX_8_CSS_CLK_SW_MASK) == 0)
591  {
592  }
593 
594  //Wait until the clock source switching is complete
595  while((IP_MC_CGM->MUX_8_CSS & MC_CGM_MUX_8_CSS_SWIP_MASK) != 0)
596  {
597  }
598 
599  //Configure clock mux 9 (EMAC_TS_CLK)
600  while((IP_MC_CGM->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWIP_MASK) != 0)
601  {
602  }
603 
604  //Set 1:1 clock divider for clock mux 9
605  IP_MC_CGM->MUX_9_DC_0 = MC_CGM_MUX_9_DC_0_DE_MASK | MC_CGM_MUX_9_DC_0_DIV(0);
606  //Wait until the divider configuration update is complete
607  while((IP_MC_CGM->MUX_9_DIV_UPD_STAT & MC_CGM_MUX_9_DIV_UPD_STAT_DIV_STAT_MASK) != 0)
608  {
609  }
610 
611  //Select EMAC_RMII_TX_CLK as source clock for clock mux 9
612  IP_MC_CGM->MUX_9_CSC = MC_CGM_MUX_9_CSC_SELCTL(24) | MC_CGM_MUX_9_CSC_CLK_SW_MASK;
613  //Wait until the CLK_SW bit is set in the status register
614  while((IP_MC_CGM->MUX_9_CSS & MC_CGM_MUX_9_CSS_CLK_SW_MASK) == 0)
615  {
616  }
617 
618  //Wait until the clock source switching is complete
619  while((IP_MC_CGM->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWIP_MASK) != 0)
620  {
621  }
622 }
623 
624 
625 /**
626  * @brief Initialize DMA descriptor lists
627  * @param[in] interface Underlying network interface
628  **/
629 
631 {
632  uint_t i;
633 
634  //Initialize TX DMA descriptor list
635  for(i = 0; i < S32K344_ETH_TX_BUFFER_COUNT; i++)
636  {
637  //The descriptor is initially owned by the application
638  txDmaDesc[i].tdes0 = 0;
639  txDmaDesc[i].tdes1 = 0;
640  txDmaDesc[i].tdes2 = 0;
641  txDmaDesc[i].tdes3 = 0;
642  }
643 
644  //Initialize TX descriptor index
645  txIndex = 0;
646 
647  //Initialize RX DMA descriptor list
648  for(i = 0; i < S32K344_ETH_RX_BUFFER_COUNT; i++)
649  {
650  //The descriptor is initially owned by the DMA
652  rxDmaDesc[i].rdes1 = 0;
653  rxDmaDesc[i].rdes2 = 0;
655  }
656 
657  //Initialize RX descriptor index
658  rxIndex = 0;
659 
660  //Start location of the TX descriptor list
661  IP_EMAC->DMA_CH0_TXDESC_LIST_ADDRESS = S32K344_ETH_REMAP_ADDR(&txDmaDesc[0]);
662  //Length of the transmit descriptor ring
663  IP_EMAC->DMA_CH0_TXDESC_RING_LENGTH = S32K344_ETH_TX_BUFFER_COUNT - 1;
664 
665  //Start location of the RX descriptor list
666  IP_EMAC->DMA_CH0_RXDESC_LIST_ADDRESS = S32K344_ETH_REMAP_ADDR(&rxDmaDesc[0]);
667  //Length of the receive descriptor ring
668  IP_EMAC->DMA_CH0_RXDESC_RING_LENGTH = S32K344_ETH_RX_BUFFER_COUNT - 1;
669 }
670 
671 
672 /**
673  * @brief S32K344 Ethernet MAC timer handler
674  *
675  * This routine is periodically called by the TCP/IP stack to handle periodic
676  * operations such as polling the link state
677  *
678  * @param[in] interface Underlying network interface
679  **/
680 
681 void s32k344EthTick(NetInterface *interface)
682 {
683  //Valid Ethernet PHY or switch driver?
684  if(interface->phyDriver != NULL)
685  {
686  //Handle periodic operations
687  interface->phyDriver->tick(interface);
688  }
689  else if(interface->switchDriver != NULL)
690  {
691  //Handle periodic operations
692  interface->switchDriver->tick(interface);
693  }
694  else
695  {
696  //Just for sanity
697  }
698 }
699 
700 
701 /**
702  * @brief Enable interrupts
703  * @param[in] interface Underlying network interface
704  **/
705 
707 {
708  //Enable Ethernet MAC interrupts
709  NVIC_EnableIRQ(EMAC_0_IRQn);
710 
711  //Valid Ethernet PHY or switch driver?
712  if(interface->phyDriver != NULL)
713  {
714  //Enable Ethernet PHY interrupts
715  interface->phyDriver->enableIrq(interface);
716  }
717  else if(interface->switchDriver != NULL)
718  {
719  //Enable Ethernet switch interrupts
720  interface->switchDriver->enableIrq(interface);
721  }
722  else
723  {
724  //Just for sanity
725  }
726 }
727 
728 
729 /**
730  * @brief Disable interrupts
731  * @param[in] interface Underlying network interface
732  **/
733 
735 {
736  //Disable Ethernet MAC interrupts
737  NVIC_DisableIRQ(EMAC_0_IRQn);
738 
739  //Valid Ethernet PHY or switch driver?
740  if(interface->phyDriver != NULL)
741  {
742  //Disable Ethernet PHY interrupts
743  interface->phyDriver->disableIrq(interface);
744  }
745  else if(interface->switchDriver != NULL)
746  {
747  //Disable Ethernet switch interrupts
748  interface->switchDriver->disableIrq(interface);
749  }
750  else
751  {
752  //Just for sanity
753  }
754 }
755 
756 
757 /**
758  * @brief S32K344 Ethernet MAC interrupt service routine
759  **/
760 
762 {
763  bool_t flag;
764  uint32_t status;
765 
766  //Interrupt service routine prologue
767  osEnterIsr();
768 
769  //This flag will be set if a higher priority task must be woken
770  flag = FALSE;
771 
772  //Read DMA status register
773  status = IP_EMAC->DMA_CH0_STATUS;
774 
775  //Packet transmitted?
776  if((status & EMAC_DMA_CH0_STATUS_TI_MASK) != 0)
777  {
778  //Clear TI interrupt flag
779  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_TI_MASK;
780 
781  //Check whether the TX buffer is available for writing
782  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
783  {
784  //Notify the TCP/IP stack that the transmitter is ready to send
785  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
786  }
787  }
788 
789  //Packet received?
790  if((status & EMAC_DMA_CH0_STATUS_RI_MASK) != 0)
791  {
792  //Clear RI interrupt flag
793  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_RI_MASK;
794 
795  //Set event flag
796  nicDriverInterface->nicEvent = TRUE;
797  //Notify the TCP/IP stack of the event
798  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
799  }
800 
801  //Clear NIS interrupt flag
802  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_NIS_MASK;
803 
804  //Interrupt service routine epilogue
805  osExitIsr(flag);
806 }
807 
808 
809 /**
810  * @brief S32K344 Ethernet MAC event handler
811  * @param[in] interface Underlying network interface
812  **/
813 
815 {
816  error_t error;
817 
818  //Process all pending packets
819  do
820  {
821  //Read incoming packet
822  error = s32k344EthReceivePacket(interface);
823 
824  //No more data in the receive buffer?
825  } while(error != ERROR_BUFFER_EMPTY);
826 }
827 
828 
829 /**
830  * @brief Send a packet
831  * @param[in] interface Underlying network interface
832  * @param[in] buffer Multi-part buffer containing the data to send
833  * @param[in] offset Offset to the first data byte
834  * @param[in] ancillary Additional options passed to the stack along with
835  * the packet
836  * @return Error code
837  **/
838 
840  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
841 {
842  size_t length;
843 
844  //Retrieve the length of the packet
845  length = netBufferGetLength(buffer) - offset;
846 
847  //Check the frame length
849  {
850  //The transmitter can accept another packet
851  osSetEvent(&interface->nicTxEvent);
852  //Report an error
853  return ERROR_INVALID_LENGTH;
854  }
855 
856  //Make sure the current buffer is available for writing
857  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) != 0)
858  {
859  return ERROR_FAILURE;
860  }
861 
862  //Copy user data to the transmit buffer
863  netBufferRead(txBuffer[txIndex], buffer, offset, length);
864 
865  //Set the start address of the buffer
866  txDmaDesc[txIndex].tdes0 = S32K344_ETH_REMAP_ADDR(txBuffer[txIndex]);
867  //Write the number of bytes to send
868  txDmaDesc[txIndex].tdes2 = EMAC_TDES2_IOC | (length & EMAC_TDES2_B1L);
869  //Give the ownership of the descriptor to the DMA
871 
872  //Data synchronization barrier
873  __DSB();
874 
875  //Clear TBU flag to resume processing
876  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_TBU_MASK;
877  //Instruct the DMA to poll the transmit descriptor list
878  IP_EMAC->DMA_CH0_TXDESC_TAIL_POINTER = 0;
879 
880  //Increment index and wrap around if necessary
881  if(++txIndex >= S32K344_ETH_TX_BUFFER_COUNT)
882  {
883  txIndex = 0;
884  }
885 
886  //Check whether the next buffer is available for writing
887  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
888  {
889  //The transmitter can accept another packet
890  osSetEvent(&interface->nicTxEvent);
891  }
892 
893  //Data successfully written
894  return NO_ERROR;
895 }
896 
897 
898 /**
899  * @brief Receive a packet
900  * @param[in] interface Underlying network interface
901  * @return Error code
902  **/
903 
905 {
906  error_t error;
907  size_t n;
908  NetRxAncillary ancillary;
909 
910  //Current buffer available for reading?
911  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_OWN) == 0)
912  {
913  //FD and LD flags should be set
914  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_FD) != 0 &&
915  (rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_LD) != 0)
916  {
917  //Make sure no error occurred
918  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_ES) == 0)
919  {
920  //Retrieve the length of the frame
921  n = rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_PL;
922  //Limit the number of data to read
924 
925  //Additional options can be passed to the stack along with the packet
926  ancillary = NET_DEFAULT_RX_ANCILLARY;
927 
928  //Pass the packet to the upper layer
929  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
930 
931  //Valid packet received
932  error = NO_ERROR;
933  }
934  else
935  {
936  //The received packet contains an error
937  error = ERROR_INVALID_PACKET;
938  }
939  }
940  else
941  {
942  //The packet is not valid
943  error = ERROR_INVALID_PACKET;
944  }
945 
946  //Set the start address of the buffer
947  rxDmaDesc[rxIndex].rdes0 = S32K344_ETH_REMAP_ADDR(rxBuffer[rxIndex]);
948  //Give the ownership of the descriptor back to the DMA
950 
951  //Increment index and wrap around if necessary
952  if(++rxIndex >= S32K344_ETH_RX_BUFFER_COUNT)
953  {
954  rxIndex = 0;
955  }
956  }
957  else
958  {
959  //No more data in the receive buffer
960  error = ERROR_BUFFER_EMPTY;
961  }
962 
963  //Clear RBU flag to resume processing
964  IP_EMAC->DMA_CH0_STATUS = EMAC_DMA_CH0_STATUS_RBU_MASK;
965  //Instruct the DMA to poll the receive descriptor list
966  IP_EMAC->DMA_CH0_RXDESC_TAIL_POINTER = 0;
967 
968  //Return status code
969  return error;
970 }
971 
972 
973 /**
974  * @brief Configure MAC address filtering
975  * @param[in] interface Underlying network interface
976  * @return Error code
977  **/
978 
980 {
981  uint_t i;
982  uint_t j;
983  uint_t k;
984  uint32_t crc;
985  uint32_t hashTable[2];
986  MacAddr unicastMacAddr[2];
987  MacFilterEntry *entry;
988 
989  //Debug message
990  TRACE_DEBUG("Updating MAC filter...\r\n");
991 
992  //Promiscuous mode?
993  if(interface->promiscuous)
994  {
995  //Pass all incoming frames regardless of their destination address
996  IP_EMAC->MAC_PACKET_FILTER = EMAC_MAC_PACKET_FILTER_PR_MASK;
997  }
998  else
999  {
1000  //Set the MAC address of the station
1001  IP_EMAC->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
1002  IP_EMAC->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];
1003 
1004  //The MAC supports 2 additional addresses for unicast perfect filtering
1005  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
1006  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
1007 
1008  //The hash table is used for multicast address filtering
1009  hashTable[0] = 0;
1010  hashTable[1] = 0;
1011 
1012  //The MAC address filter contains the list of MAC addresses to accept
1013  //when receiving an Ethernet frame
1014  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
1015  {
1016  //Point to the current entry
1017  entry = &interface->macAddrFilter[i];
1018 
1019  //Valid entry?
1020  if(entry->refCount > 0)
1021  {
1022  //Multicast address?
1023  if(macIsMulticastAddr(&entry->addr))
1024  {
1025  //Compute CRC over the current MAC address
1026  crc = s32k344EthCalcCrc(&entry->addr, sizeof(MacAddr));
1027 
1028  //The upper 6 bits in the CRC register are used to index the
1029  //contents of the hash table
1030  k = (crc >> 26) & 0x3F;
1031 
1032  //Update hash table contents
1033  hashTable[k / 32] |= (1 << (k % 32));
1034  }
1035  else
1036  {
1037  //Up to 2 additional MAC addresses can be specified
1038  if(j < 2)
1039  {
1040  //Save the unicast address
1041  unicastMacAddr[j++] = entry->addr;
1042  }
1043  }
1044  }
1045  }
1046 
1047  //Configure the first unicast address filter
1048  if(j >= 1)
1049  {
1050  //When the AE bit is set, the entry is used for perfect filtering
1051  IP_EMAC->MAC_ADDRESS1_LOW = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
1052  IP_EMAC->MAC_ADDRESS1_HIGH = unicastMacAddr[0].w[2] | EMAC_MAC_ADDRESS1_HIGH_AE_MASK;
1053  }
1054  else
1055  {
1056  //When the AE bit is cleared, the entry is ignored
1057  IP_EMAC->MAC_ADDRESS1_LOW = 0;
1058  IP_EMAC->MAC_ADDRESS1_HIGH = 0;
1059  }
1060 
1061  //Configure the second unicast address filter
1062  if(j >= 2)
1063  {
1064  //When the AE bit is set, the entry is used for perfect filtering
1065  IP_EMAC->MAC_ADDRESS2_LOW = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
1066  IP_EMAC->MAC_ADDRESS2_HIGH = unicastMacAddr[1].w[2] | EMAC_MAC_ADDRESS2_HIGH_AE_MASK;
1067  }
1068  else
1069  {
1070  //When the AE bit is cleared, the entry is ignored
1071  IP_EMAC->MAC_ADDRESS2_LOW = 0;
1072  IP_EMAC->MAC_ADDRESS2_HIGH = 0;
1073  }
1074 
1075  //Check whether frames with a multicast destination address should be
1076  //accepted
1077  if(interface->acceptAllMulticast)
1078  {
1079  //Configure the receive filter
1080  IP_EMAC->MAC_PACKET_FILTER = EMAC_MAC_PACKET_FILTER_HPF_MASK |
1081  EMAC_MAC_PACKET_FILTER_PM_MASK;
1082  }
1083  else
1084  {
1085  //Configure the receive filter
1086  IP_EMAC->MAC_PACKET_FILTER = EMAC_MAC_PACKET_FILTER_HPF_MASK |
1087  EMAC_MAC_PACKET_FILTER_HMC_MASK;
1088 
1089  //Configure the multicast hash table
1090  IP_EMAC->MAC_HASH_TABLE_REG0 = hashTable[0];
1091  IP_EMAC->MAC_HASH_TABLE_REG1 = hashTable[1];
1092 
1093  //Debug message
1094  TRACE_DEBUG(" MAC_HASH_TABLE_REG0 = 0x%08" PRIX32 "\r\n", IP_EMAC->MAC_HASH_TABLE_REG0);
1095  TRACE_DEBUG(" MAC_HASH_TABLE_REG1 = 0x%08" PRIX32 "\r\n", IP_EMAC->MAC_HASH_TABLE_REG1);
1096  }
1097  }
1098 
1099  //Successful processing
1100  return NO_ERROR;
1101 }
1102 
1103 
1104 /**
1105  * @brief Adjust MAC configuration parameters for proper operation
1106  * @param[in] interface Underlying network interface
1107  * @return Error code
1108  **/
1109 
1111 {
1112  uint32_t config;
1113 
1114  //Read current MAC configuration
1115  config = IP_EMAC->MAC_CONFIGURATION;
1116 
1117  //10BASE-T or 100BASE-TX operation mode?
1118  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
1119  {
1120  config |= EMAC_MAC_CONFIGURATION_FES_MASK;
1121  }
1122  else
1123  {
1124  config &= ~EMAC_MAC_CONFIGURATION_FES_MASK;
1125  }
1126 
1127  //Half-duplex or full-duplex mode?
1128  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
1129  {
1130  config |= EMAC_MAC_CONFIGURATION_DM_MASK;
1131  }
1132  else
1133  {
1134  config &= ~EMAC_MAC_CONFIGURATION_DM_MASK;
1135  }
1136 
1137  //Update MAC configuration register
1138  IP_EMAC->MAC_CONFIGURATION = config;
1139 
1140  //Successful processing
1141  return NO_ERROR;
1142 }
1143 
1144 
1145 /**
1146  * @brief Write PHY register
1147  * @param[in] opcode Access type (2 bits)
1148  * @param[in] phyAddr PHY address (5 bits)
1149  * @param[in] regAddr Register address (5 bits)
1150  * @param[in] data Register value
1151  **/
1152 
1153 void s32k344EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
1154  uint8_t regAddr, uint16_t data)
1155 {
1156  uint32_t temp;
1157 
1158  //Valid opcode?
1159  if(opcode == SMI_OPCODE_WRITE)
1160  {
1161  //Take care not to alter MDC clock configuration
1162  temp = IP_EMAC->MAC_MDIO_ADDRESS & EMAC_MAC_MDIO_ADDRESS_CR_MASK;
1163  //Set up a write operation
1164  temp |= EMAC_MAC_MDIO_ADDRESS_GOC_0_MASK | EMAC_MAC_MDIO_ADDRESS_GB_MASK;
1165 
1166  //PHY address
1167  temp |= EMAC_MAC_MDIO_ADDRESS_PA(phyAddr);
1168  //Register address
1169  temp |= EMAC_MAC_MDIO_ADDRESS_RDA(regAddr);
1170 
1171  //Data to be written in the PHY register
1172  IP_EMAC->MAC_MDIO_DATA = data & EMAC_MAC_MDIO_DATA_GD_MASK;
1173 
1174  //Start a write operation
1175  IP_EMAC->MAC_MDIO_ADDRESS = temp;
1176  //Wait for the write to complete
1177  while((IP_EMAC->MAC_MDIO_ADDRESS & EMAC_MAC_MDIO_ADDRESS_GB_MASK) != 0)
1178  {
1179  }
1180  }
1181  else
1182  {
1183  //The MAC peripheral only supports standard Clause 22 opcodes
1184  }
1185 }
1186 
1187 
1188 /**
1189  * @brief Read PHY register
1190  * @param[in] opcode Access type (2 bits)
1191  * @param[in] phyAddr PHY address (5 bits)
1192  * @param[in] regAddr Register address (5 bits)
1193  * @return Register value
1194  **/
1195 
1196 uint16_t s32k344EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1197  uint8_t regAddr)
1198 {
1199  uint16_t data;
1200  uint32_t temp;
1201 
1202  //Valid opcode?
1203  if(opcode == SMI_OPCODE_READ)
1204  {
1205  //Take care not to alter MDC clock configuration
1206  temp = IP_EMAC->MAC_MDIO_ADDRESS & EMAC_MAC_MDIO_ADDRESS_CR_MASK;
1207 
1208  //Set up a read operation
1209  temp |= EMAC_MAC_MDIO_ADDRESS_GOC_1_MASK |
1210  EMAC_MAC_MDIO_ADDRESS_GOC_0_MASK | EMAC_MAC_MDIO_ADDRESS_GB_MASK;
1211 
1212  //PHY address
1213  temp |= EMAC_MAC_MDIO_ADDRESS_PA(phyAddr);
1214  //Register address
1215  temp |= EMAC_MAC_MDIO_ADDRESS_RDA(regAddr);
1216 
1217  //Start a read operation
1218  IP_EMAC->MAC_MDIO_ADDRESS = temp;
1219  //Wait for the read to complete
1220  while((IP_EMAC->MAC_MDIO_ADDRESS & EMAC_MAC_MDIO_ADDRESS_GB_MASK) != 0)
1221  {
1222  }
1223 
1224  //Get register value
1225  data = IP_EMAC->MAC_MDIO_DATA & EMAC_MAC_MDIO_DATA_GD_MASK;
1226  }
1227  else
1228  {
1229  //The MAC peripheral only supports standard Clause 22 opcodes
1230  data = 0;
1231  }
1232 
1233  //Return the value of the PHY register
1234  return data;
1235 }
1236 
1237 
1238 /**
1239  * @brief CRC calculation
1240  * @param[in] data Pointer to the data over which to calculate the CRC
1241  * @param[in] length Number of bytes to process
1242  * @return Resulting CRC value
1243  **/
1244 
1245 uint32_t s32k344EthCalcCrc(const void *data, size_t length)
1246 {
1247  uint_t i;
1248  uint_t j;
1249  uint32_t crc;
1250  const uint8_t *p;
1251 
1252  //Point to the data over which to calculate the CRC
1253  p = (uint8_t *) data;
1254  //CRC preset value
1255  crc = 0xFFFFFFFF;
1256 
1257  //Loop through data
1258  for(i = 0; i < length; i++)
1259  {
1260  //The message is processed bit by bit
1261  for(j = 0; j < 8; j++)
1262  {
1263  //Update CRC value
1264  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
1265  {
1266  crc = (crc << 1) ^ 0x04C11DB7;
1267  }
1268  else
1269  {
1270  crc = crc << 1;
1271  }
1272  }
1273  }
1274 
1275  //Return CRC value
1276  return ~crc;
1277 }
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