#include "string.h" #include "includes.h" #include "lwip/netif.h" #include "arch/ethernetif.h" #include "arch/sys_arch.h" #include "lwip/init.h" #include "lwip/timers.h" #include "lwip/tcpip.h" #include "lwip/dhcp.h" #include "lwip/inet.h" struct netif gnetif; ETH_InitTypeDef ETH_InitStructure; uint32_t EthStatus = 0; //初始ETH设备端口 void ETH_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Enable GPIOs clocks */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG, ENABLE); /* Enable SYSCFG clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* MII/RMII Media interface selection --------------------------------------*/ SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; /* Configure PA1, PA2 and PA7 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH); /* Configure PB5 and PB8 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_10; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_ETH); /* Configure PC1, PC2, PC3, PC4 and PC5 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH); /* Configure PG11, PG14 and PG13 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14; GPIO_Init(GPIOG, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH); } //硬件复位PHY void ETH_PHY_RESET(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_SetBits(GPIOE, GPIO_Pin_2); systick_delayms(10); GPIO_ResetBits(GPIOE, GPIO_Pin_2); systick_delayms(10); GPIO_SetBits(GPIOE, GPIO_Pin_2); systick_delayms(10); } //配置以太网接收中断 void ETH_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Enable the Ethernet global Interrupt */ 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); /* Enable the Ethernet Rx Interrupt */ ETH_DMAClearITPendingBit(ETH_DMA_IT_R); ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS); ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE); } //配置以太网外设 static void ETH_MACDMA_Config(void) { ETH_InitTypeDef ETH_InitStructure; /* Enable ETHERNET clock */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx | RCC_AHB1Periph_ETH_MAC_Rx, ENABLE); /* Reset ETHERNET on AHB Bus */ ETH_DeInit(); /* Software reset */ ETH_SoftwareReset(); /* Wait for software reset */ while (ETH_GetSoftwareResetStatus() == SET); /* ETHERNET Configuration --------------------------------------------------*/ /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */ 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; 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 ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable; #endif /*------------------------ DMA -----------------------------------*/ /* When we use the Checksum offload feature, we need to enable the Store and Forward mode: the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum, if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */ 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; ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable; ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable; ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat; ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat; ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1; /* Configure Ethernet */ if(ETH_Init(Ð_InitStructure, DP83848_PHY_ADDRESS)) EthStatus = ETH_INIT_FLAG; else EthStatus = 0; } //获取phy连接状态 1:连接 0:断开 uint8_t hd_ethGetPhyStatus(void) { if(ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_BSR) & 0x00000004) return 1; else return 0; } void ETH_BSP_Config(void) { ETH_GPIO_Config(); ETH_PHY_RESET(); ETH_MACDMA_Config(); if(EthStatus & ETH_INIT_FLAG) ETH_NVIC_Config(); if(hd_ethGetPhyStatus()) EthStatus |= ETH_LINK_FLAG; } //以太网中断处理函数 extern OS_EVENT *ETH_RecvDataSem; void ETH_IRQHandler(void) { /* Frame received */ if (ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET) { OSSemPost(ETH_RecvDataSem); } /* Clear the interrupt flags. */ /* Clear the Eth DMA Rx IT pending bits */ ETH_DMAClearITPendingBit(ETH_DMA_IT_R); ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS); } ///////////////////////////////////////////////////////PHY/////////////////////////////////////////////////////////////////////////// void low_level_init(struct netif *netif); void hd_ethCheckLinkStatus(uint16_t phyAddr) { uint8_t linksta = hd_ethGetPhyStatus(); if(EthStatus & ETH_INIT_FLAG) { if(EthStatus & ETH_LINK_FLAG) { if(linksta == 0) { netif_set_link_down(&gnetif); EthStatus &= ~ETH_LINK_FLAG; } } else { if(linksta != 0) { netif_set_link_up(&gnetif); EthStatus |= ETH_LINK_FLAG; } } } else { if(linksta != 0) { low_level_init(&gnetif); netif_set_link_up(&gnetif); #if LWIP_DHCP == 1 dhcp_start(&gnetif); #endif } } } void eth_link_callback(struct netif *netif) { __IO uint32_t timeout = 0; uint32_t tmpreg,RegValue; if(netif_is_link_up(netif)) { printf("network is up"); if(ETH_InitStructure.ETH_AutoNegotiation != ETH_AutoNegotiation_Disable) { timeout = 0; ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_BCR, PHY_AutoNegotiation); do { timeout ++; }while(!(ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_BSR) & PHY_AutoNego_Complete) && (timeout < (uint32_t)PHY_READ_TO)); RegValue = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_SR); if(RegValue & PHY_DUPLEX_STATUS) ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex; else ETH_InitStructure.ETH_Mode = ETH_Mode_HalfDuplex; if(RegValue & PHY_SPEED_STATUS) ETH_InitStructure.ETH_Speed = ETH_Speed_10M; else ETH_InitStructure.ETH_Speed = ETH_Speed_100M; tmpreg = ETH->MACCR; tmpreg |= (uint32_t)(ETH_InitStructure.ETH_Speed | ETH_InitStructure.ETH_Mode); ETH->MACCR = (uint32_t)tmpreg; _eth_delay_(ETH_REG_WRITE_DELAY); tmpreg = ETH->MACCR; ETH->MACCR = tmpreg; } ETH_Start(); netif_set_up(&gnetif); } else { printf("network is down"); ETH_Stop(); netif_set_down(&gnetif); } } void ethphycheck_timer(void *arg) { LWIP_UNUSED_ARG(arg); hd_ethCheckLinkStatus(DP83848_PHY_ADDRESS); sys_timeout(1000, ethphycheck_timer, NULL); } ///////////////////////////////////////////////////////LWIP/////////////////////////////////////////////////////////////////////////// //初始化LWIP协议栈 void lwIP_Init(void) { struct ip_addr ipaddr; struct ip_addr netmask; struct ip_addr gw; tcpip_init(NULL, NULL); #if LWIP_DHCP == 1 ip_addr_set_zero(&ipaddr); ip_addr_set_zero(&netmask); ip_addr_set_zero(&gw); #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 netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input); netif_set_default(&gnetif); // netif_set_up(&gnetif); if(EthStatus == (ETH_LINK_FLAG | ETH_INIT_FLAG)) { gnetif.flags |= NETIF_FLAG_LINK_UP; netif_set_up(&gnetif); ETH_Start(); #if LWIP_DHCP == 1 dhcp_start(&gnetif); while(ip_addr_cmp(&(gnetif.ip_addr), &ipaddr)) { OSTimeDly(10/(1000/OS_TICKS_PER_SEC)); } printf("dhcp ip_addr is %s \r\n", inet_ntoa(gnetif.ip_addr)); #endif } else { netif_set_down(&gnetif); gnetif.flags &= ~NETIF_FLAG_LINK_UP; ETH_Stop(); } netif_set_link_callback(&gnetif, eth_link_callback); sys_timeout(2000, ethphycheck_timer, NULL); }