Add FreeRTOS-Plus directory with new directory structure so it matches the FreeRTOS directory.

This commit is contained in:
Richard Barry 2013-04-18 09:17:05 +00:00
parent 80f7e8cdd4
commit 64a3ab321a
528 changed files with 228252 additions and 0 deletions

View file

@ -0,0 +1,716 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DHCP.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkInterface.h"
#include "IPTraceMacroDefaults.h"
/* Exclude the entire file if DHCP is not enabled. */
#if ipconfigUSE_DHCP != 0
#if ( ipconfigUSE_DHCP != 0 ) && ( ipconfigNETWORK_MTU < 586 )
/* DHCP must be able to receive an options field of 312 bytes, the fixed
part of the DHCP packet is 240 bytes, and the IP/UDP headers take 28 bytes. */
#error ipconfigNETWORK_MTU needs to be at least 586 to use DHCP (588 if ipconfigCAN_FRAGMENT_OUTGOING_PACKETS is set to 1)
#endif
/* Parameter widths in the DHCP packet. */
#define dhcpCLIENT_HARDWARE_ADDRESS_LENGTH 16
#define dhcpSERVER_HOST_NAME_LENGTH 64
#define dhcpBOOT_FILE_NAME_LENGTH 128
/* Timer parameters. Windows simulator times are much shorter because simulated
time is not real time. */
#ifdef _WINDOWS_
#define dhcpINITIAL_DHCP_TX_PERIOD ( 100 / portTICK_RATE_MS )
#define dhcpINITIAL_TIMER_PERIOD ( 10 / portTICK_RATE_MS )
#define dhcpMAX_TIME_TO_WAIT_FOR_ACK ( 200 / portTICK_RATE_MS )
#else
#define dhcpINITIAL_DHCP_TX_PERIOD ( 5000 / portTICK_RATE_MS )
#define dhcpINITIAL_TIMER_PERIOD ( 250 / portTICK_RATE_MS )
#define dhcpMAX_TIME_TO_WAIT_FOR_ACK ( 5000 / portTICK_RATE_MS )
#endif /* _WINDOWS_ */
/* Codes of interest found in the DHCP options field. */
#define dhcpSUBNET_MASK_OPTION_CODE ( 1 )
#define dhcpGATEWAY_OPTION_CODE ( 3 )
#define hdcpDNS_SERVER_OPTIONS_CODE ( 6 )
#define dhcpMESSAGE_TYPE_OPTION_CODE ( 53 )
#define dhcpLEASE_TIME_OPTION_CODE ( 51 )
#define dhcpCLIENT_IDENTIFIER_OPTION_CODE ( 61 )
#define dhcpPARAMETER_REQUEST_OPTION_CODE ( 55 )
#define dhcpREQUEST_IP_ADDRESS_OPTION_CODE ( 50 )
#define dhcpSERVER_IP_ADDRESS_OPTION_CODE ( 54 )
/* The four DHCP message types of interest. */
#define dhcpMESSAGE_TYPE_DISCOVER ( 1 )
#define dhcpMESSAGE_TYPE_OFFER ( 2 )
#define dhcpMESSAGE_TYPE_REQUEST ( 3 )
#define dhcpMESSAGE_TYPE_ACK ( 5 )
#define dhcpMESSAGE_TYPE_NACK ( 6 )
/* Offsets into the transmitted DHCP options fields at which various parameters
are located. */
#define dhcpCLIENT_IDENTIFIER_OFFSET ( 5 )
#define dhcpREQUESTED_IP_ADDRESS_OFFSET ( 13 )
#define dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ( 19 )
/* Values used in the DHCP packets. */
#define dhcpREQUEST_OPCODE ( 1 )
#define dhcpREPLY_OPCODE ( 2 )
#define dhcpADDRESS_TYPE_ETHERNET ( 1 )
#define dhcpETHERNET_ADDRESS_LENGTH ( 6 )
/* If a lease time is not received, use the default of two days. */
#define dhcpDEFAULT_LEASE_TIME ( ( 48UL * 60UL * 60UL * 1000UL ) / portTICK_RATE_MS ) /* 48 hours in ticks. */
/* Don't allow the lease time to be too short. */
#define dhcpMINIMUM_LEASE_TIME ( 60000UL / portTICK_RATE_MS ) /* 60 seconds in ticks. */
/* Marks the end of the variable length options field in the DHCP packet. */
#define dhcpOPTION_END_BYTE 0xff
/* Offset into a DHCP message at which the first byte of the options is
located. */
#define dhcpFIRST_OPTION_BYTE_OFFSET ( 0xf0 )
/* When walking the variable length options field, the following value is used
to ensure the walk has not gone past the end of the valid options. 2 bytes is
made up of the length byte, and minimum one byte value. */
#define dhcpMAX_OPTION_LENGTH_OF_INTEREST ( 2L )
/* Standard DHCP port numbers and magic cookie value. */
#if( ipconfigBYTE_ORDER == FREERTOS_LITTLE_ENDIAN )
#define dhcpCLIENT_PORT 0x4400
#define dhcpSERVER_PORT 0x4300
#define dhcpCOOKIE 0x63538263
#else
#define dhcpCLIENT_PORT 0x0044
#define dhcpSERVER_PORT 0x0043
#define dhcpCOOKIE 0x63825363
#endif /* ipconfigBYTE_ORDER */
#include "pack_struct_start.h"
struct xDHCPMessage
{
uint8_t ucOpcode;
uint8_t ucAddressType;
uint8_t ucAddressLength;
uint8_t ucHops;
uint32_t ulTransactionID;
uint16_t usElapsedTime;
uint16_t usFlags;
uint32_t ulClientIPAddress_ciaddr;
uint32_t ulYourIPAddress_yiaddr;
uint32_t ulServerIPAddress_siaddr;
uint32_t ulRelayAgentIPAddress_giaddr;
uint8_t ucClientHardwareAddress[ dhcpCLIENT_HARDWARE_ADDRESS_LENGTH ];
uint8_t ucServerHostName[ dhcpSERVER_HOST_NAME_LENGTH ];
uint8_t ucBootFileName[ dhcpBOOT_FILE_NAME_LENGTH ];
uint32_t ulDHCPCookie;
uint8_t ucFirstOptionByte;
}
#include "pack_struct_end.h"
typedef struct xDHCPMessage xDHCPMessage_t;
/* DHCP state machine states. */
typedef enum
{
eWaitingSendFirstDiscover = 0, /* Initial state. Send a discover the first time it is called, and reset all timers. */
eWaitingOffer, /* Either resend the discover, or, if the offer is forthcoming, send a request. */
eWaitingAcknowledge, /* Either resend the request. */
eLeasedAddress, /* Resend the request at the appropriate time to renew the lease. */
eNotUsingLeasedAddress /* DHCP failed, and a default IP address is being used. */
} eDHCPState_t;
/*
* Generate a DHCP discover message and send it on the DHCP socket.
*/
static void prvSendDHCPDiscover( xMACAddress_t *pxMACAddress );
/*
* Interpret message received on the DHCP socket.
*/
static portBASE_TYPE prvProcessDHCPReplies( uint8_t ucExpectedMessageType, xMACAddress_t *pxMACAddress, xNetworkAddressingParameters_t *pxNetworkAddressing );
/*
* Generate a DHCP request packet, and send it on the DHCP socket.
*/
static void prvSendDHCPRequest( xMACAddress_t *pxMACAddress );
/*
* Prepare to start a DHCP transaction. This initialises some state variables
* and creates the DHCP socket if necessary.
*/
static void prvInitialiseDHCP( void );
/*
* Creates the part of outgoing DHCP messages that are common to all outgoing
* DHCP messages.
*/
static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress, xMACAddress_t *pxMACAddress, uint8_t ucOpcode, const uint8_t * const pucOptionsArray, size_t xOptionsArraySize );
/*
* Create the DHCP socket, if it has not been created already.
*/
static void prvCreateDHCPSocket( void );
/*-----------------------------------------------------------*/
/* The timer used to drive the DHCP state machine. */
static xTimerHandle xDHCPTimer = NULL;
/* The UDP socket used for all incoming and outgoing DHCP traffic. */
static xSocket_t xDHCPSocket = NULL;
/* Hold information in between steps in the DHCP state machine. */
static uint32_t ulTransactionId = 0UL, ulOfferedIPAddress = 0UL, ulDHCPServerAddress = 0UL, ulLeaseTime = 0;
/* Hold information on the current timer state. */
static portTickType xDHCPTxTime = 0x00, xDHCPTxPeriod = 0x00;
/* Maintains the DHCP state machine state. */
static eDHCPState_t eDHCPState = eWaitingSendFirstDiscover;
/*-----------------------------------------------------------*/
void vDHCPProcess( portBASE_TYPE xReset, xMACAddress_t *pxMACAddress, uint32_t *pulIPAddress, xNetworkAddressingParameters_t *pxNetworkAddressing )
{
if( xReset != pdFALSE )
{
eDHCPState = eWaitingSendFirstDiscover;
}
switch( eDHCPState )
{
case eWaitingSendFirstDiscover :
/* Initial state. Create the DHCP socket, timer, etc. if they
have not already been created. */
prvInitialiseDHCP();
*pulIPAddress = 0UL;
/* Send the first discover request. */
if( xDHCPSocket != NULL )
{
xDHCPTxTime = xTaskGetTickCount();
prvSendDHCPDiscover( pxMACAddress );
eDHCPState = eWaitingOffer;
}
break;
case eWaitingOffer :
/* Look for offers coming in. */
if( prvProcessDHCPReplies( dhcpMESSAGE_TYPE_OFFER, pxMACAddress, pxNetworkAddressing ) == pdPASS )
{
/* An offer has been made, generate the request. */
xDHCPTxTime = xTaskGetTickCount();
xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
prvSendDHCPRequest( pxMACAddress );
eDHCPState = eWaitingAcknowledge;
}
else
{
/* Is it time to send another Discover? */
if( ( xTaskGetTickCount() - xDHCPTxTime ) > xDHCPTxPeriod )
{
/* Increase the time period, and if it has not got to the
point of giving up - send another discovery. */
xDHCPTxPeriod <<= 1;
if( xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD )
{
ulTransactionId++;
xDHCPTxTime = xTaskGetTickCount();
prvSendDHCPDiscover( pxMACAddress );
}
else
{
/* Revert to static IP address. */
taskENTER_CRITICAL();
{
*pulIPAddress = pxNetworkAddressing->ulDefaultIPAddress;
iptraceDHCP_REQUESTS_FAILED_USING_DEFAULT_IP_ADDRESS( pxNetworkAddressing->ulDefaultIPAddress );
}
taskEXIT_CRITICAL();
eDHCPState = eNotUsingLeasedAddress;
xTimerStop( xDHCPTimer, ( portTickType ) 0 );
#if ipconfigFREERTOS_PLUS_NABTO == 1
{
vStartNabtoTask();
}
#endif /* ipconfigFREERTOS_PLUS_NABTO */
#if ipconfigUSE_NETWORK_EVENT_HOOK == 1
{
vApplicationIPNetworkEventHook( eNetworkUp );
}
#endif
/* Close socket to ensure packets don't queue on it. */
FreeRTOS_closesocket( xDHCPSocket );
xDHCPSocket = NULL;
}
}
}
break;
case eWaitingAcknowledge :
/* Look for acks coming in. */
if( prvProcessDHCPReplies( dhcpMESSAGE_TYPE_ACK, pxMACAddress, pxNetworkAddressing ) == pdPASS )
{
/* DHCP completed. The IP address can now be used, and the
timer set to the lease timeout time. */
*pulIPAddress = ulOfferedIPAddress;
eDHCPState = eLeasedAddress;
#if ipconfigFREERTOS_PLUS_NABTO == 1
{
vStartNabtoTask();
}
#endif /* ipconfigFREERTOS_PLUS_NABTO */
#if ipconfigUSE_NETWORK_EVENT_HOOK == 1
{
vApplicationIPNetworkEventHook( eNetworkUp );
}
#endif
/* Close socket to ensure packets don't queue on it. */
FreeRTOS_closesocket( xDHCPSocket );
xDHCPSocket = NULL;
if( ulLeaseTime == 0UL )
{
ulLeaseTime = dhcpDEFAULT_LEASE_TIME;
}
else if( ulLeaseTime < dhcpMINIMUM_LEASE_TIME )
{
ulLeaseTime = dhcpMINIMUM_LEASE_TIME;
}
else
{
/* The lease time is already valid. */
}
xTimerChangePeriod( xDHCPTimer, ulLeaseTime, portMAX_DELAY );
}
else
{
/* Is it time to send another Discover? */
if( ( xTaskGetTickCount() - xDHCPTxTime ) > xDHCPTxPeriod )
{
/* Increase the time period, and if it has not got to the
point of giving up - send another request. */
xDHCPTxPeriod <<= 1;
if( xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD )
{
xDHCPTxTime = xTaskGetTickCount();
prvSendDHCPRequest( pxMACAddress );
}
else
{
/* Give up, start again. */
eDHCPState = eWaitingSendFirstDiscover;
}
}
}
break;
case eLeasedAddress :
/* Resend the request at the appropriate time to renew the lease. */
prvCreateDHCPSocket();
if( xDHCPSocket != NULL )
{
xDHCPTxTime = xTaskGetTickCount();
xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
prvSendDHCPRequest( pxMACAddress );
eDHCPState = eWaitingAcknowledge;
}
xTimerChangePeriod( xDHCPTimer, dhcpINITIAL_TIMER_PERIOD, portMAX_DELAY );
break;
case eNotUsingLeasedAddress:
xTimerStop( xDHCPTimer, ( portTickType ) 0 );
break;
}
}
/*-----------------------------------------------------------*/
static void prvCreateDHCPSocket( void )
{
struct freertos_sockaddr xAddress;
portBASE_TYPE xReturn;
portTickType xTimeoutTime = 0;
/* Create the socket, if it has not already been created. */
if( xDHCPSocket == NULL )
{
xDHCPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
configASSERT( ( xDHCPSocket != FREERTOS_INVALID_SOCKET ) );
/* Ensure the Rx and Tx timeouts are zero as the DHCP executes in the
context of the IP task. */
FreeRTOS_setsockopt( xDHCPSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xTimeoutTime, sizeof( portTickType ) );
FreeRTOS_setsockopt( xDHCPSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xTimeoutTime, sizeof( portTickType ) );
/* Bind to the standard DHCP client port. */
xAddress.sin_port = dhcpCLIENT_PORT;
xReturn = FreeRTOS_bind( xDHCPSocket, &xAddress, sizeof( xAddress ) );
configASSERT( xReturn == 0 );
/* Remove compiler warnings if configASSERT() is not defined. */
( void ) xReturn;
}
}
/*-----------------------------------------------------------*/
static void prvInitialiseDHCP( void )
{
extern void vIPFunctionsTimerCallback( xTimerHandle xTimer );
/* Initialise the parameters that will be set by the DHCP process. */
if( ulTransactionId == 0 )
{
ulTransactionId = ipconfigRAND32();
}
else
{
ulTransactionId++;
}
ulOfferedIPAddress = 0UL;
ulDHCPServerAddress = 0UL;
xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
/* Create the DHCP socket if it has not already been created. */
prvCreateDHCPSocket();
if( xDHCPTimer == NULL )
{
xDHCPTimer = xTimerCreate( ( const signed char * const ) "DHCP", dhcpINITIAL_TIMER_PERIOD, pdTRUE, ( void * ) eDHCPEvent, vIPFunctionsTimerCallback );
configASSERT( xDHCPTimer );
xTimerStart( xDHCPTimer, portMAX_DELAY );
}
else
{
xTimerChangePeriod( xDHCPTimer, dhcpINITIAL_TIMER_PERIOD, portMAX_DELAY );
}
}
/*-----------------------------------------------------------*/
static portBASE_TYPE prvProcessDHCPReplies( uint8_t ucExpectedMessageType, xMACAddress_t *pxMACAddress, xNetworkAddressingParameters_t *pxNetworkAddressing )
{
uint8_t *pucUDPPayload, *pucLastByte;
struct freertos_sockaddr xClient;
uint32_t xClientLength = sizeof( xClient );
int32_t lBytes;
xDHCPMessage_t *pxDHCPMessage;
uint8_t *pucByte, ucOptionCode, ucLength;
uint32_t ulProcessed;
portBASE_TYPE xReturn = pdFALSE;
const uint32_t ulMandatoryOptions = 2; /* DHCP server address, and the correct DHCP message type must be present in the options. */
lBytes = FreeRTOS_recvfrom( xDHCPSocket, ( void * ) &pucUDPPayload, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength );
if( lBytes > 0 )
{
/* Map a DHCP structure onto the received data. */
pxDHCPMessage = ( xDHCPMessage_t * ) ( pucUDPPayload );
/* Sanity check. */
if( ( pxDHCPMessage->ulDHCPCookie == dhcpCOOKIE ) && ( pxDHCPMessage->ucOpcode == dhcpREPLY_OPCODE ) && ( pxDHCPMessage->ulTransactionID == ulTransactionId ) )
{
if( memcmp( ( void * ) &( pxDHCPMessage->ucClientHardwareAddress ), ( void * ) pxMACAddress, sizeof( xMACAddress_t ) ) == 0 )
{
/* None of the essential options have been processed yet. */
ulProcessed = 0;
/* Walk through the options until the dhcpOPTION_END_BYTE byte
is found, taking care not to walk off the end of the options. */
pucByte = &( pxDHCPMessage->ucFirstOptionByte );
pucLastByte = &( pucUDPPayload[ lBytes - dhcpMAX_OPTION_LENGTH_OF_INTEREST ] );
while( ( *pucByte != dhcpOPTION_END_BYTE ) && ( pucByte < pucLastByte ) )
{
ucOptionCode = *pucByte;
pucByte++;
ucLength = *pucByte;
pucByte++;
switch( ucOptionCode )
{
case dhcpMESSAGE_TYPE_OPTION_CODE :
if( *pucByte == ucExpectedMessageType )
{
/* The message type is the message type the
state machine is expecting. */
ulProcessed++;
}
else if( *pucByte == dhcpMESSAGE_TYPE_NACK )
{
if( ucExpectedMessageType == dhcpMESSAGE_TYPE_ACK )
{
/* Start again. */
eDHCPState = eWaitingSendFirstDiscover;
}
}
else
{
/* Don't process other message types. */
}
break;
case dhcpSUBNET_MASK_OPTION_CODE :
if( ucLength == sizeof( uint32_t ) )
{
memcpy( ( void * ) &( pxNetworkAddressing->ulNetMask ), ( void * ) pucByte, ( size_t ) ucLength );
}
break;
case dhcpGATEWAY_OPTION_CODE :
if( ucLength == sizeof( uint32_t ) )
{
/* ulProcessed is not incremented in this case
because the gateway is not essential. */
memcpy( ( void * ) &( pxNetworkAddressing->ulGatewayAddress ), ( void * ) pucByte, ( size_t ) ucLength );
}
break;
case hdcpDNS_SERVER_OPTIONS_CODE :
/* ulProcessed is not incremented in this case
because the DNS server is not essential. Only the
first DNS server address is taken. */
memcpy( ( void * ) &( pxNetworkAddressing->ulDNSServerAddress ), ( void * ) pucByte, sizeof( uint32_t ) );
break;
case dhcpSERVER_IP_ADDRESS_OPTION_CODE :
if( ucLength == sizeof( uint32_t ) )
{
if( ucExpectedMessageType == dhcpMESSAGE_TYPE_OFFER )
{
/* Offers state the replying server. */
ulProcessed++;
memcpy( ( void * ) &ulDHCPServerAddress, ( void * ) pucByte, ( size_t ) ucLength );
}
else
{
/* The ack must come from the expected server. */
if( memcmp( ( void * ) &ulDHCPServerAddress, ( void * ) pucByte, ( size_t ) ucLength ) == 0 )
{
ulProcessed++;
}
}
}
break;
case dhcpLEASE_TIME_OPTION_CODE :
if( ucLength == sizeof( &ulLeaseTime ) )
{
/* ulProcessed is not incremented in this case
because the lease time is not essential. */
memcpy( ( void * ) &ulLeaseTime, ( void * ) pucByte, ( size_t ) ucLength );
ulLeaseTime = FreeRTOS_ntohl( ulLeaseTime );
/* Convert the lease time to milliseconds
(*1000) then ticks (/portTICK_RATE_MS). */
ulLeaseTime *= ( 1000UL / portTICK_RATE_MS );
/* Divide the lease time to ensure a renew
request is sent before the lease actually
expires. */
ulLeaseTime >>= 1UL;
}
break;
default :
/* Not interested in this field. */
break;
}
/* Jump over the data to find the next option code. */
if( ucLength == 0 )
{
break;
}
else
{
pucByte += ucLength;
}
}
/* Were all the mandatory options received? */
if( ulProcessed == ulMandatoryOptions )
{
ulOfferedIPAddress = pxDHCPMessage->ulYourIPAddress_yiaddr;
xReturn = pdPASS;
}
}
}
FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayload );
}
return xReturn;
}
/*-----------------------------------------------------------*/
static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress, xMACAddress_t *pxMACAddress, uint8_t ucOpcode, const uint8_t * const pucOptionsArray, size_t xOptionsArraySize )
{
xDHCPMessage_t *pxDHCPMessage;
const size_t xRequiredBufferSize = sizeof( xDHCPMessage_t ) + xOptionsArraySize;
uint8_t *pucUDPPayloadBuffer;
/* Get a buffer. This uses a maximum delay, but the delay will be capped
to ipconfigMAX_SEND_BLOCK_TIME_TICKS so the return value still needs to be
test. */
do
{
}while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xRequiredBufferSize, portMAX_DELAY ) ) == NULL );
pxDHCPMessage = ( xDHCPMessage_t * ) pucUDPPayloadBuffer;
/* Most fields need to be zero. */
memset( ( void * ) pxDHCPMessage, 0x00, sizeof( xDHCPMessage_t ) );
/* Create the message. */
pxDHCPMessage->ucOpcode = ucOpcode;
pxDHCPMessage->ucAddressType = dhcpADDRESS_TYPE_ETHERNET;
pxDHCPMessage->ucAddressLength = dhcpETHERNET_ADDRESS_LENGTH;
pxDHCPMessage->ulTransactionID = ulTransactionId;
pxDHCPMessage->ulYourIPAddress_yiaddr = ulOfferedIPAddress;
pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE;
memcpy( ( void * ) &( pxDHCPMessage->ucClientHardwareAddress[ 0 ] ), ( void * ) pxMACAddress, sizeof( xMACAddress_t ) );
/* Copy in the const part of the options options. */
memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET ] ), ( void * ) pucOptionsArray, xOptionsArraySize );
/* Map in the client identifier. */
memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpCLIENT_IDENTIFIER_OFFSET ] ), ( void * ) pxMACAddress, sizeof( xMACAddress_t ) );
/* Set the addressing. */
pxAddress->sin_addr = ipBROADCAST_IP_ADDRESS;
pxAddress->sin_port = ( uint16_t ) dhcpSERVER_PORT;
return pucUDPPayloadBuffer;
}
/*-----------------------------------------------------------*/
static void prvSendDHCPRequest( xMACAddress_t *pxMACAddress )
{
uint8_t *pucUDPPayloadBuffer;
struct freertos_sockaddr xAddress;
static const uint8_t ucDHCPRequestOptions[] =
{
/* Do not change the ordering without also changing
dhcpCLIENT_IDENTIFIER_OFFSET, dhcpREQUESTED_IP_ADDRESS_OFFSET and
dhcpDHCP_SERVER_IP_ADDRESS_OFFSET. */
dhcpMESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_REQUEST, /* Message type option. */
dhcpCLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0, /* Client identifier. */
dhcpREQUEST_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address being requested. */
dhcpSERVER_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address of the DHCP server. */
dhcpOPTION_END_BYTE
};
pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, pxMACAddress, dhcpREQUEST_OPCODE, ucDHCPRequestOptions, sizeof( ucDHCPRequestOptions ) );
/* Copy in the IP address being requested. */
memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpREQUESTED_IP_ADDRESS_OFFSET ] ), ( void * ) &ulOfferedIPAddress, sizeof( ulOfferedIPAddress ) );
/* Copy in the address of the DHCP server being used. */
memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ] ), ( void * ) &ulDHCPServerAddress, sizeof( ulDHCPServerAddress ) );
iptraceSENDING_DHCP_REQUEST();
if( FreeRTOS_sendto( xDHCPSocket, pucUDPPayloadBuffer, ( sizeof( xDHCPMessage_t ) + sizeof( ucDHCPRequestOptions ) ), FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) == 0 )
{
/* The packet was not successfully queued for sending and must be
returned to the stack. */
FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );
}
}
/*-----------------------------------------------------------*/
static void prvSendDHCPDiscover( xMACAddress_t *pxMACAddress )
{
uint8_t *pucUDPPayloadBuffer;
struct freertos_sockaddr xAddress;
static const uint8_t ucDHCPDiscoverOptions[] =
{
/* Do not change the ordering without also changing dhcpCLIENT_IDENTIFIER_OFFSET. */
dhcpMESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_DISCOVER, /* Message type option. */
dhcpCLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0, /* Client identifier. */
dhcpPARAMETER_REQUEST_OPTION_CODE, 3, dhcpSUBNET_MASK_OPTION_CODE, dhcpGATEWAY_OPTION_CODE, hdcpDNS_SERVER_OPTIONS_CODE, /* Parameter request option. */
dhcpOPTION_END_BYTE
};
pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, pxMACAddress, dhcpREQUEST_OPCODE, ucDHCPDiscoverOptions, sizeof( ucDHCPDiscoverOptions ) );
iptraceSENDING_DHCP_DISCOVER();
if( FreeRTOS_sendto( xDHCPSocket, pucUDPPayloadBuffer, ( sizeof( xDHCPMessage_t ) + sizeof( ucDHCPDiscoverOptions ) ), FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) == 0 )
{
/* The packet was not successfully queued for sending and must be
returned to the stack. */
FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );
}
}
/*-----------------------------------------------------------*/
#endif /* ipconfigUSE_DHCP != 0 */

View file

@ -0,0 +1,411 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkInterface.h"
#include "IPTraceMacroDefaults.h"
/* Exclude the entire file if DNS is not enabled. */
#if ipconfigUSE_DNS != 0
#if( ipconfigBYTE_ORDER == FREERTOS_LITTLE_ENDIAN )
#define dnsOUTGOING_FLAGS 0x0001 /* Standard query. */
#define dnsTYPE 0x0100 /* A record (host address. */
#define dnsCLASS 0x0100 /* IN */
#define dnsDNS_PORT 0x3500
#define dnsONE_QUESTION 0x0100
#define dnsRX_FLAGS_MASK 0x0f80 /* The bits of interest in the flags field of incoming DNS messages. */
#define dnsEXPECTED_RX_FLAGS 0x0080 /* Should be a response, without any errors. */
#else
#define dnsDNS_PORT 0x35
#define dnsONE_QUESTION 0x01
#define dnsFLAG_QUERY_RESPONSE_BIT 0x8000
#define dnsFLAG_OPERATION_CODE_BITS 0x7800
#define dnsFLAG_TRUNCATION_BIT 0x0200
#define dnsFLAG_RESPONSE_CODE_BITS 0x000f
#define dnsOUTGOING_FLAGS 0x0100 /* Standard query. */
#define dnsTYPE 0x0001 /* A record (host address. */
#define dnsCLASS 0x0001 /* IN */
#define dnsRX_FLAGS_MASK 0x800f /* The bits of interest in the flags field of incoming DNS messages. */
#define dnsEXPECTED_RX_FLAGS 0x8000 /* Should be a response, without any errors. */
#endif /* ipconfigBYTE_ORDER */
/* The maximum number of times a DNS request should be sent out if a response
is not received, before giving up. */
#define dnsMAX_REQUEST_ATTEMPTS 5
/* If the top two bits in the first character of a name field are set then the
name field is an offset to the string, rather than the string itself. */
#define dnsNAME_IS_OFFSET ( ( uint8_t ) 0xc0 )
/*
* Create a socket and bind it to the standard DNS port number. Return the
* the created socket - or NULL if the socket could not be created or bound.
*/
static xSocket_t prvCreateDNSSocket( void );
/*
* Create the DNS message in the zero copy buffer passed in the first parameter.
*/
static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer, const uint8_t *pcHostName, uint16_t usIdentifier );
/*
* Simple routine that jumps over the NAME field of a resource record.
*/
static uint8_t *prvSkipNameField( uint8_t *pucByte );
/*
* Process a response packet from a DNS server.
*/
static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, uint16_t usIdentifier );
/*-----------------------------------------------------------*/
#include "pack_struct_start.h"
struct xDNSMessage
{
uint16_t usIdentifier;
uint16_t usFlags;
uint16_t usQuestions;
uint16_t usAnswers;
uint16_t usAuthorityRRs;
uint16_t usAdditionalRRs;
}
#include "pack_struct_end.h"
typedef struct xDNSMessage xDNSMessage_t;
/*-----------------------------------------------------------*/
uint32_t FreeRTOS_gethostbyname( const uint8_t *pcHostName )
{
static uint16_t usIdentifier = 0;
struct freertos_sockaddr xAddress;
static xSocket_t xDNSSocket = NULL;
uint32_t ulIPAddress = 0UL;
uint8_t *pucUDPPayloadBuffer;
static uint32_t ulAddressLength;
portBASE_TYPE xAttempt;
int32_t lBytes;
size_t xPayloadLength;
const size_t xExpectedPayloadLength = sizeof( xDNSMessage_t ) + strlen( ( const char * const ) pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2; /* Two for the count of characters in the first subdomain part, and the string end byte */
if( xDNSSocket == NULL )
{
xDNSSocket = prvCreateDNSSocket();
}
if( xDNSSocket != NULL )
{
/* Generate a unique identifier for this query. */
usIdentifier++;
for( xAttempt = 0; xAttempt < dnsMAX_REQUEST_ATTEMPTS; xAttempt++ )
{
/* Get a buffer. This uses a maximum delay, but the delay will be
capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS so the return value
still needs to be tested. */
pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xExpectedPayloadLength, portMAX_DELAY );
if( pucUDPPayloadBuffer != NULL )
{
/* Create the message in the obtained buffer. */
xPayloadLength = prvCreateDNSMessage( pucUDPPayloadBuffer, pcHostName, usIdentifier );
iptraceSENDING_DNS_REQUEST();
/* Obtain the DNS server address. */
FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulIPAddress );
/* Send the DNS message. */
xAddress.sin_addr = ulIPAddress;
xAddress.sin_port = dnsDNS_PORT;
ulIPAddress = 0;
if( FreeRTOS_sendto( xDNSSocket, pucUDPPayloadBuffer, xPayloadLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) != 0 )
{
/* Wait for the reply. */
lBytes = FreeRTOS_recvfrom( xDNSSocket, &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xAddress, &ulAddressLength );
if( lBytes > 0 )
{
/* The reply was received. Process it. */
ulIPAddress = prvParseDNSReply( pucUDPPayloadBuffer, usIdentifier );
/* Finished with the buffer. The zero copy interface
is being used, so the buffer must be freed by the
task. */
FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
if( ulIPAddress != 0 )
{
/* All done. */
break;
}
}
}
else
{
/* The message was not sent so the stack will not be
releasing the zero copy - it must be released here. */
FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
}
}
}
}
return ulIPAddress;
}
/*-----------------------------------------------------------*/
static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer, const uint8_t *pcHostName, uint16_t usIdentifier )
{
xDNSMessage_t *pxDNSMessageHeader;
uint8_t *pucStart, *pucByte;
const uint16_t usARecordType = dnsTYPE, usClass = dnsCLASS;
static const xDNSMessage_t xDefaultPartDNSHeader =
{
0, /* The identifier will be overwritten. */
dnsOUTGOING_FLAGS, /* Flags set for standard query. */
dnsONE_QUESTION, /* One question is being asked. */
0, /* No replies are included. */
0, /* No authorities. */
0 /* No additional authorities. */
};
/* Copy in the const part of the header. */
memcpy( ( void * ) pucUDPPayloadBuffer, ( void * ) &xDefaultPartDNSHeader, sizeof( xDefaultPartDNSHeader ) );
/* Write in a unique identifier. */
pxDNSMessageHeader = ( xDNSMessage_t * ) pucUDPPayloadBuffer;
pxDNSMessageHeader->usIdentifier = usIdentifier;
/* Create the resource record at the end of the header. First
find the end of the header. */
pucStart = pucUDPPayloadBuffer + sizeof( xDefaultPartDNSHeader );
/* Leave a gap for the first length bytes. */
pucByte = pucStart + 1;
/* Copy in the host name. */
strcpy( ( char * ) pucByte, ( const char * ) pcHostName );
/* Mark the end of the string. */
pucByte += strlen( ( const char * ) pcHostName );
*pucByte = 0x00;
/* Walk the string to replace the '.' characters with byte counts.
pucStart holds the address of the byte count. Walking the string
starts after the byte count position. */
pucByte = pucStart;
do
{
pucByte++;
while( ( *pucByte != 0x00 ) && ( *pucByte != '.' ) )
{
pucByte++;
}
/* Fill in the byte count, then move the pucStart pointer up to
the found byte position. */
*pucStart = ( uint8_t ) ( ( uint32_t ) pucByte - ( uint32_t ) pucStart );
( *pucStart )--;
pucStart = pucByte;
} while( *pucByte != 0x00 );
/* Finish off the record. */
pucByte++;
memcpy( ( void * ) pucByte, &usARecordType, sizeof( uint16_t ) );
pucByte += sizeof( uint16_t );
memcpy( ( void * ) pucByte, &usClass, sizeof( uint16_t ) );
pucByte += sizeof( uint16_t );
/* Return the total size of the generated message, which is the space from
the last written byte to the beginning of the buffer. */
return ( ( uint32_t ) pucByte - ( uint32_t ) pucUDPPayloadBuffer );
}
/*-----------------------------------------------------------*/
static uint8_t *prvSkipNameField( uint8_t *pucByte )
{
/* Determine if the name is the fully coded name, or an offset to the name
elsewhere in the message. */
if( ( *pucByte & dnsNAME_IS_OFFSET ) == dnsNAME_IS_OFFSET )
{
/* Jump over the two byte offset. */
pucByte += sizeof( uint16_t );
}
else
{
/* pucByte points to the full name. Walk over the string. */
while( *pucByte != 0x00 )
{
/* The number of bytes to jump for each name section is stored in the byte
before the name section. */
pucByte += ( *pucByte + 1 );
}
pucByte++;
}
return pucByte;
}
/*-----------------------------------------------------------*/
static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, uint16_t usIdentifier )
{
xDNSMessage_t *pxDNSMessageHeader;
uint32_t ulIPAddress = 0UL;
uint8_t *pucByte;
uint16_t x, usDataLength;
const uint16_t usARecordType = dnsTYPE;
pxDNSMessageHeader = ( xDNSMessage_t * ) pucUDPPayloadBuffer;
if( pxDNSMessageHeader->usIdentifier == usIdentifier )
{
if( ( pxDNSMessageHeader->usFlags & dnsRX_FLAGS_MASK ) == dnsEXPECTED_RX_FLAGS )
{
/* Start at the first byte after the header. */
pucByte = pucUDPPayloadBuffer + sizeof( xDNSMessage_t );
/* Skip any question records. */
pxDNSMessageHeader->usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions );
for( x = 0; x < pxDNSMessageHeader->usQuestions; x++ )
{
/* Skip the variable length name field. */
pucByte = prvSkipNameField( pucByte );
/* Skip the type and class fields. */
pucByte += sizeof( uint32_t );
}
/* Search through the answers records. */
pxDNSMessageHeader->usAnswers = FreeRTOS_ntohs( pxDNSMessageHeader->usAnswers );
for( x = 0; x < pxDNSMessageHeader->usAnswers; x++ )
{
pucByte = prvSkipNameField( pucByte );
/* Is the type field that of an A record? */
if( memcmp( ( void * ) pucByte, ( void * ) &usARecordType, sizeof( uint16_t ) ) == 0 )
{
/* This is the required record. Skip the type, class, and
time to live fields, plus the first byte of the data
length. */
pucByte += ( sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( uint8_t ) );
/* Sanity check the data length. */
if( *pucByte == sizeof( uint32_t ) )
{
/* Skip the second byte of the length. */
pucByte++;
/* Copy the IP address out of the record. */
memcpy( ( void * ) &ulIPAddress, ( void * ) pucByte, sizeof( uint32_t ) );
}
break;
}
else
{
/* Skip the type, class and time to live fields. */
pucByte += ( sizeof( uint32_t ) + sizeof( uint32_t ) );
/* Determine the length of the data in the field. */
memcpy( ( void * ) &usDataLength, ( void * ) pucByte, sizeof( uint16_t ) );
usDataLength = FreeRTOS_ntohs( usDataLength );
/* Jump over the data lenth bytes, and the data itself. */
pucByte += usDataLength + sizeof( uint16_t );
}
}
}
}
return ulIPAddress;
}
/*-----------------------------------------------------------*/
static xSocket_t prvCreateDNSSocket( void )
{
static xSocket_t xSocket = NULL;
struct freertos_sockaddr xAddress;
portBASE_TYPE xReturn;
portTickType xTimeoutTime = 200 / portTICK_RATE_MS;
/* This must be the first time this function has been called. Create
the socket. */
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
/* Auto bind the port. */
xAddress.sin_port = 0;
xReturn = FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );
/* Check the bind was successful, and clean up if not. */
if( xReturn != 0 )
{
FreeRTOS_closesocket( xSocket );
xSocket = NULL;
}
else
{
/* Set the send and receive timeouts. */
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xTimeoutTime, sizeof( portTickType ) );
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xTimeoutTime, sizeof( portTickType ) );
}
return xSocket;
}
#endif /* ipconfigUSE_DNS != 0 */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,23 @@
Changes between V1.0.0 and V1.0.0
+ Add select() function.
Changes between V1.0.0rc1 and V1.0.0:
+ Correct name of prvCompleteUDPHeader().
+ Ensure network down events cannot be missed when the network event queue
to which they are posted is full.
+ Only start the ARP timer when the network has connected.
+ Remove initialisation call to the DHCP state machine - the call is made
directly when the network connects.
+ Add the network event queue and the BufferAllocation_2.c counting
semaphore to the queue registry.
+ Only initialise the DMA buffers in the lpc18xx_emac.c driver if the
autonegotiation was successful.
Known issues in this version:
+ DHCP server attempts to copy the IP addresses of all the offered DNS
servers into a buffer than can only hold one address.

View file

@ -0,0 +1,5 @@
[InternetShortcut]
URL=http://www.freertos.org/udp
IDList=
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2

View file

@ -0,0 +1,138 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
#ifndef FREERTOS_DEFAULT_IP_CONFIG_H
#define FREERTOS_DEFAULT_IP_CONFIG_H
/* This file provides default values for configuration options that are missing
from the FreeRTOSIPConfig.h configuration header file. */
#ifndef ipconfigUSE_NETWORK_EVENT_HOOK
#define ipconfigUSE_NETWORK_EVENT_HOOK 0
#endif
#ifndef ipconfigMAX_SEND_BLOCK_TIME_TICKS
#define ipconfigMAX_SEND_BLOCK_TIME_TICKS ( 20 / portTICK_RATE_MS )
#endif
#ifndef ipconfigARP_CACHE_ENTRIES
#define ipconfigARP_CACHE_ENTRIES 10
#endif
#ifndef ipconfigMAX_ARP_RETRANSMISSIONS
#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 )
#endif
#ifndef ipconfigMAX_ARP_AGE
#define ipconfigMAX_ARP_AGE 150
#endif
#ifndef ipconfigINCLUDE_FULL_INET_ADDR
#define ipconfigINCLUDE_FULL_INET_ADDR 1
#endif
#ifndef ipconfigNUM_NETWORK_BUFFERS
#define ipconfigNUM_NETWORK_BUFFERS 45
#endif
#ifndef ipconfigEVENT_QUEUE_LENGTH
#define ipconfigEVENT_QUEUE_LENGTH ( ipconfigNUM_NETWORK_BUFFERS + 5 )
#endif
#ifndef ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND
#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1
#endif
#ifndef updconfigIP_TIME_TO_LIVE
#define updconfigIP_TIME_TO_LIVE 128
#endif
#ifndef ipconfigCAN_FRAGMENT_OUTGOING_PACKETS
#define ipconfigCAN_FRAGMENT_OUTGOING_PACKETS 0
#endif
#ifndef ipconfigNETWORK_MTU
#define ipconfigNETWORK_MTU 1500
#endif
#ifndef ipconfigUSE_DHCP
#define ipconfigUSE_DHCP 1
#endif
#ifndef ipconfigMAXIMUM_DISCOVER_TX_PERIOD
#ifdef _WINDOWS_
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( 999 / portTICK_RATE_MS )
#else
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( 30000 / portTICK_RATE_MS )
#endif /* _WINDOWS_ */
#endif /* ipconfigMAXIMUM_DISCOVER_TX_PERIOD */
#ifndef ipconfigUSE_DNS
#define ipconfigUSE_DNS 1
#endif
#ifndef ipconfigREPLY_TO_INCOMING_PINGS
#define ipconfigREPLY_TO_INCOMING_PINGS 1
#endif
#ifndef ipconfigSUPPORT_OUTGOING_PINGS
#define ipconfigSUPPORT_OUTGOING_PINGS 0
#endif
#ifndef updconfigLOOPBACK_ETHERNET_PACKETS
#define updconfigLOOPBACK_ETHERNET_PACKETS 0
#endif
#ifndef ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES
#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1
#endif
#ifndef ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES
#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1
#endif
#ifndef configINCLUDE_TRACE_RELATED_CLI_COMMANDS
#define ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS 0
#else
#define ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS configINCLUDE_TRACE_RELATED_CLI_COMMANDS
#endif
#ifndef ipconfigFREERTOS_PLUS_NABTO
#define ipconfigFREERTOS_PLUS_NABTO 0
#endif
#endif /* FREERTOS_DEFAULT_IP_CONFIG_H */

View file

@ -0,0 +1,63 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
#ifndef FREERTOS_DHCP_H
#define FREERTOS_DHCP_H
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "IPTraceMacroDefaults.h"
/*
* NOT A PUBLIC API FUNCTION.
*/
void vDHCPProcess( portBASE_TYPE xReset, xMACAddress_t *pxMACAddress, uint32_t *pulIPAddress, xNetworkAddressingParameters_t *pxNetworkAddressing );
#endif /* FREERTOS_DHCP_H */

View file

@ -0,0 +1,65 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
#ifndef FREERTOS_DNS_H
#define FREERTOS_DNS_H
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "IPTraceMacroDefaults.h"
/**
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
* FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/FreeRTOS_UDP_API_Functions.shtml
*/
uint32_t FreeRTOS_gethostbyname( const uint8_t *pcHostName );
#endif /* FREERTOS_DNS_H */

View file

@ -0,0 +1,344 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
#ifndef FREERTOS_IP_PRIVATE_H
#define FREERTOS_IP_PRIVATE_H
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "IPTraceMacroDefaults.h"
typedef struct xNetworkAddressingParameters
{
uint32_t ulDefaultIPAddress;
uint32_t ulNetMask;
uint32_t ulGatewayAddress;
uint32_t ulDNSServerAddress;
} xNetworkAddressingParameters_t;
/*-----------------------------------------------------------*/
/* Protocol headers. */
/*-----------------------------------------------------------*/
#include "pack_struct_start.h"
struct xETH_HEADER
{
xMACAddress_t xDestinationAddress;
xMACAddress_t xSourceAddress;
uint16_t usFrameType;
}
#include "pack_struct_end.h"
typedef struct xETH_HEADER xEthernetHeader_t;
#include "pack_struct_start.h"
struct xARP_HEADER
{
uint16_t usHardwareType;
uint16_t usProtocolType;
uint8_t ucHardwareAddressLength;
uint8_t ucProtocolAddressLength;
uint16_t usOperation;
xMACAddress_t xSenderHardwareAddress;
uint32_t ulSenderProtocolAddress;
xMACAddress_t xTargetHardwareAddress;
uint32_t ulTargetProtocolAddress;
}
#include "pack_struct_end.h"
typedef struct xARP_HEADER xARPHeader_t;
#include "pack_struct_start.h"
struct xIP_HEADER
{
uint8_t ucVersionHeaderLength;
uint8_t ucDifferentiatedServicesCode;
uint16_t usLength;
uint16_t usIdentification;
uint16_t usFragmentOffset;
uint8_t ucTimeToLive;
uint8_t ucProtocol;
uint16_t usHeaderChecksum;
uint32_t ulSourceIPAddress;
uint32_t ulDestinationIPAddress;
}
#include "pack_struct_end.h"
typedef struct xIP_HEADER xIPHeader_t;
#define ipSIZE_OF_IP_HEADER 20
#include "pack_struct_start.h"
struct xICMP_HEADER
{
uint8_t ucTypeOfMessage;
uint8_t ucTypeOfService;
uint16_t usChecksum;
uint16_t usIdentifier;
uint16_t usSequenceNumber;
}
#include "pack_struct_end.h"
typedef struct xICMP_HEADER xICMPHeader_t;
#include "pack_struct_start.h"
struct xUDP_HEADER
{
uint16_t usSourcePort;
uint16_t usDestinationPort;
uint16_t usLength;
uint16_t usChecksum;
}
#include "pack_struct_end.h"
typedef struct xUDP_HEADER xUDPHeader_t;
#define ipSIZE_OF_UDP_HEADER 8
#include "pack_struct_start.h"
struct xPSEUDO_HEADER
{
uint32_t ulSourceAddress;
uint32_t ulDestinationAddress;
uint8_t ucZeros;
uint8_t ucProtocol;
uint16_t usUDPLength;
}
#include "pack_struct_end.h"
typedef struct xPSEUDO_HEADER xPseudoHeader_t;
/*-----------------------------------------------------------*/
/* Nested protocol packets. */
/*-----------------------------------------------------------*/
#include "pack_struct_start.h"
struct xARP_PACKET
{
xEthernetHeader_t xEthernetHeader;
xARPHeader_t xARPHeader;
}
#include "pack_struct_end.h"
typedef struct xARP_PACKET xARPPacket_t;
#include "pack_struct_start.h"
struct xIP_PACKET
{
xEthernetHeader_t xEthernetHeader;
xIPHeader_t xIPHeader;
}
#include "pack_struct_end.h"
typedef struct xIP_PACKET xIPPacket_t;
#include "pack_struct_start.h"
struct xICMP_PACKET
{
xEthernetHeader_t xEthernetHeader;
xIPHeader_t xIPHeader;
xICMPHeader_t xICMPHeader;
}
#include "pack_struct_end.h"
typedef struct xICMP_PACKET xICMPPacket_t;
#include "pack_struct_start.h"
struct xUDP_PACKET
{
xEthernetHeader_t xEthernetHeader;
xIPHeader_t xIPHeader;
xUDPHeader_t xUDPHeader;
}
#include "pack_struct_end.h"
typedef struct xUDP_PACKET xUDPPacket_t;
/* Dimensions the buffers that are filled by received Ethernet frames. */
#define ipETHERNET_CRC_BYTES ( 4UL )
#define ipETHERNET_OPTIONAL_802_1Q_TAG_BYTES ( 4UL )
#define ipTOTAL_ETHERNET_FRAME_SIZE ( ipconfigNETWORK_MTU + sizeof( xEthernetHeader_t ) + ipETHERNET_CRC_BYTES + ipETHERNET_OPTIONAL_802_1Q_TAG_BYTES )
/* The maximum UDP payload length. */
#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IP_HEADER ) - ipSIZE_OF_UDP_HEADER )
typedef enum
{
eReleaseBuffer = 0, /* Processing the frame did not find anything to do - just release the buffer. */
eProcessBuffer, /* An Ethernet frame has a valid address - continue process its contents. */
eReturnEthernetFrame, /* The Ethernet frame contains an ARP or ICMP packet that can be returned to its source. */
eFrameConsumed /* Processing the Ethernet packet contents resulted in the payload being sent to the stack. */
} eFrameProcessingResult_t;
typedef enum
{
eNetworkDownEvent = 0, /* The network interface has been lost and/or needs [re]connecting. */
eEthernetRxEvent, /* The network interface has queued a received Ethernet frame. */
eARPTimerEvent, /* The ARP timer expired. */
eStackTxEvent, /* The software stack has queued a packet to transmit. */
eDHCPEvent /* Process the DHCP state machine. */
} eIPEvent_t;
typedef struct IP_TASK_COMMANDS
{
eIPEvent_t eEventType;
void *pvData;
} xIPStackEvent_t;
#define ipBROADCAST_IP_ADDRESS 0xffffffffUL
/* Offset into the Ethernet frame that is used to temporarily store information
on the fragmentation status of the packet being sent. The value is important,
as it is past the location into which the destination address will get placed. */
#define ipFRAGMENTATION_PARAMETERS_OFFSET ( 6 )
#define ipSOCKET_OPTIONS_OFFSET ( 6 )
/* Only used when outgoing fragmentation is being used (FreeRTOSIPConfig.h
setting. */
#define ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT( usFragmentOffset ) ( ( ( usFragmentOffset ) == 0 ) ? ipUDP_PAYLOAD_OFFSET : ipIP_PAYLOAD_OFFSET )
/* The offset into a UDP packet at which the UDP data (payload) starts. */
#define ipUDP_PAYLOAD_OFFSET ( sizeof( xUDPPacket_t ) )
/* The offset into an IP packet into which the IP data (payload) starts. */
#define ipIP_PAYLOAD_OFFSET ( sizeof( xIPPacket_t ) )
/* Space left at the beginning of a network buffer storage area to store a
pointer back to the network buffer. Should be a multiple of 8 to ensure
8 byte alignment is maintained on architectures that require it. */
#define ipBUFFER_PADDING ( 8 )
#include "pack_struct_start.h"
struct xUDP_IP_FRACMENT_PARAMETERS
{
uint8_t ucSocketOptions;
uint8_t ucPadFor16BitAlignment;
uint16_t usFragmentedPacketOffset;
uint16_t usFragmentLength;
uint16_t usPayloadChecksum;
}
#include "pack_struct_end.h"
typedef struct xUDP_IP_FRACMENT_PARAMETERS xIPFragmentParameters_t;
#if( ipconfigBYTE_ORDER == FREERTOS_LITTLE_ENDIAN )
/* Ethernet frame types. */
#define ipARP_TYPE ( 0x0608U )
#define ipIP_TYPE ( 0x0008U )
/* ARP related definitions. */
#define ipARP_PROTOCOL_TYPE ( 0x0008U )
#define ipARP_HARDWARE_TYPE_ETHERNET ( 0x0100U )
#define ipARP_REQUEST ( 0x0100 )
#define ipARP_REPLY ( 0x0200 )
#else
/* Ethernet frame types. */
#define ipARP_TYPE ( 0x0806U )
#define ipIP_TYPE ( 0x0800U )
/* ARP related definitions. */
#define ipARP_PROTOCOL_TYPE ( 0x0800U )
#define ipARP_HARDWARE_TYPE_ETHERNET ( 0x0001U )
#define ipARP_REQUEST ( 0x0001 )
#define ipARP_REPLY ( 0x0002 )
#endif /* ipconfigBYTE_ORDER == FREERTOS_LITTLE_ENDIAN */
/* The structure used to store buffers and pass them around the network stack.
Buffers can be in use by the stack, in use by the network interface hardware
driver, or free (not in use). */
typedef struct xNETWORK_BUFFER
{
xListItem xBufferListItem; /* Used to reference the buffer form the free buffer list or a socket. */
uint32_t ulIPAddress; /* Source or destination IP address, depending on usage scenario. */
uint8_t *pucEthernetBuffer; /* Pointer to the start of the Ethernet frame. */
size_t xDataLength; /* Starts by holding the total Ethernet frame length, then the UDP payload length. */
uint16_t usPort; /* Source or destination port, depending on usage scenario. */
uint16_t usBoundPort; /* The port to which a transmitting socket is bound. */
} xNetworkBufferDescriptor_t;
void vNetworkBufferRelease( xNetworkBufferDescriptor_t * const pxNetworkBuffer );
/*
* A version of FreeRTOS_GetReleaseNetworkBuffer() that can be called from an
* interrupt. If a non zero value is returned, then the calling ISR should
* perform a context switch before exiting the ISR.
*/
portBASE_TYPE FreeRTOS_ReleaseFreeNetworkBufferFromISR( void );
/*
* Create a message that contains a command to initialise the network interface.
* This is used during initialisation, and at any time the network interface
* goes down thereafter. The network interface hardware driver is responsible
* for sending the message that contains the network interface down command/
* event.
*
* Only use the FreeRTOS_NetworkDownFromISR() version if the function is to be
* called from an interrupt service routine. If FreeRTOS_NetworkDownFromISR()
* returns a non-zero value then a context switch should be performed ebfore
* the interrupt is exited.
*/
void FreeRTOS_NetworkDown( void );
portBASE_TYPE FreeRTOS_NetworkDownFromISR( void );
/*
* Inspect an Ethernet frame to see if it contains data that the stack needs to
* process. eProcessBuffer is returned if the frame should be processed by the
* stack. eReleaseBuffer is returned if the frame should be discarded.
*/
eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucEthernetBuffer );
#if( ipconfigINCLUDE_TEST_CODE == 1 )
unsigned portBASE_TYPE uxGetNumberOfFreeNetworkBuffers( void );
#endif /* ipconfigINCLUDE_TEST_CODE */
/* Socket related private functions. */
portBASE_TYPE xProcessReceivedUDPPacket( xNetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort );
void FreeRTOS_SocketsInit( void );
/* If FreeRTOS+NABTO is included then include the prototype of the function that
creates the Nabto task. */
#if( ipconfigFREERTOS_PLUS_NABTO == 1 )
void vStartNabtoTask( void );
#endif
#endif /* FREERTOS_IP_PRIVATE_H */

View file

@ -0,0 +1,173 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
#ifndef FREERTOS_UDP_H
#define FREERTOS_UDP_H
/* Standard includes. */
#include <string.h>
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#ifndef INC_FREERTOS_H
#error FreeRTOS.h must be included before FreeRTOS_Sockets.h.
#endif
#ifndef TASK_H
#error The FreeRTOS header file task.h must be included before FreeRTOS_Sockets.h.
#endif
/* Assigned to an xSocket_t variable when the socket is not valid, probably
because it could not be created. */
#define FREERTOS_INVALID_SOCKET ( ( void * ) ~0U )
/* API function error values. As errno is supported, the FreeRTOS sockets
functions return error codes rather than just a pass or fail indication. */
#define FREERTOS_SOCKET_ERROR ( -1 )
#define FREERTOS_EWOULDBLOCK ( -2 )
#define FREERTOS_EINVAL ( -4 )
#define FREERTOS_EADDRNOTAVAIL ( -5 )
#define FREERTOS_EADDRINUSE ( -6 )
#define FREERTOS_ENOBUFS ( -7 )
#define FREERTOS_ENOPROTOOPT ( -8 )
/* Values for the parameters to FreeRTOS_socket(), inline with the Berkeley
standard. See the documentation of FreeRTOS_socket() for more information. */
#define FREERTOS_AF_INET ( 2 )
#define FREERTOS_SOCK_DGRAM ( 2 )
#define FREERTOS_IPPROTO_UDP ( 17 )
/* A bit value that can be passed into the FreeRTOS_sendto() function as part of
the flags parameter. Setting the FREERTOS_ZERO_COPY in the flags parameter
indicates that the zero copy interface is being used. See the documentation for
FreeRTOS_sockets() for more information. */
#define FREERTOS_ZERO_COPY ( 0x01UL )
/* Values that can be passed in the option name parameter of calls to
FreeRTOS_setsockopt(). */
#define FREERTOS_SO_RCVTIMEO ( 0 ) /* Used to set the receive time out. */
#define FREERTOS_SO_SNDTIMEO ( 1 ) /* Used to set the send time out. */
#define FREERTOS_SO_UDPCKSUM_OUT ( 0x02 ) /* Used to turn the use of the UDP checksum by a socket on or off. This also doubles as part of an 8-bit bitwise socket option. */
#define FREERTOS_NOT_LAST_IN_FRAGMENTED_PACKET ( 0x80 ) /* For internal use only, but also part of an 8-bit bitwise value. */
#define FREERTOS_FRAGMENTED_PACKET ( 0x40 ) /* For internal use only, but also part of an 8-bit bitwise value. */
/* For compatibility with the expected Berkeley sockets naming. */
#define socklen_t uint32_t
/* For this limited implementation, only two members are required in the
Berkeley style sockaddr structure. */
struct freertos_sockaddr
{
uint16_t sin_port;
uint32_t sin_addr;
};
#if ipconfigBYTE_ORDER == FREERTOS_LITTLE_ENDIAN
#define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \
( ( ( uint32_t ) ( ucOctet3 ) ) << 24UL ) | \
( ( ( uint32_t ) ( ucOctet2 ) ) << 16UL ) | \
( ( ( uint32_t ) ( ucOctet1 ) ) << 8UL ) | \
( ( uint32_t ) ( ucOctet0 ) )
#define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer ) \
sprintf( ( char * ) ( pucBuffer ), "%d.%d.%d.%d", \
( ( ulIPAddress ) & 0xffUL ), \
( ( ( ulIPAddress ) >> 8UL ) & 0xffUL ), \
( ( ( ulIPAddress ) >> 16UL ) & 0xffUL ), \
( ( ( ulIPAddress ) >> 24UL ) & 0xffUL ) )
#else /* ipconfigBYTE_ORDER */
#define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \
( ( ( uint32_t ) ( ucOctet0 ) ) << 24UL ) | \
( ( ( uint32_t ) ( ucOctet1 ) ) << 16UL ) | \
( ( ( uint32_t ) ( ucOctet2 ) ) << 8UL ) | \
( ( uint32_t ) ( ucOctet3 ) )
#define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer ) \
sprintf( ( char * ) ( pucBuffer ), "%d.%d.%d.%d", \
( ( ( ulIPAddress ) >> 24UL ) & 0xffUL ) ), \
( ( ( ulIPAddress ) >> 16UL ) & 0xffUL ), \
( ( ( ulIPAddress ) >> 8UL ) & 0xffUL ), \
( ( ulIPAddress ) & 0xffUL )
#endif /* ipconfigBYTE_ORDER */
/* The socket type itself. */
typedef void *xSocket_t;
/* The xSocketSet_t type is the equivalent to the fd_set type used by the
Berkeley API. */
typedef void *xSocketSet_t;
/**
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
* FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/FreeRTOS_UDP_API_Functions.shtml
*/
xSocket_t FreeRTOS_socket( portBASE_TYPE xDomain, portBASE_TYPE xType, portBASE_TYPE xProtocol );
int32_t FreeRTOS_recvfrom( xSocket_t xSocket, void *pvBuffer, size_t xBufferLength, uint32_t ulFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength );
int32_t FreeRTOS_sendto( xSocket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, uint32_t ulFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength );
portBASE_TYPE FreeRTOS_bind( xSocket_t xSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );
portBASE_TYPE FreeRTOS_setsockopt( xSocket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength );
portBASE_TYPE FreeRTOS_closesocket( xSocket_t xSocket );
uint32_t FreeRTOS_gethostbyname( const uint8_t *pcHostName );
uint32_t FreeRTOS_inet_addr( const uint8_t * pucIPAddress );
#if ipconfigSUPPORT_SELECT_FUNCTION == 1
xSocketSet_t FreeRTOS_CreateSocketSet( unsigned portBASE_TYPE uxEventQueueLength );
portBASE_TYPE FreeRTOS_FD_SET( xSocket_t xSocket, xSocketSet_t xSocketSet );
portBASE_TYPE FreeRTOS_FD_CLR( xSocket_t xSocket, xSocketSet_t xSocketSet );
xSocket_t FreeRTOS_select( xSocketSet_t xSocketSet, portTickType xBlockTimeTicks );
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
#endif /* FREERTOS_UDP_H */

View file

@ -0,0 +1,118 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
#ifndef FREERTOS_IP_H
#define FREERTOS_IP_H
/* Use in FreeRTOSIPConfig.h. */
#define FREERTOS_LITTLE_ENDIAN 0
#define FREERTOS_BIG_ENDIAN 1
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "FreeRTOSIPConfigDefaults.h"
#include "IPTraceMacroDefaults.h"
/* The number of octets in the MAC and IP addresses respectively. */
#define ipMAC_ADDRESS_LENGTH_BYTES ( 6 )
#define ipIP_ADDRESS_LENGTH_BYTES ( 4 )
#include "pack_struct_start.h"
struct xMAC_ADDRESS
{
uint8_t ucBytes[ ipMAC_ADDRESS_LENGTH_BYTES ];
}
#include "pack_struct_end.h"
typedef struct xMAC_ADDRESS xMACAddress_t;
typedef enum eNETWORK_EVENTS
{
eNetworkUp, /* The network is configured. */
eNetworkDown /* The network connection has been lost. */
} eIPCallbackEvent_t;
typedef enum ePING_REPLY_STATUS
{
eSuccess = 0, /* A correct reply has been received for an outgoing ping. */
eInvalidChecksum, /* A reply was received for an outgoing ping but the checksum of the reply was incorrect. */
eInvalidData /* A reply was received to an outgoing ping but the payload of the reply was not correct. */
} ePingReplyStatus_t;
/* Endian related definitions. */
#if( ipconfigBYTE_ORDER == FREERTOS_LITTLE_ENDIAN )
uint16_t FreeRTOS_htons( uint16_t usIn );
uint32_t FreeRTOS_htonl( uint32_t ulIn );
#else
#define FreeRTOS_htons( x ) ( x )
#define FreeRTOS_htonl( x ) ( x )
#endif /* ipconfigBYTE_ORDER == FREERTOS_LITTLE_ENDIAN */
#define FreeRTOS_ntohs( x ) FreeRTOS_htons( x )
#define FreeRTOS_ntohl( x ) FreeRTOS_htonl( x )
/**
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
* FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/FreeRTOS_UDP_API_Functions.shtml
*/
portBASE_TYPE FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );
void * FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, portTickType xBlockTimeTicks );
void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress );
portBASE_TYPE FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, portTickType xBlockTimeTicks );
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier );
void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer );
uint8_t * FreeRTOS_GetMACAddress( void );
#endif /* FREERTOS_IP_H */

View file

@ -0,0 +1,172 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/* This file provides default (empty) implementations for any IP trace macros
that are not defined by the user. See
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/UDP_IP_Trace.shtml */
#ifndef UDP_TRACE_MACRO_DEFAULTS_H
#define UDP_TRACE_MACRO_DEFAULTS_H
#ifndef iptraceNETWORK_DOWN
#define iptraceNETWORK_DOWN()
#endif
#ifndef iptraceNETWORK_BUFFER_RELEASED
#define iptraceNETWORK_BUFFER_RELEASED( pxBufferAddress )
#endif
#ifndef iptraceNETWORK_BUFFER_OBTAINED
#define iptraceNETWORK_BUFFER_OBTAINED( pxBufferAddress )
#endif
#ifndef iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR
#define iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxBufferAddress )
#endif
#ifndef iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER
#define iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER()
#endif
#ifndef iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR
#define iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR()
#endif
#ifndef iptraceCREATING_ARP_REQUEST
#define iptraceCREATING_ARP_REQUEST( ulIPAddress )
#endif
#ifndef iptraceARP_TABLE_ENTRY_WILL_EXPIRE
#define iptraceARP_TABLE_ENTRY_WILL_EXPIRE( ulIPAddress )
#endif
#ifndef iptraceARP_TABLE_ENTRY_EXPIRED
#define iptraceARP_TABLE_ENTRY_EXPIRED( ulIPAddress )
#endif
#ifndef iptraceARP_TABLE_ENTRY_CREATED
#define iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, ucMACAddress )
#endif
#ifndef iptraceSENDING_UDP_PACKET
#define iptraceSENDING_UDP_PACKET( ulIPAddress )
#endif
#ifndef iptracePACKET_DROPPED_TO_GENERATE_ARP
#define iptracePACKET_DROPPED_TO_GENERATE_ARP( ulIPAddress )
#endif
#ifndef iptraceICMP_PACKET_RECEIVED
#define iptraceICMP_PACKET_RECEIVED()
#endif
#ifndef iptraceSENDING_PING_REPLY
#define iptraceSENDING_PING_REPLY( ulIPAddress )
#endif
#ifndef traceARP_PACKET_RECEIVED
#define traceARP_PACKET_RECEIVED()
#endif
#ifndef iptracePROCESSING_RECEIVED_ARP_REPLY
#define iptracePROCESSING_RECEIVED_ARP_REPLY( ulIPAddress )
#endif
#ifndef iptraceSENDING_ARP_REPLY
#define iptraceSENDING_ARP_REPLY( ulIPAddress )
#endif
#ifndef iptraceFAILED_TO_CREATE_SOCKET
#define iptraceFAILED_TO_CREATE_SOCKET()
#endif
#ifndef iptraceRECVFROM_DISCARDING_BYTES
#define iptraceRECVFROM_DISCARDING_BYTES( xNumberOfBytesDiscarded )
#endif
#ifndef iptraceETHERNET_RX_EVENT_LOST
#define iptraceETHERNET_RX_EVENT_LOST()
#endif
#ifndef iptraceSTACK_TX_EVENT_LOST
#define iptraceSTACK_TX_EVENT_LOST( xEvent )
#endif
#ifndef iptraceNETWORK_EVENT_RECEIVED
#define iptraceNETWORK_EVENT_RECEIVED( eEvent )
#endif
#ifndef iptraceBIND_FAILED
#define iptraceBIND_FAILED( xSocket, usPort )
#endif
#ifndef iptraceDHCP_REQUESTS_FAILED_USING_DEFAULT_IP_ADDRESS
#define iptraceDHCP_REQUESTS_FAILED_USING_DEFAULT_IP_ADDRESS( ulIPAddress )
#endif
#ifndef iptraceSENDING_DHCP_DISCOVER
#define iptraceSENDING_DHCP_DISCOVER()
#endif
#ifndef iptraceSENDING_DHCP_REQUEST
#define iptraceSENDING_DHCP_REQUEST()
#endif
#ifndef iptraceNETWORK_INTERFACE_TRANSMIT
#define iptraceNETWORK_INTERFACE_TRANSMIT()
#endif
#ifndef iptraceNETWORK_INTERFACE_RECEIVE
#define iptraceNETWORK_INTERFACE_RECEIVE()
#endif
#ifndef iptraceSENDING_DNS_REQUEST
#define iptraceSENDING_DNS_REQUEST()
#endif
#ifndef iptraceWAITING_FOR_TX_DMA_DESCRIPTOR
#define iptraceWAITING_FOR_TX_DMA_DESCRIPTOR
#endif
#ifndef ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS
#define ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS 0
#endif
#ifndef iptraceFAILED_TO_NOTIFY_SELECT_GROUP
#define iptraceFAILED_TO_NOTIFY_SELECT_GROUP( xSocket )
#endif
#endif /* UDP_TRACE_MACRO_DEFAULTS_H */

View file

@ -0,0 +1,50 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
#ifndef NETWORK_BUFFER_MANAGEMENT_H
#define NETWORK_BUFFER_MANAGEMENT_H
/* NOTE PUBLIC API FUNCTIONS. */
portBASE_TYPE xNetworkBuffersInitialise( void );
xNetworkBufferDescriptor_t *pxNetworkBufferGet( size_t xRequestedSizeBytes, portTickType xBlockTimeTicks );
xNetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes );
void vNetworkBufferRelease( xNetworkBufferDescriptor_t * const pxNetworkBuffer );
portBASE_TYPE vNetworkBufferReleaseFromISR( xNetworkBufferDescriptor_t * const pxNetworkBuffer );
uint8_t *pucEthernetBufferGet( size_t *pxRequestedSizeBytes );
void vEthernetBufferRelease( uint8_t *pucEthernetBuffer );
#endif /* NETWORK_BUFFER_MANAGEMENT_H */

View file

@ -0,0 +1,47 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
#ifndef NETWORK_INTERFACE_H
#define NETWORK_INTERFACE_H
/* NOTE PUBLIC API FUNCTIONS. */
portBASE_TYPE xNetworkInterfaceInitialise( void );
portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer );
void vNetworkInterfaceAllocateRAMToBuffers( xNetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFERS ] );
#endif /* NETWORK_INTERFACE_H */

View file

@ -0,0 +1,242 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/******************************************************************************
*
* See the following web page for essential buffer allocation scheme usage and
* configuration details:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Buffer_Management.shtml
*
******************************************************************************/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "NetworkInterface.h"
/* For an Ethernet interrupt to be able to obtain a network buffer there must
be at least this number of buffers available. */
#define ipINTERRUPT_BUFFER_GET_THRESHOLD ( 3 )
/* A list of free (available) xNetworkBufferDescriptor_t structures. */
static xList xFreeBuffersList;
/* Declares the pool of xNetworkBufferDescriptor_t structures that are available to the
system. All the network buffers referenced from xFreeBuffersList exist in this
array. The array is not accessed directly except during initialisation, when
the xFreeBuffersList is filled (as all the buffers are free when the system is
booted). */
static xNetworkBufferDescriptor_t xNetworkBuffers[ ipconfigNUM_NETWORK_BUFFERS ];
/* The semaphore used to obtain network buffers. */
static xSemaphoreHandle xNetworkBufferSemaphore = NULL;
/*-----------------------------------------------------------*/
portBASE_TYPE xNetworkBuffersInitialise( void )
{
portBASE_TYPE xReturn, x;
/* Only initialise the buffers and their associated kernel objects if they
have not been initialised before. */
if( xNetworkBufferSemaphore == NULL )
{
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFERS, ipconfigNUM_NETWORK_BUFFERS );
configASSERT( xNetworkBufferSemaphore );
if( xNetworkBufferSemaphore != NULL )
{
vListInitialise( &xFreeBuffersList );
/* Initialise all the network buffers. The buffer storage comes
from the network interface, and different hardware has different
requirements. */
vNetworkInterfaceAllocateRAMToBuffers( xNetworkBuffers );
for( x = 0; x < ipconfigNUM_NETWORK_BUFFERS; x++ )
{
/* Initialise and set the owner of the buffer list items. */
vListInitialiseItem( &( xNetworkBuffers[ x ].xBufferListItem ) );
listSET_LIST_ITEM_OWNER( &( xNetworkBuffers[ x ].xBufferListItem ), &xNetworkBuffers[ x ] );
/* Currently, all buffers are available for use. */
vListInsert( &xFreeBuffersList, &( xNetworkBuffers[ x ].xBufferListItem ) );
}
}
}
if( xNetworkBufferSemaphore == NULL )
{
xReturn = pdFAIL;
}
else
{
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
xNetworkBufferDescriptor_t *pxNetworkBufferGet( size_t xRequestedSizeBytes, portTickType xBlockTimeTicks )
{
xNetworkBufferDescriptor_t *pxReturn = NULL;
/*_RB_ The current implementation only has a single size memory block, so
the requested size parameter is not used (yet). */
( void ) xRequestedSizeBytes;
/* If there is a semaphore available, there is a network buffer available. */
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
{
/* Protect the structure as it is accessed from tasks and interrupts. */
taskENTER_CRITICAL();
{
pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
uxListRemove( &( pxReturn->xBufferListItem ) );
}
taskEXIT_CRITICAL();
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
}
else
{
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
}
return pxReturn;
}
/*-----------------------------------------------------------*/
xNetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes )
{
xNetworkBufferDescriptor_t *pxReturn = NULL;
unsigned portBASE_TYPE uxSavedInterruptStatus;
/*_RB_ The current implementation only has a single size memory block, so
the requested size parameter is not used (yet). */
( void ) xRequestedSizeBytes;
/* If there is a semaphore available then there is a buffer available, but,
as this is called from an interrupt, only take a buffer if there are at
least ipINTERRUPT_BUFFER_GET_THRESHOLD buffers remaining. This prevents,
to a certain degree at least, a rapidly executing interrupt exhausting
buffer and in so doing preventing tasks from continuing. */
if( uxQueueMessagesWaitingFromISR( ( xQueueHandle ) xNetworkBufferSemaphore ) > ipINTERRUPT_BUFFER_GET_THRESHOLD )
{
if( xSemaphoreTakeFromISR( xNetworkBufferSemaphore, NULL ) == pdPASS )
{
/* Protect the structure as it is accessed from tasks and interrupts. */
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
uxListRemove( &( pxReturn->xBufferListItem ) );
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxReturn );
}
}
if( pxReturn == NULL )
{
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR();
}
return pxReturn;
}
/*-----------------------------------------------------------*/
portBASE_TYPE vNetworkBufferReleaseFromISR( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
unsigned portBASE_TYPE uxSavedInterruptStatus;
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. */
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
return xHigherPriorityTaskWoken;
}
/*-----------------------------------------------------------*/
void vNetworkBufferRelease( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
portBASE_TYPE xListItemAlreadyInFreeList;
/* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. */
taskENTER_CRITICAL();
{
xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
if( xListItemAlreadyInFreeList == pdFALSE )
{
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
}
configASSERT( xListItemAlreadyInFreeList == pdFALSE );
}
taskEXIT_CRITICAL();
xSemaphoreGive( xNetworkBufferSemaphore );
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
/*-----------------------------------------------------------*/
#if( ipconfigINCLUDE_TEST_CODE == 1 )
unsigned portBASE_TYPE uxGetNumberOfFreeNetworkBuffers( void )
{
return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
}
#endif /* ipconfigINCLUDE_TEST_CODE */

View file

@ -0,0 +1,280 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/******************************************************************************
*
* See the following web page for essential buffer allocation scheme usage and
* configuration details:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Buffer_Management.shtml
*
******************************************************************************/
/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR
THAT WILL FRAGMENT THE HEAP MEMORY. For example, heap_2 must not be used,
heap_4 can be used. */
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkInterface.h"
/* For an Ethernet interrupt to be able to obtain a network buffer there must
be at least this number of buffers available. */
#define ipINTERRUPT_BUFFER_GET_THRESHOLD ( 3 )
/* A list of free (available) xNetworkBufferDescriptor_t structures. */
static xList xFreeBuffersList;
/* Declares the pool of xNetworkBufferDescriptor_t structures that are available to the
system. All the network buffers referenced from xFreeBuffersList exist in this
array. The array is not accessed directly except during initialisation, when
the xFreeBuffersList is filled (as all the buffers are free when the system is
booted). */
static xNetworkBufferDescriptor_t xNetworkBuffers[ ipconfigNUM_NETWORK_BUFFERS ];
/* The semaphore used to obtain network buffers. */
static xSemaphoreHandle xNetworkBufferSemaphore = NULL;
/*-----------------------------------------------------------*/
portBASE_TYPE xNetworkBuffersInitialise( void )
{
portBASE_TYPE xReturn, x;
/* Only initialise the buffers and their associated kernel objects if they
have not been initialised before. */
if( xNetworkBufferSemaphore == NULL )
{
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFERS, ipconfigNUM_NETWORK_BUFFERS );
configASSERT( xNetworkBufferSemaphore );
vQueueAddToRegistry( xNetworkBufferSemaphore, ( signed char * ) "NetBufSem" );
/* If the trace recorder code is included name the semaphore for viewing
in FreeRTOS+Trace. */
#if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1
{
extern xQueueHandle xNetworkEventQueue;
vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );
vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" );
}
#endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */
if( xNetworkBufferSemaphore != NULL )
{
vListInitialise( &xFreeBuffersList );
/* Initialise all the network buffers. No storage is allocated to
the buffers yet. */
for( x = 0; x < ipconfigNUM_NETWORK_BUFFERS; x++ )
{
/* Initialise and set the owner of the buffer list items. */
xNetworkBuffers[ x ].pucEthernetBuffer = NULL;
vListInitialiseItem( &( xNetworkBuffers[ x ].xBufferListItem ) );
listSET_LIST_ITEM_OWNER( &( xNetworkBuffers[ x ].xBufferListItem ), &xNetworkBuffers[ x ] );
/* Currently, all buffers are available for use. */
vListInsert( &xFreeBuffersList, &( xNetworkBuffers[ x ].xBufferListItem ) );
}
}
}
if( xNetworkBufferSemaphore == NULL )
{
xReturn = pdFAIL;
}
else
{
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
uint8_t *pucEthernetBufferGet( size_t *pxRequestedSizeBytes )
{
uint8_t *pucEthernetBuffer;
if( *pxRequestedSizeBytes < sizeof( xARPPacket_t ) )
{
/* Buffers must be at least large enough to hold ARP packets, otherwise
nothing can be done. */
*pxRequestedSizeBytes = sizeof( xARPPacket_t );
}
/* Allocate a buffer large enough to store the requested Ethernet frame size
and a pointer to a network buffer structure (hence the addition of
ipBUFFER_PADDING bytes). */
pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( *pxRequestedSizeBytes + ipBUFFER_PADDING );
/* Enough space is left at the start of the buffer to place a pointer to
the network buffer structure that references this Ethernet buffer. Return
a pointer to the start of the Ethernet buffer itself. */
pucEthernetBuffer += ipBUFFER_PADDING;
return pucEthernetBuffer;
}
/*-----------------------------------------------------------*/
void vEthernetBufferRelease( uint8_t *pucEthernetBuffer )
{
/* There is space before the Ethernet buffer in which a pointer to the
network buffer that references this Ethernet buffer is stored. Remove the
space before freeing the buffer. */
if( pucEthernetBuffer != NULL )
{
pucEthernetBuffer -= ipBUFFER_PADDING;
vPortFree( ( void * ) pucEthernetBuffer );
}
}
/*-----------------------------------------------------------*/
xNetworkBufferDescriptor_t *pxNetworkBufferGet( size_t xRequestedSizeBytes, portTickType xBlockTimeTicks )
{
xNetworkBufferDescriptor_t *pxReturn = NULL;
if( ( xRequestedSizeBytes != 0 ) && ( xRequestedSizeBytes < sizeof( xARPPacket_t ) ) )
{
/* ARP packets can replace application packets, so the storage must be
at least large enough to hold an ARP. */
xRequestedSizeBytes = sizeof( xARPPacket_t );
}
/* If there is a semaphore available, there is a network buffer available. */
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
{
/* Protect the structure as it is accessed from tasks and interrupts. */
taskENTER_CRITICAL();
{
pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
uxListRemove( &( pxReturn->xBufferListItem ) );
}
taskEXIT_CRITICAL();
/* Allocate storage of exactly the requested size to the buffer. */
configASSERT( pxReturn->pucEthernetBuffer == NULL );
if( xRequestedSizeBytes > 0 )
{
/* Extra space is obtained so a pointer to the network buffer can
be stored at the beginning of the buffer. */
pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );
if( pxReturn->pucEthernetBuffer == NULL )
{
/* The attempt to allocate storage for the buffer payload failed,
so the network buffer structure cannot be used and must be
released. */
vNetworkBufferRelease( pxReturn );
pxReturn = NULL;
}
else
{
/* Store a pointer to the network buffer structure in the
buffer storage area, then move the buffer pointer on past the
stored pointer so the pointer value is not overwritten by the
application when the buffer is used. */
*( ( xNetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;
pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
/* Store the actual size of the allocated buffer, which may be
greater than the requested size. */
pxReturn->xDataLength = xRequestedSizeBytes;
}
}
else
{
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
}
}
if( pxReturn == NULL )
{
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
}
return pxReturn;
}
/*-----------------------------------------------------------*/
void vNetworkBufferRelease( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
portBASE_TYPE xListItemAlreadyInFreeList;
/* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. Release the
storage allocated to the buffer payload. THIS FILE SHOULD NOT BE USED
IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP
MEMORY. For example, heap_2 must not be used, heap_4 can be used. */
vEthernetBufferRelease( pxNetworkBuffer->pucEthernetBuffer );
pxNetworkBuffer->pucEthernetBuffer = NULL;
taskENTER_CRITICAL();
{
xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
if( xListItemAlreadyInFreeList == pdFALSE )
{
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
}
configASSERT( xListItemAlreadyInFreeList == pdFALSE );
}
taskEXIT_CRITICAL();
xSemaphoreGive( xNetworkBufferSemaphore );
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
/*-----------------------------------------------------------*/
#if( ipconfigINCLUDE_TEST_CODE == 1 )
unsigned portBASE_TYPE uxGetNumberOfFreeNetworkBuffers( void )
{
return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
}
#endif /* ipconfigINCLUDE_TEST_CODE */

View file

@ -0,0 +1,58 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/*****************************************************************************
*
* See the following URL for an exaplanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
*
*****************************************************************************/
__attribute__( (packed) );

View file

@ -0,0 +1,60 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/*****************************************************************************
*
* See the following URL for an exaplanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
*
*****************************************************************************/
/* Nothing to do here. */

View file

@ -0,0 +1,60 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/*****************************************************************************
*
* See the following URL for an exaplanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
*
*****************************************************************************/
;
#pragma pack( pop )

View file

@ -0,0 +1,59 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/*****************************************************************************
*
* See the following URL for an exaplanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
*
*****************************************************************************/
#pragma pack( push, 1 )

View file

@ -0,0 +1,66 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/*****************************************************************************
*
* See the following URL for an exaplanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
*
*****************************************************************************/
#ifdef _SH
#ifdef __RENESAS__
;
#pragma unpack
#endif
#endif

View file

@ -0,0 +1,65 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/*****************************************************************************
*
* See the following URL for an exaplanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
*
*****************************************************************************/
#ifdef _SH
#ifdef __RENESAS__
#pragma pack 1
#endif
#endif

View file

@ -0,0 +1,277 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* Hardware abstraction. */
#include "FreeRTOS_IO.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h"
/* Driver includes. */
#include "lpc17xx_emac.h"
#include "lpc17xx_pinsel.h"
/* Demo includes. */
#include "NetworkInterface.h"
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
/* When a packet is ready to be sent, if it cannot be sent immediately then the
task performing the transmit will block for niTX_BUFFER_FREE_WAIT
milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
up. */
#define niTX_BUFFER_FREE_WAIT ( ( portTickType ) 2UL / portTICK_RATE_MS )
#define niMAX_TX_ATTEMPTS ( 5 )
/* The length of the queue used to send interrupt status words from the
interrupt handler to the deferred handler task. */
#define niINTERRUPT_QUEUE_LENGTH ( 10 )
/*-----------------------------------------------------------*/
/*
* A deferred interrupt handler task that processes
*/
static void prvEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* The queue used to communicate Ethernet events with the IP task. */
extern xQueueHandle xNetworkEventQueue;
/* The semaphore used to wake the deferred interrupt handler task when an Rx
interrupt is received. */
static xSemaphoreHandle xEMACRxEventSemaphore = NULL;
/*-----------------------------------------------------------*/
portBASE_TYPE xNetworkInterfaceInitialise( void )
{
EMAC_CFG_Type Emac_Config;
PINSEL_CFG_Type xPinConfig;
portBASE_TYPE xStatus, xReturn;
extern uint8_t ucMACAddress[ 6 ];
/* Enable Ethernet Pins */
boardCONFIGURE_ENET_PINS( xPinConfig );
Emac_Config.Mode = EMAC_MODE_AUTO;
Emac_Config.pbEMAC_Addr = ucMACAddress;
xStatus = EMAC_Init( &Emac_Config );
LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE );
if( xStatus != ERROR )
{
vSemaphoreCreateBinary( xEMACRxEventSemaphore );
configASSERT( xEMACRxEventSemaphore );
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, ( const signed char * const ) "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
/* Enable the interrupt and set its priority to the minimum
interrupt priority. */
NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( ENET_IRQn );
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
configASSERT( xStatus != ERROR );
return xReturn;
}
/*-----------------------------------------------------------*/
portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
portBASE_TYPE xReturn = pdFAIL;
int32_t x;
extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );
/* Attempt to obtain access to a Tx buffer. */
for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
{
if( EMAC_CheckTransmitIndex() == TRUE )
{
/* Will the data fit in the Tx buffer? */
if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */
{
/* Assign the buffer to the Tx descriptor that is now known to
be free. */
EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer );
/* The EMAC now owns the buffer. */
pxNetworkBuffer->pucBuffer = NULL;
/* Initiate the Tx. */
EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
iptraceNETWORK_INTERFACE_TRANSMIT();
/* The Tx has been initiated. */
xReturn = pdPASS;
}
break;
}
else
{
vTaskDelay( niTX_BUFFER_FREE_WAIT );
}
}
/* Finished with the network buffer. */
vNetworkBufferRelease( pxNetworkBuffer );
return xReturn;
}
/*-----------------------------------------------------------*/
void ENET_IRQHandler( void )
{
uint32_t ulInterruptCause;
while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )
{
/* Clear the interrupt. */
LPC_EMAC->IntClear = ulInterruptCause;
/* Clear fatal error conditions. NOTE: The driver does not clear all
errors, only those actually experienced. For future reference, range
errors are not actually errors so can be ignored. */
if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )
{
LPC_EMAC->Command |= EMAC_CR_TX_RES;
}
/* Unblock the deferred interrupt handler task if the event was an
Rx. */
if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )
{
xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );
}
}
/* Shortcut calling portEND_SWITCHING_ISR(). */
vPortYieldFromISR();
}
/*-----------------------------------------------------------*/
static void prvEMACHandlerTask( void *pvParameters )
{
size_t xDataLength;
const uint16_t usCRCLength = 4;
xNetworkBufferDescriptor_t *pxNetworkBuffer;
xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
/* This is not included in the header file for some reason. */
extern uint8_t *EMAC_NextPacketToRead( void );
( void ) pvParameters;
configASSERT( xEMACRxEventSemaphore );
for( ;; )
{
/* Wait for the EMAC interrupt to indicate that another packet has been
received. The while() loop is only needed if INCLUDE_vTaskSuspend is
set to 0 in FreeRTOSConfig.h. */
while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );
/* At least one packet has been received. */
while( EMAC_CheckReceiveIndex() != FALSE )
{
/* Obtain the length, minus the CRC. The CRC is four bytes
but the length is already minus 1. */
xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );
if( xDataLength > 0U )
{
/* Obtain a network buffer to pass this data into the
stack. No storage is required as the network buffer
will point directly to the buffer that already holds
the received data. */
pxNetworkBuffer = pxNetworkBufferGet( 0, ( portTickType ) 0 );
if( pxNetworkBuffer != NULL )
{
pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead();
pxNetworkBuffer->xDataLength = xDataLength;
xRxEvent.pvData = ( void * ) pxNetworkBuffer;
/* Data was received and stored. Send a message to the IP
task to let it know. */
if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( portTickType ) 0 ) == pdFALSE )
{
vNetworkBufferRelease( pxNetworkBuffer );
iptraceETHERNET_RX_EVENT_LOST();
}
}
else
{
iptraceETHERNET_RX_EVENT_LOST();
}
iptraceNETWORK_INTERFACE_RECEIVE();
}
/* Release the frame. */
EMAC_UpdateRxConsumeIndex();
}
}
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,308 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h"
/* Driver includes. */
#include "lpc18xx_emac.h"
/* Demo includes. */
#include "NetworkInterface.h"
#if configMAC_INTERRUPT_PRIORITY > configMAC_INTERRUPT_PRIORITY
#error configMAC_INTERRUPT_PRIORITY must be greater than or equal to configMAC_INTERRUPT_PRIORITY (higher numbers mean lower logical priority)
#endif
#ifndef configNUM_RX_ETHERNET_DMA_DESCRIPTORS
#error configNUM_RX_ETHERNET_DMA_DESCRIPTORS must be defined in FreeRTOSConfig.h to set the number of RX DMA descriptors
#endif
#ifndef configNUM_TX_ETHERNET_DMA_DESCRIPTORS
#error configNUM_TX_ETHERNET_DMA_DESCRIPTORS must be defined in FreeRTOSConfig.h to set the number of TX DMA descriptors
#endif
/* If a packet cannot be sent immediately then the task performing the send
operation will be held in the Blocked state (so other tasks can execute) for
niTX_BUFFER_FREE_WAIT ticks. It will do this a maximum of niMAX_TX_ATTEMPTS
before giving up. */
#define niTX_BUFFER_FREE_WAIT ( ( portTickType ) 2UL / portTICK_RATE_MS )
#define niMAX_TX_ATTEMPTS ( 5 )
/*-----------------------------------------------------------*/
/*
* A deferred interrupt handler task that processes received frames.
*/
static void prvEMACDeferredInterruptHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* The queue used to communicate Ethernet events to the IP task. */
extern xQueueHandle xNetworkEventQueue;
/* The semaphore used to wake the deferred interrupt handler task when an Rx
interrupt is received. */
static xSemaphoreHandle xEMACRxEventSemaphore = NULL;
/*-----------------------------------------------------------*/
portBASE_TYPE xNetworkInterfaceInitialise( void )
{
EMAC_CFG_Type Emac_Config;
portBASE_TYPE xReturn;
extern uint8_t ucMACAddress[ 6 ];
Emac_Config.pbEMAC_Addr = ucMACAddress;
xReturn = EMAC_Init( &Emac_Config );
if( xReturn == pdPASS )
{
LPC_ETHERNET->DMA_INT_EN = DMA_INT_NOR_SUM | DMA_INT_RECEIVE;
/* Create the event semaphore if it has not already been created. */
if( xEMACRxEventSemaphore == NULL )
{
vSemaphoreCreateBinary( xEMACRxEventSemaphore );
#if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1
{
/* If the trace recorder code is included name the semaphore for
viewing in FreeRTOS+Trace. */
vTraceSetQueueName( xEMACRxEventSemaphore, "MAC_RX" );
}
#endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */
}
configASSERT( xEMACRxEventSemaphore );
/* The Rx deferred interrupt handler task is created at the highest
possible priority to ensure the interrupt handler can return directly to
it no matter which task was running when the interrupt occurred. */
xTaskCreate( prvEMACDeferredInterruptHandlerTask, /* The function that implements the task. */
( const signed char * const ) "MACTsk",
configMINIMAL_STACK_SIZE, /* Stack allocated to the task (defined in words, not bytes). */
NULL, /* The task parameter is not used. */
configMAX_PRIORITIES - 1, /* The priority assigned to the task. */
NULL ); /* The handle is not required, so NULL is passed. */
/* Enable the interrupt and set its priority as configured. THIS
DRIVER REQUIRES configMAC_INTERRUPT_PRIORITY TO BE DEFINED, PREFERABLY
IN FreeRTOSConfig.h. */
NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( ETHERNET_IRQn );
}
return xReturn;
}
/*-----------------------------------------------------------*/
portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
portBASE_TYPE xReturn = pdFAIL;
int32_t x;
/* Attempt to obtain access to a Tx descriptor. */
for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
{
if( EMAC_CheckTransmitIndex() == TRUE )
{
/* Assign the buffer being transmitted to the Tx descriptor. */
EMAC_SetNextPacketToSend( pxNetworkBuffer->pucEthernetBuffer );
/* The EMAC now owns the buffer and will free it when it has been
transmitted. Set pucBuffer to NULL to ensure the buffer is not
freed when the network buffer structure is returned to the pool
of network buffers. */
pxNetworkBuffer->pucEthernetBuffer = NULL;
/* Initiate the Tx. */
EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
iptraceNETWORK_INTERFACE_TRANSMIT();
/* The Tx has been initiated. */
xReturn = pdPASS;
break;
}
else
{
iptraceWAITING_FOR_TX_DMA_DESCRIPTOR();
vTaskDelay( niTX_BUFFER_FREE_WAIT );
}
}
/* Finished with the network buffer. */
vNetworkBufferRelease( pxNetworkBuffer );
return xReturn;
}
/*-----------------------------------------------------------*/
void ETH_IRQHandler( void )
{
uint32_t ulInterruptCause;
ulInterruptCause = LPC_ETHERNET->DMA_STAT ;
/* Clear the interrupt. */
LPC_ETHERNET->DMA_STAT |= ( DMA_INT_NOR_SUM | DMA_INT_RECEIVE );
/* Clear fatal error conditions. NOTE: The driver does not clear all
errors, only those actually experienced. For future reference, range
errors are not actually errors so can be ignored. */
if( ( ulInterruptCause & ( 1 << 13 ) ) != 0U )
{
LPC_ETHERNET->DMA_STAT |= ( 1 << 13 );
}
/* Unblock the deferred interrupt handler task if the event was an Rx. */
if( ( ulInterruptCause & DMA_INT_RECEIVE ) != 0UL )
{
xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );
}
/* Shortcut to calling portEND_SWITCHING_ISR(). Only do this if you
understand what you are doing! Otherwise use portEND_SWITCHING_ISR()
directly. */
vPortYieldFromISR();
}
/*-----------------------------------------------------------*/
static void prvEMACDeferredInterruptHandlerTask( void *pvParameters )
{
xNetworkBufferDescriptor_t *pxNetworkBuffer;
xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
( void ) pvParameters;
configASSERT( xEMACRxEventSemaphore );
for( ;; )
{
/* Wait for the EMAC interrupt to indicate that another packet has been
received. The while() loop is only needed if INCLUDE_vTaskSuspend is
set to 0 in FreeRTOSConfig.h. If INCLUDE_vTaskSuspend is set to 1
then portMAX_DELAY would be an indefinite block time and
xSemaphoreTake() would only return when the semaphore was actually
obtained. */
while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );
/* At least one packet has been received. */
while( EMAC_CheckReceiveIndex() != FALSE )
{
/* The buffer filled by the DMA is going to be passed into the IP
stack. Allocate another buffer for the DMA descriptor. */
pxNetworkBuffer = pxNetworkBufferGet( ipTOTAL_ETHERNET_FRAME_SIZE, ( portTickType ) 0 );
if( pxNetworkBuffer != NULL )
{
/* Swap the buffer just allocated and referenced from the
pxNetworkBuffer with the buffer that has already been filled by
the DMA. pxNetworkBuffer will then hold a reference to the
buffer that already contains the data without any data having
been copied between buffers. */
EMAC_NextPacketToRead( pxNetworkBuffer );
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 1
{
if( pxNetworkBuffer->xDataLength > 0 )
{
/* If the frame would not be processed by the IP stack then
don't even bother sending it to the IP stack. */
if( eConsiderFrameForProcessing( pxNetworkBuffer->pucEthernetBuffer ) != eProcessBuffer )
{
pxNetworkBuffer->xDataLength = 0;
}
}
}
#endif
if( pxNetworkBuffer->xDataLength > 0 )
{
/* Store a pointer to the network buffer structure in the
padding space that was left in front of the Ethernet frame.
The pointer is needed to ensure the network buffer structure
can be located when it is time for it to be freed if the
Ethernet frame gets used as a zero copy buffer. */
*( ( xNetworkBufferDescriptor_t ** ) ( ( pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING ) ) ) = pxNetworkBuffer;
/* Data was received and stored. Send it to the IP task
for processing. */
xRxEvent.pvData = ( void * ) pxNetworkBuffer;
if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( portTickType ) 0 ) == pdFALSE )
{
/* The buffer could not be sent to the IP task so the
buffer must be released. */
vNetworkBufferRelease( pxNetworkBuffer );
iptraceETHERNET_RX_EVENT_LOST();
}
else
{
iptraceNETWORK_INTERFACE_RECEIVE();
}
}
else
{
/* The buffer does not contain any data so there is no
point sending it to the IP task. Just release it. */
vNetworkBufferRelease( pxNetworkBuffer );
iptraceETHERNET_RX_EVENT_LOST();
}
}
else
{
iptraceETHERNET_RX_EVENT_LOST();
}
/* Release the descriptor. */
EMAC_UpdateRxConsumeIndex();
}
}
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,610 @@
/**********************************************************************
* Copyright(C) 2011, NXP Semiconductor
* All rights reserved.
* Heavily modified by Real Time Engineers ltd.
***********************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
**********************************************************************/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
/* Library includes. */
#include "lpc18xx_emac.h"
#include "lpc18xx_rgu.h"
#include "lpc18xx_scu.h"
#include "lpc18xx_gpio.h"
#define emacTIMEOUT_DELAY ( 2 )
#define emacNEGOTIATE_DELAY ( 10 / portTICK_RATE_MS )
#define emacEXPECTED_RX_STATUS_MASK ( RX_FIRST_SEGM | RX_LAST_SEGM )
/* Rx descriptors and data array. */
static volatile RX_Desc Rx_Desc[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];
static unsigned int RxDescIndex = 0;
/** Rx Status data array - Must be 8-Byte aligned */
#if defined ( __CC_ARM )
static __align(8) RX_Stat Rx_Stat[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];
#elif defined ( __ICCARM__ )
#pragma data_alignment=8
static RX_Stat Rx_Stat[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];
#elif defined ( __GNUC__ )
static volatile __attribute__ ((aligned (8))) RX_Stat Rx_Stat[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];
#endif
/* Tx descriptors and status array. */
static volatile TX_Desc Tx_Desc[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS ];
static volatile TX_Stat Tx_Stat[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS ];
static unsigned int TxDescIndex = 0;
/* Private Functions ---------------------------------------------------------- */
static void rx_descr_init( void );
static void tx_descr_init( void );
static int32_t write_PHY( uint32_t PhyReg, uint16_t Value );
static int32_t read_PHY( uint32_t PhyReg );
static void setEmacAddr( uint8_t abStationAddr[] );
/*********************************************************************//**
* @brief Initializes the EMAC peripheral according to the specified
* parameters in the EMAC_ConfigStruct.
* @param[in] EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure
* that contains the configuration information for the
* specified EMAC peripheral.
* @return None
*
* Note: This function will initialize EMAC module according to procedure below:
* - Remove the soft reset condition from the MAC
* - Configure the PHY via the MIIM interface of the MAC
* - Select RMII mode
* - Configure the transmit and receive DMA engines, including the descriptor arrays
* - Configure the host registers (MAC1,MAC2 etc.) in the MAC
* - Enable the receive and transmit data paths
* In default state after initializing, only Rx Done and Tx Done interrupt are enabled,
* all remain interrupts are disabled
* (Ref. from LPC17xx UM)
**********************************************************************/
portBASE_TYPE EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
{
int32_t id1, id2, regv, phy = 0;
int32_t phy_linkstatus_reg, phy_linkstatus_mask;
uint32_t x;
const uint32_t ulMaxAttempts = 250UL;
portBASE_TYPE xReturn = pdPASS;
/* Enable Ethernet Pins (NGX LPC1830 Xplorer. */
scu_pinmux(0x2 ,0 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC7);
scu_pinmux(0x1 ,17 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
scu_pinmux(0x1 ,18 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
scu_pinmux(0x1 ,20 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
scu_pinmux(0x1 ,19 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC0);
scu_pinmux(0x0 ,1 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC6);
scu_pinmux(0x1 ,15 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
scu_pinmux(0x0 ,0 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC2);
scu_pinmux(0x1 ,16 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
scu_pinmux(0xC ,9 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
scu_pinmux(0x1 ,16 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC7);
/* Ethernet RESET Pins */
scu_pinmux(0x1 ,0 , MD_PUP, FUNC0);
GPIO_SetDir(0,(1<<4), 1);
GPIO_SetValue(0,(1<<4));
#if MII /* Select MII interface */ // check MUXING for new Eagle...
scu_pinmux(0xC ,6 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); // ENET_RXD2: PC_6 -> FUNC3
scu_pinmux(0xC ,7 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); // ENET_RXD3: PC_7 -> FUNC3
scu_pinmux(0xC ,0 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); // ENET_RXLK: PC_0 -> FUNC3
scu_pinmux(0xC ,2 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); // ENET_TXD2: PC_2 -> FUNC3
scu_pinmux(0xC ,3 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); // ENET_TXD3: PC_3 -> FUNC3
scu_pinmux(0xC ,5 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); // ENET_TX_ER: PC_5 -> FUNC3
scu_pinmux(0x0 ,1 , (MD_PLN | MD_EZI | MD_ZI), FUNC2); // ENET_COL: P0_1 -> FUNC2
#else /* Select RMII interface */
LPC_CREG->CREG6 |= RMII_SELECT;
#endif
RGU_SoftReset( RGU_SIG_ETHERNET );
/* Wait for reset. */
while( !( LPC_RGU->RESET_ACTIVE_STATUS0 & ( 1 << ETHERNET_RST ) ) )
{
vTaskDelay( emacTIMEOUT_DELAY );
}
/* Reset all GMAC Subsystem internal registers and logic. */
LPC_ETHERNET->DMA_BUS_MODE |= DMA_SOFT_RESET;
/* Wait for software reset completion. */
while( LPC_ETHERNET->DMA_BUS_MODE & DMA_SOFT_RESET )
{
vTaskDelay( emacTIMEOUT_DELAY );
}
/* Put the PHY in reset mode */
write_PHY( PHY_REG_BMCR, PHY_BMCR_RESET );
/* Wait for hardware reset to end. */
for( x = 0; x < ulMaxAttempts; x++ )
{
regv = read_PHY (PHY_REG_BMCR);
if( !( regv & PHY_BMCR_RESET ) )
{
/* Reset complete */
break;
}
else
{
vTaskDelay( emacTIMEOUT_DELAY );
}
}
if( x == ulMaxAttempts )
{
xReturn = pdFAIL;
}
/* Check if this is a DP83848C PHY. */
id1 = read_PHY( PHY_REG_IDR1 );
id2 = read_PHY( PHY_REG_IDR2 );
if( ( ( id1 << 16 ) | ( id2 & 0xFFF0 ) ) == DP83848C_ID )
{
phy = DP83848C_ID;
}
else if( ( ( id1 << 16 ) | id2 ) == LAN8720_ID )
{
phy = LAN8720_ID;
}
if( phy != 0 )
{
/* Use autonegotiation about the link speed. */
write_PHY( PHY_REG_BMCR, PHY_AUTO_NEG );
/* Wait to complete Auto_Negotiation. */
for( x = 0; x < ulMaxAttempts; x++ )
{
regv = read_PHY( PHY_REG_BMSR );
if( ( regv & PHY_AUTO_NEG_DONE ) != 0 )
{
/* Auto negotiation Complete. */
break;
}
else
{
vTaskDelay( emacNEGOTIATE_DELAY );
}
}
if( x == ulMaxAttempts )
{
xReturn = pdFAIL;
}
}
else
{
xReturn = pdFAIL;
}
if( xReturn == pdPASS )
{
/* Default to DP83848C. */
phy_linkstatus_reg = PHY_REG_STS;
phy_linkstatus_mask = 0x0001;
if( phy == LAN8720_ID )
{
phy_linkstatus_reg = PHY_REG_BMSR;
phy_linkstatus_mask = 0x0004;
}
/* Check the link status. */
for( x = 0; x < ulMaxAttempts; x++ )
{
regv = read_PHY( phy_linkstatus_reg );
if( ( regv & phy_linkstatus_mask ) != 0 )
{
/* Link is on. */
break;
}
else
{
vTaskDelay( emacNEGOTIATE_DELAY );
}
}
if( x == ulMaxAttempts )
{
xReturn = pdFAIL;
}
regv = read_PHY( PHY_REG_SPCON );
regv &= PHY_REG_HCDSPEED_MASK;
/* Configure 100MBit/10MBit mode and Full/Half Duplex mode. */
switch( regv )
{
case PHY_REG_HCDSPEED_10MB_FULLD:
LPC_ETHERNET->MAC_CONFIG |= MAC_DUPMODE;
break;
case PHY_REG_HCDSPEED_100MB_HALFD:
LPC_ETHERNET->MAC_CONFIG |= MAC_100MPS;
break;
case PHY_REG_HCDSPEED_100MB_FULLD:
LPC_ETHERNET->MAC_CONFIG |= MAC_DUPMODE;
LPC_ETHERNET->MAC_CONFIG |= MAC_100MPS;
break;
default:
break;
}
/* Set the Ethernet MAC Address registers */
setEmacAddr( EMAC_ConfigStruct->pbEMAC_Addr );
/* Initialize Descriptor Lists */
rx_descr_init();
tx_descr_init();
/* Configure Filter
LPC_ETHERNET->MAC_FRAME_FILTER is left at its default value.
MAC_PROMISCUOUS and MAC_RECEIVEALL can be set if required. */
/* Enable Receiver and Transmitter */
LPC_ETHERNET->MAC_CONFIG |= (MAC_TX_ENABLE | MAC_RX_ENABLE);
/* Enable interrupts */
LPC_ETHERNET->DMA_INT_EN = DMA_INT_NOR_SUM | DMA_INT_RECEIVE ;
/* Start Transmission & Receive processes */
LPC_ETHERNET->DMA_OP_MODE |= (DMA_SS_TRANSMIT | DMA_SS_RECEIVE );
}
return xReturn;
}
/*********************************************************************//**
**********************************************************************/
portBASE_TYPE EMAC_CheckTransmitIndex( void )
{
portBASE_TYPE xReturn;
if( ( Tx_Desc[ TxDescIndex ].Status & OWN_BIT ) == 0 )
{
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
/*********************************************************************//**
* @brief EMAC_SetNextPacketToSend
* @param[in] pucBuffer
* @return None
***********************************************************************/
void EMAC_SetNextPacketToSend( uint8_t * pucBuffer )
{
/* The old packet is now finished with and can be freed. */
vEthernetBufferRelease( ( void * ) Tx_Desc[ TxDescIndex ].Packet );
/* Assign the new packet to the descriptor. */
Tx_Desc[ TxDescIndex ].Packet = ( uint32_t ) pucBuffer;
}
void EMAC_StartTransmitNextBuffer( uint32_t ulLength )
{
Tx_Desc[ TxDescIndex ].Ctrl = ulLength;
Tx_Desc[ TxDescIndex ].Status |= OWN_BIT;
/* Wake Up the DMA if it's in Suspended Mode. */
LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;
TxDescIndex++;
if( TxDescIndex == configNUM_TX_ETHERNET_DMA_DESCRIPTORS )
{
TxDescIndex = 0;
}
}
/*********************************************************************//**
* @brief Get size of current Received data in received buffer (due to
* RxConsumeIndex)
* @param[in] None
* @return Size of received data
**********************************************************************/
uint32_t EMAC_GetReceiveDataSize(void)
{
unsigned short RxLen = 0;
RxLen = ( Rx_Desc[ RxDescIndex ].Status >> 16 ) & 0x03FFF;
return RxLen;
}
/*********************************************************************//**
* @brief Increase the RxConsumeIndex (after reading the Receive buffer
* to release the Receive buffer) and wrap-around the index if
* it reaches the maximum Receive Number
* @param[in] None
* @return None
**********************************************************************/
void EMAC_UpdateRxConsumeIndex( void )
{
Rx_Desc[ RxDescIndex ].Status = OWN_BIT;
RxDescIndex++;
if( RxDescIndex == configNUM_RX_ETHERNET_DMA_DESCRIPTORS )
{
RxDescIndex = 0;
}
}
/*********************************************************************//**
* @brief Check whether if the current RxConsumeIndex is not equal to the
* current RxProduceIndex.
* @param[in] None
* @return TRUE if they're not equal, otherwise return FALSE
*
* Note: In case the RxConsumeIndex is not equal to the RxProduceIndex,
* it means there're available data has been received. They should be read
* out and released the Receive Data Buffer by updating the RxConsumeIndex value.
**********************************************************************/
portBASE_TYPE EMAC_CheckReceiveIndex(void)
{
portBASE_TYPE xReturn;
if( ( Rx_Desc[ RxDescIndex ].Status & OWN_BIT ) == 0 )
{
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
void EMAC_NextPacketToRead( xNetworkBufferDescriptor_t *pxNetworkBuffer )
{
uint8_t *pucTemp;
/* Swap the buffer in the network buffer with the buffer used by the DMA.
This allows the data to be passed out without having to perform any copies. */
pucTemp = ( uint8_t * ) Rx_Desc[ RxDescIndex ].Packet;
Rx_Desc[ RxDescIndex ].Packet = ( uint32_t ) pxNetworkBuffer->pucEthernetBuffer;
pxNetworkBuffer->pucEthernetBuffer = pucTemp;
/* Only supports frames coming in single buffers. If this frame is split
across multiple buffers then reject it (and if the frame is needed increase
the ipconfigNETWORK_MTU setting). */
if( ( Rx_Desc[ RxDescIndex ].Status & emacEXPECTED_RX_STATUS_MASK ) != emacEXPECTED_RX_STATUS_MASK )
{
pxNetworkBuffer->xDataLength = 0;
}
else
{
pxNetworkBuffer->xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( ipETHERNET_CRC_BYTES - 1U );;
}
}
/*********************************************************************//**
* @brief Initializes RX Descriptor
* @param[in] None
* @return None
***********************************************************************/
static void rx_descr_init( void )
{
uint32_t x;
size_t xBufferSize = ipTOTAL_ETHERNET_FRAME_SIZE;
for( x = 0; x < configNUM_RX_ETHERNET_DMA_DESCRIPTORS; x++ )
{
/* Obtain the buffer first, as the size of the buffer might be changed
within the pucEthernetBufferGet() call. */
Rx_Desc[ x ].Packet = ( uint32_t ) pucEthernetBufferGet( &xBufferSize );
Rx_Desc[ x ].Status = OWN_BIT;
Rx_Desc[ x ].Ctrl = xBufferSize;
Rx_Desc[ x ].NextDescripter = ( uint32_t ) &Rx_Desc[ x + 1 ];
configASSERT( ( ( ( uint32_t ) Rx_Desc[x].Packet ) & 0x07 ) == 0 );
}
/* Last Descriptor */
Rx_Desc[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS - 1 ].Ctrl |= RX_END_RING;
RxDescIndex = 0;
/* Set Starting address of RX Descriptor list */
LPC_ETHERNET->DMA_REC_DES_ADDR = ( uint32_t ) Rx_Desc;
}
/*********************************************************************//**
* @brief Initializes TX Descriptor
* @param[in] None
* @return None
***********************************************************************/
static void tx_descr_init( void )
{
/* Initialize Transmit Descriptor and Status array. */
uint32_t x;
for( x = 0; x < configNUM_TX_ETHERNET_DMA_DESCRIPTORS; x++ )
{
Tx_Desc[ x ].Status = TX_LAST_SEGM | TX_FIRST_SEGM;
Tx_Desc[ x ].Ctrl = 0;
Tx_Desc[ x ].NextDescripter = ( uint32_t ) &Tx_Desc[ x + 1 ];
/* Packet is assigned when a Tx is initiated. */
Tx_Desc[ x ].Packet = ( uint32_t )NULL;
}
/* Last Descriptor? */
Tx_Desc[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS-1 ].Status |= TX_END_RING;
/* Set Starting address of TX Descriptor list */
LPC_ETHERNET->DMA_TRANS_DES_ADDR = ( uint32_t ) Tx_Desc;
}
/*********************************************************************//**
* @brief Write value to PHY device
* @param[in] PhyReg: PHY Register address
* @param[in] Value: Value to write
* @return 0 - if success
* 1 - if fail
***********************************************************************/
static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)
{
uint32_t x;
const uint32_t ulMaxAttempts = 250UL;
int32_t lReturn = pdPASS;
/* Write a data 'Value' to PHY register 'PhyReg'. */
x = 0;
while( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY )
{
x++;
if( x >= ulMaxAttempts )
{
/* Time out. */
lReturn = pdFAIL;
break;
}
else
{
/* GMII is busy. */
vTaskDelay( emacTIMEOUT_DELAY );
}
}
if( lReturn == pdPASS )
{
LPC_ETHERNET->MAC_MII_ADDR = ( DP83848C_DEF_ADR << 11 ) | ( PhyReg << 6 ) | GMII_WRITE;
LPC_ETHERNET->MAC_MII_DATA = Value;
/* Start PHY Write Cycle. */
LPC_ETHERNET->MAC_MII_ADDR |= GMII_BUSY;
/* Wait untl operation completed. */
for( x = 0; x < ulMaxAttempts; x++ )
{
if( ( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY ) == 0 )
{
break;
}
else
{
vTaskDelay( emacTIMEOUT_DELAY );
}
}
if( x == ulMaxAttempts )
{
/* Timeout. */
lReturn = pdFAIL;
}
}
return lReturn;
}
/*********************************************************************//**
* @brief Read value from PHY device
* @param[in] PhyReg: PHY Register address
* @return 0 - if success
* 1 - if fail
***********************************************************************/
static int32_t read_PHY( uint32_t PhyReg )
{
int32_t lValue = 0;
uint32_t x;
const uint32_t ulMaxAttempts = 250UL;
/* Write a data 'Value' to PHY register 'PhyReg'. */
x = 0;
while( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY )
{
x++;
if( x >= ulMaxAttempts )
{
/* Time out. */
break;
}
else
{
/* GMII is busy. */
vTaskDelay( emacTIMEOUT_DELAY );
}
}
if( x < ulMaxAttempts )
{
/* Read a PHY register 'PhyReg'. */
LPC_ETHERNET->MAC_MII_ADDR = ( DP83848C_DEF_ADR << 11 ) | ( PhyReg << 6 ) | GMII_READ;
/* Start PHY Read Cycle. */
LPC_ETHERNET->MAC_MII_ADDR |= GMII_BUSY;
/* Wait until operation completed */
for( x = 0; x < ulMaxAttempts; x++ )
{
if( ( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY ) == 0 )
{
break;
}
else
{
vTaskDelay( emacTIMEOUT_DELAY );
}
}
configASSERT( x != ulMaxAttempts );
lValue = LPC_ETHERNET->MAC_MII_DATA;
}
return lValue;
}
/*********************************************************************//**
* @brief Set Station MAC address for EMAC module
* @param[in] abStationAddr Pointer to Station address that contains 6-bytes
* of MAC address (should be in order from MAC Address 1 to MAC Address 6)
* @return None
**********************************************************************/
static void setEmacAddr( uint8_t abStationAddr[] )
{
/* Set the Ethernet MAC Address registers */
LPC_ETHERNET->MAC_ADDR0_HIGH = (( uint32_t ) abStationAddr[ 5 ] << 8 ) | ( uint32_t )abStationAddr[ 4 ];
LPC_ETHERNET->MAC_ADDR0_LOW = (( uint32_t )abStationAddr[ 3 ] << 24) | (( uint32_t )abStationAddr[ 2 ] << 16) | (( uint32_t )abStationAddr[ 1 ] << 8 ) | ( uint32_t )abStationAddr[ 0 ];
}

View file

@ -0,0 +1,238 @@
/***********************************************************************//**
* @file lpc17xx_emac.h
* @brief Contains all macro definitions and function prototypes
* support for Ethernet MAC firmware library on LPC17xx
* @version 2.0
* @date 21. May. 2010
* @author NXP MCU SW Application Team
**************************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
**************************************************************************/
/* Peripheral group ----------------------------------------------------------- */
/** @defgroup EMAC EMAC
* @ingroup LPC1700CMSIS_FwLib_Drivers
* @{
*/
#ifndef LPC18XX_EMAC_H_
#define LPC18XX_EMAC_H_
/* Includes ------------------------------------------------------------------- */
#include "LPC18xx.h"
#ifdef __cplusplus
extern "C"
{
#endif
#include "lpc_types.h"
/* Configuration */
/* Interface Selection */
#define MII 0 // =0 RMII - =1 MII
/* End of Configuration */
/* Descriptors Fields bits */
#define OWN_BIT (1U<<31) /* Own bit in RDES0 & TDES0 */
#define RX_END_RING (1<<15) /* Receive End of Ring bit in RDES1 */
#define RX_NXTDESC_FLAG (1<<14) /* Second Address Chained bit in RDES1 */
#define TX_LAST_SEGM (1<<29) /* Last Segment bit in TDES0 */
#define RX_LAST_SEGM (1<<9)
#define TX_FIRST_SEGM (1<<28) /* First Segment bit in TDES0 */
#define RX_FIRST_SEGM (1<<8) /* First Segment bit in TDES0 */
#define TX_END_RING (1<<21) /* Transmit End of Ring bit in TDES0 */
#define TX_NXTDESC_FLAG (1<<20) /* Second Address Chained bit in TDES0 */
/* EMAC Memory Buffer configuration for 16K Ethernet RAM */
#define EMAC_ETH_MAX_FLEN ipETHERNET_FRAME_SIZE_TO_USE
/* NOTE: EMAC_NUM_RX_FRAG is not used by the example FreeRTOS drivers - use
configNUM_RX_ETHERNET_DMA_DESCRIPTORS. */
#define EMAC_NUM_RX_FRAG 6 /**< Num.of RX Fragments */
/* NOTE: EMAC_NUM_TX_FRAG is not used by the example FreeRTOS drivers - use
configNUM_TX_ETHERNET_DMA_DESCRIPTORS. */
#define EMAC_NUM_TX_FRAG 2 /**< Num.of TX Fragments */
/* EMAC Control and Status bits */
#define MAC_RX_ENABLE (1<<2) /* Receiver Enable in MAC_CONFIG reg */
#define MAC_TX_ENABLE (1<<3) /* Transmitter Enable in MAC_CONFIG reg */
#define MAC_PADCRC_STRIP (1<<7) /* Automatic Pad-CRC Stripping in MAC_CONFIG reg */
#define MAC_DUPMODE (1<<11) /* Duplex Mode in MAC_CONFIG reg */
#define MAC_100MPS (1<<14) /* Speed is 100Mbps in MAC_CONFIG reg */
#define MAC_PROMISCUOUS (1U<<0) /* Promiscuous Mode bit in MAC_FRAME_FILTER reg */
#define MAC_DIS_BROAD (1U<<5) /* Disable Broadcast Frames bit in MAC_FRAME_FILTER reg */
#define MAC_RECEIVEALL (1U<<31) /* Receive All bit in MAC_FRAME_FILTER reg */
#define DMA_SOFT_RESET 0x01 /* Software Reset bit in DMA_BUS_MODE reg */
#define DMA_SS_RECEIVE (1<<1) /* Start/Stop Receive bit in DMA_OP_MODE reg */
#define DMA_SS_TRANSMIT (1<<13) /* Start/Stop Transmission bit in DMA_OP_MODE reg */
#define DMA_INT_TRANSMIT (1<<0) /* Transmit Interrupt Enable bit in DMA_INT_EN reg */
#define DMA_INT_OVERFLOW (1<<4) /* Overflow Interrupt Enable bit in DMA_INT_EN reg */
#define DMA_INT_UNDERFLW (1<<5) /* Underflow Interrupt Enable bit in DMA_INT_EN reg */
#define DMA_INT_RECEIVE (1<<6) /* Receive Interrupt Enable bit in DMA_INT_EN reg */
#define DMA_INT_ABN_SUM (1<<15) /* Abnormal Interrupt Summary Enable bit in DMA_INT_EN reg */
#define DMA_INT_NOR_SUM (1<<16) /* Normal Interrupt Summary Enable bit in DMA_INT_EN reg */
/* MII Management Command Register */
#define GMII_READ (0<<1) /* GMII Read PHY */
#define GMII_WRITE (1<<1) /* GMII Write PHY */
#define GMII_BUSY 0x00000001 /* GMII is Busy / Start Read/Write */
#define MII_WR_TOUT 0x00050000 /* MII Write timeout count */
#define MII_RD_TOUT 0x00050000 /* MII Read timeout count */
/* MII Management Address Register */
#define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */
/* LAN8720 PHY Registers */
#define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */
#define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */
#define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */
#define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */
#define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */
#define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */
#define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */
#define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */
/* LAN8720 PHY Speed identify */
#define PHY_REG_SPCON 0x1f /* Speed indication Register */
#define PHY_REG_HCDSPEED_MASK 0x1c /* Speed indication Register mask*/
#define PHY_REG_HCDSPEED_10MB_HALFD 0x04 /* Speed is 10Mbps HALF-duplex */
#define PHY_REG_HCDSPEED_10MB_FULLD 0x14 /* Speed is 10Mbps FULL-duplex */
#define PHY_REG_HCDSPEED_100MB_HALFD 0x08 /* Speed is 100Mbps HALF-duplex */
#define PHY_REG_HCDSPEED_100MB_FULLD 0x18 /* Speed is 100Mbps FULL-duplex */
/* PHY Extended Registers */
#define PHY_REG_STS 0x10 /* Status Register */
#define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */
#define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */
#define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */
#define PHY_REG_RECR 0x15 /* Receive Error Counter */
#define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */
#define PHY_REG_RBR 0x17 /* RMII and Bypass Register */
#define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */
#define PHY_REG_PHYCR 0x19 /* PHY Control Register */
#define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */
#define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */
#define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */
/* PHY Control and Status bits */
#define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
#define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
#define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
#define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
#define PHY_AUTO_NEG 0x1000 /* Select Auto Negotiation */
#define PHY_AUTO_NEG_DONE 0x0020 /* AutoNegotiation Complete in BMSR PHY reg */
#define PHY_BMCR_RESET 0x8000 /* Reset bit at BMCR PHY reg */
#define LINK_VALID_STS 0x0001 /* Link Valid Status at REG_STS PHY reg */
#define FULL_DUP_STS 0x0004 /* Full Duplex Status at REG_STS PHY reg */
#define SPEED_10M_STS 0x0002 /* 10Mbps Status at REG_STS PHY reg */
#define DP83848C_DEF_ADR 0x01 /* Default PHY device address */
#define DP83848C_ID 0x20005C90 /* PHY Identifier (without Rev. info */
#define LAN8720_ID 0x0007C0F1 /* PHY Identifier for SMSC PHY */
/* Misc */
#define ETHERNET_RST 22 /* Reset Output for EMAC at RGU */
#define RMII_SELECT 0x04 /* Select RMII in EMACCFG */
/**
* @brief EMAC configuration structure definition
*/
typedef struct {
uint32_t Mode; /**< Supported EMAC PHY device speed, should be one of the following:
- EMAC_MODE_AUTO
- EMAC_MODE_10M_FULL
- EMAC_MODE_10M_HALF
- EMAC_MODE_100M_FULL
- EMAC_MODE_100M_HALF
*/
uint8_t *pbEMAC_Addr; /**< Pointer to EMAC Station address that contains 6-bytes
of MAC address, it must be sorted in order (bEMAC_Addr[0]..[5])
*/
} EMAC_CFG_Type;
/* Descriptor and status formats ---------------------------------------------- */
/**
* @brief RX Descriptor structure type definition
*/
typedef struct {
uint32_t Status; /**< Receive Status Descriptor */
uint32_t Ctrl; /**< Receive Control Descriptor */
uint32_t Packet; /**< Receive Packet Descriptor */
uint32_t NextDescripter;/**< Receive Next Descriptor Address */
} RX_Desc;
/**
* @brief RX Status structure type definition
*/
typedef struct {
uint32_t Info; /**< Receive Information Status */
uint32_t HashCRC; /**< Receive Hash CRC Status */
} RX_Stat;
/**
* @brief TX Descriptor structure type definition
*/
typedef struct {
uint32_t Status; /**< Transmit Status Descriptor */
uint32_t Ctrl; /**< Transmit Control Descriptor */
uint32_t Packet; /**< Transmit Packet Descriptor */
uint32_t NextDescripter; /**< Transmit Next Descriptor Address */
} TX_Desc;
/**
* @brief TX Status structure type definition
*/
typedef struct {
uint32_t Info; /**< Transmit Information Status */
} TX_Stat;
/**
* @brief TX Data Buffer structure definition
*/
typedef struct {
uint32_t ulDataLen; /**< Data length */
uint32_t *pbDataBuf; /**< A word-align data pointer to data buffer */
} EMAC_PACKETBUF_Type;
/* Prototypes */
portBASE_TYPE EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct);
int32_t EMAC_UpdatePHYStatus(void);
uint32_t EMAC_GetReceiveDataSize(void);
void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );
void EMAC_NextPacketToRead( xNetworkBufferDescriptor_t *pxNetworkBuffer );
void EMAC_UpdateRxConsumeIndex(void);
portBASE_TYPE EMAC_CheckReceiveIndex(void);
portBASE_TYPE EMAC_CheckTransmitIndex(void);
#ifdef __cplusplus
}
#endif
#endif /* LPC18XX_EMAC_H_ */
/**
* @}
*/
/* --------------------------------- End Of File ------------------------------ */

View file

@ -0,0 +1,161 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h"
/* Hardware includes. */
#include "hwEthernet.h"
/* Demo includes. */
#include "NetworkInterface.h"
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
/* When a packet is ready to be sent, if it cannot be sent immediately then the
task performing the transmit will block for niTX_BUFFER_FREE_WAIT
milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
up. */
#define niTX_BUFFER_FREE_WAIT ( ( portTickType ) 2UL / portTICK_RATE_MS )
#define niMAX_TX_ATTEMPTS ( 5 )
/* The length of the queue used to send interrupt status words from the
interrupt handler to the deferred handler task. */
#define niINTERRUPT_QUEUE_LENGTH ( 10 )
/*-----------------------------------------------------------*/
/*
* A deferred interrupt handler task that processes
*/
extern void vEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* The queue used to communicate Ethernet events with the IP task. */
extern xQueueHandle xNetworkEventQueue;
/* The semaphore used to wake the deferred interrupt handler task when an Rx
interrupt is received. */
xSemaphoreHandle xEMACRxEventSemaphore = NULL;
/*-----------------------------------------------------------*/
portBASE_TYPE xNetworkInterfaceInitialise( void )
{
portBASE_TYPE xStatus, xReturn;
extern uint8_t ucMACAddress[ 6 ];
/* Initialise the MAC. */
vInitEmac();
while( lEMACWaitForLink() != pdPASS )
{
vTaskDelay( 20 );
}
vSemaphoreCreateBinary( xEMACRxEventSemaphore );
configASSERT( xEMACRxEventSemaphore );
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( vEMACHandlerTask, ( const signed char * const ) "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
xReturn = pdPASS;
return xReturn;
}
/*-----------------------------------------------------------*/
portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );
vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );
/* Finished with the network buffer. */
vNetworkBufferRelease( pxNetworkBuffer );
return pdTRUE;
}
/*-----------------------------------------------------------*/
#if 0
void ENET_IRQHandler( void )
{
uint32_t ulInterruptCause;
while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )
{
/* Clear the interrupt. */
LPC_EMAC->IntClear = ulInterruptCause;
/* Clear fatal error conditions. NOTE: The driver does not clear all
errors, only those actually experienced. For future reference, range
errors are not actually errors so can be ignored. */
if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )
{
LPC_EMAC->Command |= EMAC_CR_TX_RES;
}
/* Unblock the deferred interrupt handler task if the event was an
Rx. */
if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )
{
xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );
}
}
/* Shortcut calling portEND_SWITCHING_ISR(). */
vPortYieldFromISR();
}
/*-----------------------------------------------------------*/
#endif

View file

@ -0,0 +1,469 @@
/*
* FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
*
* FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
* of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
* and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
* model, information on which is provided below:
*
* - Open source licensing -
* FreeRTOS+UDP is a free download and may be used, modified and distributed
* without charge provided the user adheres to version two of the GNU General
* Public license (GPL) and does not remove the copyright notice or this text.
* The GPL V2 text is available on the gnu.org web site, and on the following
* URL: http://www.FreeRTOS.org/gpl-2.0.txt
*
* - Commercial licensing -
* Businesses and individuals who wish to incorporate FreeRTOS+UDP into
* proprietary software for redistribution in any form must first obtain a
* (very) low cost commercial license - and in-so-doing support the maintenance,
* support and further development of the FreeRTOS+UDP product. Commercial
* licenses can be obtained from http://shop.freertos.org and do not require any
* source files to be changed.
*
* FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
* use FreeRTOS+UDP unless you agree that you use the software 'as is'.
* FreeRTOS+UDP 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/udp
*
*/
/* WinPCap includes. */
#define HAVE_REMOTE
#include "pcap.h"
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h"
/* Demo includes. */
#include "NetworkInterface.h"
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it
considers need processing. In this case ipCONSIDER_FRAME_FOR_PROCESSING() can
be #defined away. If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 0
then the Ethernet driver will pass all received packets to the stack, and the
stack must do the filtering itself. In this case ipCONSIDER_FRAME_FOR_PROCESSING
needs to call eConsiderFrameForProcessing. */
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
/*-----------------------------------------------------------*/
/*
* Print out a numbered list of network interfaces that are available on the
* host computer.
*/
static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );
/*
* Open the network interface. The number of the interface to be opened is set
* by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
*/
static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );
/*
* Configure the capture filter to allow blocking reads, and to filter out
* packets that are not of interest to this demo.
*/
static void prvConfigureCaptureBehaviour( void );
/*
* A function that simulates Ethernet interrupts by periodically polling the
* WinPCap interface for new data.
*/
static void prvInterruptSimulatorTask( void *pvParameters );
/* The interface being used by WinPCap. */
static pcap_t *pxOpenedInterfaceHandle = NULL;
/*-----------------------------------------------------------*/
/* Required by the WinPCap library. */
static char cErrorBuffer[ PCAP_ERRBUF_SIZE ];
/* When statically allocated network buffers are used (as opposed to having
the buffer payloads allocated and freed as required) the actual buffer storage
areas must be defined in the portable layer. This is because different
microcontrollers have different location, size and alignment requirements. In
this case the network buffers are declared in NetworkInterface.c because, as
this file is only used on Windows machines, wasting a few bytes in buffers that
never get used does not matter (the buffers will not get used if the dynamic
payload allocation file is included in the project). */
static uint8_t ucBuffers[ ipconfigNUM_NETWORK_BUFFERS ][ ipTOTAL_ETHERNET_FRAME_SIZE ];
/* The queue used to communicate Ethernet events with the IP task. */
extern xQueueHandle xNetworkEventQueue;
/* Protect the PCAP interface as it is accessed from two tasks (an interrupt
simulator is used as real interrupts cannot be obtained from the Ethernet as
would normally be the case). */
xSemaphoreHandle xPCAPMutex = NULL;
/*-----------------------------------------------------------*/
portBASE_TYPE xNetworkInterfaceInitialise( void )
{
portBASE_TYPE xReturn = pdFALSE;
pcap_if_t *pxAllNetworkInterfaces;
if( xPCAPMutex == NULL )
{
xPCAPMutex = xSemaphoreCreateMutex();
configASSERT( xPCAPMutex );
}
/* Query the computer the simulation is being executed on to find the
network interfaces it has installed. */
pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();
/* Open the network interface. The number of the interface to be opened is
set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
Calling this function will set the pxOpenedInterfaceHandle variable. If,
after calling this function, pxOpenedInterfaceHandle is equal to NULL, then
the interface could not be opened. */
if( pxAllNetworkInterfaces != NULL )
{
prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );
}
if( pxOpenedInterfaceHandle != NULL )
{
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
#if updconfigLOOPBACK_ETHERNET_PACKETS == 1
portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
xEthernetHeader_t *pxEthernetHeader;
xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
extern uint8_t xDefaultPartUDPPacketHeader[];
static const xMACAddress_t xBroadcastMACAddress = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
portBASE_TYPE xCanLoopback;
pxEthernetHeader = ( xEthernetHeader_t * ) pxNetworkBuffer->pucEthernetBuffer;
if( memcmp( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) &xBroadcastMACAddress, sizeof( xMACAddress_t ) ) == 0 )
{
/* This is a broadcast. */
xCanLoopback = pdTRUE;
}
else if( memcmp( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) xDefaultPartUDPPacketHeader, sizeof( xMACAddress_t ) ) == 0 )
{
/* This is being sent to itself. */
xCanLoopback = pdTRUE;
}
else
{
/* This is being sent externally. */
xCanLoopback = pdFALSE;
}
iptraceNETWORK_INTERFACE_TRANSMIT();
if( xCanLoopback == pdTRUE )
{
/* Just loop the frame back to the input queue. Here the loopback
is sending a message to itself, so a block time cannot be used for
fear of deadlocking. */
xRxEvent.pvData = ( void * ) pxNetworkBuffer;
if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( portTickType ) 0 ) == pdFALSE )
{
vNetworkBufferRelease( pxNetworkBuffer );
iptraceETHERNET_RX_EVENT_LOST();
}
}
else
{
/* Send the packet. */
xSemaphoreTake( xPCAPMutex, portMAX_DELAY );
{
pcap_sendpacket( pxOpenedInterfaceHandle, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
}
xSemaphoreGive( xPCAPMutex );
/* The buffer has been transmitted so can be released. */
vNetworkBufferRelease( pxNetworkBuffer );
}
return pdPASS;
}
#else /* updconfigLOOPBACK_ETHERNET_PACKETS == 1 */
portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
xSemaphoreTake( xPCAPMutex, portMAX_DELAY );
{
iptraceNETWORK_INTERFACE_TRANSMIT();
pcap_sendpacket( pxOpenedInterfaceHandle, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
}
xSemaphoreGive( xPCAPMutex );
/* The buffer has been transmitted so can be released. */
vNetworkBufferRelease( pxNetworkBuffer );
return pdPASS;
}
#endif /* updconfigLOOPBACK_ETHERNET_PACKETS == 1 */
/*-----------------------------------------------------------*/
static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
{
pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;
long lInterfaceNumber = 1;
if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
{
printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );
pxAllNetworkInterfaces = NULL;
}
if( pxAllNetworkInterfaces != NULL )
{
/* Print out the list of network interfaces. The first in the list
is interface '1', not interface '0'. */
for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )
{
printf( "%d. %s", lInterfaceNumber, xInterface->name );
if( xInterface->description != NULL )
{
printf( " (%s)\r\n", xInterface->description );
}
else
{
printf( " (No description available)\r\n") ;
}
lInterfaceNumber++;
}
}
if( lInterfaceNumber == 1 )
{
/* The interface number was never incremented, so the above for() loop
did not execute meaning no interfaces were found. */
printf( " \r\nNo network interfaces were found.\r\n" );
pxAllNetworkInterfaces = NULL;
}
printf( "\r\nThe interface that will be opened is set by configNETWORK_INTERFACE_TO_USE which should be defined in FreeRTOSConfig.h\r\n" );
printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );
if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )
{
printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );
if( pxAllNetworkInterfaces != NULL )
{
/* Free the device list, as no devices are going to be opened. */
pcap_freealldevs( pxAllNetworkInterfaces );
pxAllNetworkInterfaces = NULL;
}
}
return pxAllNetworkInterfaces;
}
/*-----------------------------------------------------------*/
static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
{
pcap_if_t *xInterface;
long x;
/* Walk the list of devices until the selected device is located. */
xInterface = pxAllNetworkInterfaces;
for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )
{
xInterface = xInterface->next;
}
/* Open the selected interface. */
pxOpenedInterfaceHandle = pcap_open( xInterface->name, /* The name of the selected interface. */
ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */
PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscious mode as the MAC and
IP address is going to be "simulated", and
not be the real MAC and IP address. This allows
trafic to the simulated IP address to be routed
to uIP, and trafic to the real IP address to be
routed to the Windows TCP/IP stack. */
0x00L, /* The read time out. */
NULL, /* No authentication is required as this is
not a remote capture session. */
cErrorBuffer
);
if ( pxOpenedInterfaceHandle == NULL )
{
printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );
}
else
{
/* Configure the capture filter to allow blocking reads, and to filter
out packets that are not of interest to this demo. */
prvConfigureCaptureBehaviour();
}
/* The device list is no longer required. */
pcap_freealldevs( pxAllNetworkInterfaces );
}
/*-----------------------------------------------------------*/
static void prvConfigureCaptureBehaviour( void )
{
struct bpf_program xFilterCode;
const long lMinBytesToCopy = 10L, lBlocking = 1L;
unsigned long ulNetMask;
/* Unblock a read as soon as anything is received. */
pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );
/* Allow blocking. */
pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );
/* Set up a filter so only the packets of interest are passed to the IP
stack. cErrorBuffer is used for convenience to create the string. Don't
confuse this with an error message. *//*_RB_ This should not use the #defined constants. *//*_RB_ Constants should not be used, but passed through a generic network API. */
sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x", configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 );
/*_RB_ Constants should not be used, but passed through a generic network API. */
ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )
{
printf("\r\nThe packet filter string is invalid\r\n" );
}
else
{
if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )
{
printf( "\r\nAn error occurred setting the packet filter.\r\n" );
}
}
/* Create a task that simulates an interrupt in a real system. This will
block waiting for packets, then send a message to the uIP task when data
is available. */
xTaskCreate( prvInterruptSimulatorTask, ( signed char * ) "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL );
}
/*-----------------------------------------------------------*/
static void prvInterruptSimulatorTask( void *pvParameters )
{
static struct pcap_pkthdr *pxHeader;
const uint8_t *pucPacketData;
long lResult;
xNetworkBufferDescriptor_t *pxNetworkBuffer;
xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
eFrameProcessingResult_t eResult;
/* Just to kill the compiler warning. */
( void ) pvParameters;
for( ;; )
{
/* Get the next packet. */
xSemaphoreTake( xPCAPMutex, portMAX_DELAY );
{
lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );
}
xSemaphoreGive( xPCAPMutex );
if( lResult == 1 )
{
eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );
if( eResult == eProcessBuffer )
{
/* Will the data fit into the frame buffer? */
if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )
{
/* Obtain a buffer into which the data can be placed. This
is only an interrupt simulator, not a real interrupt, so it
is ok to call the task level function here. */
xSemaphoreTake( xPCAPMutex, portMAX_DELAY );
{
pxNetworkBuffer = pxNetworkBufferGet( pxHeader->len, 0 );
}
xSemaphoreGive( xPCAPMutex );
if( pxNetworkBuffer != NULL )
{
memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );
pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;
xRxEvent.pvData = ( void * ) pxNetworkBuffer;
/* Data was received and stored. Send a message to the IP
task to let it know. */
if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( portTickType ) 0 ) == pdFALSE )
{
/* The buffer could not be sent to the stack so
must be released again. This is only an interrupt
simulator, not a real interrupt, so it is ok to use
the task level function here. */
vNetworkBufferRelease( pxNetworkBuffer );
iptraceETHERNET_RX_EVENT_LOST();
}
}
else
{
iptraceETHERNET_RX_EVENT_LOST();
}
}
else
{
/* Log that a packet was dropped because it would have
overflowed the buffer. */
}
}
}
else
{
/* There is no real way of simulating an interrupt. Make sure
other tasks can run. */
vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );
}
}
}
/*-----------------------------------------------------------*/
#if configUSE_STATIC_BUFFERS == 1
void vNetworkInterfaceAllocateRAMToBuffers( xNetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFERS ] )
{
portBASE_TYPE x;
for( x = 0; x < ipconfigNUM_NETWORK_BUFFERS; x++ )
{
pxNetworkBuffers[ x ].pucEthernetBuffer = &( ucBuffers[ x ][ 0 ] );
}
}
#endif
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,16 @@
Contains the files that implement FreeRTOS+UDP.
User documentation, including an API reference is available on:
http://www.FreeRTOS.org/udp
A description of the source code organisation is available on:
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/FreeRTOS_UDP_IP_Embedded_Ethernet_Tutorial.shtml
The porting guide is available one:
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/FreeRTOS_UDP_Porting.shtml
At this time it is recommended to use BufferAllocation_2.c in which case it is
essential to use the heap_4.c memory allocation scheme:
http://www.freertos.org/a00111.html