STM32F4+FreeRTOS+FreeRTosTcpIp移植教程

        花了几天时间完成了FreeRTOS自带的TCP/IP协议栈在stm32F407上的移植,在此记录并分享,第一次写这个,写的不好的地方见谅。

         硬件是stm32F407最小系统(内带phy控制器),所以还需要一个phy芯片,选了DP83848这款不带协议栈的芯片。

 

 

选了一款淘宝上的以太网模块,内置芯片就是DP83848,只提供RMII接口(mac和phy的通信方式),自带50M振晶

(所以不需要stm32PA8口输出时钟源)。

两者硬件接口如下:

 

软件方面:

 

(1)需要完成stm32MAC控制器的初始化。(st库自带有)

(2)需要完成DP83848的驱动。(st库自带有)

(3)FreeRTos和Tcp/IP stack的移植。

(1)创建project

我选的st库是Keil.STM32F4xx_DFP.2.9.0.pack,里面就有关于以太网mac和phy的驱动程序,在keil里面创建工程并添加USER,

FreeRTOS和FreeRTOS-Plus-TCP三个文件夹,最后如下:
 

 

Device目录下是stm32外设的库,CMSIS Driver目录下就是关于mac和DP83848的库,这两个驱动的代码请自行结合里面(点击打开链接

Referance目录下Ethernet interface查看,其实就是C文件里各有一个结构体,里面有一些函数作初始化,读,写等。如下所示

 

两个控制块里面的函数何时调用,怎么使用,将在后面TCP移植处说明。

这里说一下简单的配置:

1.打开新建工程Device目录下RTE_Device.h文件,查找RTE_ETH宏,修改成1。

2.因为我们要使用RMII接口,所以确保RTE_Device.h下,宏RTE_ETH_MII为0,宏RTE_ETH_RMII为1,并查看一下GPIO的配置,默认如下:
 

你没修改其他配置的话,请按照上图GPIO配置接好stm32和DP83848。

(2)接下来是freertos的移植:我下载的是FreeRTOSv9.0.0

1.首先看看FreeRTOSv9.0.0里面source目录下的东西:

你没修改其他配置的话,请按照上图GPIO配置接好stm32和DP83848。

(2)接下来是freertos的移植:我下载的是FreeRTOSv9.0.0

1.首先看看FreeRTOSv9.0.0里面source目录下的东西:

至少需要tasks,queue,list才能构成freertos的内核,但是因为后面还要移植TCP/IP协议栈,所以其他部分也需要。portable目录里的东西和

硬件平台和编译软件有关,目录里面内容如下:

在这里,我们需要RVDS目录下ARM_CM4F文件夹内的port.cportmacro.h和MemMang目录下的heap_4.c

2.然后,我们把这些.c和.h添加到工程中的FreeRTOS目录下,现在工程目录如下图所示:

 

3.最后,我们需要一个配置文件来配置我们FreeRTOS内核的功能,在工程FreeRTOS目录的include文件夹内添加FreeRTOSConfig.h文件,

并将下面代码粘贴进去。


/*

    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.

    All rights reserved



    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.



    This file is part of the FreeRTOS distribution.



    FreeRTOS is free software; you can redistribute it and/or modify it under

    the terms of the GNU General Public License (version 2) as published by the

    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.



    ***************************************************************************

    >>!   NOTE: The modification to the GPL is included to allow you to     !<<

    >>!   distribute a combined work that includes FreeRTOS without being   !<<

    >>!   obliged to provide the source code for proprietary components     !<<

    >>!   outside of the FreeRTOS kernel.                                   !<<

    ***************************************************************************



    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY

    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS

    FOR A PARTICULAR PURPOSE.  Full license text is available on the following

    link: http://www.freertos.org/a00114.html



    ***************************************************************************

     *                                                                       *

     *    FreeRTOS provides completely free yet professionally developed,    *

     *    robust, strictly quality controlled, supported, and cross          *

     *    platform software that is more than just the market leader, it     *

     *    is the industry's de facto standard.                               *

     *                                                                       *

     *    Help yourself get started quickly while simultaneously helping     *

     *    to support the FreeRTOS project by purchasing a FreeRTOS           *

     *    tutorial book, reference manual, or both:                          *

     *    http://www.FreeRTOS.org/Documentation                              *

     *                                                                       *

    ***************************************************************************



    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading

    the FAQ page "My application does not run, what could be wrong?".  Have you

    defined configASSERT()?



    http://www.FreeRTOS.org/support - In return for receiving this top quality

    embedded software for free we request you assist our global community by

    participating in the support forum.



    http://www.FreeRTOS.org/training - Investing in training allows your team to

    be as productive as possible as early as possible.  Now you can receive

    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers

    Ltd, and the world's leading authority on the world's leading RTOS.



    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,

    including FreeRTOS+Trace - an indispensable productivity tool, a DOS

    compatible FAT file system, and our tiny thread aware UDP/IP stack.



    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.

    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.



    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High

    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS

    licenses offer ticketed support, indemnification and commercial middleware.



    http://www.SafeRTOS.com - High Integrity Systems also provide a safety

    engineered and independently SIL3 certified version for use in safety and

    mission critical applications that require provable dependability.



    1 tab == 4 spaces!

*/

 

 

#ifndef FREERTOS_CONFIG_H

#define FREERTOS_CONFIG_H

 

/*-----------------------------------------------------------

 * Application specific definitions.

 *

 * These definitions should be adjusted for your particular hardware and

 * application requirements.

 *

 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE

 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.

 *

 * See http://www.freertos.org/a00110.html.

 *----------------------------------------------------------*/

 

/* Ensure stdint is only used by the compiler, and not the assembler. */

#ifdef __ICCARM__

	#include <stdint.h>

	extern uint32_t SystemCoreClock;

#endif

 

#define configUSE_PREEMPTION			1

#define configUSE_IDLE_HOOK				0

#define configUSE_TICK_HOOK				0

#define configCPU_CLOCK_HZ				( (uint32_t) 168000000)

#define configTICK_RATE_HZ				( ( TickType_t ) 250 )

#define configMAX_PRIORITIES			( 5 )

#define configMINIMAL_STACK_SIZE		( ( unsigned short ) 130 )

#define configTOTAL_HEAP_SIZE			( ( size_t ) ( 50 * 1024 ) )

#define configMAX_TASK_NAME_LEN			( 16 )

#define configUSE_TRACE_FACILITY		0

#define configUSE_16_BIT_TICKS			0

#define configIDLE_SHOULD_YIELD			1

#define configUSE_MUTEXES				1

//#define configQUEUE_REGISTRY_SIZE		8

//#define configCHECK_FOR_STACK_OVERFLOW	0

//#define configUSE_RECURSIVE_MUTEXES		1

//#define configUSE_MALLOC_FAILED_HOOK	0

//#define configUSE_APPLICATION_TASK_TAG	0

#define configUSE_COUNTING_SEMAPHORES	1

//#define configGENERATE_RUN_TIME_STATS	0

 

/* Co-routine definitions. */

#define configUSE_CO_ROUTINES 		0

#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

 

 

/* Set the following definitions to 1 to include the API function, or zero

to exclude the API function. */

#define INCLUDE_vTaskPrioritySet		1

#define INCLUDE_uxTaskPriorityGet		1

#define INCLUDE_vTaskDelete				1

#define INCLUDE_vTaskCleanUpResources	1

#define INCLUDE_vTaskSuspend			1

#define INCLUDE_vTaskDelayUntil			1

#define INCLUDE_vTaskDelay				1

 

#define INCLUDE_xEventGroupSetBitsFromISR						1

#define INCLUDE_xTimerPendFunctionCall							1

 

/* Cortex-M specific definitions. */

#ifdef __NVIC_PRIO_BITS

	/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */

	#define configPRIO_BITS       		__NVIC_PRIO_BITS

#else

	#define configPRIO_BITS       		4        /* 15 priority levels */

#endif

 

/* The lowest interrupt priority that can be used in a call to a "set priority"

function. */

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			0xf

 

/* The highest interrupt priority that can be used by any interrupt service

routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL

INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER

PRIORITY THAN THIS! (higher priorities are lower numeric values. */

#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5

 

/* Interrupt priorities used by the kernel port layer itself.  These are generic

to all Cortex-M ports, and do not rely on any particular library functions. */

#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!

See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */

#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

	

/* Normal assert() semantics without relying on the provision of an assert.h

header file. */

//#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }	

 

/* used by software timers */

#define configUSE_TIMERS          1

#define configSUPPORT_DYNAMIC_ALLOCATION 1

#define configTIMER_TASK_PRIORITY  2

#define configTIMER_QUEUE_LENGTH   10

#define configTIMER_TASK_STACK_DEPTH        configMINIMAL_STACK_SIZE

/* used by software timers */

 

	

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS

standard names. */

#define vPortSVCHandler SVC_Handler

#define xPortPendSVHandler PendSV_Handler

#define xPortSysTickHandler SysTick_Handler

 

#endif /* FREERTOS_CONFIG_H */

 

OK,到现在,FreeRTOS已经可以在STM32上跑起来了。你自己随便写个LED灯的代码测试一下吧。FreeRTOS的API请参考这里

 

(3)最后是FreeRTOS自带的TCP/IP协议栈的移植:

首先看看FreeRTOS-Plus-Tcp目录下的文件:

protocols目录下为一些上层协议(Http,FTP等)暂时先不用,portable目录下的东西和上面内核代码一样,与硬件平台和编译软件有关,打开portable目录,显示如下:

 

BufferManagement目录下为以太网buffer管理方案,在此选择BufferAllocation_2.c(动态分配内存方案),更多详细信息请点击这里。

Compiler目录下的东西和编译器有关,这里是要提供两个编译器内置的命令以取消结构体自动字节对齐,如果你用的IDE是keil,那么默认编译器是armcc,你需要在Compiler目录下的pack_struct_start.h文件内添加#pragma pack(1),并在pack_struct_end.h文件内添加#pragma pack(),最后如下图所示:
 

NetworkInterface目录下的NetworkInterface.c文件和硬件有关,需要提供驱动的初始化,读,写等方法给FreeRTOS的TCP/IP协议栈调用,配置方法请参考这里。如果你不想花时间看,那就直接复制下面我写的,我并没有去实现FreeRTOS官方推荐的zero copy方法,实现的是另一种。具体如下:
 


/*

 * Some constants, hardware definitions and comments taken from ST's HAL driver

 * library, COPYRIGHT(c) 2015 STMicroelectronics.

 */

 

/*

 * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.

 * Authors include Hein Tibosch and Richard Barry

 *

 *******************************************************************************

 ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***

 ***                                                                         ***

 ***                                                                         ***

 ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***

 ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***

 ***   download):                                                            ***

 ***                                                                         ***

 ***   FreeRTOS+TCP is functional and has been used in commercial products   ***

 ***   for some time.  Be aware however that we are still refining its       ***

 ***   design, the source code does not yet quite conform to the strict      ***

 ***   coding and style standards mandated by Real Time Engineers ltd., and  ***

 ***   the documentation and testing is not necessarily complete.            ***

 ***                                                                         ***

 ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***

 ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***

 ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***

 ***   under a license other than that described below.                      ***

 ***                                                                         ***

 ***                                                                         ***

 ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***

 *******************************************************************************

 *

 * FreeRTOS+TCP can be used under two different free open source licenses.  The

 * license that applies is dependent on the processor on which FreeRTOS+TCP is

 * executed, as follows:

 *

 * If FreeRTOS+TCP is executed on one of the processors listed under the Special

 * License Arrangements heading of the FreeRTOS+TCP license information web

 * page, then it can be used under the terms of the FreeRTOS Open Source

 * License.  If FreeRTOS+TCP is used on any other processor, then it can be used

 * under the terms of the GNU General Public License V2.  Links to the relevant

 * licenses follow:

 *

 * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license

 * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license

 * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt

 *

 * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot

 * use FreeRTOS+TCP unless you agree that you use the software 'as is'.

 * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied

 * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR

 * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they

 * implied, expressed, or statutory.

 *

 * 1 tab == 4 spaces!

 *

 * http://www.FreeRTOS.org

 * http://www.FreeRTOS.org/plus

 * http://www.FreeRTOS.org/labs

 *

 */

 

/* Standard includes. */

#include <stdint.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

/* FreeRTOS includes. */

#include "FreeRTOS.h"

#include "task.h"

#include "queue.h"

#include "semphr.h"

 

/* FreeRTOS+TCP includes. */

#include "FreeRTOS_IP.h"

#include "FreeRTOS_Sockets.h"

#include "FreeRTOS_IP_Private.h"

#include "NetworkBufferManagement.h"

#include "NetworkInterface.h"

 

#include "Driver_ETH.h"

#include "Driver_ETH_MAC.h"

#include "Driver_ETH_PHY.h"

 

static void receiveHandlerTask( void *pvParameters );

static TaskHandle_t receiveHandler = NULL;

 

static ARM_ETH_MAC_ADDR   own_mac_address ;//device mac adress stores here. MSB first

static ARM_DRIVER_ETH_MAC *mac;

static ARM_ETH_MAC_CAPABILITIES  capabilities;

 

extern ARM_DRIVER_ETH_MAC Driver_ETH_MAC0;

extern ARM_DRIVER_ETH_PHY ARM_Driver_ETH_PHY_(0);

#define Driver_ETH_PHY0 	ARM_Driver_ETH_PHY_(0)

 

/*callback function for ARM_ETH_MAC_SignalEvent_t*/

void ethernet_mac_notify (uint32_t event)  {

  switch (event)  {

     case ARM_ETH_MAC_EVENT_RX_FRAME:

			 /*received frame,call receive fuction*/

			//led1_toggle();

			xTaskNotifyGive( receiveHandler );

		 break;

		 

		 case ARM_ETH_MAC_EVENT_TX_FRAME:

			 /* deliver finished */

		 break;

		 

		 case ARM_ETH_MAC_EVENT_WAKEUP:

		 break;

		 

		 case ARM_ETH_MAC_EVENT_TIMER_ALARM:

			 /* do nothing */

			break;

  }  

}

 

/* init the mac */

int32_t macIntialise(void){

	own_mac_address.b[0] = configMAC_ADDR0;

	own_mac_address.b[1] = configMAC_ADDR1;

	own_mac_address.b[2] = configMAC_ADDR2;

	own_mac_address.b[3] = configMAC_ADDR3;

	own_mac_address.b[4] = configMAC_ADDR4;

	own_mac_address.b[5] = configMAC_ADDR5;

	

	mac = &Driver_ETH_MAC0;

  capabilities = mac->GetCapabilities ();

	 

	

	

	if(mac->Initialize (ethernet_mac_notify) == ARM_DRIVER_OK && mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK){

		

		if (capabilities.mac_address == 0)  {

			// populate own_mac_address with the address to use.-----the fact situation

			mac->SetMacAddress(&own_mac_address);

		}

		else {

			mac->GetMacAddress(&own_mac_address);

		}

		

		return ARM_DRIVER_OK;

	}

	else{

		return ARM_DRIVER_ERROR;

	}

}

 

/* init the phy */

 int32_t phyIntialise(void){

	int32_t state = ARM_DRIVER_OK; 

	

	/* link the mac and phy through MAC0.PHY_Read() and MAC0.PHY_write */

	if(Driver_ETH_PHY0.Initialize(Driver_ETH_MAC0.PHY_Read,Driver_ETH_MAC0.PHY_Write)!= ARM_DRIVER_OK){

		state = ARM_DRIVER_ERROR;

		return state;

	}

	

	/* power on */

	if(Driver_ETH_PHY0.PowerControl(ARM_POWER_FULL)!=ARM_DRIVER_OK){

		state = ARM_DRIVER_ERROR;

		return state;

	}

	

	/* set RMII interface */

	if(Driver_ETH_PHY0.SetInterface (capabilities.media_interface)!=ARM_DRIVER_OK){

		state = ARM_DRIVER_ERROR;

		return state;

	}

	

	/* set mode */

	if(Driver_ETH_PHY0.SetMode (ARM_ETH_PHY_AUTO_NEGOTIATE)!=ARM_DRIVER_OK){

		state = ARM_DRIVER_ERROR;

		return state;

	}

	

	return state;

}

 

/*init the mac and phy*/

BaseType_t xNetworkInterfaceInitialise( void )

{

	static ARM_ETH_LINK_INFO info;

	BaseType_t state = pdFALSE;

	if(state == pdFALSE){

		state = xTaskCreate( receiveHandlerTask, "receiveHandlerTask", 1000, NULL, 1, &receiveHandler );

	}

	

	if(macIntialise() == ARM_DRIVER_OK  && phyIntialise() ==ARM_DRIVER_OK){

		ARM_ETH_LINK_STATE link = Driver_ETH_PHY0.GetLinkState ();

		

		while(link != ARM_ETH_LINK_UP){

			link = Driver_ETH_PHY0.GetLinkState ();

		}

		

		info = Driver_ETH_PHY0.GetLinkInfo ();

    mac->Control(ARM_ETH_MAC_CONFIGURE,

                 info.speed  << ARM_ETH_MAC_SPEED_Pos  |

                 info.duplex << ARM_ETH_MAC_DUPLEX_Pos |

                 ARM_ETH_MAC_ADDRESS_BROADCAST);

    mac->Control(ARM_ETH_MAC_CONTROL_TX, 1);

    mac->Control(ARM_ETH_MAC_CONTROL_RX, 1);

		return pdPASS;

	}

	else{

		//error

		return pdFALSE;

	}

}

/*-----------------------------------------------------------*/

 

 

/* send tcp/ip buffer to mac buffer */

static void sendData(uint8_t *pucEthernetBuffer,size_t xDataLength){

	if(mac->SendFrame(pucEthernetBuffer,xDataLength,ARM_ETH_MAC_TX_FRAME_EVENT|ARM_ETH_MAC_TX_FRAME_TIMESTAMP) == ARM_DRIVER_OK){

		//success

	}

	else{

		//error

	}

}

 

 

/* send frame */

#if ( ipconfigZERO_COPY_TX_DRIVER == 0)

/*the Simple network interfaces ,just use Ethernet peripheral driver library functions to copy

data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer.*/

BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,BaseType_t xReleaseAfterSend ){

	/* Simple network interfaces (as opposed to more efficient zero copy network

    interfaces) just use Ethernet peripheral driver library functions to copy

    data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer.

    This example assumes SendData() is a peripheral driver library function that

    takes a pointer to the start of the data to be sent and the length of the

    data to be sent as two separate parameters.  The start of the data is located

    by pxDescriptor->pucEthernetBuffer.  The length of the data is located

    by pxDescriptor->xDataLength. */

    sendData( pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength );

 

    /* Call the standard trace macro to log the send event. */

    iptraceNETWORK_INTERFACE_TRANSMIT();

 

    if( xReleaseAfterSend != pdFALSE )

    {

        /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet

        buffer.  The Ethernet buffer is therefore no longer needed, and must be

        freed for re-use. */

        vReleaseNetworkBufferAndDescriptor( pxDescriptor );

    }

 

    return pdTRUE;

}

#else

/*zero copy method here*/

 

#endif

/*-----------------------------------------------------------*/

 

/*receive data func , will be notify after ARM_ETH_MAC_EVENT_RX_FRAME event*/

#if (ipconfigZERO_COPY_RX_DRIVER==0)

static void receiveHandlerTask( void *pvParameters ){

	NetworkBufferDescriptor_t *receiveBufferDescriptor;

	size_t xBytesReceived;

	/* Used to indicate that xSendEventStructToIPTask() is being called becauseof an Ethernet receive event. */

	IPStackEvent_t xRxEvent;

	

	while(1){

		/* Wait for the Ethernet MAC interrupt to indicate that another packet

       has been received.  The task notification is used in a similar way to a

       counting semaphore to count Rx events, but is a lot more efficient than

       a semaphore. */

			ulTaskNotifyTake( pdFALSE, portMAX_DELAY );

		

		/* See how much data was received.  Here it is assumed ReceiveSize() is

       a peripheral driver function that returns the number of bytes in the

       received Ethernet frame. */

       xBytesReceived = mac->GetRxFrameSize();

		

		if( xBytesReceived > 0 ){

			/* Allocate a network buffer descriptor that points to a buffer

       large enough to hold the received frame.  As this is the simple

       rather than efficient example the received data will just be copied

       into this buffer. */

       receiveBufferDescriptor = pxGetNetworkBufferWithDescriptor( xBytesReceived, 0 );

			 if( receiveBufferDescriptor != NULL ){

					/* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet

          buffer large enough to hold the received data.  Copy the

          received data into pcNetworkBuffer->pucEthernetBuffer.  Here it

          is assumed ReceiveData() is a peripheral driver function that

          copies the received data into a buffer passed in as the function's

          parameter.  Remember! While is is a simple robust technique -

          it is not efficient.  An example that uses a zero copy technique

          is provided further down this page. */

          mac->ReadFrame(receiveBufferDescriptor->pucEthernetBuffer,xBytesReceived);

					receiveBufferDescriptor->xDataLength = xBytesReceived;

				 

					/* See if the data contained in the received Ethernet frame needs

          to be processed.  NOTE! It is preferable to do this in

          the interrupt service routine itself, which would remove the need

          to unblock this task for packets that don't need processing. */

          if( eConsiderFrameForProcessing( receiveBufferDescriptor->pucEthernetBuffer )== eProcessBuffer ){

							/* The event about to be sent to the TCP/IP is an Rx event. */

              xRxEvent.eEventType = eNetworkRxEvent;

 

              /* pvData is used to point to the network buffer descriptor that

              now references the received data. */

              xRxEvent.pvData = ( void * ) receiveBufferDescriptor;

							

							/* Send the data to the TCP/IP stack. */

              if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE ){

									/* The buffer could not be sent to the IP task so the buffer must be released. */

                  vReleaseNetworkBufferAndDescriptor( receiveBufferDescriptor );

 

                  /* Make a call to the standard trace macro to log the occurrence. */

                  iptraceETHERNET_RX_EVENT_LOST();

							}else{

									/* The message was successfully sent to the TCP/IP stack.

									Call the standard trace macro to log the occurrence. */

                  iptraceNETWORK_INTERFACE_RECEIVE();					

							}

					}else{

                   /* The Ethernet frame can be dropped, but the Ethernet buffer

                   must be released. */

                   vReleaseNetworkBufferAndDescriptor( receiveBufferDescriptor );

          }

								

			 }else{

					/* The event was lost because a network buffer was not available.

          Call the standard trace macro to log the occurrence. */

          iptraceETHERNET_RX_EVENT_LOST();

			 }

		}

	}

}

#else

/*zero copy method here*/

 

#endif

然后,NetworkInterface.h里面内容如下:


#ifndef NETWORK_INTERFACE_H

#define NETWORK_INTERFACE_H

 

#ifdef __cplusplus

extern "C" {

#endif

 

	

/* NOTE PUBLIC API FUNCTIONS. */

BaseType_t xNetworkInterfaceInitialise( void );

BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend );

void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] );

	

int32_t	macIntialise(void);

int32_t phyIntialise(void);

 

#ifdef __cplusplus

} // extern "C"

#endif

 

#endif /* NETWORK_INTERFACE_H */

最后,和FreeRTOS内核类似,需要提供一个配置文件,名为FreeRTOSIPConfig.h,内容如下:


/*

    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.

    All rights reserved



    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.



    This file is part of the FreeRTOS distribution.



    FreeRTOS is free software; you can redistribute it and/or modify it under

    the terms of the GNU General Public License (version 2) as published by the

    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.



    ***************************************************************************

    >>!   NOTE: The modification to the GPL is included to allow you to     !<<

    >>!   distribute a combined work that includes FreeRTOS without being   !<<

    >>!   obliged to provide the source code for proprietary components     !<<

    >>!   outside of the FreeRTOS kernel.                                   !<<

    ***************************************************************************



    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY

    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS

    FOR A PARTICULAR PURPOSE.  Full license text is available on the following

    link: http://www.freertos.org/a00114.html



    ***************************************************************************

     *                                                                       *

     *    FreeRTOS provides completely free yet professionally developed,    *

     *    robust, strictly quality controlled, supported, and cross          *

     *    platform software that is more than just the market leader, it     *

     *    is the industry's de facto standard.                               *

     *                                                                       *

     *    Help yourself get started quickly while simultaneously helping     *

     *    to support the FreeRTOS project by purchasing a FreeRTOS           *

     *    tutorial book, reference manual, or both:                          *

     *    http://www.FreeRTOS.org/Documentation                              *

     *                                                                       *

    ***************************************************************************



    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading

    the FAQ page "My application does not run, what could be wrong?".  Have you

    defined configASSERT()?



    http://www.FreeRTOS.org/support - In return for receiving this top quality

    embedded software for free we request you assist our global community by

    participating in the support forum.



    http://www.FreeRTOS.org/training - Investing in training allows your team to

    be as productive as possible as early as possible.  Now you can receive

    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers

    Ltd, and the world's leading authority on the world's leading RTOS.



    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,

    including FreeRTOS+Trace - an indispensable productivity tool, a DOS

    compatible FAT file system, and our tiny thread aware UDP/IP stack.



    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.

    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.



    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High

    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS

    licenses offer ticketed support, indemnification and commercial middleware.



    http://www.SafeRTOS.com - High Integrity Systems also provide a safety

    engineered and independently SIL3 certified version for use in safety and

    mission critical applications that require provable dependability.



    1 tab == 4 spaces!

*/

 

 

/*****************************************************************************

 *

 * See the following URL for configuration information.

 * http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html

 *

 *****************************************************************************/

 

#ifndef FREERTOS_IP_CONFIG_H

#define FREERTOS_IP_CONFIG_H

 

#ifdef __cplusplus

extern "C" {

#endif

 

#include "FreeRTOS.h"	

 

/* Define the byte order of the target MCU (the MCU FreeRTOS+TCP is executing

on).  Valid options are pdFREERTOS_BIG_ENDIAN and pdFREERTOS_LITTLE_ENDIAN. */

#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN

 

/* The checksums will be checked and calculated by the STM32F4x ETH peripheral. */

#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM		( 1 )

#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM		( 1 )

 

/* Several API's will block until the result is known, or the action has been

performed, for example FreeRTOS_send() and FreeRTOS_recv().  The timeouts can be

set per socket, using setsockopt().  If not set, the times below will be

used as defaults. */

#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME	( 5000 )

#define	ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME	( 5000 )

 

#define ipconfigZERO_COPY_RX_DRIVER			( 0 )

#define ipconfigZERO_COPY_TX_DRIVER			( 0 )

 

/* Include support for LLMNR: Link-local Multicast Name Resolution

(non-Microsoft) */

#define ipconfigUSE_LLMNR					( 1 )

 

/* Include support for NBNS: NetBIOS Name Service (Microsoft) */

#define ipconfigUSE_NBNS					( 0 )

 

/* Include support for DNS caching.  For TCP, having a small DNS cache is very

useful.  When a cache is present, ipconfigDNS_REQUEST_ATTEMPTS can be kept low

and also DNS may use small timeouts.  If a DNS reply comes in after the DNS

socket has been destroyed, the result will be stored into the cache.  The next

call to FreeRTOS_gethostbyname() will return immediately, without even creating

a socket. */

#define ipconfigUSE_DNS_CACHE				( 1 )

#define ipconfigDNS_CACHE_NAME_LENGTH		( 16 )

#define ipconfigDNS_CACHE_ENTRIES			( 4 )

#define ipconfigDNS_REQUEST_ATTEMPTS		( 4 )

 

/* The IP stack executes it its own task (although any application task can make

use of its services through the published sockets API). ipconfigIP_TASK_PRIORITY

sets the priority of the task that executes the IP stack.  The priority is a

standard FreeRTOS task priority so can take any value from 0 (the lowest

priority) to (configMAX_PRIORITIES - 1) (the highest priority).

configMAX_PRIORITIES is a standard FreeRTOS configuration parameter defined in

FreeRTOSConfig.h, not FreeRTOSIPConfig.h. Consideration needs to be given as to

the priority assigned to the task executing the IP stack relative to the

priority assigned to tasks that use the IP stack. */

#define ipconfigIP_TASK_PRIORITY			( configMAX_PRIORITIES - 2 )

 

/* The size, in words (not bytes), of the stack allocated to the FreeRTOS+TCP

task.  This setting is less important when the FreeRTOS Win32 simulator is used

as the Win32 simulator only stores a fixed amount of information on the task

stack.  FreeRTOS includes optional stack overflow detection, see:

http://www.freertos.org/Stacks-and-stack-overflow-checking.html */

#define ipconfigIP_TASK_STACK_SIZE_WORDS	( configMINIMAL_STACK_SIZE * 5 )

 

/* ipconfigRAND32() is called by the IP stack to generate random numbers for

things such as a DHCP transaction number or initial sequence number.  Random

number generation is performed via this macro to allow applications to use their

own random number generation method.  For example, it might be possible to

generate a random number by sampling noise on an analogue input. */

extern UBaseType_t uxRand(void);

#define ipconfigRAND32()	uxRand()

 

/* If ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 then FreeRTOS+TCP will call the

network event hook at the appropriate times.  If ipconfigUSE_NETWORK_EVENT_HOOK

is not set to 1 then the network event hook will never be called.  See

http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/vApplicationIPNetworkEventHook.shtml

*/

#define ipconfigUSE_NETWORK_EVENT_HOOK 1

 

/* Sockets have a send block time attribute.  If FreeRTOS_sendto() is called but

a network buffer cannot be obtained then the calling task is held in the Blocked

state (so other tasks can continue to executed) until either a network buffer

becomes available or the send block time expires.  If the send block time expires

then the send operation is aborted.  The maximum allowable send block time is

capped to the value set by ipconfigMAX_SEND_BLOCK_TIME_TICKS.  Capping the

maximum allowable send block time prevents prevents a deadlock occurring when

all the network buffers are in use and the tasks that process (and subsequently

free) the network buffers are themselves blocked waiting for a network buffer.

ipconfigMAX_SEND_BLOCK_TIME_TICKS is specified in RTOS ticks.  A time in

milliseconds can be converted to a time in ticks by dividing the time in

milliseconds by portTICK_PERIOD_MS. */

#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( 5000 / portTICK_PERIOD_MS )

 

/* If ipconfigUSE_DHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP

address, netmask, DNS server address and gateway address from a DHCP server.  If

ipconfigUSE_DHCP is 0 then FreeRTOS+TCP will use a static IP address.  The

stack will revert to using the static IP address even when ipconfigUSE_DHCP is

set to 1 if a valid configuration cannot be obtained from a DHCP server for any

reason.  The static configuration used is that passed into the stack by the

FreeRTOS_IPInit() function call. */

#define ipconfigUSE_DHCP				1

#define ipconfigDHCP_REGISTER_HOSTNAME	1

#define ipconfigDHCP_USES_UNICAST       1

 

/* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at

increasing time intervals until either a reply is received from a DHCP server

and accepted, or the interval between transmissions reaches

ipconfigMAXIMUM_DISCOVER_TX_PERIOD.  The IP stack will revert to using the

static IP address passed as a parameter to FreeRTOS_IPInit() if the

re-transmission time interval reaches ipconfigMAXIMUM_DISCOVER_TX_PERIOD without

a DHCP reply being received. */

#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD		( pdMS_TO_TICKS( 30000 ) )

 

/* The ARP cache is a table that maps IP addresses to MAC addresses.  The IP

stack can only send a UDP message to a remove IP address if it knowns the MAC

address associated with the IP address, or the MAC address of the router used to

contact the remote IP address.  When a UDP message is received from a remote IP

address the MAC address and IP address are added to the ARP cache.  When a UDP

message is sent to a remote IP address that does not already appear in the ARP

cache then the UDP message is replaced by a ARP message that solicits the

required MAC address information.  ipconfigARP_CACHE_ENTRIES defines the maximum

number of entries that can exist in the ARP table at any one time. */

#define ipconfigARP_CACHE_ENTRIES		6

 

/* ARP requests that do not result in an ARP response will be re-transmitted a

maximum of ipconfigMAX_ARP_RETRANSMISSIONS times before the ARP request is

aborted. */

#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 )

 

/* ipconfigMAX_ARP_AGE defines the maximum time between an entry in the ARP

table being created or refreshed and the entry being removed because it is stale.

New ARP requests are sent for ARP cache entries that are nearing their maximum

age.  ipconfigMAX_ARP_AGE is specified in tens of seconds, so a value of 150 is

equal to 1500 seconds (or 25 minutes). */

#define ipconfigMAX_ARP_AGE			150

 

/* Implementing FreeRTOS_inet_addr() necessitates the use of string handling

routines, which are relatively large.  To save code space the full

FreeRTOS_inet_addr() implementation is made optional, and a smaller and faster

alternative called FreeRTOS_inet_addr_quick() is provided.  FreeRTOS_inet_addr()

takes an IP in decimal dot format (for example, "192.168.0.1") as its parameter.

FreeRTOS_inet_addr_quick() takes an IP address as four separate numerical octets

(for example, 192, 168, 0, 1) as its parameters.  If

ipconfigINCLUDE_FULL_INET_ADDR is set to 1 then both FreeRTOS_inet_addr() and

FreeRTOS_indet_addr_quick() are available.  If ipconfigINCLUDE_FULL_INET_ADDR is

not set to 1 then only FreeRTOS_indet_addr_quick() is available. */

#define ipconfigINCLUDE_FULL_INET_ADDR	1

 

/* ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS defines the total number of network buffer that

are available to the IP stack.  The total number of network buffers is limited

to ensure the total amount of RAM that can be consumed by the IP stack is capped

to a pre-determinable value. */

#if( ipconfigZERO_COPY_RX_DRIVER != 0 )

	/* _HT_ Actually we should know the value of 'configNUM_RX_DESCRIPTORS' here. */

	#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS		( 25 + 6 )

#else

	#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS		25

#endif

 

/* A FreeRTOS queue is used to send events from application tasks to the IP

stack.  ipconfigEVENT_QUEUE_LENGTH sets the maximum number of events that can

be queued for processing at any one time.  The event queue must be a minimum of

5 greater than the total number of network buffers. */

#define ipconfigEVENT_QUEUE_LENGTH		( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 )

 

/* The address of a socket is the combination of its IP address and its port

number.  FreeRTOS_bind() is used to manually allocate a port number to a socket

(to 'bind' the socket to a port), but manual binding is not normally necessary

for client sockets (those sockets that initiate outgoing connections rather than

wait for incoming connections on a known port number).  If

ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 then calling

FreeRTOS_sendto() on a socket that has not yet been bound will result in the IP

stack automatically binding the socket to a port number from the range

socketAUTO_PORT_ALLOCATION_START_NUMBER to 0xffff.  If

ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 then calling FreeRTOS_sendto()

on a socket that has not yet been bound will result in the send operation being

aborted. */

#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1

 

/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */

#define ipconfigUDP_TIME_TO_LIVE		128

#define ipconfigTCP_TIME_TO_LIVE		128 /* also defined in FreeRTOSIPConfigDefaults.h */

 

/* USE_TCP: Use TCP and all its features */

#define ipconfigUSE_TCP				( 1 )

 

/* USE_WIN: Let TCP use windowing mechanism. */

#define ipconfigUSE_TCP_WIN			( 1 )

 

/* The MTU is the maximum number of bytes the payload of a network frame can

contain.  For normal Ethernet V2 frames the maximum MTU is 1500.  Setting a

lower value can save RAM, depending on the buffer management scheme used.  If

ipconfigCAN_FRAGMENT_OUTGOING_PACKETS is 1 then (ipconfigNETWORK_MTU - 28) must

be divisible by 8. */

 

#define ipconfigNETWORK_MTU					1500

 

/* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver.  DNS is used

through the FreeRTOS_gethostbyname() API function. */

#define ipconfigUSE_DNS								1

 

/* If ipconfigREPLY_TO_INCOMING_PINGS is set to 1 then the IP stack will

generate replies to incoming ICMP echo (ping) requests. */

#define ipconfigREPLY_TO_INCOMING_PINGS				1

 

/* If ipconfigSUPPORT_OUTGOING_PINGS is set to 1 then the

FreeRTOS_SendPingRequest() API function is available. */

#define ipconfigSUPPORT_OUTGOING_PINGS				1

 

/* If ipconfigSUPPORT_SELECT_FUNCTION is set to 1 then the FreeRTOS_select()

(and associated) API function is available. */

#define ipconfigSUPPORT_SELECT_FUNCTION				1

 

/* If ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is set to 1 then Ethernet frames

that are not in Ethernet II format will be dropped.  This option is included for

potential future IP stack developments. */

#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES  1

 

/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1 then it is the

responsibility of the Ethernet interface to filter out packets that are of no

interest.  If the Ethernet interface does not implement this functionality, then

set ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES to 0 to have the IP stack

perform the filtering instead (it is much less efficient for the stack to do it

because the packet will already have been passed into the stack).  If the

Ethernet driver does all the necessary filtering in hardware then software

filtering can be removed by using a value other than 1 or 0. */

#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES	1

 

/* The windows simulator cannot really simulate MAC interrupts, and needs to

block occasionally to allow other tasks to run. */

#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ( 2 / portTICK_PERIOD_MS )

 

/* Advanced only: in order to access 32-bit fields in the IP packets with

32-bit memory instructions, all packets will be stored 32-bit-aligned, plus

16-bits.  This has to do with the contents of the IP-packets: all 32-bit fields

are 32-bit-aligned, plus 16-bit(!). */

#define ipconfigPACKET_FILLER_SIZE 2

 

/* Define the size of the pool of TCP window descriptors.  On the average, each

TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6

outstanding packets (for Rx and Tx).  When using up to 10 TP sockets

simultaneously, one could define TCP_WIN_SEG_COUNT as 120. */

#define ipconfigTCP_WIN_SEG_COUNT 64

 

/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed

maximum size.  Define the size of Rx buffer for TCP sockets. */

#define ipconfigTCP_RX_BUFFER_LENGTH			( 3 * 1460 )

 

/* Define the size of Tx buffer for TCP sockets. */

#define ipconfigTCP_TX_BUFFER_LENGTH			( 2 * 1460 )

 

/* When using call-back handlers, the driver may check if the handler points to

real program memory (RAM or flash) or just has a random non-zero value. */

#define ipconfigIS_VALID_PROG_ADDRESS(x) ( (x) != NULL )

 

/* Include support for TCP hang protection.  All sockets in a connecting or

disconnecting stage will timeout after a period of non-activity. */

#define ipconfigTCP_HANG_PROTECTION				( 1 )

#define ipconfigTCP_HANG_PROTECTION_TIME		( 30 )

 

/* Include support for TCP keep-alive messages. */

#define ipconfigTCP_KEEP_ALIVE				( 1 )

#define ipconfigTCP_KEEP_ALIVE_INTERVAL		( 20 ) /* in seconds */

 

/* Set to 1 or 0 to include/exclude FTP and HTTP functionality from the standard

server task. */

#define ipconfigUSE_FTP						1

#define ipconfigUSE_HTTP					1

 

/* Buffer and window sizes used by the FTP and HTTP servers respectively.  The

FTP and HTTP servers both execute in the standard server task. */

#define ipconfigFTP_TX_BUFSIZE				( 4 * ipconfigTCP_MSS )

#define ipconfigFTP_TX_WINSIZE				( 2 )

#define ipconfigFTP_RX_BUFSIZE				( 8 * ipconfigTCP_MSS )

#define ipconfigFTP_RX_WINSIZE				( 4 )

#define ipconfigHTTP_TX_BUFSIZE				( 3 * ipconfigTCP_MSS )

#define ipconfigHTTP_TX_WINSIZE				( 2 )

#define ipconfigHTTP_RX_BUFSIZE				( 4 * ipconfigTCP_MSS )

#define ipconfigHTTP_RX_WINSIZE				( 4 )

 

/* UDP Logging related constants follow.  The standard UDP logging facility

writes formatted strings to a buffer, and creates a task that removes messages

from the buffer and sends them to the UDP address and port defined by the

constants that follow. */

 

/* Prototype for the function used to print out.  In this case the standard

UDP logging facility is used. */

extern int lUDPLoggingPrintf( const char *pcFormatString, ... );

 

/* Set to 1 to print out debug messages.  If ipconfigHAS_DEBUG_PRINTF is set to

1 then FreeRTOS_debug_printf should be defined to the function used to print

out the debugging messages. */

#define ipconfigHAS_DEBUG_PRINTF	0

#if( ipconfigHAS_DEBUG_PRINTF == 1 )

	#define FreeRTOS_debug_printf(X)	lUDPLoggingPrintf X

#endif

 

/* Set to 1 to print out non debugging messages, for example the output of the

FreeRTOS_netstat() command, and ping replies.  If ipconfigHAS_PRINTF is set to 1

then FreeRTOS_printf should be set to the function used to print out the

messages. */

#define ipconfigHAS_PRINTF			1

#if( ipconfigHAS_PRINTF == 1 )

	#define FreeRTOS_printf(X)			lUDPLoggingPrintf X

#endif

 

/* When set to 1, the application writer must provide the implementation of a

function with the following name and prototype:



BaseType_t xApplicationDNSQueryHook( const char *pcName );



The function must return pdTRUE if pcName matches a test name assigned to the

device, and pdFALSE in all other cases.  */

#define ipconfigDNS_USE_CALLBACKS			1

#define ipconfigSUPPORT_SIGNALS				1

 

/* This demo creates a virtual network connection by accessing the raw Ethernet

or WiFi data to and from a real network connection.  Many computers have more

than one real network port, and configNETWORK_INTERFACE_TO_USE is used to tell

the demo which real port should be used to create the virtual port.  The ports

available are displayed on the console when the application is executed.  For

example, on my development laptop setting configNETWORK_INTERFACE_TO_USE to 4

results in the wired network being used, while setting

configNETWORK_INTERFACE_TO_USE to 2 results in the wireless network being

used. */

#define configNETWORK_INTERFACE_TO_USE 4L

 

/* Default MAC address configuration.  The demo creates a virtual network

connection that uses this MAC address by accessing the raw Ethernet/WiFi data

to and from a real network connection on the host PC.  See the

configNETWORK_INTERFACE_TO_USE definition above for information on how to

configure the real network connection to use. */

#define configMAC_ADDR0		0x00

#define configMAC_ADDR1		0x11

#define configMAC_ADDR2		0x22

#define configMAC_ADDR3		0x33

#define configMAC_ADDR4		0x44

#define configMAC_ADDR5		0x41

 

/* Default IP address configuration.  Used in ipconfigUSE_DNS is set to 0, or

ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */

#define configIP_ADDR0		192

#define configIP_ADDR1		168

#define configIP_ADDR2		0

#define configIP_ADDR3		55

 

/* Default gateway IP address configuration.  Used in ipconfigUSE_DNS is set to

0, or ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */

#define configGATEWAY_ADDR0	192

#define configGATEWAY_ADDR1	168

#define configGATEWAY_ADDR2	0

#define configGATEWAY_ADDR3	1

 

/* Default DNS server configuration.  OpenDNS addresses are 208.67.222.222 and

208.67.220.220.  Used in ipconfigUSE_DNS is set to 0, or ipconfigUSE_DNS is set

to 1 but a DNS server cannot be contacted.*/

#define configDNS_SERVER_ADDR0 	208

#define configDNS_SERVER_ADDR1 	67

#define configDNS_SERVER_ADDR2 	222

#define configDNS_SERVER_ADDR3 	222

 

/* Default netmask configuration.  Used in ipconfigUSE_DNS is set to 0, or

ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */

#define configNET_MASK0		255

#define configNET_MASK1		255

#define configNET_MASK2		0

#define configNET_MASK3		0

 

/* The UDP port to which print messages are sent. */

#define configPRINT_PORT	( 15000 )

 

 

/* The example IP trace macros are included here so the definitions are

available in all the FreeRTOS+TCP source files. */

#include "DemoIPTrace.h"

 

 

#ifdef __cplusplus

} /* extern "C" */

#endif

 

#endif /* FREERTOS_IP_CONFIG_H */

此时,工程目录如下所示:

根据FreeRTOS官方的tutorial,此时已近配置完成,但编译后会发现,仍然有几个函数没有完成定义,这是在配置文件下产生的,需要由用户

自己完成的函数,分别是以下函数:

int lUDPLoggingPrintf( const char *fmt, ... ) //调试用

const char *pcApplicationHostnameHook( void ) //返回主机名称

BaseType_t xApplicationDNSQueryHook( const char *pcName ) //DNS或LLMNR请求的查询回调

void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier ) //ping回复回调

void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )  //网络事件回调

UBaseType_t uxRand() //随机数产生

在User目录下新建一个文件,我的是netInfoConfig.c用来完成上面的这些函数,复制下面的代码进去:
 


#include "FreeRTOSLib.h"          //自己把Freertos的头文件加进来

#include "FreeRTOSTcpLib.h"          //协议栈的头文件加进来

 

#include <stdio.h>

#include <string.h>

#include <stdarg.h>

 

#include "randomNum.h"

#include "netInfoConfig.h"

 

#include "led.h"

 

/* Define a name that will be used for LLMNR and NBNS searches. */

#define mainHOST_NAME				"CocolYoungStm32"

#define mainDEVICE_NICK_NAME		"YYFStm32"

 

 

static BaseType_t UDP_DEBUG_INIT();

 

/*

	return a rand num

*/

UBaseType_t uxRand(){

	return (UBaseType_t) getRandomNum();

}

 

 

/* The default IP and MAC address used by the demo.  The address configuration

defined here will be used if ipconfigUSE_DHCP is 0, or if ipconfigUSE_DHCP is

1 but a DHCP server could not be contacted.  See the online documentation for

more information. */

const uint8_t ucIPAddress[ 4 ] = { configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 };

const uint8_t ucNetMask[ 4 ] = { configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 };

const uint8_t ucGatewayAddress[ 4 ] = { configGATEWAY_ADDR0, configGATEWAY_ADDR1, configGATEWAY_ADDR2, configGATEWAY_ADDR3 };

const uint8_t ucDNSServerAddress[ 4 ] = { configDNS_SERVER_ADDR0, configDNS_SERVER_ADDR1, configDNS_SERVER_ADDR2, configDNS_SERVER_ADDR3 };

 

/* Default MAC address configuration.  The demo creates a virtual network

connection that uses this MAC address by accessing the raw Ethernet data

to and from a real network connection on the host PC.  See the

configNETWORK_INTERFACE_TO_USE definition for information on how to configure

the real network connection to use. */

const uint8_t ucMACAddress[ 6 ] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };

 

 

/*

*Brief:

	vApplicationIPNetworkEventHook() is an application 

	defined hook (or callback) function that is called by the 

	TCP/IP stack when the network either connects or disconnects. 

	As the function is called by the TCP/IP stack the TCP/IP sets 

	sets the value of the function's parameter.

*param:

	eNetworkEvent = 0 , the net connected.

	eNetworkEvent = 1 , the net disconnected.

*/	

void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )

{

uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress;

static BaseType_t xTasksAlreadyCreated = pdFALSE;

int8_t cBuffer[ 16 ];

 

    /* Check this was a network up event, as opposed to a network down event. */

    if( eNetworkEvent == eNetworkUp )

    {

        /* Create the tasks that use the TCP/IP stack if they have not already been

        created. */

        if( xTasksAlreadyCreated == pdFALSE )

        {

            /*

             * Create the tasks here.

             */

					UDP_DEBUG_INIT();//debug printf init

					

					//led1_flash();

					//xTaskCreate( aFunction, "aFunction", 1000, NULL, 3, NULL );

					//xTaskCreate( eth_send_task, "test_send", 1000, NULL, 3, NULL );

          xTasksAlreadyCreated = pdTRUE;

        }

 

        /* The network is up and configured.  Print out the configuration,

        which may have been obtained from a DHCP server. */

        FreeRTOS_GetAddressConfiguration( &ulIPAddress,

                                          &ulNetMask,

                                          &ulGatewayAddress,

                                          &ulDNSServerAddress );

 

        /* Convert the IP address to a string then print it out. */

        FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );

        lUDPLoggingPrintf( "IP Address: %s\r\n", cBuffer );

 

        /* Convert the net mask to a string then print it out. */

        FreeRTOS_inet_ntoa( ulNetMask, cBuffer );

        lUDPLoggingPrintf( "Subnet Mask: %s\r\n", cBuffer );

 

        /* Convert the IP address of the gateway to a string then print it out. */

        FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );

        lUDPLoggingPrintf( "Gateway IP Address: %s\r\n", cBuffer );

 

        /* Convert the IP address of the DNS server to a string then print it out. */

        FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer );

        lUDPLoggingPrintf( "DNS server IP Address: %s\r\n", cBuffer );

    }

}

/*--------------------------------------------------------*/

 

/*

	there are series of func should be defined when ipconfigSUPPORT_OUTGOING_PINGS is set to 1.

*/

QueueHandle_t xPingReplyQueue;//this queue should be create for vApplicationPingReplyHook()

 

/* this func should be used before FreeRTOS_SendPingRequest() to init the xPingReplyQueue*/

void xPingReplyQueueCreate(){

	xPingReplyQueue = xQueueCreate( 20, sizeof( uint16_t ) );

}

void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier )

{

    switch( eStatus )

    {

        case eSuccess    :

            /* A valid ping reply has been received.  Post the sequence number

            on the queue that is read by the vSendPing() function below.  Do

            not wait more than 10ms trying to send the message if it cannot be

            sent immediately because this function is called from the TCP/IP

            RTOS task - blocking in this function will block the TCP/IP RTOS task. */

            xQueueSend( xPingReplyQueue, &usIdentifier, 10 / portTICK_PERIOD_MS );

            break;

 

        case eInvalidChecksum :

        case eInvalidData :

            /* A reply was received but it was not valid. */

            break;

    }

}

 

 

/*

 * The following function should be provided by the user and return true if it

 * matches the domain name.

	*this func will be used to judge whether *pcName matche DNS request or LLMNR request.

	return pdTRUE if matching DNS request,

	return pdFALSE if matching LLMNR request.

 */

BaseType_t xApplicationDNSQueryHook( const char *pcName ){

		BaseType_t xReturn;

 

		/* Determine if a name lookup is for this node.  Two names are given

		to this node: that returned by pcApplicationHostnameHook() and that set

		by mainDEVICE_NICK_NAME. */

		if( strcmp( pcName, pcApplicationHostnameHook() ) == 0 )

		{

			xReturn = pdPASS;

		}

		else if( strcmp( pcName, mainDEVICE_NICK_NAME ) == 0 )

		{

			xReturn = pdPASS;

		}

		else

		{

			xReturn = pdFAIL;

		}

 

		return xReturn;

}

/*----------------------------------------------*/

 

const char *pcApplicationHostnameHook( void ){

 

	return mainHOST_NAME;

}

 

 

/*-----------------------------------------------------------*/

	

void IP_init( void ){

	/***NOTE*** Tasks that use the network are created in the network event hook

	when the network is connected and ready for use (see the definition of

	vApplicationIPNetworkEventHook() below).  The address values passed in here

	are used if ipconfigUSE_DHCP is set to 0, or if ipconfigUSE_DHCP is set to 1

	but a DHCP server cannot be	contacted. */

	FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress );

}

 

 

/*------------DEBUG ONLY----------------*/

Socket_t UDP_DEBUG_SOCKET;

 

/*

Brief : func used for init the udp

Return : if sucess,return pdTRUE

*/

static BaseType_t UDP_DEBUG_INIT(){

	struct freertos_sockaddr xBindAddress;

 

    /* Create a UDP socket. */

    UDP_DEBUG_SOCKET = FreeRTOS_socket( FREERTOS_AF_INET,

                               FREERTOS_SOCK_DGRAM,

                               FREERTOS_IPPROTO_UDP );

 

    /* Check the socket was created successfully. */

    if( UDP_DEBUG_SOCKET != FREERTOS_INVALID_SOCKET )

    {

        /* The socket was created successfully and can now be used to send data

        using the FreeRTOS_sendto() API function.  Sending to a socket that has

        not first been bound will result in the socket being automatically bound

        to a port number.  Use FreeRTOS_bind() to bind the socket to a

        specific port number.  This example binds the socket to port 9999.  The

        port number is specified in network byte order, so FreeRTOS_htons() is

        used. */

        xBindAddress.sin_port = FreeRTOS_htons( 9999 );

        if( FreeRTOS_bind( UDP_DEBUG_SOCKET, &xBindAddress, sizeof( &xBindAddress ) ) == 0 )

        {

					/* bind success */

					return pdTRUE;

				}

				else{

					return pdFALSE;

				}

		}else{

			return pdFALSE;

		}

}

 

/*

Brief:

this func only for debug printf

Param:

msg: the message.

len: the message length

Return:

the length

*/

static size_t UDP_SEND_DATA(const char* msg , size_t len){

	static struct freertos_sockaddr xDestinationAddress;

	int32_t iReturned;

	

	/* dest address and port */

	xDestinationAddress.sin_addr = FreeRTOS_inet_addr_quick( 192, 168, 0, 33 );

  xDestinationAddress.sin_port = FreeRTOS_htons( 60000 );

	

	/* Send the buffer with ulFlags set to 0, so the FREERTOS_ZERO_COPY bit

  is clear. */

  iReturned = FreeRTOS_sendto(

                                  /* The socket being send to. */

                                  UDP_DEBUG_SOCKET,

                                  /* The data being sent. */

                                  msg,

                                  /* The length of the data being sent. */

                                  len,

                                  /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */

                                  0,

                                  /* Where the data is being sent. */

                                  &xDestinationAddress,

                                  /* Not used but should be set as shown. */

                                  sizeof( xDestinationAddress )

                             );

 

    if( iReturned == len )

    {

       return len;

    }	

		else{

			return 0;

		}

}

 

/*

	only for debug

*/

int lUDPLoggingPrintf( const char *fmt, ... ){

	va_list ap;

	char msg[128];

	int len;

 

	va_start(ap, fmt);

	len = vsnprintf(msg, sizeof(msg), fmt, ap);

	UDP_SEND_DATA(msg, len);

	va_end(ap);

	return len;

}

/*------------DEBUG ONLY----------------*/

 

 

记住,一切与网络有关的任务请创建在void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )内。

stm32外设自带随机数发生器,在工程User目录下创建randomNum.c和randomNum.h,添加如下内容:


#include "randomNum.h"

 

/* RNG handler declaration */

RNG_HandleTypeDef RngHandle;

 

static void Error_Handler(){

		while(1){

			

		}

}

 

void RNG_init(){

	__HAL_RCC_RNG_CLK_ENABLE();

	

	/*## Configure the RNG peripheral #######################################*/

  RngHandle.Instance = RNG;

	

	/* DeInitialize the RNG peripheral */

  if (HAL_RNG_DeInit(&RngHandle) != HAL_OK)

  {

    /* DeInitialization Error */

    Error_Handler();

  }    

 

  /* Initialize the RNG peripheral */

  if (HAL_RNG_Init(&RngHandle) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler();

  }

}

 

uint32_t getRandomNum(){

	uint32_t num;

	if (HAL_RNG_GenerateRandomNumber(&RngHandle, &num) != HAL_OK)

      {

        /* Random number generation error */

        Error_Handler();      

      }

	return num;

}

 

void getRandomNumTo(uint32_t * num){

 

	if (HAL_RNG_GenerateRandomNumber(&RngHandle, num) != HAL_OK)

      {

        /* Random number generation error */

        Error_Handler();      

      }

}

 

#ifndef __RANDOMNUM__H

#define __RANDOMNUM__H

 

#include "stm32f4xx_hal_rng.h"

#include "stm32f4xx_hal_rcc.h"

 

void RNG_init(void);

uint32_t getRandomNum(void);

void getRandomNumTo(uint32_t * num);

#endif

最后,在工程的User目录下创建main.c,内容如下:


/* stm32F4 HAL lib includes */

#include "stm32f4xx_hal.h"

 

/* FreeRTOS includes. */

#include "FreeRTOS.h"

 

/* user includes */

#include "randomNum.h"

#include "netInfoConfig.h"

#include "led.h"

 

 

int main(){	

		

	//led_init();

  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

	RNG_init();

	

	/***NOTE*** Tasks that use the network are created in the network event hook

	when the network is connected and ready for use (see the definition of

	vApplicationIPNetworkEventHook() below).  The address values passed in here

	are used if ipconfigUSE_DHCP is set to 0, or if ipconfigUSE_DHCP is set to 1

	but a DHCP server cannot be	contacted. */

	IP_init();

	

	

	vTaskStartScheduler();

 

	/* If all is well, the scheduler will now be running, and the following

	line will never be reached.  If the following line does execute, then

	there was insufficient FreeRTOS heap memory available for the idle and/or

	timer tasks	to be created.  See the memory management section on the

	FreeRTOS web site for more details (this is standard text that is not not

	really applicable to the Win32 simulator port). */

	while(1);

}

再次提醒,有关网络的void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )内,

因为要保证网络已经连接之后才能创建网络有关的任务。随机数的初始化应该在网络初始化前面。

 最后工程目录如下:

最后,ping一下看看能否ping通,或者随便写个任务看看能不能抓到包。

随便写个任务,1s发一次“fffffffffffffffffffffffffffffffffffffffffffff”

 

 OK,到此搞定。

源码:https://github.com/YoungYoung619/Stm32-FreeRTOS-TCPIP

 

https://blog.csdn.net/weixin_37673586/article/details/79253597

 

 

 

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个问题中混杂了很多不同的概念。我会分别解释: 1. stm32f4xx: 这是指STMicroelectronics(意法半导体)推出的一款32位微控制器系列,它们应用广泛,有很多种型号。 2. lwIP: 这是指"lightweight IP",它是一个开源的TCP/IP协议栈。它具有轻量级、可移植、可扩展等优点,所以在一些嵌入式系统中得到应用。 3. FreeRTOS: 这是指"Free Real-time Operating System",它是一个开源的实时操作系统。它具有小巧、快速、可移植等优点,以及很多年的实战经验,所以在很多嵌入式系统中得到应用。 4. 移植: 指将特定系统的软件、驱动程序等适应不同系统,开发时多数情况下需要将软件适配到具体系统中。 综上所述, "stm32f4xx lwip freertos移植"意为适配lwIP协议栈和FreeRTOS操作系统到stm32f4xx处理器平台。 ### 回答2: STM32F4xx是属于嵌入式系统中的一种芯片,它具有高性能、低功耗、丰富外设等优点。在进行网络通信时,常常会使用到LWIP协议栈(LightWeight IP),LWIP是一个轻量级的开源TCP/IP协议栈,具有跨平台、高度可移植等特性。而FreeRTOS是一种优秀的实时操作系统,能够支持多任务、多线程、中断处理等功能,因此,将这两者进行移植,实现STM32F4xx芯片的网络通信,特别是TCP/IP通信,将是一个很有挑战的任务。 移植LWIP协议栈需要进行以下步骤: 第一步:根据STM32F4xx芯片的电路板、内存大小、外设特性等环境,进行LWIP协议栈的移植。主要包括系统初始化、网络驱动、网络协议栈、网络接口等方面的内容。 第二步:通过LWIP的API接口,实现协议的配置,包括IP地址、掩码、网关、DNS服务器等,并根据不同的协议类型(如TCP、UDP、ICMP等)进行配置。 第三步:通过FreeRTOS的API接口,将网络协议栈与操作系统进行整合,实现多任务并发处理、中断处理、定时器计数等功能,并保证系统稳定性和实时性。 在进行STM32F4xx lwip freertos移植时,需要注意以下几个方面: 一、内存管理:STM32F4xx芯片的RAM和Flash比较小,需要合理地分配内存,避免资源浪费和系统崩溃。 二、时钟配置:LWIP和FreeRTOS都需要使用操作系统的时钟进行计数和同步。因此,需要把选定的操作系统时钟映射到芯片上的RC/XTAL或内部晶振,保证时钟精度和稳定性。 三、中断处理:由于网络协议栈需要进行中断处理,因此需要注意中断的优先级和中断处理函数的编写。中断处理函数需要精简、高效,不影响系统的实时性和稳定性。 四、网络接口:STM32F4xx芯片支持多种不同的网络接口,在移植中需要根据具体的需求,选择相应的硬件接口进行配置。并根据不同的接口类型,进行网络驱动程序的编写和配置。 总之,STM32F4xx lwip freertos移植并不是一项简单的任务,需要开发者具备深厚的嵌入式开发经验和相关技能。通过合理的规划、持续的优化,可以实现高效稳定的网络通信。 ### 回答3: 随着物联网应用的日益普及,嵌入式系统中使用lwIP和FreeRTOS的需求越来越大。STM32F4系列是一种高性能的嵌入式微控制器,它支持lwIP和FreeRTOS,因此很适合用于物联网领域的开发。这篇文章将介绍STM32F4xx lwip和FreeRTOS移植步骤。 1. 系统架构 在移植前,需要先了解STM32F4xx系列的架构。STM32F4xx系列的主要子系统有: - Cortex-M4内核 - 系统存储器(SRAM)和闪存 - 外设:USART、SPI、I2C、USB、以太网等 - DMA控制器 lwIP是一个轻量级的IP协议组件库,它能够在嵌入式系统中实现TCP/IP协议栈。在STM32F4xx系列中,lwIP和FreeRTOS可以运行在主内存中。为了获得更好的性能,建议采用SRAM作为系统存储器,并为lwIP和FreeRTOS预留足够的内存空间。 2. 移植步骤 2.1. 配置IDE开发环境 移植lwIP和FreeRTOS需要用到IDE工具,比如Keil、IAR和TrueStudio等。在开发过程中,需要配置好编译器、调试器和开发板等相关环境。 2.2. 配置FreeRTOS FreeRTOSSTM32F4xx系列中的线程操作提供支持。在移植过程中,需要设置线程的优先级、任务管理器、内存管理器和时间管理器等。同时,还需要对FreeRTOS进行适当的调优,以获得更好的性能和可靠性。 2.3. 配置lwIP lwIP的移植涉及到网络协议栈,需要对其进行详细的配置。首先要配置网络接口,包括MAC和IP地址、子网掩码、网关和DNS服务器等。然后需要配置协议栈参数,包括缓冲区的大小、超时时间和最大传输单元(MTU)等。最后还需要配置协议栈服务,包括DHCP、NAT、HTTP、FTP和SMTP等。 2.4. 配置硬件平台 在移植过程中,需要配置硬件平台,包括外设控制器、DMA控制器和引脚映射等。在使用网卡时,还需要配置PHY芯片。 3. 移植测试 在完成lwIP和FreeRTOS移植后,需要进行测试以确保其功能正常。测试方法包括: - 使用ping测试网络连接 - 使用telnet实现远程命令 - 使用HTTP服务器进行数据交互 移植过程中可能会遇到各种问题,比如芯片引脚分配不当、外设驱动程序错误、协议栈配置不正确等。为了快速诊断问题,可以使用调试工具(比如JTAG调试器)或日志文件进行调试。 总之,STM32F4xx lwip和FreeRTOS移植并不是一件容易的事,它需要开发人员具备扎实的嵌入式系统和网络编程技能。当然,一旦成功地移植了它们,就可以让设备更好地应用于物联网领域,为用户提供更为方便、高效和安全的服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值