drv_eth.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-11-19 SummerGift first version
  9. * 2018-12-25 zylx fix some bugs
  10. * 2019-06-10 SummerGift optimize PHY state detection process
  11. * 2019-09-03 xiaofan optimize link change detection process
  12. * 2024-08-30 wangyuqiang add the netdev driver for EtherCAT EOE
  13. */
  14. #include "drv_config.h"
  15. #include "drv_eth.h"
  16. #include <hal_data.h>
  17. #include <netif/ethernetif.h>
  18. #include <lwipopts.h>
  19. #if defined(BSP_USING_ETHERCAT_EOE)
  20. #include "eoe_vether_feature.h"
  21. #define ETHER_NETIF_PORT_BIT(x) ((uint32_t)(1) << (x))
  22. #define ETHER_NETIF_PORT_ALL ((uint32_t)(0xFFFFFFFF))
  23. #define UM_ETHER_NETIF_FEATURE_NUMBER_OF_ETHER_PORTS (3)
  24. #define ETHER_NETIF_PORT_MASK ((uint32_t) ~((uint32_t)(0xFFFFFFFF) << (UM_ETHER_NETIF_FEATURE_NUMBER_OF_ETHER_PORTS)))
  25. #define R_GMAC_Open EOE_VETHER_Open
  26. #define R_GMAC_Write EOE_VETHER_Write
  27. #define R_GMAC_Read EOE_VETHER_Read
  28. #endif
  29. /* debug option */
  30. // #define ETH_RX_DUMP
  31. // #define ETH_TX_DUMP
  32. #define MINIMUM_ETHERNET_FRAME_SIZE (60U)
  33. #define ETH_MAX_PACKET_SIZE (2048U)
  34. #define ETHER_GMAC_INTERRUPT_FACTOR_RECEPTION (0x000000C0)
  35. #define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE
  36. #define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE
  37. // #define DRV_DEBUG
  38. #define LOG_TAG "drv.eth"
  39. #ifdef DRV_DEBUG
  40. #define DBG_LVL DBG_LOG
  41. #else
  42. #define DBG_LVL DBG_INFO
  43. #endif /* DRV_DEBUG */
  44. #include <rtdbg.h>
  45. struct rt_eth_dev
  46. {
  47. /* inherit from ethernet device */
  48. struct eth_device parent;
  49. #ifndef PHY_USING_INTERRUPT_MODE
  50. rt_timer_t poll_link_timer;
  51. #endif
  52. };
  53. static rt_uint8_t *Rx_Buff, *Tx_Buff;
  54. // static ETH_HandleTypeDef EthHandle;
  55. static struct rt_eth_dev ra_eth_device;
  56. static uint8_t g_link_change = 0; ///< Link change (bit0:port0, bit1:port1, bit2:port2)
  57. static uint8_t g_link_status = 0; ///< Link status (bit0:port0, bit1:port1, bit2:port2)
  58. static uint8_t previous_link_status = 0;
  59. #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
  60. #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
  61. static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
  62. {
  63. unsigned char *buf = (unsigned char *)ptr;
  64. int i, j;
  65. for (i = 0; i < buflen; i += 16)
  66. {
  67. rt_kprintf("%08X: ", i);
  68. for (j = 0; j < 16; j++)
  69. if (i + j < buflen)
  70. rt_kprintf("%02X ", buf[i + j]);
  71. else
  72. rt_kprintf(" ");
  73. rt_kprintf(" ");
  74. for (j = 0; j < 16; j++)
  75. if (i + j < buflen)
  76. rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
  77. rt_kprintf("\n");
  78. }
  79. }
  80. #endif
  81. static int phy_rtl8211f_led_fixup(ether_phy_instance_ctrl_t *phydev)
  82. {
  83. #define RTL_8211F_PAGE_SELECT 0x1F
  84. #define RTL_8211F_EEELCR_ADDR 0x11
  85. #define RTL_8211F_LED_PAGE 0xD04
  86. #define RTL_8211F_LCR_ADDR 0x10
  87. uint32_t val1, val2 = 0;
  88. /* switch to led page */
  89. R_ETHER_PHY_Write(phydev, RTL_8211F_PAGE_SELECT, RTL_8211F_LED_PAGE);
  90. /* set led1(green) Link 10/100/1000M, and set led2(yellow) Link 10/100/1000M+Active */
  91. R_ETHER_PHY_Read(phydev, RTL_8211F_LCR_ADDR, &val1);
  92. val1 |= (1 << 5);
  93. val1 |= (1 << 8);
  94. val1 &= (~(1 << 9));
  95. val1 |= (1 << 10);
  96. val1 |= (1 << 11);
  97. R_ETHER_PHY_Write(phydev, RTL_8211F_LCR_ADDR, val1);
  98. /* set led1(green) EEE LED function disabled so it can keep on when linked */
  99. R_ETHER_PHY_Read(phydev, RTL_8211F_EEELCR_ADDR, &val2);
  100. val2 &= (~(1 << 2));
  101. R_ETHER_PHY_Write(phydev, RTL_8211F_EEELCR_ADDR, val2);
  102. /* switch back to page0 */
  103. R_ETHER_PHY_Write(phydev, RTL_8211F_PAGE_SELECT, 0xa42);
  104. return 0;
  105. }
  106. void ether_phy_targets_initialize_rtl8211_rgmii(ether_phy_instance_ctrl_t *p_instance_ctrl)
  107. {
  108. rt_thread_mdelay(100);
  109. phy_rtl8211f_led_fixup(p_instance_ctrl);
  110. }
  111. extern void phy_reset(void);
  112. /* EMAC initialization function */
  113. static rt_err_t rt_ra_eth_init(void)
  114. {
  115. fsp_err_t res;
  116. res = R_GMAC_Open(&g_ether0_ctrl, &g_ether0_cfg);
  117. if (res != FSP_SUCCESS)
  118. LOG_W("R_ETHER_Open failed!, res = %d", res);
  119. return RT_EOK;
  120. }
  121. static rt_err_t rt_ra_eth_open(rt_device_t dev, rt_uint16_t oflag)
  122. {
  123. LOG_D("emac open");
  124. return RT_EOK;
  125. }
  126. static rt_err_t rt_ra_eth_close(rt_device_t dev)
  127. {
  128. LOG_D("emac close");
  129. return RT_EOK;
  130. }
  131. static rt_ssize_t rt_ra_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  132. {
  133. LOG_D("emac read");
  134. rt_set_errno(-RT_ENOSYS);
  135. return 0;
  136. }
  137. static rt_ssize_t rt_ra_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  138. {
  139. LOG_D("emac write");
  140. rt_set_errno(-RT_ENOSYS);
  141. return 0;
  142. }
  143. static rt_err_t rt_ra_eth_control(rt_device_t dev, int cmd, void *args)
  144. {
  145. switch (cmd)
  146. {
  147. case NIOCTL_GADDR:
  148. /* get mac address */
  149. if (args)
  150. {
  151. SMEMCPY(args, g_ether0_ctrl.p_gmac_cfg->p_mac_address, 6);
  152. }
  153. else
  154. {
  155. return -RT_ERROR;
  156. }
  157. break;
  158. default:
  159. break;
  160. }
  161. return RT_EOK;
  162. }
  163. /* ethernet device interface */
  164. /* transmit data*/
  165. rt_err_t rt_ra_eth_tx(rt_device_t dev, struct pbuf *p)
  166. {
  167. fsp_err_t res;
  168. struct pbuf *q;
  169. uint8_t *buffer = Tx_Buff;
  170. uint32_t framelength = 0;
  171. uint32_t bufferoffset = 0;
  172. uint32_t byteslefttocopy = 0;
  173. uint32_t payloadoffset = 0;
  174. bufferoffset = 0;
  175. LOG_D("send frame len : %d", p->tot_len);
  176. /* copy frame from pbufs to driver buffers */
  177. for (q = p; q != NULL; q = q->next)
  178. {
  179. /* Get bytes in current lwIP buffer */
  180. byteslefttocopy = q->len;
  181. payloadoffset = 0;
  182. /* Check if the length of data to copy is bigger than Tx buffer size*/
  183. while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE)
  184. {
  185. /* Copy data to Tx buffer*/
  186. SMEMCPY((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset));
  187. byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
  188. payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
  189. framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
  190. bufferoffset = 0;
  191. }
  192. /* Copy the remaining bytes */
  193. SMEMCPY((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), byteslefttocopy);
  194. bufferoffset = bufferoffset + byteslefttocopy;
  195. framelength = framelength + byteslefttocopy;
  196. }
  197. #ifdef ETH_TX_DUMP
  198. dump_hex(buffer, p->tot_len);
  199. #endif
  200. #ifdef ETH_RX_DUMP
  201. if (p)
  202. {
  203. LOG_E("******p buf frame *********");
  204. for (q = p; q != NULL; q = q->next)
  205. {
  206. dump_hex(q->payload, q->len);
  207. }
  208. }
  209. #endif
  210. res = R_GMAC_Write(&g_ether0_ctrl, buffer, p->tot_len); //>MINIMUM_ETHERNET_FRAME_SIZE?p->tot_len:MINIMUM_ETHERNET_FRAME_SIZE);
  211. if (res != FSP_SUCCESS)
  212. LOG_W("R_ETHER_Write failed!, res = %d", res);
  213. return RT_EOK;
  214. }
  215. /* receive data*/
  216. struct pbuf *rt_ra_eth_rx(rt_device_t dev)
  217. {
  218. struct pbuf *p = NULL;
  219. struct pbuf *q = NULL;
  220. uint32_t len = 0;
  221. uint8_t *buffer = Rx_Buff;
  222. fsp_err_t res;
  223. res = R_GMAC_Read(&g_ether0_ctrl, buffer, &len);
  224. if (res != FSP_SUCCESS)
  225. LOG_D("R_ETHER_Read failed!, res = %d", res);
  226. uint32_t bufferoffset = 0;
  227. uint32_t payloadoffset = 0;
  228. uint32_t byteslefttocopy = 0;
  229. LOG_D("receive frame len : %d", len);
  230. if (len > 0)
  231. {
  232. /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
  233. p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
  234. }
  235. #ifdef ETH_RX_DUMP
  236. if (p)
  237. {
  238. dump_hex(buffer, p->tot_len);
  239. }
  240. #endif
  241. if (p != NULL)
  242. {
  243. bufferoffset = 0;
  244. for (q = p; q != NULL; q = q->next)
  245. {
  246. byteslefttocopy = q->len;
  247. payloadoffset = 0;
  248. /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
  249. while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE)
  250. {
  251. /* Copy data to pbuf */
  252. SMEMCPY((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
  253. byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
  254. payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
  255. bufferoffset = 0;
  256. }
  257. /* Copy remaining data in pbuf */
  258. SMEMCPY((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), byteslefttocopy);
  259. bufferoffset = bufferoffset + byteslefttocopy;
  260. }
  261. }
  262. #ifdef ETH_RX_DUMP
  263. if (p)
  264. {
  265. LOG_E("******p buf frame *********");
  266. for (q = p; q != NULL; q = q->next)
  267. {
  268. dump_hex(q->payload, q->len);
  269. }
  270. }
  271. #endif
  272. return p;
  273. }
  274. static void phy_linkchange()
  275. {
  276. fsp_err_t res;
  277. gmac_link_status_t port_status;
  278. uint8_t port = 0;
  279. uint8_t port_bit = 0;
  280. #ifndef BSP_USING_ETHERCAT_EOE
  281. res = R_GMAC_LinkProcess(&g_ether0_ctrl);
  282. if (res != FSP_SUCCESS)
  283. LOG_D("R_ETHER_LinkProcess failed!, res = %d", res);
  284. if (0 == g_ether0.p_cfg->p_callback)
  285. {
  286. for (port = 0; port < PING_PORT_COUNT; port++)
  287. {
  288. res = R_GMAC_GetLinkStatus(&g_ether0_ctrl, port, &port_status);
  289. if (FSP_SUCCESS != res)
  290. {
  291. /* An error has occurred */
  292. LOG_E("R_GMAC_GetLinkStatus failed!, res = %d", res);
  293. break;
  294. }
  295. if (GMAC_LINK_STATUS_DOWN != port_status)
  296. {
  297. /* Set link up */
  298. g_link_status |= (uint8_t)(1U << port);
  299. }
  300. }
  301. if (FSP_SUCCESS == res)
  302. {
  303. /* Set changed link status */
  304. g_link_change = previous_link_status ^ g_link_status;
  305. }
  306. }
  307. if (FSP_SUCCESS == res)
  308. {
  309. for (port = 0; port < PING_PORT_COUNT; port++)
  310. {
  311. port_bit = (uint8_t)(1U << port);
  312. if (g_link_change & port_bit)
  313. {
  314. /* Link status changed */
  315. g_link_change &= (uint8_t)(~port_bit); // change bit clear
  316. if (g_link_status & port_bit)
  317. {
  318. /* Changed to Link-up */
  319. eth_device_linkchange(&ra_eth_device.parent, RT_TRUE);
  320. LOG_I("link up");
  321. }
  322. else
  323. {
  324. /* Changed to Link-down */
  325. eth_device_linkchange(&ra_eth_device.parent, RT_FALSE);
  326. LOG_I("link down");
  327. }
  328. }
  329. }
  330. }
  331. #else
  332. res = EOE_VETHER_LinkProcess(&g_ether0_ctrl);
  333. if (res != FSP_SUCCESS)
  334. LOG_D("R_ETHER_LinkProcess failed!, res = %d", res);
  335. g_link_status &= ~ETHER_NETIF_PORT_ALL;
  336. for (port = 0; port < BSP_FEATURE_GMAC_MAX_PORTS; port++)
  337. {
  338. /** Check the link state of single port. */
  339. res = EOE_VETHER_GetLinkStatus(&g_ether0_ctrl, port, &port_status);
  340. /** If link status can be gotten correctly and is ready, the port is linking. */
  341. if (FSP_SUCCESS == res && GMAC_LINK_STATUS_READY == port_status)
  342. {
  343. g_link_status |= ETHER_NETIF_PORT_BIT(port);
  344. }
  345. /** Otherwise, the port is not linking. */
  346. else
  347. {
  348. g_link_status &= ~ETHER_NETIF_PORT_BIT(port);
  349. }
  350. }
  351. if (g_link_status & ETHER_NETIF_PORT_MASK)
  352. {
  353. /* Changed to Link-up */
  354. if (previous_link_status != g_link_status)
  355. {
  356. eth_device_linkchange(&ra_eth_device.parent, RT_TRUE);
  357. LOG_I("link up");
  358. }
  359. }
  360. else
  361. {
  362. /* Changed to Link-down */
  363. eth_device_linkchange(&ra_eth_device.parent, RT_FALSE);
  364. LOG_I("link down");
  365. }
  366. #endif
  367. previous_link_status = g_link_status;
  368. }
  369. void user_ether0_callback(ether_callback_args_t *p_args)
  370. {
  371. rt_interrupt_enter();
  372. switch (p_args->event)
  373. {
  374. case ETHER_EVENT_LINK_ON: ///< Link up detection event/
  375. g_link_status |= (uint8_t)p_args->status_link; ///< status up
  376. g_link_change |= (uint8_t)p_args->status_link; ///< change bit set
  377. break;
  378. case ETHER_EVENT_LINK_OFF: ///< Link down detection event
  379. g_link_status &= (uint8_t)(~p_args->status_link); ///< status down
  380. g_link_change |= (uint8_t)p_args->status_link; ///< change bit set
  381. break;
  382. case ETHER_EVENT_WAKEON_LAN: ///< Magic packet detection event
  383. /* If EDMAC FR (Frame Receive Event) or FDE (Receive Descriptor Empty Event)
  384. * interrupt occurs, send rx mailbox. */
  385. case ETHER_EVENT_SBD_INTERRUPT: ///< BSD Interrupt event
  386. {
  387. rt_err_t result;
  388. result = eth_device_ready(&(ra_eth_device.parent));
  389. if (result != RT_EOK)
  390. rt_kprintf("RX err =%d\n", result);
  391. break;
  392. }
  393. case ETHER_EVENT_PMT_INTERRUPT: ///< PMT Interrupt event
  394. break;
  395. default:
  396. break;
  397. }
  398. rt_interrupt_leave();
  399. }
  400. /* Register the EMAC device */
  401. static int rt_hw_ra_eth_init(void)
  402. {
  403. rt_err_t state = RT_EOK;
  404. /* Prepare receive and send buffers */
  405. Rx_Buff = (rt_uint8_t *)rt_calloc(1, ETH_MAX_PACKET_SIZE);
  406. if (Rx_Buff == RT_NULL)
  407. {
  408. LOG_E("No memory");
  409. state = -RT_ENOMEM;
  410. goto __exit;
  411. }
  412. Tx_Buff = (rt_uint8_t *)rt_calloc(1, ETH_MAX_PACKET_SIZE);
  413. if (Tx_Buff == RT_NULL)
  414. {
  415. LOG_E("No memory");
  416. state = -RT_ENOMEM;
  417. goto __exit;
  418. }
  419. ra_eth_device.parent.parent.init = NULL;
  420. ra_eth_device.parent.parent.open = rt_ra_eth_open;
  421. ra_eth_device.parent.parent.close = rt_ra_eth_close;
  422. ra_eth_device.parent.parent.read = rt_ra_eth_read;
  423. ra_eth_device.parent.parent.write = rt_ra_eth_write;
  424. ra_eth_device.parent.parent.control = rt_ra_eth_control;
  425. ra_eth_device.parent.parent.user_data = RT_NULL;
  426. ra_eth_device.parent.eth_rx = rt_ra_eth_rx;
  427. ra_eth_device.parent.eth_tx = rt_ra_eth_tx;
  428. rt_ra_eth_init();
  429. /* register eth device */
  430. state = eth_device_init(&(ra_eth_device.parent), "e0");
  431. if (RT_EOK == state)
  432. {
  433. LOG_D("emac device init success");
  434. }
  435. else
  436. {
  437. LOG_E("emac device init faild: %d", state);
  438. state = -RT_ERROR;
  439. goto __exit;
  440. }
  441. ra_eth_device.poll_link_timer = rt_timer_create("phylnk", (void (*)(void *))phy_linkchange,
  442. NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC);
  443. if (!ra_eth_device.poll_link_timer || rt_timer_start(ra_eth_device.poll_link_timer) != RT_EOK)
  444. {
  445. LOG_E("Start link change detection timer failed");
  446. }
  447. __exit:
  448. if (state != RT_EOK)
  449. {
  450. if (Rx_Buff)
  451. {
  452. rt_free(Rx_Buff);
  453. }
  454. if (Tx_Buff)
  455. {
  456. rt_free(Tx_Buff);
  457. }
  458. }
  459. return state;
  460. }
  461. INIT_DEVICE_EXPORT(rt_hw_ra_eth_init);