123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- #include "stm32f4x7_phy.h"
- #include "interface.h"
- #include "lwip/api.h"
- #include "lwip/sockets.h"
- #include "netconf.h"
- #include "stm32f4x7_eth.h"
- ETH_InitTypeDef ETH_InitStructure;
- __IO uint32_t EthStatus = 0;
- extern struct netif gnetif;
- static void phy_gpio_config(void);
- static void phy_mac_dma_config(void);
- static void nvic_configuration(void);
- /**
- * @brief Inserts a delay time.
- * @param nCount: number of 10ms periods to wait for.
- * @retval None
- */
- void ETH_Delay10ms(uint32_t nCount)
- {
- // OSTimeDly(10 * nCount);
- USE_Delay(10 * nCount);
- }
- /*!
- \brief setup ethernet system(GPIOs, clocks, MAC, DMA, systick)
- \param[in] none
- \param[out] none
- \retval none
- */
- void eth_init(void)
- {
- nvic_configuration();
- /* configure the GPIO ports for ethernet pins */
- phy_gpio_config();
- /* configure the ethernet MAC/DMA */
- phy_mac_dma_config();
- /* Get Ethernet link status*/
- if (ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_SR) & 1)
- {
- EthStatus |= ETH_LINK_FLAG;
- }
- /* Configure the PHY to generate an interrupt on change of link status */
- Eth_Link_PHYITConfig(ETHERNET_PHY_ADDRESS);
- ETH_DMAITConfig(ETH_DMA_IT_R | ETH_DMA_IT_NIS, ENABLE);
- }
- /*!
- \brief configures the ethernet interface
- \param[in] none
- \param[out] none
- \retval none
- */
- static void phy_mac_dma_config(void)
- {
- /* Reset ETHERNET on AHB Bus */
- ETH_DeInit();
- /* Software reset */
- ETH_SoftwareReset();
- /* Wait for software reset */
- while (ETH_GetSoftwareResetStatus() == SET)
- ;
- /* ETHERNET Configuration ------------------------------*/
- /* 缺省配置ETH_InitStructure */
- ETH_StructInit(Ð_InitStructure);
- /* Fill ETH_InitStructure parametrs */
- /*-------------------- MAC ----------------------------*/
- /* 开启网络自适应功能,速度和工作模式无需配置 */
- ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
- // ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable;
- // ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
- // ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
- /* 关闭反馈 */
- ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
- /* 关闭重传功能 */
- ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
- /* 关闭自动去除PDA/CRC功能 */
- ETH_InitStructure.ETH_AutomaticPadCRCStrip =
- ETH_AutomaticPadCRCStrip_Disable;
- /* 关闭接收所有的帧 */
- ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
- /* 允许接收所有广播帧 */
- ETH_InitStructure.ETH_BroadcastFramesReception =
- ETH_BroadcastFramesReception_Enable;
- /* 关闭混合模式的地址过滤 */
- ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
- /* 对于组播地址使用完美地址过滤 */
- ETH_InitStructure.ETH_MulticastFramesFilter =
- ETH_MulticastFramesFilter_Perfect;
- /* 对单播地址使用完美地址过滤 */
- ETH_InitStructure.ETH_UnicastFramesFilter =
- ETH_UnicastFramesFilter_Perfect;
- #ifdef CHECKSUM_BY_HARDWARE
- /* 开启ipv4和TCP/UDP/ICMP的帧校验和卸载 */
- ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
- #endif
- /*------------------------ DMA -------------------------------*/
- /*当我们使用帧校验和卸载功能的时候,一定要使能存储转发模式,存储
- 转发模式中要保证整个帧存储在FIFO中, 这样MAC能插入/识别出帧校验
- 值,当真校验正确的时候DMA就可以处理帧,否则就丢弃掉该帧*/
- /* 开启丢弃TCP/IP错误帧 */
- ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame =
- ETH_DropTCPIPChecksumErrorFrame_Enable;
- /* 开启接收数据的存储转发模式 */
- ETH_InitStructure.ETH_ReceiveStoreForward =
- ETH_ReceiveStoreForward_Enable;
- /* 开启发送数据的存储转发模式 */
- ETH_InitStructure.ETH_TransmitStoreForward =
- ETH_TransmitStoreForward_Enable;
- /* 禁止转发错误帧 */
- ETH_InitStructure.ETH_ForwardErrorFrames =
- ETH_ForwardErrorFrames_Disable;
- /* 不转发过小的好帧 */
- ETH_InitStructure.ETH_ForwardUndersizedGoodFrames =
- ETH_ForwardUndersizedGoodFrames_Disable;
- /* 打开处理第二帧功能 */
- ETH_InitStructure.ETH_SecondFrameOperate =
- ETH_SecondFrameOperate_Enable;
- /* 开启DMA传输的地址对齐功能 */
- ETH_InitStructure.ETH_AddressAlignedBeats =
- ETH_AddressAlignedBeats_Enable;
- /* 开启固定突发功能 */
- ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
- /* DMA发送的最大突发长度为32个节拍 */
- ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
- /*DMA接收的最大突发长度为32个节拍 */
- ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
- ETH_InitStructure.ETH_DMAArbitration =
- ETH_DMAArbitration_RoundRobin_RxTx_2_1;
- /* 配置ETH */
- EthStatus = ETH_Init(Ð_InitStructure, ETHERNET_PHY_ADDRESS);
- }
- /*!
- \brief configures the nested vectored interrupt controller
- \param[in] none
- \param[out] none
- \retval none
- */
- static void nvic_configuration(void)
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- /*!
- \brief configures the different GPIO ports
- \param[in] none
- \param[out] none
- \retval none
- */
- static void phy_gpio_config(void)
- {
- /* Enable SYSCFG clock */
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
- #ifdef MII_MODE
- #ifdef PHY_CLOCK_MCO
- /* output HXTAL clock (25MHz) on CKOUT0 pin(PA8) to clock the PHY */
- RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1);
- #endif /* PHY_CLOCK_MCO */
- SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);
- #elif defined RMII_MODE
- SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
- #endif
- }
- /**
- * @brief This function handles Ethernet link status.
- * @param None
- * @retval None
- */
- void Eth_Link_ITHandler(uint16_t PHYAddress)
- {
- /* Check whether the link interrupt has occurred or not */
- if (((ETH_ReadPHYRegister(PHYAddress, PHY_MISR)) & PHY_LINK_STATUS) != 0)
- {
- if ((ETH_ReadPHYRegister(PHYAddress, PHY_SR) & 1))
- {
- netif_set_link_up(&gnetif);
- }
- else
- {
- netif_set_link_down(&gnetif);
- }
- }
- }
- /**
- * @brief Configure the PHY to generate an interrupt on change of link status.
- * @param PHYAddress: external PHY address
- * @retval None
- */
- uint32_t Eth_Link_PHYITConfig(uint16_t PHYAddress)
- {
- uint16_t tmpreg = 0;
- /* Read MICR register */
- tmpreg = ETH_ReadPHYRegister(PHYAddress, PHY_MICR);
- /* Enable output interrupt events to signal via the INT pin */
- tmpreg |= (uint16_t)(PHY_MICR_INT_EN | PHY_MICR_INT_OE);
- if (!(ETH_WritePHYRegister(PHYAddress, PHY_MICR, tmpreg)))
- {
- /* Return ERROR in case of write timeout */
- return ETH_ERROR;
- }
- /* Read MISR register */
- tmpreg = ETH_ReadPHYRegister(PHYAddress, PHY_MISR);
- /* Enable Interrupt on change of link status */
- tmpreg |= (uint16_t)PHY_MISR_LINK_INT_EN;
- if (!(ETH_WritePHYRegister(PHYAddress, PHY_MISR, tmpreg)))
- {
- /* Return ERROR in case of write timeout */
- return ETH_ERROR;
- }
- /* Return SUCCESS */
- return ETH_SUCCESS;
- }
- /**
- * @brief Link callback function, this function is called on change of link status.
- * @param The network interface
- * @retval None
- */
- void ETH_link_callback(struct netif *netif)
- {
- __IO uint32_t timeout = 0;
- uint32_t tmpreg;
- uint16_t RegValue;
- ip4_addr_t ipaddr;
- ip4_addr_t netmask;
- ip4_addr_t gw;
- if (netif_is_link_up(netif))
- {
- /* Restart the auto-negotiation */
- if (ETH_InitStructure.ETH_AutoNegotiation != ETH_AutoNegotiation_Disable)
- {
- /* Reset Timeout counter */
- timeout = 0;
- /* Enable auto-negotiation */
- ETH_WritePHYRegister(ETHERNET_PHY_ADDRESS, PHY_BCR, PHY_AutoNegotiation);
- /* Wait until the auto-negotiation will be completed */
- do
- {
- timeout++;
- } while (!(ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_BSR) & PHY_AutoNego_Complete) && (timeout < (uint32_t)PHY_READ_TO));
- /* Reset Timeout counter */
- timeout = 0;
- /* Read the result of the auto-negotiation */
- RegValue = ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_SR);
- /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
- if ((RegValue & PHY_DUPLEX_STATUS) != (uint16_t)RESET)
- {
- /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
- ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
- }
- else
- {
- /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
- ETH_InitStructure.ETH_Mode = ETH_Mode_HalfDuplex;
- }
- /* Configure the MAC with the speed fixed by the auto-negotiation process */
- if (RegValue & PHY_SPEED_STATUS)
- {
- /* Set Ethernet speed to 10M following the auto-negotiation */
- ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
- }
- else
- {
- /* Set Ethernet speed to 100M following the auto-negotiation */
- ETH_InitStructure.ETH_Speed = ETH_Speed_100M;
- }
- /*------------------------ ETHERNET MACCR Re-Configuration --------------------*/
- /* Get the ETHERNET MACCR value */
- tmpreg = ETH->MACCR;
- /* Set the FES bit according to ETH_Speed value */
- /* Set the DM bit according to ETH_Mode value */
- tmpreg |= (uint32_t)(ETH_InitStructure.ETH_Speed | ETH_InitStructure.ETH_Mode);
- /* Write to ETHERNET MACCR */
- ETH->MACCR = (uint32_t)tmpreg;
- _eth_delay_(ETH_REG_WRITE_DELAY);
- tmpreg = ETH->MACCR;
- ETH->MACCR = tmpreg;
- }
- /* Restart MAC interface */
- ETH_Start();
- #ifdef USE_DHCP
- ipaddr.addr = 0;
- netmask.addr = 0;
- gw.addr = 0;
- DHCP_state = DHCP_START;
- #else
- IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
- IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
- IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
- #endif /* USE_DHCP */
- netif_set_addr(&gnetif, &ipaddr, &netmask, &gw);
- /* When the netif is fully configured this function must be called.*/
- netif_set_up(&gnetif);
- /* 打印调试信息 */
- printf("LwIP Network Cable is now connected \r\n");
- #ifndef USE_DHCP
- /* Display static IP address */
- printf("LwIP Static IP address = %d.%d.%d.%d \r\n", IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
- #endif /* USE_DHCP */
- }
- else
- {
- ETH_Stop();
- #ifdef USE_DHCP
- DHCP_state = DHCP_LINK_DOWN;
- dhcp_stop(netif);
- #endif /* USE_DHCP */
- /* When the netif link is down this function must be called.*/
- netif_set_down(&gnetif);
- /* 打印调试信息 */
- printf("LwIP Network Cable is unplugged \r\n");
- }
- }
|