1 /*
2 * Copyright (c) 2006-2024, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2017-10-10 Tanek the first version
9 * 2019-5-10 misonyo add DMA TX and RX function
10 * 2020-10-14 wangqiang use phy device in phy monitor thread
11 * 2022-08-29 xjy198903 add 1170 rgmii support
12 */
13
14 #include <rtthread.h>
15 #include <rtdevice.h>
16
17 #ifdef RT_USING_FINSH
18 #include <finsh.h>
19 #endif
20
21 #include "fsl_enet.h"
22
23 #ifdef RT_USING_LWIP
24
25 #include <netif/ethernetif.h>
26 #include "lwipopts.h"
27
28 #define DBG_TAG "drv.eth"
29 #define DBG_LVL DBG_INFO
30 #include <rtdbg.h>
31
32
33 /* The PHY ID one register */
34 #define PHY_ID1_REG 0x02U
35 /* The PHY ID two register */
36 #define PHY_ID2_REG 0x03U
37 /* The PHY auto-negotiate advertise register */
38 #define PHY_AUTONEG_ADVERTISE_REG 0x04U
39
40 /* The PHY basic control register */
41 #define PHY_BASIC_CONTROL_REG 0x00U
42 #define PHY_RESET_MASK (1<<15)
43 #define PHY_AUTO_NEGOTIATION_MASK (1<<12)
44
45 #define PHY_LINK (1 << 0)
46 #define PHY_100M (1 << 1)
47 #define PHY_FULL_DUPLEX (1 << 2)
48
49
50
51 /* The PHY basic status register */
52 #define PHY_BASIC_STATUS_REG 0x01U
53 #define PHY_LINKED_STATUS_MASK (1<<2)
54 #define PHY_AUTONEGO_COMPLETE_MASK (1<<5)
55
56
57 /* The PHY status register. */
58 #define PHY_Status_REG 0x1FU
59
60 #define PHY_100M_MASK (1<<3)
61 #define PHY_FULL_DUPLEX_MASK (1<<4)
62 #define PHY_Status_SPEED_100M(sr) ((sr) & PHY_100M_MASK)
63 #define PHY_Status_FULL_DUPLEX(sr) ((sr) & PHY_FULL_DUPLEX_MASK)
64
65
66 //extern phy_lan8741_resource_t g_phy_resource;
67 #define EXAMPLE_ENET_BASE ENET0
68 #define EXAMPLE_PHY_ADDRESS 0x00U
69 #define ENET_EXAMPLE_IRQ ETHERNET_IRQn
70 #define EXAMPLE_CLOCK_FREQ (50000000U)
71 #define ENET_RXBD_NUM (4)
72 #define ENET_TXBD_NUM (4)
73 #define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN)
74 #define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT)
75 #define ENET_ALIGN(x, align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)-1)))
76
77
78 rt_align(4) enet_rx_bd_struct_t g_rxBuffDescrip[ENET_RXBD_NUM];
79 rt_align(4) enet_tx_bd_struct_t g_txBuffDescrip[ENET_RXBD_NUM];
80
81 static enet_tx_reclaim_info_t g_txDirty[ENET_TXBD_NUM];
82
83
84
85 #define MAX_ADDR_LEN 6
86
87
88 struct rt_stm32_eth
89 {
90 /* inherit from ethernet device */
91 struct eth_device parent;
92 #ifndef PHY_USING_INTERRUPT_MODE
93 rt_timer_t poll_link_timer;
94 #endif
95
96 /* interface address info, hw address */
97 rt_uint8_t dev_addr[MAX_ADDR_LEN];
98 enet_handle_t g_handle;
99 rt_uint32_t rx_channel;
100 };
101
102 static struct rt_stm32_eth stm32_eth_device;
103
104
105
ENET_IntCallback(ENET_Type * base,enet_handle_t * handle,enet_event_t event,uint8_t channel,enet_tx_reclaim_info_t * txReclaimInfo,void * param)106 static void ENET_IntCallback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, uint8_t channel, enet_tx_reclaim_info_t *txReclaimInfo, void *param)
107 {
108 rt_err_t result;
109
110 switch (event)
111 {
112 case kENET_TxIntEvent:
113 /* Get frame info after whole frame transmits out */
114 // if (txReclaimInfo != NULL)
115 // {
116 // rt_free((*txReclaimInfo).context);
117 // }
118 break;
119 case kENET_RxIntEvent:
120 stm32_eth_device.rx_channel = channel;
121 result = eth_device_ready(&(stm32_eth_device.parent));
122 if (result != RT_EOK)
123 {
124 LOG_I("_enet_rx_data err = %d", result);
125 }
126 default:
127 break;
128 }
129 }
130
rt_stm32_eth_init(rt_device_t dev)131 static rt_err_t rt_stm32_eth_init(rt_device_t dev)
132 {
133 uint32_t count = 0;
134 bool link = false;
135 bool autonego = false;
136 status_t status;
137 enet_config_t config;
138 int i;
139 uint32_t rxbuffer[ENET_RXBD_NUM];
140
141 struct rt_stm32_eth *eth = (struct rt_stm32_eth*)dev->user_data;
142
143 for (i = 0; i < ENET_RXBD_NUM; i++)
144 {
145 /* This is for rx buffers, static alloc and dynamic alloc both ok. use as your wish. */
146 rxbuffer[i] = (uint32_t)rt_malloc(ENET_RXBUFF_SIZE);
147 }
148
149 /* prepare the buffer configuration. */
150 enet_buffer_config_t buffConfig[1] = {{
151 ENET_RXBD_NUM,
152 ENET_TXBD_NUM,
153 &g_txBuffDescrip[0],
154 &g_txBuffDescrip[0],
155 &g_txDirty[0],
156 &g_rxBuffDescrip[0],
157 &g_rxBuffDescrip[ENET_RXBD_NUM],
158 &rxbuffer[0],
159 ENET_BuffSizeAlign(ENET_RXBUFF_SIZE),
160 }};
161
162
163 CLOCK_AttachClk(kNONE_to_ENETRMII);
164 CLOCK_EnableClock(kCLOCK_Enet);
165
166 ENET_SetSMI(EXAMPLE_ENET_BASE, CLOCK_GetCoreSysClkFreq());
167 ENET_GetDefaultConfig(&config);
168
169 /* Use the actual speed and duplex when phy success to finish the autonegotiation. */
170 config.miiSpeed = kENET_MiiSpeed100M;
171 config.miiDuplex = kENET_MiiFullDuplex;
172 config.interrupt = (kENET_DmaRx) | (kENET_DmaTx);
173
174 ENET_Init(EXAMPLE_ENET_BASE, &config, &stm32_eth_device.dev_addr[0], EXAMPLE_CLOCK_FREQ);
175 ENET_DescriptorInit(EXAMPLE_ENET_BASE, &config, &buffConfig[0]);
176 ENET_CreateHandler(EXAMPLE_ENET_BASE, ð->g_handle, &config, &buffConfig[0], ENET_IntCallback, NULL);
177 ENET_StartRxTx(EXAMPLE_ENET_BASE, 1, 1);
178
179 return RT_EOK;
180 }
181
182
183
rt_stm32_eth_control(rt_device_t dev,int cmd,void * args)184 static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
185 {
186 switch (cmd)
187 {
188 case NIOCTL_GADDR:
189 /* get mac address */
190 if (args)
191 {
192 SMEMCPY(args, stm32_eth_device.dev_addr, 6);
193 }
194 else
195 {
196 return -RT_ERROR;
197 }
198 break;
199
200 default :
201 break;
202 }
203
204 return RT_EOK;
205 }
206
207
rt_stm32_eth_tx(rt_device_t dev,struct pbuf * p)208 rt_err_t rt_stm32_eth_tx(rt_device_t dev, struct pbuf *p)
209 {
210 struct pbuf *q;
211 status_t status;
212
213 struct rt_stm32_eth *eth = (struct rt_stm32_eth*)dev->user_data;
214 // LOG_D("rt_stm32_eth_tx: len: %d, tot_len:%d", p->len, p->tot_len);
215
216 enet_buffer_struct_t txBuff[ENET_TXBD_NUM];
217 enet_tx_frame_struct_t txFrame = {0};
218
219 for (q = p; q != NULL; q = q->next)
220 {
221 txBuff[txFrame.txBuffNum].buffer = q->payload;
222 txBuff[txFrame.txBuffNum].length = q->len;
223 txFrame.txBuffNum++;
224 }
225
226 txFrame.txBuffArray = txBuff;
227 txFrame.txConfig.intEnable = true;
228 txFrame.txConfig.tsEnable = true;
229 txFrame.context = RT_NULL;
230
231
232 status = ENET_SendFrame(EXAMPLE_ENET_BASE, ð->g_handle, &txFrame, 0);
233
234 return (status == kStatus_Success);
235 }
236
rt_stm32_eth_rx(rt_device_t dev)237 struct pbuf *rt_stm32_eth_rx(rt_device_t dev)
238 {
239 struct pbuf *p = RT_NULL;
240 uint32_t len = 0;
241 status_t status;
242
243 struct rt_stm32_eth *eth = (struct rt_stm32_eth*)dev->user_data;
244
245 status = ENET_GetRxFrameSize(EXAMPLE_ENET_BASE, ð->g_handle, &len, eth->rx_channel);
246
247 // LOG_D("rt_stm32_eth_rx: status:%d, length: %d, channel:%d", status, len, eth->rx_channel);
248
249 if (len != 0 && (status == kStatus_Success))
250 {
251 /* Received valid frame. Deliver the rx buffer with the size equal to length. */
252 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
253 if (p != NULL)
254 {
255 status = ENET_ReadFrame(EXAMPLE_ENET_BASE, ð->g_handle, p->payload, len, eth->rx_channel, NULL);
256
257 if (status == kStatus_Success)
258 {
259 return p;
260 }
261 else
262 {
263 LOG_D(" A frame read failed\n");
264 pbuf_free(p);
265 }
266 }
267 else
268 {
269 LOG_D(" pbuf_alloc faild\n");
270 }
271 }
272 else if (status == kStatus_ENET_RxFrameError)
273 {
274 /* update the receive buffer. */
275 ENET_ReadFrame(EXAMPLE_ENET_BASE, ð->g_handle, NULL, 0, eth->rx_channel, NULL);
276 }
277 return RT_NULL;
278 }
279
280
281
phy_monitor_thread_entry(void * parameter)282 static void phy_monitor_thread_entry(void *parameter)
283 {
284 uint8_t phy_addr = 0xFF;
285 uint8_t detected_count = 0;
286
287 while(phy_addr == 0xFF)
288 {
289 /* phy search */
290 rt_uint16_t i, temp;
291 for (i = 0; i <= 0x1F; i++)
292 {
293 // EthHandle.Init.PhyAddress = i;
294 ENET_MDIORead(EXAMPLE_ENET_BASE, i, PHY_ID1_REG, &temp);
295
296 if (temp != 0xFFFF && temp != 0x00)
297 {
298 phy_addr = i;
299 break;
300 }
301 }
302
303 detected_count++;
304 rt_thread_mdelay(1000);
305
306 if (detected_count > 10)
307 {
308 LOG_E("No PHY device was detected, please check hardware!");
309 }
310 }
311
312 LOG_D("Found a phy, address:0x%02X", phy_addr);
313
314 /* RESET PHY */
315 LOG_D("RESET PHY!");
316 ENET_MDIOWrite(EXAMPLE_ENET_BASE, phy_addr, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK);
317 rt_thread_mdelay(2000);
318 ENET_MDIOWrite(EXAMPLE_ENET_BASE, phy_addr, PHY_BASIC_CONTROL_REG, PHY_AUTO_NEGOTIATION_MASK);
319
320 while(1)
321 {
322 static rt_uint8_t phy_speed = 0;
323 uint8_t phy_speed_new = 0;
324 uint16_t status;
325
326 ENET_MDIORead(EXAMPLE_ENET_BASE, phy_addr, PHY_BASIC_STATUS_REG, &status);
327 LOG_D("phy basic status reg is 0x%X", status);
328
329 if (status & (PHY_AUTONEGO_COMPLETE_MASK | PHY_LINKED_STATUS_MASK))
330 {
331 uint16_t SR = 0;
332
333 phy_speed_new |= PHY_LINK;
334
335 ENET_MDIORead(EXAMPLE_ENET_BASE, phy_addr, PHY_Status_REG, &SR);
336 LOG_D("phy control status reg is 0x%X", SR);
337
338 if (PHY_Status_SPEED_100M(SR))
339 {
340 phy_speed_new |= PHY_100M;
341 }
342
343 if (PHY_Status_FULL_DUPLEX(SR))
344 {
345 phy_speed_new |= PHY_FULL_DUPLEX;
346 }
347 }
348
349 if (phy_speed != phy_speed_new)
350 {
351 phy_speed = phy_speed_new;
352 if (phy_speed & PHY_LINK)
353 {
354 LOG_D("link up");
355 if (phy_speed & PHY_100M)
356 {
357 LOG_D("100Mbps");
358 }
359 else
360 {
361 LOG_D("10Mbps");
362 }
363
364 if (phy_speed & PHY_FULL_DUPLEX)
365 {
366 LOG_D("full-duplex");
367 }
368 else
369 {
370 LOG_D("half-duplex");
371 }
372
373 /* send link up. */
374 eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
375 }
376 else
377 {
378 LOG_I("link down");
379 eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
380 }
381 }
382 rt_thread_mdelay(1000);
383 }
384 }
385
386
rt_hw_imxrt_eth_init(void)387 static int rt_hw_imxrt_eth_init(void)
388 {
389 rt_err_t state = RT_EOK;
390
391 stm32_eth_device.dev_addr[0] = 0x00;
392 stm32_eth_device.dev_addr[1] = 0x80;
393 stm32_eth_device.dev_addr[2] = 0xE1;
394 stm32_eth_device.dev_addr[3] = 0x01;
395 stm32_eth_device.dev_addr[4] = 0x02;
396 stm32_eth_device.dev_addr[5] = 0x03;
397
398 stm32_eth_device.parent.parent.init = rt_stm32_eth_init;
399 stm32_eth_device.parent.parent.open = RT_NULL;
400 stm32_eth_device.parent.parent.close = RT_NULL;
401 stm32_eth_device.parent.parent.read = RT_NULL;
402 stm32_eth_device.parent.parent.write = RT_NULL;
403 stm32_eth_device.parent.parent.control = rt_stm32_eth_control;
404 stm32_eth_device.parent.parent.user_data = &stm32_eth_device;
405
406 stm32_eth_device.parent.eth_rx = rt_stm32_eth_rx;
407 stm32_eth_device.parent.eth_tx = rt_stm32_eth_tx;
408
409 /* register eth device */
410 state = eth_device_init(&(stm32_eth_device.parent), "e0");
411 if (RT_EOK != state)
412 {
413 LOG_E("emac device init faild: %d", state);
414 state = -RT_ERROR;
415 }
416
417 /* start phy monitor */
418 rt_thread_startup(rt_thread_create("phy", phy_monitor_thread_entry, RT_NULL, 1024, RT_THREAD_PRIORITY_MAX - 2, 2));
419 return state;
420
421 }
422
423 INIT_DEVICE_EXPORT(rt_hw_imxrt_eth_init);
424
425 #endif
426