stm32f4x7_phy.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include "stm32f4x7_phy.h"
  2. #include "dwt.h"
  3. #include "lwip/api.h"
  4. #include "lwip/sockets.h"
  5. #include "stm32f4x7_eth.h"
  6. ETH_InitTypeDef ETH_InitStructure;
  7. __IO uint32_t EthStatus = 0;
  8. extern struct netif gnetif;
  9. static void phy_gpio_config(void);
  10. static void phy_mac_dma_config(void);
  11. static void nvic_configuration(void);
  12. /**
  13. * @brief Inserts a delay time.
  14. * @param nCount: number of 10ms periods to wait for.
  15. * @retval None
  16. */
  17. void ETH_Delay10ms(uint32_t nCount)
  18. {
  19. // OSTimeDly(10 * nCount);
  20. us_delay(10 * nCount);
  21. }
  22. /*!
  23. \brief setup ethernet system(GPIOs, clocks, MAC, DMA, systick)
  24. \param[in] none
  25. \param[out] none
  26. \retval none
  27. */
  28. void eth_init(void)
  29. {
  30. nvic_configuration();
  31. /* configure the GPIO ports for ethernet pins */
  32. phy_gpio_config();
  33. /* configure the ethernet MAC/DMA */
  34. phy_mac_dma_config();
  35. /* Get Ethernet link status*/
  36. if (ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_SR) & 1)
  37. {
  38. EthStatus |= ETH_LINK_FLAG;
  39. }
  40. // /* Configure the PHY to generate an interrupt on change of link status */
  41. // Eth_Link_PHYITConfig(ETHERNET_PHY_ADDRESS);
  42. ETH_DMAITConfig(ETH_DMA_IT_R | ETH_DMA_IT_NIS, ENABLE);
  43. }
  44. /*!
  45. \brief configures the ethernet interface
  46. \param[in] none
  47. \param[out] none
  48. \retval none
  49. */
  50. static void phy_mac_dma_config(void)
  51. {
  52. /* Reset ETHERNET on AHB Bus */
  53. ETH_DeInit();
  54. /* Software reset */
  55. ETH_SoftwareReset();
  56. /* Wait for software reset */
  57. while (ETH_GetSoftwareResetStatus() == SET)
  58. ;
  59. /* ETHERNET Configuration ------------------------------*/
  60. /* 缺省配置ETH_InitStructure */
  61. ETH_StructInit(&ETH_InitStructure);
  62. /* Fill ETH_InitStructure parametrs */
  63. /*-------------------- MAC ----------------------------*/
  64. /* 开启网络自适应功能,速度和工作模式无需配置 */
  65. ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
  66. // ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable;
  67. // ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
  68. // ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
  69. /* 关闭反馈 */
  70. ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
  71. /* 关闭重传功能 */
  72. ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
  73. /* 关闭自动去除PDA/CRC功能 */
  74. ETH_InitStructure.ETH_AutomaticPadCRCStrip =
  75. ETH_AutomaticPadCRCStrip_Disable;
  76. /* 关闭接收所有的帧 */
  77. ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
  78. /* 允许接收所有广播帧 */
  79. ETH_InitStructure.ETH_BroadcastFramesReception =
  80. ETH_BroadcastFramesReception_Enable;
  81. /* 关闭混合模式的地址过滤 */
  82. ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
  83. /* 对于组播地址使用完美地址过滤 */
  84. ETH_InitStructure.ETH_MulticastFramesFilter =
  85. ETH_MulticastFramesFilter_Perfect;
  86. /* 对单播地址使用完美地址过滤 */
  87. ETH_InitStructure.ETH_UnicastFramesFilter =
  88. ETH_UnicastFramesFilter_Perfect;
  89. #ifdef CHECKSUM_BY_HARDWARE
  90. /* 开启ipv4和TCP/UDP/ICMP的帧校验和卸载 */
  91. ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
  92. #endif
  93. /*------------------------ DMA -------------------------------*/
  94. /*当我们使用帧校验和卸载功能的时候,一定要使能存储转发模式,存储
  95. 转发模式中要保证整个帧存储在FIFO中, 这样MAC能插入/识别出帧校验
  96. 值,当真校验正确的时候DMA就可以处理帧,否则就丢弃掉该帧*/
  97. /* 开启丢弃TCP/IP错误帧 */
  98. ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame =
  99. ETH_DropTCPIPChecksumErrorFrame_Enable;
  100. /* 开启接收数据的存储转发模式 */
  101. ETH_InitStructure.ETH_ReceiveStoreForward =
  102. ETH_ReceiveStoreForward_Enable;
  103. /* 开启发送数据的存储转发模式 */
  104. ETH_InitStructure.ETH_TransmitStoreForward =
  105. ETH_TransmitStoreForward_Enable;
  106. /* 禁止转发错误帧 */
  107. ETH_InitStructure.ETH_ForwardErrorFrames =
  108. ETH_ForwardErrorFrames_Disable;
  109. /* 不转发过小的好帧 */
  110. ETH_InitStructure.ETH_ForwardUndersizedGoodFrames =
  111. ETH_ForwardUndersizedGoodFrames_Disable;
  112. /* 打开处理第二帧功能 */
  113. ETH_InitStructure.ETH_SecondFrameOperate =
  114. ETH_SecondFrameOperate_Enable;
  115. /* 开启DMA传输的地址对齐功能 */
  116. ETH_InitStructure.ETH_AddressAlignedBeats =
  117. ETH_AddressAlignedBeats_Enable;
  118. /* 开启固定突发功能 */
  119. ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
  120. /* DMA发送的最大突发长度为32个节拍 */
  121. ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
  122. /*DMA接收的最大突发长度为32个节拍 */
  123. ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
  124. ETH_InitStructure.ETH_DMAArbitration =
  125. ETH_DMAArbitration_RoundRobin_RxTx_2_1;
  126. /* 配置ETH */
  127. EthStatus = ETH_Init(&ETH_InitStructure, ETHERNET_PHY_ADDRESS);
  128. }
  129. /*!
  130. \brief configures the nested vectored interrupt controller
  131. \param[in] none
  132. \param[out] none
  133. \retval none
  134. */
  135. static void nvic_configuration(void)
  136. {
  137. NVIC_InitTypeDef NVIC_InitStructure;
  138. NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
  139. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  140. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  141. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  142. NVIC_Init(&NVIC_InitStructure);
  143. }
  144. /*!
  145. \brief configures the different GPIO ports
  146. \param[in] none
  147. \param[out] none
  148. \retval none
  149. */
  150. static void phy_gpio_config(void)
  151. {
  152. /* Enable SYSCFG clock */
  153. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  154. #ifdef MII_MODE
  155. #ifdef PHY_CLOCK_MCO
  156. /* output HXTAL clock (25MHz) on CKOUT0 pin(PA8) to clock the PHY */
  157. RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1);
  158. #endif /* PHY_CLOCK_MCO */
  159. SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);
  160. #elif defined RMII_MODE
  161. SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
  162. #endif
  163. }
  164. /**
  165. * @brief This function handles Ethernet link status.
  166. * @param None
  167. * @retval None
  168. */
  169. void ETH_CheckLinkStatus(uint16_t PHYAddress)
  170. {
  171. static uint8_t status = 0;
  172. uint32_t t = ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_SR) & 1;
  173. /* If we have link and previous check was not yet */
  174. if (t && !status)
  175. {
  176. /* Set link up */
  177. netif_set_link_up(&gnetif);
  178. status = 1;
  179. }
  180. /* If we don't have link and it was on previous check */
  181. if (!t && status)
  182. {
  183. // EthLinkStatus = 1;
  184. /* Set link down */
  185. netif_set_link_down(&gnetif);
  186. status = 0;
  187. }
  188. }
  189. /**
  190. * @brief Configure the PHY to generate an interrupt on change of link status.
  191. * @param PHYAddress: external PHY address
  192. * @retval None
  193. */
  194. uint32_t Eth_Link_PHYITConfig(uint16_t PHYAddress)
  195. {
  196. uint16_t tmpreg = 0;
  197. /* Read MICR register */
  198. tmpreg = ETH_ReadPHYRegister(PHYAddress, PHY_MICR);
  199. /* Enable output interrupt events to signal via the INT pin */
  200. tmpreg |= (uint16_t)(PHY_MICR_INT_EN | PHY_MICR_INT_OE);
  201. if (!(ETH_WritePHYRegister(PHYAddress, PHY_MICR, tmpreg)))
  202. {
  203. /* Return ERROR in case of write timeout */
  204. return ETH_ERROR;
  205. }
  206. /* Read MISR register */
  207. tmpreg = ETH_ReadPHYRegister(PHYAddress, PHY_MISR);
  208. /* Enable Interrupt on change of link status */
  209. tmpreg |= (uint16_t)PHY_MISR_LINK_INT_EN;
  210. if (!(ETH_WritePHYRegister(PHYAddress, PHY_MISR, tmpreg)))
  211. {
  212. /* Return ERROR in case of write timeout */
  213. return ETH_ERROR;
  214. }
  215. /* Return SUCCESS */
  216. return ETH_SUCCESS;
  217. }