drv_emac.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. * COPYRIGHT (C) 2018, Real-Thread Information Technology Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. * Change Logs:
  6. * Date Author Notes
  7. * 2015-07-15 Bernard The first version
  8. */
  9. #include <board.h>
  10. #include <rtthread.h>
  11. #include "drv_emac.h"
  12. #if defined(RT_USING_LWIP)
  13. #include <finsh.h>
  14. #include <stdint.h>
  15. #include <netif/ethernetif.h>
  16. #include <lwip/opt.h>
  17. #include "MK64F12.h"
  18. #include "fsl_port.h"
  19. #include "fsl_enet.h"
  20. #include "fsl_phy.h"
  21. //#define DRV_EMAC_DEBUG
  22. //#define DRV_EMAC_RX_DUMP
  23. //#define DRV_EMAC_TX_DUMP
  24. #ifdef DRV_EMAC_DEBUG
  25. #define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__)
  26. #else
  27. #define DEBUG_PRINTF(...)
  28. #endif
  29. #define MAX_ADDR_LEN 6
  30. #define ENET_RX_RING_LEN (16)
  31. #define ENET_TX_RING_LEN (8)
  32. #define K64_EMAC_DEVICE(eth) (struct emac_device*)(eth)
  33. #define ENET_ALIGN(x) \
  34. ((unsigned int)((x) + ((ENET_BUFF_ALIGNMENT)-1)) & (unsigned int)(~(unsigned int)((ENET_BUFF_ALIGNMENT)-1)))
  35. #define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN)
  36. #define ENET_TXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN)
  37. #define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame
  38. struct emac_device
  39. {
  40. /* inherit from Ethernet device */
  41. struct eth_device parent;
  42. ALIGN(64) enet_rx_bd_struct_t RxBuffDescrip[ENET_RX_RING_LEN];
  43. ALIGN(64) enet_tx_bd_struct_t TxBuffDescrip[ENET_TX_RING_LEN];
  44. ALIGN(64) uint8_t RxDataBuff[ENET_RX_RING_LEN * ENET_ALIGN(ENET_RXBUFF_SIZE)];
  45. ALIGN(64) uint8_t TxDataBuff[ENET_TX_RING_LEN * ENET_ALIGN(ENET_TXBUFF_SIZE)];
  46. enet_handle_t enet_handle;
  47. rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* MAC address */
  48. struct rt_semaphore tx_wait;
  49. };
  50. static struct emac_device _emac;
  51. static void setup_k64_io_enet(void)
  52. {
  53. port_pin_config_t configENET = {0};
  54. #ifndef FEATURE_UVISOR
  55. /* Disable MPU only when uVisor is not around. */
  56. SYSMPU->CESR &= ~SYSMPU_CESR_VLD_MASK;
  57. #endif/*FEATURE_UVISOR*/
  58. /* Affects PORTC_PCR16 register */
  59. PORT_SetPinMux(PORTC, 16u, kPORT_MuxAlt4);
  60. /* Affects PORTC_PCR17 register */
  61. PORT_SetPinMux(PORTC, 17u, kPORT_MuxAlt4);
  62. /* Affects PORTC_PCR18 register */
  63. PORT_SetPinMux(PORTC, 18u, kPORT_MuxAlt4);
  64. /* Affects PORTC_PCR19 register */
  65. PORT_SetPinMux(PORTC, 19u, kPORT_MuxAlt4);
  66. /* Affects PORTB_PCR1 register */
  67. PORT_SetPinMux(PORTB, 1u, kPORT_MuxAlt4);
  68. configENET.openDrainEnable = kPORT_OpenDrainEnable;
  69. configENET.mux = kPORT_MuxAlt4;
  70. configENET.pullSelect = kPORT_PullUp;
  71. /* Ungate the port clock */
  72. CLOCK_EnableClock(kCLOCK_PortA);
  73. /* Affects PORTB_PCR0 register */
  74. PORT_SetPinConfig(PORTB, 0u, &configENET);
  75. /* Affects PORTA_PCR13 register */
  76. PORT_SetPinMux(PORTA, 13u, kPORT_MuxAlt4);
  77. /* Affects PORTA_PCR12 register */
  78. PORT_SetPinMux(PORTA, 12u, kPORT_MuxAlt4);
  79. /* Affects PORTA_PCR14 register */
  80. PORT_SetPinMux(PORTA, 14u, kPORT_MuxAlt4);
  81. /* Affects PORTA_PCR5 register */
  82. PORT_SetPinMux(PORTA, 5u, kPORT_MuxAlt4);
  83. /* Affects PORTA_PCR16 register */
  84. PORT_SetPinMux(PORTA, 16u, kPORT_MuxAlt4);
  85. /* Affects PORTA_PCR17 register */
  86. PORT_SetPinMux(PORTA, 17u, kPORT_MuxAlt4);
  87. /* Affects PORTA_PCR15 register */
  88. PORT_SetPinMux(PORTA, 15u, kPORT_MuxAlt4);
  89. /* Affects PORTA_PCR28 register */
  90. PORT_SetPinMux(PORTA, 28u, kPORT_MuxAlt4);
  91. }
  92. static void setup_enet_clock_init(void)
  93. {
  94. CLOCK_EnableClock(kCLOCK_PortC);
  95. CLOCK_EnableClock(kCLOCK_PortB);
  96. /* Select the Ethernet timestamp clock source */
  97. CLOCK_SetEnetTime0Clock(0x2);
  98. }
  99. static void enet_mac_rx_isr(struct emac_device* emac)
  100. {
  101. rt_err_t result;
  102. result = eth_device_ready(&(_emac.parent));
  103. if( result != RT_EOK )
  104. {
  105. DEBUG_PRINTF("RX err =%d\n", result );
  106. }
  107. }
  108. static void enet_mac_tx_isr(struct emac_device* emac)
  109. {
  110. rt_sem_release(&emac->tx_wait);
  111. }
  112. static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param)
  113. {
  114. struct emac_device* emac = param;
  115. switch (event)
  116. {
  117. case kENET_RxEvent:
  118. enet_mac_rx_isr(emac);
  119. break;
  120. case kENET_TxEvent:
  121. enet_mac_tx_isr(emac);
  122. break;
  123. default:
  124. break;
  125. }
  126. }
  127. static rt_err_t k64_emac_init(rt_device_t dev)
  128. {
  129. struct emac_device* emac = K64_EMAC_DEVICE(dev);
  130. enet_handle_t * enet_handle = &emac->enet_handle;
  131. bool link = false;
  132. uint32_t phyAddr = 0;
  133. phy_speed_t phy_speed;
  134. phy_duplex_t phy_duplex;
  135. uint32_t sysClock;
  136. enet_buffer_config_t buffCfg;
  137. enet_config_t config;
  138. /* initialize config according to emac device */
  139. setup_enet_clock_init();
  140. /* enable iomux and clock */
  141. setup_k64_io_enet();
  142. /* prepare the buffer configuration. */
  143. buffCfg.rxBdNumber = ENET_RX_RING_LEN; /* Receive buffer descriptor number. */
  144. buffCfg.txBdNumber = ENET_TX_RING_LEN; /* Transmit buffer descriptor number. */
  145. buffCfg.rxBuffSizeAlign = ENET_ALIGN(ENET_RXBUFF_SIZE); /* Aligned receive data buffer size. */
  146. buffCfg.txBuffSizeAlign = ENET_ALIGN(ENET_TXBUFF_SIZE); /* Aligned transmit data buffer size. */
  147. buffCfg.rxBdStartAddrAlign = emac->RxBuffDescrip; /* Aligned receive buffer descriptor start address. */
  148. buffCfg.txBdStartAddrAlign = emac->TxBuffDescrip; /* Aligned transmit buffer descriptor start address. */
  149. buffCfg.rxBufferAlign = emac->RxDataBuff; /* Receive data buffer start address. */
  150. buffCfg.txBufferAlign = emac->TxDataBuff; /* Transmit data buffer start address. */
  151. sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk);
  152. DEBUG_PRINTF("sysClock: %d\n", sysClock);
  153. ENET_GetDefaultConfig(&config);
  154. PHY_Init(ENET, 0, CLOCK_GetFreq(kCLOCK_CoreSysClk));
  155. if (PHY_GetLinkStatus(ENET, phyAddr, &link) == kStatus_Success)
  156. {
  157. if (link)
  158. {
  159. DEBUG_PRINTF("phy link up\n");
  160. /* Get link information from PHY */
  161. PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex);
  162. /* Change the MII speed and duplex for actual link status. */
  163. config.miiSpeed = (enet_mii_speed_t)phy_speed;
  164. config.miiDuplex = (enet_mii_duplex_t)phy_duplex;
  165. config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt;
  166. }
  167. else
  168. {
  169. DEBUG_PRINTF("phy link down\n");
  170. }
  171. config.rxMaxFrameLen = ENET_ETH_MAX_FLEN;
  172. config.macSpecialConfig = kENET_ControlFlowControlEnable;
  173. config.txAccelerConfig = 0;
  174. config.rxAccelerConfig = kENET_RxAccelMacCheckEnabled;
  175. ENET_Init(ENET, enet_handle, &config, &buffCfg, emac->dev_addr, sysClock);
  176. ENET_SetCallback(enet_handle, ethernet_callback, emac);
  177. ENET_ActiveRead(ENET);
  178. }
  179. else
  180. {
  181. DEBUG_PRINTF("read phy failed\n");
  182. }
  183. return RT_EOK;
  184. }
  185. static rt_err_t k64_emac_open(rt_device_t dev, rt_uint16_t oflag)
  186. {
  187. return RT_EOK;
  188. }
  189. static rt_err_t k64_emac_close(rt_device_t dev)
  190. {
  191. return RT_EOK;
  192. }
  193. static rt_size_t k64_emac_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  194. {
  195. rt_set_errno(-RT_ENOSYS);
  196. return 0;
  197. }
  198. static rt_size_t k64_emac_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  199. {
  200. rt_set_errno(-RT_ENOSYS);
  201. return 0;
  202. }
  203. static rt_err_t k64_emac_control(rt_device_t dev, int cmd, void *args)
  204. {
  205. struct emac_device *emac;
  206. DEBUG_PRINTF("k64_emac_control\n");
  207. emac = K64_EMAC_DEVICE(dev);
  208. RT_ASSERT(emac != RT_NULL);
  209. switch(cmd)
  210. {
  211. case NIOCTL_GADDR:
  212. /* get MAC address */
  213. if(args) rt_memcpy(args, emac->dev_addr, 6);
  214. else return -RT_ERROR;
  215. break;
  216. default :
  217. break;
  218. }
  219. return RT_EOK;
  220. }
  221. static rt_err_t k64_emac_tx(rt_device_t dev, struct pbuf* p)
  222. {
  223. rt_err_t result = RT_EOK;
  224. struct emac_device *emac = K64_EMAC_DEVICE(dev);
  225. enet_handle_t * enet_handle = &emac->enet_handle;
  226. RT_ASSERT(p != NULL);
  227. DEBUG_PRINTF("k64_emac_tx: %d\n", p->len);
  228. emac = K64_EMAC_DEVICE(dev);
  229. RT_ASSERT(emac != RT_NULL);
  230. #ifdef DRV_EMAC_RX_DUMP
  231. {
  232. int i;
  233. uint8_t * buf;
  234. buf = (uint8_t *)p->payload;
  235. for (i = 0; i < p->len; i++)
  236. {
  237. DEBUG_PRINTF("%02X ", buf[i]);
  238. if (i % 16 == 15)
  239. DEBUG_PRINTF("\n");
  240. }
  241. DEBUG_PRINTF("\n");
  242. }
  243. #endif
  244. do
  245. {
  246. result = ENET_SendFrame(ENET, enet_handle, p->payload, p->len);
  247. if (result == kStatus_ENET_TxFrameBusy)
  248. {
  249. rt_sem_take(&emac->tx_wait, RT_WAITING_FOREVER);
  250. }
  251. } while (result == kStatus_ENET_TxFrameBusy);
  252. return RT_EOK;
  253. }
  254. struct pbuf *k64_emac_rx(rt_device_t dev)
  255. {
  256. uint32_t length = 0;
  257. status_t status;
  258. enet_data_error_stats_t eErrStatic;
  259. struct pbuf* p = RT_NULL;
  260. struct emac_device *emac = K64_EMAC_DEVICE(dev);
  261. enet_handle_t * enet_handle = &emac->enet_handle;
  262. RT_ASSERT(emac != RT_NULL);
  263. DEBUG_PRINTF("k64_emac_rx\n");
  264. /* Get the Frame size */
  265. status = ENET_GetRxFrameSize(enet_handle, &length);
  266. if (status == kStatus_ENET_RxFrameError)
  267. {
  268. /* Update the received buffer when error happened. */
  269. /* Get the error information of the received g_frame. */
  270. ENET_GetRxErrBeforeReadFrame(enet_handle, &eErrStatic);
  271. /* update the receive buffer. */
  272. ENET_ReadFrame(ENET, enet_handle, NULL, 0);
  273. DEBUG_PRINTF("receive frame faild\n");
  274. return p;
  275. }
  276. /* Call ENET_ReadFrame when there is a received frame. */
  277. if (length != 0)
  278. {
  279. /* Received valid frame. Deliver the rx buffer with the size equal to length. */
  280. p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL);
  281. }
  282. if (p != NULL)
  283. {
  284. status = ENET_ReadFrame(ENET, enet_handle, p->payload, length);
  285. if (status == kStatus_Success)
  286. {
  287. #ifdef DRV_EMAC_RX_DUMP
  288. uint8_t *buf;
  289. int i;
  290. DEBUG_PRINTF(" A frame received. the length:%d\n", p->len);
  291. buf = (uint8_t *)p->payload;
  292. for (i = 0; i < p->len; i++)
  293. {
  294. DEBUG_PRINTF("%02X ", buf[i]);
  295. if (i % 16 == 15)
  296. DEBUG_PRINTF("\n");
  297. }
  298. DEBUG_PRINTF("\n");
  299. #endif
  300. }
  301. else
  302. {
  303. DEBUG_PRINTF(" A frame read failed\n");
  304. pbuf_free(p);
  305. }
  306. }
  307. return p;
  308. }
  309. int drv_emac_hw_init(void)
  310. {
  311. /* use the test MAC address */
  312. _emac.dev_addr[0] = 0x00;
  313. _emac.dev_addr[1] = 0x04;
  314. _emac.dev_addr[2] = 0x9f;
  315. _emac.dev_addr[3] = 0xc4;
  316. _emac.dev_addr[4] = 0x44;
  317. _emac.dev_addr[5] = 0x22;
  318. _emac.parent.parent.init = k64_emac_init;
  319. _emac.parent.parent.open = k64_emac_open;
  320. _emac.parent.parent.close = k64_emac_close;
  321. _emac.parent.parent.read = k64_emac_read;
  322. _emac.parent.parent.write = k64_emac_write;
  323. _emac.parent.parent.control = k64_emac_control;
  324. _emac.parent.parent.user_data = RT_NULL;
  325. _emac.parent.eth_rx = k64_emac_rx;
  326. _emac.parent.eth_tx = k64_emac_tx;
  327. /* init tx semaphore */
  328. rt_sem_init(&_emac.tx_wait, "tx_wait", ENET_TX_RING_LEN - 1, RT_IPC_FLAG_FIFO);
  329. /* register ETH device */
  330. eth_device_init(&(_emac.parent), "e0");
  331. return 0;
  332. }
  333. INIT_DEVICE_EXPORT(drv_emac_hw_init);
  334. #ifdef DRV_EMAC_DEBUG
  335. long k64_dump_tx_bd(void)
  336. {
  337. int i;
  338. enet_tx_bd_struct_t *txbd = _emac.TxBuffDescrip;
  339. for (i = 0; i < ENET_RX_RING_LEN; i++)
  340. {
  341. DEBUG_PRINTF("status: %04X, length: %04X, data: %08X\n", txbd[i].control, txbd[i].length, (uint32_t)txbd[i].buffer);
  342. }
  343. return 0;
  344. }
  345. FINSH_FUNCTION_EXPORT(k64_dump_tx_bd, dump all receive buffer descriptor);
  346. MSH_CMD_EXPORT(k64_dump_tx_bd, dump all receive buffer descriptor);
  347. long k64_dump_rx_bd(void)
  348. {
  349. int i;
  350. enet_rx_bd_struct_t *rxbd = _emac.RxBuffDescrip;
  351. for (i = 0; i < ENET_RX_RING_LEN; i++)
  352. {
  353. DEBUG_PRINTF("bd:%08X, ", (void *)&rxbd[i]);
  354. //rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, (void *)&rxbd[i], sizeof(enet_rx_bd_struct_t));
  355. DEBUG_PRINTF("status:%04X, length:%04X, data:%08X ", rxbd[i].control, rxbd[i].length, (uint32_t)rxbd[i].buffer);
  356. #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
  357. DEBUG_PRINTF("ce:%04X/%04X/%04X ", rxbd[i].controlExtend0, rxbd[i].controlExtend1, rxbd[i].controlExtend2);
  358. DEBUG_PRINTF("crc:%04X, len:%04X, type:%04X, ts:%04X", rxbd[i].payloadCheckSum, rxbd[i].headerLength, rxbd[i].protocolTyte, rxbd[i].timestamp);
  359. #endif
  360. DEBUG_PRINTF("\n");
  361. }
  362. return 0;
  363. }
  364. FINSH_FUNCTION_EXPORT(k64_dump_rx_bd, dump all receive buffer descriptor);
  365. MSH_CMD_EXPORT(k64_dump_rx_bd, dump all receive buffer descriptor);
  366. #endif
  367. #endif