drv_emac.c 18 KB

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