mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-01 08:54:14 -04:00
Add FreeRTOS-Plus directory with new directory structure so it matches the FreeRTOS directory.
This commit is contained in:
parent
80f7e8cdd4
commit
64a3ab321a
528 changed files with 228252 additions and 0 deletions
716
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/FreeRTOS_DHCP.c
Normal file
716
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/FreeRTOS_DHCP.c
Normal 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 */
|
||||
|
||||
|
411
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/FreeRTOS_DNS.c
Normal file
411
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/FreeRTOS_DNS.c
Normal 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 */
|
||||
|
||||
|
1035
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/FreeRTOS_Sockets.c
Normal file
1035
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/FreeRTOS_Sockets.c
Normal file
File diff suppressed because it is too large
Load diff
1854
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/FreeRTOS_UDP_IP.c
Normal file
1854
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/FreeRTOS_UDP_IP.c
Normal file
File diff suppressed because it is too large
Load diff
23
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/History.txt
Normal file
23
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/History.txt
Normal 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.
|
||||
|
||||
|
5
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/ReadMe.url
Normal file
5
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/ReadMe.url
Normal file
|
@ -0,0 +1,5 @@
|
|||
[InternetShortcut]
|
||||
URL=http://www.freertos.org/udp
|
||||
IDList=
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,2
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
118
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/include/FreeRTOS_UDP_IP.h
Normal file
118
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/include/FreeRTOS_UDP_IP.h
Normal 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 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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) );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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. */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -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 ];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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 ------------------------------ */
|
|
@ -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
|
||||
|
|
@ -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
|
||||
/*-----------------------------------------------------------*/
|
16
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/readme.txt
Normal file
16
FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/readme.txt
Normal 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
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue