LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)

1.创建工程
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片


2.移植库文件
将STM32F107_ETH_LwIP_V1.0.0中的库文件拷贝到工程中
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

添加文件和路径
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

创建main.c
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

将STM32F107_ETH_LwIP_V1.0.0中的中断入口文件和配置文件拷贝到工程中
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

删除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|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

设置预编译符号
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

编译,无错误无警告
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片


3.移植FreeRTOS
将FreeRTOSv10.3.1中的源码拷贝到工程中

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

删除不需要的架构文件


LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

添加文件和路径
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片


LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

将FreeRTOSv10.3.1中demo中配置文件拷贝到工程中
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

修改异常向量入口
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

创建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|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片


4.移植库文件LwIP
将lwip-2.1.2中的源码拷贝到工程中
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

添加文件和路径
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

将STM32F2x7_ETH_LwIP_V1.1.0中配置文件拷贝到工程中
【LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)】LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

将STM32F2x7_ETH_LwIP_V1.1.0中架构相关文件拷贝到工程中,并添加路径
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

编译发现部分变量类型重复定义,将cc.h中重复的部分注释掉
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

将contrib-2.1.0中FreeRTOS架构文件拷贝并覆盖到工程中
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

将sys_arch.c添加到工程中
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

编译发现,FreeRTOS部分功能未开启,修改FreeRTOS配置文件
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

编译发现,LwIP配置文件中configMAX_PRIORITIES未定义,修改
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

编译发现,不允许TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN,修改
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

编译发现,errno未定义,定义
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片


5.移植DP83848网卡驱动
将STM32F2x7_ETH_LwIP_V1.1.0网卡驱动拷贝到工程中
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

将网卡驱动文件添加到工程,并结合STM32F107_ETH_LwIP_V1.0.0工程进行适当修改
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

/** * @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_RXBUFNB4 #define ETH_TXBUFNB2#defineETH_DMARxDesc_FrameLengthShift16 #defineETH_ERROR((u32)0) #defineETH_SUCCESS((u32)1)/* Ethernet Rx & Tx DMA Descriptors */ ETH_DMADESCTypeDefDMARxDscrTab[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); }/** * @briefThis function handles ETH interrupt request. * @paramNone * @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|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

创建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_ADDRESS0x01/* 功能: 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 *//** * @briefInitializes the lwIP stack * @paramNone * @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|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

编译运行,ping成功
LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)
文章图片

    推荐阅读