drv_ethernet.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  1. /***************************************************************************//**
  2. * @file drv_ethernet.c
  3. * @brief Ethernet driver (SPI mode) of RT-Thread RTOS for using EFM32 USART
  4. * module
  5. * This driver is tested by using the Microchip ENC28J60 stand-alone Ethernet
  6. * controller with SPI interface.
  7. * COPYRIGHT (C) 2011, RT-Thread Development Team
  8. * @author onelife
  9. * @version 0.4 beta
  10. *******************************************************************************
  11. * @section License
  12. * The license and distribution terms for this file may be found in the file
  13. * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
  14. *******************************************************************************
  15. * @section Change Logs
  16. * Date Author Notes
  17. * 2011-06-22 onelife Initial creation for using EFM32 USART module
  18. ******************************************************************************/
  19. /***************************************************************************//**
  20. * @addtogroup efm32_eth
  21. * @{
  22. ******************************************************************************/
  23. /* Includes ------------------------------------------------------------------*/
  24. #include "board.h"
  25. #include "drv_usart.h"
  26. #include "hdl_interrupt.h"
  27. #include "drv_ethernet.h"
  28. #if defined(EFM32_USING_ETHERNET)
  29. #include <netif/ethernetif.h>
  30. /* Private typedef -----------------------------------------------------------*/
  31. /* Private define ------------------------------------------------------------*/
  32. /* Private macro -------------------------------------------------------------*/
  33. #ifdef EFM32_ETHERNET_DEBUG
  34. #define eth_debug(format,args...) rt_kprintf(format, ##args)
  35. #else
  36. #define eth_debug(format,args...)
  37. #endif
  38. /* Private constants ---------------------------------------------------------*/
  39. static const rt_uint8_t eth_addr[ETH_ADDR_LEN] = ETH_ADDR_DEFAULT;
  40. /* Private variables ---------------------------------------------------------*/
  41. static struct eth_device eth_dev;
  42. static struct rt_semaphore ethLock;
  43. static rt_uint8_t ethBank;
  44. static rt_uint16_t ethNxtPkt;
  45. static rt_device_t spi = RT_NULL;
  46. static rt_bool_t ethAutoCs = true;
  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. ******************************************************************************/
  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. * @brief
  76. * Send command to Ethernet device
  77. *
  78. * @details
  79. *
  80. * @note
  81. *
  82. * @param[in] cmd
  83. * Command index
  84. *
  85. * @param[in] addr
  86. * Register address
  87. *
  88. * @param[in/out] data
  89. * Pointer to the buffer of register value
  90. *
  91. * @return
  92. * Error code
  93. ******************************************************************************/
  94. static rt_err_t efm_eth_cmd(
  95. rt_uint8_t cmd,
  96. rt_uint8_t addr,
  97. rt_uint8_t *data)
  98. {
  99. RT_ASSERT(spi != RT_NULL);
  100. rt_uint8_t buf_ins[6], buf_res[2];
  101. rt_uint8_t len_ins, len_res;
  102. len_ins = 0;
  103. do
  104. {
  105. /* Build instruction buffer */
  106. /* Check if need to read back */
  107. if (cmd == ENC28J60_READ_CTRL_REG)
  108. {
  109. buf_ins[len_ins++] = 1; /* Instruction length */
  110. }
  111. /* Byte 0: Check if no address section */
  112. if (cmd == ENC28J60_READ_BUF_MEM || cmd == ENC28J60_WRITE_BUF_MEM || \
  113. cmd == ENC28J60_SOFT_RESET)
  114. {
  115. buf_ins[len_ins++] = cmd;
  116. }
  117. else
  118. {
  119. buf_ins[len_ins++] = cmd | (addr & ADDR_MASK);
  120. }
  121. /* Byte 1: Check if data section is present */
  122. if (cmd == ENC28J60_WRITE_CTRL_REG || cmd == ENC28J60_BIT_FIELD_SET || \
  123. cmd == ENC28J60_BIT_FIELD_CLR || cmd == ENC28J60_WRITE_BUF_MEM)
  124. {
  125. buf_ins[len_ins++] = *data;
  126. }
  127. /* Check if reading */
  128. if (cmd == ENC28J60_READ_CTRL_REG)
  129. {
  130. *(rt_uint8_t **)(&buf_ins[len_ins]) = buf_res; /* Pointer to RX buffer */
  131. len_ins += 4;
  132. /* Check if MAC or MII register */
  133. if (addr & SPRD_MASK)
  134. {
  135. len_res = 2;
  136. }
  137. else
  138. {
  139. len_res = 1;
  140. }
  141. /* Send command and get response */
  142. efm_eth_cs(1);
  143. if (spi->read(spi, ETH_SPI_RX_SKIP, buf_ins, len_res) == 0)
  144. {
  145. break;
  146. }
  147. *data = buf_res[len_res - 1];
  148. // eth_debug("ETH: read RX %x %x (%d)\n", buf_res[0], buf_res[1], len_res);
  149. // eth_debug("ETH: ** read RX %x %x (%d)\n",
  150. // buf_res[0], buf_res[1], buf_res[2], buf_res[3], buf_res[4],
  151. // buf_res[5], buf_res[6], buf_res[7], buf_res[8], buf_res[9],
  152. // len_res);
  153. }
  154. else
  155. {
  156. // eth_debug("ETH: ** write TX %x %x %x %x %x %x (%d) \n", buf_ins[0],
  157. // buf_ins[1], buf_ins[2], buf_ins[3], buf_ins[4], buf_ins[5],
  158. // len_ins);
  159. /* Send command and get response */
  160. efm_eth_cs(1);
  161. if (spi->write(spi, EFM32_NO_DATA, buf_ins, len_ins) == 0)
  162. {
  163. break;
  164. }
  165. }
  166. if (!(cmd == ENC28J60_READ_BUF_MEM || cmd == ENC28J60_WRITE_BUF_MEM))
  167. {
  168. efm_eth_cs(0);
  169. }
  170. return RT_EOK;
  171. } while(0);
  172. eth_debug("ETH: Send command failed!\n");
  173. efm_eth_cs(0);
  174. return -RT_ERROR;
  175. }
  176. /***************************************************************************//**
  177. * @brief
  178. * Wrapper function of send command to Ethernet device
  179. *
  180. * @details
  181. *
  182. * @note
  183. *
  184. * @param[in] cmd
  185. * Command index
  186. *
  187. * @param[in] addr
  188. * Register address
  189. *
  190. * @param[in/out] data
  191. * Pointer to the buffer of register value
  192. *
  193. * @return
  194. * Error code
  195. ******************************************************************************/
  196. static rt_err_t efm_eth_sendCmd(
  197. rt_uint8_t cmd,
  198. rt_uint8_t addr,
  199. rt_uint8_t *data)
  200. {
  201. rt_err_t ret;
  202. eth_debug("ETH: Send command %x (%x %x)\n", cmd, addr, *data);
  203. do
  204. {
  205. /* Change bank */
  206. if(((addr & BANK_MASK) != ethBank) && ((addr < EIE) || (addr > ECON1)))
  207. {
  208. rt_uint8_t temp;
  209. if ((ret = efm_eth_cmd(ENC28J60_READ_CTRL_REG, ECON1, &temp)) != RT_EOK)
  210. {
  211. break;
  212. }
  213. temp &= 0xFC;
  214. ethBank = (addr & BANK_MASK);
  215. temp |= ethBank >> BANK_SHIFT;
  216. if ((ret = efm_eth_cmd(ENC28J60_WRITE_CTRL_REG, ECON1, &temp)) != RT_EOK)
  217. {
  218. break;
  219. }
  220. }
  221. /* Send command */
  222. ret = efm_eth_cmd(cmd, addr, data);
  223. } while(0);
  224. return ret;
  225. }
  226. /***************************************************************************//**
  227. * @brief
  228. * Read register of Ethernet device
  229. *
  230. * @details
  231. *
  232. * @note
  233. *
  234. * @param[in] addr
  235. * Register address
  236. *
  237. * @return
  238. * Register value
  239. ******************************************************************************/
  240. static rt_uint8_t efm_eth_readReg(rt_uint8_t addr)
  241. {
  242. rt_uint8_t data;
  243. efm_eth_sendCmd(ENC28J60_READ_CTRL_REG, addr, &data);
  244. return data;
  245. }
  246. /***************************************************************************//**
  247. * @brief
  248. * Write register of Ethernet device
  249. *
  250. * @details
  251. *
  252. * @note
  253. *
  254. * @param[in] addr
  255. * Register address
  256. *
  257. * @param[in] data
  258. * Register value
  259. ******************************************************************************/
  260. static void efm_eth_writeReg(rt_uint8_t addr, rt_uint8_t data)
  261. {
  262. efm_eth_sendCmd(ENC28J60_WRITE_CTRL_REG, addr, &data);
  263. }
  264. /***************************************************************************//**
  265. * @brief
  266. * Read PHY register of Ethernet device
  267. *
  268. * @details
  269. *
  270. * @note
  271. *
  272. * @param[in] addr
  273. * Register address
  274. *
  275. * @return
  276. * Register value
  277. ******************************************************************************/
  278. static rt_uint16_t efm_eth_readPhy(rt_uint8_t addr)
  279. {
  280. rt_uint16_t ret;
  281. eth_debug("ETH: *** read PHY %x\n", addr);
  282. /* Set PHY register address */
  283. efm_eth_writeReg(MIREGADR, addr);
  284. /* Start read operation */
  285. efm_eth_writeReg(MICMD, MICMD_MIIRD);
  286. /* Waiting for at least 10.24 uS */
  287. while(efm_eth_readReg(MISTAT) & MISTAT_BUSY);
  288. /* Stop read operation */
  289. efm_eth_writeReg(MICMD, 0x00);
  290. /* Get the result */
  291. ret = (rt_uint16_t)efm_eth_readReg(MIRDL);
  292. ret |= (rt_uint16_t)efm_eth_readReg(MIRDH) << 8;
  293. return ret;
  294. }
  295. /***************************************************************************//**
  296. * @brief
  297. * Write PHY register of Ethernet device
  298. *
  299. * @details
  300. *
  301. * @note
  302. *
  303. * @param[in] addr
  304. * Register address
  305. *
  306. * @param[in] data
  307. * Register value
  308. ******************************************************************************/
  309. static void efm_eth_writePhy(rt_uint8_t addr, rt_uint16_t data)
  310. {
  311. eth_debug("ETH: *** write PHY %x (%x)\n", addr, data);
  312. /* Set PHY register address */
  313. efm_eth_writeReg(MIREGADR, addr);
  314. /* Set data */
  315. efm_eth_writeReg(MIWRL, data);
  316. efm_eth_writeReg(MIWRH, data >> 8);
  317. /* Waiting for at least 10.24 uS */
  318. while(efm_eth_readReg(MISTAT) & MISTAT_BUSY);
  319. }
  320. /***************************************************************************//**
  321. * @brief
  322. * Interrupt handler of Ethernet device
  323. *
  324. * @details
  325. *
  326. * @note
  327. *
  328. * @param[in] dev
  329. * Pointer to device descriptor
  330. ******************************************************************************/
  331. void efm_eth_isr(rt_device_t dev)
  332. {
  333. rt_uint8_t reg_eir, data;
  334. volatile rt_uint8_t cnt;
  335. /* Disable RX interrutp */
  336. data = EIE_PKTIE;
  337. efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data);
  338. /* Get interrupt flag */
  339. efm_eth_sendCmd(ENC28J60_READ_CTRL_REG, EIR, &reg_eir);
  340. data = 0;
  341. /* DMA completed */
  342. if (reg_eir & EIR_DMAIF)
  343. {
  344. data |= (rt_uint8_t)EIR_DMAIF;
  345. }
  346. /* Link Changed */
  347. if (reg_eir & EIR_LINKIF)
  348. {
  349. /* Read PHIR to clear the flag */
  350. efm_eth_readPhy(PHIR);
  351. }
  352. /* TX done */
  353. if (reg_eir & EIR_TXIF)
  354. {
  355. data |= (rt_uint8_t)EIR_TXIF;
  356. }
  357. /* TX error */
  358. if (reg_eir & EIR_TXERIF)
  359. {
  360. data |= (rt_uint8_t)EIR_TXERIF;
  361. }
  362. /* RX error */
  363. if (reg_eir & EIR_RXERIF)
  364. {
  365. data |= (rt_uint8_t)EIR_RXERIF;
  366. }
  367. /* Clear flags */
  368. efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIR, &data);
  369. /* Get packet counter (Errata 6) */
  370. efm_eth_sendCmd(ENC28J60_READ_CTRL_REG, EPKTCNT, (rt_uint8_t *)&cnt);
  371. if (cnt)
  372. {
  373. /* Inform Ethernet thread */
  374. eth_device_ready(&eth_dev);
  375. }
  376. }
  377. /***************************************************************************//**
  378. * @brief
  379. * Initialize Ethernet device
  380. *
  381. * @details
  382. *
  383. * @note
  384. *
  385. * @param[in] dev
  386. * Pointer to device descriptor
  387. *
  388. * @return
  389. * Error code
  390. ******************************************************************************/
  391. static rt_err_t efm_eth_init(rt_device_t dev)
  392. {
  393. rt_uint16_t reg_phy;
  394. rt_uint8_t data;
  395. /* Reset chip select */
  396. efm_eth_cs(0);
  397. /* Software reset */
  398. efm_eth_sendCmd(ENC28J60_SOFT_RESET, EFM32_NO_DATA, EFM32_NO_POINTER);
  399. /* Waiting for at least 1 ms (Errata 2) */
  400. rt_thread_delay(ETH_PERIOD_WAIT_INIT);
  401. ethNxtPkt = RXSTART_INIT;
  402. ethBank = 0;
  403. /* Init RX buffer */
  404. efm_eth_writeReg(ERXSTL, RXSTART_INIT & 0xFF);
  405. efm_eth_writeReg(ERXSTH, RXSTART_INIT >> 8);
  406. efm_eth_writeReg(ERXNDL, RXSTOP_INIT & 0xFF);
  407. efm_eth_writeReg(ERXNDH, RXSTOP_INIT >> 8);
  408. efm_eth_writeReg(ERXRDPTL, RXSTOP_INIT & 0xFF);
  409. efm_eth_writeReg(ERXRDPTH, RXSTOP_INIT >> 8);
  410. /* Init TX buffer */
  411. efm_eth_writeReg(ETXSTL, TXSTART_INIT & 0xFF);
  412. efm_eth_writeReg(ETXSTH, TXSTART_INIT >> 8);
  413. efm_eth_writeReg(ETXNDL, TXSTOP_INIT & 0xFF);
  414. efm_eth_writeReg(ETXNDH, TXSTOP_INIT >> 8);
  415. efm_eth_writeReg(EWRPTL, TXSTART_INIT & 0xFF);
  416. efm_eth_writeReg(EWRPTH, TXSTART_INIT >> 8);
  417. /* Init RX filters */
  418. /* For broadcast packets we allow only ARP packtets
  419. All other packets should be unicast only for our mac (MAADR)
  420. The pattern to match on is therefore
  421. Type ETH.DST
  422. ARP BROADCAST
  423. 06 08 -- -- -- -- -- -- ff ff ff ff ff ff
  424. These poitions are: 11 0000 0011 1111 in binary and 30 3f in hex
  425. Checksum for theses bytes is: f7 f9 */
  426. efm_eth_writeReg(EPMM0, 0x3f);
  427. efm_eth_writeReg(EPMM1, 0x30);
  428. efm_eth_writeReg(EPMCSL, 0xf9);
  429. efm_eth_writeReg(EPMCSH, 0xf7);
  430. efm_eth_writeReg(ERXFCON,
  431. ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN);
  432. //efm_eth_writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN);
  433. /* Waiting For OST: The OST does not expire until 7500 OSC1 clock cycles (300 uS)
  434. pass after Power-on Reset or wake-up from Power-Down mode occurs */
  435. /* Init MAC */
  436. /* Enable RX, IEEE defined flow control */
  437. efm_eth_writeReg(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);
  438. /* Enable padding to 60 bytes, CRC and frame length status reporting */
  439. #if defined(ETH_HALF_DUPLEX)
  440. efm_eth_writeReg(MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN);
  441. efm_eth_writeReg(MACON4, MACON4_DEFER);
  442. #else
  443. efm_eth_writeReg(MACON3, \
  444. MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX);
  445. #endif
  446. /* Set the maximum packet length */
  447. efm_eth_writeReg(MAMXFLL, MAX_FRAMELEN & 0xFF);
  448. efm_eth_writeReg(MAMXFLH, MAX_FRAMELEN >> 8);
  449. /* Set inter-packet gap (back-to-back). Full-Duplex: 0x15, Half-Duplex: 0x12 */
  450. #if defined(ETH_HALF_DUPLEX)
  451. efm_eth_writeReg(MABBIPG, 0x12);
  452. #else
  453. efm_eth_writeReg(MABBIPG, 0x15);
  454. #endif
  455. /* Set inter-packet gap (non-back-to-back).
  456. Full-Duplex: 0x0012, Half-Duplex: 0x0C12 */
  457. efm_eth_writeReg(MAIPGL, 0x12);
  458. #if defined(ETH_HALF_DUPLEX)
  459. efm_eth_writeReg(MAIPGH, 0x0C);
  460. /* Set retransmission and collision window */
  461. efm_eth_writeReg(MACLCON1, 0x0F);
  462. efm_eth_writeReg(MACLCON2, 0x37);
  463. #endif
  464. /* Set MAC address
  465. NOTE: MAC address in ENC28J60 is byte-backward */
  466. efm_eth_writeReg(MAADR1, eth_addr[0]);
  467. efm_eth_writeReg(MAADR2, eth_addr[1]);
  468. efm_eth_writeReg(MAADR3, eth_addr[2]);
  469. efm_eth_writeReg(MAADR4, eth_addr[3]);
  470. efm_eth_writeReg(MAADR5, eth_addr[4]);
  471. efm_eth_writeReg(MAADR6, eth_addr[5]);
  472. /* Init PHY */
  473. #if defined(ETH_HALF_DUPLEX)
  474. reg_phy = efm_eth_readPhy(PHCON2);
  475. efm_eth_writePhy(PHCON2, reg_phy | PHCON2_HDLDIS);
  476. #else
  477. reg_phy = efm_eth_readPhy(PHCON1);
  478. efm_eth_writePhy(PHCON1, reg_phy | PHCON1_PDPXMD);
  479. #endif
  480. /* LEDA: Display link status;
  481. LEDB: Display transmit and receive activity */
  482. reg_phy = efm_eth_readPhy(PHLCON);
  483. efm_eth_writePhy(PHLCON, (reg_phy & 0xF00F) | 0x0470);
  484. /* Disable clock output */
  485. efm_eth_writeReg(ECOCON, 0x00);
  486. /* Clear interrutp flags */
  487. data = EIR_DMAIF | EIR_TXIF | EIR_TXERIF | EIR_RXERIF;
  488. efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIR, &data);
  489. /* Enable interrutps */
  490. data = EIE_INTIE | EIE_PKTIE | EIE_TXIE;
  491. efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &data);
  492. /* Enable RX */
  493. data = ECON1_RXEN;
  494. efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data);
  495. eth_debug("ETH: Init OK\n");
  496. return RT_EOK;
  497. }
  498. /***************************************************************************//**
  499. * @brief
  500. * Open Ethernet device
  501. *
  502. * @details
  503. *
  504. * @note
  505. *
  506. * @param[in] dev
  507. * Pointer to device descriptor
  508. *
  509. * @param[in] oflag
  510. * Device open flag
  511. *
  512. * @return
  513. * Error code
  514. ******************************************************************************/
  515. static rt_err_t efm_eth_open(rt_device_t dev, rt_uint16_t oflag)
  516. {
  517. eth_debug("ETH: Open, flag %x\n", eth_dev.parent.flag);
  518. return RT_EOK;
  519. }
  520. /***************************************************************************//**
  521. * @brief
  522. * Close Ethernet device
  523. *
  524. * @details
  525. *
  526. * @note
  527. *
  528. * @param[in] dev
  529. * Pointer to device descriptor
  530. *
  531. * @return
  532. * Error code
  533. ******************************************************************************/
  534. static rt_err_t efm_eth_close(rt_device_t dev)
  535. {
  536. eth_debug("ETH: Close, flag %x\n", eth_dev.parent.flag);
  537. return RT_EOK;
  538. }
  539. /***************************************************************************//**
  540. * @brief
  541. * Read from Ethernet device (Dummy function)
  542. *
  543. * @details
  544. *
  545. * @note
  546. *
  547. * @param[in] dev
  548. * Pointer to device descriptor
  549. *
  550. * @param[in] pos
  551. * Offset
  552. *
  553. * @param[in] buffer
  554. * Poniter to the buffer
  555. *
  556. * @param[in] size
  557. * Buffer size in byte
  558. *
  559. * @return
  560. * Number of read bytes
  561. ******************************************************************************/
  562. static rt_size_t efm_eth_read(
  563. rt_device_t dev,
  564. rt_off_t pos,
  565. void *buffer,
  566. rt_size_t size)
  567. {
  568. rt_set_errno(-RT_ENOSYS);
  569. return 0;
  570. }
  571. /***************************************************************************//**
  572. * @brief
  573. * Write to Ethernet device (Dummy function)
  574. *
  575. * @details
  576. *
  577. * @note
  578. *
  579. * @param[in] dev
  580. * Pointer to device descriptor
  581. *
  582. * @param[in] pos
  583. * Offset
  584. *
  585. * @param[in] buffer
  586. * Poniter to the buffer
  587. *
  588. * @param[in] size
  589. * Buffer size in byte
  590. *
  591. * @return
  592. * Number of written bytes
  593. ******************************************************************************/
  594. static rt_size_t efm_eth_write (
  595. rt_device_t dev,
  596. rt_off_t pos,
  597. const void *buffer,
  598. rt_size_t size)
  599. {
  600. rt_set_errno(-RT_ENOSYS);
  601. return 0;
  602. }
  603. /***************************************************************************//**
  604. * @brief
  605. * Configure Ethernet device
  606. *
  607. * @details
  608. *
  609. * @note
  610. *
  611. * @param[in] dev
  612. * Pointer to device descriptor
  613. *
  614. * @param[in] cmd
  615. * Ethernet control command
  616. *
  617. * @param[in] args
  618. * Arguments
  619. *
  620. * @return
  621. * Error code
  622. ******************************************************************************/
  623. static rt_err_t efm_eth_control (
  624. rt_device_t dev,
  625. rt_uint8_t cmd,
  626. void *args)
  627. {
  628. rt_err_t ret;
  629. ret = -RT_ERROR;
  630. switch(cmd)
  631. {
  632. case NIOCTL_GADDR:
  633. /* Get MAC address */
  634. if(args)
  635. {
  636. rt_memcpy(args, eth_addr, sizeof(eth_addr));
  637. ret = RT_EOK;
  638. }
  639. break;
  640. default :
  641. break;
  642. }
  643. return RT_EOK;
  644. }
  645. /***************************************************************************//**
  646. * @brief
  647. * Packet receiving function
  648. *
  649. * @details
  650. *
  651. * @note
  652. *
  653. * @param[in] dev
  654. * Pointer to device descriptor
  655. *
  656. * @return
  657. * Pointer to packet buffer
  658. ******************************************************************************/
  659. struct pbuf *efm_eth_rx(rt_device_t dev)
  660. {
  661. rt_uint8_t buf_ins[5], buf_read[6];
  662. rt_uint8_t data, reg_eie;
  663. rt_uint16_t len_rx, sta_rx;
  664. struct pbuf* p;
  665. p = RT_NULL;
  666. /* Lock device */
  667. rt_sem_take(&ethLock, RT_WAITING_FOREVER);
  668. /* Disable interrupts */
  669. data = EIE_INTIE;
  670. efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data);
  671. reg_eie = 0;
  672. if (efm_eth_readReg(EPKTCNT))
  673. {
  674. /* Set read pointer to the start of RX packet */
  675. efm_eth_writeReg(ERDPTL, ethNxtPkt & 0xFF);
  676. efm_eth_writeReg(ERDPTH, ethNxtPkt >> 8);
  677. /* Send read buffer command */
  678. efm_eth_sendCmd(ENC28J60_READ_BUF_MEM, EFM32_NO_DATA, EFM32_NO_POINTER);
  679. /* Build instruction buffer */
  680. buf_ins[0] = 0x00;
  681. *(rt_uint8_t **)(&buf_ins[1]) = buf_read;
  682. /* Read packet header */
  683. if (spi->read(spi, EFM32_NO_DATA, buf_ins, sizeof(buf_read)) == 0)
  684. {
  685. eth_debug("ETH: RX header failed!\n");
  686. }
  687. ethNxtPkt = buf_read[0] | (buf_read[1] << 8);
  688. len_rx = buf_read[2] | (buf_read[3] << 8);
  689. sta_rx = buf_read[4] | (buf_read[5] << 8);
  690. eth_debug("ETH: RX header ethNxtPkt %x, len_rx %x, sta_rx %x\n",
  691. ethNxtPkt, len_rx, sta_rx);
  692. /* Check if OK */
  693. if (sta_rx & 0x80)
  694. {
  695. /* Allocate pbuf */
  696. p = pbuf_alloc(PBUF_LINK, len_rx - 4, PBUF_RAM);
  697. if (p != RT_NULL)
  698. {
  699. struct pbuf* q;
  700. for (q = p; q != RT_NULL; q= q->next)
  701. {
  702. /* Build instruction buffer */
  703. buf_ins[0] = 0x00;
  704. *(rt_uint8_t **)(&buf_ins[1]) = q->payload;
  705. /* Read packet header */
  706. if (spi->read(spi, EFM32_NO_DATA, buf_ins, q->len) == 0)
  707. {
  708. eth_debug("ETH: RX payload failed!\n");
  709. }
  710. #ifdef EFM32_ETHERNET_DEBUG
  711. {
  712. rt_uint8_t *temp = (rt_uint8_t *)q->payload;
  713. rt_uint32_t i;
  714. eth_debug("ETH: ***** read RX (q->len %x) *****\n", q->len);
  715. for (i = 0; i < q->len; i += 8)
  716. {
  717. eth_debug("%02x %02x %02x %02x %02x %02x %02x %02x (%d %d)\n",
  718. temp[i], temp[i + 1], temp[i + 2], temp[i + 3],
  719. temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7],
  720. i, q->len);
  721. }
  722. }
  723. #endif
  724. }
  725. }
  726. else
  727. {
  728. eth_debug("ETH: No memory for pbuf!!!\n");
  729. }
  730. }
  731. else
  732. {
  733. eth_debug("ETH: Invalid CRC or symbol error occurred!\n");
  734. }
  735. efm_eth_cs(0);
  736. /* Free buffer */
  737. efm_eth_writeReg(ERXRDPTL, ethNxtPkt & 0xFF);
  738. efm_eth_writeReg(ERXRDPTH, ethNxtPkt >> 8);
  739. /* Decrease counter */
  740. data = ECON2_PKTDEC;
  741. efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON2, &data);
  742. }
  743. else
  744. {
  745. /* Enable RX */
  746. data = ECON1_RXEN;
  747. efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data);
  748. reg_eie |= EIE_PKTIE;
  749. eth_debug("ETH: Enable RX interrupt\n");
  750. }
  751. eth_debug("ETH: RX counter %x\n", efm_eth_readReg(EPKTCNT));
  752. /* Enable interrupts */
  753. reg_eie |= EIE_INTIE;
  754. efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &reg_eie);
  755. /* Unlock device */
  756. rt_sem_release(&ethLock);
  757. return p;
  758. }
  759. /***************************************************************************//**
  760. * @brief
  761. * Packet transmission function
  762. *
  763. * @details
  764. *
  765. * @note
  766. *
  767. * @param[in] dev
  768. * Pointer to device descriptor
  769. *
  770. * @param[in] p
  771. * Pointer to packet buffer
  772. *
  773. * @return
  774. * Error code
  775. ******************************************************************************/
  776. rt_err_t efm_eth_tx(rt_device_t dev, struct pbuf* p)
  777. {
  778. rt_uint8_t data;
  779. struct pbuf* q;
  780. /* Lock device */
  781. rt_sem_take(&ethLock, RT_WAITING_FOREVER);
  782. /* Disable interrupts */
  783. data = EIE_INTIE;
  784. efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data);
  785. /* Set write pointer to the start of TX buffer */
  786. efm_eth_writeReg(EWRPTL, TXSTART_INIT & 0xFF);
  787. efm_eth_writeReg(EWRPTH, TXSTART_INIT >> 8);
  788. /* Set buffer end pointer according to the packet size */
  789. efm_eth_writeReg(ETXNDL, (TXSTART_INIT + p->tot_len + 1) & 0xFF);
  790. efm_eth_writeReg(ETXNDH, (TXSTART_INIT + p->tot_len + 1) >> 8);
  791. /* Send write buffer command */
  792. data = 0x00; /* Control byte */
  793. efm_eth_sendCmd(ENC28J60_WRITE_BUF_MEM, EFM32_NO_DATA, &data);
  794. /* Send data */
  795. for (q = p; q != NULL; q = q->next)
  796. {
  797. if (spi->write(spi, EFM32_NO_DATA, q->payload, q->len) == 0)
  798. {
  799. eth_debug("ETH: TX failed!\n");
  800. return -RT_ERROR;
  801. }
  802. #ifdef EFM32_ETHERNET_DEBUG
  803. {
  804. rt_uint8_t *temp = (rt_uint8_t *)q->payload;
  805. rt_uint32_t i;
  806. eth_debug("ETH: ***** write TX (len %d) *****\n", p->len);
  807. for (i = 0; i < q->len; i += 8)
  808. {
  809. eth_debug("%02x %02x %02x %02x %02x %02x %02x %02x (%d %d)\n",
  810. temp[i], temp[i + 1], temp[i + 2], temp[i + 3],
  811. temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7],
  812. i, q->len);
  813. }
  814. }
  815. #endif
  816. }
  817. efm_eth_cs(0);
  818. /* Start TX */
  819. data = ECON1_TXRTS;
  820. efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data);
  821. /* Errata 12 */
  822. if (efm_eth_readReg(EIR) & EIR_TXERIF)
  823. {
  824. efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, ECON1, &data);
  825. data = EIR_TXERIF;
  826. efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIR, &data);
  827. data = ECON1_TXRTS;
  828. efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data);
  829. }
  830. /* Enable interrupts */
  831. data = EIE_INTIE;
  832. efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &data);
  833. /* Unlock device */
  834. rt_sem_release(&ethLock);
  835. return RT_EOK;
  836. }
  837. /***************************************************************************//**
  838. * @brief
  839. * Initialize all Ethernet related hardware and register the device to kernel
  840. *
  841. * @details
  842. *
  843. * @note
  844. *
  845. * @return
  846. * Error code
  847. ******************************************************************************/
  848. rt_err_t efm_hw_eth_init(void)
  849. {
  850. struct efm32_usart_device_t *usart;
  851. efm32_irq_hook_init_t hook;
  852. do
  853. {
  854. /* Find SPI device */
  855. spi = rt_device_find(ETH_USING_DEVICE_NAME);
  856. if (spi == RT_NULL)
  857. {
  858. eth_debug("ETH: Can't find device %s!\n",
  859. ETH_USING_DEVICE_NAME);
  860. break;
  861. }
  862. eth_debug("ETH: Find device %s\n", ETH_USING_DEVICE_NAME);
  863. /* Config chip slect pin */
  864. usart = (struct efm32_usart_device_t *)(spi->user_data);
  865. if (!(usart->state & USART_STATE_AUTOCS))
  866. {
  867. GPIO_PinModeSet(ETH_CS_PORT, ETH_CS_PIN, gpioModePushPull, 1);
  868. ethAutoCs = false;
  869. }
  870. /* Config reset pin */
  871. GPIO_PinModeSet(ETH_RESET_PORT, ETH_RESET_PIN, gpioModePushPull, 0);
  872. /* Config interrupt pin */
  873. GPIO_PinModeSet(ETH_INT_PORT, ETH_INT_PIN, gpioModeInput, 1);
  874. /* Config interrupt */
  875. hook.type = efm32_irq_type_gpio;
  876. hook.unit = ETH_INT_PIN;
  877. hook.cbFunc = efm_eth_isr;
  878. hook.userPtr = RT_NULL;
  879. efm32_irq_hook_register(&hook);
  880. /* Clear pending interrupt */
  881. BITBAND_Peripheral(&(GPIO->IFC), ETH_INT_PIN, 0x1UL);
  882. /* Set falling edge interrupt and clear/enable it */
  883. GPIO_IntConfig(
  884. ETH_INT_PORT,
  885. ETH_INT_PIN,
  886. false,
  887. true,
  888. true);
  889. if ((rt_uint8_t)ETH_INT_PIN % 2)
  890. {
  891. NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
  892. NVIC_SetPriority(GPIO_ODD_IRQn, EFM32_IRQ_PRI_DEFAULT);
  893. NVIC_EnableIRQ(GPIO_ODD_IRQn);
  894. }
  895. else
  896. {
  897. NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
  898. NVIC_SetPriority(GPIO_EVEN_IRQn, EFM32_IRQ_PRI_DEFAULT);
  899. NVIC_EnableIRQ(GPIO_EVEN_IRQn);
  900. }
  901. /* Set SPI speed */
  902. USART_BaudrateSyncSet(usart->usart_device, 0, ETH_CLK_MAX);
  903. /* Initialize semaphore */
  904. rt_sem_init(&ethLock, "lck_eth", 1, RT_IPC_FLAG_FIFO);
  905. /* Register Ethernet device */
  906. eth_dev.parent.init = efm_eth_init;
  907. eth_dev.parent.open = efm_eth_open;
  908. eth_dev.parent.close = efm_eth_close;
  909. eth_dev.parent.read = efm_eth_read;
  910. eth_dev.parent.write = efm_eth_write;
  911. eth_dev.parent.control = efm_eth_control;
  912. eth_dev.eth_rx = efm_eth_rx;
  913. eth_dev.eth_tx = efm_eth_tx;
  914. eth_device_init(&eth_dev, ETH_DEVICE_NAME);
  915. /* Start device */
  916. GPIO_PinOutSet(ETH_RESET_PORT, ETH_RESET_PIN);
  917. eth_debug("ETH: HW init OK\n");
  918. return RT_EOK;
  919. } while (0);
  920. /* Release buffer */
  921. rt_kprintf("ETH: HW init failed!\n");
  922. return -RT_ERROR;
  923. }
  924. /***************************************************************************//**
  925. * Export to FINSH
  926. ******************************************************************************/
  927. #ifdef RT_USING_FINSH
  928. #include <finsh.h>
  929. void list_eth(void)
  930. {
  931. rt_uint16_t reg_phy;
  932. rt_uint8_t data;
  933. rt_kprintf(" ENC28J60 on %s\n", ETH_USING_DEVICE_NAME);
  934. rt_kprintf(" ------------------------------\n");
  935. rt_kprintf(" MAC address is %02x %02x %02x %02x %02x %02x\n",
  936. eth_addr[0], eth_addr[1], eth_addr[2], eth_addr[3], eth_addr[4],
  937. eth_addr[5], eth_addr[6]);
  938. reg_phy = efm_eth_readPhy(PHSTAT2);
  939. if (reg_phy & PHSTAT2_PLRITY)
  940. {
  941. rt_kprintf(" Cable polarity is reversed\n");
  942. }
  943. else
  944. {
  945. rt_kprintf(" Cable polarity is correct\n");
  946. }
  947. if (reg_phy & PHSTAT2_DPXSTAT)
  948. {
  949. rt_kprintf(" Full-duplex mode\n");
  950. }
  951. else
  952. {
  953. rt_kprintf(" Half-duplex mode\n");
  954. }
  955. if (reg_phy & PHSTAT2_LSTAT)
  956. {
  957. rt_kprintf(" Link is up\n");
  958. }
  959. else
  960. {
  961. rt_kprintf(" Link is down\n");
  962. }
  963. if (reg_phy & PHSTAT2_COLSTAT)
  964. {
  965. rt_kprintf(" Collision is occuring\n");
  966. }
  967. else
  968. {
  969. rt_kprintf(" No collision\n");
  970. }
  971. if (reg_phy & PHSTAT2_RXSTAT)
  972. {
  973. rt_kprintf(" RX is busy\n");
  974. }
  975. else
  976. {
  977. rt_kprintf(" RX is idle\n");
  978. }
  979. if (reg_phy & PHSTAT2_TXSTAT)
  980. {
  981. rt_kprintf(" TX is busy\n");
  982. }
  983. else
  984. {
  985. rt_kprintf(" TX is idle\n");
  986. }
  987. }
  988. FINSH_FUNCTION_EXPORT(list_eth, list the Ethernet device status.)
  989. #endif
  990. #endif /* defined(EFM32_USING_ETHERNET) */
  991. /******************************************************************//**
  992. * @}
  993. ******************************************************************************/