drv_eth.c 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  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. * 2017-06-08 tanek first implementation
  9. */
  10. #include <rtthread.h>
  11. #include "board.h"
  12. #include <rtdevice.h>
  13. #ifdef RT_USING_FINSH
  14. #include <finsh.h>
  15. #endif
  16. #include "fsl_enet.h"
  17. #include "fsl_gpio.h"
  18. #include "fsl_iomuxc.h"
  19. #include "fsl_phy.h"
  20. #include "fsl_cache.h"
  21. #ifdef RT_USING_LWIP
  22. #include <netif/ethernetif.h>
  23. #include "lwipopts.h"
  24. #ifdef BOARD_RT1050_ATK
  25. #include "drv_pcf8574.h"
  26. #endif
  27. #define ENET_RXBD_NUM (4)
  28. #define ENET_TXBD_NUM (4)
  29. #define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN)
  30. #define ENET_TXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN)
  31. #if defined(BOARD_RT1050_FIRE) || defined(BOARD_RT1050_ATK)
  32. #define PHY_ADDRESS 0x00u
  33. #endif
  34. #if defined(BOARD_RT1050_EVK)
  35. #define PHY_ADDRESS 0x02u
  36. #endif
  37. /* debug option */
  38. //#define ETH_RX_DUMP
  39. //#define ETH_TX_DUMP
  40. #define DBG_ENABLE
  41. #define DBG_SECTION_NAME "ETH"
  42. #define DBG_COLOR
  43. #define DBG_LEVEL DBG_INFO
  44. #include <rtdbg.h>
  45. #define MAX_ADDR_LEN 6
  46. struct rt_imxrt_eth
  47. {
  48. /* inherit from ethernet device */
  49. struct eth_device parent;
  50. enet_handle_t enet_handle;
  51. ENET_Type *enet_base;
  52. enet_data_error_stats_t error_statistic;
  53. rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
  54. rt_bool_t tx_is_waiting;
  55. struct rt_semaphore tx_wait;
  56. enet_mii_speed_t speed;
  57. enet_mii_duplex_t duplex;
  58. };
  59. ALIGN(ENET_BUFF_ALIGNMENT) enet_tx_bd_struct_t g_txBuffDescrip[ENET_TXBD_NUM] SECTION("NonCacheable");
  60. ALIGN(ENET_BUFF_ALIGNMENT) rt_uint8_t g_txDataBuff[ENET_TXBD_NUM][RT_ALIGN(ENET_TXBUFF_SIZE, ENET_BUFF_ALIGNMENT)];
  61. ALIGN(ENET_BUFF_ALIGNMENT) enet_rx_bd_struct_t g_rxBuffDescrip[ENET_RXBD_NUM] SECTION("NonCacheable");
  62. ALIGN(ENET_BUFF_ALIGNMENT) rt_uint8_t g_rxDataBuff[ENET_RXBD_NUM][RT_ALIGN(ENET_RXBUFF_SIZE, ENET_BUFF_ALIGNMENT)];
  63. static struct rt_imxrt_eth imxrt_eth_device;
  64. void _enet_rx_callback(struct rt_imxrt_eth *eth)
  65. {
  66. rt_err_t result;
  67. ENET_DisableInterrupts(eth->enet_base, kENET_RxFrameInterrupt);
  68. result = eth_device_ready(&(eth->parent));
  69. if (result != RT_EOK)
  70. rt_kprintf("RX err =%d\n", result);
  71. }
  72. void _enet_tx_callback(struct rt_imxrt_eth *eth)
  73. {
  74. if (eth->tx_is_waiting == RT_TRUE)
  75. {
  76. eth->tx_is_waiting = RT_FALSE;
  77. rt_sem_release(&eth->tx_wait);
  78. }
  79. }
  80. void _enet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *userData)
  81. {
  82. switch (event)
  83. {
  84. case kENET_RxEvent:
  85. _enet_rx_callback((struct rt_imxrt_eth *)userData);
  86. break;
  87. case kENET_TxEvent:
  88. _enet_tx_callback((struct rt_imxrt_eth *)userData);
  89. break;
  90. case kENET_ErrEvent:
  91. //rt_kprintf("kENET_ErrEvent\n");
  92. break;
  93. case kENET_WakeUpEvent:
  94. //rt_kprintf("kENET_WakeUpEvent\n");
  95. break;
  96. case kENET_TimeStampEvent:
  97. //rt_kprintf("kENET_TimeStampEvent\n");
  98. break;
  99. case kENET_TimeStampAvailEvent:
  100. //rt_kprintf("kENET_TimeStampAvailEvent \n");
  101. break;
  102. default:
  103. //rt_kprintf("unknow error\n");
  104. break;
  105. }
  106. }
  107. #if defined(BOARD_RT1050_EVK)
  108. static void evk_enet_io_init(void)
  109. {
  110. CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
  111. IOMUXC_SetPinMux(
  112. IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 is configured as GPIO1_IO09 */
  113. 0U); /* Software Input On Field: Input Path is determined by functionality */
  114. IOMUXC_SetPinMux(
  115. IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 is configured as GPIO1_IO10 */
  116. 0U); /* Software Input On Field: Input Path is determined by functionality */
  117. IOMUXC_SetPinMux(
  118. IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 is configured as LPUART1_TX */
  119. 0U); /* Software Input On Field: Input Path is determined by functionality */
  120. IOMUXC_SetPinMux(
  121. IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 is configured as LPUART1_RX */
  122. 0U); /* Software Input On Field: Input Path is determined by functionality */
  123. IOMUXC_SetPinMux(
  124. IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 is configured as ENET_RX_DATA00 */
  125. 0U); /* Software Input On Field: Input Path is determined by functionality */
  126. IOMUXC_SetPinMux(
  127. IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 is configured as ENET_RX_DATA01 */
  128. 0U); /* Software Input On Field: Input Path is determined by functionality */
  129. IOMUXC_SetPinMux(
  130. IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 is configured as ENET_RX_EN */
  131. 0U); /* Software Input On Field: Input Path is determined by functionality */
  132. IOMUXC_SetPinMux(
  133. IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 is configured as ENET_TX_DATA00 */
  134. 0U); /* Software Input On Field: Input Path is determined by functionality */
  135. IOMUXC_SetPinMux(
  136. IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 is configured as ENET_TX_DATA01 */
  137. 0U); /* Software Input On Field: Input Path is determined by functionality */
  138. IOMUXC_SetPinMux(
  139. IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 is configured as ENET_TX_EN */
  140. 0U); /* Software Input On Field: Input Path is determined by functionality */
  141. IOMUXC_SetPinMux(
  142. IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 is configured as ENET_REF_CLK */
  143. 1U); /* Software Input On Field: Force input path of pad GPIO_B1_10 */
  144. IOMUXC_SetPinMux(
  145. IOMUXC_GPIO_B1_11_ENET_RX_ER, /* GPIO_B1_11 is configured as ENET_RX_ER */
  146. 0U); /* Software Input On Field: Input Path is determined by functionality */
  147. IOMUXC_SetPinMux(
  148. IOMUXC_GPIO_EMC_40_ENET_MDC, /* GPIO_EMC_40 is configured as ENET_MDC */
  149. 0U); /* Software Input On Field: Input Path is determined by functionality */
  150. IOMUXC_SetPinMux(
  151. IOMUXC_GPIO_EMC_41_ENET_MDIO, /* GPIO_EMC_41 is configured as ENET_MDIO */
  152. 0U); /* Software Input On Field: Input Path is determined by functionality */
  153. IOMUXC_SetPinConfig(
  154. IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 PAD functional properties : */
  155. 0xB0A9u); /* Slew Rate Field: Fast Slew Rate
  156. Drive Strength Field: R0/5
  157. Speed Field: medium(100MHz)
  158. Open Drain Enable Field: Open Drain Disabled
  159. Pull / Keep Enable Field: Pull/Keeper Enabled
  160. Pull / Keep Select Field: Pull
  161. Pull Up / Down Config. Field: 100K Ohm Pull Up
  162. Hyst. Enable Field: Hysteresis Disabled */
  163. IOMUXC_SetPinConfig(
  164. IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 PAD functional properties : */
  165. 0xB0A9u); /* Slew Rate Field: Fast Slew Rate
  166. Drive Strength Field: R0/5
  167. Speed Field: medium(100MHz)
  168. Open Drain Enable Field: Open Drain Disabled
  169. Pull / Keep Enable Field: Pull/Keeper Enabled
  170. Pull / Keep Select Field: Pull
  171. Pull Up / Down Config. Field: 100K Ohm Pull Up
  172. Hyst. Enable Field: Hysteresis Disabled */
  173. IOMUXC_SetPinConfig(
  174. IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 PAD functional properties : */
  175. 0x10B0u); /* Slew Rate Field: Slow Slew Rate
  176. Drive Strength Field: R0/6
  177. Speed Field: medium(100MHz)
  178. Open Drain Enable Field: Open Drain Disabled
  179. Pull / Keep Enable Field: Pull/Keeper Enabled
  180. Pull / Keep Select Field: Keeper
  181. Pull Up / Down Config. Field: 100K Ohm Pull Down
  182. Hyst. Enable Field: Hysteresis Disabled */
  183. IOMUXC_SetPinConfig(
  184. IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 PAD functional properties : */
  185. 0x10B0u); /* Slew Rate Field: Slow Slew Rate
  186. Drive Strength Field: R0/6
  187. Speed Field: medium(100MHz)
  188. Open Drain Enable Field: Open Drain Disabled
  189. Pull / Keep Enable Field: Pull/Keeper Enabled
  190. Pull / Keep Select Field: Keeper
  191. Pull Up / Down Config. Field: 100K Ohm Pull Down
  192. Hyst. Enable Field: Hysteresis Disabled */
  193. IOMUXC_SetPinConfig(
  194. IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 PAD functional properties : */
  195. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  196. Drive Strength Field: R0/5
  197. Speed Field: max(200MHz)
  198. Open Drain Enable Field: Open Drain Disabled
  199. Pull / Keep Enable Field: Pull/Keeper Enabled
  200. Pull / Keep Select Field: Pull
  201. Pull Up / Down Config. Field: 100K Ohm Pull Up
  202. Hyst. Enable Field: Hysteresis Disabled */
  203. IOMUXC_SetPinConfig(
  204. IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 PAD functional properties : */
  205. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  206. Drive Strength Field: R0/5
  207. Speed Field: max(200MHz)
  208. Open Drain Enable Field: Open Drain Disabled
  209. Pull / Keep Enable Field: Pull/Keeper Enabled
  210. Pull / Keep Select Field: Pull
  211. Pull Up / Down Config. Field: 100K Ohm Pull Up
  212. Hyst. Enable Field: Hysteresis Disabled */
  213. IOMUXC_SetPinConfig(
  214. IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 PAD functional properties : */
  215. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  216. Drive Strength Field: R0/5
  217. Speed Field: max(200MHz)
  218. Open Drain Enable Field: Open Drain Disabled
  219. Pull / Keep Enable Field: Pull/Keeper Enabled
  220. Pull / Keep Select Field: Pull
  221. Pull Up / Down Config. Field: 100K Ohm Pull Up
  222. Hyst. Enable Field: Hysteresis Disabled */
  223. IOMUXC_SetPinConfig(
  224. IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 PAD functional properties : */
  225. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  226. Drive Strength Field: R0/5
  227. Speed Field: max(200MHz)
  228. Open Drain Enable Field: Open Drain Disabled
  229. Pull / Keep Enable Field: Pull/Keeper Enabled
  230. Pull / Keep Select Field: Pull
  231. Pull Up / Down Config. Field: 100K Ohm Pull Up
  232. Hyst. Enable Field: Hysteresis Disabled */
  233. IOMUXC_SetPinConfig(
  234. IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 PAD functional properties : */
  235. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  236. Drive Strength Field: R0/5
  237. Speed Field: max(200MHz)
  238. Open Drain Enable Field: Open Drain Disabled
  239. Pull / Keep Enable Field: Pull/Keeper Enabled
  240. Pull / Keep Select Field: Pull
  241. Pull Up / Down Config. Field: 100K Ohm Pull Up
  242. Hyst. Enable Field: Hysteresis Disabled */
  243. IOMUXC_SetPinConfig(
  244. IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 PAD functional properties : */
  245. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  246. Drive Strength Field: R0/5
  247. Speed Field: max(200MHz)
  248. Open Drain Enable Field: Open Drain Disabled
  249. Pull / Keep Enable Field: Pull/Keeper Enabled
  250. Pull / Keep Select Field: Pull
  251. Pull Up / Down Config. Field: 100K Ohm Pull Up
  252. Hyst. Enable Field: Hysteresis Disabled */
  253. IOMUXC_SetPinConfig(
  254. IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 PAD functional properties : */
  255. 0x31u); /* Slew Rate Field: Fast Slew Rate
  256. Drive Strength Field: R0/6
  257. Speed Field: low(50MHz)
  258. Open Drain Enable Field: Open Drain Disabled
  259. Pull / Keep Enable Field: Pull/Keeper Disabled
  260. Pull / Keep Select Field: Keeper
  261. Pull Up / Down Config. Field: 100K Ohm Pull Down
  262. Hyst. Enable Field: Hysteresis Disabled */
  263. IOMUXC_SetPinConfig(
  264. IOMUXC_GPIO_B1_11_ENET_RX_ER, /* GPIO_B1_11 PAD functional properties : */
  265. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  266. Drive Strength Field: R0/5
  267. Speed Field: max(200MHz)
  268. Open Drain Enable Field: Open Drain Disabled
  269. Pull / Keep Enable Field: Pull/Keeper Enabled
  270. Pull / Keep Select Field: Pull
  271. Pull Up / Down Config. Field: 100K Ohm Pull Up
  272. Hyst. Enable Field: Hysteresis Disabled */
  273. IOMUXC_SetPinConfig(
  274. IOMUXC_GPIO_EMC_40_ENET_MDC, /* GPIO_EMC_40 PAD functional properties : */
  275. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  276. Drive Strength Field: R0/5
  277. Speed Field: max(200MHz)
  278. Open Drain Enable Field: Open Drain Disabled
  279. Pull / Keep Enable Field: Pull/Keeper Enabled
  280. Pull / Keep Select Field: Pull
  281. Pull Up / Down Config. Field: 100K Ohm Pull Up
  282. Hyst. Enable Field: Hysteresis Disabled */
  283. IOMUXC_SetPinConfig(
  284. IOMUXC_GPIO_EMC_41_ENET_MDIO, /* GPIO_EMC_41 PAD functional properties : */
  285. 0xB829u); /* Slew Rate Field: Fast Slew Rate
  286. Drive Strength Field: R0/5
  287. Speed Field: low(50MHz)
  288. Open Drain Enable Field: Open Drain Enabled
  289. Pull / Keep Enable Field: Pull/Keeper Enabled
  290. Pull / Keep Select Field: Pull
  291. Pull Up / Down Config. Field: 100K Ohm Pull Up
  292. Hyst. Enable Field: Hysteresis Disabled */
  293. }
  294. #endif
  295. #ifdef BOARD_RT1050_ATK
  296. static void atk_enet_io_init(void)
  297. {
  298. CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
  299. IOMUXC_SetPinMux(
  300. IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 is configured as ENET_RX_DATA00 */
  301. 0U); /* Software Input On Field: Input Path is determined by functionality */
  302. IOMUXC_SetPinMux(
  303. IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 is configured as ENET_RX_DATA01 */
  304. 0U); /* Software Input On Field: Input Path is determined by functionality */
  305. IOMUXC_SetPinMux(
  306. IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 is configured as ENET_RX_EN */
  307. 0U); /* Software Input On Field: Input Path is determined by functionality */
  308. IOMUXC_SetPinMux(
  309. IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 is configured as ENET_TX_DATA00 */
  310. 0U); /* Software Input On Field: Input Path is determined by functionality */
  311. IOMUXC_SetPinMux(
  312. IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 is configured as ENET_TX_DATA01 */
  313. 0U); /* Software Input On Field: Input Path is determined by functionality */
  314. IOMUXC_SetPinMux(
  315. IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 is configured as ENET_TX_EN */
  316. 0U); /* Software Input On Field: Input Path is determined by functionality */
  317. IOMUXC_SetPinMux(
  318. IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 is configured as ENET_REF_CLK */
  319. 1U); /* Software Input On Field: Force input path of pad GPIO_B1_10 */
  320. IOMUXC_SetPinMux(
  321. IOMUXC_GPIO_B1_14_ENET_MDC, /* GPIO_EMC_40 is configured as ENET_MDC */
  322. 0); /* Software Input On Field: Input Path is determined by functionality */
  323. IOMUXC_SetPinMux(
  324. IOMUXC_GPIO_B1_15_ENET_MDIO, /* GPIO_EMC_41 is configured as ENET_MDIO */
  325. 0); /* Software Input On Field: Input Path is determined by functionality */
  326. IOMUXC_SetPinConfig(
  327. IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 PAD functional properties : */
  328. 0x110F9);
  329. IOMUXC_SetPinConfig(
  330. IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 PAD functional properties : */
  331. 0x110F9);
  332. IOMUXC_SetPinConfig(
  333. IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 PAD functional properties : */
  334. 0x110F9);
  335. IOMUXC_SetPinConfig(
  336. IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 PAD functional properties : */
  337. 0x110F9);
  338. IOMUXC_SetPinConfig(
  339. IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 PAD functional properties : */
  340. 0x110F9);
  341. IOMUXC_SetPinConfig(
  342. IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 PAD functional properties : */
  343. 0x110F9);
  344. IOMUXC_SetPinConfig(
  345. IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 PAD functional properties : */
  346. 0x110F9);
  347. IOMUXC_SetPinConfig(
  348. IOMUXC_GPIO_B1_14_ENET_MDC,
  349. 0x110F9);
  350. IOMUXC_SetPinConfig(
  351. IOMUXC_GPIO_B1_15_ENET_MDIO,
  352. 0x110F9);
  353. IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true);
  354. IOMUXC_GPR->GPR1 |= 1 << 23;
  355. }
  356. #endif
  357. #ifdef BOARD_RT1050_FIRE
  358. static void fire_enet_io_init(void)
  359. {
  360. CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
  361. IOMUXC_SetPinMux(
  362. IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 is configured as GPIO1_IO09 */
  363. 0U); /* Software Input On Field: Input Path is determined by functionality */
  364. IOMUXC_SetPinMux(
  365. IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 is configured as GPIO1_IO10 */
  366. 0U); /* Software Input On Field: Input Path is determined by functionality */
  367. IOMUXC_SetPinMux(
  368. IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 is configured as LPUART1_TX */
  369. 0U); /* Software Input On Field: Input Path is determined by functionality */
  370. IOMUXC_SetPinMux(
  371. IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 is configured as LPUART1_RX */
  372. 0U); /* Software Input On Field: Input Path is determined by functionality */
  373. IOMUXC_SetPinMux(
  374. IOMUXC_GPIO_B1_11_ENET_RX_ER, /* GPIO_B1_11 is configured as ENET_RX_ER */
  375. 0U); /* Software Input On Field: Input Path is determined by functionality */
  376. IOMUXC_SetPinMux(
  377. IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 is configured as ENET_RX_DATA00 */
  378. 0U); /* Software Input On Field: Input Path is determined by functionality */
  379. IOMUXC_SetPinMux(
  380. IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 is configured as ENET_RX_DATA01 */
  381. 0U); /* Software Input On Field: Input Path is determined by functionality */
  382. IOMUXC_SetPinMux(
  383. IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 is configured as ENET_RX_EN */
  384. 0U); /* Software Input On Field: Input Path is determined by functionality */
  385. IOMUXC_SetPinMux(
  386. IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 is configured as ENET_TX_DATA00 */
  387. 0U); /* Software Input On Field: Input Path is determined by functionality */
  388. IOMUXC_SetPinMux(
  389. IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 is configured as ENET_TX_DATA01 */
  390. 0U); /* Software Input On Field: Input Path is determined by functionality */
  391. IOMUXC_SetPinMux(
  392. IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 is configured as ENET_TX_EN */
  393. 0U); /* Software Input On Field: Input Path is determined by functionality */
  394. IOMUXC_SetPinMux(
  395. IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 is configured as ENET_REF_CLK */
  396. 1U); /* Software Input On Field: Force input path of pad GPIO_B1_10 */
  397. IOMUXC_SetPinMux(
  398. IOMUXC_GPIO_AD_B1_04_ENET_MDC, /* GPIO_EMC_40 is configured as ENET_MDC */
  399. 0U); /* Software Input On Field: Input Path is determined by functionality */
  400. IOMUXC_SetPinMux(
  401. IOMUXC_GPIO_B1_15_ENET_MDIO, /* GPIO_EMC_41 is configured as ENET_MDIO */
  402. 0U); /* Software Input On Field: Input Path is determined by functionality */
  403. IOMUXC_SetPinConfig(
  404. IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 PAD functional properties : */
  405. 0xB0A9u); /* Slew Rate Field: Fast Slew Rate
  406. Drive Strength Field: R0/5
  407. Speed Field: medium(100MHz)
  408. Open Drain Enable Field: Open Drain Disabled
  409. Pull / Keep Enable Field: Pull/Keeper Enabled
  410. Pull / Keep Select Field: Pull
  411. Pull Up / Down Config. Field: 100K Ohm Pull Up
  412. Hyst. Enable Field: Hysteresis Disabled */
  413. IOMUXC_SetPinConfig(
  414. IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 PAD functional properties : */
  415. 0xB0A9u); /* Slew Rate Field: Fast Slew Rate
  416. Drive Strength Field: R0/5
  417. Speed Field: medium(100MHz)
  418. Open Drain Enable Field: Open Drain Disabled
  419. Pull / Keep Enable Field: Pull/Keeper Enabled
  420. Pull / Keep Select Field: Pull
  421. Pull Up / Down Config. Field: 100K Ohm Pull Up
  422. Hyst. Enable Field: Hysteresis Disabled */
  423. IOMUXC_SetPinConfig(
  424. IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 PAD functional properties : */
  425. 0x10B0u); /* Slew Rate Field: Slow Slew Rate
  426. Drive Strength Field: R0/6
  427. Speed Field: medium(100MHz)
  428. Open Drain Enable Field: Open Drain Disabled
  429. Pull / Keep Enable Field: Pull/Keeper Enabled
  430. Pull / Keep Select Field: Keeper
  431. Pull Up / Down Config. Field: 100K Ohm Pull Down
  432. Hyst. Enable Field: Hysteresis Disabled */
  433. IOMUXC_SetPinConfig(
  434. IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 PAD functional properties : */
  435. 0x10B0u); /* Slew Rate Field: Slow Slew Rate
  436. Drive Strength Field: R0/6
  437. Speed Field: medium(100MHz)
  438. Open Drain Enable Field: Open Drain Disabled
  439. Pull / Keep Enable Field: Pull/Keeper Enabled
  440. Pull / Keep Select Field: Keeper
  441. Pull Up / Down Config. Field: 100K Ohm Pull Down
  442. Hyst. Enable Field: Hysteresis Disabled */
  443. IOMUXC_SetPinConfig(
  444. IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 PAD functional properties : */
  445. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  446. Drive Strength Field: R0/5
  447. Speed Field: max(200MHz)
  448. Open Drain Enable Field: Open Drain Disabled
  449. Pull / Keep Enable Field: Pull/Keeper Enabled
  450. Pull / Keep Select Field: Pull
  451. Pull Up / Down Config. Field: 100K Ohm Pull Up
  452. Hyst. Enable Field: Hysteresis Disabled */
  453. IOMUXC_SetPinConfig(
  454. IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 PAD functional properties : */
  455. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  456. Drive Strength Field: R0/5
  457. Speed Field: max(200MHz)
  458. Open Drain Enable Field: Open Drain Disabled
  459. Pull / Keep Enable Field: Pull/Keeper Enabled
  460. Pull / Keep Select Field: Pull
  461. Pull Up / Down Config. Field: 100K Ohm Pull Up
  462. Hyst. Enable Field: Hysteresis Disabled */
  463. IOMUXC_SetPinConfig(
  464. IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 PAD functional properties : */
  465. 0xB0E9u);
  466. /* Slew Rate Field: Fast Slew Rate
  467. Drive Strength Field: R0/5
  468. Speed Field: max(200MHz)
  469. Open Drain Enable Field: Open Drain Disabled
  470. Pull / Keep Enable Field: Pull/Keeper Enabled
  471. Pull / Keep Select Field: Pull
  472. Pull Up / Down Config. Field: 100K Ohm Pull Up
  473. Hyst. Enable Field: Hysteresis Disabled */
  474. IOMUXC_SetPinConfig(
  475. IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 PAD functional properties : */
  476. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  477. Drive Strength Field: R0/5
  478. Speed Field: max(200MHz)
  479. Open Drain Enable Field: Open Drain Disabled
  480. Pull / Keep Enable Field: Pull/Keeper Enabled
  481. Pull / Keep Select Field: Pull
  482. Pull Up / Down Config. Field: 100K Ohm Pull Up
  483. Hyst. Enable Field: Hysteresis Disabled */
  484. IOMUXC_SetPinConfig(
  485. IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 PAD functional properties : */
  486. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  487. Drive Strength Field: R0/5
  488. Speed Field: max(200MHz)
  489. Open Drain Enable Field: Open Drain Disabled
  490. Pull / Keep Enable Field: Pull/Keeper Enabled
  491. Pull / Keep Select Field: Pull
  492. Pull Up / Down Config. Field: 100K Ohm Pull Up
  493. Hyst. Enable Field: Hysteresis Disabled */
  494. IOMUXC_SetPinConfig(
  495. IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 PAD functional properties : */
  496. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  497. Drive Strength Field: R0/5
  498. Speed Field: max(200MHz)
  499. Open Drain Enable Field: Open Drain Disabled
  500. Pull / Keep Enable Field: Pull/Keeper Enabled
  501. Pull / Keep Select Field: Pull
  502. Pull Up / Down Config. Field: 100K Ohm Pull Up
  503. Hyst. Enable Field: Hysteresis Disabled */
  504. IOMUXC_SetPinConfig(
  505. IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 PAD functional properties : */
  506. 0x31u); /* Slew Rate Field: Fast Slew Rate
  507. Drive Strength Field: R0/6
  508. Speed Field: low(50MHz)
  509. Open Drain Enable Field: Open Drain Disabled
  510. Pull / Keep Enable Field: Pull/Keeper Disabled
  511. Pull / Keep Select Field: Keeper
  512. Pull Up / Down Config. Field: 100K Ohm Pull Down
  513. Hyst. Enable Field: Hysteresis Disabled */
  514. IOMUXC_SetPinConfig(
  515. IOMUXC_GPIO_B1_11_ENET_RX_ER, /* GPIO_B1_11 PAD functional properties : */
  516. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  517. Drive Strength Field: R0/5
  518. Speed Field: max(200MHz)
  519. Open Drain Enable Field: Open Drain Disabled
  520. Pull / Keep Enable Field: Pull/Keeper Enabled
  521. Pull / Keep Select Field: Pull
  522. Pull Up / Down Config. Field: 100K Ohm Pull Up
  523. Hyst. Enable Field: Hysteresis Disabled */
  524. IOMUXC_SetPinConfig(
  525. IOMUXC_GPIO_AD_B1_04_ENET_MDC,
  526. 0xB0E9u); /* Slew Rate Field: Fast Slew Rate
  527. Drive Strength Field: R0/5
  528. Speed Field: max(200MHz)
  529. Open Drain Enable Field: Open Drain Disabled
  530. Pull / Keep Enable Field: Pull/Keeper Enabled
  531. Pull / Keep Select Field: Pull
  532. Pull Up / Down Config. Field: 100K Ohm Pull Up
  533. Hyst. Enable Field: Hysteresis Disabled */
  534. IOMUXC_SetPinConfig(
  535. IOMUXC_GPIO_B1_15_ENET_MDIO,
  536. 0xB829u); /* Slew Rate Field: Fast Slew Rate
  537. Drive Strength Field: R0/5
  538. Speed Field: low(50MHz)
  539. Open Drain Enable Field: Open Drain Enabled
  540. Pull / Keep Enable Field: Pull/Keeper Enabled
  541. Pull / Keep Select Field: Pull
  542. Pull Up / Down Config. Field: 100K Ohm Pull Up
  543. Hyst. Enable Field: Hysteresis Disabled */
  544. }
  545. #endif
  546. static void _enet_clk_init(void)
  547. {
  548. const clock_enet_pll_config_t config = {true, false, 1};
  549. CLOCK_InitEnetPll(&config);
  550. IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true);
  551. }
  552. static void _delay(void)
  553. {
  554. volatile int i = 1000000;
  555. while (i--)
  556. i = i;
  557. }
  558. static void _enet_phy_reset_by_gpio(void)
  559. {
  560. gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
  561. #ifndef BOARD_RT1050_ATK
  562. GPIO_PinInit(GPIO1, 9, &gpio_config);
  563. #endif
  564. GPIO_PinInit(GPIO1, 10, &gpio_config);
  565. /* pull up the ENET_INT before RESET. */
  566. GPIO_WritePinOutput(GPIO1, 10, 1);
  567. #ifdef BOARD_RT1050_ATK
  568. pcf8574_write_bit(7, 1);
  569. _delay();
  570. pcf8574_write_bit(7, 0);
  571. #else
  572. GPIO_WritePinOutput(GPIO1, 9, 0);
  573. _delay();
  574. GPIO_WritePinOutput(GPIO1, 9, 1);
  575. #endif
  576. }
  577. static void _enet_config(void)
  578. {
  579. enet_config_t config;
  580. uint32_t sysClock;
  581. /* prepare the buffer configuration. */
  582. enet_buffer_config_t buffConfig =
  583. {
  584. ENET_RXBD_NUM,
  585. ENET_TXBD_NUM,
  586. SDK_SIZEALIGN(ENET_RXBUFF_SIZE, ENET_BUFF_ALIGNMENT),
  587. SDK_SIZEALIGN(ENET_TXBUFF_SIZE, ENET_BUFF_ALIGNMENT),
  588. &g_rxBuffDescrip[0],
  589. &g_txBuffDescrip[0],
  590. &g_rxDataBuff[0][0],
  591. &g_txDataBuff[0][0],
  592. };
  593. /* Get default configuration. */
  594. /*
  595. * config.miiMode = kENET_RmiiMode;
  596. * config.miiSpeed = kENET_MiiSpeed100M;
  597. * config.miiDuplex = kENET_MiiFullDuplex;
  598. * config.rxMaxFrameLen = ENET_FRAME_MAX_FRAMELEN;
  599. */
  600. ENET_GetDefaultConfig(&config);
  601. config.interrupt = kENET_TxFrameInterrupt | kENET_RxFrameInterrupt;
  602. //config.interrupt = 0xFFFFFFFF;
  603. config.miiSpeed = imxrt_eth_device.speed;
  604. config.miiDuplex = imxrt_eth_device.duplex;
  605. /* Set SMI to get PHY link status. */
  606. sysClock = CLOCK_GetFreq(kCLOCK_AhbClk);
  607. LOG_D("deinit");
  608. ENET_Deinit(imxrt_eth_device.enet_base);
  609. LOG_D("init");
  610. ENET_Init(imxrt_eth_device.enet_base, &imxrt_eth_device.enet_handle, &config, &buffConfig, &imxrt_eth_device.dev_addr[0], sysClock);
  611. LOG_D("set call back");
  612. ENET_SetCallback(&imxrt_eth_device.enet_handle, _enet_callback, &imxrt_eth_device);
  613. LOG_D("active read");
  614. ENET_ActiveRead(imxrt_eth_device.enet_base);
  615. }
  616. #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
  617. static void packet_dump(const char *msg, const struct pbuf *p)
  618. {
  619. const struct pbuf *q;
  620. rt_uint32_t i, j;
  621. rt_uint8_t *ptr;
  622. rt_kprintf("%s %d byte\n", msg, p->tot_len);
  623. i = 0;
  624. for (q = p; q != RT_NULL; q = q->next)
  625. {
  626. ptr = q->payload;
  627. for (j = 0; j < q->len; j++)
  628. {
  629. if ((i % 8) == 0)
  630. {
  631. rt_kprintf(" ");
  632. }
  633. if ((i % 16) == 0)
  634. {
  635. rt_kprintf("\r\n");
  636. }
  637. rt_kprintf("%02x ", *ptr);
  638. i++;
  639. ptr++;
  640. }
  641. }
  642. rt_kprintf("\n\n");
  643. }
  644. #else
  645. #define packet_dump(...)
  646. #endif /* dump */
  647. /* initialize the interface */
  648. static rt_err_t rt_imxrt_eth_init(rt_device_t dev)
  649. {
  650. LOG_D("rt_imxrt_eth_init...");
  651. _enet_config();
  652. return RT_EOK;
  653. }
  654. static rt_err_t rt_imxrt_eth_open(rt_device_t dev, rt_uint16_t oflag)
  655. {
  656. LOG_D("rt_imxrt_eth_open...");
  657. return RT_EOK;
  658. }
  659. static rt_err_t rt_imxrt_eth_close(rt_device_t dev)
  660. {
  661. LOG_D("rt_imxrt_eth_close...");
  662. return RT_EOK;
  663. }
  664. static rt_size_t rt_imxrt_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  665. {
  666. LOG_D("rt_imxrt_eth_read...");
  667. rt_set_errno(-RT_ENOSYS);
  668. return 0;
  669. }
  670. static rt_size_t rt_imxrt_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  671. {
  672. LOG_D("rt_imxrt_eth_write...");
  673. rt_set_errno(-RT_ENOSYS);
  674. return 0;
  675. }
  676. static rt_err_t rt_imxrt_eth_control(rt_device_t dev, int cmd, void *args)
  677. {
  678. LOG_D("rt_imxrt_eth_control...");
  679. switch (cmd)
  680. {
  681. case NIOCTL_GADDR:
  682. /* get mac address */
  683. if (args) rt_memcpy(args, imxrt_eth_device.dev_addr, 6);
  684. else return -RT_ERROR;
  685. break;
  686. default :
  687. break;
  688. }
  689. return RT_EOK;
  690. }
  691. static void _ENET_ActiveSend(ENET_Type *base, uint32_t ringId)
  692. {
  693. assert(ringId < FSL_FEATURE_ENET_QUEUE);
  694. switch (ringId)
  695. {
  696. case 0:
  697. base->TDAR = ENET_TDAR_TDAR_MASK;
  698. break;
  699. #if FSL_FEATURE_ENET_QUEUE > 1
  700. case kENET_Ring1:
  701. base->TDAR1 = ENET_TDAR1_TDAR_MASK;
  702. break;
  703. case kENET_Ring2:
  704. base->TDAR2 = ENET_TDAR2_TDAR_MASK;
  705. break;
  706. #endif /* FSL_FEATURE_ENET_QUEUE > 1 */
  707. default:
  708. base->TDAR = ENET_TDAR_TDAR_MASK;
  709. break;
  710. }
  711. }
  712. static status_t _ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, const uint8_t *data, uint32_t length)
  713. {
  714. assert(handle);
  715. assert(data);
  716. volatile enet_tx_bd_struct_t *curBuffDescrip;
  717. uint32_t len = 0;
  718. uint32_t sizeleft = 0;
  719. uint32_t address;
  720. /* Check the frame length. */
  721. if (length > ENET_FRAME_MAX_FRAMELEN)
  722. {
  723. return kStatus_ENET_TxFrameOverLen;
  724. }
  725. /* Check if the transmit buffer is ready. */
  726. curBuffDescrip = handle->txBdCurrent[0];
  727. if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK)
  728. {
  729. return kStatus_ENET_TxFrameBusy;
  730. }
  731. #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
  732. bool isPtpEventMessage = false;
  733. /* Check PTP message with the PTP header. */
  734. isPtpEventMessage = ENET_Ptp1588ParseFrame(data, NULL, true);
  735. #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
  736. /* One transmit buffer is enough for one frame. */
  737. if (handle->txBuffSizeAlign[0] >= length)
  738. {
  739. /* Copy data to the buffer for uDMA transfer. */
  740. #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
  741. address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer,kMEMORY_DMA2Local);
  742. #else
  743. address = (uint32_t)curBuffDescrip->buffer;
  744. #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
  745. pbuf_copy_partial((const struct pbuf *)data, (void *)address, length, 0);
  746. /* Set data length. */
  747. curBuffDescrip->length = length;
  748. #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
  749. /* For enable the timestamp. */
  750. if (isPtpEventMessage)
  751. {
  752. curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK;
  753. }
  754. else
  755. {
  756. curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK;
  757. }
  758. #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
  759. curBuffDescrip->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK);
  760. /* Increase the buffer descriptor address. */
  761. if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK)
  762. {
  763. handle->txBdCurrent[0] = handle->txBdBase[0];
  764. }
  765. else
  766. {
  767. handle->txBdCurrent[0]++;
  768. }
  769. #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
  770. /* Add the cache clean maintain. */
  771. #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
  772. address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer,kMEMORY_DMA2Local);
  773. #else
  774. address = (uint32_t)curBuffDescrip->buffer;
  775. #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
  776. DCACHE_CleanByRange(address, length);
  777. #endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */
  778. /* Active the transmit buffer descriptor. */
  779. _ENET_ActiveSend(base, 0);
  780. return kStatus_Success;
  781. }
  782. else
  783. {
  784. /* One frame requires more than one transmit buffers. */
  785. do
  786. {
  787. #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
  788. /* For enable the timestamp. */
  789. if (isPtpEventMessage)
  790. {
  791. curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK;
  792. }
  793. else
  794. {
  795. curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK;
  796. }
  797. #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
  798. /* Increase the buffer descriptor address. */
  799. if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK)
  800. {
  801. handle->txBdCurrent[0] = handle->txBdBase[0];
  802. }
  803. else
  804. {
  805. handle->txBdCurrent[0]++;
  806. }
  807. /* update the size left to be transmit. */
  808. sizeleft = length - len;
  809. if (sizeleft > handle->txBuffSizeAlign[0])
  810. {
  811. /* Data copy. */
  812. #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
  813. address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer,kMEMORY_DMA2Local);
  814. #else
  815. address = (uint32_t)curBuffDescrip->buffer;
  816. #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
  817. memcpy((void *)address, data + len, handle->txBuffSizeAlign[0]);
  818. /* Data length update. */
  819. curBuffDescrip->length = handle->txBuffSizeAlign[0];
  820. len += handle->txBuffSizeAlign[0];
  821. /* Sets the control flag. */
  822. curBuffDescrip->control &= ~ENET_BUFFDESCRIPTOR_TX_LAST_MASK;
  823. curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK;
  824. /* Active the transmit buffer descriptor*/
  825. _ENET_ActiveSend(base, 0);
  826. }
  827. else
  828. {
  829. #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
  830. address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer,kMEMORY_DMA2Local);
  831. #else
  832. address = (uint32_t)curBuffDescrip->buffer;
  833. #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
  834. memcpy((void *)address, data + len, sizeleft);
  835. curBuffDescrip->length = sizeleft;
  836. /* Set Last buffer wrap flag. */
  837. curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK;
  838. #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
  839. /* Add the cache clean maintain. */
  840. #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
  841. address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer,kMEMORY_DMA2Local);
  842. #else
  843. address = (uint32_t)curBuffDescrip->buffer;
  844. #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
  845. DCACHE_CleanByRange(address, handle->txBuffSizeAlign[0]);
  846. #endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */
  847. /* Active the transmit buffer descriptor. */
  848. _ENET_ActiveSend(base, 0);
  849. return kStatus_Success;
  850. }
  851. /* Get the current buffer descriptor address. */
  852. curBuffDescrip = handle->txBdCurrent[0];
  853. }
  854. while (!(curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK));
  855. return kStatus_ENET_TxFrameBusy;
  856. }
  857. }
  858. /* ethernet device interface */
  859. /* transmit packet. */
  860. rt_err_t rt_imxrt_eth_tx(rt_device_t dev, struct pbuf *p)
  861. {
  862. rt_err_t result = RT_EOK;
  863. enet_handle_t * enet_handle = &imxrt_eth_device.enet_handle;
  864. RT_ASSERT(p != NULL);
  865. RT_ASSERT(enet_handle != RT_NULL);
  866. LOG_D("rt_imxrt_eth_tx: %d", p->len);
  867. #ifdef ETH_TX_DUMP
  868. packet_dump("send", p);
  869. #endif
  870. do
  871. {
  872. result = _ENET_SendFrame(imxrt_eth_device.enet_base, enet_handle, (const uint8_t *)p, p->tot_len);
  873. if (result == kStatus_ENET_TxFrameBusy)
  874. {
  875. imxrt_eth_device.tx_is_waiting = RT_TRUE;
  876. rt_sem_take(&imxrt_eth_device.tx_wait, RT_WAITING_FOREVER);
  877. }
  878. }
  879. while (result == kStatus_ENET_TxFrameBusy);
  880. return RT_EOK;
  881. }
  882. /* reception packet. */
  883. struct pbuf *rt_imxrt_eth_rx(rt_device_t dev)
  884. {
  885. uint32_t length = 0;
  886. status_t status;
  887. struct pbuf *p = RT_NULL;
  888. enet_handle_t *enet_handle = &imxrt_eth_device.enet_handle;
  889. ENET_Type *enet_base = imxrt_eth_device.enet_base;
  890. enet_data_error_stats_t *error_statistic = &imxrt_eth_device.error_statistic;
  891. /* Get the Frame size */
  892. status = ENET_GetRxFrameSize(enet_handle, &length);
  893. /* Call ENET_ReadFrame when there is a received frame. */
  894. if (length != 0)
  895. {
  896. /* Received valid frame. Deliver the rx buffer with the size equal to length. */
  897. p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL);
  898. if (p != NULL)
  899. {
  900. status = ENET_ReadFrame(enet_base, enet_handle, p->payload, length);
  901. if (status == kStatus_Success)
  902. {
  903. #ifdef ETH_RX_DUMP
  904. packet_dump("recv", p);
  905. #endif
  906. return p;
  907. }
  908. else
  909. {
  910. LOG_D(" A frame read failed");
  911. pbuf_free(p);
  912. }
  913. }
  914. else
  915. {
  916. LOG_D(" pbuf_alloc faild");
  917. }
  918. }
  919. else if (status == kStatus_ENET_RxFrameError)
  920. {
  921. LOG_W("ENET_GetRxFrameSize: kStatus_ENET_RxFrameError");
  922. /* Update the received buffer when error happened. */
  923. /* Get the error information of the received g_frame. */
  924. ENET_GetRxErrBeforeReadFrame(enet_handle, error_statistic);
  925. /* update the receive buffer. */
  926. ENET_ReadFrame(enet_base, enet_handle, NULL, 0);
  927. }
  928. ENET_EnableInterrupts(enet_base, kENET_RxFrameInterrupt);
  929. return NULL;
  930. }
  931. static void phy_monitor_thread_entry(void *parameter)
  932. {
  933. phy_speed_t speed;
  934. phy_duplex_t duplex;
  935. bool link = false;
  936. _enet_phy_reset_by_gpio();
  937. PHY_Init(imxrt_eth_device.enet_base, PHY_ADDRESS, CLOCK_GetFreq(kCLOCK_AhbClk));
  938. while (1)
  939. {
  940. bool new_link = false;
  941. status_t status = PHY_GetLinkStatus(imxrt_eth_device.enet_base, PHY_ADDRESS, &new_link);
  942. if ((status == kStatus_Success) && (link != new_link))
  943. {
  944. link = new_link;
  945. if (link) // link up
  946. {
  947. PHY_GetLinkSpeedDuplex(imxrt_eth_device.enet_base,
  948. PHY_ADDRESS, &speed, &duplex);
  949. if (kPHY_Speed10M == speed)
  950. {
  951. LOG_D("10M");
  952. }
  953. else
  954. {
  955. LOG_D("100M");
  956. }
  957. if (kPHY_HalfDuplex == duplex)
  958. {
  959. LOG_D("half dumplex");
  960. }
  961. else
  962. {
  963. LOG_D("full dumplex");
  964. }
  965. if ((imxrt_eth_device.speed != (enet_mii_speed_t)speed)
  966. || (imxrt_eth_device.duplex != (enet_mii_duplex_t)duplex))
  967. {
  968. imxrt_eth_device.speed = (enet_mii_speed_t)speed;
  969. imxrt_eth_device.duplex = (enet_mii_duplex_t)duplex;
  970. LOG_D("link up, and update eth mode.");
  971. rt_imxrt_eth_init((rt_device_t)&imxrt_eth_device);
  972. }
  973. else
  974. {
  975. LOG_D("link up, eth not need re-config.");
  976. }
  977. LOG_D("link up.");
  978. eth_device_linkchange(&imxrt_eth_device.parent, RT_TRUE);
  979. }
  980. else // link down
  981. {
  982. LOG_D("link down.");
  983. eth_device_linkchange(&imxrt_eth_device.parent, RT_FALSE);
  984. }
  985. }
  986. rt_thread_delay(RT_TICK_PER_SECOND * 2);
  987. }
  988. }
  989. static int rt_hw_imxrt_eth_init(void)
  990. {
  991. rt_err_t state;
  992. #ifdef BOARD_RT1050_ATK
  993. atk_enet_io_init();
  994. #endif
  995. #ifdef BOARD_RT1050_FIRE
  996. fire_enet_io_init();
  997. #endif
  998. #if defined(BOARD_RT1050_EVK)
  999. evk_enet_io_init();
  1000. #endif
  1001. _enet_clk_init();
  1002. /* OUI 00-80-E1 STMICROELECTRONICS. */
  1003. imxrt_eth_device.dev_addr[0] = 0x00;
  1004. imxrt_eth_device.dev_addr[1] = 0x04;
  1005. imxrt_eth_device.dev_addr[2] = 0x9F;
  1006. /* generate MAC addr from 96bit unique ID (only for test). */
  1007. imxrt_eth_device.dev_addr[3] = 0x08;
  1008. imxrt_eth_device.dev_addr[4] = 0x43;
  1009. imxrt_eth_device.dev_addr[5] = 0x75;
  1010. imxrt_eth_device.speed = kENET_MiiSpeed100M;
  1011. imxrt_eth_device.duplex = kENET_MiiFullDuplex;
  1012. imxrt_eth_device.enet_base = ENET;
  1013. imxrt_eth_device.parent.parent.init = rt_imxrt_eth_init;
  1014. imxrt_eth_device.parent.parent.open = rt_imxrt_eth_open;
  1015. imxrt_eth_device.parent.parent.close = rt_imxrt_eth_close;
  1016. imxrt_eth_device.parent.parent.read = rt_imxrt_eth_read;
  1017. imxrt_eth_device.parent.parent.write = rt_imxrt_eth_write;
  1018. imxrt_eth_device.parent.parent.control = rt_imxrt_eth_control;
  1019. imxrt_eth_device.parent.parent.user_data = RT_NULL;
  1020. imxrt_eth_device.parent.eth_rx = rt_imxrt_eth_rx;
  1021. imxrt_eth_device.parent.eth_tx = rt_imxrt_eth_tx;
  1022. LOG_D("sem init: tx_wait\r");
  1023. /* init tx semaphore */
  1024. rt_sem_init(&imxrt_eth_device.tx_wait, "tx_wait", 0, RT_IPC_FLAG_FIFO);
  1025. /* register eth device */
  1026. LOG_D("eth_device_init start\r");
  1027. state = eth_device_init(&(imxrt_eth_device.parent), "e0");
  1028. if (RT_EOK == state)
  1029. {
  1030. LOG_D("eth_device_init success\r");
  1031. }
  1032. else
  1033. {
  1034. LOG_D("eth_device_init faild: %d\r", state);
  1035. }
  1036. eth_device_linkchange(&imxrt_eth_device.parent, RT_FALSE);
  1037. /* start phy monitor */
  1038. {
  1039. rt_thread_t tid;
  1040. tid = rt_thread_create("phy",
  1041. phy_monitor_thread_entry,
  1042. RT_NULL,
  1043. 512,
  1044. RT_THREAD_PRIORITY_MAX - 2,
  1045. 2);
  1046. if (tid != RT_NULL)
  1047. rt_thread_startup(tid);
  1048. }
  1049. return state;
  1050. }
  1051. #ifdef BOARD_RT1050_ATK
  1052. INIT_ENV_EXPORT(rt_hw_imxrt_eth_init);
  1053. #else
  1054. INIT_DEVICE_EXPORT(rt_hw_imxrt_eth_init);
  1055. #endif
  1056. #endif
  1057. #ifdef RT_USING_FINSH
  1058. #include <finsh.h>
  1059. void phy_read(uint32_t phyReg)
  1060. {
  1061. uint32_t data;
  1062. status_t status;
  1063. status = PHY_Read(imxrt_eth_device.enet_base, PHY_ADDRESS, phyReg, &data);
  1064. if (kStatus_Success == status)
  1065. {
  1066. rt_kprintf("PHY_Read: %02X --> %08X", phyReg, data);
  1067. }
  1068. else
  1069. {
  1070. rt_kprintf("PHY_Read: %02X --> faild", phyReg);
  1071. }
  1072. }
  1073. void phy_write(uint32_t phyReg, uint32_t data)
  1074. {
  1075. status_t status;
  1076. status = PHY_Write(imxrt_eth_device.enet_base, PHY_ADDRESS, phyReg, data);
  1077. if (kStatus_Success == status)
  1078. {
  1079. rt_kprintf("PHY_Write: %02X --> %08X\n", phyReg, data);
  1080. }
  1081. else
  1082. {
  1083. rt_kprintf("PHY_Write: %02X --> faild\n", phyReg);
  1084. }
  1085. }
  1086. void phy_dump(void)
  1087. {
  1088. uint32_t data;
  1089. status_t status;
  1090. int i;
  1091. for (i = 0; i < 32; i++)
  1092. {
  1093. status = PHY_Read(imxrt_eth_device.enet_base, PHY_ADDRESS, i, &data);
  1094. if (kStatus_Success != status)
  1095. {
  1096. rt_kprintf("phy_dump: %02X --> faild", i);
  1097. break;
  1098. }
  1099. if (i % 8 == 7)
  1100. {
  1101. rt_kprintf("%02X --> %08X ", i, data);
  1102. }
  1103. else
  1104. {
  1105. rt_kprintf("%02X --> %08X\n", i, data);
  1106. }
  1107. }
  1108. }
  1109. void enet_reg_dump(void)
  1110. {
  1111. ENET_Type *enet_base = imxrt_eth_device.enet_base;
  1112. #define DUMP_REG(__REG) \
  1113. rt_kprintf("%s(%08X): %08X\n", #__REG, (uint32_t)&enet_base->__REG, enet_base->__REG)
  1114. DUMP_REG(EIR);
  1115. DUMP_REG(EIMR);
  1116. DUMP_REG(RDAR);
  1117. DUMP_REG(TDAR);
  1118. DUMP_REG(ECR);
  1119. DUMP_REG(MMFR);
  1120. DUMP_REG(MSCR);
  1121. DUMP_REG(MIBC);
  1122. DUMP_REG(RCR);
  1123. DUMP_REG(TCR);
  1124. DUMP_REG(PALR);
  1125. DUMP_REG(PAUR);
  1126. DUMP_REG(OPD);
  1127. DUMP_REG(TXIC);
  1128. DUMP_REG(RXIC);
  1129. DUMP_REG(IAUR);
  1130. DUMP_REG(IALR);
  1131. DUMP_REG(GAUR);
  1132. DUMP_REG(GALR);
  1133. DUMP_REG(TFWR);
  1134. DUMP_REG(RDSR);
  1135. DUMP_REG(TDSR);
  1136. DUMP_REG(MRBR);
  1137. DUMP_REG(RSFL);
  1138. DUMP_REG(RSEM);
  1139. DUMP_REG(RAEM);
  1140. DUMP_REG(RAFL);
  1141. DUMP_REG(TSEM);
  1142. DUMP_REG(TAEM);
  1143. DUMP_REG(TAFL);
  1144. DUMP_REG(TIPG);
  1145. DUMP_REG(FTRL);
  1146. DUMP_REG(TACC);
  1147. DUMP_REG(RACC);
  1148. DUMP_REG(RMON_T_DROP);
  1149. DUMP_REG(RMON_T_PACKETS);
  1150. DUMP_REG(RMON_T_BC_PKT);
  1151. DUMP_REG(RMON_T_MC_PKT);
  1152. DUMP_REG(RMON_T_CRC_ALIGN);
  1153. DUMP_REG(RMON_T_UNDERSIZE);
  1154. DUMP_REG(RMON_T_OVERSIZE);
  1155. DUMP_REG(RMON_T_FRAG);
  1156. DUMP_REG(RMON_T_JAB);
  1157. DUMP_REG(RMON_T_COL);
  1158. DUMP_REG(RMON_T_P64);
  1159. DUMP_REG(RMON_T_P65TO127);
  1160. DUMP_REG(RMON_T_P128TO255);
  1161. DUMP_REG(RMON_T_P256TO511);
  1162. DUMP_REG(RMON_T_P512TO1023);
  1163. DUMP_REG(RMON_T_P1024TO2047);
  1164. DUMP_REG(RMON_T_P_GTE2048);
  1165. DUMP_REG(RMON_T_OCTETS);
  1166. DUMP_REG(IEEE_T_DROP);
  1167. DUMP_REG(IEEE_T_FRAME_OK);
  1168. DUMP_REG(IEEE_T_1COL);
  1169. DUMP_REG(IEEE_T_MCOL);
  1170. DUMP_REG(IEEE_T_DEF);
  1171. DUMP_REG(IEEE_T_LCOL);
  1172. DUMP_REG(IEEE_T_EXCOL);
  1173. DUMP_REG(IEEE_T_MACERR);
  1174. DUMP_REG(IEEE_T_CSERR);
  1175. DUMP_REG(IEEE_T_SQE);
  1176. DUMP_REG(IEEE_T_FDXFC);
  1177. DUMP_REG(IEEE_T_OCTETS_OK);
  1178. DUMP_REG(RMON_R_PACKETS);
  1179. DUMP_REG(RMON_R_BC_PKT);
  1180. DUMP_REG(RMON_R_MC_PKT);
  1181. DUMP_REG(RMON_R_CRC_ALIGN);
  1182. DUMP_REG(RMON_R_UNDERSIZE);
  1183. DUMP_REG(RMON_R_OVERSIZE);
  1184. DUMP_REG(RMON_R_FRAG);
  1185. DUMP_REG(RMON_R_JAB);
  1186. DUMP_REG(RMON_R_RESVD_0);
  1187. DUMP_REG(RMON_R_P64);
  1188. DUMP_REG(RMON_R_P65TO127);
  1189. DUMP_REG(RMON_R_P128TO255);
  1190. DUMP_REG(RMON_R_P256TO511);
  1191. DUMP_REG(RMON_R_P512TO1023);
  1192. DUMP_REG(RMON_R_P1024TO2047);
  1193. DUMP_REG(RMON_R_P_GTE2048);
  1194. DUMP_REG(RMON_R_OCTETS);
  1195. DUMP_REG(IEEE_R_DROP);
  1196. DUMP_REG(IEEE_R_FRAME_OK);
  1197. DUMP_REG(IEEE_R_CRC);
  1198. DUMP_REG(IEEE_R_ALIGN);
  1199. DUMP_REG(IEEE_R_MACERR);
  1200. DUMP_REG(IEEE_R_FDXFC);
  1201. DUMP_REG(IEEE_R_OCTETS_OK);
  1202. DUMP_REG(ATCR);
  1203. DUMP_REG(ATVR);
  1204. DUMP_REG(ATOFF);
  1205. DUMP_REG(ATPER);
  1206. DUMP_REG(ATCOR);
  1207. DUMP_REG(ATINC);
  1208. DUMP_REG(ATSTMP);
  1209. DUMP_REG(TGSR);
  1210. }
  1211. void enet_nvic_tog(void)
  1212. {
  1213. NVIC_SetPendingIRQ(ENET_IRQn);
  1214. }
  1215. void enet_rx_stat(void)
  1216. {
  1217. enet_data_error_stats_t *error_statistic = &imxrt_eth_device.error_statistic;
  1218. #define DUMP_STAT(__VAR) \
  1219. rt_kprintf("%-25s: %08X\n", #__VAR, error_statistic->__VAR);
  1220. DUMP_STAT(statsRxLenGreaterErr);
  1221. DUMP_STAT(statsRxAlignErr);
  1222. DUMP_STAT(statsRxFcsErr);
  1223. DUMP_STAT(statsRxOverRunErr);
  1224. DUMP_STAT(statsRxTruncateErr);
  1225. #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
  1226. DUMP_STAT(statsRxProtocolChecksumErr);
  1227. DUMP_STAT(statsRxIpHeadChecksumErr);
  1228. DUMP_STAT(statsRxMacErr);
  1229. DUMP_STAT(statsRxPhyErr);
  1230. DUMP_STAT(statsRxCollisionErr);
  1231. DUMP_STAT(statsTxErr);
  1232. DUMP_STAT(statsTxFrameErr);
  1233. DUMP_STAT(statsTxOverFlowErr);
  1234. DUMP_STAT(statsTxLateCollisionErr);
  1235. DUMP_STAT(statsTxExcessCollisionErr);
  1236. DUMP_STAT(statsTxUnderFlowErr);
  1237. DUMP_STAT(statsTxTsErr);
  1238. #endif
  1239. }
  1240. void enet_buf_info(void)
  1241. {
  1242. int i = 0;
  1243. for (i = 0; i < ENET_RXBD_NUM; i++)
  1244. {
  1245. rt_kprintf("%d: length: %-8d, control: %04X, buffer:%p\n",
  1246. i,
  1247. g_rxBuffDescrip[i].length,
  1248. g_rxBuffDescrip[i].control,
  1249. g_rxBuffDescrip[i].buffer);
  1250. }
  1251. for (i = 0; i < ENET_TXBD_NUM; i++)
  1252. {
  1253. rt_kprintf("%d: length: %-8d, control: %04X, buffer:%p\n",
  1254. i,
  1255. g_txBuffDescrip[i].length,
  1256. g_txBuffDescrip[i].control,
  1257. g_txBuffDescrip[i].buffer);
  1258. }
  1259. }
  1260. FINSH_FUNCTION_EXPORT(phy_read, read phy register);
  1261. FINSH_FUNCTION_EXPORT(phy_write, write phy register);
  1262. FINSH_FUNCTION_EXPORT(phy_dump, dump phy registers);
  1263. FINSH_FUNCTION_EXPORT(enet_reg_dump, dump enet registers);
  1264. FINSH_FUNCTION_EXPORT(enet_nvic_tog, toggle enet nvic pendding bit);
  1265. FINSH_FUNCTION_EXPORT(enet_rx_stat, dump enet rx statistic);
  1266. FINSH_FUNCTION_EXPORT(enet_buf_info, dump enet tx and tx buffer descripter);
  1267. #endif