stm32f4x7_phy.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. #include "stm32f4x7_phy.h"
  2. #include "dwt.h"
  3. #include "interface.h"
  4. #include "lwip/api.h"
  5. #include "lwip/sockets.h"
  6. #include "stm32f4x7_eth.h"
  7. ETH_InitTypeDef ETH_InitStructure;
  8. __IO uint32_t EthStatus = 0;
  9. extern struct netif gnetif;
  10. static void phy_gpio_config(void);
  11. static void phy_mac_dma_config(void);
  12. static void nvic_configuration(void);
  13. /**
  14. * @brief Inserts a delay time.
  15. * @param nCount: number of 10ms periods to wait for.
  16. * @retval None
  17. */
  18. void ETH_Delay10ms(uint32_t nCount)
  19. {
  20. // OSTimeDly(10 * nCount);
  21. us_delay(10 * nCount);
  22. }
  23. /*!
  24. \brief setup ethernet system(GPIOs, clocks, MAC, DMA, systick)
  25. \param[in] none
  26. \param[out] none
  27. \retval none
  28. */
  29. void eth_init(void)
  30. {
  31. nvic_configuration();
  32. /* configure the GPIO ports for ethernet pins */
  33. phy_gpio_config();
  34. /* configure the ethernet MAC/DMA */
  35. phy_mac_dma_config();
  36. /* Get Ethernet link status*/
  37. if (ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_SR) & 1)
  38. {
  39. EthStatus |= ETH_LINK_FLAG;
  40. }
  41. // /* Configure the PHY to generate an interrupt on change of link status */
  42. // Eth_Link_PHYITConfig(ETHERNET_PHY_ADDRESS);
  43. ETH_DMAITConfig(ETH_DMA_IT_R | ETH_DMA_IT_NIS, ENABLE);
  44. }
  45. /*!
  46. \brief configures the ethernet interface
  47. \param[in] none
  48. \param[out] none
  49. \retval none
  50. */
  51. static void phy_mac_dma_config(void)
  52. {
  53. /* Reset ETHERNET on AHB Bus */
  54. ETH_DeInit();
  55. /* Software reset */
  56. ETH_SoftwareReset();
  57. /* Wait for software reset */
  58. while (ETH_GetSoftwareResetStatus() == SET)
  59. ;
  60. /* ETHERNET Configuration ------------------------------*/
  61. /* 缺省配置ETH_InitStructure */
  62. ETH_StructInit(&ETH_InitStructure);
  63. /* Fill ETH_InitStructure parametrs */
  64. /*-------------------- MAC ----------------------------*/
  65. /* 开启网络自适应功能,速度和工作模式无需配置 */
  66. ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
  67. // ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable;
  68. // ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
  69. // ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
  70. /* 关闭反馈 */
  71. ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
  72. /* 关闭重传功能 */
  73. ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
  74. /* 关闭自动去除PDA/CRC功能 */
  75. ETH_InitStructure.ETH_AutomaticPadCRCStrip =
  76. ETH_AutomaticPadCRCStrip_Disable;
  77. /* 关闭接收所有的帧 */
  78. ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
  79. /* 允许接收所有广播帧 */
  80. ETH_InitStructure.ETH_BroadcastFramesReception =
  81. ETH_BroadcastFramesReception_Enable;
  82. /* 关闭混合模式的地址过滤 */
  83. ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
  84. /* 对于组播地址使用完美地址过滤 */
  85. ETH_InitStructure.ETH_MulticastFramesFilter =
  86. ETH_MulticastFramesFilter_Perfect;
  87. /* 对单播地址使用完美地址过滤 */
  88. ETH_InitStructure.ETH_UnicastFramesFilter =
  89. ETH_UnicastFramesFilter_Perfect;
  90. #ifdef CHECKSUM_BY_HARDWARE
  91. /* 开启ipv4和TCP/UDP/ICMP的帧校验和卸载 */
  92. ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
  93. #endif
  94. /*------------------------ DMA -------------------------------*/
  95. /*当我们使用帧校验和卸载功能的时候,一定要使能存储转发模式,存储
  96. 转发模式中要保证整个帧存储在FIFO中, 这样MAC能插入/识别出帧校验
  97. 值,当真校验正确的时候DMA就可以处理帧,否则就丢弃掉该帧*/
  98. /* 开启丢弃TCP/IP错误帧 */
  99. ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame =
  100. ETH_DropTCPIPChecksumErrorFrame_Enable;
  101. /* 开启接收数据的存储转发模式 */
  102. ETH_InitStructure.ETH_ReceiveStoreForward =
  103. ETH_ReceiveStoreForward_Enable;
  104. /* 开启发送数据的存储转发模式 */
  105. ETH_InitStructure.ETH_TransmitStoreForward =
  106. ETH_TransmitStoreForward_Enable;
  107. /* 禁止转发错误帧 */
  108. ETH_InitStructure.ETH_ForwardErrorFrames =
  109. ETH_ForwardErrorFrames_Disable;
  110. /* 不转发过小的好帧 */
  111. ETH_InitStructure.ETH_ForwardUndersizedGoodFrames =
  112. ETH_ForwardUndersizedGoodFrames_Disable;
  113. /* 打开处理第二帧功能 */
  114. ETH_InitStructure.ETH_SecondFrameOperate =
  115. ETH_SecondFrameOperate_Enable;
  116. /* 开启DMA传输的地址对齐功能 */
  117. ETH_InitStructure.ETH_AddressAlignedBeats =
  118. ETH_AddressAlignedBeats_Enable;
  119. /* 开启固定突发功能 */
  120. ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
  121. /* DMA发送的最大突发长度为32个节拍 */
  122. ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
  123. /*DMA接收的最大突发长度为32个节拍 */
  124. ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
  125. ETH_InitStructure.ETH_DMAArbitration =
  126. ETH_DMAArbitration_RoundRobin_RxTx_2_1;
  127. /* 配置ETH */
  128. EthStatus = ETH_Init(&ETH_InitStructure, ETHERNET_PHY_ADDRESS);
  129. }
  130. /*!
  131. \brief configures the nested vectored interrupt controller
  132. \param[in] none
  133. \param[out] none
  134. \retval none
  135. */
  136. static void nvic_configuration(void)
  137. {
  138. NVIC_InitTypeDef NVIC_InitStructure;
  139. NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
  140. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  141. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  142. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  143. NVIC_Init(&NVIC_InitStructure);
  144. }
  145. /*!
  146. \brief configures the different GPIO ports
  147. \param[in] none
  148. \param[out] none
  149. \retval none
  150. */
  151. static void phy_gpio_config(void)
  152. {
  153. /* Enable SYSCFG clock */
  154. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  155. #ifdef MII_MODE
  156. #ifdef PHY_CLOCK_MCO
  157. /* output HXTAL clock (25MHz) on CKOUT0 pin(PA8) to clock the PHY */
  158. RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1);
  159. #endif /* PHY_CLOCK_MCO */
  160. SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);
  161. #elif defined RMII_MODE
  162. SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
  163. #endif
  164. }
  165. /**
  166. * @brief This function handles Ethernet link status.
  167. * @param None
  168. * @retval None
  169. */
  170. void ETH_CheckLinkStatus(uint16_t PHYAddress)
  171. {
  172. static uint8_t status = 0;
  173. uint32_t t = ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_SR) & 1;
  174. /* If we have link and previous check was not yet */
  175. if (t && !status)
  176. {
  177. /* Set link up */
  178. netif_set_link_up(&gnetif);
  179. status = 1;
  180. }
  181. /* If we don't have link and it was on previous check */
  182. if (!t && status)
  183. {
  184. // EthLinkStatus = 1;
  185. /* Set link down */
  186. netif_set_link_down(&gnetif);
  187. status = 0;
  188. }
  189. }
  190. /**
  191. * @brief Configure the PHY to generate an interrupt on change of link status.
  192. * @param PHYAddress: external PHY address
  193. * @retval None
  194. */
  195. uint32_t Eth_Link_PHYITConfig(uint16_t PHYAddress)
  196. {
  197. uint16_t tmpreg = 0;
  198. /* Read MICR register */
  199. tmpreg = ETH_ReadPHYRegister(PHYAddress, PHY_MICR);
  200. /* Enable output interrupt events to signal via the INT pin */
  201. tmpreg |= (uint16_t)(PHY_MICR_INT_EN | PHY_MICR_INT_OE);
  202. if (!(ETH_WritePHYRegister(PHYAddress, PHY_MICR, tmpreg)))
  203. {
  204. /* Return ERROR in case of write timeout */
  205. return ETH_ERROR;
  206. }
  207. /* Read MISR register */
  208. tmpreg = ETH_ReadPHYRegister(PHYAddress, PHY_MISR);
  209. /* Enable Interrupt on change of link status */
  210. tmpreg |= (uint16_t)PHY_MISR_LINK_INT_EN;
  211. if (!(ETH_WritePHYRegister(PHYAddress, PHY_MISR, tmpreg)))
  212. {
  213. /* Return ERROR in case of write timeout */
  214. return ETH_ERROR;
  215. }
  216. /* Return SUCCESS */
  217. return ETH_SUCCESS;
  218. }
  219. /**
  220. * @brief Link callback function, this function is called on change of link status.
  221. * @param The network interface
  222. * @retval None
  223. */
  224. void ETH_link_callback(struct netif *netif)
  225. {
  226. __IO uint32_t timeout = 0;
  227. uint32_t tmpreg;
  228. uint16_t RegValue;
  229. struct ip4_addr ipaddr;
  230. struct ip4_addr netmask;
  231. struct ip4_addr gw;
  232. if (netif_is_link_up(netif))
  233. {
  234. /* Restart the auto-negotiation */
  235. if (ETH_InitStructure.ETH_AutoNegotiation !=
  236. ETH_AutoNegotiation_Disable)
  237. {
  238. /* Reset Timeout counter */
  239. timeout = 0;
  240. /* Enable auto-negotiation */
  241. ETH_WritePHYRegister(ETHERNET_PHY_ADDRESS, PHY_BCR,
  242. PHY_AutoNegotiation);
  243. /* Wait until the auto-negotiation will be completed */
  244. do
  245. {
  246. timeout++;
  247. } while (!(ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_BSR) & PHY_AutoNego_Complete) && (timeout < (uint32_t)PHY_READ_TO));
  248. /* Reset Timeout counter */
  249. timeout = 0;
  250. /* Read the result of the auto-negotiation */
  251. RegValue = ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_SR);
  252. if ((RegValue & PHY_DUPLEX_STATUS) != (uint16_t)RESET)
  253. {
  254. ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
  255. }
  256. else
  257. {
  258. ETH_InitStructure.ETH_Mode = ETH_Mode_HalfDuplex;
  259. }
  260. if (RegValue & PHY_SPEED_STATUS)
  261. {
  262. /* Set Ethernet speed to 10M following the auto-negotiation */
  263. ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
  264. }
  265. else
  266. {
  267. /* Set Ethernet speed to 100M following the auto-negotiation */
  268. ETH_InitStructure.ETH_Speed = ETH_Speed_100M;
  269. }
  270. /*------------ ETHERNET MACCR Re-Configuration -------------
  271. /* Get the ETHERNET MACCR value */
  272. tmpreg = ETH->MACCR;
  273. /* Set the FES bit according to ETH_Speed value */
  274. /* Set the DM bit according to ETH_Mode value */
  275. tmpreg |= (uint32_t)(ETH_InitStructure.ETH_Speed |
  276. ETH_InitStructure.ETH_Mode);
  277. /* Write to ETHERNET MACCR */
  278. ETH->MACCR = (uint32_t)tmpreg;
  279. _eth_delay_(ETH_REG_WRITE_DELAY);
  280. tmpreg = ETH->MACCR;
  281. ETH->MACCR = tmpreg;
  282. }
  283. /* Restart MAC interface */
  284. ETH_Start();
  285. #ifdef USE_DHCP
  286. ipaddr.addr = 0;
  287. netmask.addr = 0;
  288. gw.addr = 0;
  289. DHCP_state = DHCP_START;
  290. #else
  291. IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
  292. IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
  293. IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
  294. #endif /* USE_DHCP */
  295. netif_set_addr(&gnetif, &ipaddr, &netmask, &gw);
  296. /* When the netif is fully configured this function must be called.*/
  297. netif_set_up(&gnetif);
  298. // EthLinkStatus = 0;
  299. }
  300. else
  301. {
  302. ETH_Stop();
  303. #ifdef USE_DHCP
  304. DHCP_state = DHCP_LINK_DOWN;
  305. dhcp_stop(netif);
  306. #endif /* USE_DHCP */
  307. /* When the netif link is down this function must be called.*/
  308. netif_set_down(&gnetif);
  309. }
  310. }
  311. // void ETH_IRQHandler(void)
  312. // {
  313. // OSIntEnter();
  314. // /* frame received */
  315. // if (SET == ETH_GetDMAITStatus(ETH_DMA_FLAG_R))
  316. // {
  317. // Eth_Link_ITHandler(0x01);
  318. // /* clear the enet DMA Rx interrupt pending bits */
  319. // ETH_DMAClearITPendingBit(ETH_DMA_FLAG_R);
  320. // ETH_DMAClearITPendingBit(ETH_DMA_FLAG_NIS);
  321. // /* give the semaphore to wakeup LwIP task */
  322. // OSSemPost(g_enet_rx_sem);
  323. // }
  324. // OSIntExit();
  325. // }