netdev_stm32h7.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /*
  2. * Copyright (c) 2025, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "stm32h7xx_hal.h"
  7. #include "ec_master.h"
  8. #ifndef CONFIG_EC_PHY_RESET_PORT
  9. #error "Please define CONFIG_EC_PHY_RESET_PORT in ec_config.h"
  10. #endif
  11. #ifndef CONFIG_EC_PHY_RESET_PIN
  12. #error "Please define CONFIG_EC_PHY_RESET_PIN in ec_config.h"
  13. #endif
  14. #if USE_HAL_TIM_REGISTER_CALLBACKS == 0
  15. #error "Please set USE_HAL_TIM_REGISTER_CALLBACKS to 1 in stm32h7xx_hal_conf.h"
  16. #endif
  17. #define ETH_RX_BUFFER_SIZE 1536U
  18. #define ETH_TX_BUFFER_SIZE 1536U
  19. /* Global Ethernet handle*/
  20. ETH_HandleTypeDef EthHandle;
  21. ETH_TxPacketConfig TxConfig;
  22. // clang-format off
  23. #if defined ( __ICCARM__ ) /*!< IAR Compiler */
  24. #pragma section = ".RxDescripSection"
  25. ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
  26. #pragma section = ".TxDescripSection"
  27. ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
  28. #pragma section = ".TRx_PoolSection"
  29. __attribute__((aligned(32))) uint8_t rx_buffer[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
  30. #pragma section = ".TRx_PoolSection"
  31. __attribute__((aligned(32))) uint8_t tx_buffer[ETH_TX_DESC_CNT][ETH_TX_BUFFER_SIZE]; /* Ethernet Transmit Buffer */
  32. #elif defined ( __CC_ARM ) /* MDK ARM Compiler */
  33. __attribute__((section(".RxDescripSection"))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
  34. __attribute__((section(".TxDescripSection"))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
  35. __attribute__((section(".TRx_PoolSection"))) __attribute__((aligned(32))) uint8_t rx_buffer[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
  36. __attribute__((section(".TRx_PoolSection"))) __attribute__((aligned(32))) uint8_t tx_buffer[ETH_TX_DESC_CNT][ETH_TX_BUFFER_SIZE]; /* Ethernet Transmit Buffer */
  37. #elif defined ( __GNUC__ ) /* GNU Compiler */
  38. __attribute__((section(".RxDescripSection"))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
  39. __attribute__((section(".TxDescripSection"))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
  40. __attribute__((section(".TRx_PoolSection"))) __attribute__((aligned(32))) uint8_t rx_buffer[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
  41. __attribute__((section(".TRx_PoolSection"))) __attribute__((aligned(32))) uint8_t tx_buffer[ETH_TX_DESC_CNT][ETH_TX_BUFFER_SIZE]; /* Ethernet Transmit Buffer */
  42. #endif
  43. // clang-format on
  44. static uint32_t g_devinuse = 0;
  45. static uint8_t *ec_master_enet_buffer_alloc(void)
  46. {
  47. uint8_t devno;
  48. for (devno = 0; devno < ETH_RX_DESC_CNT; devno++) {
  49. if ((g_devinuse & (1U << devno)) == 0) {
  50. g_devinuse |= (1U << devno);
  51. return rx_buffer[devno];
  52. }
  53. }
  54. return NULL;
  55. }
  56. static void ec_master_enet_buffer_free(uint8_t *buffer)
  57. {
  58. uint8_t devno;
  59. devno = (buffer - &rx_buffer[0][0]) / ETH_RX_BUFFER_SIZE;
  60. g_devinuse &= ~(1U << devno);
  61. }
  62. ec_netdev_t g_netdev;
  63. ec_netdev_t *ec_netdev_low_level_init(uint8_t netdev_index)
  64. {
  65. static uint8_t MACAddr[6];
  66. /* Enable D2 domain SRAM1 Clock (0x30000000 AXI)*/
  67. __HAL_RCC_D2SRAM1_CLK_ENABLE();
  68. GPIO_InitTypeDef GPIO_InitStruct = { 0 };
  69. switch (CONFIG_EC_PHY_RESET_PORT) {
  70. case 0:
  71. __HAL_RCC_GPIOA_CLK_ENABLE();
  72. break;
  73. case 1:
  74. __HAL_RCC_GPIOB_CLK_ENABLE();
  75. break;
  76. case 2:
  77. __HAL_RCC_GPIOC_CLK_ENABLE();
  78. break;
  79. case 3:
  80. __HAL_RCC_GPIOD_CLK_ENABLE();
  81. break;
  82. case 4:
  83. __HAL_RCC_GPIOE_CLK_ENABLE();
  84. break;
  85. case 5:
  86. __HAL_RCC_GPIOF_CLK_ENABLE();
  87. break;
  88. case 6:
  89. __HAL_RCC_GPIOG_CLK_ENABLE();
  90. break;
  91. case 7:
  92. __HAL_RCC_GPIOH_CLK_ENABLE();
  93. break;
  94. default:
  95. EC_ASSERT_MSG(0, "Invalid CONFIG_EC_PHY_RESET_PORT\n");
  96. break;
  97. }
  98. GPIO_InitStruct.Pin = (1 << CONFIG_EC_PHY_RESET_PIN);
  99. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  100. GPIO_InitStruct.Pull = GPIO_PULLUP;
  101. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  102. HAL_GPIO_Init((GPIO_TypeDef *)(GPIOA_BASE + CONFIG_EC_PHY_RESET_PORT * 0x400UL), &GPIO_InitStruct);
  103. // phy reset
  104. HAL_GPIO_WritePin((GPIO_TypeDef *)(GPIOA_BASE + CONFIG_EC_PHY_RESET_PORT * 0x400UL), (1 << CONFIG_EC_PHY_RESET_PIN), GPIO_PIN_RESET);
  105. ec_osal_msleep(10);
  106. HAL_GPIO_WritePin((GPIO_TypeDef *)(GPIOA_BASE + CONFIG_EC_PHY_RESET_PORT * 0x400UL), (1 << CONFIG_EC_PHY_RESET_PIN), GPIO_PIN_SET);
  107. EthHandle.Instance = ETH;
  108. MACAddr[0] = 0x00;
  109. MACAddr[1] = 0x80;
  110. MACAddr[2] = 0xE1;
  111. MACAddr[3] = 0x00;
  112. MACAddr[4] = 0x00;
  113. MACAddr[5] = 0x00;
  114. EthHandle.Init.MACAddr = &MACAddr[0];
  115. EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE;
  116. EthHandle.Init.TxDesc = DMATxDscrTab;
  117. EthHandle.Init.RxDesc = DMARxDscrTab;
  118. EthHandle.Init.RxBuffLen = ETH_RX_BUFFER_SIZE;
  119. if (HAL_ETH_Init(&EthHandle) != HAL_OK) {
  120. EC_LOG_ERR("HAL_ETH_Init failed\n");
  121. while (1) {
  122. }
  123. }
  124. HAL_ETH_SetMDIOClockRange(&EthHandle);
  125. memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig));
  126. TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
  127. TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
  128. TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
  129. ec_memcpy(g_netdev.mac_addr, MACAddr, 6);
  130. for (uint32_t i = 0; i < ETH_TX_DESC_CNT; i++) {
  131. for (uint8_t j = 0; j < 6; j++) { // dst MAC
  132. EC_WRITE_U8(&tx_buffer[i][j], 0xFF);
  133. }
  134. for (uint8_t j = 0; j < 6; j++) { // src MAC
  135. EC_WRITE_U8(&tx_buffer[i][6 + j], MACAddr[j]);
  136. }
  137. EC_WRITE_U16(&tx_buffer[i][12], ec_htons(0x88a4));
  138. }
  139. return &g_netdev;
  140. }
  141. void ec_mdio_low_level_write(struct chry_phy_device *phydev, uint16_t phy_addr, uint16_t regnum, uint16_t val)
  142. {
  143. //ec_netdev_t *netdev = (ec_netdev_t *)phydev->user_data;
  144. HAL_ETH_WritePHYRegister(&EthHandle, phy_addr, regnum, val);
  145. }
  146. uint16_t ec_mdio_low_level_read(struct chry_phy_device *phydev, uint16_t phy_addr, uint16_t regnum)
  147. {
  148. //ec_netdev_t *netdev = (ec_netdev_t *)phydev->user_data;
  149. uint32_t pRegVal = 0;
  150. HAL_ETH_ReadPHYRegister(&EthHandle, phy_addr, regnum, &pRegVal);
  151. return pRegVal;
  152. }
  153. void ec_netdev_low_level_link_up(ec_netdev_t *netdev, struct chry_phy_status *status)
  154. {
  155. ETH_MACConfigTypeDef MACConf = { 0 };
  156. if (status->link) {
  157. /* Get MAC Config MAC */
  158. HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
  159. MACConf.DuplexMode = ETH_FULLDUPLEX_MODE;
  160. MACConf.Speed = ETH_SPEED_100M;
  161. HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
  162. HAL_ETH_Start_IT(&EthHandle);
  163. } else {
  164. HAL_ETH_Stop_IT(&EthHandle);
  165. }
  166. }
  167. EC_FAST_CODE_SECTION uint8_t *ec_netdev_low_level_get_txbuf(ec_netdev_t *netdev)
  168. {
  169. return (uint8_t *)tx_buffer[netdev->tx_frame_index];
  170. }
  171. EC_FAST_CODE_SECTION int ec_netdev_low_level_output(ec_netdev_t *netdev, uint32_t size)
  172. {
  173. ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = { 0 };
  174. HAL_StatusTypeDef status;
  175. memset(Txbuffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef));
  176. Txbuffer[0].buffer = tx_buffer[netdev->tx_frame_index];
  177. Txbuffer[0].len = size;
  178. Txbuffer[0].next = NULL;
  179. TxConfig.Length = size;
  180. TxConfig.TxBuffer = Txbuffer;
  181. TxConfig.pData = NULL;
  182. SCB_CleanDCache_by_Addr((uint32_t *)tx_buffer[netdev->tx_frame_index], size);
  183. status = HAL_ETH_Transmit(&EthHandle, &TxConfig, 20);
  184. if (status != HAL_OK) {
  185. return -1;
  186. }
  187. netdev->tx_frame_index++;
  188. netdev->tx_frame_index %= ETH_TX_DESC_CNT;
  189. return 0;
  190. }
  191. static ec_htimer_cb g_ec_htimer_cb = NULL;
  192. static void *g_ec_htimer_arg = NULL;
  193. static TIM_HandleTypeDef ECTimHandle;
  194. void HAL_TIM7_EC_Callback(TIM_HandleTypeDef *htim)
  195. {
  196. if (g_ec_htimer_cb) {
  197. g_ec_htimer_cb(g_ec_htimer_arg);
  198. }
  199. }
  200. void ec_htimer_start(uint32_t us, ec_htimer_cb cb, void *arg)
  201. {
  202. RCC_ClkInitTypeDef clkconfig;
  203. uint32_t uwTimclock, uwAPB1Prescaler;
  204. uint32_t uwPrescalerValue;
  205. uint32_t pFLatency;
  206. HAL_StatusTypeDef status;
  207. g_ec_htimer_cb = cb;
  208. g_ec_htimer_arg = arg;
  209. /* Enable TIM7 clock */
  210. __HAL_RCC_TIM7_CLK_ENABLE();
  211. /* Get clock configuration */
  212. HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
  213. /* Get APB1 prescaler */
  214. uwAPB1Prescaler = clkconfig.APB1CLKDivider;
  215. /* Compute TIM7 clock */
  216. if (uwAPB1Prescaler == RCC_HCLK_DIV1) {
  217. uwTimclock = HAL_RCC_GetPCLK1Freq();
  218. } else {
  219. uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
  220. }
  221. /* Compute the prescaler value to have TIM7 counter clock equal to 1MHz */
  222. uwPrescalerValue = (uint32_t)((uwTimclock / 1000000U) - 1U);
  223. /* Initialize TIM7 */
  224. ECTimHandle.Instance = TIM7;
  225. ECTimHandle.Init.Period = us - 1U;
  226. ECTimHandle.Init.Prescaler = uwPrescalerValue;
  227. ECTimHandle.Init.ClockDivision = 0U;
  228. ECTimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
  229. ECTimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  230. status = HAL_TIM_Base_Init(&ECTimHandle);
  231. if (status == HAL_OK) {
  232. __HAL_TIM_CLEAR_FLAG(&ECTimHandle, TIM_FLAG_UPDATE);
  233. HAL_TIM_RegisterCallback(&ECTimHandle, HAL_TIM_PERIOD_ELAPSED_CB_ID, HAL_TIM7_EC_Callback);
  234. /* Start the TIM time Base generation in interrupt mode */
  235. status = HAL_TIM_Base_Start_IT(&ECTimHandle);
  236. if (status == HAL_OK) {
  237. /* Enable the TIM7 global Interrupt */
  238. HAL_NVIC_EnableIRQ(TIM7_IRQn);
  239. /* Enable the TIM7 global Interrupt */
  240. HAL_NVIC_SetPriority(TIM7_IRQn, 5, 0);
  241. }
  242. }
  243. }
  244. void ec_htimer_stop(void)
  245. {
  246. HAL_NVIC_DisableIRQ(TIM7_IRQn);
  247. __HAL_TIM_CLEAR_FLAG(&ECTimHandle, TIM_FLAG_UPDATE);
  248. HAL_TIM_Base_Stop_IT(&ECTimHandle);
  249. }
  250. EC_FAST_CODE_SECTION void ec_htimer_update(uint32_t us)
  251. {
  252. TIM7->ARR = us - 1U;
  253. }
  254. #ifndef CONFIG_EC_TIMESTAMP_CUSTOM
  255. extern uint32_t SystemCoreClock;
  256. uint32_t ec_get_cpu_frequency(void)
  257. {
  258. return SystemCoreClock;
  259. }
  260. #endif
  261. void HAL_ETH_RxAllocateCallback(uint8_t **buff)
  262. {
  263. uint8_t *p;
  264. p = ec_master_enet_buffer_alloc();
  265. if (p) {
  266. *buff = p;
  267. } else {
  268. *buff = NULL;
  269. }
  270. }
  271. void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length)
  272. {
  273. /* Invalidate data cache because Rx DMA's writing to physical memory makes it stale. */
  274. *pStart = buff;
  275. *pEnd = buff + Length;
  276. SCB_InvalidateDCache_by_Addr((uint32_t *)buff, Length);
  277. ec_netdev_receive(&g_netdev, buff, Length);
  278. ec_master_enet_buffer_free(buff);
  279. }
  280. void HAL_ETH_TxFreeCallback(uint32_t *buff)
  281. {
  282. }
  283. void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
  284. {
  285. uint8_t *buffer = NULL;
  286. HAL_ETH_ReadData(&EthHandle, (void **)&buffer);
  287. }
  288. /**
  289. * @brief ETH MSP Initialization
  290. * This function configures the hardware resources used in this example
  291. * @param heth: ETH handle pointer
  292. * @retval None
  293. */
  294. void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
  295. {
  296. GPIO_InitTypeDef GPIO_InitStruct = { 0 };
  297. if (heth->Instance == ETH) {
  298. /* USER CODE BEGIN ETH_MspInit 0 */
  299. /* USER CODE END ETH_MspInit 0 */
  300. /* Peripheral clock enable */
  301. __HAL_RCC_ETH1MAC_CLK_ENABLE();
  302. __HAL_RCC_ETH1TX_CLK_ENABLE();
  303. __HAL_RCC_ETH1RX_CLK_ENABLE();
  304. __HAL_RCC_GPIOC_CLK_ENABLE();
  305. __HAL_RCC_GPIOA_CLK_ENABLE();
  306. __HAL_RCC_GPIOB_CLK_ENABLE();
  307. /**ETH GPIO Configuration
  308. PC1 ------> ETH_MDC
  309. PA1 ------> ETH_REF_CLK
  310. PA2 ------> ETH_MDIO
  311. PA7 ------> ETH_CRS_DV
  312. PC4 ------> ETH_RXD0
  313. PC5 ------> ETH_RXD1
  314. PB11 ------> ETH_TX_EN
  315. PB12 ------> ETH_TXD0
  316. PB13 ------> ETH_TXD1
  317. */
  318. GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
  319. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  320. GPIO_InitStruct.Pull = GPIO_NOPULL;
  321. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  322. GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  323. HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  324. GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
  325. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  326. GPIO_InitStruct.Pull = GPIO_NOPULL;
  327. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  328. GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  329. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  330. GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
  331. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  332. GPIO_InitStruct.Pull = GPIO_NOPULL;
  333. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  334. GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  335. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  336. /* ETH interrupt Init */
  337. HAL_NVIC_SetPriority(ETH_IRQn, 5, 0);
  338. HAL_NVIC_EnableIRQ(ETH_IRQn);
  339. /* USER CODE BEGIN ETH_MspInit 1 */
  340. /* USER CODE END ETH_MspInit 1 */
  341. }
  342. }
  343. /**
  344. * @brief ETH MSP De-Initialization
  345. * This function freeze the hardware resources used in this example
  346. * @param heth: ETH handle pointer
  347. * @retval None
  348. */
  349. void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth)
  350. {
  351. if (heth->Instance == ETH) {
  352. /* USER CODE BEGIN ETH_MspDeInit 0 */
  353. /* USER CODE END ETH_MspDeInit 0 */
  354. /* Peripheral clock disable */
  355. __HAL_RCC_ETH1MAC_CLK_DISABLE();
  356. __HAL_RCC_ETH1TX_CLK_DISABLE();
  357. __HAL_RCC_ETH1RX_CLK_DISABLE();
  358. /**ETH GPIO Configuration
  359. PC1 ------> ETH_MDC
  360. PA1 ------> ETH_REF_CLK
  361. PA2 ------> ETH_MDIO
  362. PA7 ------> ETH_CRS_DV
  363. PC4 ------> ETH_RXD0
  364. PC5 ------> ETH_RXD1
  365. PB11 ------> ETH_TX_EN
  366. PB12 ------> ETH_TXD0
  367. PB13 ------> ETH_TXD1
  368. */
  369. HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5);
  370. HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7);
  371. HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13);
  372. /* ETH interrupt DeInit */
  373. HAL_NVIC_DisableIRQ(ETH_IRQn);
  374. /* USER CODE BEGIN ETH_MspDeInit 1 */
  375. /* USER CODE END ETH_MspDeInit 1 */
  376. }
  377. }
  378. void ETH_IRQHandler(void)
  379. {
  380. HAL_ETH_IRQHandler(&EthHandle);
  381. }
  382. void TIM7_IRQHandler(void)
  383. {
  384. HAL_TIM_IRQHandler(&ECTimHandle);
  385. }