1.创建工程
2.移植库文件
将STM32F107_ETH_LwIP_V1.0.0中的库文件拷贝到工程中
添加文件和路径
创建main.c
将STM32F107_ETH_LwIP_V1.0.0中的中断入口文件和配置文件拷贝到工程中
删除stm32f10x_it.h和stm32f10x_it.c中不需要的内容
#ifndef __STM32F10x_IT_H
#define __STM32F10x_IT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f10x.h"
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
#ifdef __cplusplus
}
#endif
#endif
#include "stm32f10x_it.h"
void NMI_Handler(void)
{}
void HardFault_Handler(void)
{
while(1)
{}
}
void MemManage_Handler(void)
{
while(1)
{}
}
void BusFault_Handler(void)
{
while(1)
{}
}
void UsageFault_Handler(void)
{
while(1)
{}
}
void SVC_Handler(void)
{}
void DebugMon_Handler(void)
{}
void PendSV_Handler(void)
{}
void SysTick_Handler(void)
{}
添加路径
设置预编译符号
编译,无错误无警告
3.移植FreeRTOS
将FreeRTOSv10.3.1中的源码拷贝到工程中
删除不需要的架构文件
添加文件和路径
将FreeRTOSv10.3.1中demo中配置文件拷贝到工程中
修改异常向量入口
创建rcc.h、rcc.c、nvic.h、nvic.c、freertos.c五个文件
#ifndef __RCC_H_
#define __RCC_H_
/* 功能: RCC时钟配置
参数: 无
返回值:无
*/
void rcc_config(void);
#endif
#include "stm32f10x.h"
#include "stm32f10x_flash.h"
#include "rcc.h"
/* 功能: RCC时钟配置
参数: 无
返回值:无
*/
void rcc_config(void)
{
ErrorStatus HSEStartUpStatus;
/* RCC寄存器设置为默认配置 */
RCC_DeInit();
/* 打开外部高速时钟 */
RCC_HSEConfig(RCC_HSE_ON);
/* 等待外部高速时钟稳定 */
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
/* 设置HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* 设置PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* 设置PCLK1 = HCLK / 2 */
RCC_PCLK1Config(RCC_HCLK_Div2);
/* 设置FLASH代码延时 */
FLASH_SetLatency(FLASH_Latency_2);
/* 使能预取址缓存 */
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
RCC_PREDIV2Config(RCC_PREDIV2_Div5);
RCC_PLL2Config(RCC_PLL2Mul_8);
RCC_PLL2Cmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLL2RDY)== RESET){}
RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5);
RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);
/* 使能PLL */
RCC_PLLCmd(ENABLE);
/* 等待PLL稳定 */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
/* 设置PLL为系统时钟源 */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* 等待系统时钟源切换到PLL */
while(RCC_GetSYSCLKSource() != 0x08);
/* 设置系统节拍器时钟源为FCLK */
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
}
}
#ifndef __NVIC_H_
#define __NVIC_H_
/* 功能: 中断嵌套控制器配置
参数: 无
返回值:无
*/
void nvic_config(void);
#endif
#include "stm32f10x.h"
#include "nvic.h"
/* 功能: 中断嵌套控制器配置
参数: 无
返回值:无
*/
void nvic_config(void)
{
/* 选择中断分组4 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
}
#include "FreeRTOS.h"
#include "task.h"
void lwip_task(void *argument);
/* 功能: freertos初始化
参数: 无
返回值:无
*/
void freertos_init(void)
{
/* 按键任务 */
xTaskCreate(lwip_task, "lwip_task", 128, NULL, 4, NULL);
}
/* lwip任务 */
void lwip_task(void *argument)
{
while(1)
{
vTaskDelay(1000);
}
}
修改main.c
#include "stm32f10x.h"
#include "rcc.h"
#include "nvic.h"
#include "FreeRTOS.h"
#include "task.h"
/* 硬件初始化 */
static void prvSetupHardware(void);
/* freertos初始化 */
void freertos_init(void);
/* 主函数 */
int main(void)
{
/* 硬件初始化 */
prvSetupHardware();
/* freertos初始化 */
freertos_init();
/* 启动调度器 */
vTaskStartScheduler();
}
/* 硬件初始化 */
static void prvSetupHardware(void)
{
/* 时钟配置 */
rcc_config();
/* 中断嵌套控制器配置 */
nvic_config();
}
使用j-link调试,在任务中打上断点,系统调度正常
4.移植库文件LwIP
将lwip-2.1.2中的源码拷贝到工程中
添加文件和路径
将STM32F2x7_ETH_LwIP_V1.1.0中配置文件拷贝到工程中
将STM32F2x7_ETH_LwIP_V1.1.0中架构相关文件拷贝到工程中,并添加路径
编译发现部分变量类型重复定义,将cc.h中重复的部分注释掉
将contrib-2.1.0中FreeRTOS架构文件拷贝并覆盖到工程中
将sys_arch.c添加到工程中
编译发现,FreeRTOS部分功能未开启,修改FreeRTOS配置文件
编译发现,LwIP配置文件中configMAX_PRIORITIES未定义,修改
编译发现,不允许TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN,修改
编译发现,errno未定义,定义
5.移植DP83848网卡驱动
将STM32F2x7_ETH_LwIP_V1.1.0网卡驱动拷贝到工程中
将网卡驱动文件添加到工程,并结合STM32F107_ETH_LwIP_V1.0.0工程进行适当修改
/**
* @file
* Ethernet Interface Skeleton
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels
*
*/
/*
* This file is a skeleton for developing Ethernet network interface
* drivers for lwIP. Add code to the low_level functions and do a
* search-and-replace for the word "ethernetif" to replace it with
* something that better describes your network interface.
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "netif/etharp.h"
#include "ethernetif.h"
#include "stm32_eth.h"
#include
#include "FreeRTOS.h"
#include "semphr.h"
#define netifMTU (1500)
#define netifINTERFACE_TASK_STACK_SIZE ( 350 )
#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define netifGUARD_BLOCK_TIME ( 250 )
/* The time to block waiting for input. */
#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 )
/* Define those to better describe your network interface. */
#define IFNAME0 's'
#define IFNAME1 't'
static struct netif *s_pxNetIf = NULL;
xSemaphoreHandle s_xSemaphore = NULL;
#define ETH_RXBUFNB 4
#define ETH_TXBUFNB 2
#define ETH_DMARxDesc_FrameLengthShift 16
#define ETH_ERROR ((u32)0)
#define ETH_SUCCESS ((u32)1)
/* Ethernet Rx & Tx DMA Descriptors */
ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
/* Ethernet Receive buffers */
uint8_t Rx_Buff[ETH_RXBUFNB][ETH_MAX_PACKET_SIZE];
/* Ethernet Transmit buffers */
uint8_t Tx_Buff[ETH_TXBUFNB][ETH_MAX_PACKET_SIZE];
/* Global pointers to track current transmit and receive descriptors */
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);
static void ethernetif_input( void * pvParameters );
/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void low_level_init(struct netif *netif)
{
uint32_t i;
/* set netif MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* set netif MAC hardware address */
netif->hwaddr[0] = 0x00;
netif->hwaddr[1] = 0x80;
netif->hwaddr[2] = 0xE1;
netif->hwaddr[3] = 0x00;
netif->hwaddr[4] = 0x00;
netif->hwaddr[5] = 0x00;
/* set netif maximum transfer unit */
netif->mtu = 1500;
/* Accept broadcast address and ARP traffic */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
s_pxNetIf =netif;
/* create binary semaphore used for informing ethernetif of frame reception */
if (s_xSemaphore == NULL)
{
s_xSemaphore= xSemaphoreCreateCounting(20,0);
}
/* initialize MAC address in ethernet MAC */
ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr);
/* 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 */
{
for(i=0; iBuffer1Addr);
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);
xSemaphoreGive(xTxSemaphore);
}
return ERR_OK;
}
/**
* 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;
uint32_t l=0;
FrameTypeDef frame;
u8 *buffer;
p = NULL;
/* Get received frame */
frame = ETH_RxPkt_ChainMode();
/* check that frame has no error */
if ((frame.descriptor->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET)
{
/* 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);
/* Copy received frame from ethernet driver buffer to stack buffer */
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;
}
/**
* This function is the ethernetif_input task, it is processed 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
*/
void ethernetif_input( void * pvParameters )
{
struct pbuf *p;
for( ;; )
{
if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
{
p = low_level_input( s_pxNetIf );
if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
{
pbuf_free(p);
p=NULL;
}
}
}
}
/**
* 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)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = etharp_output;
netif->linkoutput = low_level_output;
/* initialize the hardware */
low_level_init(netif);
return ERR_OK;
}
/*******************************************************************************
* 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);
}
/**
* @brief This function handles ETH interrupt request.
* @param None
* @retval None
*/
void ETH_IRQHandler(void)
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* Frame received */
if ( ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET)
{
/* Give the semaphore to wakeup LwIP task */
xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );
}
/* Clear the interrupt flags. */
/* Clear the Eth DMA Rx IT pending bits */
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
/* Switch tasks if necessary. */
if( xHigherPriorityTaskWoken != pdFALSE )
{
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
}
编译发现,FreeRTOS部分功能未开启,修改FreeRTOS配置文件
创建eth.h和eth.c文件
#ifndef __ETH_H_
#define __ETH_H_
/* 功能: ETH配置
参数: 无
返回值:无
*/
void eth_config(void);
#endif
#include "stm32_eth.h"
#include "eth.h"
#define PHY_ADDRESS 0x01
/* 功能: ETH配置
参数: 无
返回值:无
*/
void eth_config(void)
{
///
/* 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_AFIO, ENABLE);
///
GPIO_InitTypeDef GPIO_InitStructure;
/* SWJ重映射 */
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
/* ETH重映射 */
GPIO_PinRemapConfig(GPIO_Remap_ETH, ENABLE);
/* MCO输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ETHERNET pins configuration
- ETH_MII_MDIO / ETH_RMII_MDIO: PA2
- ETH_MII_MDC / ETH_RMII_MDC: PC1
- 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_RX_CLK / ETH_RMII_REF_CLK: PA1
- ETH_MII_RX_DV / ETH_RMII_CRS_DV: PD8
- ETH_MII_RXD0 / ETH_RMII_RXD0: PD9
- ETH_MII_RXD1 / ETH_RMII_RXD1: PD10 */
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);
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);
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);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOD, &GPIO_InitStructure);
///
/* NVIC configuration */
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the Ethernet global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
///
ETH_InitTypeDef ETH_InitStructure;
/* RMII Media interface selection ------------------------------------------*/
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);
/* 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);
}
修改main.c
#include "stm32f10x.h"
#include "rcc.h"
#include "nvic.h"
#include "eth.h"
#include "FreeRTOS.h"
#include "task.h"
/* 硬件初始化 */
static void prvSetupHardware(void);
/* freertos初始化 */
void freertos_init(void);
/* 主函数 */
int main(void)
{
/* 硬件初始化 */
prvSetupHardware();
/* freertos初始化 */
freertos_init();
/* 启动调度器 */
vTaskStartScheduler();
}
/* 硬件初始化 */
static void prvSetupHardware(void)
{
/* 时钟配置 */
rcc_config();
/* 中断嵌套控制器配置 */
nvic_config();
/* ETH配置 */
eth_config();
}
创建lwip.h和lwip.c
#ifndef __LWIP_H_
#define __LWIP_H_
void LwIP_Init(void);
#endif
#include "lwip.h"
#include "lwip/tcpip.h"
#include "ethernetif.h"
struct netif xnetif; /* network interface structure */
/**
* @brief Initializes the lwIP stack
* @param None
* @retval None
*/
void LwIP_Init(void)
{
ip4_addr_t ipaddr, netmask, gw;
/* Create tcp_ip stack thread */
tcpip_init( NULL, NULL );
/* IP address setting & display on STM32_evalboard LCD*/
IP4_ADDR(&ipaddr, 192, 168, 1, 10);
IP4_ADDR(&netmask, 255, 255 , 255, 0);
IP4_ADDR(&gw, 192, 168, 1, 1);
/* - netif_add(struct netif *netif, struct ip_addr *ipaddr,
struct ip_addr *netmask, struct ip_addr *gw,
void *state, err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif))
Adds your network interface to the netif_list. Allocate a struct
netif and pass a pointer to this structure as the first argument.
Give pointers to cleared ip_addr structures when using DHCP,
or fill them with sane numbers otherwise. The state pointer may be NULL.
The init function pointer must point to a initialization function for
your ethernet netif interface. The following code illustrates it's use.*/
netif_add(&xnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
/* Registers the default network interface. */
netif_set_default(&xnetif);
/* When the netif is fully configured this function must be called.*/
netif_set_up(&xnetif);
}
修改freertos.c
#include "FreeRTOS.h"
#include "task.h"
#include "lwip.h"
void lwip_task(void *argument);
/* 功能: freertos初始化
参数: 无
返回值:无
*/
void freertos_init(void)
{
/* 按键任务 */
xTaskCreate(lwip_task, "lwip_task", 128, NULL, 4, NULL);
}
int errno;
/* lwip任务 */
void lwip_task(void *argument)
{
LwIP_Init();
while(1)
{
vTaskDelay(1000);
}
}
编译运行,ping不通。仿真发现是ICMP校验问题。修改lwip配置文件
编译运行,ping成功