1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2011-06-22 onelife Initial creation for using EFM32 USART module
9 * 2011-07-25 onelife Add lock (semaphore) to prevent simultaneously access
10 * 2011-07-28 onelife Add get_ip() and update_ip() utilities
11 */
12
13 /***************************************************************************//**
14 * @addtogroup efm32_eth
15 * @{
16 ******************************************************************************/
17
18 /* Includes ------------------------------------------------------------------*/
19 #include "board.h"
20 #include "drv_usart.h"
21 #include "hdl_interrupt.h"
22 #include "drv_ethernet.h"
23
24 #if defined(EFM32_USING_ETHERNET)
25 #include <netif/ethernetif.h>
26
27 /* Private typedef -----------------------------------------------------------*/
28 /* Private define ------------------------------------------------------------*/
29 /* Private macro -------------------------------------------------------------*/
30 #ifdef EFM32_ETHERNET_DEBUG
31 #define eth_debug(format,args...) rt_kprintf(format, ##args)
32 #else
33 #define eth_debug(format,args...)
34 #endif
35
36 /* Private constants ---------------------------------------------------------*/
37 static const rt_uint8_t eth_addr[ETH_ADDR_LEN] = ETH_ADDR_DEFAULT;
38
39 /* Private variables ---------------------------------------------------------*/
40 static struct eth_device eth_dev;
41 static struct rt_semaphore ethLock;
42 static rt_uint8_t ethBank;
43 static rt_uint16_t ethNxtPkt;
44 static rt_device_t spi = RT_NULL;
45 static rt_bool_t ethAutoCs = true;
46
47 /* Private function prototypes -----------------------------------------------*/
48 /* Private functions ---------------------------------------------------------*/
49 /***************************************************************************//**
50 * @brief
51 * Set/Clear chip select
52 *
53 * @details
54 *
55 * @note
56 *
57 * @param[in] enable
58 * Chip select pin setting
59 ******************************************************************************/
efm_eth_cs(rt_uint8_t enable)60 static void efm_eth_cs(rt_uint8_t enable)
61 {
62 if (!ethAutoCs)
63 {
64 if (enable)
65 {
66 GPIO_PinOutClear(ETH_CS_PORT, ETH_CS_PIN);
67 }
68 else
69 {
70 GPIO_PinOutSet(ETH_CS_PORT, ETH_CS_PIN);
71 }
72 }
73 }
74
75 /***************************************************************************//**
76 * @brief
77 * Send command to Ethernet device
78 *
79 * @details
80 *
81 * @note
82 *
83 * @param[in] cmd
84 * Command index
85 *
86 * @param[in] addr
87 * Register address
88 *
89 * @param[in/out] data
90 * Pointer to the buffer of register value
91 *
92 * @return
93 * Error code
94 ******************************************************************************/
efm_eth_cmd(rt_uint8_t cmd,rt_uint8_t addr,rt_uint8_t * data)95 static rt_err_t efm_eth_cmd(
96 rt_uint8_t cmd,
97 rt_uint8_t addr,
98 rt_uint8_t *data)
99 {
100 RT_ASSERT(spi != RT_NULL);
101
102 rt_uint8_t buf_ins[6], buf_res[2];
103 rt_uint8_t len_ins, len_res;
104
105 len_ins = 0;
106 do
107 {
108 /* Build instruction buffer */
109 /* Check if need to read back */
110 if (cmd == ENC28J60_READ_CTRL_REG)
111 {
112 buf_ins[len_ins++] = 1; /* Instruction length */
113 }
114 /* Byte 0: Check if no address section */
115 if (cmd == ENC28J60_READ_BUF_MEM || cmd == ENC28J60_WRITE_BUF_MEM || \
116 cmd == ENC28J60_SOFT_RESET)
117 {
118 buf_ins[len_ins++] = cmd;
119 }
120 else
121 {
122 buf_ins[len_ins++] = cmd | (addr & ADDR_MASK);
123 }
124 /* Byte 1: Check if data section is present */
125 if (cmd == ENC28J60_WRITE_CTRL_REG || cmd == ENC28J60_BIT_FIELD_SET || \
126 cmd == ENC28J60_BIT_FIELD_CLR || cmd == ENC28J60_WRITE_BUF_MEM)
127 {
128 buf_ins[len_ins++] = *data;
129 }
130
131 /* Check if reading */
132 if (cmd == ENC28J60_READ_CTRL_REG)
133 {
134 *(rt_uint8_t **)(&buf_ins[len_ins]) = buf_res; /* Pointer to RX buffer */
135 len_ins += 4;
136
137 /* Check if MAC or MII register */
138 if (addr & SPRD_MASK)
139 {
140 len_res = 2;
141 }
142 else
143 {
144 len_res = 1;
145 }
146
147 /* Send command and get response */
148 efm_eth_cs(1);
149 if (spi->read(spi, ETH_SPI_RX_SKIP, buf_ins, len_res) == 0)
150 {
151 break;
152 }
153 *data = buf_res[len_res - 1];
154 // eth_debug("ETH: read RX %x %x (%d)\n", buf_res[0], buf_res[1], len_res);
155 // eth_debug("ETH: ** read RX %x %x (%d)\n",
156 // buf_res[0], buf_res[1], buf_res[2], buf_res[3], buf_res[4],
157 // buf_res[5], buf_res[6], buf_res[7], buf_res[8], buf_res[9],
158 // len_res);
159 }
160 else
161 {
162 // eth_debug("ETH: ** write TX %x %x %x %x %x %x (%d) \n", buf_ins[0],
163 // buf_ins[1], buf_ins[2], buf_ins[3], buf_ins[4], buf_ins[5],
164 // len_ins);
165 /* Send command and get response */
166 efm_eth_cs(1);
167 if (spi->write(spi, EFM32_NO_DATA, buf_ins, len_ins) == 0)
168 {
169 break;
170 }
171 }
172
173 if (!(cmd == ENC28J60_READ_BUF_MEM || cmd == ENC28J60_WRITE_BUF_MEM))
174 {
175 efm_eth_cs(0);
176 }
177 return RT_EOK;
178 } while(0);
179
180 eth_debug("ETH: Send command failed!\n");
181 efm_eth_cs(0);
182 return -RT_ERROR;
183 }
184
185 /***************************************************************************//**
186 * @brief
187 * Wrapper function of send command to Ethernet device
188 *
189 * @details
190 *
191 * @note
192 *
193 * @param[in] cmd
194 * Command index
195 *
196 * @param[in] addr
197 * Register address
198 *
199 * @param[in/out] data
200 * Pointer to the buffer of register value
201 *
202 * @return
203 * Error code
204 ******************************************************************************/
efm_eth_sendCmd(rt_uint8_t cmd,rt_uint8_t addr,rt_uint8_t * data)205 static rt_err_t efm_eth_sendCmd(
206 rt_uint8_t cmd,
207 rt_uint8_t addr,
208 rt_uint8_t *data)
209 {
210 rt_err_t ret;
211
212 eth_debug("ETH: Send command %x (%x %x)\n", cmd, addr, *data);
213 do
214 {
215 /* Change bank */
216 if(((addr & BANK_MASK) != ethBank) && ((addr < EIE) || (addr > ECON1)))
217 {
218 rt_uint8_t temp;
219
220 if ((ret = efm_eth_cmd(ENC28J60_READ_CTRL_REG, ECON1, &temp)) != RT_EOK)
221 {
222 break;
223 }
224 temp &= 0xFC;
225 ethBank = (addr & BANK_MASK);
226 temp |= ethBank >> BANK_SHIFT;
227 if ((ret = efm_eth_cmd(ENC28J60_WRITE_CTRL_REG, ECON1, &temp)) != RT_EOK)
228 {
229 break;
230 }
231 }
232 /* Send command */
233 ret = efm_eth_cmd(cmd, addr, data);
234 } while(0);
235
236 return ret;
237 }
238
239 /***************************************************************************//**
240 * @brief
241 * Read register of Ethernet device
242 *
243 * @details
244 *
245 * @note
246 *
247 * @param[in] addr
248 * Register address
249 *
250 * @return
251 * Register value
252 ******************************************************************************/
efm_eth_readReg(rt_uint8_t addr)253 static rt_uint8_t efm_eth_readReg(rt_uint8_t addr)
254 {
255 rt_uint8_t data;
256
257 efm_eth_sendCmd(ENC28J60_READ_CTRL_REG, addr, &data);
258
259 return data;
260 }
261
262 /***************************************************************************//**
263 * @brief
264 * Write register of Ethernet device
265 *
266 * @details
267 *
268 * @note
269 *
270 * @param[in] addr
271 * Register address
272 *
273 * @param[in] data
274 * Register value
275 ******************************************************************************/
efm_eth_writeReg(rt_uint8_t addr,rt_uint8_t data)276 static void efm_eth_writeReg(rt_uint8_t addr, rt_uint8_t data)
277 {
278 efm_eth_sendCmd(ENC28J60_WRITE_CTRL_REG, addr, &data);
279 }
280
281 /***************************************************************************//**
282 * @brief
283 * Read PHY register of Ethernet device
284 *
285 * @details
286 *
287 * @note
288 *
289 * @param[in] addr
290 * Register address
291 *
292 * @return
293 * Register value
294 ******************************************************************************/
efm_eth_readPhy(rt_uint8_t addr)295 static rt_uint16_t efm_eth_readPhy(rt_uint8_t addr)
296 {
297 rt_uint16_t ret;
298
299 eth_debug("ETH: *** read PHY %x\n", addr);
300
301 /* Set PHY register address */
302 efm_eth_writeReg(MIREGADR, addr);
303
304 /* Start read operation */
305 efm_eth_writeReg(MICMD, MICMD_MIIRD);
306 /* Waiting for at least 10.24 uS */
307 while(efm_eth_readReg(MISTAT) & MISTAT_BUSY);
308
309 /* Stop read operation */
310 efm_eth_writeReg(MICMD, 0x00);
311
312 /* Get the result */
313 ret = (rt_uint16_t)efm_eth_readReg(MIRDL);
314 ret |= (rt_uint16_t)efm_eth_readReg(MIRDH) << 8;
315 return ret;
316 }
317
318 /***************************************************************************//**
319 * @brief
320 * Write PHY register of Ethernet device
321 *
322 * @details
323 *
324 * @note
325 *
326 * @param[in] addr
327 * Register address
328 *
329 * @param[in] data
330 * Register value
331 ******************************************************************************/
efm_eth_writePhy(rt_uint8_t addr,rt_uint16_t data)332 static void efm_eth_writePhy(rt_uint8_t addr, rt_uint16_t data)
333 {
334 eth_debug("ETH: *** write PHY %x (%x)\n", addr, data);
335
336 /* Set PHY register address */
337 efm_eth_writeReg(MIREGADR, addr);
338
339 /* Set data */
340 efm_eth_writeReg(MIWRL, data);
341 efm_eth_writeReg(MIWRH, data >> 8);
342 /* Waiting for at least 10.24 uS */
343 while(efm_eth_readReg(MISTAT) & MISTAT_BUSY);
344 }
345
346 /***************************************************************************//**
347 * @brief
348 * Interrupt handler of Ethernet device
349 *
350 * @details
351 *
352 * @note
353 *
354 * @param[in] dev
355 * Pointer to device descriptor
356 ******************************************************************************/
efm_eth_isr(rt_device_t dev)357 void efm_eth_isr(rt_device_t dev)
358 {
359 rt_uint8_t reg_eir, data;
360 volatile rt_uint8_t cnt;
361
362 /* Disable RX and other interrutps */
363 data = EIE_PKTIE | EIE_INTIE;
364 efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data);
365
366 /* Get interrupt flag */
367 efm_eth_sendCmd(ENC28J60_READ_CTRL_REG, EIR, ®_eir);
368
369 data = 0;
370 /* DMA completed */
371 if (reg_eir & EIR_DMAIF)
372 {
373 data |= (rt_uint8_t)EIR_DMAIF;
374 }
375 /* Link Changed */
376 if (reg_eir & EIR_LINKIF)
377 {
378 /* Read PHIR to clear the flag */
379 efm_eth_readPhy(PHIR);
380 }
381 /* TX done */
382 if (reg_eir & EIR_TXIF)
383 {
384 data |= (rt_uint8_t)EIR_TXIF;
385 }
386 /* TX error */
387 if (reg_eir & EIR_TXERIF)
388 {
389 data |= (rt_uint8_t)EIR_TXERIF;
390 }
391 /* RX error */
392 if (reg_eir & EIR_RXERIF)
393 {
394 data |= (rt_uint8_t)EIR_RXERIF;
395 }
396 /* Clear flags */
397 efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIR, &data);
398
399 /* Get packet counter (Errata 6) */
400 efm_eth_sendCmd(ENC28J60_READ_CTRL_REG, EPKTCNT, (rt_uint8_t *)&cnt);
401 if (cnt)
402 {
403 /* Inform Ethernet thread */
404 eth_device_ready(ð_dev);
405 }
406
407 /* Enable other interrupts */
408 data = EIE_INTIE;
409 efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &data);
410 }
411
412 /***************************************************************************//**
413 * @brief
414 * Initialize Ethernet device
415 *
416 * @details
417 *
418 * @note
419 *
420 * @param[in] dev
421 * Pointer to device descriptor
422 *
423 * @return
424 * Error code
425 ******************************************************************************/
efm_eth_init(rt_device_t dev)426 static rt_err_t efm_eth_init(rt_device_t dev)
427 {
428 rt_uint16_t reg_phy;
429 rt_uint8_t data;
430
431 /* Reset chip select */
432 efm_eth_cs(0);
433 /* Software reset */
434 efm_eth_sendCmd(ENC28J60_SOFT_RESET, EFM32_NO_DATA, EFM32_NO_POINTER);
435 /* Waiting for at least 1 ms (Errata 2) */
436 rt_thread_delay(ETH_PERIOD_WAIT_INIT);
437 ethNxtPkt = RXSTART_INIT;
438 ethBank = 0;
439
440 /* Init RX buffer */
441 efm_eth_writeReg(ERXSTL, RXSTART_INIT & 0xFF);
442 efm_eth_writeReg(ERXSTH, RXSTART_INIT >> 8);
443 efm_eth_writeReg(ERXNDL, RXSTOP_INIT & 0xFF);
444 efm_eth_writeReg(ERXNDH, RXSTOP_INIT >> 8);
445 efm_eth_writeReg(ERXRDPTL, RXSTOP_INIT & 0xFF);
446 efm_eth_writeReg(ERXRDPTH, RXSTOP_INIT >> 8);
447
448 /* Init TX buffer */
449 efm_eth_writeReg(ETXSTL, TXSTART_INIT & 0xFF);
450 efm_eth_writeReg(ETXSTH, TXSTART_INIT >> 8);
451 efm_eth_writeReg(ETXNDL, TXSTOP_INIT & 0xFF);
452 efm_eth_writeReg(ETXNDH, TXSTOP_INIT >> 8);
453 efm_eth_writeReg(EWRPTL, TXSTART_INIT & 0xFF);
454 efm_eth_writeReg(EWRPTH, TXSTART_INIT >> 8);
455
456 /* Init RX filters */
457 /* For broadcast packets we allow only ARP packtets
458 All other packets should be unicast only for our mac (MAADR)
459
460 The pattern to match on is therefore
461 Type ETH.DST
462 ARP BROADCAST
463 06 08 -- -- -- -- -- -- ff ff ff ff ff ff
464 These poitions are: 11 0000 0011 1111 in binary and 30 3f in hex
465 Checksum for theses bytes is: f7 f9 */
466 efm_eth_writeReg(EPMM0, 0x3f);
467 efm_eth_writeReg(EPMM1, 0x30);
468 efm_eth_writeReg(EPMCSL, 0xf9);
469 efm_eth_writeReg(EPMCSH, 0xf7);
470 efm_eth_writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN);
471 //efm_eth_writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN);
472 /* Waiting For OST: The OST does not expire until 7500 OSC1 clock cycles (300 uS)
473 pass after Power-on Reset or wake-up from Power-Down mode occurs */
474
475 /* Init MAC */
476 /* Enable RX, IEEE defined flow control */
477 efm_eth_writeReg(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);
478 /* Enable padding to 60 bytes, CRC and frame length status reporting */
479 #if defined(ETH_HALF_DUPLEX)
480 efm_eth_writeReg(MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN);
481 efm_eth_writeReg(MACON4, MACON4_DEFER);
482 #else
483 efm_eth_writeReg(MACON3, \
484 MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX);
485 #endif
486 /* Set the maximum packet length */
487 efm_eth_writeReg(MAMXFLL, MAX_FRAMELEN & 0xFF);
488 efm_eth_writeReg(MAMXFLH, MAX_FRAMELEN >> 8);
489 /* Set inter-packet gap (back-to-back). Full-Duplex: 0x15, Half-Duplex: 0x12 */
490 #if defined(ETH_HALF_DUPLEX)
491 efm_eth_writeReg(MABBIPG, 0x12);
492 #else
493 efm_eth_writeReg(MABBIPG, 0x15);
494 #endif
495 /* Set inter-packet gap (non-back-to-back).
496 Full-Duplex: 0x0012, Half-Duplex: 0x0C12 */
497 efm_eth_writeReg(MAIPGL, 0x12);
498 #if defined(ETH_HALF_DUPLEX)
499 efm_eth_writeReg(MAIPGH, 0x0C);
500 /* Set retransmission and collision window */
501 efm_eth_writeReg(MACLCON1, 0x0F);
502 efm_eth_writeReg(MACLCON2, 0x37);
503 #endif
504 /* Set MAC address
505 NOTE: MAC address in ENC28J60 is byte-backward */
506 efm_eth_writeReg(MAADR1, eth_addr[0]);
507 efm_eth_writeReg(MAADR2, eth_addr[1]);
508 efm_eth_writeReg(MAADR3, eth_addr[2]);
509 efm_eth_writeReg(MAADR4, eth_addr[3]);
510 efm_eth_writeReg(MAADR5, eth_addr[4]);
511 efm_eth_writeReg(MAADR6, eth_addr[5]);
512
513 /* Init PHY */
514 #if defined(ETH_HALF_DUPLEX)
515 reg_phy = efm_eth_readPhy(PHCON2);
516 efm_eth_writePhy(PHCON2, reg_phy | PHCON2_HDLDIS);
517 #else
518 reg_phy = efm_eth_readPhy(PHCON1);
519 efm_eth_writePhy(PHCON1, reg_phy | PHCON1_PDPXMD);
520 #endif
521 /* LEDA: Display link status;
522 LEDB: Display transmit and receive activity */
523 reg_phy = efm_eth_readPhy(PHLCON);
524 efm_eth_writePhy(PHLCON, (reg_phy & 0xF00F) | 0x0470);
525
526 /* Disable clock output */
527 efm_eth_writeReg(ECOCON, 0x00);
528
529 /* Clear interrutp flags */
530 data = EIR_DMAIF | EIR_TXIF | EIR_TXERIF | EIR_RXERIF;
531 efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIR, &data);
532 /* Enable interrutps */
533 data = EIE_INTIE | EIE_PKTIE | EIE_TXIE;
534 efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &data);
535 /* Enable RX */
536 data = ECON1_RXEN;
537 efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data);
538
539 eth_debug("ETH: Init OK\n");
540 return RT_EOK;
541 }
542
543 /***************************************************************************//**
544 * @brief
545 * Open Ethernet device
546 *
547 * @details
548 *
549 * @note
550 *
551 * @param[in] dev
552 * Pointer to device descriptor
553 *
554 * @param[in] oflag
555 * Device open flag
556 *
557 * @return
558 * Error code
559 ******************************************************************************/
efm_eth_open(rt_device_t dev,rt_uint16_t oflag)560 static rt_err_t efm_eth_open(rt_device_t dev, rt_uint16_t oflag)
561 {
562 eth_debug("ETH: Open, flag %x\n", eth_dev.parent.flag);
563 return RT_EOK;
564 }
565
566 /***************************************************************************//**
567 * @brief
568 * Close Ethernet device
569 *
570 * @details
571 *
572 * @note
573 *
574 * @param[in] dev
575 * Pointer to device descriptor
576 *
577 * @return
578 * Error code
579 ******************************************************************************/
efm_eth_close(rt_device_t dev)580 static rt_err_t efm_eth_close(rt_device_t dev)
581 {
582 eth_debug("ETH: Close, flag %x\n", eth_dev.parent.flag);
583 return RT_EOK;
584 }
585
586 /***************************************************************************//**
587 * @brief
588 * Read from Ethernet device (Dummy function)
589 *
590 * @details
591 *
592 * @note
593 *
594 * @param[in] dev
595 * Pointer to device descriptor
596 *
597 * @param[in] pos
598 * Offset
599 *
600 * @param[in] buffer
601 * Poniter to the buffer
602 *
603 * @param[in] size
604 * Buffer size in byte
605 *
606 * @return
607 * Number of read bytes
608 ******************************************************************************/
efm_eth_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)609 static rt_ssize_t efm_eth_read(
610 rt_device_t dev,
611 rt_off_t pos,
612 void *buffer,
613 rt_size_t size)
614 {
615 rt_set_errno(-RT_ENOSYS);
616 return 0;
617 }
618
619 /***************************************************************************//**
620 * @brief
621 * Write to Ethernet device (Dummy function)
622 *
623 * @details
624 *
625 * @note
626 *
627 * @param[in] dev
628 * Pointer to device descriptor
629 *
630 * @param[in] pos
631 * Offset
632 *
633 * @param[in] buffer
634 * Poniter to the buffer
635 *
636 * @param[in] size
637 * Buffer size in byte
638 *
639 * @return
640 * Number of written bytes
641 ******************************************************************************/
efm_eth_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)642 static rt_ssize_t efm_eth_write (
643 rt_device_t dev,
644 rt_off_t pos,
645 const void *buffer,
646 rt_size_t size)
647 {
648 rt_set_errno(-RT_ENOSYS);
649 return 0;
650 }
651
652 /***************************************************************************//**
653 * @brief
654 * Configure Ethernet device
655 *
656 * @details
657 *
658 * @note
659 *
660 * @param[in] dev
661 * Pointer to device descriptor
662 *
663 * @param[in] cmd
664 * Ethernet control command
665 *
666 * @param[in] args
667 * Arguments
668 *
669 * @return
670 * Error code
671 ******************************************************************************/
efm_eth_control(rt_device_t dev,rt_uint8_t cmd,void * args)672 static rt_err_t efm_eth_control (
673 rt_device_t dev,
674 rt_uint8_t cmd,
675 void *args)
676 {
677 rt_err_t ret;
678
679 ret = -RT_ERROR;
680 switch(cmd)
681 {
682 case NIOCTL_GADDR:
683 /* Get MAC address */
684 if(args)
685 {
686 rt_memcpy(args, eth_addr, sizeof(eth_addr));
687 ret = RT_EOK;
688 }
689 break;
690
691 default :
692 break;
693 }
694
695 return RT_EOK;
696 }
697
698 /***************************************************************************//**
699 * @brief
700 * Packet receiving function
701 *
702 * @details
703 *
704 * @note
705 *
706 * @param[in] dev
707 * Pointer to device descriptor
708 *
709 * @return
710 * Pointer to packet buffer
711 ******************************************************************************/
efm_eth_rx(rt_device_t dev)712 struct pbuf *efm_eth_rx(rt_device_t dev)
713 {
714 rt_uint8_t buf_ins[5], buf_read[6];
715 rt_uint8_t data, reg_eie;
716 rt_uint16_t len_rx, sta_rx;
717 struct pbuf* p;
718
719 /* Lock device */
720 rt_sem_take(ðLock, RT_WAITING_FOREVER);
721
722 /* Disable interrupts */
723 data = EIE_INTIE;
724 efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data);
725
726 p = RT_NULL;
727 reg_eie = 0;
728 if (efm_eth_readReg(EPKTCNT))
729 {
730 /* Set read pointer to the start of RX packet */
731 efm_eth_writeReg(ERDPTL, ethNxtPkt & 0xFF);
732 efm_eth_writeReg(ERDPTH, ethNxtPkt >> 8);
733
734 /* Send read buffer command */
735 efm_eth_sendCmd(ENC28J60_READ_BUF_MEM, EFM32_NO_DATA, EFM32_NO_POINTER);
736 /* Build instruction buffer */
737 buf_ins[0] = 0x00;
738 *(rt_uint8_t **)(&buf_ins[1]) = buf_read;
739 /* Read packet header */
740 if (spi->read(spi, EFM32_NO_DATA, buf_ins, sizeof(buf_read)) == 0)
741 {
742 eth_debug("ETH: RX header failed!\n");
743 }
744
745 ethNxtPkt = buf_read[0] | (buf_read[1] << 8);
746 len_rx = buf_read[2] | (buf_read[3] << 8);
747 sta_rx = buf_read[4] | (buf_read[5] << 8);
748 eth_debug("ETH: RX header ethNxtPkt %x, len_rx %x, sta_rx %x\n",
749 ethNxtPkt, len_rx, sta_rx);
750 /* Check if OK */
751 if (sta_rx & 0x80)
752 {
753 /* Allocate pbuf */
754 p = pbuf_alloc(PBUF_LINK, len_rx - 4, PBUF_RAM);
755 if (p != RT_NULL)
756 {
757 struct pbuf* q;
758
759 for (q = p; q != RT_NULL; q= q->next)
760 {
761 /* Build instruction buffer */
762 buf_ins[0] = 0x00;
763 *(rt_uint8_t **)(&buf_ins[1]) = q->payload;
764 /* Read packet header */
765 if (spi->read(spi, EFM32_NO_DATA, buf_ins, q->len) == 0)
766 {
767 eth_debug("ETH: RX payload failed!\n");
768 }
769 #ifdef EFM32_ETHERNET_DEBUG
770 {
771 rt_uint8_t *temp = (rt_uint8_t *)q->payload;
772 rt_uint32_t i;
773
774 eth_debug("ETH: ***** read RX (q->len %x) *****\n", q->len);
775 for (i = 0; i < q->len; i += 8)
776 {
777 eth_debug("%02x %02x %02x %02x %02x %02x %02x %02x | %c %c %c %c %c %c %c %c\n",
778 temp[i], temp[i + 1], temp[i + 2], temp[i + 3],
779 temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7],
780 temp[i], temp[i + 1], temp[i + 2], temp[i + 3],
781 temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7]);
782 }
783 }
784 #endif
785 }
786 }
787 else
788 {
789 eth_debug("ETH: No memory for pbuf!!!\n");
790 }
791 }
792 else
793 {
794 eth_debug("ETH: Invalid CRC or symbol error occurred!\n");
795 }
796 efm_eth_cs(0);
797
798 /* Free buffer */
799 efm_eth_writeReg(ERXRDPTL, ethNxtPkt & 0xFF);
800 efm_eth_writeReg(ERXRDPTH, ethNxtPkt >> 8);
801
802 /* Decrease counter */
803 data = ECON2_PKTDEC;
804 efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON2, &data);
805 }
806 else
807 {
808 /* Enable RX */
809 data = ECON1_RXEN;
810 efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data);
811
812 reg_eie |= EIE_PKTIE;
813 eth_debug("ETH: Enable RX interrupt\n");
814 }
815 eth_debug("ETH: RX counter %x\n", efm_eth_readReg(EPKTCNT));
816
817 /* Enable interrupts */
818 reg_eie |= EIE_INTIE;
819 efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, ®_eie);
820
821 /* Unlock device */
822 rt_sem_release(ðLock);
823
824 return p;
825 }
826
827 /***************************************************************************//**
828 * @brief
829 * Packet transmission function
830 *
831 * @details
832 *
833 * @note
834 *
835 * @param[in] dev
836 * Pointer to device descriptor
837 *
838 * @param[in] p
839 * Pointer to packet buffer
840 *
841 * @return
842 * Error code
843 ******************************************************************************/
efm_eth_tx(rt_device_t dev,struct pbuf * p)844 rt_err_t efm_eth_tx(rt_device_t dev, struct pbuf* p)
845 {
846 rt_uint8_t data;
847 struct pbuf* q;
848
849 /* Lock device */
850 rt_sem_take(ðLock, RT_WAITING_FOREVER);
851
852 /* Disable interrupts */
853 data = EIE_INTIE;
854 efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data);
855
856 /* Set write pointer to the start of TX buffer */
857 efm_eth_writeReg(EWRPTL, TXSTART_INIT & 0xFF);
858 efm_eth_writeReg(EWRPTH, TXSTART_INIT >> 8);
859 /* Set buffer end pointer according to the packet size */
860 efm_eth_writeReg(ETXNDL, (TXSTART_INIT + p->tot_len + 1) & 0xFF);
861 efm_eth_writeReg(ETXNDH, (TXSTART_INIT + p->tot_len + 1) >> 8);
862
863 /* Send write buffer command */
864 data = 0x00; /* Control byte */
865 efm_eth_sendCmd(ENC28J60_WRITE_BUF_MEM, EFM32_NO_DATA, &data);
866 /* Send data */
867 for (q = p; q != NULL; q = q->next)
868 {
869 if (spi->write(spi, EFM32_NO_DATA, q->payload, q->len) == 0)
870 {
871 eth_debug("ETH: TX failed!\n");
872 return -RT_ERROR;
873 }
874 #ifdef EFM32_ETHERNET_DEBUG
875 {
876 rt_uint8_t *temp = (rt_uint8_t *)q->payload;
877 rt_uint32_t i;
878
879 eth_debug("ETH: ***** write TX (len %d) *****\n", p->len);
880 for (i = 0; i < q->len; i += 8)
881 {
882 eth_debug("%02x %02x %02x %02x %02x %02x %02x %02x | %c %c %c %c %c %c %c %c\n",
883 temp[i], temp[i + 1], temp[i + 2], temp[i + 3],
884 temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7],
885 temp[i], temp[i + 1], temp[i + 2], temp[i + 3],
886 temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7]);
887 }
888 }
889 #endif
890 }
891 efm_eth_cs(0);
892 /* Start TX */
893 data = ECON1_TXRTS;
894 efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data);
895 /* Errata 12 */
896 if (efm_eth_readReg(EIR) & EIR_TXERIF)
897 {
898 efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, ECON1, &data);
899 data = EIR_TXERIF;
900 efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIR, &data);
901 data = ECON1_TXRTS;
902 efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data);
903 }
904
905 /* Waiting for a while */
906 rt_thread_delay(ETH_PERIOD_WAIT_INIT);
907 /* Enable interrupts */
908 data = EIE_INTIE;
909 efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &data);
910
911 /* Unlock device */
912 rt_sem_release(ðLock);
913
914 return RT_EOK;
915 }
916
917 /***************************************************************************//**
918 * @brief
919 * Initialize all Ethernet related hardware and register the device to kernel
920 *
921 * @details
922 *
923 * @note
924 *
925 * @return
926 * Error code
927 ******************************************************************************/
efm_hw_eth_init(void)928 rt_err_t efm_hw_eth_init(void)
929 {
930 struct efm32_usart_device_t *usart;
931 efm32_irq_hook_init_t hook;
932
933 do
934 {
935 /* Find SPI device */
936 spi = rt_device_find(ETH_USING_DEVICE_NAME);
937 if (spi == RT_NULL)
938 {
939 eth_debug("ETH: Can't find device %s!\n",
940 ETH_USING_DEVICE_NAME);
941 break;
942 }
943 eth_debug("ETH: Find device %s\n", ETH_USING_DEVICE_NAME);
944
945 /* Config chip slect pin */
946 usart = (struct efm32_usart_device_t *)(spi->user_data);
947 if (!(usart->state & USART_STATE_AUTOCS))
948 {
949 GPIO_PinModeSet(ETH_CS_PORT, ETH_CS_PIN, gpioModePushPull, 1);
950 ethAutoCs = false;
951 }
952 /* Config reset pin */
953 GPIO_PinModeSet(ETH_RESET_PORT, ETH_RESET_PIN, gpioModePushPull, 0);
954 /* Config interrupt pin */
955 GPIO_PinModeSet(ETH_INT_PORT, ETH_INT_PIN, gpioModeInput, 1);
956
957 /* Config interrupt */
958 hook.type = efm32_irq_type_gpio;
959 hook.unit = ETH_INT_PIN;
960 hook.cbFunc = efm_eth_isr;
961 hook.userPtr = RT_NULL;
962 efm32_irq_hook_register(&hook);
963 /* Clear pending interrupt */
964 BITBAND_Peripheral(&(GPIO->IFC), ETH_INT_PIN, 0x1UL);
965 /* Set falling edge interrupt and clear/enable it */
966 GPIO_IntConfig(
967 ETH_INT_PORT,
968 ETH_INT_PIN,
969 false,
970 true,
971 true);
972 if ((rt_uint8_t)ETH_INT_PIN % 2)
973 {
974 NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
975 NVIC_SetPriority(GPIO_ODD_IRQn, EFM32_IRQ_PRI_DEFAULT);
976 NVIC_EnableIRQ(GPIO_ODD_IRQn);
977 }
978 else
979 {
980 NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
981 NVIC_SetPriority(GPIO_EVEN_IRQn, EFM32_IRQ_PRI_DEFAULT);
982 NVIC_EnableIRQ(GPIO_EVEN_IRQn);
983 }
984
985 /* Set SPI speed */
986 USART_BaudrateSyncSet(usart->usart_device, 0, ETH_CLK_MAX);
987
988 /* Initialize semaphore */
989 rt_sem_init(ðLock, ETH_DEVICE_NAME, 1, RT_IPC_FLAG_FIFO);
990
991 /* Register Ethernet device */
992 eth_dev.parent.init = efm_eth_init;
993 eth_dev.parent.open = efm_eth_open;
994 eth_dev.parent.close = efm_eth_close;
995 eth_dev.parent.read = efm_eth_read;
996 eth_dev.parent.write = efm_eth_write;
997 eth_dev.parent.control = efm_eth_control;
998 eth_dev.eth_rx = efm_eth_rx;
999 eth_dev.eth_tx = efm_eth_tx;
1000 eth_device_init(ð_dev, ETH_DEVICE_NAME);
1001
1002 /* Start device */
1003 GPIO_PinOutSet(ETH_RESET_PORT, ETH_RESET_PIN);
1004
1005 eth_debug("ETH: HW init OK\n");
1006 return RT_EOK;
1007 } while (0);
1008
1009 /* Release buffer */
1010 rt_kprintf("ETH: HW init failed!\n");
1011 return -RT_ERROR;
1012 }
1013
1014 /*******************************************************************************
1015 * Export to FINSH
1016 ******************************************************************************/
1017 #if defined(EFM32_USING_ETH_UTILS)
1018 #ifdef RT_USING_FINSH
1019 #include <finsh.h>
1020
list_eth(void)1021 void list_eth(void)
1022 {
1023 rt_uint16_t reg_phy;
1024 rt_uint8_t data;
1025
1026 rt_kprintf(" ENC28J60 on %s\n", ETH_USING_DEVICE_NAME);
1027 rt_kprintf(" ------------------------------\n");
1028 reg_phy = efm_eth_readPhy(PHSTAT2);
1029 if (reg_phy & PHSTAT2_PLRITY)
1030 {
1031 rt_kprintf(" Cable polarity is reversed\n");
1032 }
1033 else
1034 {
1035 rt_kprintf(" Cable polarity is correct\n");
1036 }
1037 if (reg_phy & PHSTAT2_DPXSTAT)
1038 {
1039 rt_kprintf(" Full-duplex mode\n");
1040 }
1041 else
1042 {
1043 rt_kprintf(" Half-duplex mode\n");
1044 }
1045 if (reg_phy & PHSTAT2_LSTAT)
1046 {
1047 rt_kprintf(" Link is up\n");
1048 }
1049 else
1050 {
1051 rt_kprintf(" Link is down\n");
1052 }
1053 if (reg_phy & PHSTAT2_COLSTAT)
1054 {
1055 rt_kprintf(" Collision is occuring\n");
1056 }
1057 else
1058 {
1059 rt_kprintf(" No collision\n");
1060 }
1061 if (reg_phy & PHSTAT2_RXSTAT)
1062 {
1063 rt_kprintf(" RX is busy\n");
1064 }
1065 else
1066 {
1067 rt_kprintf(" RX is idle\n");
1068 }
1069 if (reg_phy & PHSTAT2_TXSTAT)
1070 {
1071 rt_kprintf(" TX is busy\n");
1072 }
1073 else
1074 {
1075 rt_kprintf(" TX is idle\n");
1076 }
1077 }
1078 FINSH_FUNCTION_EXPORT(list_eth, list the Ethernet device status.)
1079
1080 #include "lwip\api.h"
1081
get_ip(char * ip)1082 rt_err_t get_ip(char *ip)
1083 {
1084 err_t ret;
1085 struct ip_addr server_ip;
1086 struct netconn *conn;
1087 struct netbuf *buf;
1088 char *rq, *rq2;
1089 u16_t len;
1090 const char query[] = "GET / HTTP/1.0\r\nHOST: checkip.dyndns.com\r\n\r\n";
1091 const char find[] = "body";
1092
1093 do
1094 {
1095 #if defined(RT_LWIP_DNS)
1096 ret = netconn_gethostbyname("checkip.dyndns.com", &server_ip);
1097 if (ret != ERR_OK)
1098 {
1099 break;
1100 }
1101 #else
1102 IP4_ADDR(&server_ip, 216,146,38,70); // IP address of "checkip.dyndns.com"
1103 #endif
1104
1105 conn = netconn_new(NETCONN_TCP);
1106 if (conn == NULL)
1107 {
1108 break;
1109 }
1110
1111 ret = netconn_connect(conn, &server_ip, 80);
1112 if (ret != ERR_OK)
1113 {
1114 break;
1115 }
1116
1117 /* Send the query */
1118 ret = netconn_write(conn, query, sizeof(query) - 1, 0);
1119 if (ret != ERR_OK)
1120 {
1121 break;
1122 }
1123
1124 buf = netconn_recv(conn);
1125 if (buf != NULL)
1126 {
1127 /* Get the response */
1128 ret = netbuf_data(buf, (void **)&rq, &len);
1129 if (ret != ERR_OK)
1130 {
1131 break;
1132 }
1133
1134 /* Find the IP address */
1135 rq = rt_strstr(rq, find);
1136 if (rq == RT_NULL)
1137 {
1138 break;
1139 }
1140 rq += 5;
1141 rq2 = rq;
1142 rq2 = rt_strstr(rq2, find);
1143 if (rq2 == RT_NULL)
1144 {
1145 break;
1146 }
1147 rq2 -= 2;
1148 *rq2 = 0x0;
1149 // rt_kprintf("[%s]\n", rq);
1150 }
1151 else
1152 {
1153 break;
1154 }
1155
1156 /* Copy the IP address to buffer */
1157 if (ip != NULL)
1158 {
1159 while(*rq < '0' || *rq > '9')
1160 {
1161 rq++;
1162 }
1163 rt_memcpy(ip, rq, rq2 - rq + 1);
1164 }
1165 netconn_delete(conn);
1166 netbuf_delete(buf);
1167 return RT_EOK;
1168 } while (0);
1169
1170 netconn_delete(conn);
1171 netbuf_delete(buf);
1172 return -RT_ERROR;
1173 }
1174
list_myip(void)1175 void list_myip(void)
1176 {
1177 rt_uint8_t ip[20];
1178
1179 if (get_ip(ip) != RT_EOK)
1180 {
1181 rt_kprintf("Get IP failed!\n");
1182 return;
1183 }
1184
1185 rt_kprintf("Current IP: [%s]\n", ip);
1186 }
1187 FINSH_FUNCTION_EXPORT(list_myip, list the current IP address.)
1188
1189 #if !defined(hostName) || !defined(userPwdB64)
1190 #error "The 'hostName' and 'userPwdB64' must be defined to use update_ip() function"
1191 #endif
1192
update_ip(char * ip)1193 rt_err_t update_ip(char *ip)
1194 {
1195 err_t ret;
1196 struct ip_addr server_ip;
1197 struct netconn *conn;
1198 struct netbuf *buf;
1199 char *rq;
1200 u16_t len, len2;
1201 char query[200] = "GET /nic/update?hostname=";
1202 const char query2[] = "&myip=";
1203 const char query3[] = " HTTP/1.0\r\nHost: members.dyndns.org\r\nAuthorization: Basic ";
1204 const char query4[] = "\r\nUser-Agent: onelife - EFM32 - 0.4\r\n\r\n";
1205 const char find[] = "good";
1206
1207 /* Make the query */
1208 len = rt_strlen(query);
1209 len2 = sizeof(hostName) - 1;
1210 rt_memcpy(&query[len], hostName, len2);
1211 len += len2;
1212
1213 len2 = sizeof(query2) - 1;
1214 rt_memcpy(&query[len], query2, len2);
1215 len += len2;
1216
1217 len2 = rt_strlen(ip);
1218 rt_memcpy(&query[len], ip, len2);
1219 len += len2;
1220
1221 len2 = sizeof(query3) - 1;
1222 rt_memcpy(&query[len], query3, len2);
1223 len += len2;
1224
1225 len2 = sizeof(userPwdB64) - 1;
1226 rt_memcpy(&query[len], userPwdB64, len2);
1227 len += len2;
1228
1229 len2 = sizeof(query4) - 1;
1230 rt_memcpy(&query[len], query4, len2);
1231 len += len2;
1232
1233 query[len] = 0x0;
1234 // rt_kprintf("Query: %s\n", &query[100]);
1235
1236 do
1237 {
1238 #if defined(RT_LWIP_DNS)
1239 ret = netconn_gethostbyname("members.dyndns.org", &server_ip);
1240 if (ret != ERR_OK)
1241 {
1242 break;
1243 }
1244 #else
1245 IP4_ADDR(&server_ip, 204,13,248,112); // IP address of "members.dyndns.org"
1246 #endif
1247
1248 conn = netconn_new(NETCONN_TCP);
1249 if (conn == NULL)
1250 {
1251 break;
1252 }
1253
1254 ret = netconn_connect(conn, &server_ip, 80);
1255 if (ret != ERR_OK)
1256 {
1257 break;
1258 }
1259
1260 /* Send the query */
1261 ret = netconn_write(conn, query, len, 0);
1262 if (ret != ERR_OK)
1263 {
1264 break;
1265 }
1266
1267 /* Get the response */
1268 buf = netconn_recv(conn);
1269 if (buf != NULL)
1270 {
1271 ret = netbuf_data(buf, (void **)&rq, &len);
1272 if (ret != ERR_OK)
1273 {
1274 break;
1275 }
1276
1277 /* Find the result */
1278 rq = rt_strstr(rq, find);
1279 if (rq == RT_NULL)
1280 {
1281 break;
1282 }
1283 // rt_kprintf("[%s]\n", rq);
1284 }
1285 else
1286 {
1287 break;
1288 }
1289
1290 netconn_delete(conn);
1291 netbuf_delete(buf);
1292 return RT_EOK;
1293 } while (0);
1294
1295 netconn_delete(conn);
1296 netbuf_delete(buf);
1297 return -RT_ERROR;
1298 }
1299
update_myip(char * ip)1300 void update_myip(char *ip)
1301 {
1302 rt_kprintf("Update host, \"%s\", to new IP address %s: ", hostName, ip);
1303
1304 if (update_ip(ip) != RT_EOK)
1305 {
1306 rt_kprintf("failed!\n");
1307 return;
1308 }
1309
1310 rt_kprintf("succeeded.\n", ip);
1311 }
1312 FINSH_FUNCTION_EXPORT(update_myip, update DDNS with specified IP address.)
1313
1314 #endif /* RT_USING_FINSH */
1315 #endif /* defined(EFM32_USING_ETH_UTILS) */
1316
1317 #endif /* defined(EFM32_USING_ETHERNET) */
1318 /******************************************************************//**
1319 * @}
1320 ******************************************************************************/
1321