lwip-1.4.1\src\core\ipv4\icmp.c
注释掉:#if CHECKSUM_GEN_ICMP
新增加:#ifdef CHECKSUM_BY_HARDWARE
代码如下:
//#if CHECKSUM_GEN_ICMP
// /* adjust the checksum */
// if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
// iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
// } else {
// iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
// }
//#else /* CHECKSUM_GEN_ICMP */
// iecho->chksum = 0;
//#endif /* CHECKSUM_GEN_ICMP */
/* This part of code has been modified by ST's MCD Application Team */
/* To use the Checksum Offload Engine for the putgoing ICMP packets,
the ICMP checksum field should be set to 0, this is required only for Tx ICMP*/
#ifdef CHECKSUM_BY_HARDWARE
iecho->chksum = 0;
#else
/* adjust the checksum */
if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
iecho->chksum += htons(ICMP_ECHO << 8) + 1;
} else {
iecho->chksum += htons(ICMP_ECHO << 8);
}
#endif
lwip-1.4.1\src\netif\ethernetif.c
需要参考实际网络硬件进行改写
增加必要的宏文件:
填充 struct ethernetif 结构体
struct ethernetif { struct eth_addr *ethaddr; /* Add whatever per-interface state that is needed here. */ int unused; };
ethernetif 是一个结构体,用来描述底层硬件设备,该结构体唯一不可或缺的是MAC地址,它是LWIP用于相应ARP查询的核心数据。其他如果没有特殊需要,可以不添加其他成员数据。
加入一些函数需要的参数定义
/* Forward declarations. */
err_t ethernetif_input(struct netif *netif);
#define ETH_RXBUFNB 4
#define ETH_TXBUFNB 2
uint8_t MACaddr[6];
ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];/* Ethernet Rx & Tx DMA Descriptors */
uint8_t Rx_Buff[ETH_RXBUFNB][ETH_MAX_PACKET_SIZE], Tx_Buff[ETH_TXBUFNB][ETH_MAX_PACKET_SIZE];/* Ethernet buffers */
ETH_DMADESCTypeDef *DMATxDesc = DMATxDscrTab;
extern ETH_DMADESCTypeDef *DMATxDescToSet;
extern ETH_DMADESCTypeDef *DMARxDescToGet;
typedef struct{
u32 length;
u32 buffer;
ETH_DMADESCTypeDef *descriptor;
}FrameTypeDef;
FrameTypeDef ETH_RxPkt_ChainMode(void);
u32 ETH_GetCurrentTxBuffer(void);
u32 ETH_TxPkt_ChainMode(u16 FrameLength);
/** * Setting the MAC address. * @param netif the already initialized lwip network interface structure for this ethernetif */ void Set_MAC_Address(uint8_t* macadd) { MACaddr[0] = macadd[0]; MACaddr[1] = macadd[1]; MACaddr[2] = macadd[2]; MACaddr[3] = macadd[3]; MACaddr[4] = macadd[4]; MACaddr[5] = macadd[5]; ETH_MACAddressConfig(ETH_MAC_Address0, macadd); }
设置MAC地址
static void low_level_init(struct netif *netif) { /* set MAC hardware address length */ netif->hwaddr_len = ETHARP_HWADDR_LEN; /* set MAC hardware address */ netif->hwaddr[0] = MACaddr[0]; netif->hwaddr[1] = MACaddr[1]; netif->hwaddr[2] = MACaddr[2]; netif->hwaddr[3] = MACaddr[3]; netif->hwaddr[4] = MACaddr[4]; netif->hwaddr[5] = MACaddr[5]; /* maximum transfer unit */ netif->mtu = 1500; /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; /* Initialize Tx Descriptors list: Chain Mode */ ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); /* Initialize Rx Descriptors list: Chain Mode */ ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); /* Enable Ethernet Rx interrrupt */ { int i; for(i=0; i
重写该函数: static void low_level_init(struct netif *netif)
static err_t low_level_output(struct netif *netif, struct pbuf *p) { struct pbuf *q; int l = 0; u8 *buffer = (u8 *)ETH_GetCurrentTxBuffer(); for(q = p; q != NULL; q = q->next) { memcpy((u8_t*)&buffer[l], q->payload, q->len); l = l + q->len; } ETH_TxPkt_ChainMode(l); return ERR_OK; }
static err_t low_level_output(struct netif *netif, struct pbuf *p)
/** * Should allocate a pbuf and transfer the bytes of the incoming * packet from the interface into the pbuf. * * @param netif the lwip network interface structure for this ethernetif * @return a pbuf filled with the received packet (including MAC header) * NULL on memory error */ static struct pbuf * low_level_input(struct netif *netif) { struct pbuf *p, *q; u16_t len; int l =0; FrameTypeDef frame; u8 *buffer; p = NULL; frame = ETH_RxPkt_ChainMode(); /* Obtain the size of the packet and put it into the "len" variable. */ len = frame.length; buffer = (u8 *)frame.buffer; /* We allocate a pbuf chain of pbufs from the pool. */ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); if (p != NULL) { for (q = p; q != NULL; q = q->next) { memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len); l = l + q->len; } } /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */ frame.descriptor->Status = ETH_DMARxDesc_OWN; /* When Rx Buffer unavailable flag is set: clear it and resume reception */ if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) { /* Clear RBUS ETHERNET DMA flag */ ETH->DMASR = ETH_DMASR_RBUS; /* Resume DMA reception */ ETH->DMARPDR = 0; } return p; }
static struct pbuf *low_level_input(struct netif *netif)
/** * This function should be called when a packet is ready to be read * from the interface. It uses the function low_level_input() that * should handle the actual reception of bytes from the network * interface. Then the type of the received packet is determined and * the appropriate input function is called. * * @param netif the lwip network interface structure for this ethernetif */ err_t ethernetif_input(struct netif *netif) { err_t err; struct pbuf *p; /* move received packet into a new pbuf */ p = low_level_input(netif); /* no packet could be read, silently ignore this */ if (p == NULL) return ERR_MEM; err = netif->input(p, netif); if (err != ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); pbuf_free(p); p = NULL; } return err; }
err_t ethernetif_input(struct netif *netif)
/** * Should be called at the beginning of the program to set up the * network interface. It calls the function low_level_init() to do the * actual setup of the hardware. * * This function should be passed as a parameter to netif_add(). * * @param netif the lwip network interface structure for this ethernetif * @return ERR_OK if the loopif is initialized * ERR_MEM if private data couldn't be allocated * any other err_t on error */ err_t ethernetif_init(struct netif *netif) { struct ethernetif *ethernetif; LWIP_ASSERT("netif != NULL", (netif != NULL)); ethernetif = mem_malloc(sizeof(struct ethernetif)); if (ethernetif == NULL) { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n")); return ERR_MEM; } #if LWIP_NETIF_HOSTNAME /* Initialize interface hostname */ netif->hostname = "lwip"; #endif /* LWIP_NETIF_HOSTNAME */ /* * Initialize the snmp variables and counters inside the struct netif. * The last argument should be replaced with your link speed, in units * of bits per second. */ NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000); netif->state = ethernetif; netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; /* We directly use etharp_output() here to save a function call. * You can instead declare your own function an call etharp_output() * from it if you have to do some checks before sending (e.g. if link * is available...) */ netif->output = etharp_output; netif->linkoutput = low_level_output; ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); /* initialize the hardware */ low_level_init(netif); return ERR_OK; }
err_t ethernetif_init(struct netif *netif)
/******************************************************************************* * Function Name : ETH_RxPkt_ChainMode * Description : Receives a packet. * Input : None * Output : None * Return : frame: farme size and location *******************************************************************************/ FrameTypeDef ETH_RxPkt_ChainMode(void) { u32 framelength = 0; FrameTypeDef frame = {0,0}; /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ if((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) != (u32)RESET) { frame.length = ETH_ERROR; if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) { /* Clear RBUS ETHERNET DMA flag */ ETH->DMASR = ETH_DMASR_RBUS; /* Resume DMA reception */ ETH->DMARPDR = 0; } /* Return error: OWN bit set */ return frame; } if(((DMARxDescToGet->Status & ETH_DMARxDesc_ES) == (u32)RESET) && ((DMARxDescToGet->Status & ETH_DMARxDesc_LS) != (u32)RESET) && ((DMARxDescToGet->Status & ETH_DMARxDesc_FS) != (u32)RESET)) { /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ framelength = ((DMARxDescToGet->Status & ETH_DMARxDesc_FL) >> ETH_DMARxDesc_FrameLengthShift) - 4; /* Get the addrees of the actual buffer */ frame.buffer = DMARxDescToGet->Buffer1Addr; } else { /* Return ERROR */ framelength = ETH_ERROR; } frame.length = framelength; frame.descriptor = DMARxDescToGet; /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */ /* Chained Mode */ /* Selects the next DMA Rx descriptor list for next buffer to read */ DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet->Buffer2NextDescAddr); /* Return Frame */ return (frame); } /******************************************************************************* * Function Name : ETH_TxPkt_ChainMode * Description : Transmits a packet, from application buffer, pointed by ppkt. * Input : - FrameLength: Tx Packet size. * Output : None * Return : ETH_ERROR: in case of Tx desc owned by DMA * ETH_SUCCESS: for correct transmission *******************************************************************************/ u32 ETH_TxPkt_ChainMode(u16 FrameLength) { /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ if((DMATxDescToSet->Status & ETH_DMATxDesc_OWN) != (u32)RESET) { /* Return ERROR: OWN bit set */ return ETH_ERROR; } /* Setting the Frame Length: bits[12:0] */ DMATxDescToSet->ControlBufferSize = (FrameLength & ETH_DMATxDesc_TBS1); /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */ DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS; /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ DMATxDescToSet->Status |= ETH_DMATxDesc_OWN; /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ if ((ETH->DMASR & ETH_DMASR_TBUS) != (u32)RESET) { /* Clear TBUS ETHERNET DMA flag */ ETH->DMASR = ETH_DMASR_TBUS; /* Resume DMA transmission*/ ETH->DMATPDR = 0; } /* Update the ETHERNET DMA global Tx descriptor with next Tx decriptor */ /* Chained Mode */ /* Selects the next DMA Tx descriptor list for next buffer to send */ DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet->Buffer2NextDescAddr); /* Return SUCCESS */ return ETH_SUCCESS; } /******************************************************************************* * Function Name : ETH_GetCurrentTxBuffer * Description : Return the address of the buffer pointed by the current descritor. * Input : None * Output : None * Return : Buffer address *******************************************************************************/ u32 ETH_GetCurrentTxBuffer(void) { /* Return Buffer address */ return (DMATxDescToSet->Buffer1Addr); }
以上,就是 lwip协议栈层,是怎么与STM32底层数据进行传递处理的。
可以看出发送函数 low_level_output() 和接收 low_level_input() 相辅相成,作为与stm32底层连接的两个重要的函数,还需要两个次要的函数, ethernetif_init() 与 low_level_init()
主要是ETH的初始化以及对PHY芯片的配置过程
/* Includes ------------------------------------------------------------------*/ #include "stm32_eth.h" #include "stm32f107.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define LAN8720A_PHY /* Ethernet pins mapped on STM3210C-EVAL Board */ #define PHY_ADDRESS 0 /* Relative to STM3210C-EVAL Board */ //#define MII_MODE /* MII mode for STM3210C-EVAL Board (MB784) (check jumpers setting) */ #define RMII_MODE /* RMII mode for STM3210C-EVAL Board (MB784) (check jumpers setting) */ /*--------------- LCD Messages ---------------*/ #define MESSAGE1 " STM32F107 " #define MESSAGE2 " Connectivity Line " #define MESSAGE3 " * LwIP demos * " #define MESSAGE4 " " /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ void GPIO_Configuration(void); void NVIC_Configuration(void); void ADC_Configuration(void); void Ethernet_Configuration(void); void delay_ms(uint16_t ms) { uint16_t i,j; for( i = 0; i < ms; i++ ) { for( j = 0; j < 1141; j++ ); } } /** * @brief Setup STM32 system (clocks, Ethernet, GPIO, NVIC) and STM3210C-EVAL resources. * @param None * @retval None */ void System_Setup(void) { RCC_ClocksTypeDef RCC_Clocks; /* Setup STM32 clock, PLL and Flash configuration) */ SystemInit(); /* Enable USART2 clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); /* Enable ETHERNET clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx | RCC_AHBPeriph_ETH_MAC_Rx, ENABLE); /* Enable GPIOs and ADC1 clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE); /* NVIC configuration */ NVIC_Configuration(); /* Configure the GPIO ports */ GPIO_Configuration(); /* Configure the Ethernet peripheral */ Ethernet_Configuration(); /* SystTick configuration: an interrupt every 10ms */ RCC_GetClocksFreq(&RCC_Clocks); SysTick_Config(RCC_Clocks.SYSCLK_Frequency / 100); /* Update the SysTick IRQ priority should be higher than the Ethernet IRQ */ /* The Localtime should be updated during the Ethernet packets processing */ NVIC_SetPriority (SysTick_IRQn, 1); } /** * @brief Configures the Ethernet Interface * @param None * @retval None */ void Ethernet_Configuration(void) { ETH_InitTypeDef ETH_InitStructure; /* MII/RMII Media interface selection ------------------------------------------*/ #ifdef MII_MODE /* Mode MII with STM3210C-EVAL */ GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_MII); /* Get HSE clock = 25MHz on PA8 pin (MCO) */ RCC_MCOConfig(RCC_MCO_HSE); #elif defined RMII_MODE /* Mode RMII with STM3210C-EVAL */ GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_RMII); /* Set PLL3 clock output to 50MHz (25MHz /5 *10 =50MHz) */ RCC_PLL3Config(RCC_PLL3Mul_10); /* Enable PLL3 */ RCC_PLL3Cmd(ENABLE); /* Wait till PLL3 is ready */ while (RCC_GetFlagStatus(RCC_FLAG_PLL3RDY) == RESET) {} /* Get PLL3 clock on PA8 pin (MCO) */ RCC_MCOConfig(RCC_MCO_PLL3CLK); #endif /* 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_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 */ ETH_Init(Ð_InitStructure, PHY_ADDRESS); /* Enable the Ethernet Rx Interrupt */ ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE); } /** * @brief Configures the different GPIO ports. * @param None * @retval None */ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_SetBits(GPIOE,GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2); GPIO_ResetBits(GPIOE,GPIO_Pin_2); /* ETHERNET pins configuration */ /* AF Output Push Pull: - ETH_MII_MDIO / ETH_RMII_MDIO: PA2 - ETH_MII_MDC / ETH_RMII_MDC: PC1 - ETH_MII_TXD2: PC2 - ETH_MII_TX_EN / ETH_RMII_TX_EN: PB11 - ETH_MII_TXD0 / ETH_RMII_TXD0: PB12 - ETH_MII_TXD1 / ETH_RMII_TXD1: PB13 - ETH_MII_PPS_OUT / ETH_RMII_PPS_OUT: PB5 - ETH_MII_TXD3: PB8 */ /* Configure PA2 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure PC1 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Configure PB11, PB12 and PB13 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_12 | GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Configure PA0, PA1 and PA3 as input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure PB10 as input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Configure PC3 as input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_3); /// LAN8720_RST=0; //硬件复位LAN8720 delay_ms(500); GPIO_SetBits(GPIOA,GPIO_Pin_3); } void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); /* 2 bit for pre-emption priority, 2 bits for subpriority */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 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);
ETH工作模式、MCU的GPIO管脚配置(stm32f107.c)
void ETH_IRQHandler(void) { /* Handles all the received frames */ while(ETH_GetRxPktSize() != 0) { LwIP_Pkt_Handle(); } /* Clear the Eth DMA Rx IT pending bits */ ETH_DMAClearITPendingBit(ETH_DMA_IT_R); ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS); }
增加以太网中断处理函数 ETH_IRQHandler (stm32f10x_it.c)
/** @defgroup PHY_basic_status_register * @{ */ #define PHY_AutoNego_Complete ((u16)0x0020) /*!< Auto-Negotioation process completed */ #define PHY_Linked_Status ((u16)0x0004) /*!< Valid link established */ #define PHY_Jabber_detection ((u16)0x0002) /*!< Jabber condition detected */ /** @defgroup PHY_status_register * @{ */ /* The PHY status register value change from a PHY to another so the user have to update this value depending on the used external PHY */ /** * @brief For LAN8700 */ #define PHY_SR 31 /*!< Tranceiver Status Register */ /** * @brief For DP83848 */ //#define PHY_SR 16 /*!< Tranceiver Status Register */ /* The Speed and Duplex mask values change from a PHY to another so the user have to update this value depending on the used external PHY */ /** * @brief For LAN8700 */ #define PHY_Speed_Status ((u16)0x0004) /*!< Configured information of Speed: 10Mbps */ #define PHY_Duplex_Status ((u16)0x0010) /*!< Configured information of Duplex: Full-duplex */ /** * @brief For DP83848 */ //#define PHY_Speed_Status ((u16)0x0002) /*!< Configured information of Speed: 10Mbps */ //#define PHY_Duplex_Status ((u16)0x0004) /*!< Configured information of Duplex: Full-duplex */
PHY芯片的配置(stm32_eth.h)