drv_emac.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-12-12 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_EMAC) && defined(RT_USING_LWIP)
  14. #include <rtdevice.h>
  15. #include "NuMicro.h"
  16. #include <netif/ethernetif.h>
  17. #include <netif/etharp.h>
  18. #include <lwip/icmp.h>
  19. #include <lwip/pbuf.h>
  20. #include <lwip/sys.h>
  21. #include "lwipopts.h"
  22. #include "drv_sys.h"
  23. //#include "drv_pdma.h"
  24. /* Private define ---------------------------------------------------------------*/
  25. // RT_DEV_NAME_PREFIX e
  26. #define NU_EMAC_DEBUG
  27. #if defined(NU_EMAC_DEBUG)
  28. //#define NU_EMAC_RX_DUMP
  29. //#define NU_EMAC_TX_DUMP
  30. #define NU_EMAC_TRACE rt_kprintf
  31. #else
  32. #define NU_EMAC_TRACE(...)
  33. #endif
  34. #define NU_EMAC_TID_STACK_SIZE 1024
  35. /* Private typedef --------------------------------------------------------------*/
  36. enum
  37. {
  38. EMAC_START = -1,
  39. #if defined(BSP_USING_EMAC0)
  40. EMAC0_IDX,
  41. #endif
  42. #if defined(BSP_USING_EMAC1)
  43. EMAC1_IDX,
  44. #endif
  45. EMAC_CNT
  46. };
  47. struct nu_emac_lwip_pbuf
  48. {
  49. struct pbuf_custom p; // lwip pbuf
  50. EMAC_FRAME_T *psPktFrameDataBuf; // gmac descriptor
  51. EMAC_MEMMGR_T *psMemMgr;
  52. EMAC_DESCRIPTOR_T *rx_desc;
  53. const struct memp_desc *memp_rx_pool;
  54. };
  55. typedef struct nu_emac_lwip_pbuf *nu_emac_lwip_pbuf_t;
  56. struct nu_emac
  57. {
  58. struct eth_device eth;
  59. char *name;
  60. EMAC_MEMMGR_T memmgr;
  61. IRQn_Type irqn_tx;
  62. IRQn_Type irqn_rx;
  63. E_SYS_IPRST rstidx;
  64. E_SYS_IPCLK clkidx;
  65. rt_thread_t link_monitor;
  66. rt_uint8_t mac_addr[6];
  67. struct rt_semaphore eth_sem;
  68. const struct memp_desc *memp_rx_pool;
  69. };
  70. typedef struct nu_emac *nu_emac_t;
  71. /* Private functions ------------------------------------------------------------*/
  72. #if defined(NU_EMAC_RX_DUMP) || defined(NU_EMAC_TX_DUMP)
  73. static void nu_emac_pkt_dump(const char *msg, const struct pbuf *p);
  74. #endif
  75. #if LWIP_IPV4 && LWIP_IGMP
  76. static err_t nu_igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, enum netif_mac_filter_action action);
  77. #endif
  78. static void nu_emac_halt(nu_emac_t);
  79. static void nu_emac_reinit(nu_emac_t);
  80. static void link_monitor(void *param);
  81. static rt_err_t nu_emac_init(rt_device_t dev);
  82. static rt_err_t nu_emac_open(rt_device_t dev, rt_uint16_t oflag);
  83. static rt_err_t nu_emac_close(rt_device_t dev);
  84. static rt_size_t nu_emac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
  85. static rt_size_t nu_emac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
  86. static rt_err_t nu_emac_control(rt_device_t dev, int cmd, void *args);
  87. static rt_err_t nu_emac_tx(rt_device_t dev, struct pbuf *p);
  88. static struct pbuf *nu_emac_rx(rt_device_t dev);
  89. static void rt_hw_nu_emac_assign_macaddr(nu_emac_t psNuEMAC);
  90. static int rt_hw_nu_emac_init(void);
  91. static void *nu_emac_memcpy(void *dest, void *src, unsigned int count);
  92. static void nu_emac_tx_isr(int vector, void *param);
  93. static void nu_emac_rx_isr(int vector, void *param);
  94. /* Public functions -------------------------------------------------------------*/
  95. /* Private variables ------------------------------------------------------------*/
  96. #if defined(BSP_USING_EMAC0)
  97. LWIP_MEMPOOL_DECLARE(emac0_rx, EMAC_RX_DESC_SIZE, sizeof(struct nu_emac_lwip_pbuf), "EMAC0 RX PBUF pool");
  98. #endif
  99. #if defined(BSP_USING_EMAC1)
  100. LWIP_MEMPOOL_DECLARE(emac1_rx, EMAC_RX_DESC_SIZE, sizeof(struct nu_emac_lwip_pbuf), "EMAC1 RX PBUF pool");
  101. #endif
  102. static struct nu_emac nu_emac_arr[] =
  103. {
  104. #if defined(BSP_USING_EMAC0)
  105. {
  106. .name = "e0",
  107. .memmgr.psEmac = (EMAC_T *)EMC0_BA,
  108. .irqn_tx = IRQ_EMC0_TX,
  109. .irqn_rx = IRQ_EMC0_RX,
  110. .rstidx = EMAC0RST,
  111. .clkidx = EMAC0CKEN,
  112. .memp_rx_pool = &memp_emac0_rx
  113. },
  114. #endif
  115. #if defined(BSP_USING_EMAC1)
  116. {
  117. .name = "e1",
  118. .memmgr.psEmac = (EMAC_T *)EMC1_BA,
  119. .irqn_tx = IRQ_EMC1_TX,
  120. .irqn_rx = IRQ_EMC1_RX,
  121. .rstidx = EMAC1RST,
  122. .clkidx = EMAC1CKEN,
  123. .memp_rx_pool = &memp_emac1_rx
  124. },
  125. #endif
  126. };
  127. #if defined(NU_EMAC_RX_DUMP) || defined(NU_EMAC_TX_DUMP)
  128. static void nu_emac_pkt_dump(const char *msg, const struct pbuf *p)
  129. {
  130. rt_uint32_t i;
  131. rt_uint8_t *ptr = p->payload;
  132. NU_EMAC_TRACE("%s %d byte\n", msg, p->tot_len);
  133. for (i = 0; i < p->tot_len; i++)
  134. {
  135. if ((i % 8) == 0)
  136. {
  137. NU_EMAC_TRACE(" ");
  138. }
  139. if ((i % 16) == 0)
  140. {
  141. NU_EMAC_TRACE("\r\n");
  142. }
  143. NU_EMAC_TRACE("%02x ", *ptr);
  144. ptr++;
  145. }
  146. NU_EMAC_TRACE("\n\n");
  147. }
  148. #endif /* dump */
  149. static void nu_emac_halt(nu_emac_t psNuEmac)
  150. {
  151. EMAC_T *EMAC = psNuEmac->memmgr.psEmac;
  152. EMAC_DISABLE_RX(EMAC);
  153. EMAC_DISABLE_TX(EMAC);
  154. }
  155. static void *nu_emac_memcpy(void *dest, void *src, unsigned int count)
  156. {
  157. return rt_memcpy(dest, src, count);
  158. }
  159. static void nu_emac_reinit(nu_emac_t psNuEmac)
  160. {
  161. rt_uint32_t EMAC_CAMxM[EMAC_CAMENTRY_NB];
  162. rt_uint32_t EMAC_CAMxL[EMAC_CAMENTRY_NB];
  163. rt_uint32_t EMAC_CAMEN;
  164. EMAC_T *EMAC = psNuEmac->memmgr.psEmac;
  165. // Backup MAC address.
  166. EMAC_CAMEN = EMAC->CAMEN;
  167. for (rt_uint8_t index = 0 ; index < EMAC_CAMENTRY_NB; index ++)
  168. {
  169. rt_uint32_t *CAMxM = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0M + (index * 8));
  170. rt_uint32_t *CAMxL = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0L + (index * 8));
  171. EMAC_CAMxM[index] = *CAMxM;
  172. EMAC_CAMxL[index] = *CAMxL;
  173. }
  174. nu_emac_halt(psNuEmac);
  175. EMAC_Close(EMAC);
  176. EMAC_Open(&psNuEmac->memmgr, (uint8_t *)&psNuEmac->mac_addr[0]);
  177. EMAC_ENABLE_TX(EMAC);
  178. EMAC_ENABLE_RX(EMAC);
  179. // Restore MAC address.
  180. for (rt_uint8_t index = 0 ; index < EMAC_CAMENTRY_NB; index ++)
  181. {
  182. rt_uint32_t *CAMxM = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0M + (index * 8));
  183. rt_uint32_t *CAMxL = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0L + (index * 8));
  184. *CAMxM = EMAC_CAMxM[index];
  185. *CAMxL = EMAC_CAMxL[index];
  186. }
  187. EMAC->CAMEN = EMAC_CAMEN;
  188. }
  189. #if LWIP_IPV4 && LWIP_IGMP
  190. static err_t nu_igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, enum netif_mac_filter_action action)
  191. {
  192. nu_emac_t psNuEmac = (nu_emac_t)netif->state;
  193. rt_uint8_t mac[6];
  194. int32_t ret = 0;
  195. const uint8_t *p = (const uint8_t *)ip4_addr;
  196. mac[0] = 0x01;
  197. mac[1] = 0x00;
  198. mac[2] = 0x5E;
  199. mac[3] = *(p + 1) & 0x7F;
  200. mac[4] = *(p + 2);
  201. mac[5] = *(p + 3);
  202. ret = EMAC_FillCamEntry(psNuEmac->memmgr.psEmac, (uint8_t *)&mac[0]);
  203. if (ret >= 0)
  204. {
  205. NU_EMAC_TRACE("%s %s %s ", __FUNCTION__, (action == NETIF_ADD_MAC_FILTER) ? "add" : "del", ip4addr_ntoa(ip4_addr));
  206. NU_EMAC_TRACE("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  207. }
  208. return (ret >= 0) ? RT_EOK : -(RT_ERROR);
  209. }
  210. #endif /* LWIP_IPV4 && LWIP_IGMP */
  211. static void link_monitor(void *param)
  212. {
  213. nu_emac_t psNuEmac = (nu_emac_t)param;
  214. EMAC_T *EMAC = psNuEmac->memmgr.psEmac;
  215. uint32_t LinkStatus_Last = EMAC_LINK_DOWN;
  216. EMAC_PhyInit(EMAC);
  217. while (1)
  218. {
  219. uint32_t LinkStatus_Current = EMAC_CheckLinkStatus(EMAC);
  220. /* linkchange */
  221. if (LinkStatus_Last != LinkStatus_Current)
  222. {
  223. switch (LinkStatus_Current)
  224. {
  225. case EMAC_LINK_DOWN:
  226. NU_EMAC_TRACE("[%s] Link status: Down\n", psNuEmac->name);
  227. break;
  228. case EMAC_LINK_100F:
  229. NU_EMAC_TRACE("[%s] Link status: 100F\n", psNuEmac->name);
  230. break;
  231. case EMAC_LINK_100H:
  232. NU_EMAC_TRACE("[%s] Link status: 100H\n", psNuEmac->name);
  233. break;
  234. case EMAC_LINK_10F:
  235. NU_EMAC_TRACE("[%s] Link status: 10F\n", psNuEmac->name);
  236. break;
  237. case EMAC_LINK_10H:
  238. NU_EMAC_TRACE("[%s] Link status: 10H\n", psNuEmac->name);
  239. break;
  240. } /* switch( LinkStatus_Current ) */
  241. /* Send link status to upper layer. */
  242. if (LinkStatus_Current == EMAC_LINK_DOWN)
  243. {
  244. eth_device_linkchange(&psNuEmac->eth, RT_FALSE);
  245. }
  246. else
  247. {
  248. eth_device_linkchange(&psNuEmac->eth, RT_TRUE);
  249. }
  250. LinkStatus_Last = LinkStatus_Current;
  251. } /* if ( LinkStatus_Last != LinkStatus_Current ) */
  252. rt_thread_delay(RT_TICK_PER_SECOND);
  253. } /* while(1) */
  254. }
  255. static void nu_memmgr_init(EMAC_MEMMGR_T *psMemMgr)
  256. {
  257. psMemMgr->u32TxDescSize = EMAC_TX_DESC_SIZE;
  258. psMemMgr->u32RxDescSize = EMAC_RX_DESC_SIZE;
  259. psMemMgr->psTXDescs = (EMAC_DESCRIPTOR_T *) rt_malloc_align(sizeof(EMAC_DESCRIPTOR_T) * psMemMgr->u32TxDescSize, 32);
  260. RT_ASSERT(psMemMgr->psTXDescs != RT_NULL);
  261. psMemMgr->psRXDescs = (EMAC_DESCRIPTOR_T *) rt_malloc_align(sizeof(EMAC_DESCRIPTOR_T) * psMemMgr->u32RxDescSize, 32);
  262. RT_ASSERT(psMemMgr->psRXDescs != RT_NULL);
  263. psMemMgr->psTXFrames = (EMAC_FRAME_T *) rt_malloc_align(sizeof(EMAC_FRAME_T) * psMemMgr->u32TxDescSize, 32);
  264. RT_ASSERT(psMemMgr->psTXFrames != RT_NULL);
  265. psMemMgr->psRXFrames = (EMAC_FRAME_T *) rt_malloc_align(sizeof(EMAC_FRAME_T) * psMemMgr->u32RxDescSize, 32);
  266. RT_ASSERT(psMemMgr->psRXFrames != RT_NULL);
  267. }
  268. static rt_err_t nu_emac_init(rt_device_t dev)
  269. {
  270. nu_emac_t psNuEmac = (nu_emac_t)dev;
  271. EMAC_T *EMAC = psNuEmac->memmgr.psEmac;
  272. char szTmp[16];
  273. rt_err_t ret = RT_EOK;
  274. nu_memmgr_init(&psNuEmac->memmgr);
  275. snprintf(szTmp, sizeof(szTmp), "%sphy", psNuEmac->name);
  276. ret = rt_sem_init(&psNuEmac->eth_sem, "eth_sem", 0, RT_IPC_FLAG_FIFO);
  277. RT_ASSERT(ret == RT_EOK);
  278. EMAC_Reset(EMAC);
  279. EMAC_Close(EMAC);
  280. EMAC_Open(&psNuEmac->memmgr, (uint8_t *)&psNuEmac->mac_addr[0]);
  281. #if defined(BSP_USING_MMU)
  282. mmu_clean_invalidated_dcache((uint32_t)psNuEmac->memmgr.psTXDescs, sizeof(EMAC_DESCRIPTOR_T)*psNuEmac->memmgr.u32TxDescSize);
  283. mmu_clean_invalidated_dcache((uint32_t)psNuEmac->memmgr.psRXDescs, sizeof(EMAC_DESCRIPTOR_T)*psNuEmac->memmgr.u32RxDescSize);
  284. #endif
  285. EMAC_ENABLE_RX(EMAC);
  286. EMAC_ENABLE_TX(EMAC);
  287. EMAC_TRIGGER_RX(EMAC);
  288. #if defined(LWIP_IPV4) && defined(LWIP_IGMP)
  289. netif_set_igmp_mac_filter(psNuEmac->eth.netif, nu_igmp_mac_filter);
  290. #endif /* LWIP_IPV4 && LWIP_IGMP */
  291. psNuEmac->link_monitor = rt_thread_create((const char *)szTmp,
  292. link_monitor,
  293. (void *)psNuEmac,
  294. NU_EMAC_TID_STACK_SIZE,
  295. RT_THREAD_PRIORITY_MAX - 2,
  296. 10);
  297. RT_ASSERT(psNuEmac->link_monitor != RT_NULL);
  298. ret = rt_thread_startup(psNuEmac->link_monitor);
  299. RT_ASSERT(ret == RT_EOK);
  300. return RT_EOK;
  301. }
  302. static rt_err_t nu_emac_open(rt_device_t dev, rt_uint16_t oflag)
  303. {
  304. return RT_EOK;
  305. }
  306. static rt_err_t nu_emac_close(rt_device_t dev)
  307. {
  308. return RT_EOK;
  309. }
  310. static rt_size_t nu_emac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  311. {
  312. rt_set_errno(-RT_ENOSYS);
  313. return 0;
  314. }
  315. static rt_size_t nu_emac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  316. {
  317. rt_set_errno(-RT_ENOSYS);
  318. return 0;
  319. }
  320. static rt_err_t nu_emac_control(rt_device_t dev, int cmd, void *args)
  321. {
  322. nu_emac_t psNuEMAC = (nu_emac_t)dev;
  323. switch (cmd)
  324. {
  325. case NIOCTL_GADDR:
  326. /* Get MAC address */
  327. if (args)
  328. rt_memcpy(args, &psNuEMAC->mac_addr[0], 6);
  329. else
  330. return -RT_ERROR;
  331. break;
  332. default :
  333. break;
  334. }
  335. return RT_EOK;
  336. }
  337. static rt_err_t nu_emac_tx(rt_device_t dev, struct pbuf *p)
  338. {
  339. nu_emac_t psNuEmac = (nu_emac_t)dev;
  340. EMAC_T *EMAC = psNuEmac->memmgr.psEmac;
  341. struct pbuf *q;
  342. rt_uint32_t offset = 0;
  343. rt_uint8_t *buf;
  344. buf = (rt_uint8_t *)EMAC_ClaimFreeTXBuf(&psNuEmac->memmgr);
  345. /* Get free TX buffer */
  346. if (buf == RT_NULL)
  347. {
  348. rt_err_t result;
  349. result = rt_sem_control(&psNuEmac->eth_sem, RT_IPC_CMD_RESET, 0);
  350. RT_ASSERT(result != RT_EOK);
  351. EMAC_CLEAR_INT_FLAG(EMAC, EMAC_INTSTS_TXCPIF_Msk);
  352. EMAC_ENABLE_INT(EMAC, EMAC_INTEN_TXCPIEN_Msk);
  353. do
  354. {
  355. result = rt_sem_take(&psNuEmac->eth_sem, 10);
  356. buf = (rt_uint8_t *)EMAC_ClaimFreeTXBuf(&psNuEmac->memmgr);
  357. }
  358. while (buf == RT_NULL);
  359. }
  360. for (q = p; q != NULL; q = q->next)
  361. {
  362. rt_uint8_t *ptr;
  363. rt_uint32_t len;
  364. len = q->len;
  365. ptr = q->payload;
  366. nu_emac_memcpy(&buf[offset], ptr, len);
  367. offset += len;
  368. }
  369. #if defined(NU_EMAC_TX_DUMP)
  370. nu_emac_pkt_dump("TX dump", p);
  371. #endif
  372. /* Return SUCCESS? */
  373. return (EMAC_SendPktWoCopy(&psNuEmac->memmgr, offset) == 1) ? RT_EOK : RT_ERROR;
  374. }
  375. void nu_emac_pbuf_free(struct pbuf *p)
  376. {
  377. nu_emac_lwip_pbuf_t my_buf = (nu_emac_lwip_pbuf_t)p;
  378. SYS_ARCH_DECL_PROTECT(old_level);
  379. SYS_ARCH_PROTECT(old_level);
  380. //rt_kprintf("%08x %08x\n",my_buf, my_buf->rx_desc);
  381. /* Update RX descriptor & trigger */
  382. EMAC_RxTrigger(my_buf->psMemMgr, my_buf->rx_desc);
  383. memp_free_pool(my_buf->memp_rx_pool, my_buf);
  384. SYS_ARCH_UNPROTECT(old_level);
  385. }
  386. static struct pbuf *nu_emac_rx(rt_device_t dev)
  387. {
  388. nu_emac_t psNuEmac = (nu_emac_t)dev;
  389. struct pbuf *p = RT_NULL;
  390. uint8_t *pu8DataBuf = NULL;
  391. unsigned int avaialbe_size;
  392. EMAC_T *EMAC = psNuEmac->memmgr.psEmac;
  393. /* Check available data. */
  394. if ((avaialbe_size = EMAC_GetAvailRXBufSize(&psNuEmac->memmgr, &pu8DataBuf)) > 0)
  395. {
  396. EMAC_DESCRIPTOR_T *cur_rx = EMAC_RecvPktDoneWoRxTrigger(&psNuEmac->memmgr);
  397. nu_emac_lwip_pbuf_t my_pbuf = (nu_emac_lwip_pbuf_t)memp_malloc_pool(psNuEmac->memp_rx_pool);
  398. if (my_pbuf != RT_NULL)
  399. {
  400. my_pbuf->p.custom_free_function = nu_emac_pbuf_free;
  401. my_pbuf->psPktFrameDataBuf = (EMAC_FRAME_T *)pu8DataBuf;
  402. my_pbuf->rx_desc = cur_rx;
  403. my_pbuf->psMemMgr = &psNuEmac->memmgr;
  404. my_pbuf->memp_rx_pool = psNuEmac->memp_rx_pool;
  405. #if defined(BSP_USING_MMU)
  406. mmu_invalidate_dcache((rt_uint32_t)pu8DataBuf, (rt_uint32_t)avaialbe_size);
  407. #endif
  408. //rt_kprintf("%08x, %08x, %d\n", my_pbuf, cur_rx, avaialbe_size);
  409. p = pbuf_alloced_custom(PBUF_RAW,
  410. avaialbe_size,
  411. PBUF_REF,
  412. &my_pbuf->p,
  413. pu8DataBuf,
  414. EMAC_MAX_PKT_SIZE);
  415. if (p == RT_NULL)
  416. {
  417. rt_kprintf("%s : failed to alloted %08x\n", __func__, p);
  418. EMAC_RxTrigger(&psNuEmac->memmgr, cur_rx);
  419. }
  420. }
  421. else
  422. {
  423. rt_kprintf("LWIP_MEMPOOL_ALLOC < 0!!\n");
  424. EMAC_RxTrigger(&psNuEmac->memmgr, cur_rx);
  425. }
  426. }
  427. else /* If it hasn't RX packet, it will enable interrupt. */
  428. {
  429. /* No available RX packet, we enable RXGD/RDUIEN interrupts. */
  430. if (!(EMAC->INTEN & EMAC_INTEN_RDUIEN_Msk))
  431. {
  432. EMAC_CLEAR_INT_FLAG(EMAC, (EMAC_INTSTS_RDUIF_Msk | EMAC_INTSTS_RXGDIF_Msk));
  433. EMAC_ENABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk));
  434. }
  435. else
  436. {
  437. EMAC_CLEAR_INT_FLAG(EMAC, EMAC_INTSTS_RXGDIF_Msk);
  438. EMAC_ENABLE_INT(EMAC, EMAC_INTEN_RXGDIEN_Msk);
  439. }
  440. }
  441. return p;
  442. }
  443. static void nu_emac_rx_isr(int vector, void *param)
  444. {
  445. nu_emac_t psNuEmac = (nu_emac_t)param;
  446. EMAC_T *EMAC = psNuEmac->memmgr.psEmac;
  447. unsigned int status = EMAC->INTSTS & 0xFFFF;
  448. /* No RX descriptor available, we need to get data from RX pool */
  449. if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_RDUIF_Msk))
  450. {
  451. EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk));
  452. eth_device_ready(&psNuEmac->eth);
  453. }
  454. /* A good packet ready. */
  455. else if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_RXGDIF_Msk))
  456. {
  457. EMAC_DISABLE_INT(EMAC, EMAC_INTEN_RXGDIEN_Msk);
  458. eth_device_ready(&psNuEmac->eth);
  459. }
  460. /* Receive Bus Error Interrupt */
  461. if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_RXBEIF_Msk))
  462. {
  463. NU_EMAC_TRACE("Reinit Rx EMAC\n");
  464. EMAC_CLEAR_INT_FLAG(EMAC, EMAC_INTSTS_RXBEIF_Msk);
  465. nu_emac_reinit(psNuEmac);
  466. }
  467. EMAC->INTSTS = status;
  468. }
  469. static void nu_emac_tx_isr(int vector, void *param)
  470. {
  471. nu_emac_t psNuEmac = (nu_emac_t)param;
  472. EMAC_T *EMAC = psNuEmac->memmgr.psEmac;
  473. rt_err_t result = RT_EOK;
  474. unsigned int status = EMAC->INTSTS & 0xFFFF0000;
  475. /* Wake-up suspended process to send */
  476. if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_TXCPIF_Msk))
  477. {
  478. EMAC_DISABLE_INT(EMAC, EMAC_INTEN_TXCPIEN_Msk);
  479. result = rt_sem_release(&psNuEmac->eth_sem);
  480. RT_ASSERT(result == RT_EOK);
  481. }
  482. if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_TXBEIF_Msk))
  483. {
  484. NU_EMAC_TRACE("Reinit Tx EMAC\n");
  485. nu_emac_reinit(psNuEmac);
  486. }
  487. else
  488. EMAC_SendPktDone(&psNuEmac->memmgr);
  489. EMAC->INTSTS = status;
  490. }
  491. static void rt_hw_nu_emac_assign_macaddr(nu_emac_t psNuEMAC)
  492. {
  493. static rt_uint32_t value = 0x94539453;
  494. /* Assign MAC address */
  495. psNuEMAC->mac_addr[0] = 0x82;
  496. psNuEMAC->mac_addr[1] = 0x06;
  497. psNuEMAC->mac_addr[2] = 0x21;
  498. psNuEMAC->mac_addr[3] = (value >> 16) & 0xff;
  499. psNuEMAC->mac_addr[4] = (value >> 8) & 0xff;
  500. psNuEMAC->mac_addr[5] = (value) & 0xff;
  501. NU_EMAC_TRACE("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", \
  502. psNuEMAC->mac_addr[0], \
  503. psNuEMAC->mac_addr[1], \
  504. psNuEMAC->mac_addr[2], \
  505. psNuEMAC->mac_addr[3], \
  506. psNuEMAC->mac_addr[4], \
  507. psNuEMAC->mac_addr[5]);
  508. value++;
  509. }
  510. static int rt_hw_nu_emac_init(void)
  511. {
  512. int i;
  513. rt_err_t ret = RT_EOK;
  514. char szTmp[32];
  515. /* MDC CLK divider */
  516. outpw(REG_CLK_DIVCTL8, (inpw(REG_CLK_DIVCTL8) & ~0xFF) | 0xA0);
  517. for (i = (EMAC_START + 1); i < EMAC_CNT; i++)
  518. {
  519. nu_emac_t psNuEMAC = (nu_emac_t)&nu_emac_arr[i];
  520. nu_sys_ipclk_enable(psNuEMAC->clkidx);
  521. nu_sys_ip_reset(psNuEMAC->rstidx);
  522. rt_hw_nu_emac_assign_macaddr(psNuEMAC);
  523. /* Register member functions */
  524. psNuEMAC->eth.parent.init = nu_emac_init;
  525. psNuEMAC->eth.parent.open = nu_emac_open;
  526. psNuEMAC->eth.parent.close = nu_emac_close;
  527. psNuEMAC->eth.parent.read = nu_emac_read;
  528. psNuEMAC->eth.parent.write = nu_emac_write;
  529. psNuEMAC->eth.parent.control = nu_emac_control;
  530. psNuEMAC->eth.parent.user_data = psNuEMAC;
  531. psNuEMAC->eth.eth_rx = nu_emac_rx;
  532. psNuEMAC->eth.eth_tx = nu_emac_tx;
  533. snprintf(szTmp, sizeof(szTmp), "%s_tx", psNuEMAC->name);
  534. rt_hw_interrupt_install(psNuEMAC->irqn_tx, nu_emac_tx_isr, (void *)psNuEMAC, szTmp);
  535. rt_hw_interrupt_umask(psNuEMAC->irqn_tx);
  536. snprintf(szTmp, sizeof(szTmp), "%s_rx", psNuEMAC->name);
  537. rt_hw_interrupt_install(psNuEMAC->irqn_rx, nu_emac_rx_isr, (void *)psNuEMAC, szTmp);
  538. rt_hw_interrupt_umask(psNuEMAC->irqn_rx);
  539. /* Initial zero_copy rx pool */
  540. memp_init_pool(psNuEMAC->memp_rx_pool);
  541. /* Register eth device */
  542. ret = eth_device_init(&psNuEMAC->eth, psNuEMAC->name);
  543. RT_ASSERT(ret == RT_EOK);
  544. }
  545. return 0;
  546. }
  547. INIT_APP_EXPORT(rt_hw_nu_emac_init);
  548. #if 0
  549. /*
  550. Remeber src += lwipiperf_SRCS in components\net\lwip-*\SConscript
  551. */
  552. #include "lwip/apps/lwiperf.h"
  553. static void
  554. lwiperf_report(void *arg, enum lwiperf_report_type report_type,
  555. const ip_addr_t *local_addr, u16_t local_port, const ip_addr_t *remote_addr, u16_t remote_port,
  556. u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec)
  557. {
  558. LWIP_UNUSED_ARG(arg);
  559. LWIP_UNUSED_ARG(local_addr);
  560. LWIP_UNUSED_ARG(local_port);
  561. rt_kprintf("IPERF report: type=%d, remote: %s:%d, total bytes: %"U32_F", duration in ms: %"U32_F", kbits/s: %"U32_F"\n",
  562. (int)report_type, ipaddr_ntoa(remote_addr), (int)remote_port, bytes_transferred, ms_duration, bandwidth_kbitpsec);
  563. }
  564. void lwiperf_example_init(int argc, char **argv)
  565. {
  566. lwiperf_start_tcp_server_default(lwiperf_report, NULL);
  567. }
  568. MSH_CMD_EXPORT(lwiperf_example_init, start lwip tcp server);
  569. #endif
  570. #endif /* #if defined( BSP_USING_EMAC ) && defined( RT_USING_LWIP )*/