drv_emac.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-1-20 bluebear233 first version
  9. */
  10. #include <rtthread.h>
  11. #ifdef RT_USING_LWIP
  12. #include "NuMicro.h"
  13. #include "drv_emac.h"
  14. #include <netif/ethernetif.h>
  15. #include <netif/etharp.h>
  16. #include <lwip/icmp.h>
  17. #include "lwipopts.h"
  18. #define ETH_DEBUG
  19. //#define ETH_RX_DUMP
  20. //#define ETH_TX_DUMP
  21. #ifdef ETH_DEBUG
  22. #define ETH_TRACE rt_kprintf
  23. #else
  24. #define ETH_TRACE(...)
  25. #endif /* ETH_DEBUG */
  26. #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
  27. static void packet_dump(const char * msg, const struct pbuf* p)
  28. {
  29. rt_uint32_t i;
  30. rt_uint8_t *ptr = p->payload;
  31. ETH_TRACE("%s %d byte\n", msg, p->tot_len);
  32. for(i=0; i<p->tot_len; i++)
  33. {
  34. if( (i%8) == 0 )
  35. {
  36. ETH_TRACE(" ");
  37. }
  38. if( (i%16) == 0 )
  39. {
  40. ETH_TRACE("\r\n");
  41. }
  42. ETH_TRACE("%02x ",*ptr);
  43. ptr++;
  44. }
  45. ETH_TRACE("\n\n");
  46. }
  47. #endif /* dump */
  48. #define ETH_TRIGGER_RX() EMAC->RXST = 0
  49. #define ETH_TRIGGER_TX() EMAC->TXST = 0
  50. #define ETH_ENABLE_TX() EMAC->CTL |= EMAC_CTL_TXON
  51. #define ETH_ENABLE_RX() EMAC->CTL |= EMAC_CTL_RXON
  52. #define ETH_DISABLE_TX() EMAC->CTL &= ~EMAC_CTL_TXON
  53. #define ETH_DISABLE_RX() EMAC->CTL &= ~EMAC_CTL_RXON
  54. #define EMAC_DMARXDESC_CRCEIF_Msk (1ul << 17)
  55. #define ETH_TID_STACK 256
  56. static rt_uint8_t volatile phy_speed = 0;
  57. static rt_uint8_t eth_addr[6];
  58. static struct eth_device eth;
  59. static struct rt_semaphore eth_sem;
  60. static struct rt_thread eth_tid;
  61. static rt_uint32_t eth_stack[ETH_TID_STACK / 4];
  62. static struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
  63. static struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
  64. static struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
  65. static rt_uint32_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
  66. static rt_uint32_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
  67. static void mdio_write(rt_uint8_t addr, rt_uint8_t reg, rt_uint16_t val)
  68. {
  69. EMAC->MIIMDAT = val;
  70. EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
  71. while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
  72. }
  73. static rt_uint16_t mdio_read(rt_uint8_t addr, rt_uint8_t reg)
  74. {
  75. EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
  76. while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
  77. return EMAC->MIIMDAT;
  78. }
  79. static void init_tx_desc(void)
  80. {
  81. rt_uint32_t i;
  82. cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
  83. for(i = 0; i < TX_DESCRIPTOR_NUM; i++)
  84. {
  85. tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
  86. tx_desc[i].buf = (rt_uint8_t*)tx_buf[i];
  87. tx_desc[i].status2 = 0;
  88. tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
  89. }
  90. EMAC->TXDSA = (unsigned int)&tx_desc[0];
  91. return;
  92. }
  93. static void init_rx_desc(void)
  94. {
  95. rt_uint32_t i;
  96. cur_rx_desc_ptr = &rx_desc[0];
  97. for(i = 0; i < RX_DESCRIPTOR_NUM; i++)
  98. {
  99. rx_desc[i].status1 = OWNERSHIP_EMAC;
  100. rx_desc[i].buf = (rt_uint8_t*)rx_buf[i];
  101. rx_desc[i].status2 = 0;
  102. rx_desc[i].next = &rx_desc[(i + 1) % RX_DESCRIPTOR_NUM];
  103. }
  104. EMAC->RXDSA = (unsigned int)&rx_desc[0];
  105. return;
  106. }
  107. static void add_mac_addr(const rt_uint8_t *addr)
  108. {
  109. rt_uint32_t *EMAC_CAMxM;
  110. rt_uint32_t *EMAC_CAMxL;
  111. rt_uint8_t index = 0;
  112. rt_uint8_t mac[6];
  113. for(; index < 13; index ++)
  114. {
  115. EMAC_CAMxM = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0M + (index * 8));
  116. EMAC_CAMxL = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0L + (index * 8));
  117. mac[0] = (*EMAC_CAMxM >> 24) & 0xff;
  118. mac[1] = (*EMAC_CAMxM >> 16) & 0xff;
  119. mac[2] = (*EMAC_CAMxM >> 8) & 0xff;
  120. mac[3] = (*EMAC_CAMxM) & 0xff;
  121. mac[4] = (*EMAC_CAMxL >> 24) & 0xff;
  122. mac[5] = (*EMAC_CAMxL >> 16) & 0xff;
  123. if(memcmp(mac, addr, sizeof(mac)) == 0)
  124. {
  125. return;
  126. }
  127. if(*EMAC_CAMxM == 0 && *EMAC_CAMxL == 0)
  128. {
  129. break;
  130. }
  131. }
  132. RT_ASSERT(index < 13)
  133. *EMAC_CAMxM = (addr[0] << 24) |
  134. (addr[1] << 16) |
  135. (addr[2] << 8) |
  136. addr[3];
  137. *EMAC_CAMxL = (addr[4] << 24) |
  138. (addr[5] << 16);
  139. EMAC->CAMEN |= (1 << index);
  140. }
  141. void EMAC_init()
  142. {
  143. // Reset MAC
  144. EMAC->CTL = EMAC_CTL_RST_Msk;
  145. while(EMAC->CTL & EMAC_CTL_RST_Msk);
  146. init_tx_desc();
  147. init_rx_desc();
  148. EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | EMAC_CAMCTL_ABP_Msk;
  149. add_mac_addr(eth_addr);
  150. EMAC->CTL |= EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk | EMAC_CTL_RMIIEN_Msk;
  151. EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
  152. EMAC_INTEN_RXGDIEN_Msk |
  153. EMAC_INTEN_RDUIEN_Msk |
  154. EMAC_INTEN_RXBEIEN_Msk |
  155. EMAC_INTEN_TXIEN_Msk |
  156. EMAC_INTEN_TXBEIEN_Msk;
  157. /* Limit the max receive frame length to 1514 + 4 */
  158. EMAC->MRFL = PACKET_BUFFER_SIZE;
  159. EMAC->RXST = 0; // trigger Rx
  160. }
  161. void EMAC_Reinit(void)
  162. {
  163. rt_uint32_t EMAC_CAMxM[13];
  164. rt_uint32_t EMAC_CAMxL[13];
  165. rt_uint32_t EMAC_CAMEN;
  166. EMAC_CAMEN = EMAC->CAMEN;
  167. for(rt_uint8_t index = 0 ; index < 13; 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. EMAC_init();
  175. for(rt_uint8_t index = 0 ; index < 13; index ++)
  176. {
  177. rt_uint32_t *CAMxM = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0M + (index * 8));
  178. rt_uint32_t *CAMxL = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0L + (index * 8));
  179. *CAMxM = EMAC_CAMxM[index];
  180. *CAMxL = EMAC_CAMxL[index];
  181. }
  182. EMAC->CAMEN = EMAC_CAMEN;
  183. phy_speed = 0;
  184. }
  185. void ETH_halt(void)
  186. {
  187. EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);
  188. }
  189. __inline static rt_uint8_t *emac_get_tx_buf(void)
  190. {
  191. if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
  192. {
  193. return(RT_NULL);
  194. }
  195. else
  196. {
  197. return(cur_tx_desc_ptr->buf);
  198. }
  199. }
  200. __inline static void ETH_trigger_tx(rt_uint16_t length)
  201. {
  202. struct eth_descriptor volatile *desc;
  203. cur_tx_desc_ptr->status2 = (unsigned int)length;
  204. desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr
  205. cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;
  206. cur_tx_desc_ptr = desc;
  207. }
  208. #if LWIP_IPV4 && LWIP_IGMP
  209. static err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, u8_t action )
  210. {
  211. rt_uint8_t mac[6];
  212. const uint8_t *p = (const uint8_t *)ip4_addr;
  213. mac[0] = 0x01;
  214. mac[1] = 0x00;
  215. mac[2] = 0x5E;
  216. mac[3] = *(p+1) & 0x7F;
  217. mac[4] = *(p+2);
  218. mac[5] = *(p+3);
  219. add_mac_addr(mac);
  220. if(1)
  221. {
  222. rt_kprintf("%s %s %s ", __FUNCTION__, (action==NETIF_ADD_MAC_FILTER)?"add":"del", ip4addr_ntoa(ip4_addr));
  223. rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  224. }
  225. return 0;
  226. }
  227. #endif /* LWIP_IPV4 && LWIP_IGMP */
  228. /*
  229. * M480 EMAC Driver for RT-Thread
  230. * Change Logs:
  231. * Date Author Notes
  232. * 2017-12-31 Bluebear233 first implementation
  233. */
  234. void EMAC_RX_IRQHandler(void)
  235. {
  236. /* enter interrupt */
  237. rt_interrupt_enter();
  238. unsigned int status = EMAC->INTSTS;
  239. if(status & EMAC_INTSTS_RDUIF_Msk)
  240. {
  241. EMAC->INTEN &= ~(EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk);
  242. eth_device_ready(&eth);
  243. }
  244. else if(status & EMAC_INTSTS_RXGDIF_Msk)
  245. {
  246. EMAC->INTEN &= ~EMAC_INTEN_RXGDIEN_Msk;
  247. eth_device_ready(&eth);
  248. }
  249. if(status & EMAC_INTSTS_RXBEIF_Msk)
  250. {
  251. ETH_TRACE("Reinit Rx EMAC\n");
  252. EMAC->INTSTS = EMAC_INTSTS_RXBEIF_Msk;
  253. EMAC_Reinit();
  254. }
  255. /* leave interrupt */
  256. rt_interrupt_leave();
  257. }
  258. void EMAC_TX_IRQHandler(void)
  259. {
  260. rt_interrupt_enter();
  261. unsigned int status = EMAC->INTSTS;
  262. if(status & EMAC_INTSTS_TXCPIF_Msk)
  263. {
  264. EMAC->INTEN &= ~EMAC_INTEN_TXCPIEN_Msk;
  265. rt_sem_release(&eth_sem);
  266. }
  267. if(status & EMAC_INTSTS_TXBEIF_Msk)
  268. {
  269. ETH_TRACE("Reinit Tx EMAC\n");
  270. EMAC->INTSTS = EMAC_INTSTS_TXBEIF_Msk;
  271. EMAC_Reinit();
  272. }
  273. rt_interrupt_leave();
  274. }
  275. #define PHY_LINK_MASK (1<<0)
  276. #define PHY_10FULL_MASK (1<<1)
  277. #define PHY_100FULL_MASK (1<<2)
  278. #define PHY_10HALF_MASK (1<<3)
  279. #define PHY_100HALF_MASK (1<<4)
  280. #define PHY_ANLPA_DR100_TX_FULL (1UL << 8UL)
  281. #define PHY_ANLPA_DR100_TX_HALF (1UL << 7UL)
  282. #define PHY_ANLPA_DR10_TX_FULL (1UL << 6UL)
  283. #define PHY_ANLPA_DR10_TX_HALF (1UL << 5UL)
  284. void eth_entry(void *param)
  285. {
  286. uint8_t phy_addr = 0xFF;
  287. uint8_t phy_speed_new = 0;
  288. /* phy search */
  289. {
  290. rt_uint32_t i;
  291. rt_uint16_t temp;
  292. for(i=0; i<=0x1F; i++)
  293. {
  294. temp = mdio_read(i, 0x02);
  295. if( temp != 0xFFFF )
  296. {
  297. phy_addr = i;
  298. break;
  299. }
  300. }
  301. } /* phy search */
  302. if(phy_addr == 0xFF)
  303. {
  304. ETH_TRACE("phy not probe!\n");
  305. return;
  306. }
  307. else
  308. {
  309. ETH_TRACE("found a phy, address:0x%02X\n", phy_addr);
  310. }
  311. /* RESET PHY */
  312. mdio_write(phy_addr, MII_BMCR, BMCR_RESET);
  313. while (1)
  314. {
  315. rt_thread_delay(RT_TICK_PER_SECOND);
  316. rt_uint16_t reg = mdio_read(phy_addr, MII_BMCR);
  317. if ((reg & BMCR_RESET) == 0)
  318. {
  319. break;
  320. }
  321. }
  322. mdio_write(phy_addr, MII_ADVERTISE, ADVERTISE_CSMA |
  323. ADVERTISE_10HALF |
  324. ADVERTISE_10FULL |
  325. ADVERTISE_100HALF |
  326. ADVERTISE_100FULL);
  327. {
  328. uint16_t reg = mdio_read(phy_addr, MII_BMCR);
  329. mdio_write(phy_addr, MII_BMCR, reg | BMCR_ANRESTART);
  330. }
  331. while(1)
  332. {
  333. uint16_t status = mdio_read(phy_addr, MII_BMSR);
  334. phy_speed_new = 0;
  335. if((status & (BMSR_ANEGCAPABLE | BMSR_LSTATUS)) == (BMSR_ANEGCAPABLE | BMSR_LSTATUS))
  336. {
  337. phy_speed_new = PHY_LINK_MASK;
  338. status = mdio_read(phy_addr, MII_LPA);
  339. if(status & PHY_ANLPA_DR100_TX_FULL)
  340. {
  341. phy_speed_new |= PHY_100FULL_MASK;
  342. }
  343. else if(status & PHY_ANLPA_DR100_TX_HALF)
  344. {
  345. phy_speed_new |= PHY_100HALF_MASK;
  346. }
  347. else if(status & PHY_ANLPA_DR10_TX_FULL)
  348. {
  349. phy_speed_new |= PHY_10FULL_MASK;
  350. }
  351. else if(status & PHY_ANLPA_DR10_TX_HALF)
  352. {
  353. phy_speed_new |= PHY_10HALF_MASK;
  354. }
  355. }
  356. /* linkchange */
  357. if(phy_speed_new != phy_speed)
  358. {
  359. if(phy_speed_new & PHY_LINK_MASK)
  360. {
  361. ETH_TRACE("link up ");
  362. if(phy_speed_new & PHY_100FULL_MASK)
  363. {
  364. ETH_TRACE("100Mbps full-duplex\n");
  365. EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
  366. }
  367. else if(phy_speed_new & PHY_100HALF_MASK)
  368. {
  369. ETH_TRACE("100Mbps half-duplex\n");
  370. EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
  371. }
  372. else if(phy_speed_new & PHY_10FULL_MASK)
  373. {
  374. ETH_TRACE("10Mbps full-duplex\n");
  375. EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
  376. }
  377. else
  378. {
  379. ETH_TRACE("10Mbps half-duplex\n");
  380. EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
  381. }
  382. /* send link up. */
  383. eth_device_linkchange(&eth, RT_TRUE);
  384. } /* link up. */
  385. else
  386. {
  387. ETH_TRACE("link down\r\n");
  388. /* send link down. */
  389. eth_device_linkchange(&eth, RT_FALSE);
  390. } /* link down. */
  391. phy_speed = phy_speed_new;
  392. } /* linkchange */
  393. rt_thread_delay(RT_TICK_PER_SECOND);
  394. } /* while(1) */
  395. }
  396. static rt_err_t rt_m480_emac_init(rt_device_t dev)
  397. {
  398. /* Unlock protected registers */
  399. SYS_UnlockReg();
  400. CLK_EnableModuleClock(EMAC_MODULE);
  401. // Configure MDC clock rate to HCLK / (127 + 1) = 1.5 MHz if system is running at 192 MHz
  402. CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
  403. // Configure RMII pins
  404. // SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
  405. SYS->GPA_MFPL |= SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
  406. SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;
  407. SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;
  408. SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
  409. SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
  410. SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
  411. SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
  412. SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
  413. // Enable high slew rate on all RMII TX output pins
  414. PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
  415. (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |
  416. (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);
  417. /* Lock protected registers */
  418. SYS_LockReg();
  419. EMAC_init();
  420. NVIC_SetPriority(EMAC_TX_IRQn, 1);
  421. NVIC_EnableIRQ(EMAC_TX_IRQn);
  422. NVIC_SetPriority(EMAC_RX_IRQn, 1);
  423. NVIC_EnableIRQ(EMAC_RX_IRQn);
  424. rt_sem_init(&eth_sem, "eth_sem", 0, RT_IPC_FLAG_FIFO);
  425. rt_thread_init(&eth_tid, "eth", eth_entry, RT_NULL, eth_stack, sizeof(eth_stack), RT_THREAD_PRIORITY_MAX - 2, 10);
  426. rt_thread_startup(&eth_tid);
  427. #if LWIP_IPV4 && LWIP_IGMP
  428. netif_set_igmp_mac_filter(eth.netif, igmp_mac_filter);
  429. #endif /* LWIP_IPV4 && LWIP_IGMP */
  430. return RT_EOK;
  431. }
  432. static rt_err_t rt_m480_emac_open(rt_device_t dev, rt_uint16_t oflag)
  433. {
  434. return RT_EOK;
  435. }
  436. static rt_err_t rt_m480_emac_close(rt_device_t dev)
  437. {
  438. return RT_EOK;
  439. }
  440. static rt_size_t rt_m480_emac_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  441. {
  442. rt_set_errno(-RT_ENOSYS);
  443. return 0;
  444. }
  445. static rt_size_t rt_m480_emac_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  446. {
  447. rt_set_errno(-RT_ENOSYS);
  448. return 0;
  449. }
  450. static rt_err_t rt_m480_emac_control(rt_device_t dev, int cmd, void *args)
  451. {
  452. switch(cmd)
  453. {
  454. case NIOCTL_GADDR:
  455. /* get mac address */
  456. if(args) rt_memcpy(args, eth_addr, 6);
  457. else return -RT_ERROR;
  458. break;
  459. default :
  460. break;
  461. }
  462. return RT_EOK;
  463. }
  464. rt_err_t rt_m480_emac_tx(rt_device_t dev, struct pbuf* p)
  465. {
  466. struct pbuf* q;
  467. rt_uint32_t offset;
  468. rt_uint8_t *buf;
  469. buf = emac_get_tx_buf();
  470. /* get free tx buffer */
  471. if(buf == RT_NULL)
  472. {
  473. rt_sem_control(&eth_sem, RT_IPC_CMD_RESET, 0);
  474. EMAC->INTSTS = EMAC_INTSTS_TXCPIF_Msk;
  475. EMAC->INTEN |= EMAC_INTEN_TXCPIEN_Msk;
  476. do{
  477. rt_sem_take(&eth_sem, 1);
  478. buf = emac_get_tx_buf();
  479. }while(buf == RT_NULL);
  480. }
  481. offset = 0;
  482. for (q = p; q != NULL; q = q->next)
  483. {
  484. rt_uint8_t* ptr;
  485. rt_uint32_t len;
  486. len = q->len;
  487. ptr = q->payload;
  488. // todo 优化复制
  489. memcpy(&buf[offset], ptr, len);
  490. offset += len;
  491. }
  492. #ifdef ETH_TX_DUMP
  493. packet_dump("TX dump", p);
  494. #endif
  495. ETH_trigger_tx(offset);
  496. if(EMAC->INTSTS & EMAC_INTSTS_TDUIF_Msk)
  497. {
  498. EMAC->INTSTS = EMAC_INTSTS_TDUIF_Msk;
  499. ETH_TRIGGER_TX();
  500. }
  501. /* Return SUCCESS */
  502. return RT_EOK;
  503. }
  504. struct pbuf *rt_m480_emac_rx(rt_device_t dev)
  505. {
  506. unsigned int status;
  507. struct pbuf* p;
  508. /* init p pointer */
  509. p = RT_NULL;
  510. start:
  511. status = cur_rx_desc_ptr->status1;
  512. if(status & OWNERSHIP_EMAC)
  513. {
  514. goto end;
  515. }
  516. if ((status & RXFD_RXGD) && !(status & EMAC_DMARXDESC_CRCEIF_Msk))
  517. {
  518. p = pbuf_alloc(PBUF_RAW, status & 0xFFFF, PBUF_RAM);
  519. if (p != RT_NULL)
  520. {
  521. RT_ASSERT(p->next == RT_NULL);
  522. const char * from = (const char *)(cur_rx_desc_ptr->buf);
  523. // todo 优化复制
  524. memcpy(p->payload, from, p->len);
  525. }
  526. }
  527. #ifdef ETH_RX_DUMP
  528. packet_dump("RX dump", p);
  529. #endif /* ETH_RX_DUMP */
  530. cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
  531. cur_rx_desc_ptr = cur_rx_desc_ptr->next;
  532. if(p == RT_NULL)
  533. {
  534. goto start;
  535. }
  536. return p;
  537. end:
  538. if(!(EMAC->INTEN & EMAC_INTEN_RDUIEN_Msk))
  539. {
  540. EMAC->INTSTS = (EMAC_INTSTS_RDUIF_Msk | EMAC_INTSTS_RXGDIF_Msk);
  541. EMAC->INTEN |= (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk);
  542. ETH_TRIGGER_RX();
  543. }
  544. else
  545. {
  546. EMAC->INTSTS = EMAC_INTSTS_RXGDIF_Msk;
  547. EMAC->INTEN |= EMAC_INTEN_RXGDIEN_Msk;
  548. }
  549. return RT_NULL;
  550. }
  551. static void rt_hw_m480_emac_register(char *dev_name)
  552. {
  553. rt_uint32_t value = 0;
  554. SYS_UnlockReg();
  555. FMC_Open();
  556. for (rt_uint8_t i = 0; i < 3; i++)
  557. {
  558. value += FMC_ReadUID(i);
  559. }
  560. FMC_Close();
  561. SYS_LockReg();
  562. eth_addr[0] = 0x00;
  563. eth_addr[1] = 0x00;
  564. eth_addr[2] = 0x00;
  565. eth_addr[3] = (value >> 16) & 0xff;
  566. eth_addr[4] = (value >> 8) & 0xff;
  567. eth_addr[5] = (value) & 0xff;
  568. eth.parent.init = rt_m480_emac_init;
  569. eth.parent.open = rt_m480_emac_open;
  570. eth.parent.close = rt_m480_emac_close;
  571. eth.parent.read = rt_m480_emac_read;
  572. eth.parent.write = rt_m480_emac_write;
  573. eth.parent.control = rt_m480_emac_control;
  574. eth.parent.user_data = RT_NULL;
  575. eth.eth_rx = rt_m480_emac_rx;
  576. eth.eth_tx = rt_m480_emac_tx;
  577. /* register eth device */
  578. eth_device_init(&eth, dev_name);
  579. }
  580. static int rt_hw_nuc487_emac_init(void)
  581. {
  582. rt_hw_m480_emac_register("eh0");
  583. return RT_EOK;
  584. }
  585. INIT_APP_EXPORT(rt_hw_nuc487_emac_init);
  586. #endif