1 /*
2 * File : emac.c
3 * This file is part of RT-Thread RTOS
4 * COPYRIGHT (C) 2006-2021, RT-Thread Develop Team
5 *
6 * The license and distribution terms for this file may be
7 * found in the file LICENSE in this distribution or at
8 * http://openlab.rt-thread.com/license/LICENSE
9 *
10 * Change Logs:
11 * Date Author Notes
12 * 2014-08-29 aozima first implementation
13 */
14
15 #include <rtthread.h>
16 #include <netif/ethernetif.h>
17 #include "lwipopts.h"
18
19 #include "board.h"
20
21 #include "app_phy.h"
22
23 /* debug option */
24 #define ETH_DEBUG
25 //#define ETH_RX_DUMP
26 //#define ETH_TX_DUMP
27
28 #ifdef ETH_DEBUG
29 #define CME_ETH_PRINTF rt_kprintf
30 #else
31 #define CME_ETH_PRINTF(...)
32 #endif
33
34 #define MAX_ADDR_LEN 6
35 struct rt_cme_eth
36 {
37 /* inherit from ethernet device */
38 struct eth_device parent;
39
40 /* interface address info. */
41 rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
42
43 uint32_t ETH_Speed;
44 uint32_t ETH_Mode;
45
46 struct rt_semaphore tx_buf_free;
47 struct rt_mutex lock;
48 };
49 static struct rt_cme_eth cme_eth_device;
50
51 #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
packet_dump(const char * msg,const struct pbuf * p)52 static void packet_dump(const char * msg, const struct pbuf* p)
53 {
54 const struct pbuf* q;
55 rt_uint32_t i,j;
56 rt_uint8_t *ptr;
57
58 rt_kprintf("%s %d byte\n", msg, p->tot_len);
59
60 i=0;
61 for(q=p; q != RT_NULL; q= q->next)
62 {
63 ptr = q->payload;
64
65 for(j=0; j<q->len; j++)
66 {
67 if( (i%8) == 0 )
68 {
69 rt_kprintf(" ");
70 }
71 if( (i%16) == 0 )
72 {
73 rt_kprintf("\r\n");
74 }
75 rt_kprintf("%02x ",*ptr);
76
77 i++;
78 ptr++;
79 }
80 }
81
82 rt_kprintf("\n\n");
83 }
84 #else
85 #define packet_dump(...)
86 #endif /* dump */
87
88 /////////////////////////////////////////////////////////////////
89 uint32_t rxTotalMemory = 0x2000;
90 uint32_t rxDescNum = 3;
91 uint32_t rxBufSize = 0x400;
92 uint32_t rxBaseAddr = 0x2000C000;// C000-48K
93 uint32_t txBaseAddr = 0x2000E000;// E000-56K
94 uint32_t txTotalMemory = 0x2000;
95 BOOL isRxNoBuf = FALSE;
96
97 #define ETH_MAX_PACKET_SIZE 1520 /* ETH_HEADER + ETH_EXTRA + MAX_ETH_PAYLOAD + ETH_CRC */
98 #define ETH_RXBUFNB 4
99 #define ETH_TXBUFNB 2
100
101 struct eth_rx_buffer
102 {
103 ETH_RX_DESC desc;
104 uint32_t buffer[ETH_MAX_PACKET_SIZE/4];
105 };
106
107 struct eth_tx_buffer
108 {
109 ETH_TX_DESC desc;
110 uint32_t buffer[ETH_MAX_PACKET_SIZE/4];
111 };
112
113 static struct eth_rx_buffer rx_buffer[ETH_RXBUFNB];
114 static struct eth_tx_buffer tx_buffer[ETH_TXBUFNB];
115
RxDescChainInit(void)116 static void RxDescChainInit(void)
117 {
118 uint32_t i;
119
120 // initialize rx descriptor
121 ETH_RX_DESC *desc = &rx_buffer[0].desc;
122
123 for (i = 0; i < ETH_RXBUFNB; i++)
124 {
125 desc->RX_1.RX1_b.SIZE = ETH_MAX_PACKET_SIZE;
126 desc->bufAddr = (uint32_t)rx_buffer[i].buffer;
127
128 if((i+1) == ETH_RXBUFNB)
129 desc->nextDescAddr = (uint32_t)&rx_buffer[0].desc;
130 else
131 desc->nextDescAddr = (uint32_t)&rx_buffer[i+1].desc;
132
133 desc = (ETH_RX_DESC *)desc->nextDescAddr;
134 }
135
136 ETH_SetRxDescRing(&rx_buffer[0].desc);
137 }
138
TxDescChainInit(void)139 static void TxDescChainInit(void)
140 {
141 uint32_t i;
142
143 // initialize tx descriptor
144 ETH_TX_DESC *desc = &tx_buffer[0].desc;
145
146 for (i = 0; i < ETH_TXBUFNB; i++)
147 {
148 desc->TX_1.TX1_b.SIZE = ETH_MAX_PACKET_SIZE;
149 desc->bufAddr = (uint32_t)tx_buffer[i].buffer;
150
151 if((i+1) == ETH_TXBUFNB)
152 desc->nextDescAddr = (uint32_t)&tx_buffer[0].desc;
153 else
154 desc->nextDescAddr = (uint32_t)&tx_buffer[i+1].desc;
155
156 desc = (ETH_TX_DESC *)desc->nextDescAddr;
157 }
158
159 ETH_SetTxDescRing(&tx_buffer[0].desc);
160 }
161
162 /////////////////////////////////////////////////////////////////
163
164 /* initialize the interface */
rt_cme_eth_init(rt_device_t dev)165 static rt_err_t rt_cme_eth_init(rt_device_t dev)
166 {
167 struct rt_cme_eth * cme_eth = (struct rt_cme_eth *)dev;
168
169 ETH_InitTypeDef init;
170 ETH_FrameFilter flt;
171
172 init.ETH_Speed = phy_GetSpeed();
173 init.ETH_Duplex = phy_GetDuplex();
174 init.ETH_LinkUp = phy_IsLink();
175 init.ETH_RxEn = TRUE;
176 init.ETH_TxEn = TRUE;
177 init.ETH_ChecksumOffload = FALSE;
178 init.ETH_JumboFrame = FALSE;
179
180 memcpy(init.ETH_MacAddr, cme_eth->dev_addr, sizeof(init.ETH_MacAddr));
181
182 // Disable broadcast;
183 // TODO: why?
184 memset(&flt, 0, sizeof(ETH_FrameFilter));
185 flt.ETH_BroadcastFilterEnable = FALSE;
186 flt.ETH_OwnFilterEnable = FALSE;
187 flt.ETH_SelfDrop = FALSE;
188 flt.ETH_SourceFilterEnable = FALSE;
189 flt.ETH_SourceDrop = FALSE;
190
191 init.ETH_Filter = &flt;
192
193 if (!phy_Init())
194 {
195 rt_kprintf("phy_Init failed!\n");
196 while (1);
197 }
198
199 if (!ETH_Init(&init))
200 {
201 rt_kprintf("ETH_Init failed!\n");
202 while (1);
203 }
204
205 RxDescChainInit();
206 TxDescChainInit();
207
208 ETH_ITConfig(ETH_INT_BUS_FATAL_ERROR, TRUE);
209
210 ETH_ITConfig(ETH_INT_RX_COMPLETE_FRAME, TRUE);
211 ETH_ITConfig(ETH_INT_RX_BUF_UNAVAI, TRUE);
212 ETH_ITConfig(ETH_INT_RX_STOP, TRUE);
213 ETH_StartRx();
214
215 ETH_ITConfig(ETH_INT_TX_COMPLETE_FRAME, TRUE);
216 ETH_StartTx();
217
218 return RT_EOK;
219 }
220
rt_cme_eth_open(rt_device_t dev,rt_uint16_t oflag)221 static rt_err_t rt_cme_eth_open(rt_device_t dev, rt_uint16_t oflag)
222 {
223 return RT_EOK;
224 }
225
rt_cme_eth_close(rt_device_t dev)226 static rt_err_t rt_cme_eth_close(rt_device_t dev)
227 {
228 return RT_EOK;
229 }
230
rt_cme_eth_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)231 static rt_ssize_t rt_cme_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
232 {
233 rt_set_errno(-RT_ENOSYS);
234 return 0;
235 }
236
rt_cme_eth_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)237 static rt_ssize_t rt_cme_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
238 {
239 rt_set_errno(-RT_ENOSYS);
240 return 0;
241 }
242
rt_cme_eth_control(rt_device_t dev,int cmd,void * args)243 static rt_err_t rt_cme_eth_control(rt_device_t dev, int cmd, void *args)
244 {
245 switch(cmd)
246 {
247 case NIOCTL_GADDR:
248 /* get mac address */
249 if(args) rt_memcpy(args, cme_eth_device.dev_addr, 6);
250 else return -RT_ERROR;
251 break;
252
253 default :
254 break;
255 }
256
257 return RT_EOK;
258 }
259
260 /* ethernet device interface */
261 /* transmit packet. */
rt_cme_eth_tx(rt_device_t dev,struct pbuf * p)262 rt_err_t rt_cme_eth_tx( rt_device_t dev, struct pbuf* p)
263 {
264 rt_err_t result = RT_EOK;
265 ETH_TX_DESC *desc;
266 struct rt_cme_eth * cme_eth = (struct rt_cme_eth *)dev;
267
268 rt_mutex_take(&cme_eth->lock, RT_WAITING_FOREVER);
269
270 #ifdef ETH_TX_DUMP
271 packet_dump("TX dump", p);
272 #endif /* ETH_TX_DUMP */
273
274 /* get free tx buffer */
275 {
276 rt_err_t result;
277 result = rt_sem_take(&cme_eth->tx_buf_free, RT_TICK_PER_SECOND/10);
278 if (result != RT_EOK)
279 {
280 result = -RT_ERROR;
281 goto _exit;
282 }
283 }
284
285 desc = ETH_AcquireFreeTxDesc();
286 if(desc == RT_NULL)
287 {
288 CME_ETH_PRINTF("TxDesc not ready!\n");
289 RT_ASSERT(0);
290 result = -RT_ERROR;
291 goto _exit;
292 }
293
294 desc->TX_0.TX0_b.FS = TRUE;
295 desc->TX_0.TX0_b.LS = TRUE;
296 desc->TX_1.TX1_b.SIZE = p->tot_len;
297
298 pbuf_copy_partial(p, ( void *)(desc->bufAddr), p->tot_len, 0);
299
300 ETH_ReleaseTxDesc(desc);
301 ETH_ResumeTx();
302
303 _exit:
304 rt_mutex_release(&cme_eth->lock);
305 return result;
306 }
307
308 /* reception packet. */
rt_cme_eth_rx(rt_device_t dev)309 struct pbuf *rt_cme_eth_rx(rt_device_t dev)
310 {
311 struct pbuf* p = RT_NULL;
312 ETH_RX_DESC *desc;
313 uint32_t framelength;
314 struct rt_cme_eth * cme_eth = (struct rt_cme_eth *)dev;
315 rt_err_t result;
316
317 result = rt_mutex_take(&cme_eth->lock, RT_WAITING_FOREVER);
318 if (result == -RT_ETIMEOUT)
319 {
320 rt_kprintf("Take mutex time out.\n");
321 goto _exit;
322 }
323 else if (result == -RT_ERROR)
324 {
325 rt_kprintf("Take mutex error.\n");
326 goto _exit;
327 }
328
329 desc = ETH_AcquireFreeRxDesc();
330 if(desc == RT_NULL)
331 {
332 ETH_ITConfig(ETH_INT_RX_COMPLETE_FRAME, TRUE);
333 ETH_ITConfig(ETH_INT_RX_BUF_UNAVAI, TRUE);
334 ETH_ResumeRx();
335 goto _exit;
336 }
337
338 framelength = desc->RX_0.RX0_b.FL;
339
340 /* allocate buffer */
341 p = pbuf_alloc(PBUF_LINK, framelength, PBUF_RAM);
342 if (p != RT_NULL)
343 {
344 pbuf_take(p, (const void *)(desc->bufAddr), framelength);
345 #ifdef ETH_RX_DUMP
346 packet_dump("RX dump", p);
347 #endif /* ETH_RX_DUMP */
348 }
349
350 ETH_ReleaseRxDesc(desc);
351
352 _exit:
353 rt_mutex_release(&cme_eth->lock);
354 return p;
355 }
356
NVIC_Configuration(void)357 static void NVIC_Configuration(void)
358 {
359 NVIC_InitTypeDef NVIC_InitStructure;
360
361 /* Enable the USARTy Interrupt */
362 NVIC_InitStructure.NVIC_IRQChannel = ETH_INT_IRQn;
363 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
364 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
365 NVIC_InitStructure.NVIC_IRQChannelCmd = TRUE;
366 NVIC_Init(&NVIC_InitStructure);
367 }
368
cme_m7_eth_init(void)369 int cme_m7_eth_init(void)
370 {
371 // /* PHY RESET: PA4 */
372 // {
373 // GPIO_ResetBits(GPIOA, GPIO_Pin_4);
374 // rt_thread_delay(2);
375 // GPIO_SetBits(GPIOA, GPIO_Pin_4);
376 // rt_thread_delay(2);
377 // }
378
379 // GPIO_Configuration();
380 NVIC_Configuration();
381
382 // cme_eth_device.ETH_Speed = ETH_Speed_100M;
383 // cme_eth_device.ETH_Mode = ETH_Mode_FullDuplex;
384
385 /* OUI 00-80-E1 STMICROELECTRONICS. */
386 cme_eth_device.dev_addr[0] = 0x00;
387 cme_eth_device.dev_addr[1] = 0x80;
388 cme_eth_device.dev_addr[2] = 0xE1;
389 /* generate MAC addr from 96bit unique ID (only for test). */
390 // cme_eth_device.dev_addr[3] = *(rt_uint8_t*)(0x1FFF7A10+4);
391 // cme_eth_device.dev_addr[4] = *(rt_uint8_t*)(0x1FFF7A10+2);
392 // cme_eth_device.dev_addr[5] = *(rt_uint8_t*)(0x1FFF7A10+0);
393 cme_eth_device.dev_addr[3] = 12;
394 cme_eth_device.dev_addr[4] = 34;
395 cme_eth_device.dev_addr[5] = 56;
396
397 cme_eth_device.parent.parent.init = rt_cme_eth_init;
398 cme_eth_device.parent.parent.open = rt_cme_eth_open;
399 cme_eth_device.parent.parent.close = rt_cme_eth_close;
400 cme_eth_device.parent.parent.read = rt_cme_eth_read;
401 cme_eth_device.parent.parent.write = rt_cme_eth_write;
402 cme_eth_device.parent.parent.control = rt_cme_eth_control;
403 cme_eth_device.parent.parent.user_data = RT_NULL;
404
405 cme_eth_device.parent.eth_rx = rt_cme_eth_rx;
406 cme_eth_device.parent.eth_tx = rt_cme_eth_tx;
407
408 /* init EMAC lock */
409 rt_mutex_init(&cme_eth_device.lock, "emac0", RT_IPC_FLAG_PRIO);
410
411 /* init tx buffer free semaphore */
412 rt_sem_init(&cme_eth_device.tx_buf_free,
413 "tx_buf",
414 ETH_TXBUFNB,
415 RT_IPC_FLAG_FIFO);
416
417 /* register eth device */
418 eth_device_init(&(cme_eth_device.parent), "e0");
419
420 return RT_EOK;
421 }
422
ETH_IRQHandler(void)423 void ETH_IRQHandler(void)
424 {
425 /* enter interrupt */
426 rt_interrupt_enter();
427
428 if (ETH_GetITStatus(ETH_INT_TX_COMPLETE_FRAME))
429 {
430 rt_sem_release(&cme_eth_device.tx_buf_free);
431 ETH_ClearITPendingBit(ETH_INT_TX_COMPLETE_FRAME);
432 }
433
434 if (ETH_GetITStatus(ETH_INT_RX_STOP))
435 {
436 CME_ETH_PRINTF("ETH_INT_RX_STOP\n");
437 ETH_ClearITPendingBit(ETH_INT_RX_STOP);
438 }
439
440 if ((ETH_GetITStatus(ETH_INT_RX_BUF_UNAVAI)) ||
441 (ETH_GetITStatus(ETH_INT_RX_COMPLETE_FRAME)))
442 {
443 /* a frame has been received */
444 eth_device_ready(&(cme_eth_device.parent));
445
446 ETH_ITConfig(ETH_INT_RX_COMPLETE_FRAME, FALSE);
447 ETH_ITConfig(ETH_INT_RX_BUF_UNAVAI, FALSE);
448 ETH_ClearITPendingBit(ETH_INT_RX_BUF_UNAVAI);
449 ETH_ClearITPendingBit(ETH_INT_RX_COMPLETE_FRAME);
450 }
451
452 /* leave interrupt */
453 rt_interrupt_leave();
454 }
455
456