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, &reg_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(&eth_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(&ethLock, 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, &reg_eie);
820 
821     /* Unlock device */
822     rt_sem_release(&ethLock);
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(&ethLock, 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(&ethLock);
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(&ethLock, 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(&eth_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