初始化和收发函数是按官司主例子enet_lwip、enet_uip改的,代码如下:
/* ****************************************************************************************************** ** 标志位定义 ** ****************************************************************************************************** */ uint8_t ETH_FLAG_RXPKT; //->0:没收到数据包 1:接收到数据包 uint8_t ETH_FLAG_TXPKT; //->0:数据包发送完成 1:数据包等待发送 /* ****************************************************************************************************** ** 描述和状态定义以及EMAC内存分配 ** ****************************************************************************************************** */ #define NUM_RX_DESCRIPTORS 3 #define NUM_TX_DESCRIPTORS 3 #define RX_BUFFER_SIZE 1536 #define TX_BUFFER_SIZE 1536 tEMACDMADescriptor RxDescriptor[NUM_TX_DESCRIPTORS]; tEMACDMADescriptor TxDescriptor[NUM_RX_DESCRIPTORS]; uint8_t RxBuffer[NUM_RX_DESCRIPTORS][RX_BUFFER_SIZE]; uint8_t TxBuffer[NUM_TX_DESCRIPTORS][TX_BUFFER_SIZE]; static uint32_t RxDescIndex; static uint32_t TxDescIndex;
/* ****************************************************************************************************** ** 设备信息定义 ** ****************************************************************************************************** */ typedef struct { uint8_t mac[6]; //MAC地址. uint8_t ip[4]; //IP地址. uint8_t mark[4]; //子网掩码. uint8_t gate[4]; //默认网关. }device_t; device_t Device;
static const uint8_t IP[4] ={192,168,1,88}; //本机IP地址. static const uint8_t MARK[4] ={255,255,255,0}; //子网掩码. static const uint8_t GATE[4] ={192,168,1,1}; //默认网关.
/* ****************************************************************************************************** **函数名称: void InitDescriptors(void) ** **函数描述: 初始化发送、接收描述相关参量(OWN = 1:owned by the DMA OWN = 0:owned by the CPU) ** **参数: 无 ** **返回: 无 ** ****************************************************************************************************** */ void InitDescriptors(void) {uint32_t ui32Loop;// Initialize each of the receive descriptors. Set the OWN bit here to make sure that the receiver can start writing anything immediately.for(ui32Loop = 0; ui32Loop < NUM_RX_DESCRIPTORS; ui32Loop++){RxDescriptor[ui32Loop].ui32CtrlStatus = DES0_RX_CTRL_OWN;RxDescriptor[ui32Loop].ui32Count = (DES1_RX_CTRL_CHAINED | (RX_BUFFER_SIZE << DES1_RX_CTRL_BUFF1_SIZE_S));RxDescriptor[ui32Loop].pvBuffer1 = RxBuffer[ui32Loop];RxDescriptor[ui32Loop].DES3.pLink = (ui32Loop == (NUM_RX_DESCRIPTORS - 1)) ? &RxDescriptor[0] : &RxDescriptor[ui32Loop + 1];} // Initialize each of the transmit descriptors. Note that we leave the OWN bit clear here since we have not set up any transmissions yet.for(ui32Loop = 0; ui32Loop < NUM_TX_DESCRIPTORS; ui32Loop++){TxDescriptor[ui32Loop].ui32CtrlStatus = (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_IP_ALL_CKHSUMS); TxDescriptor[ui32Loop].ui32Count = (DES1_TX_CTRL_SADDR_INSERT | (TX_BUFFER_SIZE << DES1_TX_CTRL_BUFF1_SIZE_S));TxDescriptor[ui32Loop].pvBuffer1 = TxBuffer[ui32Loop];TxDescriptor[ui32Loop].DES3.pLink = (ui32Loop == (NUM_TX_DESCRIPTORS - 1)) ? &TxDescriptor[0] : &TxDescriptor[ui32Loop + 1];}// Start from the beginning of both descriptor chains. We actually set the transmit descriptor index to the last descriptor in the chain// since it will be incremented before use and this means the first transmission we perform will use the correct descriptor.RxDescIndex = 0;TxDescIndex = 0; // Set the descriptor pointers in the hardware.EMACRxDMADescriptorListSet(EMAC0_BASE, RxDescriptor);EMACTxDMADescriptorListSet(EMAC0_BASE, TxDescriptor); } /* ****************************************************************************************************** **函数名称: uint32_t PacketReceive(uint8_t *pui8Buf) ** **函数描述: 从DMA接收缓冲区读取一个数据包 ** **参数: pui8Buf-------数据包存储缓冲区指针 ** **返回: i32FrameLen---数据长度 ** ****************************************************************************************************** */ uint32_t PacketReceive(uint8_t *pui8Buf) {uint32_t i32FrameLen, i32Loop;// Check the arguments.ASSERT(pui8Buf != 0);// By default, we assume we got a bad frame.i32FrameLen = 0;// Make sure that CPU own the receive descriptor.if(!(RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_CTRL_OWN)){// We own the receive descriptor so check to see if it contains a valid frame. Look for a descriptor error, // indicating that the incoming packet was truncated or, if this is the last frame in a packet, the receive error bit.if(!(RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_STAT_ERR)){// We have a valid frame so copy the content to the supplied buffer. First check that the "last descriptor" flag is set. // We sized the receive buffer such that it can always hold a valid frame so this flag should never be clear at this point but...if(RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_STAT_LAST_DESC){i32FrameLen = ((RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_STAT_FRAME_LENGTH_M) >> DES0_RX_STAT_FRAME_LENGTH_S);// Sanity check.if(i32FrameLen > RX_BUFFER_SIZE){i32FrameLen = RX_BUFFER_SIZE;}// Copy the data from the DMA receive buffer into the provided frame buffer.for(i32Loop = 0; i32Loop < i32FrameLen; i32Loop++){pui8Buf[i32Loop] = RxBuffer[RxDescIndex][i32Loop];}}}// Move on to the next descriptor in the chain.RxDescIndex++;if(RxDescIndex == NUM_RX_DESCRIPTORS){RxDescIndex = 0;}// Give this descriptor back to the DMA.RxDescriptor[RxDescIndex].ui32CtrlStatus = DES0_RX_CTRL_OWN;}// Return the Frame Length.return(i32FrameLen); } /* ****************************************************************************************************** **函数名称: uint32_t PacketTransmit(uint8_t *pui8Buf, uint32_t i32BufLen) ** **函数描述: 发送数据包 ** **参数: pui8Buf-----待发送数据包缓冲区指针 ** ** i32BufLen---待发送数据包的长度 ** **返回: i32BufLen---实际发送数据的长度 ** ****************************************************************************************************** */ uint32_t PacketTransmit(uint8_t *pui8Buf, uint32_t i32BufLen) {uint32_t i32Loop;// Indicate that a packet is being sent.ETH_FLAG_TXPKT = 1; printf("ETH_FLAG_TXPKT = 1;\r\n");// Wait for the previous packet to be transmitted.while(TxDescriptor[TxDescIndex].ui32CtrlStatus & DES0_TX_CTRL_OWN); printf("ETH_FLAG_TXPKT = 2;\r\n");// Sanity check.if(i32BufLen > TX_BUFFER_SIZE){i32BufLen = TX_BUFFER_SIZE;}// Copy the packet data into the transmit buffer.for(i32Loop = 0; i32Loop < i32BufLen; i32Loop++){TxBuffer[TxDescIndex][i32Loop] = pui8Buf[i32Loop];}// Move to the next descriptor.TxDescIndex++;if(TxDescIndex == NUM_TX_DESCRIPTORS){TxDescIndex = 0;}// Fill in the packet size and tell the transmitter to start work.TxDescriptor[TxDescIndex].ui32Count = (uint32_t)i32BufLen;TxDescriptor[TxDescIndex].ui32CtrlStatus = ( DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_IP_ALL_CKHSUMS | DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_OWN);// Tell the DMA to reacquire the descriptor now that we've filled it in.EMACTxDMAPollDemand(EMAC0_BASE); printf("ETH_FLAG_TXPKT = 3;\r\n");// Return the number of bytes sent.return(i32BufLen); } /* ****************************************************************************************************** **函数名称: void HAL_EMAC_Init(void) ** **函数描述: 网口初始化 ** **参数: 无 ** **返回: 无 ** ****************************************************************************************************** */ void HAL_EMAC_Init(void) { // PF0/PF1/PF4 are used for Ethernet LEDs. GPIOPinConfigure(GPIO_PF0_EN0LED0); GPIOPinConfigure(GPIO_PF4_EN0LED1); GPIOPinConfigure(GPIO_PF1_EN0LED2); GPIOPinTypeEthernetLED(GPIOF_AHB_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4);// Wait for the MAC to be ready.while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0));// Configure for use with the internal PHY.EMACPHYConfigSet(EMAC0_BASE, EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN | EMAC_PHY_AN_100B_T_FULL_DUPLEX);// Reset the MAC.EMACReset(EMAC0_BASE);// Initialize the MAC and set the DMA mode.EMACInit(EMAC0_BASE, SystemCoreClock, EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4, 0);// Set MAC configuration options.EMACConfigSet(EMAC0_BASE,(EMAC_CONFIG_FULL_DUPLEX |EMAC_CONFIG_CHECKSUM_OFFLOAD |EMAC_CONFIG_7BYTE_PREAMBLE |EMAC_CONFIG_IF_GAP_96BITS |EMAC_CONFIG_USE_MACADDR0 |EMAC_CONFIG_SA_FROM_DESCRIPTOR |EMAC_CONFIG_BO_LIMIT_1024),(EMAC_MODE_RX_STORE_FORWARD |EMAC_MODE_TX_STORE_FORWARD |EMAC_MODE_TX_THRESHOLD_64_BYTES |EMAC_MODE_RX_THRESHOLD_64_BYTES), 0);// Initialize the Ethernet DMA descriptors.InitDescriptors();// Program the hardware with its MAC address (for filtering).EMACAddrSet(EMAC0_BASE, 0, Device.mac);// Wait for the link to become active.//while((EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) & EPHY_BMSR_LINKSTAT) == 0);// Set MAC filtering options. We receive all broadcast and multicast packets along with those addressed specifically for us.EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_SADDR | EMAC_FRMFILTER_PASS_MULTICAST | EMAC_FRMFILTER_PASS_NO_CTRL));// Clear any pending interrupts.EMACIntClear(EMAC0_BASE, EMACIntStatus(EMAC0_BASE, false));// Enable the Ethernet MAC transmitter and receiver.EMACTxEnable(EMAC0_BASE);EMACRxEnable(EMAC0_BASE);// Enable the Ethernet interrupt.IntEnable(INT_EMAC0);// Enable the Ethernet RX Packet interrupt source.EMACIntEnable(EMAC0_BASE, EMAC_INT_RECEIVE | EMAC_INT_TRANSMIT); } /* ****************************************************************************************************** **函数名称: void ENET_IRQHandler(void) ** **函数描述: 以太网中断服务程序 ** **参数: 无 ** **返回: 无 ** ****************************************************************************************************** */ void ETH_Handler(void) {uint32_t IntStatus;// Read and Clear the interrupt.IntStatus = EMACIntStatus(EMAC0_BASE, true);MAP_EMACIntClear(EMAC0_BASE, IntStatus);// Check to see if an RX Interrupt has occurred.if(IntStatus & EMAC_INT_RECEIVE){// Indicate that a packet has been received.ETH_FLAG_RXPKT = 1;}// Has the DMA finished transferring a packet to the transmitter?if(IntStatus & EMAC_INT_TRANSMIT){// Indicate that a packet has been sent.ETH_FLAG_TXPKT = 0;} }
/* ****************************************************************************************************** **函数名称: void Config(void) ** **函数描述: 参数配置函数 ** **参数: 无 ** **返回: 无 ** ****************************************************************************************************** */ void Config(void) { uint32_t ui32User0, ui32User1; FlashUserGet(&ui32User0, &ui32User1);if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff)){//// We should never get here. This is an error if the MAC address has// not been programmed into the device. Exit the program.// Let the user know there is no MAC address//printf("No MAC programmed!\n");while(1){}} Device.mac[0] = ((ui32User0 >> 0) & 0xff);Device.mac[1] = ((ui32User0 >> 8) & 0xff);Device.mac[2] = ((ui32User0 >> 16) & 0xff);Device.mac[3] = ((ui32User1 >> 0) & 0xff);Device.mac[4] = ((ui32User1 >> 8) & 0xff);Device.mac[5] = ((ui32User1 >> 16) & 0xff); memcpy(Device.ip,IP,4); //IP memcpy(Device.mark, MARK, 4); //MARK memcpy(Device.gate, GATE, 4); //GATEWAY }
/* ****************************************************************************************************** **函数名称: void APP_LWIP_Init(void) ** **函数描述: 初始化LWIP所有相关信息 ** **参数: 无 ** **返回: 无 ** ****************************************************************************************************** */ void APP_LWIP_Init(void) {
Config();
HAL_EMAC_Init(); //初始化EMAC. lwip_init(); //LwIP协议栈初始化. // add the network interface. netif_add(&my_netif, (ip4_addr_t *)&Device.ip, (ip4_addr_t *)&Device.mark, (ip4_addr_t *)&Device.gate, NULL, ethernetif_init, ethernet_input); // Registers the default network interface. netif_set_default(&my_netif);netif_set_up(&my_netif); //HTTP应用层初始化 //httpd_init(); //初始化HTTP服务器监听端口. //httpd_cgi_ssi_init(); //CGI、SSI相关初始化. //TCP应用层初始化 //tcp_server_init(); //初始化TCP服务器. //UDP应用层初始化 //udp_server_init(); //初始化UDP服务器. }
ethernetif.c代码如附件
打开LWIP_DEBUG部分调试功能,ping 192.168.1.88时,串口输出如下:
如上图,说明以太网已正确收到ARP请求,可在发送以太网数据帧时一直在等待,
while(TxDescriptor[TxDescIndex].ui32CtrlStatus & DES0_TX_CTRL_OWN);
只打印出来
printf("ETH_FLAG_TXPKT = 1;\r\n");
而没有打印
printf("ETH_FLAG_TXPKT = 2;\r\n");
求大神帮忙~!谢谢!
gaoyang9992006:
http://www.deyisupport.com/question_answer/microcontrollers/tiva_arm_cortex/f/96.aspx
请到这个版块提问,本版块维护者不太擅长这个系列。