LwIP移植到FreeRTOS(STM32F107+DP83848)

1.创建工程

LwIP移植到FreeRTOS(STM32F107+DP83848)_第1张图片
 

2.移植库文件

将STM32F107_ETH_LwIP_V1.0.0中的库文件拷贝到工程中

LwIP移植到FreeRTOS(STM32F107+DP83848)_第2张图片

添加文件和路径

LwIP移植到FreeRTOS(STM32F107+DP83848)_第3张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第4张图片

创建main.c

LwIP移植到FreeRTOS(STM32F107+DP83848)_第5张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第6张图片

将STM32F107_ETH_LwIP_V1.0.0中的中断入口文件和配置文件拷贝到工程中

LwIP移植到FreeRTOS(STM32F107+DP83848)_第7张图片

删除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)
{}

添加路径

LwIP移植到FreeRTOS(STM32F107+DP83848)_第8张图片

设置预编译符号

LwIP移植到FreeRTOS(STM32F107+DP83848)_第9张图片

编译,无错误无警告

LwIP移植到FreeRTOS(STM32F107+DP83848)_第10张图片

 

3.移植FreeRTOS

将FreeRTOSv10.3.1中的源码拷贝到工程中

 

LwIP移植到FreeRTOS(STM32F107+DP83848)_第11张图片

删除不需要的架构文件

 

 

LwIP移植到FreeRTOS(STM32F107+DP83848)_第12张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第13张图片

添加文件和路径

LwIP移植到FreeRTOS(STM32F107+DP83848)_第14张图片

 

LwIP移植到FreeRTOS(STM32F107+DP83848)_第15张图片

将FreeRTOSv10.3.1中demo中配置文件拷贝到工程中

LwIP移植到FreeRTOS(STM32F107+DP83848)_第16张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第17张图片

修改异常向量入口

LwIP移植到FreeRTOS(STM32F107+DP83848)_第18张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第19张图片

创建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调试,在任务中打上断点,系统调度正常

LwIP移植到FreeRTOS(STM32F107+DP83848)_第20张图片

 

4.移植库文件LwIP

将lwip-2.1.2中的源码拷贝到工程中

LwIP移植到FreeRTOS(STM32F107+DP83848)_第21张图片

添加文件和路径

LwIP移植到FreeRTOS(STM32F107+DP83848)_第22张图片LwIP移植到FreeRTOS(STM32F107+DP83848)_第23张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第24张图片

将STM32F2x7_ETH_LwIP_V1.1.0中配置文件拷贝到工程中

LwIP移植到FreeRTOS(STM32F107+DP83848)_第25张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第26张图片

将STM32F2x7_ETH_LwIP_V1.1.0中架构相关文件拷贝到工程中,并添加路径

LwIP移植到FreeRTOS(STM32F107+DP83848)_第27张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第28张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第29张图片

编译发现部分变量类型重复定义,将cc.h中重复的部分注释掉

LwIP移植到FreeRTOS(STM32F107+DP83848)_第30张图片

将contrib-2.1.0中FreeRTOS架构文件拷贝并覆盖到工程中

LwIP移植到FreeRTOS(STM32F107+DP83848)_第31张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第32张图片

将sys_arch.c添加到工程中

LwIP移植到FreeRTOS(STM32F107+DP83848)_第33张图片

编译发现,FreeRTOS部分功能未开启,修改FreeRTOS配置文件

LwIP移植到FreeRTOS(STM32F107+DP83848)_第34张图片

编译发现,LwIP配置文件中configMAX_PRIORITIES未定义,修改

LwIP移植到FreeRTOS(STM32F107+DP83848)_第35张图片

编译发现,不允许TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN,修改

LwIP移植到FreeRTOS(STM32F107+DP83848)_第36张图片

编译发现,errno未定义,定义

LwIP移植到FreeRTOS(STM32F107+DP83848)_第37张图片

 

5.移植DP83848网卡驱动

将STM32F2x7_ETH_LwIP_V1.1.0网卡驱动拷贝到工程中

LwIP移植到FreeRTOS(STM32F107+DP83848)_第38张图片

LwIP移植到FreeRTOS(STM32F107+DP83848)_第39张图片

将网卡驱动文件添加到工程,并结合STM32F107_ETH_LwIP_V1.0.0工程进行适当修改

LwIP移植到FreeRTOS(STM32F107+DP83848)_第40张图片

/**
 * @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配置文件

LwIP移植到FreeRTOS(STM32F107+DP83848)_第41张图片

创建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配置文件

LwIP移植到FreeRTOS(STM32F107+DP83848)_第42张图片

编译运行,ping成功

LwIP移植到FreeRTOS(STM32F107+DP83848)_第43张图片

你可能感兴趣的:(LwIP,STM32,FreeRTOS)