1
0

drv_eth.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-10-20 luobeihai first version
  9. * 2023-01-10 luobeihai fix Eanble HARDWARE_CHECKSUM bug
  10. */
  11. #include <board.h>
  12. #ifdef BSP_USING_ETH
  13. #include <netif/ethernetif.h>
  14. #include <netif/etharp.h>
  15. #include <lwip/icmp.h>
  16. #include "lwipopts.h"
  17. #include "lwip/ip.h"
  18. #include "drv_eth.h"
  19. /* debug option */
  20. //#define DRV_DEBUG
  21. //#define ETH_RX_DUMP
  22. //#define ETH_TX_DUMP
  23. #define LOG_TAG "drv.emac"
  24. #include <drv_log.h>
  25. /* Global pointers on Tx and Rx descriptor used to transmit and receive descriptors */
  26. extern ETH_DMADescConfig_T *DMATxDescToSet, *DMARxDescToGet;
  27. /* Ethernet Rx & Tx DMA Descriptors */
  28. extern ETH_DMADescConfig_T DMARxDscrTab[ETH_RXBUFNB];
  29. extern ETH_DMADescConfig_T DMATxDscrTab[ETH_TXBUFNB];
  30. /* Ethernet Receive and Transmit buffers */
  31. extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
  32. extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
  33. /* phy address */
  34. static uint8_t phy_addr = 0xFF;
  35. #define MAX_ADDR_LEN 6
  36. struct rt_apm32_eth
  37. {
  38. /* inherit from ethernet device */
  39. struct eth_device parent;
  40. rt_timer_t poll_link_timer;
  41. /* interface address info. */
  42. rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
  43. uint32_t ETH_Speed; /*!< @ref ETH_Speed */
  44. uint32_t ETH_Mode; /*!< @ref ETH_Duplex_Mode */
  45. uint32_t ETH_HashTableHigh;
  46. uint32_t ETH_HashTableLow;
  47. };
  48. static struct rt_apm32_eth apm32_eth_device;
  49. static struct rt_semaphore tx_wait;
  50. static rt_bool_t tx_is_waiting = RT_FALSE;
  51. #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
  52. #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
  53. static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
  54. {
  55. unsigned char *buf = (unsigned char *)ptr;
  56. int i, j;
  57. for (i = 0; i < buflen; i += 16)
  58. {
  59. rt_kprintf("%08X: ", i);
  60. for (j = 0; j < 16; j++)
  61. if (i + j < buflen)
  62. rt_kprintf("%02X ", buf[i + j]);
  63. else
  64. rt_kprintf(" ");
  65. rt_kprintf(" ");
  66. for (j = 0; j < 16; j++)
  67. if (i + j < buflen)
  68. rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
  69. rt_kprintf("\n");
  70. }
  71. }
  72. #endif
  73. /* interrupt service routine */
  74. void ETH_IRQHandler(void)
  75. {
  76. rt_uint32_t status, ier;
  77. /* enter interrupt */
  78. rt_interrupt_enter();
  79. /* ETH DMA status registor */
  80. status = ETH->DMASTS;
  81. /* ETH DMA interrupt resgitor */
  82. ier = ETH->DMAINTEN;
  83. if(status & ETH_DMA_INT_MMC)
  84. {
  85. ETH_ClearDMAIntFlag(ETH_DMA_INT_MMC);
  86. }
  87. if(status & ETH_DMA_INT_NIS)
  88. {
  89. rt_uint32_t nis_clear = ETH_DMA_INT_NIS;
  90. /* [0]:Transmit Interrupt. */
  91. if((status & ier) & ETH_DMA_INT_TX) /* packet transmission */
  92. {
  93. if (tx_is_waiting == RT_TRUE)
  94. {
  95. tx_is_waiting = RT_FALSE;
  96. rt_sem_release(&tx_wait);
  97. }
  98. nis_clear |= ETH_DMA_INT_TX;
  99. }
  100. /* [2]:Transmit Buffer Unavailable. */
  101. /* [6]:Receive Interrupt. */
  102. if((status & ier) & ETH_DMA_INT_RX) /* packet reception */
  103. {
  104. /* a frame has been received */
  105. eth_device_ready(&(apm32_eth_device.parent));
  106. nis_clear |= ETH_DMA_INT_RX;
  107. }
  108. /* [14]:Early Receive Interrupt. */
  109. ETH_ClearDMAIntFlag(nis_clear);
  110. }
  111. if(status & ETH_DMA_INT_AIS)
  112. {
  113. rt_uint32_t ais_clear = ETH_DMA_INT_AIS;
  114. /* [1]:Transmit Process Stopped. */
  115. if(status & ETH_DMA_INT_TPS)
  116. {
  117. ais_clear |= ETH_DMA_INT_TPS;
  118. }
  119. /* [3]:Transmit Jabber Timeout. */
  120. if(status & ETH_DMA_INT_TJT)
  121. {
  122. ais_clear |= ETH_DMA_INT_TJT;
  123. }
  124. /* [4]: Receive FIFO Overflow. */
  125. if(status & ETH_DMA_INT_RO)
  126. {
  127. ais_clear |= ETH_DMA_INT_RO;
  128. }
  129. /* [5]: Transmit Underflow. */
  130. if(status & ETH_DMA_INT_TU)
  131. {
  132. ais_clear |= ETH_DMA_INT_TU;
  133. }
  134. /* [7]: Receive Buffer Unavailable. */
  135. if(status & ETH_DMA_INT_RBU)
  136. {
  137. ais_clear |= ETH_DMA_INT_RBU;
  138. }
  139. /* [8]: Receive Process Stopped. */
  140. if(status & ETH_DMA_INT_RPS)
  141. {
  142. ais_clear |= ETH_DMA_INT_RPS;
  143. }
  144. /* [9]: Receive Watchdog Timeout. */
  145. if(status & ETH_DMA_INT_RWT)
  146. {
  147. ais_clear |= ETH_DMA_INT_RWT;
  148. }
  149. /* [10]: Early Transmit Interrupt. */
  150. /* [13]: Fatal Bus Error. */
  151. if(status & ETH_DMA_INT_FBE)
  152. {
  153. ais_clear |= ETH_DMA_INT_FBE;
  154. }
  155. ETH_ClearDMAIntFlag(ais_clear);
  156. }
  157. /* leave interrupt */
  158. rt_interrupt_leave();
  159. }
  160. #if (LWIP_IPV4 && LWIP_IGMP) || (LWIP_IPV6 && LWIP_IPV6_MLD)
  161. /* polynomial: 0x04C11DB7 */
  162. static uint32_t ethcrc(const uint8_t *data, size_t length)
  163. {
  164. uint32_t crc = 0xffffffff;
  165. size_t i;
  166. int j;
  167. for (i = 0; i < length; i++)
  168. {
  169. for (j = 0; j < 8; j++)
  170. {
  171. if (((crc >> 31) ^ (data[i] >> j)) & 0x01)
  172. {
  173. /* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */
  174. crc = (crc << 1) ^ 0x04C11DB7;
  175. }
  176. else
  177. {
  178. crc = crc << 1;
  179. }
  180. }
  181. }
  182. return ~crc;
  183. }
  184. #define HASH_BITS 6 /* #bits in hash */
  185. static void register_multicast_address(struct rt_apm32_eth *apm32_eth, const uint8_t *mac)
  186. {
  187. uint32_t crc;
  188. uint8_t hash;
  189. /* calculate crc32 value of mac address */
  190. crc = ethcrc(mac, 6);
  191. /* only upper 6 bits (HASH_BITS) are used
  192. * which point to specific bit in he hash registers
  193. */
  194. hash = (crc >> 26) & 0x3F;
  195. //rt_kprintf("register_multicast_address crc: %08X hash: %02X\n", crc, hash);
  196. if (hash > 31)
  197. {
  198. apm32_eth->ETH_HashTableHigh |= 1 << (hash - 32);
  199. ETH->HTH = apm32_eth->ETH_HashTableHigh;
  200. }
  201. else
  202. {
  203. apm32_eth->ETH_HashTableLow |= 1 << hash;
  204. ETH->HTL = apm32_eth->ETH_HashTableLow;
  205. }
  206. }
  207. #endif /* (LWIP_IPV4 && LWIP_IGMP) || (LWIP_IPV6 && LWIP_IPV6_MLD) */
  208. #if LWIP_IPV4 && LWIP_IGMP
  209. static err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, enum netif_mac_filter_action action )
  210. {
  211. uint8_t mac[6];
  212. const uint8_t *p = (const uint8_t *)ip4_addr;
  213. struct rt_apm32_eth *apm32_eth = (struct rt_apm32_eth *)netif->state;
  214. mac[0] = 0x01;
  215. mac[1] = 0x00;
  216. mac[2] = 0x5E;
  217. mac[3] = *(p+1) & 0x7F;
  218. mac[4] = *(p+2);
  219. mac[5] = *(p+3);
  220. register_multicast_address(apm32_eth, mac);
  221. if(1)
  222. {
  223. rt_kprintf("%s %s %s ", __FUNCTION__, (action==NETIF_ADD_MAC_FILTER)?"add":"del", ip4addr_ntoa(ip4_addr));
  224. rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  225. }
  226. return 0;
  227. }
  228. #endif /* LWIP_IPV4 && LWIP_IGMP */
  229. #if LWIP_IPV6 && LWIP_IPV6_MLD
  230. static err_t mld_mac_filter( struct netif *netif, const ip6_addr_t *ip6_addr, enum netif_mac_filter_action action )
  231. {
  232. uint8_t mac[6];
  233. const uint8_t *p = (const uint8_t *)&ip6_addr->addr[3];
  234. struct rt_apm32_eth *apm32_eth = (struct rt_apm32_eth *)netif->state;
  235. mac[0] = 0x33;
  236. mac[1] = 0x33;
  237. mac[2] = *(p+0);
  238. mac[3] = *(p+1);
  239. mac[4] = *(p+2);
  240. mac[5] = *(p+3);
  241. register_multicast_address(apm32_eth, mac);
  242. if(1)
  243. {
  244. rt_kprintf("%s %s %s ", __FUNCTION__, (action==NETIF_ADD_MAC_FILTER)?"add":"del", ip6addr_ntoa(ip6_addr));
  245. rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  246. }
  247. return 0;
  248. }
  249. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
  250. /* initialize the interface */
  251. static rt_err_t rt_apm32_eth_init(rt_device_t dev)
  252. {
  253. struct rt_apm32_eth * apm32_eth = (struct rt_apm32_eth *)dev;
  254. ETH_Config_T ETH_InitStructure;
  255. /* Enable ETHERNET clock */
  256. #if defined(SOC_SERIES_APM32F1)
  257. RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_ETH_MAC | RCM_AHB_PERIPH_ETH_MAC_TX |
  258. RCM_AHB_PERIPH_ETH_MAC_RX);
  259. #elif defined(SOC_SERIES_APM32F4)
  260. RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_ETH_MAC | RCM_AHB1_PERIPH_ETH_MAC_Tx |
  261. RCM_AHB1_PERIPH_ETH_MAC_Rx);
  262. #endif
  263. /* Reset ETHERNET on AHB Bus */
  264. ETH_Reset();
  265. /* Software reset */
  266. ETH_SoftwareReset();
  267. /* Wait for software reset */
  268. while(ETH_ReadSoftwareReset() == SET);
  269. /* ETHERNET Configuration --------------------------------------------------*/
  270. /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */
  271. ETH_ConfigStructInit(&ETH_InitStructure);
  272. /* Fill ETH_InitStructure parametrs */
  273. /*------------------------ MAC -----------------------------------*/
  274. ETH_InitStructure.autoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
  275. ETH_InitStructure.speed = (ETH_SPEED_T)apm32_eth->ETH_Speed;
  276. ETH_InitStructure.mode = (ETH_MODE_T)apm32_eth->ETH_Mode;
  277. ETH_InitStructure.loopbackMode = ETH_LOOPBACKMODE_DISABLE;
  278. ETH_InitStructure.retryTransmission = ETH_RETRYTRANSMISSION_DISABLE;
  279. ETH_InitStructure.automaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE;
  280. ETH_InitStructure.receiveAll = ETH_RECEIVEAll_DISABLE;
  281. ETH_InitStructure.broadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE;
  282. ETH_InitStructure.promiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE;
  283. ETH_InitStructure.multicastFramesFilter = ETH_MULTICASTFRAMESFILTER_HASHTABLE;
  284. ETH_InitStructure.hashTableHigh = apm32_eth->ETH_HashTableHigh;
  285. ETH_InitStructure.hashTableLow = apm32_eth->ETH_HashTableLow;
  286. ETH_InitStructure.unicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT;
  287. #ifdef RT_LWIP_USING_HW_CHECKSUM
  288. ETH_InitStructure.checksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
  289. #endif
  290. /*------------------------ DMA -----------------------------------*/
  291. /* When we use the Checksum offload feature, we need to enable the Store and Forward mode:
  292. the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
  293. if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
  294. ETH_InitStructure.dropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;
  295. ETH_InitStructure.receiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;
  296. ETH_InitStructure.flushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_DISABLE;
  297. ETH_InitStructure.transmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;
  298. ETH_InitStructure.forwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;
  299. ETH_InitStructure.forwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;
  300. ETH_InitStructure.secondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;
  301. ETH_InitStructure.addressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;
  302. ETH_InitStructure.fixedBurst = ETH_FIXEDBURST_ENABLE;
  303. ETH_InitStructure.rxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
  304. ETH_InitStructure.txDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
  305. ETH_InitStructure.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_2_1;
  306. /* configure Ethernet */
  307. ETH_Config(&ETH_InitStructure, phy_addr);
  308. /* Enable DMA Receive interrupt (need to enable in this case Normal interrupt) */
  309. ETH_EnableDMAInterrupt(ETH_DMA_INT_NIS | ETH_DMA_INT_RX | ETH_DMA_INT_TX);
  310. NVIC_EnableIRQ(ETH_IRQn);
  311. /* Initialize Tx Descriptors list: Chain Mode */
  312. ETH_ConfigDMATxDescChain(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
  313. /* Initialize Rx Descriptors list: Chain Mode */
  314. ETH_ConfigDMARxDescChain(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
  315. /* MAC address configuration */
  316. ETH_ConfigMACAddress(ETH_MAC_ADDRESS0, (u8*)&apm32_eth_device.dev_addr[0]);
  317. /* Enable MAC and DMA transmission and reception */
  318. ETH_Start();
  319. #if LWIP_IPV4 && LWIP_IGMP
  320. netif_set_igmp_mac_filter(apm32_eth->parent.netif, igmp_mac_filter);
  321. #endif /* LWIP_IPV4 && LWIP_IGMP */
  322. #if LWIP_IPV6 && LWIP_IPV6_MLD
  323. netif_set_mld_mac_filter(apm32_eth->parent.netif, mld_mac_filter);
  324. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
  325. return RT_EOK;
  326. }
  327. static rt_err_t rt_apm32_eth_open(rt_device_t dev, rt_uint16_t oflag)
  328. {
  329. return RT_EOK;
  330. }
  331. static rt_err_t rt_apm32_eth_close(rt_device_t dev)
  332. {
  333. return RT_EOK;
  334. }
  335. static rt_ssize_t rt_apm32_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  336. {
  337. rt_set_errno(-RT_ENOSYS);
  338. return 0;
  339. }
  340. static rt_ssize_t rt_apm32_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  341. {
  342. rt_set_errno(-RT_ENOSYS);
  343. return 0;
  344. }
  345. static rt_err_t rt_apm32_eth_control(rt_device_t dev, int cmd, void *args)
  346. {
  347. switch(cmd)
  348. {
  349. case NIOCTL_GADDR:
  350. /* get mac address */
  351. if(args) rt_memcpy(args, apm32_eth_device.dev_addr, 6);
  352. else return -RT_ERROR;
  353. break;
  354. default :
  355. break;
  356. }
  357. return RT_EOK;
  358. }
  359. /* ethernet device interface */
  360. /* transmit packet. */
  361. rt_err_t rt_apm32_eth_tx( rt_device_t dev, struct pbuf* p)
  362. {
  363. struct pbuf* q;
  364. rt_uint32_t offset;
  365. /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
  366. while ((DMATxDescToSet->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
  367. {
  368. rt_err_t result;
  369. rt_uint32_t level;
  370. level = rt_hw_interrupt_disable();
  371. tx_is_waiting = RT_TRUE;
  372. rt_hw_interrupt_enable(level);
  373. /* it's own bit set, wait it */
  374. result = rt_sem_take(&tx_wait, RT_WAITING_FOREVER);
  375. if (result == RT_EOK) break;
  376. if (result == -RT_ERROR) return -RT_ERROR;
  377. }
  378. offset = 0;
  379. for (q = p; q != NULL; q = q->next)
  380. {
  381. uint8_t *to;
  382. /* Copy the frame to be sent into memory pointed by the current ETHERNET DMA Tx descriptor */
  383. to = (uint8_t*)((DMATxDescToSet->Buffer1Addr) + offset);
  384. SMEMCPY(to, q->payload, q->len);
  385. offset += q->len;
  386. }
  387. #ifdef ETH_TX_DUMP
  388. rt_kprintf("tx_dump, len:%d\r\n", p->tot_len);
  389. dump_hex((rt_uint8_t*)(DMATxDescToSet->Buffer1Addr), p->tot_len);
  390. #endif
  391. /* Setting the Frame Length: bits[12:0] */
  392. DMATxDescToSet->ControlBufferSize = (p->tot_len & ETH_DMATXDESC_TXBS1);
  393. /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
  394. DMATxDescToSet->Status |= ETH_DMATXDESC_LS | ETH_DMATXDESC_FS;
  395. /* Enable TX Completion Interrupt */
  396. DMATxDescToSet->Status |= ETH_DMATXDESC_INTC;
  397. #ifdef RT_LWIP_USING_HW_CHECKSUM
  398. DMATxDescToSet->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;
  399. /* clean ICMP checksum APM32F need */
  400. {
  401. struct eth_hdr *ethhdr = (struct eth_hdr *)(DMATxDescToSet->Buffer1Addr);
  402. /* is IP ? */
  403. if( ethhdr->type == htons(ETHTYPE_IP) )
  404. {
  405. struct ip_hdr *iphdr = (struct ip_hdr *)(DMATxDescToSet->Buffer1Addr + SIZEOF_ETH_HDR);
  406. /* is ICMP ? */
  407. if( IPH_PROTO(iphdr) == IP_PROTO_ICMP )
  408. {
  409. struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)(DMATxDescToSet->Buffer1Addr + SIZEOF_ETH_HDR + sizeof(struct ip_hdr) );
  410. iecho->chksum = 0;
  411. }
  412. }
  413. }
  414. #endif
  415. /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
  416. DMATxDescToSet->Status |= ETH_DMATXDESC_OWN;
  417. /* When Tx Buffer unavailable flag is set: clear it and resume transmission */
  418. if ((ETH->DMASTS & BIT2) != (u32)RESET)
  419. {
  420. /** Clear TBUS ETHERNET DMA flag */
  421. ETH->DMASTS = BIT2;
  422. /** Resume DMA transmission*/
  423. ETH->DMATXPD = 0;
  424. }
  425. /* Update the ETHERNET DMA global Tx descriptor with next Tx decriptor */
  426. /* Chained Mode */
  427. /* Selects the next DMA Tx descriptor list for next buffer to send */
  428. DMATxDescToSet = (ETH_DMADescConfig_T*) (DMATxDescToSet->Buffer2NextDescAddr);
  429. /* Return SUCCESS */
  430. return RT_EOK;
  431. }
  432. /* reception packet. */
  433. struct pbuf *rt_apm32_eth_rx(rt_device_t dev)
  434. {
  435. struct pbuf* p;
  436. rt_uint32_t offset = 0, framelength = 0;
  437. /* init p pointer */
  438. p = RT_NULL;
  439. /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
  440. if(((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) != (uint32_t)RESET))
  441. return p;
  442. if (((DMARxDescToGet->Status & ETH_DMARXDESC_ERRS) == (uint32_t)RESET) &&
  443. ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) != (uint32_t)RESET) &&
  444. ((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) != (uint32_t)RESET))
  445. {
  446. /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
  447. framelength = ((DMARxDescToGet->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT) - 4;
  448. /* allocate buffer */
  449. p = pbuf_alloc(PBUF_LINK, framelength, PBUF_RAM);
  450. if (p != RT_NULL)
  451. {
  452. struct pbuf* q;
  453. for (q = p; q != RT_NULL; q= q->next)
  454. {
  455. /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */
  456. SMEMCPY(q->payload, (uint8_t *)((DMARxDescToGet->Buffer1Addr) + offset), q->len);
  457. offset += q->len;
  458. }
  459. #ifdef ETH_RX_DUMP
  460. rt_kprintf("rx_dump, len:%d\r\n", p->tot_len);
  461. dump_hex((rt_uint8_t*)(DMARxDescToGet->Buffer1Addr), p->tot_len);
  462. #endif
  463. }
  464. }
  465. /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */
  466. DMARxDescToGet->Status = ETH_DMARXDESC_OWN;
  467. /* When Rx Buffer unavailable flag is set: clear it and resume reception */
  468. if ((ETH->DMASTS & BIT7) != (u32)RESET)
  469. {
  470. /* Clear RBUS ETHERNET DMA flag */
  471. ETH->DMASTS = BIT7;
  472. /* Resume DMA reception */
  473. ETH->DMARXPD = 0;
  474. }
  475. /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */
  476. /* Chained Mode */
  477. if((DMARxDescToGet->ControlBufferSize & ETH_DMARXDESC_RXCH) != (uint32_t)RESET)
  478. {
  479. /* Selects the next DMA Rx descriptor list for next buffer to read */
  480. DMARxDescToGet = (ETH_DMADescConfig_T*) (DMARxDescToGet->Buffer2NextDescAddr);
  481. }
  482. else /* Ring Mode */
  483. {
  484. if((DMARxDescToGet->ControlBufferSize & ETH_DMARXDESC_RXER) != (uint32_t)RESET)
  485. {
  486. /* Selects the first DMA Rx descriptor for next buffer to read: last Rx descriptor was used */
  487. DMARxDescToGet = (ETH_DMADescConfig_T*) (ETH->DMARXDLADDR);
  488. }
  489. else
  490. {
  491. /* Selects the next DMA Rx descriptor list for next buffer to read */
  492. DMARxDescToGet = (ETH_DMADescConfig_T*) ((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABMOD & 0x0000007C) >> 2));
  493. }
  494. }
  495. return p;
  496. }
  497. enum {
  498. PHY_LINK = (1 << 0),
  499. PHY_100M = (1 << 1),
  500. PHY_FULL_DUPLEX = (1 << 2),
  501. };
  502. static void phy_linkchange(void)
  503. {
  504. uint8_t phy_speed_new = 0;
  505. static uint8_t phy_speed = 0;
  506. uint16_t status = ETH_ReadPHYRegister(phy_addr, PHY_BSR);
  507. LOG_D("phy basic status reg is 0x%X", status);
  508. if(status & (PHY_AUTONEGO_COMPLETE | PHY_LINKED_STATUS))
  509. {
  510. uint16_t SR;
  511. phy_speed_new |= PHY_LINK;
  512. SR = ETH_ReadPHYRegister(phy_addr, PHY_Status_REG);
  513. LOG_D("phy control status reg is 0x%X", SR);
  514. if (PHY_Status_SPEED_100M(SR))
  515. {
  516. phy_speed_new |= PHY_100M;
  517. }
  518. if (PHY_Status_FULL_DUPLEX(SR))
  519. {
  520. phy_speed_new |= PHY_FULL_DUPLEX;
  521. }
  522. }
  523. /* linkchange */
  524. if(phy_speed_new != phy_speed)
  525. {
  526. if(phy_speed_new & PHY_LINK)
  527. {
  528. LOG_D("link up ");
  529. if(phy_speed_new & PHY_100M)
  530. {
  531. LOG_D("100Mbps");
  532. apm32_eth_device.ETH_Speed = ETH_SPEED_100M;
  533. }
  534. else
  535. {
  536. apm32_eth_device.ETH_Speed = ETH_SPEED_10M;
  537. LOG_D("10Mbps");
  538. }
  539. if(phy_speed_new & PHY_FULL_DUPLEX)
  540. {
  541. LOG_D("full-duplex\r\n");
  542. apm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
  543. }
  544. else
  545. {
  546. LOG_D("half-duplex\r\n");
  547. apm32_eth_device.ETH_Mode = ETH_MODE_HALFDUPLEX;
  548. }
  549. rt_apm32_eth_init((rt_device_t)&apm32_eth_device);
  550. /* send link up. */
  551. eth_device_linkchange(&apm32_eth_device.parent, RT_TRUE);
  552. } /* link up. */
  553. else
  554. {
  555. LOG_I("link down\r\n");
  556. /* send link down. */
  557. eth_device_linkchange(&apm32_eth_device.parent, RT_FALSE);
  558. } /* link down. */
  559. phy_speed = phy_speed_new;
  560. } /* linkchange */
  561. }
  562. static void phy_monitor_thread_entry(void *parameter)
  563. {
  564. uint8_t detected_count = 0;
  565. while(phy_addr == 0xFF)
  566. {
  567. /* phy search */
  568. rt_uint32_t i, temp;
  569. for (i = 0; i <= 0x1F; i++)
  570. {
  571. temp = ETH_ReadPHYRegister(i, PHY_ID1_REG);
  572. if (temp != 0xFFFF && temp != 0x00)
  573. {
  574. phy_addr = i;
  575. break;
  576. }
  577. }
  578. detected_count++;
  579. rt_thread_mdelay(1000);
  580. if (detected_count > 10)
  581. {
  582. LOG_E("No PHY device was detected, please check hardware!");
  583. }
  584. }
  585. LOG_D("Found a phy, address:0x%02X", phy_addr);
  586. /* RESET PHY */
  587. LOG_D("RESET PHY!\r\n");
  588. ETH_WritePHYRegister(phy_addr, PHY_BCR, PHY_RESET);
  589. rt_thread_delay(RT_TICK_PER_SECOND * 2);
  590. ETH_WritePHYRegister(phy_addr, PHY_BCR, PHY_AUTONEGOTIATION);
  591. phy_linkchange();
  592. apm32_eth_device.poll_link_timer = rt_timer_create("phylnk", (void (*)(void*))phy_linkchange,
  593. NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC);
  594. if (!apm32_eth_device.poll_link_timer || rt_timer_start(apm32_eth_device.poll_link_timer) != RT_EOK)
  595. {
  596. LOG_E("Start link change detection timer failed");
  597. }
  598. }
  599. static int rt_hw_apm32_eth_init(void)
  600. {
  601. /* reset phy */
  602. extern void phy_reset(void);
  603. phy_reset();
  604. /* apm32 eth gpio init */
  605. extern void apm32_msp_eth_init(void *instance);
  606. apm32_msp_eth_init(RT_NULL);
  607. apm32_eth_device.ETH_Speed = ETH_SPEED_100M;
  608. apm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
  609. /* set mac address. */
  610. apm32_eth_device.dev_addr[0] = 0x00;
  611. apm32_eth_device.dev_addr[1] = 0x00;
  612. apm32_eth_device.dev_addr[2] = 0x00;
  613. apm32_eth_device.dev_addr[3] = 0x00;
  614. apm32_eth_device.dev_addr[4] = 0x00;
  615. apm32_eth_device.dev_addr[5] = 0x08;
  616. apm32_eth_device.parent.parent.init = rt_apm32_eth_init;
  617. apm32_eth_device.parent.parent.open = rt_apm32_eth_open;
  618. apm32_eth_device.parent.parent.close = rt_apm32_eth_close;
  619. apm32_eth_device.parent.parent.read = rt_apm32_eth_read;
  620. apm32_eth_device.parent.parent.write = rt_apm32_eth_write;
  621. apm32_eth_device.parent.parent.control = rt_apm32_eth_control;
  622. apm32_eth_device.parent.parent.user_data = RT_NULL;
  623. apm32_eth_device.parent.eth_rx = rt_apm32_eth_rx;
  624. apm32_eth_device.parent.eth_tx = rt_apm32_eth_tx;
  625. /* init tx semaphore */
  626. rt_sem_init(&tx_wait, "tx_wait", 0, RT_IPC_FLAG_FIFO);
  627. /* register eth device */
  628. eth_device_init(&(apm32_eth_device.parent), "e0");
  629. /* start phy monitor */
  630. {
  631. rt_thread_t tid;
  632. tid = rt_thread_create("phy",
  633. phy_monitor_thread_entry,
  634. RT_NULL,
  635. 512,
  636. RT_THREAD_PRIORITY_MAX - 2,
  637. 2);
  638. if (tid != RT_NULL)
  639. rt_thread_startup(tid);
  640. }
  641. return RT_EOK;
  642. }
  643. INIT_DEVICE_EXPORT(rt_hw_apm32_eth_init);
  644. #endif /* BSP_USING_ETH */