drv_ethernet.c 35 KB

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