drv_emac.c 18 KB

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