mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-26 23:36:32 -04:00
Added +TCP code to main repo.
This commit is contained in:
parent
037abdddf2
commit
77e95538dc
114 changed files with 46629 additions and 446 deletions
682
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c
Normal file
682
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c
Normal file
|
|
@ -0,0 +1,682 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#if( ipconfigUSE_LLMNR == 1 )
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#endif /* ipconfigUSE_LLMNR */
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
|
||||
/* When the age of an entry in the ARP table reaches this value (it counts down
|
||||
to zero, so this is an old entry) an ARP request will be sent to see if the
|
||||
entry is still valid and can therefore be refreshed. */
|
||||
#define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ( 3 )
|
||||
|
||||
/* The time between gratuitous ARPs. */
|
||||
#ifndef arpGRATUITOUS_ARP_PERIOD
|
||||
#define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000 ) )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Lookup an MAC address in the ARP cache from the IP address.
|
||||
*/
|
||||
static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The ARP cache. */
|
||||
static ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ];
|
||||
|
||||
/* The time at which the last gratuitous ARP was sent. Gratuitous ARPs are used
|
||||
to ensure ARP tables are up to date and to detect IP address conflicts. */
|
||||
static TickType_t xLastGratuitousARPTime = ( TickType_t ) 0;
|
||||
|
||||
/*
|
||||
* IP-clash detection is currently only used internally. When DHCP doesn't respond, the
|
||||
* driver can try out a random LinkLayer IP address (169.254.x.x). It will send out a
|
||||
* gratuitos ARP message and, after a period of time, check the variables here below:
|
||||
*/
|
||||
#if( ipconfigARP_USE_CLASH_DETECTION != 0 )
|
||||
/* Becomes non-zero if another device responded to a gratuitos ARP message. */
|
||||
BaseType_t xARPHadIPClash;
|
||||
/* MAC-address of the other device containing the same IP-address. */
|
||||
MACAddress_t xARPClashMacAddress;
|
||||
#endif /* ipconfigARP_USE_CLASH_DETECTION */
|
||||
|
||||
/* Part of the Ethernet and ARP headers are always constant when sending an IPv4
|
||||
ARP packet. This array defines the constant parts, allowing this part of the
|
||||
packet to be filled in using a simple memcpy() instead of individual writes. */
|
||||
static const uint8_t xDefaultPartARPPacketHeader[] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Ethernet destination address. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Ethernet source address. */
|
||||
0x08, 0x06, /* Ethernet frame type (ipARP_FRAME_TYPE). */
|
||||
0x00, 0x01, /* usHardwareType (ipARP_HARDWARE_TYPE_ETHERNET). */
|
||||
0x08, 0x00, /* usProtocolType. */
|
||||
ipMAC_ADDRESS_LENGTH_BYTES, /* ucHardwareAddressLength. */
|
||||
ipIP_ADDRESS_LENGTH_BYTES, /* ucProtocolAddressLength. */
|
||||
0x00, 0x01, /* usOperation (ipARP_REQUEST). */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* xSenderHardwareAddress. */
|
||||
0x00, 0x00, 0x00, 0x00, /* ulSenderProtocolAddress. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* xTargetHardwareAddress. */
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
|
||||
{
|
||||
eFrameProcessingResult_t eReturn = eReleaseBuffer;
|
||||
ARPHeader_t *pxARPHeader;
|
||||
uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
|
||||
|
||||
pxARPHeader = &( pxARPFrame->xARPHeader );
|
||||
|
||||
/* The field ulSenderProtocolAddress is badly aligned, copy byte-by-byte. */
|
||||
memcpy( ( void *)&( ulSenderProtocolAddress ), ( void * )pxARPHeader->ucSenderProtocolAddress, sizeof( ulSenderProtocolAddress ) );
|
||||
/* The field ulTargetProtocolAddress is well-aligned, a 32-bits copy. */
|
||||
ulTargetProtocolAddress = pxARPHeader->ulTargetProtocolAddress;
|
||||
|
||||
traceARP_PACKET_RECEIVED();
|
||||
|
||||
/* Don't do anything if the local IP address is zero because
|
||||
that means a DHCP request has not completed. */
|
||||
if( *ipLOCAL_IP_ADDRESS_POINTER != 0UL )
|
||||
{
|
||||
switch( pxARPHeader->usOperation )
|
||||
{
|
||||
case ipARP_REQUEST :
|
||||
/* The packet contained an ARP request. Was it for the IP
|
||||
address of the node running this code? */
|
||||
if( ulTargetProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )
|
||||
{
|
||||
iptraceSENDING_ARP_REPLY( ulSenderProtocolAddress );
|
||||
|
||||
/* The request is for the address of this node. Add the
|
||||
entry into the ARP cache, or refresh the entry if it
|
||||
already exists. */
|
||||
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );
|
||||
|
||||
/* Generate a reply payload in the same buffer. */
|
||||
pxARPHeader->usOperation = ( uint16_t ) ipARP_REPLY;
|
||||
if( ulTargetProtocolAddress == ulSenderProtocolAddress )
|
||||
{
|
||||
/* A double IP address is detected! */
|
||||
/* Give the sources MAC address the value of the broadcast address, will be swapped later */
|
||||
memcpy( pxARPFrame->xEthernetHeader.xSourceAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( xBroadcastMACAddress ) );
|
||||
memset( pxARPHeader->xTargetHardwareAddress.ucBytes, '\0', sizeof( MACAddress_t ) );
|
||||
pxARPHeader->ulTargetProtocolAddress = 0UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( pxARPHeader->xTargetHardwareAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( MACAddress_t ) );
|
||||
pxARPHeader->ulTargetProtocolAddress = ulSenderProtocolAddress;
|
||||
}
|
||||
memcpy( pxARPHeader->xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
|
||||
memcpy( ( void* )pxARPHeader->ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPHeader->ucSenderProtocolAddress ) );
|
||||
|
||||
eReturn = eReturnEthernetFrame;
|
||||
}
|
||||
break;
|
||||
|
||||
case ipARP_REPLY :
|
||||
iptracePROCESSING_RECEIVED_ARP_REPLY( ulTargetProtocolAddress );
|
||||
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );
|
||||
/* Process received ARP frame to see if there is a clash. */
|
||||
#if( ipconfigARP_USE_CLASH_DETECTION != 0 )
|
||||
{
|
||||
if( ulSenderProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )
|
||||
{
|
||||
xARPHadIPClash = pdTRUE;
|
||||
memcpy( xARPClashMacAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( xARPClashMacAddress.ucBytes ) );
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigARP_USE_CLASH_DETECTION */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Invalid. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return eReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigUSE_ARP_REMOVE_ENTRY != 0 )
|
||||
|
||||
uint32_t ulARPRemoveCacheEntryByMac( const MACAddress_t * pxMACAddress )
|
||||
{
|
||||
BaseType_t x;
|
||||
uint32_t lResult = 0;
|
||||
|
||||
/* For each entry in the ARP cache table. */
|
||||
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
|
||||
{
|
||||
if( ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )
|
||||
{
|
||||
lResult = xARPCache[ x ].ulIPAddress;
|
||||
memset( &xARPCache[ x ], '\0', sizeof( xARPCache[ x ] ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
#endif /* ipconfigUSE_ARP_REMOVE_ENTRY != 0 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress, const uint32_t ulIPAddress )
|
||||
{
|
||||
BaseType_t x, xIpEntry = -1, xMacEntry = -1, xUseEntry = 0;
|
||||
uint8_t ucMinAgeFound = 0U;
|
||||
|
||||
#if( ipconfigARP_STORES_REMOTE_ADDRESSES == 0 )
|
||||
/* Only process the IP address if it is on the local network.
|
||||
Unless: when '*ipLOCAL_IP_ADDRESS_POINTER' equals zero, the IP-address
|
||||
and netmask are still unknown. */
|
||||
if( ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) ||
|
||||
( *ipLOCAL_IP_ADDRESS_POINTER == 0ul ) )
|
||||
#else
|
||||
/* If ipconfigARP_STORES_REMOTE_ADDRESSES is non-zero, IP addresses with
|
||||
a different netmask will also be stored. After when replying to a UDP
|
||||
message from a different netmask, the IP address can be looped up and a
|
||||
reply sent. This option is useful for systems with multiple gateways,
|
||||
the reply will surely arrive. If ipconfigARP_STORES_REMOTE_ADDRESSES is
|
||||
zero the the gateway address is the only option. */
|
||||
if( pdTRUE )
|
||||
#endif
|
||||
{
|
||||
/* Start with the maximum possible number. */
|
||||
ucMinAgeFound--;
|
||||
|
||||
/* For each entry in the ARP cache table. */
|
||||
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
|
||||
{
|
||||
/* Does this line in the cache table hold an entry for the IP
|
||||
address being queried? */
|
||||
if( xARPCache[ x ].ulIPAddress == ulIPAddress )
|
||||
{
|
||||
if( pxMACAddress == NULL )
|
||||
{
|
||||
/* In case the parameter pxMACAddress is NULL, an entry will be reserved to
|
||||
indicate that there is an outstanding ARP request, This entry will have
|
||||
"ucValid == pdFALSE". */
|
||||
xIpEntry = x;
|
||||
break;
|
||||
}
|
||||
|
||||
/* See if the MAC-address also matches. */
|
||||
if( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 )
|
||||
{
|
||||
/* This function will be called for each received packet
|
||||
As this is by far the most common path the coding standard
|
||||
is relaxed in this case and a return is permitted as an
|
||||
optimisation. */
|
||||
xARPCache[ x ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
|
||||
xARPCache[ x ].ucValid = ( uint8_t ) pdTRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Found an entry containing ulIPAddress, but the MAC address
|
||||
doesn't match. Might be an entry with ucValid=pdFALSE, waiting
|
||||
for an ARP reply. Still want to see if there is match with the
|
||||
given MAC address.ucBytes. If found, either of the two entries
|
||||
must be cleared. */
|
||||
xIpEntry = x;
|
||||
}
|
||||
else if( ( pxMACAddress != NULL ) && ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )
|
||||
{
|
||||
/* Found an entry with the given MAC-address, but the IP-address
|
||||
is different. Continue looping to find a possible match with
|
||||
ulIPAddress. */
|
||||
#if( ipconfigARP_STORES_REMOTE_ADDRESSES != 0 )
|
||||
/* If ARP stores the MAC address of IP addresses outside the
|
||||
network, than the MAC address of the gateway should not be
|
||||
overwritten. */
|
||||
BaseType_t bIsLocal[ 2 ];
|
||||
bIsLocal[ 0 ] = ( ( xARPCache[ x ].ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );
|
||||
bIsLocal[ 1 ] = ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );
|
||||
if( bIsLocal[ 0 ] == bIsLocal[ 1 ] )
|
||||
{
|
||||
xMacEntry = x;
|
||||
}
|
||||
#else
|
||||
xMacEntry = x;
|
||||
#endif
|
||||
}
|
||||
/* _HT_
|
||||
Shouldn't we test for xARPCache[ x ].ucValid == pdFALSE here ? */
|
||||
else if( xARPCache[ x ].ucAge < ucMinAgeFound )
|
||||
{
|
||||
/* As the table is traversed, remember the table row that
|
||||
contains the oldest entry (the lowest age count, as ages are
|
||||
decremented to zero) so the row can be re-used if this function
|
||||
needs to add an entry that does not already exist. */
|
||||
ucMinAgeFound = xARPCache[ x ].ucAge;
|
||||
xUseEntry = x;
|
||||
}
|
||||
}
|
||||
|
||||
if( xMacEntry >= 0 )
|
||||
{
|
||||
xUseEntry = xMacEntry;
|
||||
|
||||
if( xIpEntry >= 0 )
|
||||
{
|
||||
/* Both the MAC address as well as the IP address were found in
|
||||
different locations: clear the entry which matches the
|
||||
IP-address */
|
||||
memset( &xARPCache[ xIpEntry ], '\0', sizeof( xARPCache[ xIpEntry ] ) );
|
||||
}
|
||||
}
|
||||
else if( xIpEntry >= 0 )
|
||||
{
|
||||
/* An entry containing the IP-address was found, but it had a different MAC address */
|
||||
xUseEntry = xIpEntry;
|
||||
}
|
||||
|
||||
/* If the entry was not found, we use the oldest entry and set the IPaddress */
|
||||
xARPCache[ xUseEntry ].ulIPAddress = ulIPAddress;
|
||||
|
||||
if( pxMACAddress != NULL )
|
||||
{
|
||||
memcpy( xARPCache[ xUseEntry ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) );
|
||||
|
||||
iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, (*pxMACAddress) );
|
||||
/* And this entry does not need immediate attention */
|
||||
xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
|
||||
xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdTRUE;
|
||||
}
|
||||
else if( xIpEntry < 0 )
|
||||
{
|
||||
xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_RETRANSMISSIONS;
|
||||
xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdFALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigUSE_ARP_REVERSED_LOOKUP == 1 )
|
||||
eARPLookupResult_t eARPGetCacheEntryByMac( MACAddress_t * const pxMACAddress, uint32_t *pulIPAddress )
|
||||
{
|
||||
BaseType_t x;
|
||||
eARPLookupResult_t eReturn = eARPCacheMiss;
|
||||
|
||||
/* Loop through each entry in the ARP cache. */
|
||||
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
|
||||
{
|
||||
/* Does this row in the ARP cache table hold an entry for the MAC
|
||||
address being searched? */
|
||||
if( memcmp( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
|
||||
{
|
||||
*pulIPAddress = xARPCache[ x ].ulIPAddress;
|
||||
eReturn = eARPCacheHit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return eReturn;
|
||||
}
|
||||
#endif /* ipconfigUSE_ARP_REVERSED_LOOKUP */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * const pxMACAddress )
|
||||
{
|
||||
eARPLookupResult_t eReturn;
|
||||
uint32_t ulAddressToLookup;
|
||||
|
||||
#if( ipconfigUSE_LLMNR == 1 )
|
||||
if( *pulIPAddress == ipLLMNR_IP_ADDR ) /* Is in network byte order. */
|
||||
{
|
||||
/* The LLMNR IP-address has a fixed virtual MAC address. */
|
||||
memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) );
|
||||
eReturn = eARPCacheHit;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if( ( *pulIPAddress == ipBROADCAST_IP_ADDRESS ) || /* Is it the general broadcast address 255.255.255.255? */
|
||||
( *pulIPAddress == xNetworkAddressing.ulBroadcastAddress ) )/* Or a local broadcast address, eg 192.168.1.255? */
|
||||
{
|
||||
/* This is a broadcast so uses the broadcast MAC address. */
|
||||
memcpy( pxMACAddress->ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) );
|
||||
eReturn = eARPCacheHit;
|
||||
}
|
||||
else if( *ipLOCAL_IP_ADDRESS_POINTER == 0UL )
|
||||
{
|
||||
/* The IP address has not yet been assigned, so there is nothing that
|
||||
can be done. */
|
||||
eReturn = eCantSendPacket;
|
||||
}
|
||||
else
|
||||
{
|
||||
eReturn = eARPCacheMiss;
|
||||
|
||||
if( ( *pulIPAddress & xNetworkAddressing.ulNetMask ) != ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) )
|
||||
{
|
||||
#if( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 )
|
||||
eReturn = prvCacheLookup( *pulIPAddress, pxMACAddress );
|
||||
|
||||
if( eReturn == eARPCacheHit )
|
||||
{
|
||||
/* The stack is configured to store 'remote IP addresses', i.e. addresses
|
||||
belonging to a different the netmask. prvCacheLookup() returned a hit, so
|
||||
the MAC address is known */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The IP address is off the local network, so look up the
|
||||
hardware address of the router, if any. */
|
||||
if( xNetworkAddressing.ulGatewayAddress != ( uint32_t )0u )
|
||||
{
|
||||
ulAddressToLookup = xNetworkAddressing.ulGatewayAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulAddressToLookup = *pulIPAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The IP address is on the local network, so lookup the requested
|
||||
IP address directly. */
|
||||
ulAddressToLookup = *pulIPAddress;
|
||||
}
|
||||
|
||||
if( eReturn == eARPCacheMiss )
|
||||
{
|
||||
if( ulAddressToLookup == 0UL )
|
||||
{
|
||||
/* The address is not on the local network, and there is not a
|
||||
router. */
|
||||
eReturn = eCantSendPacket;
|
||||
}
|
||||
else
|
||||
{
|
||||
eReturn = prvCacheLookup( ulAddressToLookup, pxMACAddress );
|
||||
|
||||
if( eReturn == eARPCacheMiss )
|
||||
{
|
||||
/* It might be that the ARP has to go to the gateway. */
|
||||
*pulIPAddress = ulAddressToLookup;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress )
|
||||
{
|
||||
BaseType_t x;
|
||||
eARPLookupResult_t eReturn = eARPCacheMiss;
|
||||
|
||||
/* Loop through each entry in the ARP cache. */
|
||||
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
|
||||
{
|
||||
/* Does this row in the ARP cache table hold an entry for the IP address
|
||||
being queried? */
|
||||
if( xARPCache[ x ].ulIPAddress == ulAddressToLookup )
|
||||
{
|
||||
/* A matching valid entry was found. */
|
||||
if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE )
|
||||
{
|
||||
/* This entry is waiting an ARP reply, so is not valid. */
|
||||
eReturn = eCantSendPacket;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A valid entry was found. */
|
||||
memcpy( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) );
|
||||
eReturn = eARPCacheHit;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return eReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vARPAgeCache( void )
|
||||
{
|
||||
BaseType_t x;
|
||||
TickType_t xTimeNow;
|
||||
|
||||
/* Loop through each entry in the ARP cache. */
|
||||
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
|
||||
{
|
||||
/* If the entry is valid (its age is greater than zero). */
|
||||
if( xARPCache[ x ].ucAge > 0U )
|
||||
{
|
||||
/* Decrement the age value of the entry in this ARP cache table row.
|
||||
When the age reaches zero it is no longer considered valid. */
|
||||
( xARPCache[ x ].ucAge )--;
|
||||
|
||||
/* If the entry is not yet valid, then it is waiting an ARP
|
||||
reply, and the ARP request should be retransmitted. */
|
||||
if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE )
|
||||
{
|
||||
FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );
|
||||
}
|
||||
else if( xARPCache[ x ].ucAge <= ( uint8_t ) arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST )
|
||||
{
|
||||
/* This entry will get removed soon. See if the MAC address is
|
||||
still valid to prevent this happening. */
|
||||
iptraceARP_TABLE_ENTRY_WILL_EXPIRE( xARPCache[ x ].ulIPAddress );
|
||||
FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The age has just ticked down, with nothing to do. */
|
||||
}
|
||||
|
||||
if( xARPCache[ x ].ucAge == 0u )
|
||||
{
|
||||
/* The entry is no longer valid. Wipe it out. */
|
||||
iptraceARP_TABLE_ENTRY_EXPIRED( xARPCache[ x ].ulIPAddress );
|
||||
xARPCache[ x ].ulIPAddress = 0UL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xTimeNow = xTaskGetTickCount ();
|
||||
|
||||
if( ( xLastGratuitousARPTime == ( TickType_t ) 0 ) || ( ( xTimeNow - xLastGratuitousARPTime ) > ( TickType_t ) arpGRATUITOUS_ARP_PERIOD ) )
|
||||
{
|
||||
FreeRTOS_OutputARPRequest( *ipLOCAL_IP_ADDRESS_POINTER );
|
||||
xLastGratuitousARPTime = xTimeNow;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vARPSendGratuitous( void )
|
||||
{
|
||||
/* Setting xLastGratuitousARPTime to 0 will force a gratuitous ARP the next
|
||||
time vARPAgeCache() is called. */
|
||||
xLastGratuitousARPTime = ( TickType_t ) 0;
|
||||
|
||||
/* Let the IP-task call vARPAgeCache(). */
|
||||
xSendEventToIPTask( eARPTimerEvent );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress )
|
||||
{
|
||||
NetworkBufferDescriptor_t *pxNetworkBuffer;
|
||||
|
||||
/* This is called from the context of the IP event task, so a block time
|
||||
must not be used. */
|
||||
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( ARPPacket_t ), ( TickType_t ) 0 );
|
||||
|
||||
if( pxNetworkBuffer != NULL )
|
||||
{
|
||||
pxNetworkBuffer->ulIPAddress = ulIPAddress;
|
||||
vARPGenerateRequestPacket( pxNetworkBuffer );
|
||||
|
||||
#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
|
||||
{
|
||||
if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )
|
||||
{
|
||||
BaseType_t xIndex;
|
||||
|
||||
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
|
||||
{
|
||||
pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
|
||||
}
|
||||
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
|
||||
}
|
||||
}
|
||||
|
||||
void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
|
||||
{
|
||||
ARPPacket_t *pxARPPacket;
|
||||
|
||||
pxARPPacket = ( ARPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
|
||||
|
||||
/* memcpy the const part of the header information into the correct
|
||||
location in the packet. This copies:
|
||||
xEthernetHeader.ulDestinationAddress
|
||||
xEthernetHeader.usFrameType;
|
||||
xARPHeader.usHardwareType;
|
||||
xARPHeader.usProtocolType;
|
||||
xARPHeader.ucHardwareAddressLength;
|
||||
xARPHeader.ucProtocolAddressLength;
|
||||
xARPHeader.usOperation;
|
||||
xARPHeader.xTargetHardwareAddress;
|
||||
*/
|
||||
memcpy( ( void * ) &( pxARPPacket->xEthernetHeader ), ( void * ) xDefaultPartARPPacketHeader, sizeof( xDefaultPartARPPacketHeader ) );
|
||||
memcpy( ( void * ) pxARPPacket->xEthernetHeader.xSourceAddress.ucBytes , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
|
||||
memcpy( ( void * ) pxARPPacket->xARPHeader.xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
|
||||
|
||||
memcpy( ( void* )pxARPPacket->xARPHeader.ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPPacket->xARPHeader.ucSenderProtocolAddress ) );
|
||||
pxARPPacket->xARPHeader.ulTargetProtocolAddress = pxNetworkBuffer->ulIPAddress;
|
||||
|
||||
pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t );
|
||||
|
||||
iptraceCREATING_ARP_REQUEST( pxNetworkBuffer->ulIPAddress );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_ClearARP( void )
|
||||
{
|
||||
memset( xARPCache, '\0', sizeof( xARPCache ) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 )
|
||||
|
||||
void FreeRTOS_PrintARPCache( void )
|
||||
{
|
||||
BaseType_t x, xCount = 0;
|
||||
|
||||
/* Loop through each entry in the ARP cache. */
|
||||
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
|
||||
{
|
||||
if( ( xARPCache[ x ].ulIPAddress != 0ul ) && ( xARPCache[ x ].ucAge > 0U ) )
|
||||
{
|
||||
/* See if the MAC-address also matches, and we're all happy */
|
||||
FreeRTOS_printf( ( "Arp %2ld: %3u - %16lxip : %02x:%02x:%02x : %02x:%02x:%02x\n",
|
||||
x,
|
||||
xARPCache[ x ].ucAge,
|
||||
xARPCache[ x ].ulIPAddress,
|
||||
xARPCache[ x ].xMACAddress.ucBytes[0],
|
||||
xARPCache[ x ].xMACAddress.ucBytes[1],
|
||||
xARPCache[ x ].xMACAddress.ucBytes[2],
|
||||
xARPCache[ x ].xMACAddress.ucBytes[3],
|
||||
xARPCache[ x ].xMACAddress.ucBytes[4],
|
||||
xARPCache[ x ].xMACAddress.ucBytes[5] ) );
|
||||
xCount++;
|
||||
}
|
||||
}
|
||||
|
||||
FreeRTOS_printf( ( "Arp has %ld entries\n", xCount ) );
|
||||
}
|
||||
|
||||
#endif /* ( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
|
||||
1015
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
Normal file
1015
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
Normal file
File diff suppressed because it is too large
Load diff
1228
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
Normal file
1228
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
Normal file
File diff suppressed because it is too large
Load diff
2205
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
Normal file
2205
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
Normal file
File diff suppressed because it is too large
Load diff
3644
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c
Normal file
3644
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c
Normal file
File diff suppressed because it is too large
Load diff
231
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c
Normal file
231
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
|
||||
/*
|
||||
* uxStreamBufferAdd( )
|
||||
* Adds data to a stream buffer. If uxOffset > 0, data will be written at
|
||||
* an offset from uxHead while uxHead will not be moved yet. This possibility
|
||||
* will be used when TCP data is received while earlier data is still missing.
|
||||
* If 'pucData' equals NULL, the function is called to advance 'uxHead' only.
|
||||
*/
|
||||
size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount )
|
||||
{
|
||||
size_t uxSpace, uxNextHead, uxFirst;
|
||||
|
||||
uxSpace = uxStreamBufferGetSpace( pxBuffer );
|
||||
|
||||
/* If uxOffset > 0, items can be placed in front of uxHead */
|
||||
if( uxSpace > uxOffset )
|
||||
{
|
||||
uxSpace -= uxOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
uxSpace = 0u;
|
||||
}
|
||||
|
||||
/* The number of bytes that can be written is the minimum of the number of
|
||||
bytes requested and the number available. */
|
||||
uxCount = FreeRTOS_min_uint32( uxSpace, uxCount );
|
||||
|
||||
if( uxCount != 0u )
|
||||
{
|
||||
uxNextHead = pxBuffer->uxHead;
|
||||
|
||||
if( uxOffset != 0u )
|
||||
{
|
||||
/* ( uxOffset > 0 ) means: write in front if the uxHead marker */
|
||||
uxNextHead += uxOffset;
|
||||
if( uxNextHead >= pxBuffer->LENGTH )
|
||||
{
|
||||
uxNextHead -= pxBuffer->LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
if( pucData != NULL )
|
||||
{
|
||||
/* Calculate the number of bytes that can be added in the first
|
||||
write - which may be less than the total number of bytes that need
|
||||
to be added if the buffer will wrap back to the beginning. */
|
||||
uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextHead, uxCount );
|
||||
|
||||
/* Write as many bytes as can be written in the first write. */
|
||||
memcpy( ( void* ) ( pxBuffer->ucArray + uxNextHead ), pucData, uxFirst );
|
||||
|
||||
/* If the number of bytes written was less than the number that
|
||||
could be written in the first write... */
|
||||
if( uxCount > uxFirst )
|
||||
{
|
||||
/* ...then write the remaining bytes to the start of the
|
||||
buffer. */
|
||||
memcpy( ( void * )pxBuffer->ucArray, pucData + uxFirst, uxCount - uxFirst );
|
||||
}
|
||||
}
|
||||
|
||||
if( uxOffset == 0u )
|
||||
{
|
||||
/* ( uxOffset == 0 ) means: write at uxHead position */
|
||||
uxNextHead += uxCount;
|
||||
if( uxNextHead >= pxBuffer->LENGTH )
|
||||
{
|
||||
uxNextHead -= pxBuffer->LENGTH;
|
||||
}
|
||||
pxBuffer->uxHead = uxNextHead;
|
||||
}
|
||||
|
||||
if( xStreamBufferLessThenEqual( pxBuffer, pxBuffer->uxFront, uxNextHead ) != pdFALSE )
|
||||
{
|
||||
/* Advance the front pointer */
|
||||
pxBuffer->uxFront = uxNextHead;
|
||||
}
|
||||
}
|
||||
|
||||
return uxCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* uxStreamBufferGet( )
|
||||
* 'uxOffset' can be used to read data located at a certain offset from 'lTail'.
|
||||
* If 'pucData' equals NULL, the function is called to advance 'lTail' only.
|
||||
* if 'xPeek' is pdTRUE, or if 'uxOffset' is non-zero, the 'lTail' pointer will
|
||||
* not be advanced.
|
||||
*/
|
||||
size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek )
|
||||
{
|
||||
size_t uxSize, uxCount, uxFirst, uxNextTail;
|
||||
|
||||
/* How much data is available? */
|
||||
uxSize = uxStreamBufferGetSize( pxBuffer );
|
||||
|
||||
if( uxSize > uxOffset )
|
||||
{
|
||||
uxSize -= uxOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
uxSize = 0u;
|
||||
}
|
||||
|
||||
/* Use the minimum of the wanted bytes and the available bytes. */
|
||||
uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount );
|
||||
|
||||
if( uxCount > 0u )
|
||||
{
|
||||
uxNextTail = pxBuffer->uxTail;
|
||||
|
||||
if( uxOffset != 0u )
|
||||
{
|
||||
uxNextTail += uxOffset;
|
||||
if( uxNextTail >= pxBuffer->LENGTH )
|
||||
{
|
||||
uxNextTail -= pxBuffer->LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
if( pucData != NULL )
|
||||
{
|
||||
/* Calculate the number of bytes that can be read - which may be
|
||||
less than the number wanted if the data wraps around to the start of
|
||||
the buffer. */
|
||||
uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextTail, uxCount );
|
||||
|
||||
/* Obtain the number of bytes it is possible to obtain in the first
|
||||
read. */
|
||||
memcpy( pucData, pxBuffer->ucArray + uxNextTail, uxFirst );
|
||||
|
||||
/* If the total number of wanted bytes is greater than the number
|
||||
that could be read in the first read... */
|
||||
if( uxCount > uxFirst )
|
||||
{
|
||||
/*...then read the remaining bytes from the start of the buffer. */
|
||||
memcpy( pucData + uxFirst, pxBuffer->ucArray, uxCount - uxFirst );
|
||||
}
|
||||
}
|
||||
|
||||
if( ( xPeek == pdFALSE ) && ( uxOffset == 0UL ) )
|
||||
{
|
||||
/* Move the tail pointer to effecively remove the data read from
|
||||
the buffer. */
|
||||
uxNextTail += uxCount;
|
||||
|
||||
if( uxNextTail >= pxBuffer->LENGTH )
|
||||
{
|
||||
uxNextTail -= pxBuffer->LENGTH;
|
||||
}
|
||||
|
||||
pxBuffer->uxTail = uxNextTail;
|
||||
}
|
||||
}
|
||||
|
||||
return uxCount;
|
||||
}
|
||||
|
||||
3359
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
Normal file
3359
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
Normal file
File diff suppressed because it is too large
Load diff
2009
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
Normal file
2009
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
Normal file
File diff suppressed because it is too large
Load diff
420
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c
Normal file
420
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c
Normal file
|
|
@ -0,0 +1,420 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
#if( ipconfigUSE_DNS == 1 )
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#endif
|
||||
|
||||
/* The expected IP version and header length coded into the IP header itself. */
|
||||
#define ipIP_VERSION_AND_HEADER_LENGTH_BYTE ( ( uint8_t ) 0x45 )
|
||||
|
||||
/* Part of the Ethernet and IP headers are always constant when sending an IPv4
|
||||
UDP packet. This array defines the constant parts, allowing this part of the
|
||||
packet to be filled in using a simple memcpy() instead of individual writes. */
|
||||
UDPPacketHeader_t xDefaultPartUDPPacketHeader =
|
||||
{
|
||||
/* .ucBytes : */
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Ethernet source MAC address. */
|
||||
0x08, 0x00, /* Ethernet frame type. */
|
||||
ipIP_VERSION_AND_HEADER_LENGTH_BYTE, /* ucVersionHeaderLength. */
|
||||
0x00, /* ucDifferentiatedServicesCode. */
|
||||
0x00, 0x00, /* usLength. */
|
||||
0x00, 0x00, /* usIdentification. */
|
||||
0x00, 0x00, /* usFragmentOffset. */
|
||||
ipconfigUDP_TIME_TO_LIVE, /* ucTimeToLive */
|
||||
ipPROTOCOL_UDP, /* ucProtocol. */
|
||||
0x00, 0x00, /* usHeaderChecksum. */
|
||||
0x00, 0x00, 0x00, 0x00 /* Source IP address. */
|
||||
}
|
||||
};
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vProcessGeneratedUDPPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
|
||||
{
|
||||
UDPPacket_t *pxUDPPacket;
|
||||
IPHeader_t *pxIPHeader;
|
||||
eARPLookupResult_t eReturned;
|
||||
uint32_t ulIPAddress = pxNetworkBuffer->ulIPAddress;
|
||||
|
||||
/* Map the UDP packet onto the start of the frame. */
|
||||
pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
|
||||
|
||||
/* Determine the ARP cache status for the requested IP address. */
|
||||
eReturned = eARPGetCacheEntry( &( ulIPAddress ), &( pxUDPPacket->xEthernetHeader.xDestinationAddress ) );
|
||||
|
||||
if( eReturned != eCantSendPacket )
|
||||
{
|
||||
if( eReturned == eARPCacheHit )
|
||||
{
|
||||
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
|
||||
uint8_t ucSocketOptions;
|
||||
#endif
|
||||
iptraceSENDING_UDP_PACKET( pxNetworkBuffer->ulIPAddress );
|
||||
|
||||
/* Create short cuts to the data within the packet. */
|
||||
pxIPHeader = &( pxUDPPacket->xIPHeader );
|
||||
|
||||
#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
|
||||
/* Is it possible that the packet is not actually a UDP packet
|
||||
after all, but an ICMP packet. */
|
||||
if( pxNetworkBuffer->usPort != ipPACKET_CONTAINS_ICMP_DATA )
|
||||
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
|
||||
{
|
||||
UDPHeader_t *pxUDPHeader;
|
||||
|
||||
pxUDPHeader = &( pxUDPPacket->xUDPHeader );
|
||||
|
||||
pxUDPHeader->usDestinationPort = pxNetworkBuffer->usPort;
|
||||
pxUDPHeader->usSourcePort = pxNetworkBuffer->usBoundPort;
|
||||
pxUDPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( UDPHeader_t ) );
|
||||
pxUDPHeader->usLength = FreeRTOS_htons( pxUDPHeader->usLength );
|
||||
pxUDPHeader->usChecksum = 0u;
|
||||
}
|
||||
|
||||
/* memcpy() the constant parts of the header information into
|
||||
the correct location within the packet. This fills in:
|
||||
xEthernetHeader.xSourceAddress
|
||||
xEthernetHeader.usFrameType
|
||||
xIPHeader.ucVersionHeaderLength
|
||||
xIPHeader.ucDifferentiatedServicesCode
|
||||
xIPHeader.usLength
|
||||
xIPHeader.usIdentification
|
||||
xIPHeader.usFragmentOffset
|
||||
xIPHeader.ucTimeToLive
|
||||
xIPHeader.ucProtocol
|
||||
and
|
||||
xIPHeader.usHeaderChecksum
|
||||
*/
|
||||
|
||||
/* Save options now, as they will be overwritten by memcpy */
|
||||
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
|
||||
{
|
||||
ucSocketOptions = pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ];
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy( ( void *) &( pxUDPPacket->xEthernetHeader.xSourceAddress ), ( void * ) xDefaultPartUDPPacketHeader.ucBytes, sizeof( xDefaultPartUDPPacketHeader ) );
|
||||
|
||||
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
|
||||
if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA )
|
||||
{
|
||||
pxIPHeader->ucProtocol = ipPROTOCOL_ICMP;
|
||||
pxIPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( IPHeader_t ) );
|
||||
}
|
||||
else
|
||||
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
|
||||
{
|
||||
pxIPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( IPHeader_t ) + sizeof( UDPHeader_t ) );
|
||||
}
|
||||
|
||||
/* The total transmit size adds on the Ethernet header. */
|
||||
pxNetworkBuffer->xDataLength = pxIPHeader->usLength + sizeof( EthernetHeader_t );
|
||||
pxIPHeader->usLength = FreeRTOS_htons( pxIPHeader->usLength );
|
||||
pxIPHeader->ulDestinationIPAddress = pxNetworkBuffer->ulIPAddress;
|
||||
|
||||
#if( ipconfigUSE_LLMNR == 1 )
|
||||
{
|
||||
/* LLMNR messages are typically used on a LAN and they're
|
||||
* not supposed to cross routers */
|
||||
if( pxNetworkBuffer->ulIPAddress == ipLLMNR_IP_ADDR )
|
||||
{
|
||||
pxIPHeader->ucTimeToLive = 0x01;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
|
||||
{
|
||||
pxIPHeader->usHeaderChecksum = 0u;
|
||||
pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
|
||||
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
|
||||
|
||||
if( ( ucSocketOptions & ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT ) != 0u )
|
||||
{
|
||||
usGenerateProtocolChecksum( (uint8_t*)pxUDPPacket, pdTRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
pxUDPPacket->xUDPHeader.usChecksum = 0u;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if( eReturned == eARPCacheMiss )
|
||||
{
|
||||
/* Add an entry to the ARP table with a null hardware address.
|
||||
This allows the ARP timer to know that an ARP reply is
|
||||
outstanding, and perform retransmissions if necessary. */
|
||||
vARPRefreshCacheEntry( NULL, ulIPAddress );
|
||||
|
||||
/* Generate an ARP for the required IP address. */
|
||||
iptracePACKET_DROPPED_TO_GENERATE_ARP( pxNetworkBuffer->ulIPAddress );
|
||||
pxNetworkBuffer->ulIPAddress = ulIPAddress;
|
||||
vARPGenerateRequestPacket( pxNetworkBuffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The lookup indicated that an ARP request has already been
|
||||
sent out for the queried IP address. */
|
||||
eReturned = eCantSendPacket;
|
||||
}
|
||||
}
|
||||
|
||||
if( eReturned != eCantSendPacket )
|
||||
{
|
||||
/* The network driver is responsible for freeing the network buffer
|
||||
after the packet has been sent. */
|
||||
|
||||
#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
|
||||
{
|
||||
if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )
|
||||
{
|
||||
BaseType_t xIndex;
|
||||
|
||||
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
|
||||
{
|
||||
pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
|
||||
}
|
||||
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The packet can't be sent (DHCP not completed?). Just drop the
|
||||
packet. */
|
||||
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort )
|
||||
{
|
||||
BaseType_t xReturn = pdPASS;
|
||||
FreeRTOS_Socket_t *pxSocket;
|
||||
|
||||
UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
|
||||
|
||||
pxSocket = pxUDPSocketLookup( usPort );
|
||||
|
||||
if( pxSocket )
|
||||
{
|
||||
|
||||
/* When refreshing the ARP cache with received UDP packets we must be
|
||||
careful; hundreds of broadcast messages may pass and if we're not
|
||||
handling them, no use to fill the ARP cache with those IP addresses. */
|
||||
vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS == 1 )
|
||||
{
|
||||
/* Did the owner of this socket register a reception handler ? */
|
||||
if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleReceive ) )
|
||||
{
|
||||
struct freertos_sockaddr xSourceAddress, destinationAddress;
|
||||
void *pcData = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
|
||||
FOnUDPReceive_t xHandler = ( FOnUDPReceive_t ) pxSocket->u.xUDP.pxHandleReceive;
|
||||
xSourceAddress.sin_port = pxNetworkBuffer->usPort;
|
||||
xSourceAddress.sin_addr = pxNetworkBuffer->ulIPAddress;
|
||||
destinationAddress.sin_port = usPort;
|
||||
destinationAddress.sin_addr = pxUDPPacket->xIPHeader.ulDestinationIPAddress;
|
||||
|
||||
if( xHandler( ( Socket_t * ) pxSocket, ( void* ) pcData, ( size_t ) pxNetworkBuffer->xDataLength,
|
||||
&xSourceAddress, &destinationAddress ) != pdFALSE )
|
||||
{
|
||||
xReturn = pdFAIL; /* xHandler has consumed the data, do not add it to .xWaitingPacketsList'. */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigUSE_CALLBACKS */
|
||||
|
||||
#if( ipconfigUDP_MAX_RX_PACKETS > 0 )
|
||||
{
|
||||
if( xReturn == pdPASS )
|
||||
{
|
||||
if ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) >= pxSocket->u.xUDP.uxMaxPackets )
|
||||
{
|
||||
FreeRTOS_debug_printf( ( "xProcessReceivedUDPPacket: buffer full %ld >= %ld port %u\n",
|
||||
listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ),
|
||||
pxSocket->u.xUDP.uxMaxPackets, pxSocket->usLocalPort ) );
|
||||
xReturn = pdFAIL; /* we did not consume or release the buffer */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( xReturn == pdPASS )
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
if( xReturn == pdPASS )
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Add the network packet to the list of packets to be
|
||||
processed by the socket. */
|
||||
vListInsertEnd( &( pxSocket->u.xUDP.xWaitingPacketsList ), &( pxNetworkBuffer->xBufferListItem ) );
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
xTaskResumeAll();
|
||||
|
||||
/* Set the socket's receive event */
|
||||
if( pxSocket->xEventGroup != NULL )
|
||||
{
|
||||
xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
|
||||
}
|
||||
|
||||
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
|
||||
{
|
||||
if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) )
|
||||
{
|
||||
xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_READ );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
|
||||
{
|
||||
if( pxSocket->pxUserSemaphore != NULL )
|
||||
{
|
||||
xSemaphoreGive( pxSocket->pxUserSemaphore );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if( ipconfigUSE_DHCP == 1 )
|
||||
{
|
||||
if( xIsDHCPSocket( pxSocket ) )
|
||||
{
|
||||
xSendEventToIPTask( eDHCPEvent );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no socket listening to the target port, but still it might
|
||||
be for this node. */
|
||||
|
||||
#if( ipconfigUSE_DNS == 1 )
|
||||
/* A DNS reply, check for the source port. Although the DNS client
|
||||
does open a UDP socket to send a messages, this socket will be
|
||||
closed after a short timeout. Messages that come late (after the
|
||||
socket is closed) will be treated here. */
|
||||
if( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usSourcePort ) == ipDNS_PORT )
|
||||
{
|
||||
vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
|
||||
xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#if( ipconfigUSE_LLMNR == 1 )
|
||||
/* A LLMNR request, check for the destination port. */
|
||||
if( ( usPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) ||
|
||||
( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) )
|
||||
{
|
||||
vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
|
||||
xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer );
|
||||
}
|
||||
else
|
||||
#endif /* ipconfigUSE_LLMNR */
|
||||
|
||||
#if( ipconfigUSE_NBNS == 1 )
|
||||
/* a NetBIOS request, check for the destination port */
|
||||
if( ( usPort == FreeRTOS_ntohs( ipNBNS_PORT ) ) ||
|
||||
( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipNBNS_PORT ) ) )
|
||||
{
|
||||
vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
|
||||
xReturn = ( BaseType_t )ulNBNSHandlePacket( pxNetworkBuffer );
|
||||
}
|
||||
else
|
||||
#endif /* ipconfigUSE_NBNS */
|
||||
{
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
131
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/History.txt
Normal file
131
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/History.txt
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
Changes since the 160112 release
|
||||
|
||||
FTP : now has ipconfigFTP_HAS_USER_PROPERTIES_HOOK
|
||||
Each user can be assigned a different root directory and different access rights.
|
||||
Read-only access for FTP is now possible.
|
||||
|
||||
Adapted to comply a bit more to MISRA rules.
|
||||
The introduction of unsigned true/false, e.g. pdTRUE_UNSIGNED.
|
||||
|
||||
'ipBUFFER_PADDING' now configurable (expert option).
|
||||
|
||||
Added ipconfigFTP_HAS_USER_PROPERTIES_HOOK.
|
||||
ipconfigHAS_TX_CRC_OFFLOADING
|
||||
Improve support for read only file systems in the FTP server.
|
||||
|
||||
Depending on priorities: FreeRTOS_accept() could fail if the priority of the application task is higher than the priority of the IP-task. Now with a higher priority FreeRTOS_accept() will still work correctly.
|
||||
|
||||
Depending on the tick rate: A TCP socket could freeze (stop working) when the FreeRTOS tick rate was lower than 1,000 Hz. Now also tested with 100 Hz.
|
||||
|
||||
When "ipconfigZERO_COPY_TX_DRIVER = 0", sometime xNetworkInterfaceOutput() was called to send out a small TCP ACK. The network buffer would refer to space on the TCP socket ("lastPacket"), which was not 8-byte aligned. Repaired: from now on the buffer will have a proper 8-byte alignment.
|
||||
|
||||
"#if __cplusplus" is been replaced with the more proper test "#ifdef __cplusplus".
|
||||
|
||||
|
||||
|
||||
These are the recent commits:
|
||||
565 Initial check-in of +TCP/multi
|
||||
566 LPC18xx : updated and re-tested the TCP and FAT drivers
|
||||
569 +TCP : protocols: Added an installable application hook: "CheckDrivesHook"
|
||||
570 +TCP : will now work properly when configTICK_RATE_HZ < 1000
|
||||
571 +TCP : will now work properly when configTICK_RATE_HZ < 1000
|
||||
572 +TCP : FreeRTOS_recvfrom now recognises "FREERTOS_MSG_PEEK"
|
||||
573 +FAT : Zynq : writing may fail if it goes too fast. Introduced pauses but not yet satisfied
|
||||
|
||||
|
||||
Changes between 160112 and 160111 releases
|
||||
|
||||
+ Updated the STM32 network driver so checksums are calculated by the
|
||||
hardware.
|
||||
+ Implemented a simple "quit" command in the TCP command console.
|
||||
|
||||
Changes between 150825 and 160111 releases
|
||||
|
||||
+ New device support: Demo applications and example drivers are provided
|
||||
for Atmel SAM4E and ST STM32F4 microcontrollers.
|
||||
+ Various updates to improve compliance with the FreeRTOS coding standard.
|
||||
+ Added a command console example that uses TCP/IP for input and output (the
|
||||
pre-existing command console example uses UDP/IP).
|
||||
+ Updated the UDP logging example so it will send log messages to the local
|
||||
UDP broadcast address if a specific IP address is not provided. This
|
||||
simplifies configuration, but note not all switches and routers will pass
|
||||
broadcast messages.
|
||||
+ Add TCP echo client and TCP echo server examples to the Zynq demo.
|
||||
+ Minor updates to the Zynq network driver.
|
||||
+ Update the Zynq project to use version 2015.4 of the Xilinx SDK.
|
||||
+ Introduce FreeRTOS_SignalSocket(), which can be used to interrupt a task
|
||||
that is blocked while reading from a socket ( FreeRTOS_recv[from] ).
|
||||
+ Make use of FreeRTOS_SignalSocket() in the FTP and HTTP servers.
|
||||
+ Major updates to the NTP client, although this is not included in any of
|
||||
the pre-configured demo applications yet.
|
||||
+ Added support for DHCP zero pad option.
|
||||
+ Added uxGetMinimumIPQueueSpace(), a function to monitor the minimum amount
|
||||
of space on the message queue.
|
||||
+ Better handling of zero length files in the FTP server.
|
||||
+ Fixed a bug reported by Andrey Ivanov from swissEmbedded that affects
|
||||
users of 'ipconfigZERO_COPY_TX_DRIVER'.
|
||||
|
||||
|
||||
Changes between 150825 150825 (?)
|
||||
|
||||
+ Added xApplicationDHCPUserHook() so a user defined hook will be
|
||||
called at certain points in the DHCP process if
|
||||
ipconfigDHCP_USES_USER_HOOK is set to 1.
|
||||
+ Added FreeRTOS_get_tx_head() to improve TCP zero copy behaviour - for
|
||||
expert use only.
|
||||
+ RST is no longer sent if only the ACK flag is set.
|
||||
+ Previously, an immediate ACK was only sent when buffer space was
|
||||
exhausted. Now, to improve performance, it is possible to send an
|
||||
immediate ACK earlier - dependent on the ipconfigTCP_ACK_EARLIER_PACKET
|
||||
setting.
|
||||
+ LLMNR and NBNS requests can now be sent to locate other devices -
|
||||
previously these protocols would only be replied to, not generated.
|
||||
+ Added Auto-IP functionality (still in test) in case DHCP fails. Dependent
|
||||
on the ipconfigDHCP_FALL_BACK_LINK_LAYER_ADDRESS and
|
||||
ipconfigARP_USE_CLASH_DETECTION settings.
|
||||
+ Added NTP code and demo.
|
||||
+ FTP can now STOR and RETR zero-length files.
|
||||
+ Added LLMNR demo to Win32 demo - so now the Win32 responds to
|
||||
"ping RTOSDemo".
|
||||
|
||||
Changes between 141019 and 150825
|
||||
|
||||
+ Added FTP server, which uses the new FreeRTOS+FAT component.
|
||||
+ Added basic HTTP server, which uses the new FreeRTOS+FAT component.
|
||||
+ Multiple definitions that are now common with FreeRTOS+FAT have been moved
|
||||
into FreeRTOS's ProjDefs.h header file, and so prefixed with 'pd'.
|
||||
+ Introduced ipconfigZERO_COPY_TX_DRIVER, which defines who is responsible
|
||||
for freeing a buffer sent to to the MAC driver for transmission, and
|
||||
facilitates the development of zero copy drivers.
|
||||
+ Introduced the FREERTOS_MSG_DONTWAIT flag. The flag can be used as a
|
||||
simpler and faster alternative to using FreeRTOS_setsockopt() to set the
|
||||
send or receive timeout to 0.
|
||||
+ A few functions that were previously all lower case are now mixed case, as
|
||||
lower case function names are only used when they are equivalent to a
|
||||
a Berkeley sockets API function of the same name.
|
||||
+ Introduced uxGetMinimumFreeNetworkBuffers() to return the minimum number
|
||||
of network buffers that have ever existed since the application started
|
||||
executing.
|
||||
+ Introduce ipconfigETHERNET_MINIMUM_PACKET_BYTES to allow the application
|
||||
writer to set their own minimum buffer size should the hardware not be
|
||||
capable of padding under-sized Ethernet frames.
|
||||
+ vNetworkBufferRelease() renamed vReleaseNetworkBuffer() - just for
|
||||
consistency with the names of other functions in the same file.
|
||||
+ Grouped DHCP status data into a structure.
|
||||
+ DHCP is now tried both with and without the broadcast flag.
|
||||
+ Replaced occurrences of configASSERT_VOID() with configASSERT().
|
||||
+ ipconfigDNS_USE_CALLBACKS introduced to allow FreeRTOS_gethostbyname() to
|
||||
be used without blocking.
|
||||
+ Fix: LLMNR and NBNS behaviour when the reply is in a larger buffer than the
|
||||
request, and BufferAllocation_2 was used.
|
||||
+ Introduced ipMAX_IP_TASK_SLEEP_TIME to allow the application writer to
|
||||
override the default value of 10 seconds.
|
||||
+ Fix: Correct error in *pxUDPPayloadBuffer_to_NetworkBuffer().
|
||||
+ FreeRTOS_recv() now recognises the FREERTOS_ZERO_COPY flag, which, when
|
||||
set, the void *pvBuffer parameter is interpreted as void **pvBuffer.
|
||||
+ FreeRTOS_listen() now returns an error code. Previously it always
|
||||
returned 0.
|
||||
+ Fix: Previously if a listening socket was reused, and a connection
|
||||
failed, the TCP/IP stack closed the socket, now the socket is correctly
|
||||
left unclosed as it is owned by the application.
|
||||
+ Various other formatting and minor fix alterations.
|
||||
5
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/ReadMe.url
Normal file
5
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/ReadMe.url
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,2
|
||||
[InternetShortcut]
|
||||
URL=http://www.freertos.org/tcp
|
||||
IDList=
|
||||
|
|
@ -0,0 +1,577 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_DEFAULT_IP_CONFIG_H
|
||||
#define FREERTOS_DEFAULT_IP_CONFIG_H
|
||||
|
||||
/* The error numbers defined in this file will be moved to the core FreeRTOS
|
||||
code in future versions of FreeRTOS - at which time the following header file
|
||||
will be removed. */
|
||||
#include "FreeRTOS_errno_TCP.h"
|
||||
|
||||
/* This file provides default values for configuration options that are missing
|
||||
from the FreeRTOSIPConfig.h configuration header file. */
|
||||
|
||||
|
||||
/* Ensure defined configuration constants are using the most up to date naming. */
|
||||
#ifdef tcpconfigIP_TIME_TO_LIVE
|
||||
#error now called: ipconfigTCP_TIME_TO_LIVE
|
||||
#endif
|
||||
|
||||
#ifdef updconfigIP_TIME_TO_LIVE
|
||||
#error now called: ipconfigUDP_TIME_TO_LIVE
|
||||
#endif
|
||||
|
||||
#ifdef ipFILLER_SIZE
|
||||
#error now called: ipconfigPACKET_FILLER_SIZE
|
||||
#endif
|
||||
|
||||
#ifdef dnsMAX_REQUEST_ATTEMPTS
|
||||
#error now called: ipconfigDNS_REQUEST_ATTEMPTS
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigUDP_TASK_PRIORITY
|
||||
#error now called: ipconfigIP_TASK_PRIORITY
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigUDP_TASK_STACK_SIZE_WORDS
|
||||
#error now called: ipconfigIP_TASK_STACK_SIZE_WORDS
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigDRIVER_INCLUDED_RX_IP_FILTERING
|
||||
#error now called: ipconfigETHERNET_DRIVER_FILTERS_PACKETS
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigMAX_SEND_BLOCK_TIME_TICKS
|
||||
#error now called: ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigUSE_RECEIVE_CONNECT_CALLBACKS
|
||||
#error now called: ipconfigUSE_CALLBACKS
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigNUM_NETWORK_BUFFERS
|
||||
#error now called: ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigTCP_HANG_PROT
|
||||
#error now called: ipconfigTCP_HANG_PROTECTION
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigTCP_HANG_PROT_TIME
|
||||
#error now called: ipconfigTCP_HANG_PROTECTION_TIME
|
||||
#endif
|
||||
|
||||
#ifdef FreeRTOS_lprintf
|
||||
#error now called: FreeRTOS_debug_printf
|
||||
#endif
|
||||
|
||||
#if ( ipconfigEVENT_QUEUE_LENGTH < ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 ) )
|
||||
#error The ipconfigEVENT_QUEUE_LENGTH parameter must be at least ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5
|
||||
#endif
|
||||
|
||||
#if ( ipconfigNETWORK_MTU < 46 )
|
||||
#error ipconfigNETWORK_MTU must be at least 46.
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigBUFFER_ALLOC_FIXED_SIZE
|
||||
#error ipconfigBUFFER_ALLOC_FIXED_SIZE was dropped and replaced by a const value, declared in BufferAllocation[12].c
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigNIC_SEND_PASSES_DMA
|
||||
#error now called: ipconfigZERO_COPY_TX_DRIVER
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TX_CRC_OFFLOADING
|
||||
/* _HT_ As these macro names have changed, throw an error
|
||||
if they're still defined. */
|
||||
#error now called: ipconfigHAS_TX_CRC_OFFLOADING
|
||||
#endif
|
||||
|
||||
#ifdef HAS_RX_CRC_OFFLOADING
|
||||
#error now called: ipconfigHAS_RX_CRC_OFFLOADING
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigTCP_RX_BUF_LEN
|
||||
#error ipconfigTCP_RX_BUF_LEN is now called ipconfigTCP_RX_BUFFER_LENGTH
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigTCP_TX_BUF_LEN
|
||||
#error ipconfigTCP_TX_BUF_LEN is now called ipconfigTCP_TX_BUFFER_LENGTH
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigDHCP_USES_USER_HOOK
|
||||
#error ipconfigDHCP_USES_USER_HOOK and its associated callback have been superceeded - see http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUSE_TCP
|
||||
#define ipconfigUSE_TCP ( 1 )
|
||||
#endif
|
||||
|
||||
#if ipconfigUSE_TCP
|
||||
|
||||
/* Include support for TCP scaling windows */
|
||||
#ifndef ipconfigUSE_TCP_WIN
|
||||
#define ipconfigUSE_TCP_WIN ( 1 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigTCP_WIN_SEG_COUNT
|
||||
#define ipconfigTCP_WIN_SEG_COUNT ( 256 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigIGNORE_UNKNOWN_PACKETS
|
||||
/* When non-zero, TCP will not send RST packets in reply to
|
||||
TCP packets which are unknown, or out-of-order. */
|
||||
#define ipconfigIGNORE_UNKNOWN_PACKETS ( 0 )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For debuging/logging: check if the port number is used for telnet
|
||||
* Some events will not be logged for telnet connections
|
||||
* because it would produce logging about the transmission of the logging...
|
||||
* This macro will only be used if FreeRTOS_debug_printf() is defined for logging
|
||||
*/
|
||||
#ifndef ipconfigTCP_MAY_LOG_PORT
|
||||
#define ipconfigTCP_MAY_LOG_PORT(xPort) ( ( xPort ) != 23u )
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME
|
||||
#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME portMAX_DELAY
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME
|
||||
#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME portMAX_DELAY
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FreeRTOS debug logging routine (proposal)
|
||||
* The macro will be called in the printf() style. Users can define
|
||||
* their own logging routine as:
|
||||
*
|
||||
* #define FreeRTOS_debug_printf( MSG ) my_printf MSG
|
||||
*
|
||||
* The FreeRTOS_debug_printf() must be thread-safe but does not have to be
|
||||
* interrupt-safe.
|
||||
*/
|
||||
#ifdef ipconfigHAS_DEBUG_PRINTF
|
||||
#if( ipconfigHAS_DEBUG_PRINTF == 0 )
|
||||
#ifdef FreeRTOS_debug_printf
|
||||
#error Do not define FreeRTOS_debug_print if ipconfigHAS_DEBUG_PRINTF is set to 0
|
||||
#endif /* ifdef FreeRTOS_debug_printf */
|
||||
#endif /* ( ipconfigHAS_DEBUG_PRINTF == 0 ) */
|
||||
#endif /* ifdef ipconfigHAS_DEBUG_PRINTF */
|
||||
|
||||
#ifndef FreeRTOS_debug_printf
|
||||
#define FreeRTOS_debug_printf( MSG ) do{} while(0)
|
||||
#define ipconfigHAS_DEBUG_PRINTF 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FreeRTOS general logging routine (proposal)
|
||||
* Used in some utility functions such as FreeRTOS_netstat() and FreeRTOS_PrintARPCache()
|
||||
*
|
||||
* #define FreeRTOS_printf( MSG ) my_printf MSG
|
||||
*
|
||||
* The FreeRTOS_printf() must be thread-safe but does not have to be interrupt-safe
|
||||
*/
|
||||
#ifdef ipconfigHAS_PRINTF
|
||||
#if( ipconfigHAS_PRINTF == 0 )
|
||||
#ifdef FreeRTOS_printf
|
||||
#error Do not define FreeRTOS_print if ipconfigHAS_PRINTF is set to 0
|
||||
#endif /* ifdef FreeRTOS_debug_printf */
|
||||
#endif /* ( ipconfigHAS_PRINTF == 0 ) */
|
||||
#endif /* ifdef ipconfigHAS_PRINTF */
|
||||
|
||||
#ifndef FreeRTOS_printf
|
||||
#define FreeRTOS_printf( MSG ) do{} while(0)
|
||||
#define ipconfigHAS_PRINTF 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In cases where a lot of logging is produced, FreeRTOS_flush_logging( )
|
||||
* will be called to give the logging module a chance to flush the data
|
||||
* An example of this is the netstat command, which produces many lines of logging
|
||||
*/
|
||||
#ifndef FreeRTOS_flush_logging
|
||||
#define FreeRTOS_flush_logging( ) do{} while(0)
|
||||
#endif
|
||||
|
||||
/* Malloc functions. Within most applications of FreeRTOS, the couple
|
||||
* pvPortMalloc()/vPortFree() will be used.
|
||||
* If there is also SDRAM, the user may decide to use a different memory
|
||||
* allocator:
|
||||
* MallocLarge is used to allocate large TCP buffers (for Rx/Tx)
|
||||
* MallocSocket is used to allocate the space for the sockets
|
||||
*/
|
||||
#ifndef pvPortMallocLarge
|
||||
#define pvPortMallocLarge( x ) pvPortMalloc( x )
|
||||
#endif
|
||||
|
||||
#ifndef vPortFreeLarge
|
||||
#define vPortFreeLarge(ptr) vPortFree(ptr)
|
||||
#endif
|
||||
|
||||
#ifndef pvPortMallocSocket
|
||||
#define pvPortMallocSocket( x ) pvPortMalloc( x )
|
||||
#endif
|
||||
|
||||
#ifndef vPortFreeSocket
|
||||
#define vPortFreeSocket(ptr) vPortFree(ptr)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* At several places within the library, random numbers are needed:
|
||||
* - DHCP: For creating a DHCP transaction number
|
||||
* - TCP: Set the Initial Sequence Number: this is the value of the first outgoing
|
||||
* sequence number being used when connecting to a peer.
|
||||
* Having a well randomised ISN is important to avoid spoofing
|
||||
* - UDP/TCP: for setting the first port number to be used, in case a socket
|
||||
* uses a 'random' or anonymous port number
|
||||
*/
|
||||
#ifndef ipconfigRAND32
|
||||
#define ipconfigRAND32() rand()
|
||||
#endif
|
||||
/* --------------------------------------------------------
|
||||
* End of: HT Added some macro defaults for the PLUS-UDP project
|
||||
* -------------------------------------------------------- */
|
||||
|
||||
#ifndef ipconfigUSE_NETWORK_EVENT_HOOK
|
||||
#define ipconfigUSE_NETWORK_EVENT_HOOK 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS
|
||||
#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( pdMS_TO_TICKS( 20 ) )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigARP_CACHE_ENTRIES
|
||||
#define ipconfigARP_CACHE_ENTRIES 10
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigMAX_ARP_RETRANSMISSIONS
|
||||
#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5u )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigMAX_ARP_AGE
|
||||
#define ipconfigMAX_ARP_AGE 150u
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUSE_ARP_REVERSED_LOOKUP
|
||||
#define ipconfigUSE_ARP_REVERSED_LOOKUP 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUSE_ARP_REMOVE_ENTRY
|
||||
#define ipconfigUSE_ARP_REMOVE_ENTRY 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigINCLUDE_FULL_INET_ADDR
|
||||
#define ipconfigINCLUDE_FULL_INET_ADDR 1
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS
|
||||
#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 45
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigEVENT_QUEUE_LENGTH
|
||||
#define ipconfigEVENT_QUEUE_LENGTH ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND
|
||||
#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUDP_TIME_TO_LIVE
|
||||
#define ipconfigUDP_TIME_TO_LIVE 128
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigTCP_TIME_TO_LIVE
|
||||
#define ipconfigTCP_TIME_TO_LIVE 128
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUDP_MAX_RX_PACKETS
|
||||
/* Make postive to define the maximum number of packets which will be buffered
|
||||
* for each UDP socket.
|
||||
* Can be overridden with the socket option FREERTOS_SO_UDP_MAX_RX_PACKETS
|
||||
*/
|
||||
#define ipconfigUDP_MAX_RX_PACKETS 0u
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUSE_DHCP
|
||||
#define ipconfigUSE_DHCP 1
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUSE_DHCP_HOOK
|
||||
#define ipconfigUSE_DHCP_HOOK 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigDHCP_FALL_BACK_AUTO_IP
|
||||
/*
|
||||
* Only applicable when DHCP is in use:
|
||||
* If no DHCP server responds, use "Auto-IP" : the
|
||||
* device will allocate a random LinkLayer IP address.
|
||||
*/
|
||||
#define ipconfigDHCP_FALL_BACK_AUTO_IP ( 0 )
|
||||
#endif
|
||||
|
||||
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
|
||||
#define ipconfigARP_USE_CLASH_DETECTION 1
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigARP_USE_CLASH_DETECTION
|
||||
#define ipconfigARP_USE_CLASH_DETECTION 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigNETWORK_MTU
|
||||
#define ipconfigNETWORK_MTU 1500
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigTCP_MSS
|
||||
#define ipconfigTCP_MSS ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_TCP_HEADER )
|
||||
#endif
|
||||
|
||||
/* Each TCP socket has circular stream buffers for Rx and Tx, which
|
||||
* have a fixed maximum size.
|
||||
* The defaults for these size are defined here, although
|
||||
* they can be overridden at runtime by using the setsockopt() call */
|
||||
#ifndef ipconfigTCP_RX_BUFFER_LENGTH
|
||||
#define ipconfigTCP_RX_BUFFER_LENGTH ( 4u * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
|
||||
#endif
|
||||
|
||||
/* Define the size of Tx stream buffer for TCP sockets */
|
||||
#ifndef ipconfigTCP_TX_BUFFER_LENGTH
|
||||
# define ipconfigTCP_TX_BUFFER_LENGTH ( 4u * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigMAXIMUM_DISCOVER_TX_PERIOD
|
||||
#ifdef _WINDOWS_
|
||||
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 999 ) )
|
||||
#else
|
||||
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 30000 ) )
|
||||
#endif /* _WINDOWS_ */
|
||||
#endif /* ipconfigMAXIMUM_DISCOVER_TX_PERIOD */
|
||||
|
||||
#ifndef ipconfigUSE_DNS
|
||||
#define ipconfigUSE_DNS 1
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigDNS_REQUEST_ATTEMPTS
|
||||
#define ipconfigDNS_REQUEST_ATTEMPTS 5
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUSE_DNS_CACHE
|
||||
#define ipconfigUSE_DNS_CACHE 0
|
||||
#endif
|
||||
|
||||
#if( ipconfigUSE_DNS_CACHE != 0 )
|
||||
#ifndef ipconfigDNS_CACHE_NAME_LENGTH
|
||||
#define ipconfigDNS_CACHE_NAME_LENGTH ( 16 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigDNS_CACHE_ENTRIES
|
||||
#define ipconfigDNS_CACHE_ENTRIES 0
|
||||
#endif
|
||||
#endif /* ipconfigUSE_DNS_CACHE != 0 */
|
||||
|
||||
#ifndef ipconfigCHECK_IP_QUEUE_SPACE
|
||||
#define ipconfigCHECK_IP_QUEUE_SPACE 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUSE_LLMNR
|
||||
/* Include support for LLMNR: Link-local Multicast Name Resolution (non-Microsoft) */
|
||||
#define ipconfigUSE_LLMNR ( 0 )
|
||||
#endif
|
||||
|
||||
#if( !defined( ipconfigUSE_DNS ) )
|
||||
#if( ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) )
|
||||
/* LLMNR and NBNS depend on DNS because those protocols share a lot of code. */
|
||||
#error When either LLMNR or NBNS is used, ipconfigUSE_DNS must be defined
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigREPLY_TO_INCOMING_PINGS
|
||||
#define ipconfigREPLY_TO_INCOMING_PINGS 1
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigSUPPORT_OUTGOING_PINGS
|
||||
#define ipconfigSUPPORT_OUTGOING_PINGS 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 ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM
|
||||
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ( 0 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigETHERNET_DRIVER_FILTERS_PACKETS
|
||||
#define ipconfigETHERNET_DRIVER_FILTERS_PACKETS ( 0 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigWATCHDOG_TIMER
|
||||
/* This macro will be called in every loop the IP-task makes. It may be
|
||||
replaced by user-code that triggers a watchdog */
|
||||
#define ipconfigWATCHDOG_TIMER()
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUSE_CALLBACKS
|
||||
#define ipconfigUSE_CALLBACKS ( 0 )
|
||||
#endif
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
#ifndef ipconfigIS_VALID_PROG_ADDRESS
|
||||
/* Replace this macro with a test returning non-zero if the memory pointer to by x
|
||||
* is valid memory which can contain executable code
|
||||
* In fact this is an extra safety measure: if a handler points to invalid memory,
|
||||
* it will not be called
|
||||
*/
|
||||
#define ipconfigIS_VALID_PROG_ADDRESS(x) ( ( x ) != NULL )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigHAS_INLINE_FUNCTIONS
|
||||
#define ipconfigHAS_INLINE_FUNCTIONS ( 1 )
|
||||
#endif
|
||||
|
||||
#ifndef portINLINE
|
||||
#define portINLINE inline
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigZERO_COPY_TX_DRIVER
|
||||
/* When non-zero, the buffers passed to the SEND routine may be passed
|
||||
to DMA. As soon as sending is ready, the buffers must be released by
|
||||
calling vReleaseNetworkBufferAndDescriptor(), */
|
||||
#define ipconfigZERO_COPY_TX_DRIVER ( 0 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigZERO_COPY_RX_DRIVER
|
||||
/* This define doesn't mean much to the driver, except that it makes
|
||||
sure that pxPacketBuffer_to_NetworkBuffer() will be included. */
|
||||
#define ipconfigZERO_COPY_RX_DRIVER ( 0 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM
|
||||
#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM
|
||||
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigDHCP_REGISTER_HOSTNAME
|
||||
#define ipconfigDHCP_REGISTER_HOSTNAME 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigSOCKET_HAS_USER_SEMAPHORE
|
||||
#define ipconfigSOCKET_HAS_USER_SEMAPHORE 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigSUPPORT_SELECT_FUNCTION
|
||||
#define ipconfigSUPPORT_SELECT_FUNCTION 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigTCP_KEEP_ALIVE
|
||||
#define ipconfigTCP_KEEP_ALIVE 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigDNS_USE_CALLBACKS
|
||||
#define ipconfigDNS_USE_CALLBACKS 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigSUPPORT_SIGNALS
|
||||
#define ipconfigSUPPORT_SIGNALS 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigUSE_NBNS
|
||||
#define ipconfigUSE_NBNS 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigTCP_HANG_PROTECTION
|
||||
#define ipconfigTCP_HANG_PROTECTION 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigTCP_IP_SANITY
|
||||
#define ipconfigTCP_IP_SANITY 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigARP_STORES_REMOTE_ADDRESSES
|
||||
#define ipconfigARP_STORES_REMOTE_ADDRESSES 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigBUFFER_PADDING
|
||||
/* Expert option: define a value for 'ipBUFFER_PADDING'.
|
||||
When 'ipconfigBUFFER_PADDING' equals 0,
|
||||
'ipBUFFER_PADDING' will get a default value of 8 + 2 bytes. */
|
||||
#define ipconfigBUFFER_PADDING 0
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigPACKET_FILLER_SIZE
|
||||
#define ipconfigPACKET_FILLER_SIZE 2
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_DEFAULT_IP_CONFIG_H */
|
||||
173
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h
Normal file
173
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_ARP_H
|
||||
#define FREERTOS_ARP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Application level configuration options. */
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
#include "FreeRTOSIPConfigDefaults.h"
|
||||
#include "IPTraceMacroDefaults.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Miscellaneous structure and definitions. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
typedef struct xARP_CACHE_TABLE_ROW
|
||||
{
|
||||
uint32_t ulIPAddress; /* The IP address of an ARP cache entry. */
|
||||
MACAddress_t xMACAddress; /* The MAC address of an ARP cache entry. */
|
||||
uint8_t ucAge; /* A value that is periodically decremented but can also be refreshed by active communication. The ARP cache entry is removed if the value reaches zero. */
|
||||
uint8_t ucValid; /* pdTRUE: xMACAddress is valid, pdFALSE: waiting for ARP reply */
|
||||
} ARPCacheRow_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eARPCacheMiss = 0, /* 0 An ARP table lookup did not find a valid entry. */
|
||||
eARPCacheHit, /* 1 An ARP table lookup found a valid entry. */
|
||||
eCantSendPacket /* 2 There is no IP address, or an ARP is still in progress, so the packet cannot be sent. */
|
||||
} eARPLookupResult_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eNotFragment = 0, /* The IP packet being sent is not part of a fragment. */
|
||||
eFirstFragment, /* The IP packet being sent is the first in a set of fragmented packets. */
|
||||
eFollowingFragment /* The IP packet being sent is part of a set of fragmented packets. */
|
||||
} eIPFragmentStatus_t;
|
||||
|
||||
/*
|
||||
* If ulIPAddress is already in the ARP cache table then reset the age of the
|
||||
* entry back to its maximum value. If ulIPAddress is not already in the ARP
|
||||
* cache table then add it - replacing the oldest current entry if there is not
|
||||
* a free space available.
|
||||
*/
|
||||
void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress, const uint32_t ulIPAddress );
|
||||
|
||||
#if( ipconfigARP_USE_CLASH_DETECTION != 0 )
|
||||
/* Becomes non-zero if another device responded to a gratuitos ARP message. */
|
||||
extern BaseType_t xARPHadIPClash;
|
||||
/* MAC-address of the other device containing the same IP-address. */
|
||||
extern MACAddress_t xARPClashMacAddress;
|
||||
#endif /* ipconfigARP_USE_CLASH_DETECTION */
|
||||
|
||||
#if( ipconfigUSE_ARP_REMOVE_ENTRY != 0 )
|
||||
|
||||
/*
|
||||
* In some rare cases, it might be useful to remove a ARP cache entry of a
|
||||
* known MAC address to make sure it gets refreshed.
|
||||
*/
|
||||
uint32_t ulARPRemoveCacheEntryByMac( const MACAddress_t * pxMACAddress );
|
||||
|
||||
#endif /* ipconfigUSE_ARP_REMOVE_ENTRY != 0 */
|
||||
|
||||
/*
|
||||
* Look for ulIPAddress in the ARP cache. If the IP address exists, copy the
|
||||
* associated MAC address into pxMACAddress, refresh the ARP cache entry's
|
||||
* age, and return eARPCacheHit. If the IP address does not exist in the ARP
|
||||
* cache return eARPCacheMiss. If the packet cannot be sent for any reason
|
||||
* (maybe DHCP is still in process, or the addressing needs a gateway but there
|
||||
* isn't a gateway defined) then return eCantSendPacket.
|
||||
*/
|
||||
eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * const pxMACAddress );
|
||||
|
||||
#if( ipconfigUSE_ARP_REVERSED_LOOKUP != 0 )
|
||||
|
||||
/* Lookup an IP-address if only the MAC-address is known */
|
||||
eARPLookupResult_t eARPGetCacheEntryByMac( MACAddress_t * const pxMACAddress, uint32_t *pulIPAddress );
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Reduce the age count in each entry within the ARP cache. An entry is no
|
||||
* longer considered valid and is deleted if its age reaches zero.
|
||||
*/
|
||||
void vARPAgeCache( void );
|
||||
|
||||
/*
|
||||
* Send out an ARP request for the IP address contained in pxNetworkBuffer, and
|
||||
* add an entry into the ARP table that indicates that an ARP reply is
|
||||
* outstanding so re-transmissions can be generated.
|
||||
*/
|
||||
void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );
|
||||
|
||||
/*
|
||||
* After DHCP is ready and when changing IP address, force a quick send of our new IP
|
||||
* address
|
||||
*/
|
||||
void vARPSendGratuitous( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_ARP_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
119
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h
Normal file
119
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_DHCP_H
|
||||
#define FREERTOS_DHCP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Application level configuration options. */
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
#include "IPTraceMacroDefaults.h"
|
||||
|
||||
/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
|
||||
typedef enum eDHCP_PHASE
|
||||
{
|
||||
eDHCPPhasePreDiscover, /* Driver is about to send a DHCP discovery. */
|
||||
eDHCPPhasePreRequest, /* Driver is about to request DHCP an IP address. */
|
||||
#if( ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP != 0 )
|
||||
eDHCPPhasePreLLA, /* Driver is about to try get an LLA address */
|
||||
#endif /* ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP */
|
||||
} eDHCPCallbackPhase_t;
|
||||
|
||||
/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
|
||||
typedef enum eDHCP_ANSWERS
|
||||
{
|
||||
eDHCPContinue, /* Continue the DHCP process */
|
||||
eDHCPUseDefaults, /* Stop DHCP and use the static defaults. */
|
||||
eDHCPStopNoChanges, /* Stop DHCP and continue with current settings. */
|
||||
} eDHCPCallbackAnswer_t;
|
||||
|
||||
/*
|
||||
* NOT A PUBLIC API FUNCTION.
|
||||
*/
|
||||
void vDHCPProcess( BaseType_t xReset );
|
||||
|
||||
/* Internal call: returns true if socket is the current DHCP socket */
|
||||
BaseType_t xIsDHCPSocket( Socket_t xSocket );
|
||||
|
||||
/* Prototype of the hook (or callback) function that must be provided by the
|
||||
application if ipconfigUSE_DHCP_HOOK is set to 1. See the following URL for
|
||||
usage information:
|
||||
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK
|
||||
*/
|
||||
eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase, uint32_t ulIPAddress );
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_DHCP_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
165
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h
Normal file
165
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_DNS_H
|
||||
#define FREERTOS_DNS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Application level configuration options. */
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
#include "IPTraceMacroDefaults.h"
|
||||
|
||||
|
||||
/* The Link-local Multicast Name Resolution (LLMNR)
|
||||
* is included.
|
||||
* Note that a special MAC address is required in addition to the NIC's actual
|
||||
* MAC address: 01:00:5E:00:00:FC
|
||||
*
|
||||
* The target IP address will be 224.0.0.252
|
||||
*/
|
||||
#if( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )
|
||||
#define ipLLMNR_IP_ADDR 0xE00000FC
|
||||
#else
|
||||
#define ipLLMNR_IP_ADDR 0xFC0000E0
|
||||
#endif /* ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN */
|
||||
|
||||
#define ipLLMNR_PORT 5355 /* Standard LLMNR port. */
|
||||
#define ipDNS_PORT 53 /* Standard DNS port. */
|
||||
#define ipDHCP_CLIENT 67
|
||||
#define ipDHCP_SERVER 68
|
||||
#define ipNBNS_PORT 137 /* NetBIOS Name Service. */
|
||||
#define ipNBDGM_PORT 138 /* Datagram Service, not included. */
|
||||
|
||||
/*
|
||||
* The following function should be provided by the user and return true if it
|
||||
* matches the domain name.
|
||||
*/
|
||||
extern BaseType_t xApplicationDNSQueryHook( const char *pcName );
|
||||
|
||||
/*
|
||||
* LLMNR is very similar to DNS, so is handled by the DNS routines.
|
||||
*/
|
||||
uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
|
||||
|
||||
#if( ipconfigUSE_LLMNR == 1 )
|
||||
extern const MACAddress_t xLLMNR_MacAdress;
|
||||
#endif /* ipconfigUSE_LLMNR */
|
||||
|
||||
#if( ipconfigUSE_NBNS != 0 )
|
||||
|
||||
/*
|
||||
* Inspect a NetBIOS Names-Service message. If the name matches with ours
|
||||
* (xApplicationDNSQueryHook returns true) an answer will be sent back.
|
||||
* Note that LLMNR is a better protocol for name services on a LAN as it is
|
||||
* less polluted
|
||||
*/
|
||||
uint32_t ulNBNSHandlePacket (NetworkBufferDescriptor_t *pxNetworkBuffer );
|
||||
|
||||
#endif /* ipconfigUSE_NBNS */
|
||||
|
||||
#if( ipconfigUSE_DNS_CACHE != 0 )
|
||||
|
||||
uint32_t FreeRTOS_dnslookup( const char *pcHostName );
|
||||
|
||||
#endif /* ipconfigUSE_DNS_CACHE != 0 */
|
||||
|
||||
#if( ipconfigDNS_USE_CALLBACKS != 0 )
|
||||
|
||||
/*
|
||||
* Users may define this type of function as a callback.
|
||||
* It will be called when a DNS reply is received or when a timeout has been reached.
|
||||
*/
|
||||
typedef void (* FOnDNSEvent ) ( const char * /* pcName */, void * /* pvSearchID */, uint32_t /* ulIPAddress */ );
|
||||
|
||||
/*
|
||||
* Asynchronous version of gethostbyname()
|
||||
* xTimeout is in units of ms.
|
||||
*/
|
||||
uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, FOnDNSEvent pCallback, void *pvSearchID, TickType_t xTimeout );
|
||||
void FreeRTOS_gethostbyname_cancel( void *pvSearchID );
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
|
||||
* FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:
|
||||
* _TBD_ Add URL
|
||||
*/
|
||||
uint32_t FreeRTOS_gethostbyname( const char *pcHostName );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_DNS_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
350
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h
Normal file
350
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_IP_H
|
||||
#define FREERTOS_IP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Application level configuration options. */
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
#include "FreeRTOSIPConfigDefaults.h"
|
||||
#include "IPTraceMacroDefaults.h"
|
||||
|
||||
/* Some constants defining the sizes of several parts of a packet */
|
||||
#define ipSIZE_OF_ETH_HEADER 14u
|
||||
#define ipSIZE_OF_IPv4_HEADER 20u
|
||||
#define ipSIZE_OF_IGMP_HEADER 8u
|
||||
#define ipSIZE_OF_ICMP_HEADER 8u
|
||||
#define ipSIZE_OF_UDP_HEADER 8u
|
||||
#define ipSIZE_OF_TCP_HEADER 20u
|
||||
|
||||
|
||||
/* The number of octets in the MAC and IP addresses respectively. */
|
||||
#define ipMAC_ADDRESS_LENGTH_BYTES ( 6 )
|
||||
#define ipIP_ADDRESS_LENGTH_BYTES ( 4 )
|
||||
|
||||
/* IP protocol definitions. */
|
||||
#define ipPROTOCOL_ICMP ( 1 )
|
||||
#define ipPROTOCOL_IGMP ( 2 )
|
||||
#define ipPROTOCOL_TCP ( 6 )
|
||||
#define ipPROTOCOL_UDP ( 17 )
|
||||
|
||||
/* Dimensions the buffers that are filled by received Ethernet frames. */
|
||||
#define ipSIZE_OF_ETH_CRC_BYTES ( 4UL )
|
||||
#define ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES ( 4UL )
|
||||
#define ipTOTAL_ETHERNET_FRAME_SIZE ( ( ( uint32_t ) ipconfigNETWORK_MTU ) + ( ( uint32_t ) ipSIZE_OF_ETH_HEADER ) + ipSIZE_OF_ETH_CRC_BYTES + ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES )
|
||||
|
||||
/*_RB_ Comment may need updating. */
|
||||
/* 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.
|
||||
|
||||
In order to get a 32-bit alignment of network packets, an offset of 2 bytes
|
||||
would be desirable, as defined by ipconfigPACKET_FILLER_SIZE. So the malloc'd
|
||||
buffer will have the following contents:
|
||||
uint32_t pointer; // word-aligned
|
||||
uchar_8 filler[6];
|
||||
<< ETH-header >> // half-word-aligned
|
||||
uchar_8 dest[6]; // start of pucEthernetBuffer
|
||||
uchar_8 dest[6];
|
||||
uchar16_t type;
|
||||
<< IP-header >> // word-aligned
|
||||
uint8_t ucVersionHeaderLength;
|
||||
etc
|
||||
*/
|
||||
#if( ipconfigBUFFER_PADDING != 0 )
|
||||
#define ipBUFFER_PADDING ipconfigBUFFER_PADDING
|
||||
#else
|
||||
#define ipBUFFER_PADDING ( 8u + ipconfigPACKET_FILLER_SIZE )
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
{
|
||||
ListItem_t 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/TCP 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. */
|
||||
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
|
||||
struct xNETWORK_BUFFER *pxNextBuffer; /* Possible optimisation for expert users - requires network driver support. */
|
||||
#endif
|
||||
} NetworkBufferDescriptor_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xMAC_ADDRESS
|
||||
{
|
||||
uint8_t ucBytes[ ipMAC_ADDRESS_LENGTH_BYTES ];
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
|
||||
typedef struct xMAC_ADDRESS MACAddress_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 == pdFREERTOS_LITTLE_ENDIAN )
|
||||
|
||||
/* FreeRTOS_htons / FreeRTOS_htonl: some platforms might have built-in versions
|
||||
using a single instruction so allow these versions to be overridden. */
|
||||
#ifndef FreeRTOS_htons
|
||||
#define FreeRTOS_htons( usIn ) ( (uint16_t) ( ( ( usIn ) << 8U ) | ( ( usIn ) >> 8U ) ) )
|
||||
#endif
|
||||
|
||||
#ifndef FreeRTOS_htonl
|
||||
#define FreeRTOS_htonl( ulIn ) \
|
||||
( \
|
||||
( uint32_t ) \
|
||||
( \
|
||||
( ( ( ( uint32_t ) ( ulIn ) ) ) << 24 ) | \
|
||||
( ( ( ( uint32_t ) ( ulIn ) ) & 0x0000ff00UL ) << 8 ) | \
|
||||
( ( ( ( uint32_t ) ( ulIn ) ) & 0x00ff0000UL ) >> 8 ) | \
|
||||
( ( ( ( uint32_t ) ( ulIn ) ) ) >> 24 ) \
|
||||
) \
|
||||
)
|
||||
#endif
|
||||
|
||||
#else /* ipconfigBYTE_ORDER */
|
||||
|
||||
#define FreeRTOS_htons( x ) ( ( uint16_t ) ( x ) )
|
||||
#define FreeRTOS_htonl( x ) ( ( uint32_t ) ( x ) )
|
||||
|
||||
#endif /* ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN */
|
||||
|
||||
#define FreeRTOS_ntohs( x ) FreeRTOS_htons( x )
|
||||
#define FreeRTOS_ntohl( x ) FreeRTOS_htonl( x )
|
||||
|
||||
#if( ipconfigHAS_INLINE_FUNCTIONS == 1 )
|
||||
|
||||
static portINLINE int32_t FreeRTOS_max_int32 (int32_t a, int32_t b);
|
||||
static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b);
|
||||
static portINLINE int32_t FreeRTOS_min_int32 (int32_t a, int32_t b);
|
||||
static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b);
|
||||
static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d);
|
||||
static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d);
|
||||
static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b);
|
||||
static portINLINE BaseType_t FreeRTOS_max_BaseType (BaseType_t a, BaseType_t b);
|
||||
static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b);
|
||||
static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t a, UBaseType_t b);
|
||||
|
||||
|
||||
static portINLINE int32_t FreeRTOS_max_int32 (int32_t a, int32_t b) { return a >= b ? a : b; }
|
||||
static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b) { return a >= b ? a : b; }
|
||||
static portINLINE int32_t FreeRTOS_min_int32 (int32_t a, int32_t b) { return a <= b ? a : b; }
|
||||
static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b) { return a <= b ? a : b; }
|
||||
static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d) { return d * ( ( a + d - 1u ) / d ); }
|
||||
static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d) { return d * ( a / d ); }
|
||||
|
||||
static portINLINE BaseType_t FreeRTOS_max_BaseType (BaseType_t a, BaseType_t b) { return a >= b ? a : b; }
|
||||
static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b) { return a >= b ? a : b; }
|
||||
static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b) { return a <= b ? a : b; }
|
||||
static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t a, UBaseType_t b) { return a <= b ? a : b; }
|
||||
|
||||
#else
|
||||
|
||||
#define FreeRTOS_max_int32(a,b) ( ( ( int32_t ) ( a ) ) >= ( ( int32_t ) ( b ) ) ? ( ( int32_t ) ( a ) ) : ( ( int32_t ) ( b ) ) )
|
||||
#define FreeRTOS_max_uint32(a,b) ( ( ( uint32_t ) ( a ) ) >= ( ( uint32_t ) ( b ) ) ? ( ( uint32_t ) ( a ) ) : ( ( uint32_t ) ( b ) ) )
|
||||
|
||||
#define FreeRTOS_min_int32(a,b) ( ( ( int32_t ) a ) <= ( ( int32_t ) b ) ? ( ( int32_t ) a ) : ( ( int32_t ) b ) )
|
||||
#define FreeRTOS_min_uint32(a,b) ( ( ( uint32_t ) a ) <= ( ( uint32_t ) b ) ? ( ( uint32_t ) a ) : ( ( uint32_t ) b ) )
|
||||
|
||||
/* Round-up: a = d * ( ( a + d - 1 ) / d ) */
|
||||
#define FreeRTOS_round_up(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( ( uint32_t ) ( a ) ) + ( ( uint32_t ) ( d ) ) - 1UL ) / ( ( uint32_t ) ( d ) ) ) )
|
||||
#define FreeRTOS_round_down(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( uint32_t ) ( a ) ) / ( ( uint32_t ) ( d ) ) ) )
|
||||
|
||||
#define FreeRTOS_max_BaseType(a, b) ( ( ( BaseType_t ) ( a ) ) >= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) )
|
||||
#define FreeRTOS_max_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) >= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )
|
||||
#define FreeRTOS_min_BaseType(a, b) ( ( ( BaseType_t ) ( a ) ) <= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) )
|
||||
#define FreeRTOS_min_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) <= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )
|
||||
|
||||
#endif /* ipconfigHAS_INLINE_FUNCTIONS */
|
||||
|
||||
#define pdMS_TO_MIN_TICKS( xTimeInMs ) ( pdMS_TO_TICKS( ( xTimeInMs ) ) < ( ( TickType_t ) 1 ) ? ( ( TickType_t ) 1 ) : pdMS_TO_TICKS( ( xTimeInMs ) ) )
|
||||
|
||||
#ifndef pdTRUE_SIGNED
|
||||
/* Temporary solution: eventually the defines below will appear in 'Source\include\projdefs.h' */
|
||||
#define pdTRUE_SIGNED pdTRUE
|
||||
#define pdFALSE_SIGNED pdFALSE
|
||||
#define pdTRUE_UNSIGNED ( ( UBaseType_t ) 1u )
|
||||
#define pdFALSE_UNSIGNED ( ( UBaseType_t ) 0u )
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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_TCP/FreeRTOS_TCP_API_Functions.html
|
||||
*/
|
||||
BaseType_t 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, TickType_t xBlockTimeTicks );
|
||||
void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress );
|
||||
void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint32_t *pulNetMask, const uint32_t *pulGatewayAddress, const uint32_t *pulDNSServerAddress );
|
||||
BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, TickType_t xBlockTimeTicks );
|
||||
void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer );
|
||||
const uint8_t * FreeRTOS_GetMACAddress( void );
|
||||
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
|
||||
void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier );
|
||||
uint32_t FreeRTOS_GetIPAddress( void );
|
||||
void FreeRTOS_SetIPAddress( uint32_t ulIPAddress );
|
||||
void FreeRTOS_SetNetmask( uint32_t ulNetmask );
|
||||
void FreeRTOS_SetGatewayAddress( uint32_t ulGatewayAddress );
|
||||
uint32_t FreeRTOS_GetGatewayAddress( void );
|
||||
uint32_t FreeRTOS_GetDNSServerAddress( void );
|
||||
uint32_t FreeRTOS_GetNetmask( void );
|
||||
void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress );
|
||||
BaseType_t FreeRTOS_IsNetworkUp( void );
|
||||
|
||||
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
|
||||
UBaseType_t uxGetMinimumIPQueueSpace( void );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Defined in FreeRTOS_Sockets.c
|
||||
* //_RB_ Don't think this comment is correct. If this is for internal use only it should appear after all the public API functions and not start with FreeRTOS_.
|
||||
* Socket has had activity, reset the timer so it will not be closed
|
||||
* because of inactivity
|
||||
*/
|
||||
const char *FreeRTOS_GetTCPStateName( UBaseType_t ulState);
|
||||
|
||||
/* _HT_ Temporary: show all valid ARP entries
|
||||
*/
|
||||
void FreeRTOS_PrintARPCache( void );
|
||||
void FreeRTOS_ClearARP( void );
|
||||
|
||||
#if( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
|
||||
|
||||
/* DHCP has an option for clients to register their hostname. It doesn't
|
||||
have much use, except that a device can be found in a router along with its
|
||||
name. If this option is used the callback below must be provided by the
|
||||
application writer to return a const string, denoting the device's name. */
|
||||
const char *pcApplicationHostnameHook( void );
|
||||
|
||||
#endif /* ipconfigDHCP_REGISTER_HOSTNAME */
|
||||
|
||||
|
||||
/* For backward compatibility define old structure names to the newer equivalent
|
||||
structure name. */
|
||||
#ifndef ipconfigENABLE_BACKWARD_COMPATIBILITY
|
||||
#define ipconfigENABLE_BACKWARD_COMPATIBILITY 1
|
||||
#endif
|
||||
|
||||
#if( ipconfigENABLE_BACKWARD_COMPATIBILITY == 1 )
|
||||
#define xIPStackEvent_t IPStackEvent_t
|
||||
#define xNetworkBufferDescriptor_t NetworkBufferDescriptor_t
|
||||
#define xMACAddress_t MACAddress_t
|
||||
#define xWinProperties_t WinProperties_t
|
||||
#define xSocket_t Socket_t
|
||||
#define xSocketSet_t SocketSet_t
|
||||
#define ipSIZE_OF_IP_HEADER ipSIZE_OF_IPv4_HEADER
|
||||
|
||||
/* Since August 2016, the public types and fields below have changed name:
|
||||
abbreviations TCP/UDP are now written in capitals, and type names now end with "_t". */
|
||||
#define FOnConnected FOnConnected_t
|
||||
#define FOnTcpReceive FOnTCPReceive_t
|
||||
#define FOnTcpSent FOnTCPSent_t
|
||||
#define FOnUdpReceive FOnUDPReceive_t
|
||||
#define FOnUdpSent FOnUDPSent_t
|
||||
|
||||
#define pOnTcpConnected pxOnTCPConnected
|
||||
#define pOnTcpReceive pxOnTCPReceive
|
||||
#define pOnTcpSent pxOnTCPSent
|
||||
#define pOnUdpReceive pxOnUDPReceive
|
||||
#define pOnUdpSent pxOnUDPSent
|
||||
|
||||
#define FOnUdpSent FOnUDPSent_t
|
||||
#define FOnTcpSent FOnTCPSent_t
|
||||
#endif /* ipconfigENABLE_BACKWARD_COMPATIBILITY */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_IP_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,840 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_IP_PRIVATE_H
|
||||
#define FREERTOS_IP_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Application level configuration options. */
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
#include "FreeRTOSIPConfigDefaults.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "IPTraceMacroDefaults.h"
|
||||
#include "FreeRTOS_Stream_Buffer.h"
|
||||
#if( ipconfigUSE_TCP == 1 )
|
||||
#include "FreeRTOS_TCP_WIN.h"
|
||||
#include "FreeRTOS_TCP_IP.h"
|
||||
#endif
|
||||
|
||||
#include "event_groups.h"
|
||||
|
||||
typedef struct xNetworkAddressingParameters
|
||||
{
|
||||
uint32_t ulDefaultIPAddress;
|
||||
uint32_t ulNetMask;
|
||||
uint32_t ulGatewayAddress;
|
||||
uint32_t ulDNSServerAddress;
|
||||
uint32_t ulBroadcastAddress;
|
||||
} NetworkAddressingParameters_t;
|
||||
|
||||
extern BaseType_t xTCPWindowLoggingLevel;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Protocol headers. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xETH_HEADER
|
||||
{
|
||||
MACAddress_t xDestinationAddress; /* 0 + 6 = 6 */
|
||||
MACAddress_t xSourceAddress; /* 6 + 6 = 12 */
|
||||
uint16_t usFrameType; /* 12 + 2 = 14 */
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xETH_HEADER EthernetHeader_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xARP_HEADER
|
||||
{
|
||||
uint16_t usHardwareType; /* 0 + 2 = 2 */
|
||||
uint16_t usProtocolType; /* 2 + 2 = 4 */
|
||||
uint8_t ucHardwareAddressLength; /* 4 + 1 = 5 */
|
||||
uint8_t ucProtocolAddressLength; /* 5 + 1 = 6 */
|
||||
uint16_t usOperation; /* 6 + 2 = 8 */
|
||||
MACAddress_t xSenderHardwareAddress; /* 8 + 6 = 14 */
|
||||
uint8_t ucSenderProtocolAddress[ 4 ]; /* 14 + 4 = 18 */
|
||||
MACAddress_t xTargetHardwareAddress; /* 18 + 6 = 24 */
|
||||
uint32_t ulTargetProtocolAddress; /* 24 + 4 = 28 */
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xARP_HEADER ARPHeader_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xIP_HEADER
|
||||
{
|
||||
uint8_t ucVersionHeaderLength; /* 0 + 1 = 1 */
|
||||
uint8_t ucDifferentiatedServicesCode; /* 1 + 1 = 2 */
|
||||
uint16_t usLength; /* 2 + 2 = 4 */
|
||||
uint16_t usIdentification; /* 4 + 2 = 6 */
|
||||
uint16_t usFragmentOffset; /* 6 + 2 = 8 */
|
||||
uint8_t ucTimeToLive; /* 8 + 1 = 9 */
|
||||
uint8_t ucProtocol; /* 9 + 1 = 10 */
|
||||
uint16_t usHeaderChecksum; /* 10 + 2 = 12 */
|
||||
uint32_t ulSourceIPAddress; /* 12 + 4 = 16 */
|
||||
uint32_t ulDestinationIPAddress; /* 16 + 4 = 20 */
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xIP_HEADER IPHeader_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xIGMP_HEADER
|
||||
{
|
||||
uint8_t ucVersionType; /* 0 + 1 = 1 */
|
||||
uint8_t ucMaxResponseTime; /* 1 + 1 = 2 */
|
||||
uint16_t usChecksum; /* 2 + 2 = 4 */
|
||||
uint32_t usGroupAddress; /* 4 + 4 = 8 */
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xIGMP_HEADER IGMPHeader_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xICMP_HEADER
|
||||
{
|
||||
uint8_t ucTypeOfMessage; /* 0 + 1 = 1 */
|
||||
uint8_t ucTypeOfService; /* 1 + 1 = 2 */
|
||||
uint16_t usChecksum; /* 2 + 2 = 4 */
|
||||
uint16_t usIdentifier; /* 4 + 2 = 6 */
|
||||
uint16_t usSequenceNumber; /* 6 + 2 = 8 */
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xICMP_HEADER ICMPHeader_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xUDP_HEADER
|
||||
{
|
||||
uint16_t usSourcePort; /* 0 + 2 = 2 */
|
||||
uint16_t usDestinationPort; /* 2 + 2 = 4 */
|
||||
uint16_t usLength; /* 4 + 2 = 6 */
|
||||
uint16_t usChecksum; /* 6 + 2 = 8 */
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xUDP_HEADER UDPHeader_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xTCP_HEADER
|
||||
{
|
||||
uint16_t usSourcePort; /* + 2 = 2 */
|
||||
uint16_t usDestinationPort; /* + 2 = 4 */
|
||||
uint32_t ulSequenceNumber; /* + 4 = 8 */
|
||||
uint32_t ulAckNr; /* + 4 = 12 */
|
||||
uint8_t ucTCPOffset; /* + 1 = 13 */
|
||||
uint8_t ucTCPFlags; /* + 1 = 14 */
|
||||
uint16_t usWindow; /* + 2 = 15 */
|
||||
uint16_t usChecksum; /* + 2 = 18 */
|
||||
uint16_t usUrgent; /* + 2 = 20 */
|
||||
#if ipconfigUSE_TCP == 1
|
||||
/* the option data is not a part of the TCP header */
|
||||
uint8_t ucOptdata[ipSIZE_TCP_OPTIONS]; /* + 12 = 32 */
|
||||
#endif
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xTCP_HEADER TCPHeader_t;
|
||||
|
||||
#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 PseudoHeader_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Nested protocol packets. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xARP_PACKET
|
||||
{
|
||||
EthernetHeader_t xEthernetHeader; /* 0 + 14 = 14 */
|
||||
ARPHeader_t xARPHeader; /* 14 + 28 = 42 */
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xARP_PACKET ARPPacket_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xIP_PACKET
|
||||
{
|
||||
EthernetHeader_t xEthernetHeader;
|
||||
IPHeader_t xIPHeader;
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xIP_PACKET IPPacket_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xICMP_PACKET
|
||||
{
|
||||
EthernetHeader_t xEthernetHeader;
|
||||
IPHeader_t xIPHeader;
|
||||
ICMPHeader_t xICMPHeader;
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xICMP_PACKET ICMPPacket_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xUDP_PACKET
|
||||
{
|
||||
EthernetHeader_t xEthernetHeader; /* 0 + 14 = 14 */
|
||||
IPHeader_t xIPHeader; /* 14 + 20 = 34 */
|
||||
UDPHeader_t xUDPHeader; /* 34 + 8 = 42 */
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xUDP_PACKET UDPPacket_t;
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xTCP_PACKET
|
||||
{
|
||||
EthernetHeader_t xEthernetHeader; /* 0 + 14 = 14 */
|
||||
IPHeader_t xIPHeader; /* 14 + 20 = 34 */
|
||||
TCPHeader_t xTCPHeader; /* 34 + 32 = 66 */
|
||||
}
|
||||
#include "pack_struct_end.h"
|
||||
typedef struct xTCP_PACKET TCPPacket_t;
|
||||
|
||||
typedef union XPROT_PACKET
|
||||
{
|
||||
ARPPacket_t xARPPacket;
|
||||
TCPPacket_t xTCPPacket;
|
||||
UDPPacket_t xUDPPacket;
|
||||
ICMPPacket_t xICMPPacket;
|
||||
} ProtocolPacket_t;
|
||||
|
||||
|
||||
/* The maximum UDP payload length. */
|
||||
#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_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
|
||||
{
|
||||
eNoEvent = -1,
|
||||
eNetworkDownEvent, /* 0: The network interface has been lost and/or needs [re]connecting. */
|
||||
eNetworkRxEvent, /* 1: The network interface has queued a received Ethernet frame. */
|
||||
eARPTimerEvent, /* 2: The ARP timer expired. */
|
||||
eStackTxEvent, /* 3: The software stack has queued a packet to transmit. */
|
||||
eDHCPEvent, /* 4: Process the DHCP state machine. */
|
||||
eTCPTimerEvent, /* 5: See if any TCP socket needs attention. */
|
||||
eTCPAcceptEvent, /* 6: Client API FreeRTOS_accept() waiting for client connections. */
|
||||
eTCPNetStat, /* 7: IP-task is asked to produce a netstat listing. */
|
||||
eSocketBindEvent, /* 8: Send a message to the IP-task to bind a socket to a port. */
|
||||
eSocketCloseEvent, /* 9: Send a message to the IP-task to close a socket. */
|
||||
eSocketSelectEvent, /*10: Send a message to the IP-task for select(). */
|
||||
eSocketSignalEvent, /*11: A socket must be signalled. */
|
||||
} eIPEvent_t;
|
||||
|
||||
typedef struct IP_TASK_COMMANDS
|
||||
{
|
||||
eIPEvent_t eEventType;
|
||||
void *pvData;
|
||||
} IPStackEvent_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_IPv4 : ipIP_PAYLOAD_OFFSET )
|
||||
|
||||
/* The offset into a UDP packet at which the UDP data (payload) starts. */
|
||||
#define ipUDP_PAYLOAD_OFFSET_IPv4 ( sizeof( UDPPacket_t ) )
|
||||
|
||||
/* The offset into an IP packet into which the IP data (payload) starts. */
|
||||
#define ipIP_PAYLOAD_OFFSET ( sizeof( IPPacket_t ) )
|
||||
|
||||
#include "pack_struct_start.h"
|
||||
struct xUDP_IP_FRAGMENT_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_FRAGMENT_PARAMETERS IPFragmentParameters_t;
|
||||
|
||||
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
|
||||
|
||||
/* Ethernet frame types. */
|
||||
#define ipARP_FRAME_TYPE ( 0x0608U )
|
||||
#define ipIPv4_FRAME_TYPE ( 0x0008U )
|
||||
|
||||
/* ARP related definitions. */
|
||||
#define ipARP_PROTOCOL_TYPE ( 0x0008U )
|
||||
#define ipARP_HARDWARE_TYPE_ETHERNET ( 0x0100U )
|
||||
#define ipARP_REQUEST ( 0x0100U )
|
||||
#define ipARP_REPLY ( 0x0200U )
|
||||
|
||||
#else
|
||||
|
||||
/* Ethernet frame types. */
|
||||
#define ipARP_FRAME_TYPE ( 0x0806U )
|
||||
#define ipIPv4_FRAME_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 == pdFREERTOS_LITTLE_ENDIAN */
|
||||
|
||||
|
||||
/* For convenience, a MAC address of all zeros and another of all 0xffs are
|
||||
defined const for quick reference. */
|
||||
extern const MACAddress_t xBroadcastMACAddress; /* all 0xff's */
|
||||
extern uint16_t usPacketIdentifier;
|
||||
|
||||
/* Define a default UDP packet header (declared in FreeRTOS_UDP_IP.c) */
|
||||
typedef union xUDPPacketHeader
|
||||
{
|
||||
uint8_t ucBytes[24];
|
||||
uint32_t ulWords[6];
|
||||
} UDPPacketHeader_t;
|
||||
extern UDPPacketHeader_t xDefaultPartUDPPacketHeader;
|
||||
|
||||
/* Structure that stores the netmask, gateway address and DNS server addresses. */
|
||||
extern NetworkAddressingParameters_t xNetworkAddressing;
|
||||
|
||||
/* Structure that stores the defaults for netmask, gateway address and DNS.
|
||||
These values will be copied to 'xNetworkAddressing' in case DHCP is not used,
|
||||
and also in case DHCP does not lead to a confirmed request. */
|
||||
extern NetworkAddressingParameters_t xDefaultAddressing;
|
||||
|
||||
/* True when BufferAllocation_1.c was included, false for BufferAllocation_2.c */
|
||||
extern const BaseType_t xBufferAllocFixedSize;
|
||||
|
||||
/* Defined in FreeRTOS_Sockets.c */
|
||||
#if ( ipconfigUSE_TCP == 1 )
|
||||
extern List_t xBoundTCPSocketsList;
|
||||
#endif
|
||||
|
||||
/* The local IP address is accessed from within xDefaultPartUDPPacketHeader,
|
||||
rather than duplicated in its own variable. */
|
||||
#define ipLOCAL_IP_ADDRESS_POINTER ( ( uint32_t * ) &( xDefaultPartUDPPacketHeader.ulWords[ 20u / sizeof(uint32_t) ] ) )
|
||||
|
||||
/* The local MAC address is accessed from within xDefaultPartUDPPacketHeader,
|
||||
rather than duplicated in its own variable. */
|
||||
#define ipLOCAL_MAC_ADDRESS ( &xDefaultPartUDPPacketHeader.ucBytes[0] )
|
||||
|
||||
/* ICMP packets are sent using the same function as UDP packets. The port
|
||||
number is used to distinguish between the two, as 0 is an invalid UDP port. */
|
||||
#define ipPACKET_CONTAINS_ICMP_DATA ( 0 )
|
||||
|
||||
/* For now, the lower 8 bits in 'xEventBits' will be reserved for the above
|
||||
socket events. */
|
||||
#define SOCKET_EVENT_BIT_COUNT 8
|
||||
|
||||
#define vSetField16( pxBase, xType, xField, usValue ) \
|
||||
{ \
|
||||
( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( usValue ) >> 8 ); \
|
||||
( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xff ); \
|
||||
}
|
||||
|
||||
#define vSetField32( pxBase, xType, xField, ulValue ) \
|
||||
{ \
|
||||
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( ulValue ) >> 24 ); \
|
||||
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( ( ulValue ) >> 16 ) & 0xff ); \
|
||||
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 2 ] = ( uint8_t ) ( ( ( ulValue ) >> 8 ) & 0xff ); \
|
||||
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 3 ] = ( uint8_t ) ( ( ulValue ) & 0xff ); \
|
||||
}
|
||||
|
||||
#define vFlip_16( left, right ) \
|
||||
do { \
|
||||
uint16_t tmp = (left); \
|
||||
(left) = (right); \
|
||||
(right) = tmp; \
|
||||
} while (0)
|
||||
|
||||
#define vFlip_32( left, right ) \
|
||||
do { \
|
||||
uint32_t tmp = (left); \
|
||||
(left) = (right); \
|
||||
(right) = tmp; \
|
||||
} while (0)
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (BaseType_t)(sizeof(x)/sizeof(x)[0])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
BaseType_t 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 );
|
||||
BaseType_t FreeRTOS_NetworkDownFromISR( void );
|
||||
|
||||
/*
|
||||
* Processes incoming ARP packets.
|
||||
*/
|
||||
eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame );
|
||||
|
||||
/*
|
||||
* 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 );
|
||||
|
||||
/*
|
||||
* Return the checksum generated over xDataLengthBytes from pucNextData.
|
||||
*/
|
||||
uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes );
|
||||
|
||||
/* Socket related private functions. */
|
||||
BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort );
|
||||
void vNetworkSocketsInit( void );
|
||||
|
||||
/*
|
||||
* Returns pdTRUE if the IP task has been created and is initialised. Otherwise
|
||||
* returns pdFALSE.
|
||||
*/
|
||||
BaseType_t xIPIsNetworkTaskReady( void );
|
||||
|
||||
#if( ipconfigUSE_TCP == 1 )
|
||||
|
||||
/*
|
||||
* Actually a user thing, but because xBoundTCPSocketsList, let it do by the
|
||||
* IP-task
|
||||
*/
|
||||
void vTCPNetStat( void );
|
||||
|
||||
/*
|
||||
* At least one socket needs to check for timeouts
|
||||
*/
|
||||
TickType_t xTCPTimerCheck( BaseType_t xWillSleep );
|
||||
|
||||
/* Every TCP socket has a buffer space just big enough to store
|
||||
the last TCP header received.
|
||||
As a reference of this field may be passed to DMA, force the
|
||||
alignment to 8 bytes. */
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/* Increase the alignment of this union by adding a 64-bit variable. */
|
||||
uint64_t ullAlignmentWord;
|
||||
} a;
|
||||
struct
|
||||
{
|
||||
/* The next field only serves to give 'ucLastPacket' a correct
|
||||
alignment of 8 + 2. See comments in FreeRTOS_IP.h */
|
||||
uint8_t ucFillPacket[ ipconfigPACKET_FILLER_SIZE ];
|
||||
uint8_t ucLastPacket[ sizeof( TCPPacket_t ) ];
|
||||
} u;
|
||||
} LastTCPPacket_t;
|
||||
|
||||
/*
|
||||
* Note that the values of all short and long integers in these structs
|
||||
* are being stored in the native-endian way
|
||||
* Translation should take place when accessing any structure which defines
|
||||
* network packets, such as IPHeader_t and TCPHeader_t
|
||||
*/
|
||||
typedef struct TCPSOCKET
|
||||
{
|
||||
uint32_t ulRemoteIP; /* IP address of remote machine */
|
||||
uint16_t usRemotePort; /* Port on remote machine */
|
||||
struct {
|
||||
/* Most compilers do like bit-flags */
|
||||
uint32_t
|
||||
bMssChange : 1, /* This socket has seen a change in MSS */
|
||||
bPassAccept : 1, /* when true, this socket may be returned in a call to accept() */
|
||||
bPassQueued : 1, /* when true, this socket is an orphan until it gets connected
|
||||
* Why an orphan? Because it may not be returned in a accept() call until it
|
||||
* gets the state eESTABLISHED */
|
||||
bReuseSocket : 1, /* When a listening socket gets a connection, do not create a new instance but keep on using it */
|
||||
bCloseAfterSend : 1,/* As soon as the last byte has been transmitted, finalise the connection
|
||||
* Useful in e.g. FTP connections, where the last data bytes are sent along with the FIN flag */
|
||||
bUserShutdown : 1, /* User requesting a graceful shutdown */
|
||||
bCloseRequested : 1,/* Request to finalise the connection */
|
||||
bLowWater : 1, /* high-water level has been reached. Cleared as soon as 'rx-count < lo-water' */
|
||||
bWinChange : 1, /* The value of bLowWater has changed, must send a window update */
|
||||
bSendKeepAlive : 1, /* When this flag is true, a TCP keep-alive message must be send */
|
||||
bWaitKeepAlive : 1, /* When this flag is true, a TCP keep-alive reply is expected */
|
||||
bConnPrepared : 1, /* Connecting socket: Message has been prepared */
|
||||
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
|
||||
bConnPassed : 1, /* Connecting socket: Socket has been passed in a successful select() */
|
||||
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
|
||||
bFinAccepted : 1, /* This socket has received (or sent) a FIN and accepted it */
|
||||
bFinSent : 1, /* We've sent out a FIN */
|
||||
bFinRecv : 1, /* We've received a FIN from our peer */
|
||||
bFinAcked : 1, /* Our FIN packet has been acked */
|
||||
bFinLast : 1, /* The last ACK (after FIN and FIN+ACK) has been sent or will be sent by the peer */
|
||||
bRxStopped : 1, /* Application asked to temporarily stop reception */
|
||||
bMallocError : 1, /* There was an error allocating a stream */
|
||||
bWinScaling : 1; /* A TCP-Window Scaling option was offered and accepted in the SYN phase. */
|
||||
} bits;
|
||||
uint32_t ulHighestRxAllowed;
|
||||
/* The highest sequence number that we can receive at any moment */
|
||||
uint16_t usTimeout; /* Time (in ticks) after which this socket needs attention */
|
||||
uint16_t usCurMSS; /* Current Maximum Segment Size */
|
||||
uint16_t usInitMSS; /* Initial maximum segment Size */
|
||||
uint16_t usChildCount; /* In case of a listening socket: number of connections on this port number */
|
||||
uint16_t usBacklog; /* In case of a listening socket: maximum number of concurrent connections on this port number */
|
||||
uint8_t ucRepCount; /* Send repeat count, for retransmissions
|
||||
* This counter is separate from the xmitCount in the
|
||||
* TCP win segments */
|
||||
uint8_t ucTCPState; /* TCP state: see eTCP_STATE */
|
||||
struct XSOCKET *pxPeerSocket; /* for server socket: child, for child socket: parent */
|
||||
#if( ipconfigTCP_KEEP_ALIVE == 1 )
|
||||
uint8_t ucKeepRepCount;
|
||||
TickType_t xLastAliveTime;
|
||||
#endif /* ipconfigTCP_KEEP_ALIVE */
|
||||
#if( ipconfigTCP_HANG_PROTECTION == 1 )
|
||||
TickType_t xLastActTime;
|
||||
#endif /* ipconfigTCP_HANG_PROTECTION */
|
||||
size_t uxLittleSpace;
|
||||
size_t uxEnoughSpace;
|
||||
size_t uxRxStreamSize;
|
||||
size_t uxTxStreamSize;
|
||||
StreamBuffer_t *rxStream;
|
||||
StreamBuffer_t *txStream;
|
||||
#if( ipconfigUSE_TCP_WIN == 1 )
|
||||
NetworkBufferDescriptor_t *pxAckMessage;
|
||||
#endif /* ipconfigUSE_TCP_WIN */
|
||||
/* Buffer space to store the last TCP header received. */
|
||||
LastTCPPacket_t xPacket;
|
||||
uint8_t tcpflags; /* TCP flags */
|
||||
#if( ipconfigUSE_TCP_WIN != 0 )
|
||||
uint8_t ucMyWinScaleFactor;
|
||||
uint8_t ucPeerWinScaleFactor;
|
||||
#endif
|
||||
#if( ipconfigUSE_CALLBACKS == 1 )
|
||||
FOnTCPReceive_t pxHandleReceive; /*
|
||||
* In case of a TCP socket:
|
||||
* typedef void (* FOnTCPReceive_t) (Socket_t xSocket, void *pData, size_t xLength );
|
||||
*/
|
||||
FOnTCPSent_t pxHandleSent;
|
||||
FOnConnected_t pxHandleConnected; /* Actually type: typedef void (* FOnConnected_t) (Socket_t xSocket, BaseType_t ulConnected ); */
|
||||
#endif /* ipconfigUSE_CALLBACKS */
|
||||
uint32_t ulWindowSize; /* Current Window size advertised by peer */
|
||||
uint32_t ulRxCurWinSize; /* Constantly changing: this is the current size available for data reception */
|
||||
size_t uxRxWinSize; /* Fixed value: size of the TCP reception window */
|
||||
size_t uxTxWinSize; /* Fixed value: size of the TCP transmit window */
|
||||
|
||||
TCPWindow_t xTCPWindow;
|
||||
} IPTCPSocket_t;
|
||||
|
||||
#endif /* ipconfigUSE_TCP */
|
||||
|
||||
typedef struct UDPSOCKET
|
||||
{
|
||||
List_t xWaitingPacketsList; /* Incoming packets */
|
||||
#if( ipconfigUDP_MAX_RX_PACKETS > 0 )
|
||||
UBaseType_t uxMaxPackets; /* Protection: limits the number of packets buffered per socket */
|
||||
#endif /* ipconfigUDP_MAX_RX_PACKETS */
|
||||
#if( ipconfigUSE_CALLBACKS == 1 )
|
||||
FOnUDPReceive_t pxHandleReceive; /*
|
||||
* In case of a UDP socket:
|
||||
* typedef void (* FOnUDPReceive_t) (Socket_t xSocket, void *pData, size_t xLength, struct freertos_sockaddr *pxAddr );
|
||||
*/
|
||||
FOnUDPSent_t pxHandleSent;
|
||||
#endif /* ipconfigUSE_CALLBACKS */
|
||||
} IPUDPSocket_t;
|
||||
|
||||
typedef enum eSOCKET_EVENT {
|
||||
eSOCKET_RECEIVE = 0x0001,
|
||||
eSOCKET_SEND = 0x0002,
|
||||
eSOCKET_ACCEPT = 0x0004,
|
||||
eSOCKET_CONNECT = 0x0008,
|
||||
eSOCKET_BOUND = 0x0010,
|
||||
eSOCKET_CLOSED = 0x0020,
|
||||
eSOCKET_INTR = 0x0040,
|
||||
eSOCKET_ALL = 0x007F,
|
||||
} eSocketEvent_t;
|
||||
|
||||
typedef struct XSOCKET
|
||||
{
|
||||
EventBits_t xEventBits;
|
||||
EventGroupHandle_t xEventGroup;
|
||||
|
||||
ListItem_t xBoundSocketListItem; /* Used to reference the socket from a bound sockets list. */
|
||||
TickType_t xReceiveBlockTime; /* if recv[to] is called while no data is available, wait this amount of time. Unit in clock-ticks */
|
||||
TickType_t xSendBlockTime; /* if send[to] is called while there is not enough space to send, wait this amount of time. Unit in clock-ticks */
|
||||
|
||||
uint16_t usLocalPort; /* Local port on this machine */
|
||||
uint8_t ucSocketOptions;
|
||||
uint8_t ucProtocol; /* choice of FREERTOS_IPPROTO_UDP/TCP */
|
||||
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
|
||||
SemaphoreHandle_t pxUserSemaphore;
|
||||
#endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
|
||||
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
|
||||
struct xSOCKET_SET *pxSocketSet;
|
||||
/* User may indicate which bits are interesting for this socket. */
|
||||
EventBits_t xSelectBits;
|
||||
/* These bits indicate the events which have actually occurred.
|
||||
They are maintained by the IP-task */
|
||||
EventBits_t xSocketBits;
|
||||
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
|
||||
/* TCP/UDP specific fields: */
|
||||
/* Before accessing any member of this structure, it should be confirmed */
|
||||
/* that the protocol corresponds with the type of structure */
|
||||
|
||||
union
|
||||
{
|
||||
IPUDPSocket_t xUDP;
|
||||
#if( ipconfigUSE_TCP == 1 )
|
||||
IPTCPSocket_t xTCP;
|
||||
/* Make sure that xTCP is 8-bytes aligned by
|
||||
declaring a 64-bit variable in the same union */
|
||||
uint64_t ullTCPAlignment;
|
||||
#endif /* ipconfigUSE_TCP */
|
||||
} u;
|
||||
} FreeRTOS_Socket_t;
|
||||
|
||||
#if( ipconfigUSE_TCP == 1 )
|
||||
/*
|
||||
* Lookup a TCP socket, using a multiple matching: both port numbers and
|
||||
* return IP address.
|
||||
*/
|
||||
FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort );
|
||||
|
||||
#endif /* ipconfigUSE_TCP */
|
||||
|
||||
/*
|
||||
* Look up a local socket by finding a match with the local port.
|
||||
*/
|
||||
FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort );
|
||||
|
||||
/*
|
||||
* Called when the application has generated a UDP packet to send.
|
||||
*/
|
||||
void vProcessGeneratedUDPPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );
|
||||
|
||||
/*
|
||||
* Calculate the upper-layer checksum
|
||||
* Works both for UDP, ICMP and TCP packages
|
||||
* bOut = true: checksum will be set in outgoing packets
|
||||
* bOut = false: checksum will be calculated for incoming packets
|
||||
* returning 0xffff means: checksum was correct
|
||||
*/
|
||||
uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, BaseType_t xOutgoingPacket );
|
||||
|
||||
/*
|
||||
* An Ethernet frame has been updated (maybe it was an ARP request or a PING
|
||||
* request?) and is to be sent back to its source.
|
||||
*/
|
||||
void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t xReleaseAfterSend );
|
||||
|
||||
/*
|
||||
* The internal version of bind()
|
||||
* If 'ulInternal' is true, it is called by the driver
|
||||
* The TCP driver needs to bind a socket at the moment a listening socket
|
||||
* creates a new connected socket
|
||||
*/
|
||||
BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal );
|
||||
|
||||
/*
|
||||
* Internal function to add streaming data to a TCP socket. If ulIn == true,
|
||||
* data will be added to the rxStream, otherwise to the tXStream. Normally data
|
||||
* will be written with ulOffset == 0, meaning: at the end of the FIFO. When
|
||||
* packet come in out-of-order, an offset will be used to put it in front and
|
||||
* the head will not change yet.
|
||||
*/
|
||||
int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount );
|
||||
|
||||
/*
|
||||
* Currently called for any important event.
|
||||
*/
|
||||
void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket );
|
||||
|
||||
/*
|
||||
* Some helping function, their meaning should be clear
|
||||
*/
|
||||
static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr);
|
||||
static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr)
|
||||
{
|
||||
return ( ( ( uint32_t )apChr[0] ) << 24) |
|
||||
( ( ( uint32_t )apChr[1] ) << 16) |
|
||||
( ( ( uint32_t )apChr[2] ) << 8) |
|
||||
( ( ( uint32_t )apChr[3] ) );
|
||||
}
|
||||
|
||||
static portINLINE uint16_t usChar2u16 (const uint8_t *apChr);
|
||||
static portINLINE uint16_t usChar2u16 (const uint8_t *apChr)
|
||||
{
|
||||
return ( uint16_t )
|
||||
( ( ( ( uint32_t )apChr[0] ) << 8) |
|
||||
( ( ( uint32_t )apChr[1] ) ) );
|
||||
}
|
||||
|
||||
/* Check a single socket for retransmissions and timeouts */
|
||||
BaseType_t xTCPSocketCheck( FreeRTOS_Socket_t *pxSocket );
|
||||
|
||||
BaseType_t xTCPCheckNewClient( FreeRTOS_Socket_t *pxSocket );
|
||||
|
||||
/* Defined in FreeRTOS_Sockets.c
|
||||
* Close a socket
|
||||
*/
|
||||
void *vSocketClose( FreeRTOS_Socket_t *pxSocket );
|
||||
|
||||
/*
|
||||
* Send the event eEvent to the IP task event queue, using a block time of
|
||||
* zero. Return pdPASS if the message was sent successfully, otherwise return
|
||||
* pdFALSE.
|
||||
*/
|
||||
BaseType_t xSendEventToIPTask( eIPEvent_t eEvent );
|
||||
|
||||
/*
|
||||
* The same as above, but a struct as a parameter, containing:
|
||||
* eIPEvent_t eEventType;
|
||||
* void *pvData;
|
||||
*/
|
||||
BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t xTimeout );
|
||||
|
||||
/*
|
||||
* Returns a pointer to the original NetworkBuffer from a pointer to a UDP
|
||||
* payload buffer.
|
||||
*/
|
||||
NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer );
|
||||
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
/*
|
||||
* For the case where the network driver passes a buffer directly to a DMA
|
||||
* descriptor, this function can be used to translate a 'network buffer' to
|
||||
* a 'network buffer descriptor'.
|
||||
*/
|
||||
NetworkBufferDescriptor_t *pxPacketBuffer_to_NetworkBuffer( const void *pvBuffer );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Internal: Sets a new state for a TCP socket and performs the necessary
|
||||
* actions like calling a OnConnected handler to notify the socket owner.
|
||||
*/
|
||||
#if( ipconfigUSE_TCP == 1 )
|
||||
void vTCPStateChange( FreeRTOS_Socket_t *pxSocket, enum eTCP_STATE eTCPState );
|
||||
#endif /* ipconfigUSE_TCP */
|
||||
|
||||
/*_RB_ Should this be part of the public API? */
|
||||
void FreeRTOS_netstat( void );
|
||||
|
||||
/* Returns pdTRUE is this function is called from the IP-task */
|
||||
BaseType_t xIsCallingFromIPTask( void );
|
||||
|
||||
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
|
||||
|
||||
typedef struct xSOCKET_SET
|
||||
{
|
||||
EventGroupHandle_t xSelectGroup;
|
||||
BaseType_t bApiCalled; /* True if the API was calling the private vSocketSelect */
|
||||
FreeRTOS_Socket_t *pxSocket;
|
||||
} SocketSelect_t;
|
||||
|
||||
extern void vSocketSelect( SocketSelect_t *pxSocketSelect );
|
||||
|
||||
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
|
||||
|
||||
void vIPSetDHCPTimerEnableState( BaseType_t xEnableState );
|
||||
void vIPReloadDHCPTimer( uint32_t ulLeaseTime );
|
||||
#if( ipconfigDNS_USE_CALLBACKS != 0 )
|
||||
void vIPReloadDNSTimer( uint32_t ulCheckTime );
|
||||
void vIPSetDnsTimerEnableState( BaseType_t xEnableState );
|
||||
#endif
|
||||
|
||||
/* Send the network-up event and start the ARP timer. */
|
||||
void vIPNetworkUpCalls( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_IP_PRIVATE_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,420 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_SOCKETS_H
|
||||
#define FREERTOS_SOCKETS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Standard includes. */
|
||||
#include <string.h>
|
||||
|
||||
/* Application level configuration options. */
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
|
||||
#ifndef FREERTOS_IP_CONFIG_H
|
||||
#error FreeRTOSIPConfig.h has not been included yet
|
||||
#endif
|
||||
|
||||
/* Event bit definitions are required by the select functions. */
|
||||
#include "event_groups.h"
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error FreeRTOS.h must be included before FreeRTOS_Sockets.h.
|
||||
#endif
|
||||
|
||||
#ifndef INC_TASK_H
|
||||
#ifndef TASK_H /* For compatibility with older FreeRTOS versions. */
|
||||
#error The FreeRTOS header file task.h must be included before FreeRTOS_Sockets.h.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Assigned to an Socket_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. */
|
||||
/* HT: Extended the number of error codes, gave them positive values and if possible
|
||||
the corresponding found in errno.h
|
||||
In case of an error, API's will still return negative numbers, e.g.
|
||||
return -pdFREERTOS_ERRNO_EWOULDBLOCK;
|
||||
in case an operation would block */
|
||||
|
||||
/* The following defines are obsolete, please use -pdFREERTOS_ERRNO_Exxx */
|
||||
|
||||
#define FREERTOS_SOCKET_ERROR ( -1 )
|
||||
#define FREERTOS_EWOULDBLOCK ( - pdFREERTOS_ERRNO_EWOULDBLOCK )
|
||||
#define FREERTOS_EINVAL ( - pdFREERTOS_ERRNO_EINVAL )
|
||||
#define FREERTOS_EADDRNOTAVAIL ( - pdFREERTOS_ERRNO_EADDRNOTAVAIL )
|
||||
#define FREERTOS_EADDRINUSE ( - pdFREERTOS_ERRNO_EADDRINUSE )
|
||||
#define FREERTOS_ENOBUFS ( - pdFREERTOS_ERRNO_ENOBUFS )
|
||||
#define FREERTOS_ENOPROTOOPT ( - pdFREERTOS_ERRNO_ENOPROTOOPT )
|
||||
#define FREERTOS_ECLOSED ( - pdFREERTOS_ERRNO_ENOTCONN )
|
||||
|
||||
/* 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_AF_INET6 ( 10 )
|
||||
#define FREERTOS_SOCK_DGRAM ( 2 )
|
||||
#define FREERTOS_IPPROTO_UDP ( 17 )
|
||||
|
||||
#define FREERTOS_SOCK_STREAM ( 1 )
|
||||
#define FREERTOS_IPPROTO_TCP ( 6 )
|
||||
/* IP packet of type "Any local network"
|
||||
* can be used in stead of TCP for testing with sockets in raw mode
|
||||
*/
|
||||
#define FREERTOS_IPPROTO_USR_LAN ( 63 )
|
||||
|
||||
/* 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 ( 1 )
|
||||
|
||||
/* 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 ( 2 ) /* 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. */
|
||||
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
|
||||
#define FREERTOS_SO_SET_SEMAPHORE ( 3 ) /* Used to set a user's semaphore */
|
||||
#endif
|
||||
#define FREERTOS_SO_SNDBUF ( 4 ) /* Set the size of the send buffer (TCP only) */
|
||||
#define FREERTOS_SO_RCVBUF ( 5 ) /* Set the size of the receive buffer (TCP only) */
|
||||
|
||||
#if ipconfigUSE_CALLBACKS == 1
|
||||
#define FREERTOS_SO_TCP_CONN_HANDLER ( 6 ) /* Install a callback for (dis) connection events. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
|
||||
#define FREERTOS_SO_TCP_RECV_HANDLER ( 7 ) /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
|
||||
#define FREERTOS_SO_TCP_SENT_HANDLER ( 8 ) /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
|
||||
#define FREERTOS_SO_UDP_RECV_HANDLER ( 9 ) /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
|
||||
#define FREERTOS_SO_UDP_SENT_HANDLER ( 10 ) /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
|
||||
#endif /* ipconfigUSE_CALLBACKS */
|
||||
|
||||
#define FREERTOS_SO_REUSE_LISTEN_SOCKET ( 11 ) /* When a listening socket gets connected, do not create a new one but re-use it */
|
||||
#define FREERTOS_SO_CLOSE_AFTER_SEND ( 12 ) /* As soon as the last byte has been transmitted, finalise the connection */
|
||||
#define FREERTOS_SO_WIN_PROPERTIES ( 13 ) /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
|
||||
#define FREERTOS_SO_SET_FULL_SIZE ( 14 ) /* Refuse to send packets smaller than MSS */
|
||||
|
||||
#define FREERTOS_SO_STOP_RX ( 15 ) /* Tempoarily hold up reception, used by streaming client */
|
||||
|
||||
#if( ipconfigUDP_MAX_RX_PACKETS > 0 )
|
||||
#define FREERTOS_SO_UDP_MAX_RX_PACKETS ( 16 ) /* This option helps to limit the maximum number of packets a UDP socket will buffer */
|
||||
#endif
|
||||
|
||||
#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. */
|
||||
|
||||
/* Values for flag for FreeRTOS_shutdown(). */
|
||||
#define FREERTOS_SHUT_RD ( 0 ) /* Not really at this moment, just for compatibility of the interface */
|
||||
#define FREERTOS_SHUT_WR ( 1 )
|
||||
#define FREERTOS_SHUT_RDWR ( 2 )
|
||||
|
||||
/* Values for flag for FreeRTOS_recv(). */
|
||||
#define FREERTOS_MSG_OOB ( 2 ) /* process out-of-band data */
|
||||
#define FREERTOS_MSG_PEEK ( 4 ) /* peek at incoming message */
|
||||
#define FREERTOS_MSG_DONTROUTE ( 8 ) /* send without using routing tables */
|
||||
#define FREERTOS_MSG_DONTWAIT ( 16 ) /* Can be used with recvfrom(), sendto(), recv(), and send(). */
|
||||
|
||||
typedef struct xWIN_PROPS {
|
||||
/* Properties of the Tx buffer and Tx window */
|
||||
int32_t lTxBufSize; /* Unit: bytes */
|
||||
int32_t lTxWinSize; /* Unit: MSS */
|
||||
|
||||
/* Properties of the Rx buffer and Rx window */
|
||||
int32_t lRxBufSize; /* Unit: bytes */
|
||||
int32_t lRxWinSize; /* Unit: MSS */
|
||||
} WinProperties_t;
|
||||
|
||||
/* 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
|
||||
{
|
||||
/* _HT_ On 32- and 64-bit architectures, the addition of the two uint8_t
|
||||
fields doesn't make the structure bigger, due to alignment.
|
||||
The fields are inserted as a preparation for IPv6. */
|
||||
|
||||
/* sin_len and sin_family not used in the IPv4-only release. */
|
||||
uint8_t sin_len; /* length of this structure. */
|
||||
uint8_t sin_family; /* FREERTOS_AF_INET. */
|
||||
uint16_t sin_port;
|
||||
uint32_t sin_addr;
|
||||
};
|
||||
|
||||
#if ipconfigBYTE_ORDER == pdFREERTOS_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 ), "%u.%u.%u.%u", \
|
||||
( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ), \
|
||||
( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \
|
||||
( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\
|
||||
( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ) )
|
||||
|
||||
#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 ), "%u.%u.%u.%u", \
|
||||
( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ), \
|
||||
( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\
|
||||
( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \
|
||||
( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ) )
|
||||
|
||||
#endif /* ipconfigBYTE_ORDER */
|
||||
|
||||
/* The socket type itself. */
|
||||
typedef void *Socket_t;
|
||||
|
||||
/* The SocketSet_t type is the equivalent to the fd_set type used by the
|
||||
Berkeley API. */
|
||||
typedef void *SocketSet_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_TCP/FreeRTOS_TCP_API_Functions.html
|
||||
*/
|
||||
Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol );
|
||||
int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength );
|
||||
int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength );
|
||||
BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );
|
||||
|
||||
/* function to get the local address and IP port */
|
||||
size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );
|
||||
|
||||
/* Made available when ipconfigETHERNET_DRIVER_FILTERS_PACKETS is set to 1. */
|
||||
BaseType_t xPortHasUDPSocket( uint16_t usPortNr );
|
||||
|
||||
#if ipconfigUSE_TCP == 1
|
||||
|
||||
BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );
|
||||
BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog );
|
||||
BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags );
|
||||
BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags );
|
||||
Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength );
|
||||
BaseType_t FreeRTOS_shutdown (Socket_t xSocket, BaseType_t xHow);
|
||||
|
||||
#if( ipconfigSUPPORT_SIGNALS != 0 )
|
||||
/* Send a signal to the task which is waiting for a given socket. */
|
||||
BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket );
|
||||
|
||||
/* Send a signal to the task which reads from this socket (FromISR
|
||||
version). */
|
||||
BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
#endif /* ipconfigSUPPORT_SIGNALS */
|
||||
|
||||
/* Return the remote address and IP port. */
|
||||
BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );
|
||||
|
||||
/* returns pdTRUE if TCP socket is connected */
|
||||
BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket );
|
||||
|
||||
/* returns the actual size of MSS being used */
|
||||
BaseType_t FreeRTOS_mss( Socket_t xSocket );
|
||||
|
||||
/* for internal use only: return the connection status */
|
||||
BaseType_t FreeRTOS_connstatus( Socket_t xSocket );
|
||||
|
||||
/* Returns the number of bytes that may be added to txStream */
|
||||
BaseType_t FreeRTOS_maywrite( Socket_t xSocket );
|
||||
|
||||
/*
|
||||
* Two helper functions, mostly for testing
|
||||
* rx_size returns the number of bytes available in the Rx buffer
|
||||
* tx_space returns the free space in the Tx buffer
|
||||
*/
|
||||
BaseType_t FreeRTOS_rx_size( Socket_t xSocket );
|
||||
BaseType_t FreeRTOS_tx_space( Socket_t xSocket );
|
||||
BaseType_t FreeRTOS_tx_size( Socket_t xSocket );
|
||||
|
||||
/* Returns the number of outstanding bytes in txStream. */
|
||||
/* The function FreeRTOS_outstanding() was already implemented
|
||||
FreeRTOS_tx_size(). */
|
||||
#define FreeRTOS_outstanding( xSocket ) FreeRTOS_tx_size( xSocket )
|
||||
|
||||
/* Returns the number of bytes in the socket's rxStream. */
|
||||
/* The function FreeRTOS_recvcount() was already implemented
|
||||
FreeRTOS_rx_size(). */
|
||||
#define FreeRTOS_recvcount( xSocket ) FreeRTOS_rx_size( xSocket )
|
||||
|
||||
/*
|
||||
* For advanced applications only:
|
||||
* Get a direct pointer to the circular transmit buffer.
|
||||
* '*pxLength' will contain the number of bytes that may be written.
|
||||
*/
|
||||
uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength );
|
||||
|
||||
#endif /* ipconfigUSE_TCP */
|
||||
|
||||
/*
|
||||
* Connect / disconnect handler for a TCP socket
|
||||
* For example:
|
||||
* static void vMyConnectHandler (Socket_t xSocket, BaseType_t ulConnected)
|
||||
* {
|
||||
* }
|
||||
* F_TCP_UDP_Handler_t xHnd = { vMyConnectHandler };
|
||||
* FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_CONN_HANDLER, ( void * ) &xHnd, sizeof( xHnd ) );
|
||||
*/
|
||||
|
||||
typedef void (* FOnConnected_t )( Socket_t /* xSocket */, BaseType_t /* ulConnected */ );
|
||||
|
||||
/*
|
||||
* Reception handler for a TCP socket
|
||||
* A user-proved function will be called on reception of a message
|
||||
* If the handler returns a positive number, the messages will not be stored
|
||||
* For example:
|
||||
* static BaseType_t xOnTCPReceive( Socket_t xSocket, void * pData, size_t xLength )
|
||||
* {
|
||||
* // handle the message
|
||||
* return 1;
|
||||
* }
|
||||
* F_TCP_UDP_Handler_t xHand = { xOnTCPReceive };
|
||||
* FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_RECV_HANDLER, ( void * ) &xHand, sizeof( xHand ) );
|
||||
*/
|
||||
typedef BaseType_t (* FOnTCPReceive_t )( Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */ );
|
||||
typedef void (* FOnTCPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ );
|
||||
|
||||
/*
|
||||
* Reception handler for a UDP socket
|
||||
* A user-proved function will be called on reception of a message
|
||||
* If the handler returns a positive number, the messages will not be stored
|
||||
*/
|
||||
typedef BaseType_t (* FOnUDPReceive_t ) (Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */,
|
||||
const struct freertos_sockaddr * /* pxFrom */, const struct freertos_sockaddr * /* pxDest */ );
|
||||
typedef void (* FOnUDPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ );
|
||||
|
||||
|
||||
typedef union xTCP_UDP_HANDLER
|
||||
{
|
||||
FOnConnected_t pxOnTCPConnected; /* FREERTOS_SO_TCP_CONN_HANDLER */
|
||||
FOnTCPReceive_t pxOnTCPReceive; /* FREERTOS_SO_TCP_RECV_HANDLER */
|
||||
FOnTCPSent_t pxOnTCPSent; /* FREERTOS_SO_TCP_SENT_HANDLER */
|
||||
FOnUDPReceive_t pxOnUDPReceive; /* FREERTOS_SO_UDP_RECV_HANDLER */
|
||||
FOnUDPSent_t pxOnUDPSent; /* FREERTOS_SO_UDP_SENT_HANDLER */
|
||||
} F_TCP_UDP_Handler_t;
|
||||
|
||||
BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength );
|
||||
BaseType_t FreeRTOS_closesocket( Socket_t xSocket );
|
||||
uint32_t FreeRTOS_gethostbyname( const char *pcHostName );
|
||||
uint32_t FreeRTOS_inet_addr( const char * pcIPAddress );
|
||||
|
||||
/*
|
||||
* For the web server: borrow the circular Rx buffer for inspection
|
||||
* HTML driver wants to see if a sequence of 13/10/13/10 is available
|
||||
*/
|
||||
const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket );
|
||||
|
||||
void FreeRTOS_netstat( void );
|
||||
|
||||
#if ipconfigSUPPORT_SELECT_FUNCTION == 1
|
||||
|
||||
/* For FD_SET and FD_CLR, a combination of the following bits can be used: */
|
||||
|
||||
typedef enum eSELECT_EVENT {
|
||||
eSELECT_READ = 0x0001,
|
||||
eSELECT_WRITE = 0x0002,
|
||||
eSELECT_EXCEPT = 0x0004,
|
||||
eSELECT_INTR = 0x0008,
|
||||
eSELECT_ALL = 0x000F,
|
||||
/* Reserved for internal use: */
|
||||
eSELECT_CALL_IP = 0x0010,
|
||||
/* end */
|
||||
} eSelectEvent_t;
|
||||
|
||||
SocketSet_t FreeRTOS_CreateSocketSet( void );
|
||||
void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet );
|
||||
void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xBitsToSet );
|
||||
void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xBitsToClear );
|
||||
EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet );
|
||||
BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks );
|
||||
|
||||
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_SOCKETS_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* FreeRTOS_Stream_Buffer.h
|
||||
*
|
||||
* A cicular character buffer
|
||||
* An implementation of a circular buffer without a length field
|
||||
* If LENGTH defines the size of the buffer, a maximum of (LENGT-1) bytes can be stored
|
||||
* In order to add or read data from the buffer, memcpy() will be called at most 2 times
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_STREAM_BUFFER_H
|
||||
#define FREERTOS_STREAM_BUFFER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct xSTREAM_BUFFER {
|
||||
volatile size_t uxTail; /* next item to read */
|
||||
volatile size_t uxMid; /* iterator within the valid items */
|
||||
volatile size_t uxHead; /* next position store a new item */
|
||||
volatile size_t uxFront; /* iterator within the free space */
|
||||
size_t LENGTH; /* const value: number of reserved elements */
|
||||
uint8_t ucArray[ sizeof( size_t ) ];
|
||||
} StreamBuffer_t;
|
||||
|
||||
static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer );
|
||||
static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer )
|
||||
{
|
||||
/* Make the circular buffer empty */
|
||||
pxBuffer->uxHead = 0u;
|
||||
pxBuffer->uxTail = 0u;
|
||||
pxBuffer->uxFront = 0u;
|
||||
pxBuffer->uxMid = 0u;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );
|
||||
static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )
|
||||
{
|
||||
/* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */
|
||||
size_t uxCount;
|
||||
|
||||
uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1u;
|
||||
if( uxCount >= pxBuffer->LENGTH )
|
||||
{
|
||||
uxCount -= pxBuffer->LENGTH;
|
||||
}
|
||||
|
||||
return uxCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );
|
||||
static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )
|
||||
{
|
||||
/* Returns the distance between uxLower and uxUpper */
|
||||
size_t uxCount;
|
||||
|
||||
uxCount = pxBuffer->LENGTH + uxUpper - uxLower;
|
||||
if ( uxCount >= pxBuffer->LENGTH )
|
||||
{
|
||||
uxCount -= pxBuffer->LENGTH;
|
||||
}
|
||||
|
||||
return uxCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer );
|
||||
static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer )
|
||||
{
|
||||
/* Returns the number of items which can still be added to uxHead
|
||||
before hitting on uxTail */
|
||||
size_t uxHead = pxBuffer->uxHead;
|
||||
size_t uxTail = pxBuffer->uxTail;
|
||||
|
||||
return uxStreamBufferSpace( pxBuffer, uxHead, uxTail );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer );
|
||||
static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer )
|
||||
{
|
||||
/* Distance between uxFront and uxTail
|
||||
or the number of items which can still be added to uxFront,
|
||||
before hitting on uxTail */
|
||||
|
||||
size_t uxFront = pxBuffer->uxFront;
|
||||
size_t uxTail = pxBuffer->uxTail;
|
||||
|
||||
return uxStreamBufferSpace( pxBuffer, uxFront, uxTail );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer );
|
||||
static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer )
|
||||
{
|
||||
/* Returns the number of items which can be read from uxTail
|
||||
before reaching uxHead */
|
||||
size_t uxHead = pxBuffer->uxHead;
|
||||
size_t uxTail = pxBuffer->uxTail;
|
||||
|
||||
return uxStreamBufferDistance( pxBuffer, uxTail, uxHead );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer );
|
||||
static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer )
|
||||
{
|
||||
/* Returns the distance between uxHead and uxMid */
|
||||
size_t uxHead = pxBuffer->uxHead;
|
||||
size_t uxMid = pxBuffer->uxMid;
|
||||
|
||||
return uxStreamBufferDistance( pxBuffer, uxMid, uxHead );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount );
|
||||
static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount )
|
||||
{
|
||||
/* Increment uxMid, but no further than uxHead */
|
||||
size_t uxSize = uxStreamBufferMidSpace( pxBuffer );
|
||||
|
||||
if( uxCount > uxSize )
|
||||
{
|
||||
uxCount = uxSize;
|
||||
}
|
||||
pxBuffer->uxMid += uxCount;
|
||||
if( pxBuffer->uxMid >= pxBuffer->LENGTH )
|
||||
{
|
||||
pxBuffer->uxMid -= pxBuffer->LENGTH;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer );
|
||||
static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* True if no item is available */
|
||||
if( pxBuffer->uxHead == pxBuffer->uxTail )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer );
|
||||
static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer )
|
||||
{
|
||||
/* True if the available space equals zero. */
|
||||
return ( BaseType_t ) ( uxStreamBufferGetSpace( pxBuffer ) == 0u );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight );
|
||||
static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
size_t uxTail = pxBuffer->uxTail;
|
||||
|
||||
/* Returns true if ( uxLeft < uxRight ) */
|
||||
if( ( uxLeft < uxTail ) ^ ( uxRight < uxTail ) )
|
||||
{
|
||||
if( uxRight < uxTail )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( uxLeft <= uxRight )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
}
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData );
|
||||
static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData )
|
||||
{
|
||||
size_t uxNextTail = pxBuffer->uxTail;
|
||||
size_t uxSize = uxStreamBufferGetSize( pxBuffer );
|
||||
|
||||
*ppucData = pxBuffer->ucArray + uxNextTail;
|
||||
|
||||
return FreeRTOS_min_uint32( uxSize, pxBuffer->LENGTH - uxNextTail );
|
||||
}
|
||||
|
||||
/*
|
||||
* Add bytes to a stream buffer.
|
||||
*
|
||||
* pxBuffer - The buffer to which the bytes will be added.
|
||||
* uxOffset - If uxOffset > 0, data will be written at an offset from uxHead
|
||||
* while uxHead will not be moved yet.
|
||||
* pucData - A pointer to the data to be added.
|
||||
* uxCount - The number of bytes to add.
|
||||
*/
|
||||
size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount );
|
||||
|
||||
/*
|
||||
* Read bytes from a stream buffer.
|
||||
*
|
||||
* pxBuffer - The buffer from which the bytes will be read.
|
||||
* uxOffset - Can be used to read data located at a certain offset from 'uxTail'.
|
||||
* pucData - A pointer to the buffer into which data will be read.
|
||||
* uxMaxCount - The number of bytes to read.
|
||||
* xPeek - If set to pdTRUE the data will remain in the buffer.
|
||||
*/
|
||||
size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek );
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* !defined( FREERTOS_STREAM_BUFFER_H ) */
|
||||
112
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h
Normal file
112
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_TCP_IP_H
|
||||
#define FREERTOS_TCP_IP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
|
||||
|
||||
typedef enum eTCP_STATE {
|
||||
/* Comments about the TCP states are borrowed from the very useful
|
||||
* Wiki page:
|
||||
* http://en.wikipedia.org/wiki/Transmission_Control_Protocol */
|
||||
eCLOSED = 0u, /* 0 (server + client) no connection state at all. */
|
||||
eTCP_LISTEN, /* 1 (server) waiting for a connection request
|
||||
from any remote TCP and port. */
|
||||
eCONNECT_SYN, /* 2 (client) internal state: socket wants to send
|
||||
a connect */
|
||||
eSYN_FIRST, /* 3 (server) Just created, must ACK the SYN request. */
|
||||
eSYN_RECEIVED, /* 4 (server) waiting for a confirming connection request
|
||||
acknowledgement after having both received and sent a connection request. */
|
||||
eESTABLISHED, /* 5 (server + client) an open connection, data received can be
|
||||
delivered to the user. The normal state for the data transfer phase of the connection. */
|
||||
eFIN_WAIT_1, /* 6 (server + client) waiting for a connection termination request from the remote TCP,
|
||||
or an acknowledgement of the connection termination request previously sent. */
|
||||
eFIN_WAIT_2, /* 7 (server + client) waiting for a connection termination request from the remote TCP. */
|
||||
eCLOSE_WAIT, /* 8 (server + client) waiting for a connection termination request from the local user. */
|
||||
eCLOSING, /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
|
||||
eLAST_ACK, /* 9 (server + client) waiting for an acknowledgement of the connection termination request
|
||||
previously sent to the remote TCP
|
||||
(which includes an acknowledgement of its connection termination request). */
|
||||
eTIME_WAIT, /* 10 (either server or client) waiting for enough time to pass to be sure the remote TCP received the
|
||||
acknowledgement of its connection termination request. [According to RFC 793 a connection can
|
||||
stay in TIME-WAIT for a maximum of four minutes known as a MSL (maximum segment lifetime).] */
|
||||
} eIPTCPState_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_TCP_IP_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* FreeRTOS_TCP_WIN.c
|
||||
* Module which handles the TCP windowing schemes for FreeRTOS-PLUS-TCP
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_TCP_WIN_H
|
||||
#define FREERTOS_TCP_WIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern BaseType_t xTCPWindowLoggingLevel;
|
||||
|
||||
typedef struct xTCPTimer
|
||||
{
|
||||
uint32_t ulBorn;
|
||||
} TCPTimer_t;
|
||||
|
||||
typedef struct xTCP_SEGMENT
|
||||
{
|
||||
uint32_t ulSequenceNumber; /* The sequence number of the first byte in this packet */
|
||||
int32_t lMaxLength; /* Maximum space, number of bytes which can be stored in this segment */
|
||||
int32_t lDataLength; /* Actual number of bytes */
|
||||
int32_t lStreamPos; /* reference to the [t|r]xStream of the socket */
|
||||
TCPTimer_t xTransmitTimer; /* saves a timestamp at the moment this segment gets transmitted (TX only) */
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t
|
||||
ucTransmitCount : 8,/* Number of times the segment has been transmitted, used to calculate the RTT */
|
||||
ucDupAckCount : 8, /* Counts the number of times that a higher segment was ACK'd. After 3 times a Fast Retransmission takes place */
|
||||
bOutstanding : 1, /* It the peer's turn, we're just waiting for an ACK */
|
||||
bAcked : 1, /* This segment has been acknowledged */
|
||||
bIsForRx : 1; /* pdTRUE if segment is used for reception */
|
||||
} bits;
|
||||
uint32_t ulFlags;
|
||||
} u;
|
||||
#if( ipconfigUSE_TCP_WIN != 0 )
|
||||
struct xLIST_ITEM xQueueItem; /* TX only: segments can be linked in one of three queues: xPriorityQueue, xTxQueue, and xWaitQueue */
|
||||
struct xLIST_ITEM xListItem; /* With this item the segment can be connected to a list, depending on who is owning it */
|
||||
#endif
|
||||
} TCPSegment_t;
|
||||
|
||||
typedef struct xTCP_WINSIZE
|
||||
{
|
||||
uint32_t ulRxWindowLength;
|
||||
uint32_t ulTxWindowLength;
|
||||
} TCPWinSize_t;
|
||||
|
||||
/*
|
||||
* If TCP time-stamps are being used, they will occupy 12 bytes in
|
||||
* each packet, and thus the message space will become smaller
|
||||
*/
|
||||
/* Keep this as a multiple of 4 */
|
||||
#if( ipconfigUSE_TCP_WIN == 1 )
|
||||
#if( ipconfigUSE_TCP_TIMESTAMPS == 1 )
|
||||
#define ipSIZE_TCP_OPTIONS ( 16u + 12u )
|
||||
#else
|
||||
#define ipSIZE_TCP_OPTIONS 16u
|
||||
#endif
|
||||
#else
|
||||
#if ipconfigUSE_TCP_TIMESTAMPS == 1
|
||||
#define ipSIZE_TCP_OPTIONS ( 12u + 12u )
|
||||
#else
|
||||
#define ipSIZE_TCP_OPTIONS 12u
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Every TCP connection owns a TCP window for the administration of all packets
|
||||
* It owns two sets of segment descriptors, incoming and outgoing
|
||||
*/
|
||||
typedef struct xTCP_WINDOW
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t
|
||||
bHasInit : 1, /* The window structure has been initialised */
|
||||
bSendFullSize : 1, /* May only send packets with a size equal to MSS (for optimisation) */
|
||||
bTimeStamps : 1; /* Socket is supposed to use TCP time-stamps. This depends on the */
|
||||
} bits; /* party which opens the connection */
|
||||
uint32_t ulFlags;
|
||||
} u;
|
||||
TCPWinSize_t xSize;
|
||||
struct
|
||||
{
|
||||
uint32_t ulFirstSequenceNumber; /* Logging & debug: the first segment received/sent in this connection
|
||||
* for Tx: initial send sequence number (ISS)
|
||||
* for Rx: initial receive sequence number (IRS) */
|
||||
uint32_t ulCurrentSequenceNumber;/* Tx/Rx: the oldest sequence number not yet confirmed, also SND.UNA / RCV.NXT
|
||||
* In other words: the sequence number of the left side of the sliding window */
|
||||
uint32_t ulFINSequenceNumber; /* The sequence number which carried the FIN flag */
|
||||
uint32_t ulHighestSequenceNumber;/* Sequence number of the right-most byte + 1 */
|
||||
#if( ipconfigUSE_TCP_TIMESTAMPS == 1 )
|
||||
uint32_t ulTimeStamp; /* The value of the TCP timestamp, transmitted or received */
|
||||
#endif
|
||||
} rx, tx;
|
||||
uint32_t ulOurSequenceNumber; /* The SEQ number we're sending out */
|
||||
uint32_t ulUserDataLength; /* Number of bytes in Rx buffer which may be passed to the user, after having received a 'missing packet' */
|
||||
uint32_t ulNextTxSequenceNumber; /* The sequence number given to the next byte to be added for transmission */
|
||||
int32_t lSRTT; /* Smoothed Round Trip Time, it may increment quickly and it decrements slower */
|
||||
uint8_t ucOptionLength; /* Number of valid bytes in ulOptionsData[] */
|
||||
#if( ipconfigUSE_TCP_WIN == 1 )
|
||||
List_t xPriorityQueue; /* Priority queue: segments which must be sent immediately */
|
||||
List_t xTxQueue; /* Transmit queue: segments queued for transmission */
|
||||
List_t xWaitQueue; /* Waiting queue: outstanding segments */
|
||||
TCPSegment_t *pxHeadSegment; /* points to a segment which has not been transmitted and it's size is still growing (user data being added) */
|
||||
uint32_t ulOptionsData[ipSIZE_TCP_OPTIONS/sizeof(uint32_t)]; /* Contains the options we send out */
|
||||
List_t xTxSegments; /* A linked list of all transmission segments, sorted on sequence number */
|
||||
List_t xRxSegments; /* A linked list of reception segments, order depends on sequence of arrival */
|
||||
#else
|
||||
/* For tiny TCP, there is only 1 outstanding TX segment */
|
||||
TCPSegment_t xTxSegment; /* Priority queue */
|
||||
#endif
|
||||
uint16_t usOurPortNumber; /* Mostly for debugging/logging: our TCP port number */
|
||||
uint16_t usPeerPortNumber; /* debugging/logging: the peer's TCP port number */
|
||||
uint16_t usMSS; /* Current accepted MSS */
|
||||
uint16_t usMSSInit; /* MSS as configured by the socket owner */
|
||||
} TCPWindow_t;
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
*
|
||||
* Creation and destruction
|
||||
*
|
||||
*=============================================================================*/
|
||||
|
||||
/* Create and initialize a window */
|
||||
void vTCPWindowCreate( TCPWindow_t *pxWindow, uint32_t ulRxWindowLength,
|
||||
uint32_t ulTxWindowLength, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS );
|
||||
|
||||
/* Destroy a window (always returns NULL)
|
||||
* It will free some resources: a collection of segments */
|
||||
void vTCPWindowDestroy( TCPWindow_t *pxWindow );
|
||||
|
||||
/* Initialize a window */
|
||||
void vTCPWindowInit( TCPWindow_t *pxWindow, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS );
|
||||
|
||||
/*=============================================================================
|
||||
*
|
||||
* Rx functions
|
||||
*
|
||||
*=============================================================================*/
|
||||
|
||||
/* if true may be passed directly to user (segment expected and window is empty)
|
||||
* But pxWindow->ackno should always be used to set "BUF->ackno" */
|
||||
int32_t lTCPWindowRxCheck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength, uint32_t ulSpace );
|
||||
|
||||
/* When lTCPWindowRxCheck returned false, please call store for this unexpected data */
|
||||
BaseType_t xTCPWindowRxStore( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength );
|
||||
|
||||
/* This function will be called as soon as a FIN is received. It will return true
|
||||
* if there are no 'open' reception segments */
|
||||
BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow );
|
||||
|
||||
/* _HT_ Temporary function for testing/debugging
|
||||
* Not used at this moment */
|
||||
void vTCPWinShowSegments( TCPWindow_t *pxWindow, BaseType_t bForRx );
|
||||
|
||||
/*=============================================================================
|
||||
*
|
||||
* Tx functions
|
||||
*
|
||||
*=============================================================================*/
|
||||
|
||||
/* Adds data to the Tx-window */
|
||||
int32_t lTCPWindowTxAdd( TCPWindow_t *pxWindow, uint32_t ulLength, int32_t lPosition, int32_t lMax );
|
||||
|
||||
/* Check data to be sent and calculate the time period we may sleep */
|
||||
BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay );
|
||||
|
||||
/* See if anything is left to be sent
|
||||
* Function will be called when a FIN has been received. Only when the TX window is clean,
|
||||
* it will return pdTRUE */
|
||||
BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow );
|
||||
|
||||
/* Fetches data to be sent.
|
||||
* apPos will point to a location with the circular data buffer: txStream */
|
||||
uint32_t ulTCPWindowTxGet( TCPWindow_t *pxWindow, uint32_t ulWindowSize, int32_t *plPosition );
|
||||
|
||||
/* Receive a normal ACK */
|
||||
uint32_t ulTCPWindowTxAck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber );
|
||||
|
||||
/* Receive a SACK option */
|
||||
uint32_t ulTCPWindowTxSack( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_TCP_WIN_H */
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_UDP_IP_H
|
||||
#define FREERTOS_UDP_IP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Application level configuration options. */
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
#include "FreeRTOSIPConfigDefaults.h"
|
||||
#include "IPTraceMacroDefaults.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_UDP_IP_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_ERRNO_TCP
|
||||
#define FREERTOS_ERRNO_TCP
|
||||
|
||||
/* The following definitions will be included in the core FreeRTOS code in
|
||||
future versions of FreeRTOS - hence the 'pd' (ProjDefs) prefix - at which time
|
||||
this file will be removed. */
|
||||
|
||||
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
|
||||
itself. */
|
||||
|
||||
/* For future compatibility (see comment above), check the definitions have not
|
||||
already been made. */
|
||||
#ifndef pdFREERTOS_ERRNO_NONE
|
||||
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
|
||||
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
|
||||
#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
|
||||
#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
|
||||
#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
|
||||
#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
|
||||
#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
|
||||
#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
|
||||
#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
|
||||
#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
|
||||
#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
|
||||
#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
|
||||
#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
|
||||
#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
|
||||
#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
|
||||
#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
|
||||
#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
|
||||
#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
|
||||
#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
|
||||
#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
|
||||
#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
|
||||
#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
|
||||
#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
|
||||
#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
|
||||
#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
|
||||
#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
|
||||
#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
|
||||
#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
|
||||
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
|
||||
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
|
||||
#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
|
||||
#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
|
||||
#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
|
||||
#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
|
||||
#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
|
||||
#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
|
||||
#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
|
||||
#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
|
||||
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
|
||||
|
||||
/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
|
||||
itself. */
|
||||
#define pdFREERTOS_LITTLE_ENDIAN 0
|
||||
#define pdFREERTOS_BIG_ENDIAN 1
|
||||
|
||||
#endif /* pdFREERTOS_ERRNO_NONE */
|
||||
|
||||
#endif /* FREERTOS_ERRNO_TCP */
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* 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_TCP/TCP_IP_Trace.html */
|
||||
|
||||
#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 iptraceFAILED_TO_CREATE_EVENT_GROUP
|
||||
#define iptraceFAILED_TO_CREATE_EVENT_GROUP()
|
||||
#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 iptraceDHCP_SUCCEDEED
|
||||
#define iptraceDHCP_SUCCEDEED( address )
|
||||
#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
|
||||
|
||||
#ifndef pvPortMallocSocket
|
||||
#define pvPortMallocSocket(xSize) pvPortMalloc( ( xSize ) )
|
||||
#endif
|
||||
|
||||
#ifndef iptraceRECVFROM_TIMEOUT
|
||||
#define iptraceRECVFROM_TIMEOUT()
|
||||
#endif
|
||||
|
||||
#ifndef iptraceRECVFROM_INTERRUPTED
|
||||
#define iptraceRECVFROM_INTERRUPTED()
|
||||
#endif
|
||||
|
||||
#ifndef iptraceNO_BUFFER_FOR_SENDTO
|
||||
#define iptraceNO_BUFFER_FOR_SENDTO()
|
||||
#endif
|
||||
|
||||
#ifndef iptraceSENDTO_SOCKET_NOT_BOUND
|
||||
#define iptraceSENDTO_SOCKET_NOT_BOUND()
|
||||
#endif
|
||||
|
||||
#ifndef iptraceSENDTO_DATA_TOO_LONG
|
||||
#define iptraceSENDTO_DATA_TOO_LONG()
|
||||
#endif
|
||||
|
||||
#endif /* UDP_TRACE_MACRO_DEFAULTS_H */
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_BUFFER_MANAGEMENT_H
|
||||
#define NETWORK_BUFFER_MANAGEMENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* NOTE PUBLIC API FUNCTIONS. */
|
||||
BaseType_t xNetworkBuffersInitialise( void );
|
||||
NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks );
|
||||
NetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes );
|
||||
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer );
|
||||
BaseType_t vNetworkBufferReleaseFromISR( NetworkBufferDescriptor_t * const pxNetworkBuffer );
|
||||
uint8_t *pucGetNetworkBuffer( size_t *pxRequestedSizeBytes );
|
||||
void vReleaseNetworkBuffer( uint8_t *pucEthernetBuffer );
|
||||
|
||||
/* Get the current number of free network buffers. */
|
||||
UBaseType_t uxGetNumberOfFreeNetworkBuffers( void );
|
||||
|
||||
/* Get the lowest number of free network buffers. */
|
||||
UBaseType_t uxGetMinimumFreeNetworkBuffers( void );
|
||||
|
||||
/* Copy a network buffer into a bigger buffer. */
|
||||
NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer,
|
||||
BaseType_t xNewLength);
|
||||
|
||||
/* Increase the size of a Network Buffer.
|
||||
In case BufferAllocation_2.c is used, the new space must be allocated. */
|
||||
NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer,
|
||||
size_t xNewSizeBytes );
|
||||
|
||||
#if ipconfigTCP_IP_SANITY
|
||||
/*
|
||||
* Check if an address is a valid pointer to a network descriptor
|
||||
* by looking it up in the array of network descriptors
|
||||
*/
|
||||
UBaseType_t bIsValidNetworkDescriptor (const NetworkBufferDescriptor_t * pxDesc);
|
||||
BaseType_t prvIsFreeBuffer( const NetworkBufferDescriptor_t *pxDescr );
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* NETWORK_BUFFER_MANAGEMENT_H */
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_INTERFACE_H
|
||||
#define NETWORK_INTERFACE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* NOTE PUBLIC API FUNCTIONS. */
|
||||
BaseType_t xNetworkInterfaceInitialise( void );
|
||||
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend );
|
||||
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] );
|
||||
BaseType_t xGetPhyLinkStatus( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* NETWORK_INTERFACE_H */
|
||||
|
||||
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* See the following web page for essential buffer allocation scheme usage and
|
||||
* configuration details:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
/* For an Ethernet interrupt to be able to obtain a network buffer there must
|
||||
be at least this number of buffers available. */
|
||||
#define baINTERRUPT_BUFFER_GET_THRESHOLD ( 3 )
|
||||
|
||||
/* A list of free (available) NetworkBufferDescriptor_t structures. */
|
||||
static List_t xFreeBuffersList;
|
||||
|
||||
/* Some statistics about the use of buffers. */
|
||||
static UBaseType_t uxMinimumFreeNetworkBuffers = 0u;
|
||||
|
||||
/* Declares the pool of NetworkBufferDescriptor_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 NetworkBufferDescriptor_t xNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];
|
||||
|
||||
/* This constant is defined as true to let FreeRTOS_TCP_IP.c know that the
|
||||
network buffers have constant size, large enough to hold the biggest Ethernet
|
||||
packet. No resizing will be done. */
|
||||
const BaseType_t xBufferAllocFixedSize = pdTRUE;
|
||||
|
||||
/* The semaphore used to obtain network buffers. */
|
||||
static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;
|
||||
|
||||
#if( ipconfigTCP_IP_SANITY != 0 )
|
||||
static char cIsLow = pdFALSE;
|
||||
UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc );
|
||||
#else
|
||||
static UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc );
|
||||
#endif /* ipconfigTCP_IP_SANITY */
|
||||
|
||||
static void prvShowWarnings( void );
|
||||
|
||||
/* The user can define their own ipconfigBUFFER_ALLOC_LOCK() and
|
||||
ipconfigBUFFER_ALLOC_UNLOCK() macros, especially for use form an ISR. If these
|
||||
are not defined then default them to call the normal enter/exit critical
|
||||
section macros. */
|
||||
#if !defined( ipconfigBUFFER_ALLOC_LOCK )
|
||||
|
||||
#define ipconfigBUFFER_ALLOC_INIT( ) do {} while (0)
|
||||
#define ipconfigBUFFER_ALLOC_LOCK_FROM_ISR() \
|
||||
UBaseType_t uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \
|
||||
{
|
||||
|
||||
#define ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR() \
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
|
||||
}
|
||||
|
||||
#define ipconfigBUFFER_ALLOC_LOCK() taskENTER_CRITICAL()
|
||||
#define ipconfigBUFFER_ALLOC_UNLOCK() taskEXIT_CRITICAL()
|
||||
|
||||
#endif /* ipconfigBUFFER_ALLOC_LOCK */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigTCP_IP_SANITY != 0 )
|
||||
|
||||
/* HT: SANITY code will be removed as soon as the library is stable
|
||||
* and and ready to become public
|
||||
* Function below gives information about the use of buffers */
|
||||
#define WARN_LOW ( 2 )
|
||||
#define WARN_HIGH ( ( 5 * ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) / 10 )
|
||||
|
||||
#endif /* ipconfigTCP_IP_SANITY */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigTCP_IP_SANITY != 0 )
|
||||
|
||||
BaseType_t prvIsFreeBuffer( const NetworkBufferDescriptor_t *pxDescr )
|
||||
{
|
||||
return ( bIsValidNetworkDescriptor( pxDescr ) != 0 ) &&
|
||||
( listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxDescr->xBufferListItem ) ) != 0 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvShowWarnings( void )
|
||||
{
|
||||
UBaseType_t uxCount = uxGetNumberOfFreeNetworkBuffers( );
|
||||
if( ( ( cIsLow == 0 ) && ( uxCount <= WARN_LOW ) ) || ( ( cIsLow != 0 ) && ( uxCount >= WARN_HIGH ) ) )
|
||||
{
|
||||
cIsLow = !cIsLow;
|
||||
FreeRTOS_debug_printf( ( "*** Warning *** %s %lu buffers left\n", cIsLow ? "only" : "now", uxCount ) );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc )
|
||||
{
|
||||
uint32_t offset = ( uint32_t ) ( ((const char *)pxDesc) - ((const char *)xNetworkBuffers) );
|
||||
if( ( offset >= sizeof( xNetworkBuffers ) ) ||
|
||||
( ( offset % sizeof( xNetworkBuffers[0] ) ) != 0 ) )
|
||||
return pdFALSE;
|
||||
return (UBaseType_t) (pxDesc - xNetworkBuffers) + 1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#else
|
||||
static UBaseType_t bIsValidNetworkDescriptor (const NetworkBufferDescriptor_t * pxDesc)
|
||||
{
|
||||
( void ) pxDesc;
|
||||
return ( UBaseType_t ) pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvShowWarnings( void )
|
||||
{
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* ipconfigTCP_IP_SANITY */
|
||||
|
||||
BaseType_t xNetworkBuffersInitialise( void )
|
||||
{
|
||||
BaseType_t xReturn, x;
|
||||
|
||||
/* Only initialise the buffers and their associated kernel objects if they
|
||||
have not been initialised before. */
|
||||
if( xNetworkBufferSemaphore == NULL )
|
||||
{
|
||||
/* In case alternative locking is used, the mutexes can be initialised
|
||||
here */
|
||||
ipconfigBUFFER_ALLOC_INIT();
|
||||
|
||||
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
|
||||
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_BUFFER_DESCRIPTORS; 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 ) );
|
||||
}
|
||||
|
||||
uxMinimumFreeNetworkBuffers = ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
|
||||
}
|
||||
}
|
||||
|
||||
if( xNetworkBufferSemaphore == NULL )
|
||||
{
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )
|
||||
{
|
||||
NetworkBufferDescriptor_t *pxReturn = NULL;
|
||||
BaseType_t xInvalid = pdFALSE;
|
||||
UBaseType_t uxCount;
|
||||
|
||||
/* The current implementation only has a single size memory block, so
|
||||
the requested size parameter is not used (yet). */
|
||||
( void ) xRequestedSizeBytes;
|
||||
|
||||
if( xNetworkBufferSemaphore != NULL )
|
||||
{
|
||||
/* 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. */
|
||||
ipconfigBUFFER_ALLOC_LOCK();
|
||||
{
|
||||
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
|
||||
|
||||
if( ( bIsValidNetworkDescriptor( pxReturn ) != pdFALSE_UNSIGNED ) &&
|
||||
listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxReturn->xBufferListItem ) ) )
|
||||
{
|
||||
uxListRemove( &( pxReturn->xBufferListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
xInvalid = pdTRUE;
|
||||
}
|
||||
}
|
||||
ipconfigBUFFER_ALLOC_UNLOCK();
|
||||
|
||||
if( xInvalid == pdTRUE )
|
||||
{
|
||||
/* _RB_ Can printf() be called from an interrupt? (comment
|
||||
above says this can be called from an interrupt too) */
|
||||
/* _HT_ The function shall not be called from an ISR. Comment
|
||||
was indeed misleading. Hopefully clear now?
|
||||
So the printf()is OK here. */
|
||||
FreeRTOS_debug_printf( ( "pxGetNetworkBufferWithDescriptor: INVALID BUFFER: %p (valid %lu)\n",
|
||||
pxReturn, bIsValidNetworkDescriptor( pxReturn ) ) );
|
||||
pxReturn = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reading UBaseType_t, no critical section needed. */
|
||||
uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );
|
||||
|
||||
/* For stats, latch the lowest number of network buffers since
|
||||
booting. */
|
||||
if( uxMinimumFreeNetworkBuffers > uxCount )
|
||||
{
|
||||
uxMinimumFreeNetworkBuffers = uxCount;
|
||||
}
|
||||
|
||||
pxReturn->xDataLength = xRequestedSizeBytes;
|
||||
|
||||
#if( ipconfigTCP_IP_SANITY != 0 )
|
||||
{
|
||||
prvShowWarnings();
|
||||
}
|
||||
#endif /* ipconfigTCP_IP_SANITY */
|
||||
|
||||
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
|
||||
{
|
||||
/* make sure the buffer is not linked */
|
||||
pxReturn->pxNextBuffer = NULL;
|
||||
}
|
||||
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
|
||||
|
||||
if( xTCPWindowLoggingLevel > 3 )
|
||||
{
|
||||
FreeRTOS_debug_printf( ( "BUF_GET[%ld]: %p (%p)\n",
|
||||
bIsValidNetworkDescriptor( pxReturn ),
|
||||
pxReturn, pxReturn->pucEthernetBuffer ) );
|
||||
}
|
||||
}
|
||||
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
|
||||
}
|
||||
else
|
||||
{
|
||||
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
|
||||
}
|
||||
}
|
||||
|
||||
return pxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
NetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes )
|
||||
{
|
||||
NetworkBufferDescriptor_t *pxReturn = NULL;
|
||||
|
||||
/* 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 baINTERRUPT_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( ( QueueHandle_t ) xNetworkBufferSemaphore ) > ( UBaseType_t ) baINTERRUPT_BUFFER_GET_THRESHOLD )
|
||||
{
|
||||
if( xSemaphoreTakeFromISR( xNetworkBufferSemaphore, NULL ) == pdPASS )
|
||||
{
|
||||
/* Protect the structure as it is accessed from tasks and interrupts. */
|
||||
ipconfigBUFFER_ALLOC_LOCK_FROM_ISR();
|
||||
{
|
||||
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
|
||||
uxListRemove( &( pxReturn->xBufferListItem ) );
|
||||
}
|
||||
ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();
|
||||
|
||||
iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxReturn );
|
||||
}
|
||||
}
|
||||
|
||||
if( pxReturn == NULL )
|
||||
{
|
||||
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR();
|
||||
}
|
||||
|
||||
return pxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t vNetworkBufferReleaseFromISR( NetworkBufferDescriptor_t * const pxNetworkBuffer )
|
||||
{
|
||||
BaseType_t 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. */
|
||||
ipconfigBUFFER_ALLOC_LOCK_FROM_ISR();
|
||||
{
|
||||
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
|
||||
}
|
||||
ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();
|
||||
|
||||
xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );
|
||||
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
|
||||
|
||||
return xHigherPriorityTaskWoken;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
|
||||
{
|
||||
BaseType_t xListItemAlreadyInFreeList;
|
||||
|
||||
if( bIsValidNetworkDescriptor( pxNetworkBuffer ) == pdFALSE_UNSIGNED )
|
||||
{
|
||||
FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) );
|
||||
return ;
|
||||
}
|
||||
/* Ensure the buffer is returned to the list of free buffers before the
|
||||
counting semaphore is 'given' to say a buffer is available. */
|
||||
ipconfigBUFFER_ALLOC_LOCK();
|
||||
{
|
||||
{
|
||||
xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
|
||||
|
||||
if( xListItemAlreadyInFreeList == pdFALSE )
|
||||
{
|
||||
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
ipconfigBUFFER_ALLOC_UNLOCK();
|
||||
|
||||
if( xListItemAlreadyInFreeList )
|
||||
{
|
||||
FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n",
|
||||
pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) );
|
||||
}
|
||||
if( xListItemAlreadyInFreeList == pdFALSE )
|
||||
{
|
||||
xSemaphoreGive( xNetworkBufferSemaphore );
|
||||
prvShowWarnings();
|
||||
if( xTCPWindowLoggingLevel > 3 )
|
||||
FreeRTOS_debug_printf( ( "BUF_PUT[%ld]: %p (%p) (now %lu)\n",
|
||||
bIsValidNetworkDescriptor( pxNetworkBuffer ),
|
||||
pxNetworkBuffer, pxNetworkBuffer->pucEthernetBuffer,
|
||||
uxGetNumberOfFreeNetworkBuffers( ) ) );
|
||||
}
|
||||
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
|
||||
{
|
||||
return uxMinimumFreeNetworkBuffers;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )
|
||||
{
|
||||
return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
|
||||
}
|
||||
|
||||
NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, size_t xNewSizeBytes )
|
||||
{
|
||||
/* In BufferAllocation_1.c all network buffer are allocated with a
|
||||
maximum size of 'ipTOTAL_ETHERNET_FRAME_SIZE'.No need to resize the
|
||||
network buffer. */
|
||||
( void ) xNewSizeBytes;
|
||||
return pxNetworkBuffer;
|
||||
}
|
||||
|
||||
/*#endif */ /* ipconfigINCLUDE_TEST_CODE */
|
||||
|
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* See the following web page for essential buffer allocation scheme usage and
|
||||
* configuration details:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* 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+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
/* The obtained network buffer must be large enough to hold a packet that might
|
||||
replace the packet that was requested to be sent. */
|
||||
#if ipconfigUSE_TCP == 1
|
||||
#define baMINIMAL_BUFFER_SIZE sizeof( TCPPacket_t )
|
||||
#else
|
||||
#define baMINIMAL_BUFFER_SIZE sizeof( ARPPacket_t )
|
||||
#endif /* ipconfigUSE_TCP == 1 */
|
||||
|
||||
/*_RB_ This is too complex not to have an explanation. */
|
||||
#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
|
||||
#define ASSERT_CONCAT_(a, b) a##b
|
||||
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
|
||||
#define STATIC_ASSERT(e) \
|
||||
;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
|
||||
|
||||
STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );
|
||||
#endif
|
||||
|
||||
/* A list of free (available) NetworkBufferDescriptor_t structures. */
|
||||
static List_t xFreeBuffersList;
|
||||
|
||||
/* Some statistics about the use of buffers. */
|
||||
static size_t uxMinimumFreeNetworkBuffers;
|
||||
|
||||
/* Declares the pool of NetworkBufferDescriptor_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 NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];
|
||||
|
||||
/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the
|
||||
network buffers have a variable size: resizing may be necessary */
|
||||
const BaseType_t xBufferAllocFixedSize = pdFALSE;
|
||||
|
||||
/* The semaphore used to obtain network buffers. */
|
||||
static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkBuffersInitialise( void )
|
||||
{
|
||||
BaseType_t 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_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
|
||||
configASSERT( xNetworkBufferSemaphore );
|
||||
#if ( configQUEUE_REGISTRY_SIZE > 0 )
|
||||
{
|
||||
vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" );
|
||||
}
|
||||
#endif /* configQUEUE_REGISTRY_SIZE */
|
||||
|
||||
/* If the trace recorder code is included name the semaphore for viewing
|
||||
in FreeRTOS+Trace. */
|
||||
#if( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 )
|
||||
{
|
||||
extern QueueHandle_t 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_BUFFER_DESCRIPTORS; x++ )
|
||||
{
|
||||
/* Initialise and set the owner of the buffer list items. */
|
||||
xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL;
|
||||
vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
|
||||
listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] );
|
||||
|
||||
/* Currently, all buffers are available for use. */
|
||||
vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
|
||||
}
|
||||
|
||||
uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
|
||||
}
|
||||
}
|
||||
|
||||
if( xNetworkBufferSemaphore == NULL )
|
||||
{
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint8_t *pucGetNetworkBuffer( size_t *pxRequestedSizeBytes )
|
||||
{
|
||||
uint8_t *pucEthernetBuffer;
|
||||
size_t xSize = *pxRequestedSizeBytes;
|
||||
|
||||
if( xSize < baMINIMAL_BUFFER_SIZE )
|
||||
{
|
||||
/* Buffers must be at least large enough to hold a TCP-packet with
|
||||
headers, or an ARP packet, in case TCP is not included. */
|
||||
xSize = baMINIMAL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/* Round up xSize to the nearest multiple of N bytes,
|
||||
where N equals 'sizeof( size_t )'. */
|
||||
if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )
|
||||
{
|
||||
xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;
|
||||
}
|
||||
*pxRequestedSizeBytes = xSize;
|
||||
|
||||
/* 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( xSize + ipBUFFER_PADDING );
|
||||
configASSERT( pucEthernetBuffer );
|
||||
|
||||
if( pucEthernetBuffer != NULL )
|
||||
{
|
||||
/* 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 vReleaseNetworkBuffer( 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 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )
|
||||
{
|
||||
NetworkBufferDescriptor_t *pxReturn = NULL;
|
||||
size_t uxCount;
|
||||
|
||||
if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
|
||||
{
|
||||
/* ARP packets can replace application packets, so the storage must be
|
||||
at least large enough to hold an ARP. */
|
||||
xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/* Add 2 bytes to xRequestedSizeBytes and round up xRequestedSizeBytes
|
||||
to the nearest multiple of N bytes, where N equals 'sizeof( size_t )'. */
|
||||
xRequestedSizeBytes += 2u;
|
||||
if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )
|
||||
{
|
||||
xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;
|
||||
}
|
||||
|
||||
/* 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 = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
|
||||
uxListRemove( &( pxReturn->xBufferListItem ) );
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
/* Reading UBaseType_t, no critical section needed. */
|
||||
uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );
|
||||
|
||||
if( uxMinimumFreeNetworkBuffers > uxCount )
|
||||
{
|
||||
uxMinimumFreeNetworkBuffers = uxCount;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
vReleaseNetworkBufferAndDescriptor( 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. */
|
||||
*( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;
|
||||
pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;
|
||||
|
||||
/* Store the actual size of the allocated buffer, which may be
|
||||
greater than the original requested size. */
|
||||
pxReturn->xDataLength = xRequestedSizeBytes;
|
||||
|
||||
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
|
||||
{
|
||||
/* make sure the buffer is not linked */
|
||||
pxReturn->pxNextBuffer = NULL;
|
||||
}
|
||||
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A descriptor is being returned without an associated buffer being
|
||||
allocated. */
|
||||
}
|
||||
}
|
||||
|
||||
if( pxReturn == NULL )
|
||||
{
|
||||
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
|
||||
}
|
||||
else
|
||||
{
|
||||
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
|
||||
}
|
||||
|
||||
return pxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
|
||||
{
|
||||
BaseType_t 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. */
|
||||
vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
|
||||
pxNetworkBuffer->pucEthernetBuffer = NULL;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
|
||||
|
||||
if( xListItemAlreadyInFreeList == pdFALSE )
|
||||
{
|
||||
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
if( xListItemAlreadyInFreeList == pdFALSE )
|
||||
{
|
||||
xSemaphoreGive( xNetworkBufferSemaphore );
|
||||
}
|
||||
|
||||
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Returns the number of free network buffers
|
||||
*/
|
||||
UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )
|
||||
{
|
||||
return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
|
||||
{
|
||||
return uxMinimumFreeNetworkBuffers;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, size_t xNewSizeBytes )
|
||||
{
|
||||
size_t xOriginalLength;
|
||||
uint8_t *pucBuffer;
|
||||
|
||||
xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;
|
||||
xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;
|
||||
|
||||
pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );
|
||||
|
||||
if( pucBuffer == NULL )
|
||||
{
|
||||
/* In case the allocation fails, return NULL. */
|
||||
pxNetworkBuffer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxNetworkBuffer->xDataLength = xNewSizeBytes;
|
||||
if( xNewSizeBytes > xOriginalLength )
|
||||
{
|
||||
xNewSizeBytes = xOriginalLength;
|
||||
}
|
||||
|
||||
memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );
|
||||
vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
|
||||
pxNetworkBuffer->pucEthernetBuffer = pucBuffer;
|
||||
}
|
||||
|
||||
return pxNetworkBuffer;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* See the following URL for an explanation of this file:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
|
||||
*
|
||||
*****************************************************************************/
|
||||
__attribute__( (packed) );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* See the following URL for an explanation of this file:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* Nothing to do here. */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* See the following URL for an explanation of this file:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* See the following URL for an explanation of this file:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__packed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* See the following URL for an explanation of this file:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
;
|
||||
#pragma pack( pop )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* See the following URL for an explanation of this file:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma pack( push, 1 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* See the following URL for an explanation of this file:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifdef _SH
|
||||
#ifdef __RENESAS__
|
||||
;
|
||||
#pragma unpack
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* See the following URL for an explanation of this file:
|
||||
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifdef _SH
|
||||
#ifdef __RENESAS__
|
||||
#pragma pack 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,680 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "NetworkInterface.h"
|
||||
|
||||
/* Some files from the Atmel Software Framework */
|
||||
/*_RB_ The SAM4E portable layer has three different header files called gmac.h! */
|
||||
#include "instance/gmac.h"
|
||||
#include <sysclk.h>
|
||||
#include <ethernet_phy.h>
|
||||
|
||||
#ifndef BMSR_LINK_STATUS
|
||||
#define BMSR_LINK_STATUS 0x0004 //!< Link status
|
||||
#endif
|
||||
|
||||
#ifndef PHY_LS_HIGH_CHECK_TIME_MS
|
||||
/* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
|
||||
receiving packets. */
|
||||
#define PHY_LS_HIGH_CHECK_TIME_MS 15000
|
||||
#endif
|
||||
|
||||
#ifndef PHY_LS_LOW_CHECK_TIME_MS
|
||||
/* Check if the LinkSStatus in the PHY is still low every second. */
|
||||
#define PHY_LS_LOW_CHECK_TIME_MS 1000
|
||||
#endif
|
||||
|
||||
/* Interrupt events to process. Currently only the Rx event is processed
|
||||
although code for other events is included to allow for possible future
|
||||
expansion. */
|
||||
#define EMAC_IF_RX_EVENT 1UL
|
||||
#define EMAC_IF_TX_EVENT 2UL
|
||||
#define EMAC_IF_ERR_EVENT 4UL
|
||||
#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )
|
||||
|
||||
#define ETHERNET_CONF_PHY_ADDR BOARD_GMAC_PHY_ADDR
|
||||
|
||||
#define HZ_PER_MHZ ( 1000000UL )
|
||||
|
||||
#ifndef EMAC_MAX_BLOCK_TIME_MS
|
||||
#define EMAC_MAX_BLOCK_TIME_MS 100ul
|
||||
#endif
|
||||
|
||||
#if !defined( GMAC_USES_TX_CALLBACK ) || ( GMAC_USES_TX_CALLBACK != 1 )
|
||||
#error Please define GMAC_USES_TX_CALLBACK as 1
|
||||
#endif
|
||||
|
||||
#if( ipconfigZERO_COPY_RX_DRIVER != 0 )
|
||||
#warning The EMAC of SAM4E has fixed-size RX buffers so ZERO_COPY_RX is not possible
|
||||
#endif
|
||||
|
||||
/* Default the size of the stack used by the EMAC deferred handler task to 4x
|
||||
the size of the stack used by the idle task - but allow this to be overridden in
|
||||
FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
|
||||
#ifndef configEMAC_TASK_STACK_SIZE
|
||||
#define configEMAC_TASK_STACK_SIZE ( 4 * configMINIMAL_STACK_SIZE )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Wait a fixed time for the link status to indicate the network is up.
|
||||
*/
|
||||
static BaseType_t xGMACWaitLS( TickType_t xMaxTime );
|
||||
|
||||
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )
|
||||
void vGMACGenerateChecksum( uint8_t *apBuffer );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Called from the ASF GMAC driver.
|
||||
*/
|
||||
static void prvRxCallback( uint32_t ulStatus );
|
||||
static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer );
|
||||
|
||||
/*
|
||||
* A deferred interrupt handler task that processes GMAC interrupts.
|
||||
*/
|
||||
static void prvEMACHandlerTask( void *pvParameters );
|
||||
|
||||
/*
|
||||
* Initialise the ASF GMAC driver.
|
||||
*/
|
||||
static BaseType_t prvGMACInit( void );
|
||||
|
||||
/*
|
||||
* Try to obtain an Rx packet from the hardware.
|
||||
*/
|
||||
static uint32_t prvEMACRxPoll( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Bit map of outstanding ETH interrupt events for processing. Currently only
|
||||
the Rx interrupt is handled, although code is included for other events to
|
||||
enable future expansion. */
|
||||
static volatile uint32_t ulISREvents;
|
||||
|
||||
/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
|
||||
static uint32_t ulPHYLinkStatus = 0;
|
||||
static volatile BaseType_t xGMACSwitchRequired;
|
||||
|
||||
/* ethernet_phy_addr: the address of the PHY in use.
|
||||
Atmel was a bit ambiguous about it so the address will be stored
|
||||
in this variable, see ethernet_phy.c */
|
||||
extern int ethernet_phy_addr;
|
||||
|
||||
/* LLMNR multicast address. */
|
||||
static const uint8_t llmnr_mac_address[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
|
||||
|
||||
/* The GMAC object as defined by the ASF drivers. */
|
||||
static gmac_device_t gs_gmac_dev;
|
||||
|
||||
/* MAC address to use. */
|
||||
extern const uint8_t ucMACAddress[ 6 ];
|
||||
|
||||
/* Holds the handle of the task used as a deferred interrupt processor. The
|
||||
handle is used so direct notifications can be sent to the task for all EMAC/DMA
|
||||
related interrupts. */
|
||||
TaskHandle_t xEMACTaskHandle = NULL;
|
||||
|
||||
static QueueHandle_t xTxBufferQueue;
|
||||
int tx_release_count[ 4 ];
|
||||
|
||||
/* xTXDescriptorSemaphore is a counting semaphore with
|
||||
a maximum count of GMAC_TX_BUFFERS, which is the number of
|
||||
DMA TX descriptors. */
|
||||
static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* GMAC interrupt handler.
|
||||
*/
|
||||
void GMAC_Handler(void)
|
||||
{
|
||||
xGMACSwitchRequired = pdFALSE;
|
||||
|
||||
/* gmac_handler() may call prvRxCallback() which may change
|
||||
the value of xGMACSwitchRequired. */
|
||||
gmac_handler( &gs_gmac_dev );
|
||||
|
||||
if( xGMACSwitchRequired != pdFALSE )
|
||||
{
|
||||
portEND_SWITCHING_ISR( xGMACSwitchRequired );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvRxCallback( uint32_t ulStatus )
|
||||
{
|
||||
if( ( ( ulStatus & GMAC_RSR_REC ) != 0 ) && ( xEMACTaskHandle != NULL ) )
|
||||
{
|
||||
/* let the prvEMACHandlerTask know that there was an RX event. */
|
||||
ulISREvents |= EMAC_IF_RX_EVENT;
|
||||
/* Only an RX interrupt can wakeup prvEMACHandlerTask. */
|
||||
vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer )
|
||||
{
|
||||
if( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) )
|
||||
{
|
||||
/* let the prvEMACHandlerTask know that there was an RX event. */
|
||||
ulISREvents |= EMAC_IF_TX_EVENT;
|
||||
|
||||
vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );
|
||||
xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired );
|
||||
tx_release_count[ 2 ]++;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceInitialise( void )
|
||||
{
|
||||
const TickType_t x5_Seconds = 5000UL;
|
||||
|
||||
if( xEMACTaskHandle == NULL )
|
||||
{
|
||||
prvGMACInit();
|
||||
|
||||
/* Wait at most 5 seconds for a Link Status in the PHY. */
|
||||
xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );
|
||||
|
||||
/* The handler task is created at the highest possible priority to
|
||||
ensure the interrupt handler can return directly to it. */
|
||||
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
|
||||
configASSERT( xEMACTaskHandle );
|
||||
}
|
||||
|
||||
if( xTxBufferQueue == NULL )
|
||||
{
|
||||
xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );
|
||||
configASSERT( xTxBufferQueue );
|
||||
}
|
||||
|
||||
if( xTXDescriptorSemaphore == NULL )
|
||||
{
|
||||
xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );
|
||||
configASSERT( xTXDescriptorSemaphore );
|
||||
}
|
||||
/* When returning non-zero, the stack will become active and
|
||||
start DHCP (in configured) */
|
||||
return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xGetPhyLinkStatus( void )
|
||||
{
|
||||
BaseType_t xResult;
|
||||
|
||||
/* This function returns true if the Link Status in the PHY is high. */
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
|
||||
{
|
||||
xResult = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xResult = pdFALSE;
|
||||
}
|
||||
|
||||
return xResult;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
|
||||
{
|
||||
/* Do not wait too long for a free TX DMA buffer. */
|
||||
const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
|
||||
|
||||
do {
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
|
||||
{
|
||||
/* Do not attempt to send packets as long as the Link Status is low. */
|
||||
break;
|
||||
}
|
||||
if( xTXDescriptorSemaphore == NULL )
|
||||
{
|
||||
/* Semaphore has not been created yet? */
|
||||
break;
|
||||
}
|
||||
if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
|
||||
{
|
||||
/* Time-out waiting for a free TX descriptor. */
|
||||
tx_release_count[ 3 ]++;
|
||||
break;
|
||||
}
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
{
|
||||
/* Confirm that the pxDescriptor may be kept by the driver. */
|
||||
configASSERT( bReleaseAfterSend != pdFALSE );
|
||||
}
|
||||
#endif /* ipconfigZERO_COPY_TX_DRIVER */
|
||||
|
||||
gmac_dev_write( &gs_gmac_dev, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, prvTxCallback );
|
||||
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
{
|
||||
/* Confirm that the pxDescriptor may be kept by the driver. */
|
||||
bReleaseAfterSend = pdFALSE;
|
||||
}
|
||||
#endif /* ipconfigZERO_COPY_TX_DRIVER */
|
||||
/* Not interested in a call-back after TX. */
|
||||
iptraceNETWORK_INTERFACE_TRANSMIT();
|
||||
} while( 0 );
|
||||
|
||||
if( bReleaseAfterSend != pdFALSE )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
|
||||
}
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvGMACInit( void )
|
||||
{
|
||||
uint32_t ncfgr;
|
||||
|
||||
gmac_options_t gmac_option;
|
||||
|
||||
memset( &gmac_option, '\0', sizeof( gmac_option ) );
|
||||
gmac_option.uc_copy_all_frame = 0;
|
||||
gmac_option.uc_no_boardcast = 0;
|
||||
memcpy( gmac_option.uc_mac_addr, ucMACAddress, sizeof( gmac_option.uc_mac_addr ) );
|
||||
|
||||
gs_gmac_dev.p_hw = GMAC;
|
||||
gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option );
|
||||
|
||||
NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY );
|
||||
NVIC_EnableIRQ( GMAC_IRQn );
|
||||
|
||||
/* Contact the Ethernet PHY and store it's address in 'ethernet_phy_addr' */
|
||||
ethernet_phy_init( GMAC, ETHERNET_CONF_PHY_ADDR, sysclk_get_cpu_hz() );
|
||||
|
||||
ethernet_phy_auto_negotiate( GMAC, ethernet_phy_addr );
|
||||
ethernet_phy_set_link( GMAC, ethernet_phy_addr, 1 );
|
||||
|
||||
/* The GMAC driver will call a hook prvRxCallback(), which
|
||||
in turn will wake-up the task by calling vTaskNotifyGiveFromISR() */
|
||||
gmac_dev_set_rx_callback( &gs_gmac_dev, prvRxCallback );
|
||||
gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );
|
||||
|
||||
ncfgr = GMAC_NCFGR_SPD | GMAC_NCFGR_FD;
|
||||
|
||||
GMAC->GMAC_NCFGR = ( GMAC->GMAC_NCFGR & ~( GMAC_NCFGR_SPD | GMAC_NCFGR_FD ) ) | ncfgr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static inline unsigned long ulReadMDIO( unsigned /*short*/ usAddress )
|
||||
{
|
||||
uint32_t ulValue, ulReturn;
|
||||
int rc;
|
||||
|
||||
gmac_enable_management( GMAC, 1 );
|
||||
rc = gmac_phy_read( GMAC, ethernet_phy_addr, usAddress, &ulValue );
|
||||
gmac_enable_management( GMAC, 0 );
|
||||
if( rc == GMAC_OK )
|
||||
{
|
||||
ulReturn = ulValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = 0UL;
|
||||
}
|
||||
|
||||
return ulReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t xGMACWaitLS( TickType_t xMaxTime )
|
||||
{
|
||||
TickType_t xStartTime = xTaskGetTickCount();
|
||||
TickType_t xEndTime;
|
||||
BaseType_t xReturn;
|
||||
const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
xEndTime = xTaskGetTickCount();
|
||||
|
||||
if( ( xEndTime - xStartTime ) > xMaxTime )
|
||||
{
|
||||
/* Wated more than xMaxTime, return. */
|
||||
xReturn = pdFALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check the link status again. */
|
||||
ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
|
||||
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
|
||||
{
|
||||
/* Link is up - return. */
|
||||
xReturn = pdTRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Link is down - wait in the Blocked state for a short while (to allow
|
||||
other tasks to execute) before checking again. */
|
||||
vTaskDelay( xShortTime );
|
||||
}
|
||||
|
||||
FreeRTOS_printf( ( "xGMACWaitLS: %ld (PHY %d) freq %lu Mz\n",
|
||||
xReturn,
|
||||
ethernet_phy_addr,
|
||||
sysclk_get_cpu_hz() / HZ_PER_MHZ ) );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
//#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )
|
||||
|
||||
void vGMACGenerateChecksum( uint8_t *apBuffer )
|
||||
{
|
||||
ProtocolPacket_t *xProtPacket = (ProtocolPacket_t *)apBuffer;
|
||||
|
||||
if ( xProtPacket->xTCPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )
|
||||
{
|
||||
IPHeader_t *pxIPHeader = &( xProtPacket->xTCPPacket.xIPHeader );
|
||||
|
||||
/* Calculate the IP header checksum. */
|
||||
pxIPHeader->usHeaderChecksum = 0x00;
|
||||
pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0u, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
|
||||
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
|
||||
|
||||
/* Calculate the TCP checksum for an outgoing packet. */
|
||||
usGenerateProtocolChecksum( ( uint8_t * ) apBuffer, pdTRUE );
|
||||
}
|
||||
}
|
||||
|
||||
//#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t prvEMACRxPoll( void )
|
||||
{
|
||||
unsigned char *pucUseBuffer;
|
||||
uint32_t ulReceiveCount, ulResult, ulReturnValue = 0;
|
||||
static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL;
|
||||
const UBaseType_t xMinDescriptorsToLeave = 2UL;
|
||||
const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL );
|
||||
static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* If pxNextNetworkBufferDescriptor was not left pointing at a valid
|
||||
descriptor then allocate one now. */
|
||||
if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) )
|
||||
{
|
||||
pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime );
|
||||
}
|
||||
|
||||
if( pxNextNetworkBufferDescriptor != NULL )
|
||||
{
|
||||
/* Point pucUseBuffer to the buffer pointed to by the descriptor. */
|
||||
pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* As long as pxNextNetworkBufferDescriptor is NULL, the incoming
|
||||
messages will be flushed and ignored. */
|
||||
pucUseBuffer = NULL;
|
||||
}
|
||||
|
||||
/* Read the next packet from the hardware into pucUseBuffer. */
|
||||
ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount );
|
||||
|
||||
if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) )
|
||||
{
|
||||
/* No data from the hardware. */
|
||||
break;
|
||||
}
|
||||
|
||||
if( pxNextNetworkBufferDescriptor == NULL )
|
||||
{
|
||||
/* Data was read from the hardware, but no descriptor was available
|
||||
for it, so it will be dropped. */
|
||||
iptraceETHERNET_RX_EVENT_LOST();
|
||||
continue;
|
||||
}
|
||||
|
||||
iptraceNETWORK_INTERFACE_RECEIVE();
|
||||
pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount;
|
||||
xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor;
|
||||
|
||||
/* Send the descriptor to the IP task for processing. */
|
||||
if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE )
|
||||
{
|
||||
/* The buffer could not be sent to the stack so must be released
|
||||
again. */
|
||||
vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor );
|
||||
iptraceETHERNET_RX_EVENT_LOST();
|
||||
FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
|
||||
}
|
||||
|
||||
/* Now the buffer has either been passed to the IP-task,
|
||||
or it has been released in the code above. */
|
||||
pxNextNetworkBufferDescriptor = NULL;
|
||||
ulReturnValue++;
|
||||
}
|
||||
|
||||
return ulReturnValue;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vCheckBuffersAndQueue( void )
|
||||
{
|
||||
static UBaseType_t uxLastMinBufferCount = 0;
|
||||
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
|
||||
static UBaseType_t uxLastMinQueueSpace;
|
||||
#endif
|
||||
static UBaseType_t uxCurrentCount;
|
||||
|
||||
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
|
||||
{
|
||||
uxCurrentCount = uxGetMinimumIPQueueSpace();
|
||||
if( uxLastMinQueueSpace != uxCurrentCount )
|
||||
{
|
||||
/* The logging produced below may be helpful
|
||||
while tuning +TCP: see how many buffers are in use. */
|
||||
uxLastMinQueueSpace = uxCurrentCount;
|
||||
FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigCHECK_IP_QUEUE_SPACE */
|
||||
uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
|
||||
if( uxLastMinBufferCount != uxCurrentCount )
|
||||
{
|
||||
/* The logging produced below may be helpful
|
||||
while tuning +TCP: see how many buffers are in use. */
|
||||
uxLastMinBufferCount = uxCurrentCount;
|
||||
FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
|
||||
uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void prvEMACHandlerTask( void *pvParameters )
|
||||
{
|
||||
TimeOut_t xPhyTime;
|
||||
TickType_t xPhyRemTime;
|
||||
UBaseType_t uxCount;
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
NetworkBufferDescriptor_t *pxBuffer;
|
||||
#endif
|
||||
uint8_t *pucBuffer;
|
||||
BaseType_t xResult = 0;
|
||||
uint32_t xStatus;
|
||||
const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
|
||||
|
||||
/* Remove compiler warnings about unused parameters. */
|
||||
( void ) pvParameters;
|
||||
|
||||
configASSERT( xEMACTaskHandle );
|
||||
|
||||
vTaskSetTimeOutState( &xPhyTime );
|
||||
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
vCheckBuffersAndQueue();
|
||||
|
||||
if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
|
||||
{
|
||||
/* No events to process now, wait for the next. */
|
||||
ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
|
||||
}
|
||||
|
||||
if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
|
||||
{
|
||||
ulISREvents &= ~EMAC_IF_RX_EVENT;
|
||||
|
||||
/* Wait for the EMAC interrupt to indicate that another packet has been
|
||||
received. */
|
||||
xResult = prvEMACRxPoll();
|
||||
}
|
||||
|
||||
if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
|
||||
{
|
||||
/* Future extension: code to release TX buffers if zero-copy is used. */
|
||||
ulISREvents &= ~EMAC_IF_TX_EVENT;
|
||||
while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE )
|
||||
{
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
{
|
||||
pxBuffer = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
|
||||
if( pxBuffer != NULL )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxBuffer );
|
||||
tx_release_count[ 0 ]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_release_count[ 1 ]++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
tx_release_count[ 0 ]++;
|
||||
}
|
||||
#endif
|
||||
uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore );
|
||||
if( uxCount < GMAC_TX_BUFFERS )
|
||||
{
|
||||
/* Tell the counting semaphore that one more TX descriptor is available. */
|
||||
xSemaphoreGive( xTXDescriptorSemaphore );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
|
||||
{
|
||||
/* Future extension: logging about errors that occurred. */
|
||||
ulISREvents &= ~EMAC_IF_ERR_EVENT;
|
||||
}
|
||||
|
||||
if( xResult > 0 )
|
||||
{
|
||||
/* A packet was received. No need to check for the PHY status now,
|
||||
but set a timer to check it later on. */
|
||||
vTaskSetTimeOutState( &xPhyTime );
|
||||
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
|
||||
xResult = 0;
|
||||
}
|
||||
else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
|
||||
{
|
||||
/* Check the link status again. */
|
||||
xStatus = ulReadMDIO( PHY_REG_01_BMSR );
|
||||
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
|
||||
{
|
||||
ulPHYLinkStatus = xStatus;
|
||||
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
|
||||
}
|
||||
|
||||
vTaskSetTimeOutState( &xPhyTime );
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
|
||||
{
|
||||
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
|
||||
}
|
||||
else
|
||||
{
|
||||
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -0,0 +1,746 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* Copyright (c) 2012 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SAM4E_GMAC_COMPONENT_
|
||||
#define _SAM4E_GMAC_COMPONENT_
|
||||
|
||||
/* ============================================================================= */
|
||||
/** SOFTWARE API DEFINITION FOR Gigabit Ethernet MAC */
|
||||
/* ============================================================================= */
|
||||
/** \addtogroup SAM4E_GMAC Gigabit Ethernet MAC */
|
||||
/*@{*/
|
||||
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
/** \brief GmacSa hardware registers */
|
||||
typedef struct {
|
||||
RwReg GMAC_SAB; /**< \brief (GmacSa Offset: 0x0) Specific Address 1 Bottom [31:0] Register */
|
||||
RwReg GMAC_SAT; /**< \brief (GmacSa Offset: 0x4) Specific Address 1 Top [47:32] Register */
|
||||
} GmacSa;
|
||||
/** \brief Gmac hardware registers */
|
||||
#define GMACSA_NUMBER 4
|
||||
typedef struct {
|
||||
RwReg GMAC_NCR; /**< \brief (Gmac Offset: 0x000) Network Control Register */
|
||||
RwReg GMAC_NCFGR; /**< \brief (Gmac Offset: 0x004) Network Configuration Register */
|
||||
RoReg GMAC_NSR; /**< \brief (Gmac Offset: 0x008) Network Status Register */
|
||||
RwReg GMAC_UR; /**< \brief (Gmac Offset: 0x00C) User Register */
|
||||
RwReg GMAC_DCFGR; /**< \brief (Gmac Offset: 0x010) DMA Configuration Register */
|
||||
RwReg GMAC_TSR; /**< \brief (Gmac Offset: 0x014) Transmit Status Register */
|
||||
RwReg GMAC_RBQB; /**< \brief (Gmac Offset: 0x018) Receive Buffer Queue Base Address */
|
||||
RwReg GMAC_TBQB; /**< \brief (Gmac Offset: 0x01C) Transmit Buffer Queue Base Address */
|
||||
RwReg GMAC_RSR; /**< \brief (Gmac Offset: 0x020) Receive Status Register */
|
||||
RoReg GMAC_ISR; /**< \brief (Gmac Offset: 0x024) Interrupt Status Register */
|
||||
WoReg GMAC_IER; /**< \brief (Gmac Offset: 0x028) Interrupt Enable Register */
|
||||
WoReg GMAC_IDR; /**< \brief (Gmac Offset: 0x02C) Interrupt Disable Register */
|
||||
RoReg GMAC_IMR; /**< \brief (Gmac Offset: 0x030) Interrupt Mask Register */
|
||||
RwReg GMAC_MAN; /**< \brief (Gmac Offset: 0x034) PHY Maintenance Register */
|
||||
RoReg GMAC_RPQ; /**< \brief (Gmac Offset: 0x038) Received Pause Quantum Register */
|
||||
RwReg GMAC_TPQ; /**< \brief (Gmac Offset: 0x03C) Transmit Pause Quantum Register */
|
||||
RwReg GMAC_TPSF; /**< \brief (Gmac Offset: 0x040) TX Partial Store and Forward Register */
|
||||
RwReg GMAC_RPSF; /**< \brief (Gmac Offset: 0x044) RX Partial Store and Forward Register */
|
||||
RoReg Reserved1[14];
|
||||
RwReg GMAC_HRB; /**< \brief (Gmac Offset: 0x080) Hash Register Bottom [31:0] */
|
||||
RwReg GMAC_HRT; /**< \brief (Gmac Offset: 0x084) Hash Register Top [63:32] */
|
||||
GmacSa GMAC_SA[GMACSA_NUMBER]; /**< \brief (Gmac Offset: 0x088) 1 .. 4 */
|
||||
RwReg GMAC_TIDM[4]; /**< \brief (Gmac Offset: 0x0A8) Type ID Match 1 Register */
|
||||
RwReg GMAC_WOL; /**< \brief (Gmac Offset: 0x0B8) Wake on LAN Register */
|
||||
RwReg GMAC_IPGS; /**< \brief (Gmac Offset: 0x0BC) IPG Stretch Register */
|
||||
RwReg GMAC_SVLAN; /**< \brief (Gmac Offset: 0x0C0) Stacked VLAN Register */
|
||||
RwReg GMAC_TPFCP; /**< \brief (Gmac Offset: 0x0C4) Transmit PFC Pause Register */
|
||||
RwReg GMAC_SAMB1; /**< \brief (Gmac Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register */
|
||||
RwReg GMAC_SAMT1; /**< \brief (Gmac Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register */
|
||||
RoReg Reserved2[12];
|
||||
RoReg GMAC_OTLO; /**< \brief (Gmac Offset: 0x100) Octets Transmitted [31:0] Register */
|
||||
RoReg GMAC_OTHI; /**< \brief (Gmac Offset: 0x104) Octets Transmitted [47:32] Register */
|
||||
RoReg GMAC_FT; /**< \brief (Gmac Offset: 0x108) Frames Transmitted Register */
|
||||
RoReg GMAC_BCFT; /**< \brief (Gmac Offset: 0x10C) Broadcast Frames Transmitted Register */
|
||||
RoReg GMAC_MFT; /**< \brief (Gmac Offset: 0x110) Multicast Frames Transmitted Register */
|
||||
RoReg GMAC_PFT; /**< \brief (Gmac Offset: 0x114) Pause Frames Transmitted Register */
|
||||
RoReg GMAC_BFT64; /**< \brief (Gmac Offset: 0x118) 64 Byte Frames Transmitted Register */
|
||||
RoReg GMAC_TBFT127; /**< \brief (Gmac Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register */
|
||||
RoReg GMAC_TBFT255; /**< \brief (Gmac Offset: 0x120) 128 to 255 Byte Frames Transmitted Register */
|
||||
RoReg GMAC_TBFT511; /**< \brief (Gmac Offset: 0x124) 256 to 511 Byte Frames Transmitted Register */
|
||||
RoReg GMAC_TBFT1023; /**< \brief (Gmac Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register */
|
||||
RoReg GMAC_TBFT1518; /**< \brief (Gmac Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register */
|
||||
RoReg GMAC_GTBFT1518; /**< \brief (Gmac Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register */
|
||||
RoReg GMAC_TUR; /**< \brief (Gmac Offset: 0x134) Transmit Under Runs Register */
|
||||
RoReg GMAC_SCF; /**< \brief (Gmac Offset: 0x138) Single Collision Frames Register */
|
||||
RoReg GMAC_MCF; /**< \brief (Gmac Offset: 0x13C) Multiple Collision Frames Register */
|
||||
RoReg GMAC_EC; /**< \brief (Gmac Offset: 0x140) Excessive Collisions Register */
|
||||
RoReg GMAC_LC; /**< \brief (Gmac Offset: 0x144) Late Collisions Register */
|
||||
RoReg GMAC_DTF; /**< \brief (Gmac Offset: 0x148) Deferred Transmission Frames Register */
|
||||
RoReg GMAC_CSE; /**< \brief (Gmac Offset: 0x14C) Carrier Sense Errors Register */
|
||||
RoReg GMAC_ORLO; /**< \brief (Gmac Offset: 0x150) Octets Received [31:0] Received */
|
||||
RoReg GMAC_ORHI; /**< \brief (Gmac Offset: 0x154) Octets Received [47:32] Received */
|
||||
RoReg GMAC_FR; /**< \brief (Gmac Offset: 0x158) Frames Received Register */
|
||||
RoReg GMAC_BCFR; /**< \brief (Gmac Offset: 0x15C) Broadcast Frames Received Register */
|
||||
RoReg GMAC_MFR; /**< \brief (Gmac Offset: 0x160) Multicast Frames Received Register */
|
||||
RoReg GMAC_PFR; /**< \brief (Gmac Offset: 0x164) Pause Frames Received Register */
|
||||
RoReg GMAC_BFR64; /**< \brief (Gmac Offset: 0x168) 64 Byte Frames Received Register */
|
||||
RoReg GMAC_TBFR127; /**< \brief (Gmac Offset: 0x16C) 65 to 127 Byte Frames Received Register */
|
||||
RoReg GMAC_TBFR255; /**< \brief (Gmac Offset: 0x170) 128 to 255 Byte Frames Received Register */
|
||||
RoReg GMAC_TBFR511; /**< \brief (Gmac Offset: 0x174) 256 to 511Byte Frames Received Register */
|
||||
RoReg GMAC_TBFR1023; /**< \brief (Gmac Offset: 0x178) 512 to 1023 Byte Frames Received Register */
|
||||
RoReg GMAC_TBFR1518; /**< \brief (Gmac Offset: 0x17C) 1024 to 1518 Byte Frames Received Register */
|
||||
RoReg GMAC_TMXBFR; /**< \brief (Gmac Offset: 0x180) 1519 to Maximum Byte Frames Received Register */
|
||||
RoReg GMAC_UFR; /**< \brief (Gmac Offset: 0x184) Undersize Frames Received Register */
|
||||
RoReg GMAC_OFR; /**< \brief (Gmac Offset: 0x188) Oversize Frames Received Register */
|
||||
RoReg GMAC_JR; /**< \brief (Gmac Offset: 0x18C) Jabbers Received Register */
|
||||
RoReg GMAC_FCSE; /**< \brief (Gmac Offset: 0x190) Frame Check Sequence Errors Register */
|
||||
RoReg GMAC_LFFE; /**< \brief (Gmac Offset: 0x194) Length Field Frame Errors Register */
|
||||
RoReg GMAC_RSE; /**< \brief (Gmac Offset: 0x198) Receive Symbol Errors Register */
|
||||
RoReg GMAC_AE; /**< \brief (Gmac Offset: 0x19C) Alignment Errors Register */
|
||||
RoReg GMAC_RRE; /**< \brief (Gmac Offset: 0x1A0) Receive Resource Errors Register */
|
||||
RoReg GMAC_ROE; /**< \brief (Gmac Offset: 0x1A4) Receive Overrun Register */
|
||||
RoReg GMAC_IHCE; /**< \brief (Gmac Offset: 0x1A8) IP Header Checksum Errors Register */
|
||||
RoReg GMAC_TCE; /**< \brief (Gmac Offset: 0x1AC) TCP Checksum Errors Register */
|
||||
RoReg GMAC_UCE; /**< \brief (Gmac Offset: 0x1B0) UDP Checksum Errors Register */
|
||||
RoReg Reserved3[5];
|
||||
RwReg GMAC_TSSS; /**< \brief (Gmac Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register */
|
||||
RwReg GMAC_TSSN; /**< \brief (Gmac Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register */
|
||||
RwReg GMAC_TS; /**< \brief (Gmac Offset: 0x1D0) 1588 Timer Seconds Register */
|
||||
RwReg GMAC_TN; /**< \brief (Gmac Offset: 0x1D4) 1588 Timer Nanoseconds Register */
|
||||
WoReg GMAC_TA; /**< \brief (Gmac Offset: 0x1D8) 1588 Timer Adjust Register */
|
||||
RwReg GMAC_TI; /**< \brief (Gmac Offset: 0x1DC) 1588 Timer Increment Register */
|
||||
RoReg GMAC_EFTS; /**< \brief (Gmac Offset: 0x1E0) PTP Event Frame Transmitted Seconds */
|
||||
RoReg GMAC_EFTN; /**< \brief (Gmac Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds */
|
||||
RoReg GMAC_EFRS; /**< \brief (Gmac Offset: 0x1E8) PTP Event Frame Received Seconds */
|
||||
RoReg GMAC_EFRN; /**< \brief (Gmac Offset: 0x1EC) PTP Event Frame Received Nanoseconds */
|
||||
RoReg GMAC_PEFTS; /**< \brief (Gmac Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds */
|
||||
RoReg GMAC_PEFTN; /**< \brief (Gmac Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds */
|
||||
RoReg GMAC_PEFRS; /**< \brief (Gmac Offset: 0x1F8) PTP Peer Event Frame Received Seconds */
|
||||
RoReg GMAC_PEFRN; /**< \brief (Gmac Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds */
|
||||
RoReg Reserved4[128];
|
||||
RoReg GMAC_ISRPQ[7]; /**< \brief (Gmac Offset: 0x400) Interrupt Status Register Priority Queue */
|
||||
RoReg Reserved5[9];
|
||||
RwReg GMAC_TBQBAPQ[7]; /**< \brief (Gmac Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue */
|
||||
RoReg Reserved6[9];
|
||||
RwReg GMAC_RBQBAPQ[7]; /**< \brief (Gmac Offset: 0x480) Receive Buffer Queue Base Address Priority Queue */
|
||||
RoReg Reserved7[1];
|
||||
RwReg GMAC_RBSRPQ[7]; /**< \brief (Gmac Offset: 0x4A0) Receive Buffer Size Register Priority Queue */
|
||||
RoReg Reserved8[17];
|
||||
RwReg GMAC_ST1RPQ[16]; /**< \brief (Gmac Offset: 0x500) Screening Type1 Register Priority Queue */
|
||||
RwReg GMAC_ST2RPQ[16]; /**< \brief (Gmac Offset: 0x540) Screening Type2 Register Priority Queue */
|
||||
RoReg Reserved9[32];
|
||||
WoReg GMAC_IERPQ[7]; /**< \brief (Gmac Offset: 0x600) Interrupt Enable Register Priority Queue */
|
||||
RoReg Reserved10[1];
|
||||
WoReg GMAC_IDRPQ[7]; /**< \brief (Gmac Offset: 0x620) Interrupt Disable Register Priority Queue */
|
||||
RoReg Reserved11[1];
|
||||
RwReg GMAC_IMRPQ[7]; /**< \brief (Gmac Offset: 0x640) Interrupt Mask Register Priority Queue */
|
||||
} Gmac;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
/* -------- GMAC_NCR : (GMAC Offset: 0x000) Network Control Register -------- */
|
||||
#define GMAC_NCR_LB (0x1u << 0) /**< \brief (GMAC_NCR) Loop Back */
|
||||
#define GMAC_NCR_LBL (0x1u << 1) /**< \brief (GMAC_NCR) Loop Back Local */
|
||||
#define GMAC_NCR_RXEN (0x1u << 2) /**< \brief (GMAC_NCR) Receive Enable */
|
||||
#define GMAC_NCR_TXEN (0x1u << 3) /**< \brief (GMAC_NCR) Transmit Enable */
|
||||
#define GMAC_NCR_MPE (0x1u << 4) /**< \brief (GMAC_NCR) Management Port Enable */
|
||||
#define GMAC_NCR_CLRSTAT (0x1u << 5) /**< \brief (GMAC_NCR) Clear Statistics Registers */
|
||||
#define GMAC_NCR_INCSTAT (0x1u << 6) /**< \brief (GMAC_NCR) Increment Statistics Registers */
|
||||
#define GMAC_NCR_WESTAT (0x1u << 7) /**< \brief (GMAC_NCR) Write Enable for Statistics Registers */
|
||||
#define GMAC_NCR_BP (0x1u << 8) /**< \brief (GMAC_NCR) Back pressure */
|
||||
#define GMAC_NCR_TSTART (0x1u << 9) /**< \brief (GMAC_NCR) Start Transmission */
|
||||
#define GMAC_NCR_THALT (0x1u << 10) /**< \brief (GMAC_NCR) Transmit Halt */
|
||||
#define GMAC_NCR_TXPF (0x1u << 11) /**< \brief (GMAC_NCR) Transmit Pause Frame */
|
||||
#define GMAC_NCR_TXZQPF (0x1u << 12) /**< \brief (GMAC_NCR) Transmit Zero Quantum Pause Frame */
|
||||
#define GMAC_NCR_RDS (0x1u << 14) /**< \brief (GMAC_NCR) Read Snapshot */
|
||||
#define GMAC_NCR_SRTSM (0x1u << 15) /**< \brief (GMAC_NCR) Store Receive Time Stamp to Memory */
|
||||
#define GMAC_NCR_ENPBPR (0x1u << 16) /**< \brief (GMAC_NCR) Enable PFC Priority-based Pause Reception */
|
||||
#define GMAC_NCR_TXPBPF (0x1u << 17) /**< \brief (GMAC_NCR) Transmit PFC Priority-based Pause Frame */
|
||||
#define GMAC_NCR_FNP (0x1u << 18) /**< \brief (GMAC_NCR) Flush Next Packet */
|
||||
/* -------- GMAC_NCFGR : (GMAC Offset: 0x004) Network Configuration Register -------- */
|
||||
#define GMAC_NCFGR_SPD (0x1u << 0) /**< \brief (GMAC_NCFGR) Speed */
|
||||
#define GMAC_NCFGR_FD (0x1u << 1) /**< \brief (GMAC_NCFGR) Full Duplex */
|
||||
#define GMAC_NCFGR_DNVLAN (0x1u << 2) /**< \brief (GMAC_NCFGR) Discard Non-VLAN FRAMES */
|
||||
#define GMAC_NCFGR_JFRAME (0x1u << 3) /**< \brief (GMAC_NCFGR) Jumbo Frame Size */
|
||||
#define GMAC_NCFGR_CAF (0x1u << 4) /**< \brief (GMAC_NCFGR) Copy All Frames */
|
||||
#define GMAC_NCFGR_NBC (0x1u << 5) /**< \brief (GMAC_NCFGR) No Broadcast */
|
||||
#define GMAC_NCFGR_MTIHEN (0x1u << 6) /**< \brief (GMAC_NCFGR) Multicast Hash Enable */
|
||||
#define GMAC_NCFGR_UNIHEN (0x1u << 7) /**< \brief (GMAC_NCFGR) Unicast Hash Enable */
|
||||
#define GMAC_NCFGR_MAXFS (0x1u << 8) /**< \brief (GMAC_NCFGR) 1536 Maximum Frame Size */
|
||||
#define GMAC_NCFGR_GBE (0x1u << 10) /**< \brief (GMAC_NCFGR) Gigabit Mode Enable */
|
||||
#define GMAC_NCFGR_PIS (0x1u << 11) /**< \brief (GMAC_NCFGR) Physical Interface Select */
|
||||
#define GMAC_NCFGR_RTY (0x1u << 12) /**< \brief (GMAC_NCFGR) Retry Test */
|
||||
#define GMAC_NCFGR_PEN (0x1u << 13) /**< \brief (GMAC_NCFGR) Pause Enable */
|
||||
#define GMAC_NCFGR_RXBUFO_Pos 14
|
||||
#define GMAC_NCFGR_RXBUFO_Msk (0x3u << GMAC_NCFGR_RXBUFO_Pos) /**< \brief (GMAC_NCFGR) Receive Buffer Offset */
|
||||
#define GMAC_NCFGR_RXBUFO(value) ((GMAC_NCFGR_RXBUFO_Msk & ((value) << GMAC_NCFGR_RXBUFO_Pos)))
|
||||
#define GMAC_NCFGR_LFERD (0x1u << 16) /**< \brief (GMAC_NCFGR) Length Field Error Frame Discard */
|
||||
#define GMAC_NCFGR_RFCS (0x1u << 17) /**< \brief (GMAC_NCFGR) Remove FCS */
|
||||
#define GMAC_NCFGR_CLK_Pos 18
|
||||
#define GMAC_NCFGR_CLK_Msk (0x7u << GMAC_NCFGR_CLK_Pos) /**< \brief (GMAC_NCFGR) MDC CLock Division */
|
||||
#define GMAC_NCFGR_CLK_MCK_8 (0x0u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 8 (MCK up to 20 MHz) */
|
||||
#define GMAC_NCFGR_CLK_MCK_16 (0x1u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 16 (MCK up to 40 MHz) */
|
||||
#define GMAC_NCFGR_CLK_MCK_32 (0x2u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 32 (MCK up to 80 MHz) */
|
||||
#define GMAC_NCFGR_CLK_MCK_48 (0x3u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 48 (MCK up to 120MHz) */
|
||||
#define GMAC_NCFGR_CLK_MCK_64 (0x4u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 64 (MCK up to 160 MHz) */
|
||||
#define GMAC_NCFGR_CLK_MCK_96 (0x5u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 96 (MCK up to 240 MHz) */
|
||||
#define GMAC_NCFGR_CLK_MCK_128 (0x6u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 128 (MCK up to 320 MHz) */
|
||||
#define GMAC_NCFGR_CLK_MCK_224 (0x7u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 224 (MCK up to 540 MHz) */
|
||||
#define GMAC_NCFGR_DBW_Pos 21
|
||||
#define GMAC_NCFGR_DBW_Msk (0x3u << GMAC_NCFGR_DBW_Pos) /**< \brief (GMAC_NCFGR) Data Bus Width */
|
||||
#define GMAC_NCFGR_DBW_DBW32 (0x0u << 21) /**< \brief (GMAC_NCFGR) 32-bit data bus width */
|
||||
#define GMAC_NCFGR_DBW_DBW64 (0x1u << 21) /**< \brief (GMAC_NCFGR) 64-bit data bus width */
|
||||
#define GMAC_NCFGR_DCPF (0x1u << 23) /**< \brief (GMAC_NCFGR) Disable Copy of Pause Frames */
|
||||
#define GMAC_NCFGR_RXCOEN (0x1u << 24) /**< \brief (GMAC_NCFGR) Receive Checksum Offload Enable */
|
||||
#define GMAC_NCFGR_EFRHD (0x1u << 25) /**< \brief (GMAC_NCFGR) Enable Frames Received in Half Duplex */
|
||||
#define GMAC_NCFGR_IRXFCS (0x1u << 26) /**< \brief (GMAC_NCFGR) Ignore RX FCS */
|
||||
#define GMAC_NCFGR_IPGSEN (0x1u << 28) /**< \brief (GMAC_NCFGR) IP Stretch Enable */
|
||||
#define GMAC_NCFGR_RXBP (0x1u << 29) /**< \brief (GMAC_NCFGR) Receive Bad Preamble */
|
||||
#define GMAC_NCFGR_IRXER (0x1u << 30) /**< \brief (GMAC_NCFGR) Ignore IPG rx_er */
|
||||
/* -------- GMAC_NSR : (GMAC Offset: 0x008) Network Status Register -------- */
|
||||
#define GMAC_NSR_MDIO (0x1u << 1) /**< \brief (GMAC_NSR) MDIO Input Status */
|
||||
#define GMAC_NSR_IDLE (0x1u << 2) /**< \brief (GMAC_NSR) PHY Management Logic Idle */
|
||||
/* -------- GMAC_UR : (GMAC Offset: 0x00C) User Register -------- */
|
||||
#define GMAC_UR_RGMII (0x1u << 0) /**< \brief (GMAC_UR) RGMII Mode */
|
||||
#define GMAC_UR_HDFC (0x1u << 6) /**< \brief (GMAC_UR) Half Duplex Flow Control */
|
||||
#define GMAC_UR_BPDG (0x1u << 7) /**< \brief (GMAC_UR) BPDG Bypass Deglitchers */
|
||||
/* -------- GMAC_DCFGR : (GMAC Offset: 0x010) DMA Configuration Register -------- */
|
||||
#define GMAC_DCFGR_FBLDO_Pos 0
|
||||
#define GMAC_DCFGR_FBLDO_Msk (0x1fu << GMAC_DCFGR_FBLDO_Pos) /**< \brief (GMAC_DCFGR) Fixed Burst Length for DMA Data Operations: */
|
||||
#define GMAC_DCFGR_FBLDO_SINGLE (0x1u << 0) /**< \brief (GMAC_DCFGR) 00001: Always use SINGLE AHB bursts */
|
||||
#define GMAC_DCFGR_FBLDO_INCR4 (0x4u << 0) /**< \brief (GMAC_DCFGR) 001xx: Attempt to use INCR4 AHB bursts (Default) */
|
||||
#define GMAC_DCFGR_FBLDO_INCR8 (0x8u << 0) /**< \brief (GMAC_DCFGR) 01xxx: Attempt to use INCR8 AHB bursts */
|
||||
#define GMAC_DCFGR_FBLDO_INCR16 (0x10u << 0) /**< \brief (GMAC_DCFGR) 1xxxx: Attempt to use INCR16 AHB bursts */
|
||||
#define GMAC_DCFGR_ESMA (0x1u << 6) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Management Descriptor Accesses */
|
||||
#define GMAC_DCFGR_ESPA (0x1u << 7) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Packet Data Accesses */
|
||||
#define GMAC_DCFGR_RXBMS_Pos 8
|
||||
#define GMAC_DCFGR_RXBMS_Msk (0x3u << GMAC_DCFGR_RXBMS_Pos) /**< \brief (GMAC_DCFGR) Receiver Packet Buffer Memory Size Select */
|
||||
#define GMAC_DCFGR_RXBMS_EIGHTH (0x0u << 8) /**< \brief (GMAC_DCFGR) 1 Kbyte Memory Size */
|
||||
#define GMAC_DCFGR_RXBMS_QUARTER (0x1u << 8) /**< \brief (GMAC_DCFGR) 2 Kbytes Memory Size */
|
||||
#define GMAC_DCFGR_RXBMS_HALF (0x2u << 8) /**< \brief (GMAC_DCFGR) 4 Kbytes Memory Size */
|
||||
#define GMAC_DCFGR_RXBMS_FULL (0x3u << 8) /**< \brief (GMAC_DCFGR) 8 Kbytes Memory Size */
|
||||
#define GMAC_DCFGR_TXPBMS (0x1u << 10) /**< \brief (GMAC_DCFGR) Transmitter Packet Buffer Memory Size Select */
|
||||
#define GMAC_DCFGR_TXCOEN (0x1u << 11) /**< \brief (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable */
|
||||
#define GMAC_DCFGR_DRBS_Pos 16
|
||||
#define GMAC_DCFGR_DRBS_Msk (0xffu << GMAC_DCFGR_DRBS_Pos) /**< \brief (GMAC_DCFGR) DMA Receive Buffer Size */
|
||||
#define GMAC_DCFGR_DRBS(value) ((GMAC_DCFGR_DRBS_Msk & ((value) << GMAC_DCFGR_DRBS_Pos)))
|
||||
#define GMAC_DCFGR_DDRP (0x1u << 24) /**< \brief (GMAC_DCFGR) DMA Discard Receive Packets */
|
||||
/* -------- GMAC_TSR : (GMAC Offset: 0x014) Transmit Status Register -------- */
|
||||
#define GMAC_TSR_UBR (0x1u << 0) /**< \brief (GMAC_TSR) Used Bit Read */
|
||||
#define GMAC_TSR_COL (0x1u << 1) /**< \brief (GMAC_TSR) Collision Occurred */
|
||||
#define GMAC_TSR_RLE (0x1u << 2) /**< \brief (GMAC_TSR) Retry Limit Exceeded */
|
||||
#define GMAC_TSR_TXGO (0x1u << 3) /**< \brief (GMAC_TSR) Transmit Go */
|
||||
#define GMAC_TSR_TFC (0x1u << 4) /**< \brief (GMAC_TSR) Transmit Frame Corruption due to AHB error */
|
||||
#define GMAC_TSR_TXCOMP (0x1u << 5) /**< \brief (GMAC_TSR) Transmit Complete */
|
||||
#define GMAC_TSR_UND (0x1u << 6) /**< \brief (GMAC_TSR) Transmit Under Run */
|
||||
#define GMAC_TSR_LCO (0x1u << 7) /**< \brief (GMAC_TSR) Late Collision Occurred */
|
||||
#define GMAC_TSR_HRESP (0x1u << 8) /**< \brief (GMAC_TSR) HRESP Not OK */
|
||||
/* -------- GMAC_RBQB : (GMAC Offset: 0x018) Receive Buffer Queue Base Address -------- */
|
||||
#define GMAC_RBQB_ADDR_Pos 2
|
||||
#define GMAC_RBQB_ADDR_Msk (0x3fffffffu << GMAC_RBQB_ADDR_Pos) /**< \brief (GMAC_RBQB) Receive buffer queue base address */
|
||||
#define GMAC_RBQB_ADDR(value) ((GMAC_RBQB_ADDR_Msk & ((value) << GMAC_RBQB_ADDR_Pos)))
|
||||
/* -------- GMAC_TBQB : (GMAC Offset: 0x01C) Transmit Buffer Queue Base Address -------- */
|
||||
#define GMAC_TBQB_ADDR_Pos 2
|
||||
#define GMAC_TBQB_ADDR_Msk (0x3fffffffu << GMAC_TBQB_ADDR_Pos) /**< \brief (GMAC_TBQB) Transmit Buffer Queue Base Address */
|
||||
#define GMAC_TBQB_ADDR(value) ((GMAC_TBQB_ADDR_Msk & ((value) << GMAC_TBQB_ADDR_Pos)))
|
||||
/* -------- GMAC_RSR : (GMAC Offset: 0x020) Receive Status Register -------- */
|
||||
#define GMAC_RSR_BNA (0x1u << 0) /**< \brief (GMAC_RSR) Buffer Not Available */
|
||||
#define GMAC_RSR_REC (0x1u << 1) /**< \brief (GMAC_RSR) Frame Received */
|
||||
#define GMAC_RSR_RXOVR (0x1u << 2) /**< \brief (GMAC_RSR) Receive Overrun */
|
||||
#define GMAC_RSR_HNO (0x1u << 3) /**< \brief (GMAC_RSR) HRESP Not OK */
|
||||
/* -------- GMAC_ISR : (GMAC Offset: 0x024) Interrupt Status Register -------- */
|
||||
#define GMAC_ISR_MFS (0x1u << 0) /**< \brief (GMAC_ISR) Management Frame Sent */
|
||||
#define GMAC_ISR_RCOMP (0x1u << 1) /**< \brief (GMAC_ISR) Receive Complete */
|
||||
#define GMAC_ISR_RXUBR (0x1u << 2) /**< \brief (GMAC_ISR) RX Used Bit Read */
|
||||
#define GMAC_ISR_TXUBR (0x1u << 3) /**< \brief (GMAC_ISR) TX Used Bit Read */
|
||||
#define GMAC_ISR_TUR (0x1u << 4) /**< \brief (GMAC_ISR) Transmit Under Run */
|
||||
#define GMAC_ISR_RLEX (0x1u << 5) /**< \brief (GMAC_ISR) Retry Limit Exceeded or Late Collision */
|
||||
#define GMAC_ISR_TFC (0x1u << 6) /**< \brief (GMAC_ISR) Transmit Frame Corruption due to AHB error */
|
||||
#define GMAC_ISR_TCOMP (0x1u << 7) /**< \brief (GMAC_ISR) Transmit Complete */
|
||||
#define GMAC_ISR_ROVR (0x1u << 10) /**< \brief (GMAC_ISR) Receive Overrun */
|
||||
#define GMAC_ISR_HRESP (0x1u << 11) /**< \brief (GMAC_ISR) HRESP Not OK */
|
||||
#define GMAC_ISR_PFNZ (0x1u << 12) /**< \brief (GMAC_ISR) Pause Frame with Non-zero Pause Quantum Received */
|
||||
#define GMAC_ISR_PTZ (0x1u << 13) /**< \brief (GMAC_ISR) Pause Time Zero */
|
||||
#define GMAC_ISR_PFTR (0x1u << 14) /**< \brief (GMAC_ISR) Pause Frame Transmitted */
|
||||
#define GMAC_ISR_EXINT (0x1u << 15) /**< \brief (GMAC_ISR) External Interrupt */
|
||||
#define GMAC_ISR_DRQFR (0x1u << 18) /**< \brief (GMAC_ISR) PTP Delay Request Frame Received */
|
||||
#define GMAC_ISR_SFR (0x1u << 19) /**< \brief (GMAC_ISR) PTP Sync Frame Received */
|
||||
#define GMAC_ISR_DRQFT (0x1u << 20) /**< \brief (GMAC_ISR) PTP Delay Request Frame Transmitted */
|
||||
#define GMAC_ISR_SFT (0x1u << 21) /**< \brief (GMAC_ISR) PTP Sync Frame Transmitted */
|
||||
#define GMAC_ISR_PDRQFR (0x1u << 22) /**< \brief (GMAC_ISR) PDelay Request Frame Received */
|
||||
#define GMAC_ISR_PDRSFR (0x1u << 23) /**< \brief (GMAC_ISR) PDelay Response Frame Received */
|
||||
#define GMAC_ISR_PDRQFT (0x1u << 24) /**< \brief (GMAC_ISR) PDelay Request Frame Transmitted */
|
||||
#define GMAC_ISR_PDRSFT (0x1u << 25) /**< \brief (GMAC_ISR) PDelay Response Frame Transmitted */
|
||||
#define GMAC_ISR_SRI (0x1u << 26) /**< \brief (GMAC_ISR) TSU Seconds Register Increment */
|
||||
#define GMAC_ISR_WOL (0x1u << 28) /**< \brief (GMAC_ISR) Wake On LAN */
|
||||
/* -------- GMAC_IER : (GMAC Offset: 0x028) Interrupt Enable Register -------- */
|
||||
#define GMAC_IER_MFS (0x1u << 0) /**< \brief (GMAC_IER) Management Frame Sent */
|
||||
#define GMAC_IER_RCOMP (0x1u << 1) /**< \brief (GMAC_IER) Receive Complete */
|
||||
#define GMAC_IER_RXUBR (0x1u << 2) /**< \brief (GMAC_IER) RX Used Bit Read */
|
||||
#define GMAC_IER_TXUBR (0x1u << 3) /**< \brief (GMAC_IER) TX Used Bit Read */
|
||||
#define GMAC_IER_TUR (0x1u << 4) /**< \brief (GMAC_IER) Transmit Under Run */
|
||||
#define GMAC_IER_RLEX (0x1u << 5) /**< \brief (GMAC_IER) Retry Limit Exceeded or Late Collision */
|
||||
#define GMAC_IER_TFC (0x1u << 6) /**< \brief (GMAC_IER) Transmit Frame Corruption due to AHB error */
|
||||
#define GMAC_IER_TCOMP (0x1u << 7) /**< \brief (GMAC_IER) Transmit Complete */
|
||||
#define GMAC_IER_ROVR (0x1u << 10) /**< \brief (GMAC_IER) Receive Overrun */
|
||||
#define GMAC_IER_HRESP (0x1u << 11) /**< \brief (GMAC_IER) HRESP Not OK */
|
||||
#define GMAC_IER_PFNZ (0x1u << 12) /**< \brief (GMAC_IER) Pause Frame with Non-zero Pause Quantum Received */
|
||||
#define GMAC_IER_PTZ (0x1u << 13) /**< \brief (GMAC_IER) Pause Time Zero */
|
||||
#define GMAC_IER_PFTR (0x1u << 14) /**< \brief (GMAC_IER) Pause Frame Transmitted */
|
||||
#define GMAC_IER_EXINT (0x1u << 15) /**< \brief (GMAC_IER) External Interrupt */
|
||||
#define GMAC_IER_DRQFR (0x1u << 18) /**< \brief (GMAC_IER) PTP Delay Request Frame Received */
|
||||
#define GMAC_IER_SFR (0x1u << 19) /**< \brief (GMAC_IER) PTP Sync Frame Received */
|
||||
#define GMAC_IER_DRQFT (0x1u << 20) /**< \brief (GMAC_IER) PTP Delay Request Frame Transmitted */
|
||||
#define GMAC_IER_SFT (0x1u << 21) /**< \brief (GMAC_IER) PTP Sync Frame Transmitted */
|
||||
#define GMAC_IER_PDRQFR (0x1u << 22) /**< \brief (GMAC_IER) PDelay Request Frame Received */
|
||||
#define GMAC_IER_PDRSFR (0x1u << 23) /**< \brief (GMAC_IER) PDelay Response Frame Received */
|
||||
#define GMAC_IER_PDRQFT (0x1u << 24) /**< \brief (GMAC_IER) PDelay Request Frame Transmitted */
|
||||
#define GMAC_IER_PDRSFT (0x1u << 25) /**< \brief (GMAC_IER) PDelay Response Frame Transmitted */
|
||||
#define GMAC_IER_SRI (0x1u << 26) /**< \brief (GMAC_IER) TSU Seconds Register Increment */
|
||||
#define GMAC_IER_WOL (0x1u << 28) /**< \brief (GMAC_IER) Wake On LAN */
|
||||
/* -------- GMAC_IDR : (GMAC Offset: 0x02C) Interrupt Disable Register -------- */
|
||||
#define GMAC_IDR_MFS (0x1u << 0) /**< \brief (GMAC_IDR) Management Frame Sent */
|
||||
#define GMAC_IDR_RCOMP (0x1u << 1) /**< \brief (GMAC_IDR) Receive Complete */
|
||||
#define GMAC_IDR_RXUBR (0x1u << 2) /**< \brief (GMAC_IDR) RX Used Bit Read */
|
||||
#define GMAC_IDR_TXUBR (0x1u << 3) /**< \brief (GMAC_IDR) TX Used Bit Read */
|
||||
#define GMAC_IDR_TUR (0x1u << 4) /**< \brief (GMAC_IDR) Transmit Under Run */
|
||||
#define GMAC_IDR_RLEX (0x1u << 5) /**< \brief (GMAC_IDR) Retry Limit Exceeded or Late Collision */
|
||||
#define GMAC_IDR_TFC (0x1u << 6) /**< \brief (GMAC_IDR) Transmit Frame Corruption due to AHB error */
|
||||
#define GMAC_IDR_TCOMP (0x1u << 7) /**< \brief (GMAC_IDR) Transmit Complete */
|
||||
#define GMAC_IDR_ROVR (0x1u << 10) /**< \brief (GMAC_IDR) Receive Overrun */
|
||||
#define GMAC_IDR_HRESP (0x1u << 11) /**< \brief (GMAC_IDR) HRESP Not OK */
|
||||
#define GMAC_IDR_PFNZ (0x1u << 12) /**< \brief (GMAC_IDR) Pause Frame with Non-zero Pause Quantum Received */
|
||||
#define GMAC_IDR_PTZ (0x1u << 13) /**< \brief (GMAC_IDR) Pause Time Zero */
|
||||
#define GMAC_IDR_PFTR (0x1u << 14) /**< \brief (GMAC_IDR) Pause Frame Transmitted */
|
||||
#define GMAC_IDR_EXINT (0x1u << 15) /**< \brief (GMAC_IDR) External Interrupt */
|
||||
#define GMAC_IDR_DRQFR (0x1u << 18) /**< \brief (GMAC_IDR) PTP Delay Request Frame Received */
|
||||
#define GMAC_IDR_SFR (0x1u << 19) /**< \brief (GMAC_IDR) PTP Sync Frame Received */
|
||||
#define GMAC_IDR_DRQFT (0x1u << 20) /**< \brief (GMAC_IDR) PTP Delay Request Frame Transmitted */
|
||||
#define GMAC_IDR_SFT (0x1u << 21) /**< \brief (GMAC_IDR) PTP Sync Frame Transmitted */
|
||||
#define GMAC_IDR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IDR) PDelay Request Frame Received */
|
||||
#define GMAC_IDR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IDR) PDelay Response Frame Received */
|
||||
#define GMAC_IDR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IDR) PDelay Request Frame Transmitted */
|
||||
#define GMAC_IDR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IDR) PDelay Response Frame Transmitted */
|
||||
#define GMAC_IDR_SRI (0x1u << 26) /**< \brief (GMAC_IDR) TSU Seconds Register Increment */
|
||||
#define GMAC_IDR_WOL (0x1u << 28) /**< \brief (GMAC_IDR) Wake On LAN */
|
||||
/* -------- GMAC_IMR : (GMAC Offset: 0x030) Interrupt Mask Register -------- */
|
||||
#define GMAC_IMR_MFS (0x1u << 0) /**< \brief (GMAC_IMR) Management Frame Sent */
|
||||
#define GMAC_IMR_RCOMP (0x1u << 1) /**< \brief (GMAC_IMR) Receive Complete */
|
||||
#define GMAC_IMR_RXUBR (0x1u << 2) /**< \brief (GMAC_IMR) RX Used Bit Read */
|
||||
#define GMAC_IMR_TXUBR (0x1u << 3) /**< \brief (GMAC_IMR) TX Used Bit Read */
|
||||
#define GMAC_IMR_TUR (0x1u << 4) /**< \brief (GMAC_IMR) Transmit Under Run */
|
||||
#define GMAC_IMR_RLEX (0x1u << 5) /**< \brief (GMAC_IMR) Retry Limit Exceeded or Late Collision */
|
||||
#define GMAC_IMR_TFC (0x1u << 6) /**< \brief (GMAC_IMR) Transmit Frame Corruption due to AHB error */
|
||||
#define GMAC_IMR_TCOMP (0x1u << 7) /**< \brief (GMAC_IMR) Transmit Complete */
|
||||
#define GMAC_IMR_ROVR (0x1u << 10) /**< \brief (GMAC_IMR) Receive Overrun */
|
||||
#define GMAC_IMR_HRESP (0x1u << 11) /**< \brief (GMAC_IMR) HRESP Not OK */
|
||||
#define GMAC_IMR_PFNZ (0x1u << 12) /**< \brief (GMAC_IMR) Pause Frame with Non-zero Pause Quantum Received */
|
||||
#define GMAC_IMR_PTZ (0x1u << 13) /**< \brief (GMAC_IMR) Pause Time Zero */
|
||||
#define GMAC_IMR_PFTR (0x1u << 14) /**< \brief (GMAC_IMR) Pause Frame Transmitted */
|
||||
#define GMAC_IMR_EXINT (0x1u << 15) /**< \brief (GMAC_IMR) External Interrupt */
|
||||
#define GMAC_IMR_DRQFR (0x1u << 18) /**< \brief (GMAC_IMR) PTP Delay Request Frame Received */
|
||||
#define GMAC_IMR_SFR (0x1u << 19) /**< \brief (GMAC_IMR) PTP Sync Frame Received */
|
||||
#define GMAC_IMR_DRQFT (0x1u << 20) /**< \brief (GMAC_IMR) PTP Delay Request Frame Transmitted */
|
||||
#define GMAC_IMR_SFT (0x1u << 21) /**< \brief (GMAC_IMR) PTP Sync Frame Transmitted */
|
||||
#define GMAC_IMR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IMR) PDelay Request Frame Received */
|
||||
#define GMAC_IMR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IMR) PDelay Response Frame Received */
|
||||
#define GMAC_IMR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IMR) PDelay Request Frame Transmitted */
|
||||
#define GMAC_IMR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IMR) PDelay Response Frame Transmitted */
|
||||
/* -------- GMAC_MAN : (GMAC Offset: 0x034) PHY Maintenance Register -------- */
|
||||
#define GMAC_MAN_DATA_Pos 0
|
||||
#define GMAC_MAN_DATA_Msk (0xffffu << GMAC_MAN_DATA_Pos) /**< \brief (GMAC_MAN) PHY Data */
|
||||
#define GMAC_MAN_DATA(value) ((GMAC_MAN_DATA_Msk & ((value) << GMAC_MAN_DATA_Pos)))
|
||||
#define GMAC_MAN_WTN_Pos 16
|
||||
#define GMAC_MAN_WTN_Msk (0x3u << GMAC_MAN_WTN_Pos) /**< \brief (GMAC_MAN) Write Ten */
|
||||
#define GMAC_MAN_WTN(value) ((GMAC_MAN_WTN_Msk & ((value) << GMAC_MAN_WTN_Pos)))
|
||||
#define GMAC_MAN_REGA_Pos 18
|
||||
#define GMAC_MAN_REGA_Msk (0x1fu << GMAC_MAN_REGA_Pos) /**< \brief (GMAC_MAN) Register Address */
|
||||
#define GMAC_MAN_REGA(value) ((GMAC_MAN_REGA_Msk & ((value) << GMAC_MAN_REGA_Pos)))
|
||||
#define GMAC_MAN_PHYA_Pos 23
|
||||
#define GMAC_MAN_PHYA_Msk (0x1fu << GMAC_MAN_PHYA_Pos) /**< \brief (GMAC_MAN) PHY Address */
|
||||
#define GMAC_MAN_PHYA(value) ((GMAC_MAN_PHYA_Msk & ((value) << GMAC_MAN_PHYA_Pos)))
|
||||
#define GMAC_MAN_OP_Pos 28
|
||||
#define GMAC_MAN_OP_Msk (0x3u << GMAC_MAN_OP_Pos) /**< \brief (GMAC_MAN) Operation */
|
||||
#define GMAC_MAN_OP(value) ((GMAC_MAN_OP_Msk & ((value) << GMAC_MAN_OP_Pos)))
|
||||
#define GMAC_MAN_CLTTO (0x1u << 30) /**< \brief (GMAC_MAN) Clause 22 Operation */
|
||||
#define GMAC_MAN_WZO (0x1u << 31) /**< \brief (GMAC_MAN) Write ZERO */
|
||||
/* -------- GMAC_RPQ : (GMAC Offset: 0x038) Received Pause Quantum Register -------- */
|
||||
#define GMAC_RPQ_RPQ_Pos 0
|
||||
#define GMAC_RPQ_RPQ_Msk (0xffffu << GMAC_RPQ_RPQ_Pos) /**< \brief (GMAC_RPQ) Received Pause Quantum */
|
||||
/* -------- GMAC_TPQ : (GMAC Offset: 0x03C) Transmit Pause Quantum Register -------- */
|
||||
#define GMAC_TPQ_TPQ_Pos 0
|
||||
#define GMAC_TPQ_TPQ_Msk (0xffffu << GMAC_TPQ_TPQ_Pos) /**< \brief (GMAC_TPQ) Transmit Pause Quantum */
|
||||
#define GMAC_TPQ_TPQ(value) ((GMAC_TPQ_TPQ_Msk & ((value) << GMAC_TPQ_TPQ_Pos)))
|
||||
/* -------- GMAC_TPSF : (GMAC Offset: 0x040) TX Partial Store and Forward Register -------- */
|
||||
#define GMAC_TPSF_TPB1ADR_Pos 0
|
||||
#define GMAC_TPSF_TPB1ADR_Msk (0xfffu << GMAC_TPSF_TPB1ADR_Pos) /**< \brief (GMAC_TPSF) tx_pbuf_addr-1:0 */
|
||||
#define GMAC_TPSF_TPB1ADR(value) ((GMAC_TPSF_TPB1ADR_Msk & ((value) << GMAC_TPSF_TPB1ADR_Pos)))
|
||||
#define GMAC_TPSF_ENTXP (0x1u << 31) /**< \brief (GMAC_TPSF) Enable TX Partial Store and Forward Operation */
|
||||
/* -------- GMAC_RPSF : (GMAC Offset: 0x044) RX Partial Store and Forward Register -------- */
|
||||
#define GMAC_RPSF_RPB1ADR_Pos 0
|
||||
#define GMAC_RPSF_RPB1ADR_Msk (0xfffu << GMAC_RPSF_RPB1ADR_Pos) /**< \brief (GMAC_RPSF) rx_pbuf_addr-1:0 */
|
||||
#define GMAC_RPSF_RPB1ADR(value) ((GMAC_RPSF_RPB1ADR_Msk & ((value) << GMAC_RPSF_RPB1ADR_Pos)))
|
||||
#define GMAC_RPSF_ENRXP (0x1u << 31) /**< \brief (GMAC_RPSF) Enable RX Partial Store and Forward Operation */
|
||||
/* -------- GMAC_HRB : (GMAC Offset: 0x080) Hash Register Bottom [31:0] -------- */
|
||||
#define GMAC_HRB_ADDR_Pos 0
|
||||
#define GMAC_HRB_ADDR_Msk (0xffffffffu << GMAC_HRB_ADDR_Pos) /**< \brief (GMAC_HRB) Hash Address */
|
||||
#define GMAC_HRB_ADDR(value) ((GMAC_HRB_ADDR_Msk & ((value) << GMAC_HRB_ADDR_Pos)))
|
||||
/* -------- GMAC_HRT : (GMAC Offset: 0x084) Hash Register Top [63:32] -------- */
|
||||
#define GMAC_HRT_ADDR_Pos 0
|
||||
#define GMAC_HRT_ADDR_Msk (0xffffffffu << GMAC_HRT_ADDR_Pos) /**< \brief (GMAC_HRT) Hash Address */
|
||||
#define GMAC_HRT_ADDR(value) ((GMAC_HRT_ADDR_Msk & ((value) << GMAC_HRT_ADDR_Pos)))
|
||||
/* -------- GMAC_SAB1 : (GMAC Offset: 0x088) Specific Address 1 Bottom [31:0] Register -------- */
|
||||
#define GMAC_SAB1_ADDR_Pos 0
|
||||
#define GMAC_SAB1_ADDR_Msk (0xffffffffu << GMAC_SAB1_ADDR_Pos) /**< \brief (GMAC_SAB1) Specific Address 1 */
|
||||
#define GMAC_SAB1_ADDR(value) ((GMAC_SAB1_ADDR_Msk & ((value) << GMAC_SAB1_ADDR_Pos)))
|
||||
/* -------- GMAC_SAT1 : (GMAC Offset: 0x08C) Specific Address 1 Top [47:32] Register -------- */
|
||||
#define GMAC_SAT1_ADDR_Pos 0
|
||||
#define GMAC_SAT1_ADDR_Msk (0xffffu << GMAC_SAT1_ADDR_Pos) /**< \brief (GMAC_SAT1) Specific Address 1 */
|
||||
#define GMAC_SAT1_ADDR(value) ((GMAC_SAT1_ADDR_Msk & ((value) << GMAC_SAT1_ADDR_Pos)))
|
||||
/* -------- GMAC_SAB2 : (GMAC Offset: 0x090) Specific Address 2 Bottom [31:0] Register -------- */
|
||||
#define GMAC_SAB2_ADDR_Pos 0
|
||||
#define GMAC_SAB2_ADDR_Msk (0xffffffffu << GMAC_SAB2_ADDR_Pos) /**< \brief (GMAC_SAB2) Specific Address 2 */
|
||||
#define GMAC_SAB2_ADDR(value) ((GMAC_SAB2_ADDR_Msk & ((value) << GMAC_SAB2_ADDR_Pos)))
|
||||
/* -------- GMAC_SAT2 : (GMAC Offset: 0x094) Specific Address 2 Top [47:32] Register -------- */
|
||||
#define GMAC_SAT2_ADDR_Pos 0
|
||||
#define GMAC_SAT2_ADDR_Msk (0xffffu << GMAC_SAT2_ADDR_Pos) /**< \brief (GMAC_SAT2) Specific Address 2 */
|
||||
#define GMAC_SAT2_ADDR(value) ((GMAC_SAT2_ADDR_Msk & ((value) << GMAC_SAT2_ADDR_Pos)))
|
||||
/* -------- GMAC_SAB3 : (GMAC Offset: 0x098) Specific Address 3 Bottom [31:0] Register -------- */
|
||||
#define GMAC_SAB3_ADDR_Pos 0
|
||||
#define GMAC_SAB3_ADDR_Msk (0xffffffffu << GMAC_SAB3_ADDR_Pos) /**< \brief (GMAC_SAB3) Specific Address 3 */
|
||||
#define GMAC_SAB3_ADDR(value) ((GMAC_SAB3_ADDR_Msk & ((value) << GMAC_SAB3_ADDR_Pos)))
|
||||
/* -------- GMAC_SAT3 : (GMAC Offset: 0x09C) Specific Address 3 Top [47:32] Register -------- */
|
||||
#define GMAC_SAT3_ADDR_Pos 0
|
||||
#define GMAC_SAT3_ADDR_Msk (0xffffu << GMAC_SAT3_ADDR_Pos) /**< \brief (GMAC_SAT3) Specific Address 3 */
|
||||
#define GMAC_SAT3_ADDR(value) ((GMAC_SAT3_ADDR_Msk & ((value) << GMAC_SAT3_ADDR_Pos)))
|
||||
/* -------- GMAC_SAB4 : (GMAC Offset: 0x0A0) Specific Address 4 Bottom [31:0] Register -------- */
|
||||
#define GMAC_SAB4_ADDR_Pos 0
|
||||
#define GMAC_SAB4_ADDR_Msk (0xffffffffu << GMAC_SAB4_ADDR_Pos) /**< \brief (GMAC_SAB4) Specific Address 4 */
|
||||
#define GMAC_SAB4_ADDR(value) ((GMAC_SAB4_ADDR_Msk & ((value) << GMAC_SAB4_ADDR_Pos)))
|
||||
/* -------- GMAC_SAT4 : (GMAC Offset: 0x0A4) Specific Address 4 Top [47:32] Register -------- */
|
||||
#define GMAC_SAT4_ADDR_Pos 0
|
||||
#define GMAC_SAT4_ADDR_Msk (0xffffu << GMAC_SAT4_ADDR_Pos) /**< \brief (GMAC_SAT4) Specific Address 4 */
|
||||
#define GMAC_SAT4_ADDR(value) ((GMAC_SAT4_ADDR_Msk & ((value) << GMAC_SAT4_ADDR_Pos)))
|
||||
/* -------- GMAC_TIDM[4] : (GMAC Offset: 0x0A8) Type ID Match 1 Register -------- */
|
||||
#define GMAC_TIDM_TID_Pos 0
|
||||
#define GMAC_TIDM_TID_Msk (0xffffu << GMAC_TIDM_TID_Pos) /**< \brief (GMAC_TIDM[4]) Type ID Match 1 */
|
||||
#define GMAC_TIDM_TID(value) ((GMAC_TIDM_TID_Msk & ((value) << GMAC_TIDM_TID_Pos)))
|
||||
/* -------- GMAC_WOL : (GMAC Offset: 0x0B8) Wake on LAN Register -------- */
|
||||
#define GMAC_WOL_IP_Pos 0
|
||||
#define GMAC_WOL_IP_Msk (0xffffu << GMAC_WOL_IP_Pos) /**< \brief (GMAC_WOL) ARP Request IP Address */
|
||||
#define GMAC_WOL_IP(value) ((GMAC_WOL_IP_Msk & ((value) << GMAC_WOL_IP_Pos)))
|
||||
#define GMAC_WOL_MAG (0x1u << 16) /**< \brief (GMAC_WOL) Magic Packet Event Enable */
|
||||
#define GMAC_WOL_ARP (0x1u << 17) /**< \brief (GMAC_WOL) ARP Request IP Address */
|
||||
#define GMAC_WOL_SA1 (0x1u << 18) /**< \brief (GMAC_WOL) Specific Address Register 1 Event Enable */
|
||||
#define GMAC_WOL_MTI (0x1u << 19) /**< \brief (GMAC_WOL) Multicast Hash Event Enable */
|
||||
/* -------- GMAC_IPGS : (GMAC Offset: 0x0BC) IPG Stretch Register -------- */
|
||||
#define GMAC_IPGS_FL_Pos 0
|
||||
#define GMAC_IPGS_FL_Msk (0xffffu << GMAC_IPGS_FL_Pos) /**< \brief (GMAC_IPGS) Frame Length */
|
||||
#define GMAC_IPGS_FL(value) ((GMAC_IPGS_FL_Msk & ((value) << GMAC_IPGS_FL_Pos)))
|
||||
/* -------- GMAC_SVLAN : (GMAC Offset: 0x0C0) Stacked VLAN Register -------- */
|
||||
#define GMAC_SVLAN_VLAN_TYPE_Pos 0
|
||||
#define GMAC_SVLAN_VLAN_TYPE_Msk (0xffffu << GMAC_SVLAN_VLAN_TYPE_Pos) /**< \brief (GMAC_SVLAN) User Defined VLAN_TYPE Field */
|
||||
#define GMAC_SVLAN_VLAN_TYPE(value) ((GMAC_SVLAN_VLAN_TYPE_Msk & ((value) << GMAC_SVLAN_VLAN_TYPE_Pos)))
|
||||
#define GMAC_SVLAN_ESVLAN (0x1u << 31) /**< \brief (GMAC_SVLAN) Enable Stacked VLAN Processing Mode */
|
||||
/* -------- GMAC_TPFCP : (GMAC Offset: 0x0C4) Transmit PFC Pause Register -------- */
|
||||
#define GMAC_TPFCP_PEV_Pos 0
|
||||
#define GMAC_TPFCP_PEV_Msk (0xffu << GMAC_TPFCP_PEV_Pos) /**< \brief (GMAC_TPFCP) Priority Enable Vector */
|
||||
#define GMAC_TPFCP_PEV(value) ((GMAC_TPFCP_PEV_Msk & ((value) << GMAC_TPFCP_PEV_Pos)))
|
||||
#define GMAC_TPFCP_PQ_Pos 8
|
||||
#define GMAC_TPFCP_PQ_Msk (0xffu << GMAC_TPFCP_PQ_Pos) /**< \brief (GMAC_TPFCP) Pause Quantum */
|
||||
#define GMAC_TPFCP_PQ(value) ((GMAC_TPFCP_PQ_Msk & ((value) << GMAC_TPFCP_PQ_Pos)))
|
||||
/* -------- GMAC_SAMB1 : (GMAC Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register -------- */
|
||||
#define GMAC_SAMB1_ADDR_Pos 0
|
||||
#define GMAC_SAMB1_ADDR_Msk (0xffffffffu << GMAC_SAMB1_ADDR_Pos) /**< \brief (GMAC_SAMB1) Specific Address 1 Mask */
|
||||
#define GMAC_SAMB1_ADDR(value) ((GMAC_SAMB1_ADDR_Msk & ((value) << GMAC_SAMB1_ADDR_Pos)))
|
||||
/* -------- GMAC_SAMT1 : (GMAC Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register -------- */
|
||||
#define GMAC_SAMT1_ADDR_Pos 0
|
||||
#define GMAC_SAMT1_ADDR_Msk (0xffffu << GMAC_SAMT1_ADDR_Pos) /**< \brief (GMAC_SAMT1) Specific Address 1 Mask */
|
||||
#define GMAC_SAMT1_ADDR(value) ((GMAC_SAMT1_ADDR_Msk & ((value) << GMAC_SAMT1_ADDR_Pos)))
|
||||
/* -------- GMAC_OTLO : (GMAC Offset: 0x100) Octets Transmitted [31:0] Register -------- */
|
||||
#define GMAC_OTLO_TXO_Pos 0
|
||||
#define GMAC_OTLO_TXO_Msk (0xffffffffu << GMAC_OTLO_TXO_Pos) /**< \brief (GMAC_OTLO) Transmitted Octets */
|
||||
/* -------- GMAC_OTHI : (GMAC Offset: 0x104) Octets Transmitted [47:32] Register -------- */
|
||||
#define GMAC_OTHI_TXO_Pos 0
|
||||
#define GMAC_OTHI_TXO_Msk (0xffffu << GMAC_OTHI_TXO_Pos) /**< \brief (GMAC_OTHI) Transmitted Octets */
|
||||
/* -------- GMAC_FT : (GMAC Offset: 0x108) Frames Transmitted Register -------- */
|
||||
#define GMAC_FT_FTX_Pos 0
|
||||
#define GMAC_FT_FTX_Msk (0xffffffffu << GMAC_FT_FTX_Pos) /**< \brief (GMAC_FT) Frames Transmitted without Error */
|
||||
/* -------- GMAC_BCFT : (GMAC Offset: 0x10C) Broadcast Frames Transmitted Register -------- */
|
||||
#define GMAC_BCFT_BFTX_Pos 0
|
||||
#define GMAC_BCFT_BFTX_Msk (0xffffffffu << GMAC_BCFT_BFTX_Pos) /**< \brief (GMAC_BCFT) Broadcast Frames Transmitted without Error */
|
||||
/* -------- GMAC_MFT : (GMAC Offset: 0x110) Multicast Frames Transmitted Register -------- */
|
||||
#define GMAC_MFT_MFTX_Pos 0
|
||||
#define GMAC_MFT_MFTX_Msk (0xffffffffu << GMAC_MFT_MFTX_Pos) /**< \brief (GMAC_MFT) Multicast Frames Transmitted without Error */
|
||||
/* -------- GMAC_PFT : (GMAC Offset: 0x114) Pause Frames Transmitted Register -------- */
|
||||
#define GMAC_PFT_PFTX_Pos 0
|
||||
#define GMAC_PFT_PFTX_Msk (0xffffu << GMAC_PFT_PFTX_Pos) /**< \brief (GMAC_PFT) Pause Frames Transmitted Register */
|
||||
/* -------- GMAC_BFT64 : (GMAC Offset: 0x118) 64 Byte Frames Transmitted Register -------- */
|
||||
#define GMAC_BFT64_NFTX_Pos 0
|
||||
#define GMAC_BFT64_NFTX_Msk (0xffffffffu << GMAC_BFT64_NFTX_Pos) /**< \brief (GMAC_BFT64) 64 Byte Frames Transmitted without Error */
|
||||
/* -------- GMAC_TBFT127 : (GMAC Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register -------- */
|
||||
#define GMAC_TBFT127_NFTX_Pos 0
|
||||
#define GMAC_TBFT127_NFTX_Msk (0xffffffffu << GMAC_TBFT127_NFTX_Pos) /**< \brief (GMAC_TBFT127) 65 to 127 Byte Frames Transmitted without Error */
|
||||
/* -------- GMAC_TBFT255 : (GMAC Offset: 0x120) 128 to 255 Byte Frames Transmitted Register -------- */
|
||||
#define GMAC_TBFT255_NFTX_Pos 0
|
||||
#define GMAC_TBFT255_NFTX_Msk (0xffffffffu << GMAC_TBFT255_NFTX_Pos) /**< \brief (GMAC_TBFT255) 128 to 255 Byte Frames Transmitted without Error */
|
||||
/* -------- GMAC_TBFT511 : (GMAC Offset: 0x124) 256 to 511 Byte Frames Transmitted Register -------- */
|
||||
#define GMAC_TBFT511_NFTX_Pos 0
|
||||
#define GMAC_TBFT511_NFTX_Msk (0xffffffffu << GMAC_TBFT511_NFTX_Pos) /**< \brief (GMAC_TBFT511) 256 to 511 Byte Frames Transmitted without Error */
|
||||
/* -------- GMAC_TBFT1023 : (GMAC Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register -------- */
|
||||
#define GMAC_TBFT1023_NFTX_Pos 0
|
||||
#define GMAC_TBFT1023_NFTX_Msk (0xffffffffu << GMAC_TBFT1023_NFTX_Pos) /**< \brief (GMAC_TBFT1023) 512 to 1023 Byte Frames Transmitted without Error */
|
||||
/* -------- GMAC_TBFT1518 : (GMAC Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register -------- */
|
||||
#define GMAC_TBFT1518_NFTX_Pos 0
|
||||
#define GMAC_TBFT1518_NFTX_Msk (0xffffffffu << GMAC_TBFT1518_NFTX_Pos) /**< \brief (GMAC_TBFT1518) 1024 to 1518 Byte Frames Transmitted without Error */
|
||||
/* -------- GMAC_GTBFT1518 : (GMAC Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register -------- */
|
||||
#define GMAC_GTBFT1518_NFTX_Pos 0
|
||||
#define GMAC_GTBFT1518_NFTX_Msk (0xffffffffu << GMAC_GTBFT1518_NFTX_Pos) /**< \brief (GMAC_GTBFT1518) Greater than 1518 Byte Frames Transmitted without Error */
|
||||
/* -------- GMAC_TUR : (GMAC Offset: 0x134) Transmit Under Runs Register -------- */
|
||||
#define GMAC_TUR_TXUNR_Pos 0
|
||||
#define GMAC_TUR_TXUNR_Msk (0x3ffu << GMAC_TUR_TXUNR_Pos) /**< \brief (GMAC_TUR) Transmit Under Runs */
|
||||
/* -------- GMAC_SCF : (GMAC Offset: 0x138) Single Collision Frames Register -------- */
|
||||
#define GMAC_SCF_SCOL_Pos 0
|
||||
#define GMAC_SCF_SCOL_Msk (0x3ffffu << GMAC_SCF_SCOL_Pos) /**< \brief (GMAC_SCF) Single Collision */
|
||||
/* -------- GMAC_MCF : (GMAC Offset: 0x13C) Multiple Collision Frames Register -------- */
|
||||
#define GMAC_MCF_MCOL_Pos 0
|
||||
#define GMAC_MCF_MCOL_Msk (0x3ffffu << GMAC_MCF_MCOL_Pos) /**< \brief (GMAC_MCF) Multiple Collision */
|
||||
/* -------- GMAC_EC : (GMAC Offset: 0x140) Excessive Collisions Register -------- */
|
||||
#define GMAC_EC_XCOL_Pos 0
|
||||
#define GMAC_EC_XCOL_Msk (0x3ffu << GMAC_EC_XCOL_Pos) /**< \brief (GMAC_EC) Excessive Collisions */
|
||||
/* -------- GMAC_LC : (GMAC Offset: 0x144) Late Collisions Register -------- */
|
||||
#define GMAC_LC_LCOL_Pos 0
|
||||
#define GMAC_LC_LCOL_Msk (0x3ffu << GMAC_LC_LCOL_Pos) /**< \brief (GMAC_LC) Late Collisions */
|
||||
/* -------- GMAC_DTF : (GMAC Offset: 0x148) Deferred Transmission Frames Register -------- */
|
||||
#define GMAC_DTF_DEFT_Pos 0
|
||||
#define GMAC_DTF_DEFT_Msk (0x3ffffu << GMAC_DTF_DEFT_Pos) /**< \brief (GMAC_DTF) Deferred Transmission */
|
||||
/* -------- GMAC_CSE : (GMAC Offset: 0x14C) Carrier Sense Errors Register -------- */
|
||||
#define GMAC_CSE_CSR_Pos 0
|
||||
#define GMAC_CSE_CSR_Msk (0x3ffu << GMAC_CSE_CSR_Pos) /**< \brief (GMAC_CSE) Carrier Sense Error */
|
||||
/* -------- GMAC_ORLO : (GMAC Offset: 0x150) Octets Received [31:0] Received -------- */
|
||||
#define GMAC_ORLO_RXO_Pos 0
|
||||
#define GMAC_ORLO_RXO_Msk (0xffffffffu << GMAC_ORLO_RXO_Pos) /**< \brief (GMAC_ORLO) Received Octets */
|
||||
/* -------- GMAC_ORHI : (GMAC Offset: 0x154) Octets Received [47:32] Received -------- */
|
||||
#define GMAC_ORHI_RXO_Pos 0
|
||||
#define GMAC_ORHI_RXO_Msk (0xffffu << GMAC_ORHI_RXO_Pos) /**< \brief (GMAC_ORHI) Received Octets */
|
||||
/* -------- GMAC_FR : (GMAC Offset: 0x158) Frames Received Register -------- */
|
||||
#define GMAC_FR_FRX_Pos 0
|
||||
#define GMAC_FR_FRX_Msk (0xffffffffu << GMAC_FR_FRX_Pos) /**< \brief (GMAC_FR) Frames Received without Error */
|
||||
/* -------- GMAC_BCFR : (GMAC Offset: 0x15C) Broadcast Frames Received Register -------- */
|
||||
#define GMAC_BCFR_BFRX_Pos 0
|
||||
#define GMAC_BCFR_BFRX_Msk (0xffffffffu << GMAC_BCFR_BFRX_Pos) /**< \brief (GMAC_BCFR) Broadcast Frames Received without Error */
|
||||
/* -------- GMAC_MFR : (GMAC Offset: 0x160) Multicast Frames Received Register -------- */
|
||||
#define GMAC_MFR_MFRX_Pos 0
|
||||
#define GMAC_MFR_MFRX_Msk (0xffffffffu << GMAC_MFR_MFRX_Pos) /**< \brief (GMAC_MFR) Multicast Frames Received without Error */
|
||||
/* -------- GMAC_PFR : (GMAC Offset: 0x164) Pause Frames Received Register -------- */
|
||||
#define GMAC_PFR_PFRX_Pos 0
|
||||
#define GMAC_PFR_PFRX_Msk (0xffffu << GMAC_PFR_PFRX_Pos) /**< \brief (GMAC_PFR) Pause Frames Received Register */
|
||||
/* -------- GMAC_BFR64 : (GMAC Offset: 0x168) 64 Byte Frames Received Register -------- */
|
||||
#define GMAC_BFR64_NFRX_Pos 0
|
||||
#define GMAC_BFR64_NFRX_Msk (0xffffffffu << GMAC_BFR64_NFRX_Pos) /**< \brief (GMAC_BFR64) 64 Byte Frames Received without Error */
|
||||
/* -------- GMAC_TBFR127 : (GMAC Offset: 0x16C) 65 to 127 Byte Frames Received Register -------- */
|
||||
#define GMAC_TBFR127_NFRX_Pos 0
|
||||
#define GMAC_TBFR127_NFRX_Msk (0xffffffffu << GMAC_TBFR127_NFRX_Pos) /**< \brief (GMAC_TBFR127) 65 to 127 Byte Frames Received without Error */
|
||||
/* -------- GMAC_TBFR255 : (GMAC Offset: 0x170) 128 to 255 Byte Frames Received Register -------- */
|
||||
#define GMAC_TBFR255_NFRX_Pos 0
|
||||
#define GMAC_TBFR255_NFRX_Msk (0xffffffffu << GMAC_TBFR255_NFRX_Pos) /**< \brief (GMAC_TBFR255) 128 to 255 Byte Frames Received without Error */
|
||||
/* -------- GMAC_TBFR511 : (GMAC Offset: 0x174) 256 to 511Byte Frames Received Register -------- */
|
||||
#define GMAC_TBFR511_NFRX_Pos 0
|
||||
#define GMAC_TBFR511_NFRX_Msk (0xffffffffu << GMAC_TBFR511_NFRX_Pos) /**< \brief (GMAC_TBFR511) 256 to 511 Byte Frames Received without Error */
|
||||
/* -------- GMAC_TBFR1023 : (GMAC Offset: 0x178) 512 to 1023 Byte Frames Received Register -------- */
|
||||
#define GMAC_TBFR1023_NFRX_Pos 0
|
||||
#define GMAC_TBFR1023_NFRX_Msk (0xffffffffu << GMAC_TBFR1023_NFRX_Pos) /**< \brief (GMAC_TBFR1023) 512 to 1023 Byte Frames Received without Error */
|
||||
/* -------- GMAC_TBFR1518 : (GMAC Offset: 0x17C) 1024 to 1518 Byte Frames Received Register -------- */
|
||||
#define GMAC_TBFR1518_NFRX_Pos 0
|
||||
#define GMAC_TBFR1518_NFRX_Msk (0xffffffffu << GMAC_TBFR1518_NFRX_Pos) /**< \brief (GMAC_TBFR1518) 1024 to 1518 Byte Frames Received without Error */
|
||||
/* -------- GMAC_TMXBFR : (GMAC Offset: 0x180) 1519 to Maximum Byte Frames Received Register -------- */
|
||||
#define GMAC_TMXBFR_NFRX_Pos 0
|
||||
#define GMAC_TMXBFR_NFRX_Msk (0xffffffffu << GMAC_TMXBFR_NFRX_Pos) /**< \brief (GMAC_TMXBFR) 1519 to Maximum Byte Frames Received without Error */
|
||||
/* -------- GMAC_UFR : (GMAC Offset: 0x184) Undersize Frames Received Register -------- */
|
||||
#define GMAC_UFR_UFRX_Pos 0
|
||||
#define GMAC_UFR_UFRX_Msk (0x3ffu << GMAC_UFR_UFRX_Pos) /**< \brief (GMAC_UFR) Undersize Frames Received */
|
||||
/* -------- GMAC_OFR : (GMAC Offset: 0x188) Oversize Frames Received Register -------- */
|
||||
#define GMAC_OFR_OFRX_Pos 0
|
||||
#define GMAC_OFR_OFRX_Msk (0x3ffu << GMAC_OFR_OFRX_Pos) /**< \brief (GMAC_OFR) Oversized Frames Received */
|
||||
/* -------- GMAC_JR : (GMAC Offset: 0x18C) Jabbers Received Register -------- */
|
||||
#define GMAC_JR_JRX_Pos 0
|
||||
#define GMAC_JR_JRX_Msk (0x3ffu << GMAC_JR_JRX_Pos) /**< \brief (GMAC_JR) Jabbers Received */
|
||||
/* -------- GMAC_FCSE : (GMAC Offset: 0x190) Frame Check Sequence Errors Register -------- */
|
||||
#define GMAC_FCSE_FCKR_Pos 0
|
||||
#define GMAC_FCSE_FCKR_Msk (0x3ffu << GMAC_FCSE_FCKR_Pos) /**< \brief (GMAC_FCSE) Frame Check Sequence Errors */
|
||||
/* -------- GMAC_LFFE : (GMAC Offset: 0x194) Length Field Frame Errors Register -------- */
|
||||
#define GMAC_LFFE_LFER_Pos 0
|
||||
#define GMAC_LFFE_LFER_Msk (0x3ffu << GMAC_LFFE_LFER_Pos) /**< \brief (GMAC_LFFE) Length Field Frame Errors */
|
||||
/* -------- GMAC_RSE : (GMAC Offset: 0x198) Receive Symbol Errors Register -------- */
|
||||
#define GMAC_RSE_RXSE_Pos 0
|
||||
#define GMAC_RSE_RXSE_Msk (0x3ffu << GMAC_RSE_RXSE_Pos) /**< \brief (GMAC_RSE) Receive Symbol Errors */
|
||||
/* -------- GMAC_AE : (GMAC Offset: 0x19C) Alignment Errors Register -------- */
|
||||
#define GMAC_AE_AER_Pos 0
|
||||
#define GMAC_AE_AER_Msk (0x3ffu << GMAC_AE_AER_Pos) /**< \brief (GMAC_AE) Alignment Errors */
|
||||
/* -------- GMAC_RRE : (GMAC Offset: 0x1A0) Receive Resource Errors Register -------- */
|
||||
#define GMAC_RRE_RXRER_Pos 0
|
||||
#define GMAC_RRE_RXRER_Msk (0x3ffffu << GMAC_RRE_RXRER_Pos) /**< \brief (GMAC_RRE) Receive Resource Errors */
|
||||
/* -------- GMAC_ROE : (GMAC Offset: 0x1A4) Receive Overrun Register -------- */
|
||||
#define GMAC_ROE_RXOVR_Pos 0
|
||||
#define GMAC_ROE_RXOVR_Msk (0x3ffu << GMAC_ROE_RXOVR_Pos) /**< \brief (GMAC_ROE) Receive Overruns */
|
||||
/* -------- GMAC_IHCE : (GMAC Offset: 0x1A8) IP Header Checksum Errors Register -------- */
|
||||
#define GMAC_IHCE_HCKER_Pos 0
|
||||
#define GMAC_IHCE_HCKER_Msk (0xffu << GMAC_IHCE_HCKER_Pos) /**< \brief (GMAC_IHCE) IP Header Checksum Errors */
|
||||
/* -------- GMAC_TCE : (GMAC Offset: 0x1AC) TCP Checksum Errors Register -------- */
|
||||
#define GMAC_TCE_TCKER_Pos 0
|
||||
#define GMAC_TCE_TCKER_Msk (0xffu << GMAC_TCE_TCKER_Pos) /**< \brief (GMAC_TCE) TCP Checksum Errors */
|
||||
/* -------- GMAC_UCE : (GMAC Offset: 0x1B0) UDP Checksum Errors Register -------- */
|
||||
#define GMAC_UCE_UCKER_Pos 0
|
||||
#define GMAC_UCE_UCKER_Msk (0xffu << GMAC_UCE_UCKER_Pos) /**< \brief (GMAC_UCE) UDP Checksum Errors */
|
||||
/* -------- GMAC_TSSS : (GMAC Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register -------- */
|
||||
#define GMAC_TSSS_VTS_Pos 0
|
||||
#define GMAC_TSSS_VTS_Msk (0xffffffffu << GMAC_TSSS_VTS_Pos) /**< \brief (GMAC_TSSS) Value of Timer Seconds Register Capture */
|
||||
#define GMAC_TSSS_VTS(value) ((GMAC_TSSS_VTS_Msk & ((value) << GMAC_TSSS_VTS_Pos)))
|
||||
/* -------- GMAC_TSSN : (GMAC Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register -------- */
|
||||
#define GMAC_TSSN_VTN_Pos 0
|
||||
#define GMAC_TSSN_VTN_Msk (0x3fffffffu << GMAC_TSSN_VTN_Pos) /**< \brief (GMAC_TSSN) Value Timer Nanoseconds Register Capture */
|
||||
#define GMAC_TSSN_VTN(value) ((GMAC_TSSN_VTN_Msk & ((value) << GMAC_TSSN_VTN_Pos)))
|
||||
/* -------- GMAC_TS : (GMAC Offset: 0x1D0) 1588 Timer Seconds Register -------- */
|
||||
#define GMAC_TS_TCS_Pos 0
|
||||
#define GMAC_TS_TCS_Msk (0xffffffffu << GMAC_TS_TCS_Pos) /**< \brief (GMAC_TS) Timer Count in Seconds */
|
||||
#define GMAC_TS_TCS(value) ((GMAC_TS_TCS_Msk & ((value) << GMAC_TS_TCS_Pos)))
|
||||
/* -------- GMAC_TN : (GMAC Offset: 0x1D4) 1588 Timer Nanoseconds Register -------- */
|
||||
#define GMAC_TN_TNS_Pos 0
|
||||
#define GMAC_TN_TNS_Msk (0x3fffffffu << GMAC_TN_TNS_Pos) /**< \brief (GMAC_TN) Timer Count in Nanoseconds */
|
||||
#define GMAC_TN_TNS(value) ((GMAC_TN_TNS_Msk & ((value) << GMAC_TN_TNS_Pos)))
|
||||
/* -------- GMAC_TA : (GMAC Offset: 0x1D8) 1588 Timer Adjust Register -------- */
|
||||
#define GMAC_TA_ITDT_Pos 0
|
||||
#define GMAC_TA_ITDT_Msk (0x3fffffffu << GMAC_TA_ITDT_Pos) /**< \brief (GMAC_TA) Increment/Decrement */
|
||||
#define GMAC_TA_ITDT(value) ((GMAC_TA_ITDT_Msk & ((value) << GMAC_TA_ITDT_Pos)))
|
||||
#define GMAC_TA_ADJ (0x1u << 31) /**< \brief (GMAC_TA) Adjust 1588 Timer */
|
||||
/* -------- GMAC_TI : (GMAC Offset: 0x1DC) 1588 Timer Increment Register -------- */
|
||||
#define GMAC_TI_CNS_Pos 0
|
||||
#define GMAC_TI_CNS_Msk (0xffu << GMAC_TI_CNS_Pos) /**< \brief (GMAC_TI) Count Nanoseconds */
|
||||
#define GMAC_TI_CNS(value) ((GMAC_TI_CNS_Msk & ((value) << GMAC_TI_CNS_Pos)))
|
||||
#define GMAC_TI_ACNS_Pos 8
|
||||
#define GMAC_TI_ACNS_Msk (0xffu << GMAC_TI_ACNS_Pos) /**< \brief (GMAC_TI) Alternative Count Nanoseconds */
|
||||
#define GMAC_TI_ACNS(value) ((GMAC_TI_ACNS_Msk & ((value) << GMAC_TI_ACNS_Pos)))
|
||||
#define GMAC_TI_NIT_Pos 16
|
||||
#define GMAC_TI_NIT_Msk (0xffu << GMAC_TI_NIT_Pos) /**< \brief (GMAC_TI) Number of Increments */
|
||||
#define GMAC_TI_NIT(value) ((GMAC_TI_NIT_Msk & ((value) << GMAC_TI_NIT_Pos)))
|
||||
/* -------- GMAC_EFTS : (GMAC Offset: 0x1E0) PTP Event Frame Transmitted Seconds -------- */
|
||||
#define GMAC_EFTS_RUD_Pos 0
|
||||
#define GMAC_EFTS_RUD_Msk (0xffffffffu << GMAC_EFTS_RUD_Pos) /**< \brief (GMAC_EFTS) Register Update */
|
||||
/* -------- GMAC_EFTN : (GMAC Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds -------- */
|
||||
#define GMAC_EFTN_RUD_Pos 0
|
||||
#define GMAC_EFTN_RUD_Msk (0x3fffffffu << GMAC_EFTN_RUD_Pos) /**< \brief (GMAC_EFTN) Register Update */
|
||||
/* -------- GMAC_EFRS : (GMAC Offset: 0x1E8) PTP Event Frame Received Seconds -------- */
|
||||
#define GMAC_EFRS_RUD_Pos 0
|
||||
#define GMAC_EFRS_RUD_Msk (0xffffffffu << GMAC_EFRS_RUD_Pos) /**< \brief (GMAC_EFRS) Register Update */
|
||||
/* -------- GMAC_EFRN : (GMAC Offset: 0x1EC) PTP Event Frame Received Nanoseconds -------- */
|
||||
#define GMAC_EFRN_RUD_Pos 0
|
||||
#define GMAC_EFRN_RUD_Msk (0x3fffffffu << GMAC_EFRN_RUD_Pos) /**< \brief (GMAC_EFRN) Register Update */
|
||||
/* -------- GMAC_PEFTS : (GMAC Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds -------- */
|
||||
#define GMAC_PEFTS_RUD_Pos 0
|
||||
#define GMAC_PEFTS_RUD_Msk (0xffffffffu << GMAC_PEFTS_RUD_Pos) /**< \brief (GMAC_PEFTS) Register Update */
|
||||
/* -------- GMAC_PEFTN : (GMAC Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds -------- */
|
||||
#define GMAC_PEFTN_RUD_Pos 0
|
||||
#define GMAC_PEFTN_RUD_Msk (0x3fffffffu << GMAC_PEFTN_RUD_Pos) /**< \brief (GMAC_PEFTN) Register Update */
|
||||
/* -------- GMAC_PEFRS : (GMAC Offset: 0x1F8) PTP Peer Event Frame Received Seconds -------- */
|
||||
#define GMAC_PEFRS_RUD_Pos 0
|
||||
#define GMAC_PEFRS_RUD_Msk (0xffffffffu << GMAC_PEFRS_RUD_Pos) /**< \brief (GMAC_PEFRS) Register Update */
|
||||
/* -------- GMAC_PEFRN : (GMAC Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds -------- */
|
||||
#define GMAC_PEFRN_RUD_Pos 0
|
||||
#define GMAC_PEFRN_RUD_Msk (0x3fffffffu << GMAC_PEFRN_RUD_Pos) /**< \brief (GMAC_PEFRN) Register Update */
|
||||
/* -------- GMAC_ISRPQ[7] : (GMAC Offset: 0x400) Interrupt Status Register Priority Queue -------- */
|
||||
#define GMAC_ISRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_ISRPQ[7]) Receive Complete */
|
||||
#define GMAC_ISRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_ISRPQ[7]) RX Used Bit Read */
|
||||
#define GMAC_ISRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_ISRPQ[7]) Retry Limit Exceeded or Late Collision */
|
||||
#define GMAC_ISRPQ_TFC (0x1u << 6) /**< \brief (GMAC_ISRPQ[7]) Transmit Frame Corruption due to AHB error */
|
||||
#define GMAC_ISRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_ISRPQ[7]) Transmit Complete */
|
||||
#define GMAC_ISRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_ISRPQ[7]) Receive Overrun */
|
||||
#define GMAC_ISRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_ISRPQ[7]) HRESP Not OK */
|
||||
/* -------- GMAC_TBQBAPQ[7] : (GMAC Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue -------- */
|
||||
#define GMAC_TBQBAPQ_TXBQBA_Pos 2
|
||||
#define GMAC_TBQBAPQ_TXBQBA_Msk (0x3fu << GMAC_TBQBAPQ_TXBQBA_Pos) /**< \brief (GMAC_TBQBAPQ[7]) Transmit Buffer Queue Base Address */
|
||||
#define GMAC_TBQBAPQ_TXBQBA(value) ((GMAC_TBQBAPQ_TXBQBA_Msk & ((value) << GMAC_TBQBAPQ_TXBQBA_Pos)))
|
||||
/* -------- GMAC_RBQBAPQ[7] : (GMAC Offset: 0x480) Receive Buffer Queue Base Address Priority Queue -------- */
|
||||
#define GMAC_RBQBAPQ_RXBQBA_Pos 2
|
||||
#define GMAC_RBQBAPQ_RXBQBA_Msk (0x3fu << GMAC_RBQBAPQ_RXBQBA_Pos) /**< \brief (GMAC_RBQBAPQ[7]) Receive Buffer Queue Base Address */
|
||||
#define GMAC_RBQBAPQ_RXBQBA(value) ((GMAC_RBQBAPQ_RXBQBA_Msk & ((value) << GMAC_RBQBAPQ_RXBQBA_Pos)))
|
||||
/* -------- GMAC_RBSRPQ[7] : (GMAC Offset: 0x4A0) Receive Buffer Size Register Priority Queue -------- */
|
||||
#define GMAC_RBSRPQ_RBS_Pos 0
|
||||
#define GMAC_RBSRPQ_RBS_Msk (0xffffu << GMAC_RBSRPQ_RBS_Pos) /**< \brief (GMAC_RBSRPQ[7]) Receive Buffer Size */
|
||||
#define GMAC_RBSRPQ_RBS(value) ((GMAC_RBSRPQ_RBS_Msk & ((value) << GMAC_RBSRPQ_RBS_Pos)))
|
||||
/* -------- GMAC_ST1RPQ[16] : (GMAC Offset: 0x500) Screening Type1 Register Priority Queue -------- */
|
||||
#define GMAC_ST1RPQ_QNB_Pos 0
|
||||
#define GMAC_ST1RPQ_QNB_Msk (0xfu << GMAC_ST1RPQ_QNB_Pos) /**< \brief (GMAC_ST1RPQ[16]) Que Number (0->7) */
|
||||
#define GMAC_ST1RPQ_QNB(value) ((GMAC_ST1RPQ_QNB_Msk & ((value) << GMAC_ST1RPQ_QNB_Pos)))
|
||||
#define GMAC_ST1RPQ_DSTCM_Pos 4
|
||||
#define GMAC_ST1RPQ_DSTCM_Msk (0xffu << GMAC_ST1RPQ_DSTCM_Pos) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match */
|
||||
#define GMAC_ST1RPQ_DSTCM(value) ((GMAC_ST1RPQ_DSTCM_Msk & ((value) << GMAC_ST1RPQ_DSTCM_Pos)))
|
||||
#define GMAC_ST1RPQ_UDPM_Pos 12
|
||||
#define GMAC_ST1RPQ_UDPM_Msk (0xffffu << GMAC_ST1RPQ_UDPM_Pos) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match */
|
||||
#define GMAC_ST1RPQ_UDPM(value) ((GMAC_ST1RPQ_UDPM_Msk & ((value) << GMAC_ST1RPQ_UDPM_Pos)))
|
||||
#define GMAC_ST1RPQ_DSTCE (0x1u << 28) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match Enable */
|
||||
#define GMAC_ST1RPQ_UDPE (0x1u << 29) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match Enable */
|
||||
/* -------- GMAC_ST2RPQ[16] : (GMAC Offset: 0x540) Screening Type2 Register Priority Queue -------- */
|
||||
#define GMAC_ST2RPQ_QNB_Pos 0
|
||||
#define GMAC_ST2RPQ_QNB_Msk (0xfu << GMAC_ST2RPQ_QNB_Pos) /**< \brief (GMAC_ST2RPQ[16]) Que Number (0->7) */
|
||||
#define GMAC_ST2RPQ_QNB(value) ((GMAC_ST2RPQ_QNB_Msk & ((value) << GMAC_ST2RPQ_QNB_Pos)))
|
||||
#define GMAC_ST2RPQ_VLANP_Pos 4
|
||||
#define GMAC_ST2RPQ_VLANP_Msk (0xfu << GMAC_ST2RPQ_VLANP_Pos) /**< \brief (GMAC_ST2RPQ[16]) VLAN Priority */
|
||||
#define GMAC_ST2RPQ_VLANP(value) ((GMAC_ST2RPQ_VLANP_Msk & ((value) << GMAC_ST2RPQ_VLANP_Pos)))
|
||||
#define GMAC_ST2RPQ_VLANE (0x1u << 8) /**< \brief (GMAC_ST2RPQ[16]) VLAN Enable */
|
||||
/* -------- GMAC_IERPQ[7] : (GMAC Offset: 0x600) Interrupt Enable Register Priority Queue -------- */
|
||||
#define GMAC_IERPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IERPQ[7]) Receive Complete */
|
||||
#define GMAC_IERPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IERPQ[7]) RX Used Bit Read */
|
||||
#define GMAC_IERPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IERPQ[7]) Retry Limit Exceeded or Late Collision */
|
||||
#define GMAC_IERPQ_TFC (0x1u << 6) /**< \brief (GMAC_IERPQ[7]) Transmit Frame Corruption due to AHB error */
|
||||
#define GMAC_IERPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IERPQ[7]) Transmit Complete */
|
||||
#define GMAC_IERPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IERPQ[7]) Receive Overrun */
|
||||
#define GMAC_IERPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IERPQ[7]) HRESP Not OK */
|
||||
/* -------- GMAC_IDRPQ[7] : (GMAC Offset: 0x620) Interrupt Disable Register Priority Queue -------- */
|
||||
#define GMAC_IDRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IDRPQ[7]) Receive Complete */
|
||||
#define GMAC_IDRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IDRPQ[7]) RX Used Bit Read */
|
||||
#define GMAC_IDRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IDRPQ[7]) Retry Limit Exceeded or Late Collision */
|
||||
#define GMAC_IDRPQ_TFC (0x1u << 6) /**< \brief (GMAC_IDRPQ[7]) Transmit Frame Corruption due to AHB error */
|
||||
#define GMAC_IDRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IDRPQ[7]) Transmit Complete */
|
||||
#define GMAC_IDRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IDRPQ[7]) Receive Overrun */
|
||||
#define GMAC_IDRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IDRPQ[7]) HRESP Not OK */
|
||||
/* -------- GMAC_IMRPQ[7] : (GMAC Offset: 0x640) Interrupt Mask Register Priority Queue -------- */
|
||||
#define GMAC_IMRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IMRPQ[7]) Receive Complete */
|
||||
#define GMAC_IMRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IMRPQ[7]) RX Used Bit Read */
|
||||
#define GMAC_IMRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IMRPQ[7]) Retry Limit Exceeded or Late Collision */
|
||||
#define GMAC_IMRPQ_AHB (0x1u << 6) /**< \brief (GMAC_IMRPQ[7]) AHB Error */
|
||||
#define GMAC_IMRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IMRPQ[7]) Transmit Complete */
|
||||
#define GMAC_IMRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IMRPQ[7]) Receive Overrun */
|
||||
#define GMAC_IMRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IMRPQ[7]) HRESP Not OK */
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
#endif /* _SAM4E_GMAC_COMPONENT_ */
|
||||
|
|
@ -0,0 +1,454 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief API driver for KSZ8051MNL PHY component.
|
||||
*
|
||||
* Copyright (c) 2013 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
|
||||
#include "ethernet_phy.h"
|
||||
#include "instance/gmac.h"
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)
|
||||
*
|
||||
* Driver for the ksz8051mnl component. This driver provides access to the main
|
||||
* features of the PHY.
|
||||
*
|
||||
* \section dependencies Dependencies
|
||||
* This driver depends on the following modules:
|
||||
* - \ref gmac_group Ethernet Media Access Controller (GMAC) module.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
SPhyProps phyProps;
|
||||
|
||||
/* Max PHY number */
|
||||
#define ETH_PHY_MAX_ADDR 31
|
||||
|
||||
/* Ethernet PHY operation max retry count */
|
||||
#define ETH_PHY_RETRY_MAX 1000000
|
||||
|
||||
/* Ethernet PHY operation timeout */
|
||||
#define ETH_PHY_TIMEOUT 10
|
||||
|
||||
/**
|
||||
* \brief Find a valid PHY Address ( from addrStart to 31 ).
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
* \param uc_start_addr Start address of the PHY to be searched.
|
||||
*
|
||||
* \return 0xFF when no valid PHY address is found.
|
||||
*/
|
||||
int ethernet_phy_addr = 0;
|
||||
static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,
|
||||
uint8_t uc_start_addr)
|
||||
{
|
||||
uint32_t ul_value = 0;
|
||||
uint8_t uc_cnt;
|
||||
uint8_t uc_phy_address = uc_phy_addr;
|
||||
|
||||
gmac_enable_management(p_gmac, true);
|
||||
/*
|
||||
#define GMII_OUI_MSB 0x0022
|
||||
#define GMII_OUI_LSB 0x05
|
||||
|
||||
PHYID1 = 0x0022
|
||||
PHYID2 = 0x1550
|
||||
0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0
|
||||
*/
|
||||
/* Check the current PHY address */
|
||||
gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);
|
||||
|
||||
/* Find another one */
|
||||
if (ul_value != GMII_OUI_MSB) {
|
||||
ethernet_phy_addr = 0xFF;
|
||||
for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {
|
||||
uc_phy_address = (uc_phy_address + 1) & 0x1F;
|
||||
ul_value = 0;
|
||||
gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);
|
||||
if (ul_value == GMII_OUI_MSB) {
|
||||
ethernet_phy_addr = uc_phy_address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gmac_enable_management(p_gmac, false);
|
||||
|
||||
if (ethernet_phy_addr != 0xFF) {
|
||||
gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);
|
||||
}
|
||||
return ethernet_phy_addr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Perform a HW initialization to the PHY and set up clocks.
|
||||
*
|
||||
* This should be called only once to initialize the PHY pre-settings.
|
||||
* The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).
|
||||
* The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
|
||||
* The RXDV pin is used to select test mode on reset (pulled up for test mode).
|
||||
* The above pins should be predefined for corresponding settings in resetPins.
|
||||
* The GMAC peripheral pins are configured after the reset is done.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
* \param ul_mck GMAC MCK.
|
||||
*
|
||||
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)
|
||||
{
|
||||
uint8_t uc_rc = GMAC_TIMEOUT;
|
||||
uint8_t uc_phy;
|
||||
|
||||
ethernet_phy_reset(GMAC,uc_phy_addr);
|
||||
|
||||
/* Configure GMAC runtime clock */
|
||||
uc_rc = gmac_set_mdc_clock(p_gmac, mck);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check PHY Address */
|
||||
uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);
|
||||
if (uc_phy == 0xFF) {
|
||||
return 0;
|
||||
}
|
||||
if (uc_phy != uc_phy_addr) {
|
||||
ethernet_phy_reset(p_gmac, uc_phy_addr);
|
||||
}
|
||||
phy_props.phy_chn = uc_phy;
|
||||
return uc_phy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the Link & speed settings, and automatically set up the GMAC with the
|
||||
* settings.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
* \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
|
||||
*
|
||||
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
|
||||
uint8_t uc_apply_setting_flag)
|
||||
{
|
||||
uint32_t ul_stat1;
|
||||
uint32_t ul_stat2;
|
||||
uint8_t uc_phy_address, uc_speed = true, uc_fd = true;
|
||||
uint8_t uc_rc = GMAC_TIMEOUT;
|
||||
|
||||
gmac_enable_management(p_gmac, true);
|
||||
|
||||
uc_phy_address = uc_phy_addr;
|
||||
|
||||
uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
/* Disable PHY management and start the GMAC transfer */
|
||||
gmac_enable_management(p_gmac, false);
|
||||
|
||||
return uc_rc;
|
||||
}
|
||||
if ((ul_stat1 & GMII_LINK_STATUS) == 0) {
|
||||
/* Disable PHY management and start the GMAC transfer */
|
||||
gmac_enable_management(p_gmac, false);
|
||||
|
||||
return GMAC_INVALID;
|
||||
}
|
||||
|
||||
if (uc_apply_setting_flag == 0) {
|
||||
/* Disable PHY management and start the GMAC transfer */
|
||||
gmac_enable_management(p_gmac, false);
|
||||
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
/* Read advertisement */
|
||||
uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);
|
||||
phy_props.phy_stat1 = ul_stat1;
|
||||
phy_props.phy_stat2 = ul_stat2;
|
||||
if (uc_rc != GMAC_OK) {
|
||||
/* Disable PHY management and start the GMAC transfer */
|
||||
gmac_enable_management(p_gmac, false);
|
||||
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {
|
||||
/* Set GMAC for 100BaseTX and Full Duplex */
|
||||
uc_speed = true;
|
||||
uc_fd = true;
|
||||
} else
|
||||
if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {
|
||||
/* Set MII for 100BaseTX and Half Duplex */
|
||||
uc_speed = true;
|
||||
uc_fd = false;
|
||||
} else
|
||||
if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {
|
||||
/* Set MII for 10BaseT and Full Duplex */
|
||||
uc_speed = false;
|
||||
uc_fd = true;
|
||||
} else
|
||||
if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {
|
||||
/* Set MII for 10BaseT and Half Duplex */
|
||||
uc_speed = false;
|
||||
uc_fd = false;
|
||||
}
|
||||
|
||||
gmac_set_speed(p_gmac, uc_speed);
|
||||
gmac_enable_full_duplex(p_gmac, uc_fd);
|
||||
|
||||
/* Start the GMAC transfers */
|
||||
gmac_enable_management(p_gmac, false);
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
PhyProps_t phy_props;
|
||||
|
||||
/**
|
||||
* \brief Issue an auto negotiation of the PHY.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
*
|
||||
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)
|
||||
{
|
||||
uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;
|
||||
uint32_t ul_value;
|
||||
uint32_t ul_phy_anar;
|
||||
uint32_t ul_retry_count = 0;
|
||||
uint8_t uc_speed = 0;
|
||||
uint8_t uc_fd=0;
|
||||
uint8_t uc_rc = GMAC_TIMEOUT;
|
||||
|
||||
gmac_enable_management(p_gmac, true);
|
||||
|
||||
/* Set up control register */
|
||||
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = -1;
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */
|
||||
ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);
|
||||
ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */
|
||||
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = -2;
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Auto_negotiation Advertisement Register.
|
||||
* MII advertising for Next page.
|
||||
* 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
|
||||
*/
|
||||
ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |
|
||||
GMII_AN_IEEE_802_3;
|
||||
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = -3;
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
/* Read & modify control register */
|
||||
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = -4;
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;
|
||||
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = -5;
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
/* Restart auto negotiation */
|
||||
ul_value |= (uint32_t)GMII_RESTART_AUTONEG;
|
||||
ul_value &= ~(uint32_t)GMII_ISOLATE;
|
||||
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = -6;
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
/* Check if auto negotiation is completed */
|
||||
while (1) {
|
||||
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = -7;
|
||||
return uc_rc;
|
||||
}
|
||||
/* Done successfully */
|
||||
if (ul_value & GMII_AUTONEG_COMP) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Timeout check */
|
||||
if (ul_retry_max) {
|
||||
if (++ul_retry_count >= ul_retry_max) {
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = -8;
|
||||
return GMAC_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the auto negotiate link partner base page */
|
||||
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);
|
||||
if (uc_rc != GMAC_OK) {
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = -9;
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
|
||||
/* Set up the GMAC link speed */
|
||||
if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {
|
||||
/* Set MII for 100BaseTX and Full Duplex */
|
||||
uc_speed = true;
|
||||
uc_fd = true;
|
||||
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {
|
||||
/* Set MII for 10BaseT and Full Duplex */
|
||||
uc_speed = false;
|
||||
uc_fd = true;
|
||||
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {
|
||||
/* Set MII for 100BaseTX and half Duplex */
|
||||
uc_speed = true;
|
||||
uc_fd = false;
|
||||
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {
|
||||
/* Set MII for 10BaseT and half Duplex */
|
||||
uc_speed = false;
|
||||
uc_fd = false;
|
||||
}
|
||||
|
||||
gmac_set_speed(p_gmac, uc_speed);
|
||||
gmac_enable_full_duplex(p_gmac, uc_fd);
|
||||
|
||||
/* Select Media Independent Interface type */
|
||||
gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);
|
||||
|
||||
gmac_enable_transmit(GMAC, true);
|
||||
gmac_enable_receive(GMAC, true);
|
||||
|
||||
gmac_enable_management(p_gmac, false);
|
||||
phy_props.phy_result = 1;
|
||||
return uc_rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Issue a SW reset to reset all registers of the PHY.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
*
|
||||
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)
|
||||
{
|
||||
uint32_t ul_bmcr = GMII_RESET;
|
||||
uint8_t uc_phy_address = uc_phy_addr;
|
||||
uint32_t ul_timeout = ETH_PHY_TIMEOUT;
|
||||
uint8_t uc_rc = GMAC_TIMEOUT;
|
||||
|
||||
gmac_enable_management(p_gmac, true);
|
||||
|
||||
ul_bmcr = GMII_RESET;
|
||||
gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);
|
||||
|
||||
do {
|
||||
gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);
|
||||
ul_timeout--;
|
||||
} while ((ul_bmcr & GMII_RESET) && ul_timeout);
|
||||
|
||||
gmac_enable_management(p_gmac, false);
|
||||
|
||||
if (!ul_timeout) {
|
||||
uc_rc = GMAC_OK;
|
||||
}
|
||||
|
||||
return (uc_rc);
|
||||
}
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief KSZ8051MNL (Ethernet PHY) driver for SAM.
|
||||
*
|
||||
* Copyright (c) 2013 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ETHERNET_PHY_H_INCLUDED
|
||||
#define ETHERNET_PHY_H_INCLUDED
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// IEEE defined Registers
|
||||
#define GMII_BMCR 0x00 // Basic Control
|
||||
#define GMII_BMSR 0x01 // Basic Status
|
||||
#define GMII_PHYID1 0x02 // PHY Idendifier 1
|
||||
#define GMII_PHYID2 0x03 // PHY Idendifier 2
|
||||
#define GMII_ANAR 0x04 // Auto_Negotiation Advertisement
|
||||
#define GMII_ANLPAR 0x05 // Auto_negotiation Link Partner Ability
|
||||
#define GMII_ANER 0x06 // Auto-negotiation Expansion
|
||||
#define GMII_ANNPR 0x07 // Auto-negotiation Next Page
|
||||
#define GMII_ANLPNPAR 0x08 // Link Partner Next Page Ability
|
||||
//#define GMII_1000BTCR 9 // 1000Base-T Control // Reserved
|
||||
//#define GMII_1000BTSR 10 // 1000Base-T Status // Reserved
|
||||
#define GMII_AFECR1 0x11 // AFE Control 1
|
||||
//#define GMII_ERDWR 12 // Extend Register - Data Write Register
|
||||
//#define GMII_ERDRR 13 // Extend Register - Data Read Register
|
||||
//14 reserved
|
||||
#define GMII_RXERCR 0x15 // RXER Counter
|
||||
|
||||
#define PHY_REG_01_BMSR 0x01 // Basic mode status register
|
||||
#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
|
||||
#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
|
||||
#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
|
||||
#define PHY_REG_05_LPA 0x05 // Link partner ability reg
|
||||
#define PHY_REG_06_ANER 0x06 // 6 RW Auto-Negotiation Expansion Register
|
||||
#define PHY_REG_07_ANNPTR 0x07 // 7 RW Auto-Negotiation Next Page TX
|
||||
#define PHY_REG_08_RESERVED0 0x08 // 0x08..0x0Fh 8-15 RW RESERVED
|
||||
|
||||
#define PHY_REG_10_PHYSTS 0x10 // 16 RO PHY Status Register
|
||||
#define PHY_REG_11_MICR 0x11 // 17 RW MII Interrupt Control Register
|
||||
#define PHY_REG_12_MISR 0x12 // 18 RO MII Interrupt Status Register
|
||||
#define PHY_REG_13_RESERVED1 0x13 // 19 RW RESERVED
|
||||
#define PHY_REG_14_FCSCR 0x14 // 20 RO False Carrier Sense Counter Register
|
||||
#define PHY_REG_15_RECR 0x15 // 21 RO Receive Error Counter Register
|
||||
#define PHY_REG_16_PCSR 0x16 // 22 RW PCS Sub-Layer Configuration and Status Register
|
||||
#define PHY_REG_17_RBR 0x17 // 23 RW RMII and Bypass Register
|
||||
#define PHY_REG_18_LEDCR 0x18 // 24 RW LED Direct Control Register
|
||||
#define PHY_REG_19_PHYCR 0x19 // 25 RW PHY Control Register
|
||||
#define PHY_REG_1A_10BTSCR 0x1A // 26 RW 10Base-T Status/Control Register
|
||||
#define PHY_REG_1B_CDCTRL1 0x1B // 27 RW CD Test Control Register and BIST Extensions Register
|
||||
#define PHY_REG_1B_INT_CTRL 0x1B // 27 RW KSZ8041NL interrupt control
|
||||
#define PHY_REG_1C_RESERVED2 0x1C // 28 RW RESERVED
|
||||
#define PHY_REG_1D_EDCR 0x1D // 29 RW Energy Detect Control Register
|
||||
#define PHY_REG_1E_RESERVED3 0x1E //
|
||||
#define PHY_REG_1F_RESERVED4 0x1F // 30-31 RW RESERVED
|
||||
|
||||
#define PHY_REG_1E_PHYCR_1 0x1E //
|
||||
#define PHY_REG_1F_PHYCR_2 0x1F //
|
||||
|
||||
#define PHY_SPEED_10 1
|
||||
#define PHY_SPEED_100 2
|
||||
#define PHY_SPEED_AUTO (PHY_SPEED_10|PHY_SPEED_100)
|
||||
|
||||
#define PHY_MDIX_DIRECT 1
|
||||
#define PHY_MDIX_CROSSED 2
|
||||
#define PHY_MDIX_AUTO (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)
|
||||
|
||||
#define PHY_DUPLEX_HALF 1
|
||||
#define PHY_DUPLEX_FULL 2
|
||||
#define PHY_DUPLEX_AUTO (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)
|
||||
|
||||
typedef struct _SPhyProps {
|
||||
unsigned char speed;
|
||||
unsigned char mdix;
|
||||
unsigned char duplex;
|
||||
unsigned char spare;
|
||||
} SPhyProps;
|
||||
|
||||
const char *phyPrintable (const SPhyProps *apProps);
|
||||
|
||||
extern SPhyProps phyProps;
|
||||
|
||||
#define GMII_OMSOR 0x16 // Operation Mode Strap Override
|
||||
#define GMII_OMSSR 0x17 // Operation Mode Strap Status
|
||||
#define GMII_ECR 0x18 // Expanded Control
|
||||
//#define GMII_DPPSR 19 // Digital PMA/PCS Status
|
||||
//20 reserved
|
||||
//#define GMII_RXERCR 21 // RXER Counter Register
|
||||
//22-26 reserved
|
||||
#define GMII_ICSR 0x1B // Interrupt Control/Status
|
||||
//#define GMII_DDC1R 28 // Digital Debug Control 1 Register
|
||||
#define GMII_LCSR 0x1D // LinkMD Control/Status
|
||||
|
||||
//29-30 reserved
|
||||
#define GMII_PCR1 0x1E // PHY Control 1
|
||||
#define GMII_PCR2 0x1F // PHY Control 2
|
||||
|
||||
/*
|
||||
//Extend Registers
|
||||
#define GMII_CCR 256 // Common Control Register
|
||||
#define GMII_SSR 257 // Strap Status Register
|
||||
#define GMII_OMSOR 258 // Operation Mode Strap Override Register
|
||||
#define GMII_OMSSR 259 // Operation Mode Strap Status Register
|
||||
#define GMII_RCCPSR 260 // RGMII Clock and Control Pad Skew Register
|
||||
#define GMII_RRDPSR 261 // RGMII RX Data Pad Skew Register
|
||||
#define GMII_ATR 263 // Analog Test Register
|
||||
*/
|
||||
|
||||
|
||||
// Bit definitions: GMII_BMCR 0x00 Basic Control
|
||||
#define GMII_RESET (1 << 15) // 1= Software Reset; 0=Normal Operation
|
||||
#define GMII_LOOPBACK (1 << 14) // 1=loopback Enabled; 0=Normal Operation
|
||||
#define GMII_SPEED_SELECT (1 << 13) // 1=100Mbps; 0=10Mbps
|
||||
#define GMII_AUTONEG (1 << 12) // Auto-negotiation Enable
|
||||
#define GMII_POWER_DOWN (1 << 11) // 1=Power down 0=Normal operation
|
||||
#define GMII_ISOLATE (1 << 10) // 1 = Isolates 0 = Normal operation
|
||||
#define GMII_RESTART_AUTONEG (1 << 9) // 1 = Restart auto-negotiation 0 = Normal operation
|
||||
#define GMII_DUPLEX_MODE (1 << 8) // 1 = Full duplex operation 0 = Normal operation
|
||||
#define GMII_COLLISION_TEST (1 << 7) // 1 = Enable COL test; 0 = Disable COL test
|
||||
//#define GMII_SPEED_SELECT_MSB (1 << 6) // Reserved
|
||||
// Reserved 6 to 0 // Read as 0, ignore on write
|
||||
|
||||
// Bit definitions: GMII_BMSR 0x01 Basic Status
|
||||
#define GMII_100BASE_T4 (1 << 15) // 100BASE-T4 Capable
|
||||
#define GMII_100BASE_TX_FD (1 << 14) // 100BASE-TX Full Duplex Capable
|
||||
#define GMII_100BASE_T4_HD (1 << 13) // 100BASE-TX Half Duplex Capable
|
||||
#define GMII_10BASE_T_FD (1 << 12) // 10BASE-T Full Duplex Capable
|
||||
#define GMII_10BASE_T_HD (1 << 11) // 10BASE-T Half Duplex Capable
|
||||
// Reserved 10 to79 // Read as 0, ignore on write
|
||||
//#define GMII_EXTEND_STATUS (1 << 8) // 1 = Extend Status Information In Reg 15
|
||||
// Reserved 7
|
||||
#define GMII_MF_PREAMB_SUPPR (1 << 6) // MII Frame Preamble Suppression
|
||||
#define GMII_AUTONEG_COMP (1 << 5) // Auto-negotiation Complete
|
||||
#define GMII_REMOTE_FAULT (1 << 4) // Remote Fault
|
||||
#define GMII_AUTONEG_ABILITY (1 << 3) // Auto Configuration Ability
|
||||
#define GMII_LINK_STATUS (1 << 2) // Link Status
|
||||
#define GMII_JABBER_DETECT (1 << 1) // Jabber Detect
|
||||
#define GMII_EXTEND_CAPAB (1 << 0) // Extended Capability
|
||||
|
||||
|
||||
// Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1
|
||||
// Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2
|
||||
#define GMII_LSB_MASK 0x3F
|
||||
#define GMII_OUI_MSB 0x0022
|
||||
#define GMII_OUI_LSB 0x05
|
||||
|
||||
|
||||
// Bit definitions: GMII_ANAR 0x04 Auto_Negotiation Advertisement
|
||||
// Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability
|
||||
#define GMII_NP (1 << 15) // Next page Indication
|
||||
// Reserved 7
|
||||
#define GMII_RF (1 << 13) // Remote Fault
|
||||
// Reserved 12 // Write as 0, ignore on read
|
||||
#define GMII_PAUSE_MASK (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)
|
||||
// 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)
|
||||
#define GMII_100T4 (1 << 9) // 100BASE-T4 Support
|
||||
#define GMII_100TX_FDX (1 << 8) // 100BASE-TX Full Duplex Support
|
||||
#define GMII_100TX_HDX (1 << 7) // 100BASE-TX Support
|
||||
#define GMII_10_FDX (1 << 6) // 10BASE-T Full Duplex Support
|
||||
#define GMII_10_HDX (1 << 5) // 10BASE-T Support
|
||||
// Selector 4 to 0 // Protocol Selection Bits
|
||||
#define GMII_AN_IEEE_802_3 0x0001 // [00001] = IEEE 802.3
|
||||
|
||||
|
||||
// Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion
|
||||
// Reserved 15 to 5 // Read as 0, ignore on write
|
||||
#define GMII_PDF (1 << 4) // Local Device Parallel Detection Fault
|
||||
#define GMII_LP_NP_ABLE (1 << 3) // Link Partner Next Page Able
|
||||
#define GMII_NP_ABLE (1 << 2) // Local Device Next Page Able
|
||||
#define GMII_PAGE_RX (1 << 1) // New Page Received
|
||||
#define GMII_LP_AN_ABLE (1 << 0) // Link Partner Auto-negotiation Able
|
||||
|
||||
/**
|
||||
* \brief Perform a HW initialization to the PHY and set up clocks.
|
||||
*
|
||||
* This should be called only once to initialize the PHY pre-settings.
|
||||
* The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups).
|
||||
* The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
|
||||
* The RXDV pin is used to select test mode on reset (pulled up for test mode).
|
||||
* The above pins should be predefined for corresponding settings in resetPins.
|
||||
* The GMAC peripheral pins are configured after the reset is done.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
* \param ul_mck GMAC MCK.
|
||||
*
|
||||
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the Link & speed settings, and automatically set up the GMAC with the
|
||||
* settings.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
* \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
|
||||
*
|
||||
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
|
||||
uint8_t uc_apply_setting_flag);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Issue an auto negotiation of the PHY.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
*
|
||||
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr);
|
||||
|
||||
/**
|
||||
* \brief Issue a SW reset to reset all registers of the PHY.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
*
|
||||
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr);
|
||||
|
||||
typedef struct xPHY_PROPS {
|
||||
signed char phy_result;
|
||||
uint32_t phy_params;
|
||||
uint32_t phy_stat1;
|
||||
uint32_t phy_stat2;
|
||||
unsigned char phy_chn;
|
||||
} PhyProps_t;
|
||||
extern PhyProps_t phy_props;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */
|
||||
|
||||
|
|
@ -0,0 +1,945 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief GMAC (Ethernet MAC) driver for SAM.
|
||||
*
|
||||
* Copyright (c) 2013 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
|
||||
#include "compiler.h"
|
||||
#include "instance/gmac.h"
|
||||
#include "ethernet_phy.h"
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (int)( sizeof(x) / sizeof(x)[0] )
|
||||
#endif
|
||||
/**
|
||||
* \defgroup gmac_group Ethernet Media Access Controller
|
||||
*
|
||||
* See \ref gmac_quickstart.
|
||||
*
|
||||
* Driver for the GMAC (Ethernet Media Access Controller).
|
||||
* This file contains basic functions for the GMAC, with support for all modes, settings
|
||||
* and clock speeds.
|
||||
*
|
||||
* \section dependencies Dependencies
|
||||
* This driver does not depend on other modules.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** TX descriptor lists */
|
||||
COMPILER_ALIGNED(8)
|
||||
static gmac_tx_descriptor_t gs_tx_desc[ GMAC_TX_BUFFERS ];
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
/** TX callback lists */
|
||||
static gmac_dev_tx_cb_t gs_tx_callback[ GMAC_TX_BUFFERS ];
|
||||
#endif
|
||||
/** RX descriptors lists */
|
||||
COMPILER_ALIGNED(8)
|
||||
static gmac_rx_descriptor_t gs_rx_desc[ GMAC_RX_BUFFERS ];
|
||||
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
|
||||
/** Send Buffer. Section 3.6 of AMBA 2.0 spec states that burst should not cross the
|
||||
* 1K Boundaries. Receive buffer manager write operations are burst of 2 words => 3 lsb bits
|
||||
* of the address shall be set to 0.
|
||||
*/
|
||||
COMPILER_ALIGNED(8)
|
||||
static uint8_t gs_uc_tx_buffer[ GMAC_TX_BUFFERS * GMAC_TX_UNITSIZE ];
|
||||
#endif /* ipconfigZERO_COPY_TX_DRIVER */
|
||||
|
||||
/** Receive Buffer */
|
||||
COMPILER_ALIGNED(8)
|
||||
static uint8_t gs_uc_rx_buffer[ GMAC_RX_BUFFERS * GMAC_RX_UNITSIZE ];
|
||||
|
||||
/**
|
||||
* GMAC device memory management struct.
|
||||
*/
|
||||
typedef struct gmac_dev_mem {
|
||||
/* Pointer to allocated buffer for RX. The address should be 8-byte aligned
|
||||
and the size should be GMAC_RX_UNITSIZE * wRxSize. */
|
||||
uint8_t *p_rx_buffer;
|
||||
/* Pointer to allocated RX descriptor list. */
|
||||
gmac_rx_descriptor_t *p_rx_dscr;
|
||||
/* RX size, in number of registered units (RX descriptors). */
|
||||
/* Increased size from 16- to 32-bits, because it's more efficient */
|
||||
uint32_t us_rx_size;
|
||||
/* Pointer to allocated buffer for TX. The address should be 8-byte aligned
|
||||
and the size should be GMAC_TX_UNITSIZE * wTxSize. */
|
||||
uint8_t *p_tx_buffer;
|
||||
/* Pointer to allocated TX descriptor list. */
|
||||
gmac_tx_descriptor_t *p_tx_dscr;
|
||||
/* TX size, in number of registered units (TX descriptors). */
|
||||
uint32_t us_tx_size;
|
||||
} gmac_dev_mem_t;
|
||||
|
||||
/** Return count in buffer */
|
||||
#define CIRC_CNT( head, tail, size ) ( ( ( head ) - ( tail ) ) % ( size ) )
|
||||
|
||||
/*
|
||||
* Return space available, from 0 to size-1.
|
||||
* Always leave one free char as a completely full buffer that has (head == tail),
|
||||
* which is the same as empty.
|
||||
*/
|
||||
#define CIRC_SPACE( head, tail, size ) CIRC_CNT( ( tail ), ( ( head ) + 1 ), ( size ) )
|
||||
|
||||
/** Circular buffer is empty ? */
|
||||
#define CIRC_EMPTY( head, tail ) ( head == tail )
|
||||
/** Clear circular buffer */
|
||||
#define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( 0 )
|
||||
|
||||
/** Increment head or tail */
|
||||
static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )
|
||||
{
|
||||
( *lHeadOrTail ) ++;
|
||||
if( ( *lHeadOrTail ) >= ( int32_t )ulSize )
|
||||
{
|
||||
( *lHeadOrTail ) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait PHY operation to be completed.
|
||||
*
|
||||
* \param p_gmac HW controller address.
|
||||
* \param ul_retry The retry times, 0 to wait forever until completeness.
|
||||
*
|
||||
* Return GMAC_OK if the operation is completed successfully.
|
||||
*/
|
||||
static uint8_t gmac_wait_phy(Gmac* p_gmac, const uint32_t ul_retry)
|
||||
{
|
||||
volatile uint32_t ul_retry_count = 0;
|
||||
const uint32_t xPHYPollDelay = pdMS_TO_TICKS( 1ul );
|
||||
|
||||
while (!gmac_is_phy_idle(p_gmac)) {
|
||||
if (ul_retry == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ul_retry_count++;
|
||||
|
||||
if (ul_retry_count >= ul_retry) {
|
||||
return GMAC_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Block the task to allow other tasks to execute while the PHY
|
||||
is not connected. */
|
||||
vTaskDelay( xPHYPollDelay );
|
||||
}
|
||||
return GMAC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable transfer, reset registers and descriptor lists.
|
||||
*
|
||||
* \param p_dev Pointer to GMAC driver instance.
|
||||
*
|
||||
*/
|
||||
static void gmac_reset_tx_mem(gmac_device_t* p_dev)
|
||||
{
|
||||
Gmac *p_hw = p_dev->p_hw;
|
||||
uint8_t *p_tx_buff = p_dev->p_tx_buffer;
|
||||
gmac_tx_descriptor_t *p_td = p_dev->p_tx_dscr;
|
||||
|
||||
uint32_t ul_index;
|
||||
uint32_t ul_address;
|
||||
|
||||
/* Disable TX */
|
||||
gmac_enable_transmit(p_hw, 0);
|
||||
|
||||
/* Set up the TX descriptors */
|
||||
CIRC_CLEAR(p_dev->l_tx_head, p_dev->l_tx_tail);
|
||||
for( ul_index = 0; ul_index < p_dev->ul_tx_list_size; ul_index++ )
|
||||
{
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
{
|
||||
ul_address = (uint32_t) 0u;
|
||||
}
|
||||
#else
|
||||
{
|
||||
ul_address = (uint32_t) (&(p_tx_buff[ul_index * GMAC_TX_UNITSIZE]));
|
||||
}
|
||||
#endif /* ipconfigZERO_COPY_TX_DRIVER */
|
||||
p_td[ul_index].addr = ul_address;
|
||||
p_td[ul_index].status.val = GMAC_TXD_USED;
|
||||
}
|
||||
p_td[p_dev->ul_tx_list_size - 1].status.val =
|
||||
GMAC_TXD_USED | GMAC_TXD_WRAP;
|
||||
|
||||
/* Set transmit buffer queue */
|
||||
gmac_set_tx_queue(p_hw, (uint32_t) p_td);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable receiver, reset registers and descriptor list.
|
||||
*
|
||||
* \param p_drv Pointer to GMAC Driver instance.
|
||||
*/
|
||||
static void gmac_reset_rx_mem(gmac_device_t* p_dev)
|
||||
{
|
||||
Gmac *p_hw = p_dev->p_hw;
|
||||
uint8_t *p_rx_buff = p_dev->p_rx_buffer;
|
||||
gmac_rx_descriptor_t *pRd = p_dev->p_rx_dscr;
|
||||
|
||||
uint32_t ul_index;
|
||||
uint32_t ul_address;
|
||||
|
||||
/* Disable RX */
|
||||
gmac_enable_receive(p_hw, 0);
|
||||
|
||||
/* Set up the RX descriptors */
|
||||
p_dev->ul_rx_idx = 0;
|
||||
for( ul_index = 0; ul_index < p_dev->ul_rx_list_size; ul_index++ )
|
||||
{
|
||||
ul_address = (uint32_t) (&(p_rx_buff[ul_index * GMAC_RX_UNITSIZE]));
|
||||
pRd[ul_index].addr.val = ul_address & GMAC_RXD_ADDR_MASK;
|
||||
pRd[ul_index].status.val = 0;
|
||||
}
|
||||
pRd[p_dev->ul_rx_list_size - 1].addr.val |= GMAC_RXD_WRAP;
|
||||
|
||||
/* Set receive buffer queue */
|
||||
gmac_set_rx_queue(p_hw, (uint32_t) pRd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize the allocated buffer lists for GMAC driver to transfer data.
|
||||
* Must be invoked after gmac_dev_init() but before RX/TX starts.
|
||||
*
|
||||
* \note If input address is not 8-byte aligned, the address is automatically
|
||||
* adjusted and the list size is reduced by one.
|
||||
*
|
||||
* \param p_gmac Pointer to GMAC instance.
|
||||
* \param p_gmac_dev Pointer to GMAC device instance.
|
||||
* \param p_dev_mm Pointer to the GMAC memory management control block.
|
||||
* \param p_tx_cb Pointer to allocated TX callback list.
|
||||
*
|
||||
* \return GMAC_OK or GMAC_PARAM.
|
||||
*/
|
||||
static uint8_t gmac_init_mem(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
|
||||
gmac_dev_mem_t* p_dev_mm
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
, gmac_dev_tx_cb_t* p_tx_cb
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (p_dev_mm->us_rx_size <= 1 || p_dev_mm->us_tx_size <= 1
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
|| p_tx_cb == NULL
|
||||
#endif
|
||||
) {
|
||||
return GMAC_PARAM;
|
||||
}
|
||||
|
||||
/* Assign RX buffers */
|
||||
if (((uint32_t) p_dev_mm->p_rx_buffer & 0x7)
|
||||
|| ((uint32_t) p_dev_mm->p_rx_dscr & 0x7)) {
|
||||
p_dev_mm->us_rx_size--;
|
||||
}
|
||||
p_gmac_dev->p_rx_buffer =
|
||||
(uint8_t *) ((uint32_t) p_dev_mm->p_rx_buffer & 0xFFFFFFF8);
|
||||
p_gmac_dev->p_rx_dscr =
|
||||
(gmac_rx_descriptor_t *) ((uint32_t) p_dev_mm->p_rx_dscr
|
||||
& 0xFFFFFFF8);
|
||||
p_gmac_dev->ul_rx_list_size = p_dev_mm->us_rx_size;
|
||||
|
||||
/* Assign TX buffers */
|
||||
if (((uint32_t) p_dev_mm->p_tx_buffer & 0x7)
|
||||
|| ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) {
|
||||
p_dev_mm->us_tx_size--;
|
||||
}
|
||||
p_gmac_dev->p_tx_buffer =
|
||||
(uint8_t *) ((uint32_t) p_dev_mm->p_tx_buffer & 0xFFFFFFF8);
|
||||
p_gmac_dev->p_tx_dscr =
|
||||
(gmac_tx_descriptor_t *) ((uint32_t) p_dev_mm->p_tx_dscr
|
||||
& 0xFFFFFFF8);
|
||||
p_gmac_dev->ul_tx_list_size = p_dev_mm->us_tx_size;
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
p_gmac_dev->func_tx_cb_list = p_tx_cb;
|
||||
#endif
|
||||
/* Reset TX & RX */
|
||||
gmac_reset_rx_mem(p_gmac_dev);
|
||||
gmac_reset_tx_mem(p_gmac_dev);
|
||||
|
||||
/* Enable Rx and Tx, plus the statistics register */
|
||||
gmac_enable_transmit(p_gmac, true);
|
||||
gmac_enable_receive(p_gmac, true);
|
||||
gmac_enable_statistics_write(p_gmac, true);
|
||||
|
||||
/* Set up the interrupts for transmission and errors */
|
||||
gmac_enable_interrupt(p_gmac,
|
||||
GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */
|
||||
GMAC_IER_TUR | /* Enable transmit underrun interrupt. */
|
||||
GMAC_IER_RLEX | /* Enable retry limit exceeded interrupt. */
|
||||
GMAC_IER_TFC | /* Enable transmit buffers exhausted in mid-frame interrupt. */
|
||||
GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */
|
||||
GMAC_IER_ROVR | /* Enable receive overrun interrupt. */
|
||||
GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */
|
||||
GMAC_IER_PFNZ | /* Enable pause frame received interrupt. */
|
||||
GMAC_IER_PTZ); /* Enable pause time zero interrupt. */
|
||||
|
||||
return GMAC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read the PHY register.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_address PHY address.
|
||||
* \param uc_address Register address.
|
||||
* \param p_value Pointer to a 32-bit location to store read data.
|
||||
*
|
||||
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,
|
||||
uint32_t* p_value)
|
||||
{
|
||||
gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 1, 0);
|
||||
|
||||
if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {
|
||||
return GMAC_TIMEOUT;
|
||||
}
|
||||
*p_value = gmac_get_phy_data(p_gmac);
|
||||
return GMAC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Write the PHY register.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param uc_phy_address PHY Address.
|
||||
* \param uc_address Register Address.
|
||||
* \param ul_value Data to write, actually 16-bit data.
|
||||
*
|
||||
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
|
||||
*/
|
||||
uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,
|
||||
uint8_t uc_address, uint32_t ul_value)
|
||||
{
|
||||
gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 0, ul_value);
|
||||
|
||||
if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {
|
||||
return GMAC_TIMEOUT;
|
||||
}
|
||||
return GMAC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialize the GMAC driver.
|
||||
*
|
||||
* \param p_gmac Pointer to the GMAC instance.
|
||||
* \param p_gmac_dev Pointer to the GMAC device instance.
|
||||
* \param p_opt GMAC configure options.
|
||||
*/
|
||||
void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
|
||||
gmac_options_t* p_opt)
|
||||
{
|
||||
gmac_dev_mem_t gmac_dev_mm;
|
||||
|
||||
/* Disable TX & RX and more */
|
||||
gmac_network_control(p_gmac, 0);
|
||||
gmac_disable_interrupt(p_gmac, ~0u);
|
||||
|
||||
|
||||
gmac_clear_statistics(p_gmac);
|
||||
|
||||
/* Clear all status bits in the receive status register. */
|
||||
gmac_clear_rx_status(p_gmac, GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA);
|
||||
|
||||
/* Clear all status bits in the transmit status register */
|
||||
gmac_clear_tx_status(p_gmac, GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE
|
||||
| GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_UND);
|
||||
|
||||
/* Clear interrupts */
|
||||
gmac_get_interrupt_status(p_gmac);
|
||||
#if !defined(ETHERNET_CONF_DATA_OFFSET)
|
||||
/* Receive Buffer Offset
|
||||
* Indicates the number of bytes by which the received data
|
||||
* is offset from the start of the receive buffer
|
||||
* which can be handy for alignment reasons */
|
||||
/* Note: FreeRTOS+TCP wants to have this offset set to 2 bytes */
|
||||
#error ETHERNET_CONF_DATA_OFFSET not defined, assuming 0
|
||||
#endif
|
||||
/* Enable the copy of data into the buffers
|
||||
ignore broadcasts, and not copy FCS. */
|
||||
|
||||
gmac_set_configure(p_gmac,
|
||||
( gmac_get_configure(p_gmac) & ~GMAC_NCFGR_RXBUFO_Msk ) |
|
||||
GMAC_NCFGR_RFCS | /* Remove FCS, frame check sequence (last 4 bytes) */
|
||||
GMAC_NCFGR_PEN | /* Pause Enable */
|
||||
GMAC_NCFGR_RXBUFO( ETHERNET_CONF_DATA_OFFSET ) |
|
||||
GMAC_RXD_RXCOEN );
|
||||
|
||||
/*
|
||||
* GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable.
|
||||
* Note: tha SAM4E does have RX checksum offloading
|
||||
* but TX checksum offloading has NOT been implemented.
|
||||
* http://community.atmel.com/forum/sam4e-gmac-transmit-checksum-offload-enablesolved
|
||||
*/
|
||||
|
||||
gmac_set_dma(p_gmac,
|
||||
gmac_get_dma(p_gmac) | GMAC_DCFGR_TXCOEN );
|
||||
|
||||
gmac_enable_copy_all(p_gmac, p_opt->uc_copy_all_frame);
|
||||
gmac_disable_broadcast(p_gmac, p_opt->uc_no_boardcast);
|
||||
|
||||
/* Fill in GMAC device memory management */
|
||||
gmac_dev_mm.p_rx_buffer = gs_uc_rx_buffer;
|
||||
gmac_dev_mm.p_rx_dscr = gs_rx_desc;
|
||||
gmac_dev_mm.us_rx_size = GMAC_RX_BUFFERS;
|
||||
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
{
|
||||
gmac_dev_mm.p_tx_buffer = NULL;
|
||||
}
|
||||
#else
|
||||
{
|
||||
gmac_dev_mm.p_tx_buffer = gs_uc_tx_buffer;
|
||||
}
|
||||
#endif
|
||||
gmac_dev_mm.p_tx_dscr = gs_tx_desc;
|
||||
gmac_dev_mm.us_tx_size = GMAC_TX_BUFFERS;
|
||||
|
||||
gmac_init_mem(p_gmac, p_gmac_dev, &gmac_dev_mm
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
, gs_tx_callback
|
||||
#endif
|
||||
);
|
||||
|
||||
gmac_set_address(p_gmac, 0, p_opt->uc_mac_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Frames can be read from the GMAC in multiple sections.
|
||||
*
|
||||
* Returns > 0 if a complete frame is available
|
||||
* It also it cleans up incomplete older frames
|
||||
*/
|
||||
|
||||
static uint32_t gmac_dev_poll(gmac_device_t* p_gmac_dev)
|
||||
{
|
||||
uint32_t ulReturn = 0;
|
||||
int32_t ulIndex = p_gmac_dev->ul_rx_idx;
|
||||
gmac_rx_descriptor_t *pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];
|
||||
|
||||
/* Discard any incomplete frames */
|
||||
while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) &&
|
||||
(pxHead->status.val & GMAC_RXD_SOF) == 0) {
|
||||
pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
|
||||
circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);
|
||||
pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];
|
||||
p_gmac_dev->ul_rx_idx = ulIndex;
|
||||
#if( GMAC_STATS != 0 )
|
||||
{
|
||||
gmacStats.incompCount++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0) {
|
||||
if ((pxHead->status.val & GMAC_RXD_EOF) != 0) {
|
||||
/* Here a complete frame has been seen with SOF and EOF */
|
||||
ulReturn = pxHead->status.bm.len;
|
||||
break;
|
||||
}
|
||||
circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);
|
||||
pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];
|
||||
if ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) == 0) {
|
||||
/* CPU is not the owner (yet) */
|
||||
break;
|
||||
}
|
||||
if ((pxHead->status.val & GMAC_RXD_SOF) != 0) {
|
||||
/* Strange, we found a new Start Of Frame
|
||||
* discard previous segments */
|
||||
int32_t ulPrev = p_gmac_dev->ul_rx_idx;
|
||||
pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];
|
||||
do {
|
||||
pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
|
||||
circ_inc32 (&ulPrev, p_gmac_dev->ul_rx_list_size);
|
||||
pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];
|
||||
#if( GMAC_STATS != 0 )
|
||||
{
|
||||
gmacStats.truncCount++;
|
||||
}
|
||||
#endif
|
||||
} while (ulPrev != ulIndex);
|
||||
p_gmac_dev->ul_rx_idx = ulIndex;
|
||||
}
|
||||
}
|
||||
return ulReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Frames can be read from the GMAC in multiple sections.
|
||||
* Read ul_frame_size bytes from the GMAC receive buffers to pcTo.
|
||||
* p_rcv_size is the size of the entire frame. Generally gmac_read
|
||||
* will be repeatedly called until the sum of all the ul_frame_size equals
|
||||
* the value of p_rcv_size.
|
||||
*
|
||||
* \param p_gmac_dev Pointer to the GMAC device instance.
|
||||
* \param p_frame Address of the frame buffer.
|
||||
* \param ul_frame_size Length of the frame.
|
||||
* \param p_rcv_size Received frame size.
|
||||
*
|
||||
* \return GMAC_OK if receiving frame successfully, otherwise failed.
|
||||
*/
|
||||
uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,
|
||||
uint32_t ul_frame_size, uint32_t* p_rcv_size)
|
||||
{
|
||||
int32_t nextIdx; /* A copy of the Rx-index 'ul_rx_idx' */
|
||||
int32_t bytesLeft = gmac_dev_poll (p_gmac_dev);
|
||||
gmac_rx_descriptor_t *pxHead;
|
||||
|
||||
if (bytesLeft == 0 )
|
||||
{
|
||||
return GMAC_RX_NULL;
|
||||
}
|
||||
|
||||
/* gmac_dev_poll has confirmed that there is a complete frame at
|
||||
* the current position 'ul_rx_idx'
|
||||
*/
|
||||
nextIdx = p_gmac_dev->ul_rx_idx;
|
||||
|
||||
/* Read +2 bytes because buffers are aligned at -2 bytes */
|
||||
bytesLeft = min( bytesLeft + 2, ( int32_t )ul_frame_size );
|
||||
|
||||
/* The frame will be copied in 1 or 2 memcpy's */
|
||||
if( ( p_frame != NULL ) && ( bytesLeft != 0 ) )
|
||||
{
|
||||
const uint8_t *source;
|
||||
int32_t left;
|
||||
int32_t toCopy;
|
||||
|
||||
source = p_gmac_dev->p_rx_buffer + nextIdx * GMAC_RX_UNITSIZE;
|
||||
left = bytesLeft;
|
||||
toCopy = ( p_gmac_dev->ul_rx_list_size - nextIdx ) * GMAC_RX_UNITSIZE;
|
||||
if(toCopy > left )
|
||||
{
|
||||
toCopy = left;
|
||||
}
|
||||
memcpy (p_frame, source, toCopy);
|
||||
left -= toCopy;
|
||||
|
||||
if( left != 0ul )
|
||||
{
|
||||
memcpy (p_frame + toCopy, (void*)p_gmac_dev->p_rx_buffer, left);
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
pxHead = &p_gmac_dev->p_rx_dscr[nextIdx];
|
||||
pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
|
||||
circ_inc32 (&nextIdx, p_gmac_dev->ul_rx_list_size);
|
||||
} while ((pxHead->status.val & GMAC_RXD_EOF) == 0);
|
||||
|
||||
p_gmac_dev->ul_rx_idx = nextIdx;
|
||||
|
||||
*p_rcv_size = bytesLeft;
|
||||
|
||||
return GMAC_OK;
|
||||
}
|
||||
|
||||
|
||||
extern void vGMACGenerateChecksum( uint8_t *apBuffer );
|
||||
|
||||
/**
|
||||
* \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the
|
||||
* GMAC Tx buffers, and then indicates to the GMAC that the buffer is ready.
|
||||
* If lEndOfFrame is true then the data being copied is the end of the frame
|
||||
* and the frame can be transmitted.
|
||||
*
|
||||
* \param p_gmac_dev Pointer to the GMAC device instance.
|
||||
* \param p_buffer Pointer to the data buffer.
|
||||
* \param ul_size Length of the frame.
|
||||
* \param func_tx_cb Transmit callback function.
|
||||
*
|
||||
* \return Length sent.
|
||||
*/
|
||||
uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
|
||||
uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb)
|
||||
{
|
||||
|
||||
volatile gmac_tx_descriptor_t *p_tx_td;
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
volatile gmac_dev_tx_cb_t *p_func_tx_cb;
|
||||
#endif
|
||||
|
||||
Gmac *p_hw = p_gmac_dev->p_hw;
|
||||
|
||||
#if( GMAC_USES_TX_CALLBACK == 0 )
|
||||
( void )func_tx_cb;
|
||||
#endif
|
||||
|
||||
/* Check parameter */
|
||||
if (ul_size > GMAC_TX_UNITSIZE) {
|
||||
return GMAC_PARAM;
|
||||
}
|
||||
|
||||
/* Pointers to the current transmit descriptor */
|
||||
p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_head];
|
||||
|
||||
/* If no free TxTd, buffer can't be sent, schedule the wakeup callback */
|
||||
// if (CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
|
||||
// p_gmac_dev->ul_tx_list_size) == 0)
|
||||
{
|
||||
if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)
|
||||
return GMAC_TX_BUSY;
|
||||
}
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
/* Pointers to the current Tx callback */
|
||||
p_func_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_head];
|
||||
#endif
|
||||
|
||||
/* Set up/copy data to transmission buffer */
|
||||
if (p_buffer && ul_size) {
|
||||
/* Driver manages the ring buffer */
|
||||
/* Calculating the checksum here is faster than calculating it from the GMAC buffer
|
||||
* because withing p_buffer, it is well aligned */
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
{
|
||||
/* Zero-copy... */
|
||||
p_tx_td->addr = ( uint32_t ) p_buffer;
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Or memcopy... */
|
||||
memcpy((void *)p_tx_td->addr, p_buffer, ul_size);
|
||||
}
|
||||
#endif /* ipconfigZERO_COPY_TX_DRIVER */
|
||||
vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr );
|
||||
}
|
||||
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
/* Tx callback */
|
||||
*p_func_tx_cb = func_tx_cb;
|
||||
#endif
|
||||
|
||||
/* Update transmit descriptor status */
|
||||
|
||||
/* The buffer size defined is the length of ethernet frame,
|
||||
so it's always the last buffer of the frame. */
|
||||
if( p_gmac_dev->l_tx_head == ( int32_t )( p_gmac_dev->ul_tx_list_size - 1 ) )
|
||||
{
|
||||
/* No need to 'and' with GMAC_TXD_LEN_MASK because ul_size has been checked */
|
||||
p_tx_td->status.val =
|
||||
ul_size | GMAC_TXD_LAST | GMAC_TXD_WRAP;
|
||||
} else {
|
||||
p_tx_td->status.val =
|
||||
ul_size | GMAC_TXD_LAST;
|
||||
}
|
||||
|
||||
circ_inc32( &p_gmac_dev->l_tx_head, p_gmac_dev->ul_tx_list_size );
|
||||
|
||||
/* Now start to transmit if it is still not done */
|
||||
gmac_start_transmission(p_hw);
|
||||
|
||||
return GMAC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get current load of transmit.
|
||||
*
|
||||
* \param p_gmac_dev Pointer to the GMAC device instance.
|
||||
*
|
||||
* \return Current load of transmit.
|
||||
*/
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
/* Without defining GMAC_USES_TX_CALLBACK, l_tx_tail won't be updated */
|
||||
uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev)
|
||||
{
|
||||
uint16_t us_head = p_gmac_dev->l_tx_head;
|
||||
uint16_t us_tail = p_gmac_dev->l_tx_tail;
|
||||
return CIRC_CNT(us_head, us_tail, p_gmac_dev->ul_tx_list_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Register/Clear RX callback. Callback will be invoked after the next received
|
||||
* frame.
|
||||
*
|
||||
* When gmac_dev_read() returns GMAC_RX_NULL, the application task calls
|
||||
* gmac_dev_set_rx_callback() to register func_rx_cb() callback and enters suspend state.
|
||||
* The callback is in charge to resume the task once a new frame has been
|
||||
* received. The next time gmac_dev_read() is called, it will be successful.
|
||||
*
|
||||
* This function is usually invoked from the RX callback itself with NULL
|
||||
* callback, to unregister. Once the callback has resumed the application task,
|
||||
* there is no need to invoke the callback again.
|
||||
*
|
||||
* \param p_gmac_dev Pointer to the GMAC device instance.
|
||||
* \param func_tx_cb Receive callback function.
|
||||
*/
|
||||
void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,
|
||||
gmac_dev_rx_cb_t func_rx_cb)
|
||||
{
|
||||
Gmac *p_hw = p_gmac_dev->p_hw;
|
||||
|
||||
if (func_rx_cb == NULL) {
|
||||
gmac_disable_interrupt(p_hw, GMAC_IDR_RCOMP);
|
||||
p_gmac_dev->func_rx_cb = NULL;
|
||||
} else {
|
||||
p_gmac_dev->func_rx_cb = func_rx_cb;
|
||||
gmac_enable_interrupt(p_hw, GMAC_IER_RCOMP);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Register/Clear TX wakeup callback.
|
||||
*
|
||||
* When gmac_dev_write() returns GMAC_TX_BUSY (all transmit descriptor busy), the application
|
||||
* task calls gmac_dev_set_tx_wakeup_callback() to register func_wakeup() callback and
|
||||
* enters suspend state. The callback is in charge to resume the task once
|
||||
* several transmit descriptors have been released. The next time gmac_dev_write() will be called,
|
||||
* it shall be successful.
|
||||
*
|
||||
* This function is usually invoked with NULL callback from the TX wakeup
|
||||
* callback itself, to unregister. Once the callback has resumed the
|
||||
* application task, there is no need to invoke the callback again.
|
||||
*
|
||||
* \param p_gmac_dev Pointer to GMAC device instance.
|
||||
* \param func_wakeup Pointer to wakeup callback function.
|
||||
* \param uc_threshold Number of free transmit descriptor before wakeup callback invoked.
|
||||
*
|
||||
* \return GMAC_OK, GMAC_PARAM on parameter error.
|
||||
*/
|
||||
#if( GMAC_USES_WAKEUP_CALLBACK )
|
||||
uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,
|
||||
gmac_dev_wakeup_cb_t func_wakeup_cb, uint8_t uc_threshold)
|
||||
{
|
||||
if (func_wakeup_cb == NULL) {
|
||||
p_gmac_dev->func_wakeup_cb = NULL;
|
||||
} else {
|
||||
if (uc_threshold <= p_gmac_dev->ul_tx_list_size) {
|
||||
p_gmac_dev->func_wakeup_cb = func_wakeup_cb;
|
||||
p_gmac_dev->uc_wakeup_threshold = uc_threshold;
|
||||
} else {
|
||||
return GMAC_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
return GMAC_OK;
|
||||
}
|
||||
#endif /* GMAC_USES_WAKEUP_CALLBACK */
|
||||
|
||||
/**
|
||||
* \brief Reset TX & RX queue & statistics.
|
||||
*
|
||||
* \param p_gmac_dev Pointer to GMAC device instance.
|
||||
*/
|
||||
void gmac_dev_reset(gmac_device_t* p_gmac_dev)
|
||||
{
|
||||
Gmac *p_hw = p_gmac_dev->p_hw;
|
||||
|
||||
gmac_reset_rx_mem(p_gmac_dev);
|
||||
gmac_reset_tx_mem(p_gmac_dev);
|
||||
gmac_network_control(p_hw, GMAC_NCR_TXEN | GMAC_NCR_RXEN
|
||||
| GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
|
||||
}
|
||||
|
||||
void gmac_dev_halt(Gmac* p_gmac);
|
||||
|
||||
void gmac_dev_halt(Gmac* p_gmac)
|
||||
{
|
||||
gmac_network_control(p_gmac, GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
|
||||
gmac_disable_interrupt(p_gmac, ~0u);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief GMAC Interrupt handler.
|
||||
*
|
||||
* \param p_gmac_dev Pointer to GMAC device instance.
|
||||
*/
|
||||
|
||||
#if( GMAC_STATS != 0 )
|
||||
extern int logPrintf( const char *pcFormat, ... );
|
||||
|
||||
void gmac_show_irq_counts ()
|
||||
{
|
||||
int index;
|
||||
for (index = 0; index < ARRAY_SIZE(intPairs); index++) {
|
||||
if (gmacStats.intStatus[intPairs[index].index]) {
|
||||
logPrintf("%s : %6u\n", intPairs[index].name, gmacStats.intStatus[intPairs[index].index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void gmac_handler(gmac_device_t* p_gmac_dev)
|
||||
{
|
||||
Gmac *p_hw = p_gmac_dev->p_hw;
|
||||
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
gmac_tx_descriptor_t *p_tx_td;
|
||||
gmac_dev_tx_cb_t *p_tx_cb = NULL;
|
||||
uint32_t ul_tx_status_flag;
|
||||
#endif
|
||||
#if( GMAC_STATS != 0 )
|
||||
int index;
|
||||
#endif
|
||||
|
||||
/* volatile */ uint32_t ul_isr;
|
||||
/* volatile */ uint32_t ul_rsr;
|
||||
/* volatile */ uint32_t ul_tsr;
|
||||
|
||||
ul_isr = gmac_get_interrupt_status(p_hw);
|
||||
ul_rsr = gmac_get_rx_status(p_hw);
|
||||
ul_tsr = gmac_get_tx_status(p_hw);
|
||||
|
||||
/* Why clear bits that are ignored anyway ? */
|
||||
/* ul_isr &= ~(gmac_get_interrupt_mask(p_hw) | 0xF8030300); */
|
||||
#if( GMAC_STATS != 0 )
|
||||
{
|
||||
for (index = 0; index < ARRAY_SIZE(intPairs); index++) {
|
||||
if (ul_isr & intPairs[index].mask)
|
||||
gmacStats.intStatus[intPairs[index].index]++;
|
||||
}
|
||||
}
|
||||
#endif /* GMAC_STATS != 0 */
|
||||
|
||||
/* RX packet */
|
||||
if ((ul_isr & GMAC_ISR_RCOMP) || (ul_rsr & (GMAC_RSR_REC|GMAC_RSR_RXOVR|GMAC_RSR_BNA))) {
|
||||
/* Clear status */
|
||||
gmac_clear_rx_status(p_hw, ul_rsr);
|
||||
|
||||
if (ul_isr & GMAC_ISR_RCOMP)
|
||||
ul_rsr |= GMAC_RSR_REC;
|
||||
/* Invoke callbacks which can be useful to wake op a task */
|
||||
if (p_gmac_dev->func_rx_cb) {
|
||||
p_gmac_dev->func_rx_cb(ul_rsr);
|
||||
}
|
||||
}
|
||||
|
||||
/* TX packet */
|
||||
if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & (GMAC_TSR_TXCOMP|GMAC_TSR_COL|GMAC_TSR_RLE|GMAC_TSR_UND))) {
|
||||
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
ul_tx_status_flag = GMAC_TSR_TXCOMP;
|
||||
#endif
|
||||
/* A frame transmitted */
|
||||
|
||||
/* Check RLE */
|
||||
if (ul_tsr & GMAC_TSR_RLE) {
|
||||
/* Status RLE & Number of discarded buffers */
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
ul_tx_status_flag = GMAC_TSR_RLE | CIRC_CNT(p_gmac_dev->l_tx_head,
|
||||
p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);
|
||||
p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];
|
||||
#endif
|
||||
gmac_reset_tx_mem(p_gmac_dev);
|
||||
gmac_enable_transmit(p_hw, 1);
|
||||
}
|
||||
/* Clear status */
|
||||
gmac_clear_tx_status(p_hw, ul_tsr);
|
||||
|
||||
#if( GMAC_USES_TX_CALLBACK != 0 )
|
||||
if (!CIRC_EMPTY(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail)) {
|
||||
/* Check the buffers */
|
||||
do {
|
||||
p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_tail];
|
||||
p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];
|
||||
/* Any error? Exit if buffer has not been sent yet */
|
||||
if ((p_tx_td->status.val & GMAC_TXD_USED) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Notify upper layer that a packet has been sent */
|
||||
if (*p_tx_cb) {
|
||||
(*p_tx_cb) (ul_tx_status_flag, (void*)p_tx_td->addr);
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
{
|
||||
p_tx_td->addr = 0ul;
|
||||
}
|
||||
#endif /* ipconfigZERO_COPY_TX_DRIVER */
|
||||
}
|
||||
|
||||
circ_inc32(&p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);
|
||||
} while (CIRC_CNT(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
|
||||
p_gmac_dev->ul_tx_list_size));
|
||||
}
|
||||
|
||||
if (ul_tsr & GMAC_TSR_RLE) {
|
||||
/* Notify upper layer RLE */
|
||||
if (*p_tx_cb) {
|
||||
(*p_tx_cb) (ul_tx_status_flag, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* GMAC_USES_TX_CALLBACK */
|
||||
|
||||
#if( GMAC_USES_WAKEUP_CALLBACK )
|
||||
/* If a wakeup has been scheduled, notify upper layer that it can
|
||||
send other packets, and the sending will be successful. */
|
||||
if ((CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
|
||||
p_gmac_dev->ul_tx_list_size) >= p_gmac_dev->uc_wakeup_threshold)
|
||||
&& p_gmac_dev->func_wakeup_cb) {
|
||||
p_gmac_dev->func_wakeup_cb();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 150406 (C) 2015 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB: ***
|
||||
*** ***
|
||||
*** This product is functional and is already being used in commercial ***
|
||||
*** products. Be aware however that we are still refining its design, ***
|
||||
*** the source code does not yet fully conform to the strict coding and ***
|
||||
*** style standards mandated by Real Time Engineers ltd., and the ***
|
||||
*** documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* - Open source licensing -
|
||||
* While FreeRTOS+TCP is in the lab it is provided only under version two of the
|
||||
* GNU General Public License (GPL) (which is different to the standard FreeRTOS
|
||||
* license). FreeRTOS+TCP is free to download, use and distribute under the
|
||||
* terms of that license provided the copyright notice and this text are not
|
||||
* altered or removed from the source files. 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. Active early adopters may, and
|
||||
* solely at the discretion of Real Time Engineers Ltd., be offered versions
|
||||
* under a license other then the GPL.
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* Hardware abstraction. */
|
||||
#include "FreeRTOS_IO.h"
|
||||
|
||||
/* FreeRTOS+TCP 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 ( pdMS_TO_TICKS( 2UL ) )
|
||||
#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 QueueHandle_t xNetworkEventQueue;
|
||||
|
||||
/* The semaphore used to wake the deferred interrupt handler task when an Rx
|
||||
interrupt is received. */
|
||||
static SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceInitialise( void )
|
||||
{
|
||||
EMAC_CFG_Type Emac_Config;
|
||||
PINSEL_CFG_Type xPinConfig;
|
||||
BaseType_t 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, "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;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
|
||||
{
|
||||
BaseType_t 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. */
|
||||
vReleaseNetworkBufferAndDescriptor( 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 );
|
||||
}
|
||||
}
|
||||
|
||||
/* ulInterruptCause is used for convenience here. A context switch is
|
||||
wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a
|
||||
compiler warning. */
|
||||
portEND_SWITCHING_ISR( ulInterruptCause );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvEMACHandlerTask( void *pvParameters )
|
||||
{
|
||||
size_t xDataLength;
|
||||
const uint16_t usCRCLength = 4;
|
||||
NetworkBufferDescriptor_t *pxNetworkBuffer;
|
||||
IPStackEvent_t xRxEvent = { eNetworkRxEvent, 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 = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 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( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
|
||||
iptraceETHERNET_RX_EVENT_LOST();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iptraceETHERNET_RX_EVENT_LOST();
|
||||
}
|
||||
|
||||
iptraceNETWORK_INTERFACE_RECEIVE();
|
||||
}
|
||||
|
||||
/* Release the frame. */
|
||||
EMAC_UpdateRxConsumeIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,3 @@
|
|||
NetworkInterface.c:
|
||||
Requires NXP's LPCOpen library and was developed on an LPC1830 and LPC1835 Xplorer
|
||||
boards from NGX.
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Network drivers are provided as examples only, and do not form part of the
|
||||
FreeRTOS+TCP stack itself. They:
|
||||
|
||||
+ May be based on driver code provided by the chip vendors,
|
||||
+ May not have been tested in all possible configurations,
|
||||
+ Will not necessarily be optimised.
|
||||
+ May have a dependency on a particular PHY part number.
|
||||
+ May not necessarily comply with any particular coding standard.
|
||||
+ May have dependencies on chip company libraries.
|
||||
+ May include other hardware board dependencies.
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 150406 (C) 2015 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB: ***
|
||||
*** ***
|
||||
*** This product is functional and is already being used in commercial ***
|
||||
*** products. Be aware however that we are still refining its design, ***
|
||||
*** the source code does not yet fully conform to the strict coding and ***
|
||||
*** style standards mandated by Real Time Engineers ltd., and the ***
|
||||
*** documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* - Open source licensing -
|
||||
* While FreeRTOS+TCP is in the lab it is provided only under version two of the
|
||||
* GNU General Public License (GPL) (which is different to the standard FreeRTOS
|
||||
* license). FreeRTOS+TCP is free to download, use and distribute under the
|
||||
* terms of that license provided the copyright notice and this text are not
|
||||
* altered or removed from the source files. 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. Active early adopters may, and
|
||||
* solely at the discretion of Real Time Engineers Ltd., be offered versions
|
||||
* under a license other then the GPL.
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP 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 ( ( TickType_t ) 2UL / portTICK_PERIOD_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 QueueHandle_t xNetworkEventQueue;
|
||||
|
||||
/* The semaphore used to wake the deferred interrupt handler task when an Rx
|
||||
interrupt is received. */
|
||||
SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceInitialise( void )
|
||||
{
|
||||
BaseType_t 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, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
|
||||
xReturn = pdPASS;
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
|
||||
{
|
||||
extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );
|
||||
|
||||
vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );
|
||||
|
||||
/* Finished with the network buffer. */
|
||||
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
|
||||
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,173 @@
|
|||
#define xBUFFER_CACHE_SIZE 10
|
||||
#define xMAX_FAULT_INJECTION_RATE 15
|
||||
#define xMIN_FAULT_INJECTION_RATE 3
|
||||
#define xNUM_FAULT_TYPES 1
|
||||
|
||||
static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };
|
||||
|
||||
#define xFAULT_LOG_SIZE 2048
|
||||
uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];
|
||||
uint32_t ulFaultLogIndex = 0;
|
||||
|
||||
static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )
|
||||
{
|
||||
BaseType_t x, xReturn = pdFALSE;
|
||||
|
||||
for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )
|
||||
{
|
||||
if( xNetworkBufferCache[ x ] == NULL )
|
||||
{
|
||||
xNetworkBufferCache[ x ] = pxNetworkBufferIn;
|
||||
xReturn = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static NetworkBufferDescriptor_t *prvGetCachedPacket( void )
|
||||
{
|
||||
BaseType_t x;
|
||||
NetworkBufferDescriptor_t *pxReturn = NULL;
|
||||
|
||||
for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )
|
||||
{
|
||||
if( xNetworkBufferCache[ x ] != NULL )
|
||||
{
|
||||
pxReturn = xNetworkBufferCache[ x ];
|
||||
xNetworkBufferCache[ x ] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )
|
||||
{
|
||||
NetworkBufferDescriptor_t *pxReturn;
|
||||
|
||||
/* Obtain a new descriptor. */
|
||||
pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );
|
||||
|
||||
if( pxReturn != NULL )
|
||||
{
|
||||
/* Copy in the packet data. */
|
||||
pxReturn->xDataLength = pxOriginalPacket->xDataLength;
|
||||
memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );
|
||||
}
|
||||
|
||||
return pxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )
|
||||
{
|
||||
static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;
|
||||
NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;
|
||||
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
|
||||
uint32_t ulFault;
|
||||
|
||||
return pxNetworkBufferIn;
|
||||
|
||||
ulCallCount++;
|
||||
|
||||
if( ulCallCount > ulNextFaultCallCount )
|
||||
{
|
||||
ulNextFaultCallCount = ipconfigRAND32() % xMAX_FAULT_INJECTION_RATE;
|
||||
if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )
|
||||
{
|
||||
ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;
|
||||
}
|
||||
|
||||
ulCallCount = 0;
|
||||
|
||||
ulFault = ipconfigRAND32() % xNUM_FAULT_TYPES;
|
||||
|
||||
if( ulFaultLogIndex < xFAULT_LOG_SIZE )
|
||||
{
|
||||
ulInjectedFault[ ulFaultLogIndex ] = ulFault;
|
||||
ulFaultLogIndex++;
|
||||
}
|
||||
|
||||
switch( ulFault )
|
||||
{
|
||||
case 0:
|
||||
/* Just drop the packet. */
|
||||
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
|
||||
pxReturn = NULL;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* Store the packet in the cache for later. */
|
||||
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
|
||||
{
|
||||
/* The packet may get sent later, it is not being sent
|
||||
now. */
|
||||
pxReturn = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* Send a cached packet. */
|
||||
pxReturn = prvGetCachedPacket();
|
||||
if( pxReturn != NULL )
|
||||
{
|
||||
/* A cached packet was obtained so drop the original
|
||||
packet. */
|
||||
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Could not obtain a packet from the cache so just return
|
||||
the packet that was passed in. */
|
||||
pxReturn = pxNetworkBufferIn;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
|
||||
/* Send a duplicate of the packet right away. */
|
||||
pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );
|
||||
|
||||
/* Send the original packet to the stack. */
|
||||
xRxEvent.pvData = ( void * ) pxNetworkBufferIn;
|
||||
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
|
||||
/* Send both a cached packet and the current packet. */
|
||||
xRxEvent.pvData = ( void * ) prvGetCachedPacket();
|
||||
if( xRxEvent.pvData != NULL )
|
||||
{
|
||||
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
/* Store the packet in the cache for later. */
|
||||
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
|
||||
{
|
||||
/* The packet may get sent later, it is not being sent
|
||||
now. */
|
||||
pxReturn = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -0,0 +1,631 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* WinPCap includes. */
|
||||
#define HAVE_REMOTE
|
||||
#include "pcap.h"
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
/* Thread-safe circular buffers are being used to pass data to and from the PCAP
|
||||
access functions. */
|
||||
#include "Win32-Extensions.h"
|
||||
#include "FreeRTOS_Stream_Buffer.h"
|
||||
|
||||
/* Sizes of the thread safe circular buffers used to pass data to and from the
|
||||
WinPCAP Windows threads. */
|
||||
#define xSEND_BUFFER_SIZE 32768
|
||||
#define xRECV_BUFFER_SIZE 32768
|
||||
|
||||
/* 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. */
|
||||
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
|
||||
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
|
||||
#else
|
||||
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
|
||||
#endif
|
||||
|
||||
/* Used to insert test code only. */
|
||||
#define niDISRUPT_PACKETS 0
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Windows threads that are outside of the control of the FreeRTOS simulator are
|
||||
* used to interface with the WinPCAP libraries.
|
||||
*/
|
||||
DWORD WINAPI prvWinPcapRecvThread( void *pvParam );
|
||||
DWORD WINAPI prvWinPcapSendThread( void *pvParam );
|
||||
|
||||
/*
|
||||
* 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 );
|
||||
static void prvOpenInterface( const char *pucName );
|
||||
|
||||
/*
|
||||
* 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 );
|
||||
|
||||
/*
|
||||
* Create the buffers that are used to pass data between the FreeRTOS simulator
|
||||
* and the Win32 threads that manage WinPCAP.
|
||||
*/
|
||||
static void prvCreateThreadSafeBuffers( void );
|
||||
|
||||
/*
|
||||
* Utility function used to format print messages only.
|
||||
*/
|
||||
static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Required by the WinPCap library. */
|
||||
static char cErrorBuffer[ PCAP_ERRBUF_SIZE ];
|
||||
|
||||
/* An event used to wake up the Win32 thread that sends data through the WinPCAP
|
||||
library. */
|
||||
static void *pvSendEvent = NULL;
|
||||
|
||||
/* _HT_ made the PCAP interface number configurable through the program's
|
||||
parameters in order to test in different machines. */
|
||||
static BaseType_t xConfigNextworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE;
|
||||
|
||||
/* Handles to the Windows threads that handle the PCAP IO. */
|
||||
static HANDLE vWinPcapRecvThreadHandle = NULL;
|
||||
static HANDLE vWinPcapSendThreadHandle = NULL;;
|
||||
|
||||
/* The interface being used by WinPCap. */
|
||||
static pcap_t *pxOpenedInterfaceHandle = NULL;
|
||||
|
||||
/* Circular buffers used by the PCAP Win32 threads. */
|
||||
static StreamBuffer_t *xSendBuffer = NULL;
|
||||
static StreamBuffer_t *xRecvBuffer = NULL;
|
||||
|
||||
/* The MAC address initially set to the constants defined in FreeRTOSConfig.h. */
|
||||
extern uint8_t ucMACAddress[ 6 ];
|
||||
|
||||
/* Logs the number of WinPCAP send failures, for viewing in the debugger only. */
|
||||
static volatile uint32_t ulWinPCAPSendFailures = 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceInitialise( void )
|
||||
{
|
||||
BaseType_t xReturn = pdFALSE;
|
||||
pcap_if_t *pxAllNetworkInterfaces;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCreateThreadSafeBuffers( void )
|
||||
{
|
||||
/* The buffer used to pass data to be transmitted from a FreeRTOS task to
|
||||
the Win32 thread that sends via the WinPCAP library. */
|
||||
if( xSendBuffer == NULL)
|
||||
{
|
||||
xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 );
|
||||
configASSERT( xSendBuffer );
|
||||
memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) );
|
||||
xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1;
|
||||
}
|
||||
|
||||
/* The buffer used to pass received data from the Win32 thread that receives
|
||||
via the WinPCAP library to the FreeRTOS task. */
|
||||
if( xRecvBuffer == NULL)
|
||||
{
|
||||
xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 );
|
||||
configASSERT( xRecvBuffer );
|
||||
memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) );
|
||||
xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )
|
||||
{
|
||||
size_t xSpace;
|
||||
|
||||
iptraceNETWORK_INTERFACE_TRANSMIT();
|
||||
configASSERT( xIsCallingFromIPTask() == pdTRUE );
|
||||
|
||||
/* Both the length of the data being sent and the actual data being sent
|
||||
are placed in the thread safe buffer used to pass data between the FreeRTOS
|
||||
tasks and the Win32 thread that sends data via the WinPCAP library. Drop
|
||||
the packet if there is insufficient space in the buffer to hold both. */
|
||||
xSpace = uxStreamBufferGetSpace( xSendBuffer );
|
||||
|
||||
if( ( pxNetworkBuffer->xDataLength <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
|
||||
( xSpace >= ( pxNetworkBuffer->xDataLength + sizeof( pxNetworkBuffer->xDataLength ) ) ) )
|
||||
{
|
||||
/* First write in the length of the data, then write in the data
|
||||
itself. */
|
||||
uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ), sizeof( pxNetworkBuffer->xDataLength ) );
|
||||
uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n", pxNetworkBuffer->xDataLength ) );
|
||||
}
|
||||
|
||||
/* Kick the Tx task in either case in case it doesn't know the buffer is
|
||||
full. */
|
||||
SetEvent( pvSendEvent );
|
||||
|
||||
/* The buffer has been sent so can be released. */
|
||||
if( bReleaseAfterSend != pdFALSE )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
|
||||
}
|
||||
|
||||
return pdPASS;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
|
||||
{
|
||||
pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;
|
||||
int32_t lInterfaceNumber = 1;
|
||||
char cBuffer[ 512 ];
|
||||
|
||||
if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
|
||||
{
|
||||
printf( "Could not obtain a list of network interfaces\n%s\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 )
|
||||
{
|
||||
/* The descriptions of the devices can be full of spaces, clean them
|
||||
a little. printf() can only be used here because the network is not
|
||||
up yet - so no other network tasks will be running. */
|
||||
printf( "%d. %s\n", lInterfaceNumber, prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) );
|
||||
printf( " (%s)\n", prvRemoveSpaces(cBuffer, sizeof( cBuffer ), xInterface->description ? xInterface->description : "No description" ) );
|
||||
printf( "\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( " \nNo network interfaces were found.\n" );
|
||||
pxAllNetworkInterfaces = NULL;
|
||||
}
|
||||
|
||||
printf( "The interface that will be opened is set by\n" );
|
||||
printf( "\"configNETWORK_INTERFACE_TO_USE\" which should be defined in FreeRTOSConfig.h\n" );
|
||||
printf( "Attempting to open interface number %d.\n", xConfigNextworkInterfaceToUse );
|
||||
|
||||
if( ( xConfigNextworkInterfaceToUse < 1L ) || ( xConfigNextworkInterfaceToUse > lInterfaceNumber ) )
|
||||
{
|
||||
printf( "configNETWORK_INTERFACE_TO_USE is not in the valid range.\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 prvOpenInterface( const char *pucName )
|
||||
{
|
||||
static char pucInterfaceName[ 256 ];
|
||||
|
||||
if( pucName != NULL )
|
||||
{
|
||||
strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) );
|
||||
}
|
||||
|
||||
pxOpenedInterfaceHandle = pcap_open( pucInterfaceName, /* The name of the selected interface. */
|
||||
ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */
|
||||
PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscuous mode as the MAC and
|
||||
IP address is going to be "simulated", and
|
||||
not be the real MAC and IP address. This allows
|
||||
traffic to the simulated IP address to be routed
|
||||
to uIP, and traffic to the real IP address to be
|
||||
routed to the Windows TCP/IP stack. */
|
||||
100,
|
||||
NULL, /* No authentication is required as this is
|
||||
not a remote capture session. */
|
||||
cErrorBuffer
|
||||
);
|
||||
|
||||
if ( pxOpenedInterfaceHandle == NULL )
|
||||
{
|
||||
printf( "\n%s is not supported by WinPcap and cannot be opened\n", pucInterfaceName );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure the capture filter to allow blocking reads, and to filter
|
||||
out packets that are not of interest to this demo. */
|
||||
prvConfigureCaptureBehaviour();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
|
||||
{
|
||||
pcap_if_t *xInterface;
|
||||
int32_t x;
|
||||
|
||||
/* Walk the list of devices until the selected device is located. */
|
||||
xInterface = pxAllNetworkInterfaces;
|
||||
for( x = 0L; x < ( xConfigNextworkInterfaceToUse - 1L ); x++ )
|
||||
{
|
||||
xInterface = xInterface->next;
|
||||
}
|
||||
|
||||
/* Open the selected interface. */
|
||||
prvOpenInterface( xInterface->name );
|
||||
|
||||
/* The device list is no longer required. */
|
||||
pcap_freealldevs( pxAllNetworkInterfaces );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvConfigureCaptureBehaviour( void )
|
||||
{
|
||||
struct bpf_program xFilterCode;
|
||||
uint32_t ulNetMask;
|
||||
|
||||
/* 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. */
|
||||
sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x",
|
||||
ucMACAddress[0], ucMACAddress[1], ucMACAddress[2], ucMACAddress[3], ucMACAddress[4], ucMACAddress[5] );
|
||||
|
||||
ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
|
||||
|
||||
if( pcap_compile( pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )
|
||||
{
|
||||
printf( "\nThe packet filter string is invalid\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )
|
||||
{
|
||||
printf( "\nAn error occurred setting the packet filter.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the buffers used to pass packets between the FreeRTOS simulator
|
||||
and the Win32 threads that are handling WinPCAP. */
|
||||
prvCreateThreadSafeBuffers();
|
||||
|
||||
if( pvSendEvent == NULL )
|
||||
{
|
||||
/* Create event used to signal the Win32 WinPCAP Tx thread. */
|
||||
pvSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL );
|
||||
|
||||
/* Create the Win32 thread that handles WinPCAP Rx. */
|
||||
vWinPcapRecvThreadHandle = CreateThread(
|
||||
NULL, /* Pointer to thread security attributes. */
|
||||
0, /* Initial thread stack size, in bytes. */
|
||||
prvWinPcapRecvThread, /* Pointer to thread function. */
|
||||
NULL, /* Argument for new thread. */
|
||||
0, /* Creation flags. */
|
||||
NULL );
|
||||
|
||||
/* Use the cores that are not used by the FreeRTOS tasks. */
|
||||
SetThreadAffinityMask( vWinPcapRecvThreadHandle, ~0x01u );
|
||||
|
||||
/* Create the Win32 thread that handlers WinPCAP Tx. */
|
||||
vWinPcapSendThreadHandle = CreateThread(
|
||||
NULL, /* Pointer to thread security attributes. */
|
||||
0, /* initial thread stack size, in bytes. */
|
||||
prvWinPcapSendThread, /* Pointer to thread function. */
|
||||
NULL, /* Argument for new thread. */
|
||||
0, /* Creation flags. */
|
||||
NULL );
|
||||
|
||||
/* Use the cores that are not used by the FreeRTOS tasks. */
|
||||
SetThreadAffinityMask( vWinPcapSendThreadHandle, ~0x01u );
|
||||
|
||||
/* Create a task that simulates an interrupt in a real system. This will
|
||||
block waiting for packets, then send a message to the IP task when data
|
||||
is available. */
|
||||
xTaskCreate( prvInterruptSimulatorTask, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* WinPCAP function. */
|
||||
void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data )
|
||||
{
|
||||
(void)user;
|
||||
|
||||
/* THIS IS CALLED FROM A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS
|
||||
OR TO PRINT OUT MESSAGES HERE. */
|
||||
|
||||
/* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */
|
||||
if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
|
||||
( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )
|
||||
{
|
||||
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) );
|
||||
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
DWORD WINAPI prvWinPcapRecvThread ( void *pvParam )
|
||||
{
|
||||
( void ) pvParam;
|
||||
|
||||
/* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT
|
||||
OUT MESSAGES HERE. */
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
pcap_dispatch( pxOpenedInterfaceHandle, 1, pcap_callback, ( u_char * ) "mydata" );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
DWORD WINAPI prvWinPcapSendThread( void *pvParam )
|
||||
{
|
||||
size_t xLength;
|
||||
uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
|
||||
static char cErrorMessage[ 1024 ];
|
||||
const DWORD xMaxMSToWait = 1000;
|
||||
|
||||
/* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT
|
||||
OUT MESSAGES HERE. */
|
||||
|
||||
/* Remove compiler warnings about unused parameters. */
|
||||
( void ) pvParam;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Wait until notified of something to send. */
|
||||
WaitForSingleObject( pvSendEvent, xMaxMSToWait );
|
||||
|
||||
/* Is there more than the length value stored in the circular buffer
|
||||
used to pass data from the FreeRTOS simulator into this Win32 thread? */
|
||||
while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) )
|
||||
{
|
||||
uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );
|
||||
uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );
|
||||
if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 )
|
||||
{
|
||||
ulWinPCAPSendFailures++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInterruptSimulatorTask( void *pvParameters )
|
||||
{
|
||||
struct pcap_pkthdr xHeader;
|
||||
static struct pcap_pkthdr *pxHeader;
|
||||
const uint8_t *pucPacketData;
|
||||
uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
|
||||
NetworkBufferDescriptor_t *pxNetworkBuffer;
|
||||
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
|
||||
eFrameProcessingResult_t eResult;
|
||||
|
||||
/* Remove compiler warnings about unused parameters. */
|
||||
( void ) pvParameters;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Does the circular buffer used to pass data from the Win32 thread that
|
||||
handles WinPCAP Rx into the FreeRTOS simulator contain another packet? */
|
||||
if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) )
|
||||
{
|
||||
/* Get the next packet. */
|
||||
uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)&xHeader, sizeof( xHeader ), pdFALSE );
|
||||
uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE );
|
||||
pucPacketData = ucRecvBuffer;
|
||||
pxHeader = &xHeader;
|
||||
|
||||
iptraceNETWORK_INTERFACE_RECEIVE();
|
||||
|
||||
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, but note that
|
||||
some buffer implementations cannot be called from a real
|
||||
interrupt. */
|
||||
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );
|
||||
|
||||
if( pxNetworkBuffer != NULL )
|
||||
{
|
||||
memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );
|
||||
pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;
|
||||
|
||||
#if( niDISRUPT_PACKETS == 1 )
|
||||
{
|
||||
pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData );
|
||||
}
|
||||
#endif /* niDISRUPT_PACKETS */
|
||||
|
||||
if( pxNetworkBuffer != NULL )
|
||||
{
|
||||
xRxEvent.pvData = ( void * ) pxNetworkBuffer;
|
||||
|
||||
/* Data was received and stored. Send a message to
|
||||
the IP task to let it know. */
|
||||
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
|
||||
{
|
||||
/* 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, but
|
||||
note no all buffer implementations will allow
|
||||
this function to be executed from a real
|
||||
interrupt. */
|
||||
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
|
||||
iptraceETHERNET_RX_EVENT_LOST();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The packet was already released or stored inside
|
||||
vRxFaultInjection(). Don't release it here. */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iptraceETHERNET_RX_EVENT_LOST();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Log that a packet was dropped because it would have
|
||||
overflowed the buffer, but there may be more buffers to
|
||||
process. */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no real way of simulating an interrupt. Make sure
|
||||
other tasks can run. */
|
||||
vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage )
|
||||
{
|
||||
char *pcTarget = pcBuffer;
|
||||
|
||||
/* Utility function used to formap messages being printed only. */
|
||||
while( ( *pcMessage != 0 ) && ( pcTarget < ( pcBuffer + aBuflen - 1 ) ) )
|
||||
{
|
||||
*( pcTarget++ ) = *pcMessage;
|
||||
|
||||
if( isspace( *pcMessage ) != pdFALSE )
|
||||
{
|
||||
while( isspace( *pcMessage ) != pdFALSE )
|
||||
{
|
||||
pcMessage++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pcMessage++;
|
||||
}
|
||||
}
|
||||
|
||||
*pcTarget = '\0';
|
||||
|
||||
return pcBuffer;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,430 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 200417 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "NetworkInterface.h"
|
||||
|
||||
/* Xilinx library files. */
|
||||
#include <xemacps.h>
|
||||
#include "Zynq/x_topology.h"
|
||||
#include "Zynq/x_emacpsif.h"
|
||||
#include "Zynq/x_emacpsif_hw.h"
|
||||
|
||||
/* Provided memory configured as uncached. */
|
||||
#include "uncached_memory.h"
|
||||
|
||||
#ifndef BMSR_LINK_STATUS
|
||||
#define BMSR_LINK_STATUS 0x0004UL
|
||||
#endif
|
||||
|
||||
#ifndef PHY_LS_HIGH_CHECK_TIME_MS
|
||||
/* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
|
||||
receiving packets. */
|
||||
#define PHY_LS_HIGH_CHECK_TIME_MS 15000
|
||||
#endif
|
||||
|
||||
#ifndef PHY_LS_LOW_CHECK_TIME_MS
|
||||
/* Check if the LinkSStatus in the PHY is still low every second. */
|
||||
#define PHY_LS_LOW_CHECK_TIME_MS 1000
|
||||
#endif
|
||||
|
||||
/* The size of each buffer when BufferAllocation_1 is used:
|
||||
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
|
||||
#define niBUFFER_1_PACKET_SIZE 1536
|
||||
|
||||
/* Naming and numbering of PHY registers. */
|
||||
#define PHY_REG_01_BMSR 0x01 /* Basic mode status register */
|
||||
|
||||
#ifndef iptraceEMAC_TASK_STARTING
|
||||
#define iptraceEMAC_TASK_STARTING() do { } while( 0 )
|
||||
#endif
|
||||
|
||||
/* Default the size of the stack used by the EMAC deferred handler task to twice
|
||||
the size of the stack used by the idle task - but allow this to be overridden in
|
||||
FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
|
||||
#ifndef configEMAC_TASK_STACK_SIZE
|
||||
#define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Look for the link to be up every few milliseconds until either xMaxTime time
|
||||
* has passed or a link is found.
|
||||
*/
|
||||
static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );
|
||||
|
||||
/*
|
||||
* A deferred interrupt handler for all MAC/DMA interrupt sources.
|
||||
*/
|
||||
static void prvEMACHandlerTask( void *pvParameters );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* EMAC data/descriptions. */
|
||||
static xemacpsif_s xEMACpsif;
|
||||
struct xtopology_t xXTopology =
|
||||
{
|
||||
.emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,
|
||||
.emac_type = xemac_type_emacps,
|
||||
.intc_baseaddr = 0x0,
|
||||
.intc_emac_intr = 0x0,
|
||||
.scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,
|
||||
.scugic_emac_intr = 0x36,
|
||||
};
|
||||
|
||||
XEmacPs_Config mac_config =
|
||||
{
|
||||
.DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID, /**< Unique ID of device */
|
||||
.BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */
|
||||
};
|
||||
|
||||
extern int phy_detected;
|
||||
|
||||
/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
|
||||
static uint32_t ulPHYLinkStatus = 0;
|
||||
|
||||
#if( ipconfigUSE_LLMNR == 1 )
|
||||
static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
|
||||
#endif
|
||||
|
||||
/* ucMACAddress as it appears in main.c */
|
||||
extern const uint8_t ucMACAddress[ 6 ];
|
||||
|
||||
/* Holds the handle of the task used as a deferred interrupt processor. The
|
||||
handle is used so direct notifications can be sent to the task for all EMAC/DMA
|
||||
related interrupts. */
|
||||
TaskHandle_t xEMACTaskHandle = NULL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceInitialise( void )
|
||||
{
|
||||
uint32_t ulLinkSpeed, ulDMAReg;
|
||||
BaseType_t xStatus, xLinkStatus;
|
||||
XEmacPs *pxEMAC_PS;
|
||||
const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );
|
||||
|
||||
/* Guard against the init function being called more than once. */
|
||||
if( xEMACTaskHandle == NULL )
|
||||
{
|
||||
pxEMAC_PS = &( xEMACpsif.emacps );
|
||||
memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );
|
||||
|
||||
xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);
|
||||
if( xStatus != XST_SUCCESS )
|
||||
{
|
||||
FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );
|
||||
}
|
||||
|
||||
/* Initialize the mac and set the MAC address. */
|
||||
XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );
|
||||
|
||||
#if( ipconfigUSE_LLMNR == 1 )
|
||||
{
|
||||
/* Also add LLMNR multicast MAC address. */
|
||||
XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );
|
||||
}
|
||||
#endif /* ipconfigUSE_LLMNR == 1 */
|
||||
|
||||
XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );
|
||||
ulLinkSpeed = Phy_Setup( pxEMAC_PS );
|
||||
XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);
|
||||
|
||||
/* Setting the operating speed of the MAC needs a delay. */
|
||||
vTaskDelay( pdMS_TO_TICKS( 25UL ) );
|
||||
|
||||
ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);
|
||||
|
||||
/* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive
|
||||
packets from the receiver packet buffer memory when no AHB resource is available. */
|
||||
XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
|
||||
ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);
|
||||
|
||||
setup_isr( &xEMACpsif );
|
||||
init_dma( &xEMACpsif );
|
||||
start_emacps( &xEMACpsif );
|
||||
|
||||
prvGMACWaitLS( xWaitLinkDelay );
|
||||
|
||||
/* The deferred interrupt handler task is created at the highest
|
||||
possible priority to ensure the interrupt handler can return directly
|
||||
to it. The task's handle is stored in xEMACTaskHandle so interrupts can
|
||||
notify the task when there is something to process. */
|
||||
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialisation was already performed, just wait for the link. */
|
||||
prvGMACWaitLS( xWaitRelinkDelay );
|
||||
}
|
||||
|
||||
/* Only return pdTRUE when the Link Status of the PHY is high, otherwise the
|
||||
DHCP process and all other communication will fail. */
|
||||
xLinkStatus = xGetPhyLinkStatus();
|
||||
|
||||
return ( xLinkStatus != pdFALSE );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )
|
||||
{
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
|
||||
{
|
||||
iptraceNETWORK_INTERFACE_TRANSMIT();
|
||||
emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
|
||||
}
|
||||
else if( bReleaseAfterSend != pdFALSE )
|
||||
{
|
||||
/* No link. */
|
||||
vReleaseNetworkBufferAndDescriptor( pxBuffer );
|
||||
}
|
||||
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static inline unsigned long ulReadMDIO( unsigned ulRegister )
|
||||
{
|
||||
uint16_t usValue;
|
||||
|
||||
XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );
|
||||
return usValue;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )
|
||||
{
|
||||
TickType_t xStartTime, xEndTime;
|
||||
const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );
|
||||
BaseType_t xReturn;
|
||||
|
||||
xStartTime = xTaskGetTickCount();
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
xEndTime = xTaskGetTickCount();
|
||||
|
||||
if( xEndTime - xStartTime > xMaxTime )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
break;
|
||||
}
|
||||
ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
|
||||
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay( xShortDelay );
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
|
||||
{
|
||||
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
|
||||
uint8_t *ucRAMBuffer = ucNetworkPackets;
|
||||
uint32_t ul;
|
||||
|
||||
for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
|
||||
{
|
||||
pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
|
||||
*( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
|
||||
ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xGetPhyLinkStatus( void )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvEMACHandlerTask( void *pvParameters )
|
||||
{
|
||||
TimeOut_t xPhyTime;
|
||||
TickType_t xPhyRemTime;
|
||||
UBaseType_t uxLastMinBufferCount = 0;
|
||||
UBaseType_t uxCurrentCount;
|
||||
BaseType_t xResult = 0;
|
||||
uint32_t xStatus;
|
||||
const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
|
||||
|
||||
/* Remove compiler warnings about unused parameters. */
|
||||
( void ) pvParameters;
|
||||
|
||||
/* A possibility to set some additional task properties like calling
|
||||
portTASK_USES_FLOATING_POINT() */
|
||||
iptraceEMAC_TASK_STARTING();
|
||||
|
||||
vTaskSetTimeOutState( &xPhyTime );
|
||||
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
|
||||
if( uxLastMinBufferCount != uxCurrentCount )
|
||||
{
|
||||
/* The logging produced below may be helpful
|
||||
while tuning +TCP: see how many buffers are in use. */
|
||||
uxLastMinBufferCount = uxCurrentCount;
|
||||
FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
|
||||
uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
|
||||
}
|
||||
|
||||
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
|
||||
{
|
||||
static UBaseType_t uxLastMinQueueSpace = 0;
|
||||
|
||||
uxCurrentCount = uxGetMinimumIPQueueSpace();
|
||||
if( uxLastMinQueueSpace != uxCurrentCount )
|
||||
{
|
||||
/* The logging produced below may be helpful
|
||||
while tuning +TCP: see how many buffers are in use. */
|
||||
uxLastMinQueueSpace = uxCurrentCount;
|
||||
FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigCHECK_IP_QUEUE_SPACE */
|
||||
|
||||
if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )
|
||||
{
|
||||
/* No events to process now, wait for the next. */
|
||||
ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
|
||||
}
|
||||
|
||||
if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )
|
||||
{
|
||||
xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;
|
||||
xResult = emacps_check_rx( &xEMACpsif );
|
||||
}
|
||||
|
||||
if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )
|
||||
{
|
||||
xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;
|
||||
emacps_check_tx( &xEMACpsif );
|
||||
}
|
||||
|
||||
if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )
|
||||
{
|
||||
xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;
|
||||
emacps_check_errors( &xEMACpsif );
|
||||
}
|
||||
|
||||
if( xResult > 0 )
|
||||
{
|
||||
/* A packet was received. No need to check for the PHY status now,
|
||||
but set a timer to check it later on. */
|
||||
vTaskSetTimeOutState( &xPhyTime );
|
||||
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
|
||||
xResult = 0;
|
||||
}
|
||||
else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
|
||||
{
|
||||
xStatus = ulReadMDIO( PHY_REG_01_BMSR );
|
||||
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
|
||||
{
|
||||
ulPHYLinkStatus = xStatus;
|
||||
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
|
||||
}
|
||||
|
||||
vTaskSetTimeOutState( &xPhyTime );
|
||||
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
|
||||
{
|
||||
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
|
||||
}
|
||||
else
|
||||
{
|
||||
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
|
||||
NetworkInterface for Xilinx' Zynq
|
||||
|
||||
Please include the following source files:
|
||||
|
||||
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/NetworkInterface.c
|
||||
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_dma.c
|
||||
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
|
||||
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c
|
||||
|
||||
And include the following source files from the Xilinx library:
|
||||
|
||||
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c
|
||||
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_control.c
|
||||
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_g.c
|
||||
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_intr.c
|
||||
|
||||
E.g. ps7_cortexa9_0/libsrc/emacps_v2_0/src/xemacps_intr.c
|
||||
|
||||
The following source files are NOT used for the FreeRTOS+TCP interface:
|
||||
|
||||
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_bdring.c
|
||||
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_hw.c
|
||||
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_sinit.c
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Xilinx, Inc.
|
||||
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
|
||||
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
|
||||
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
|
||||
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
|
||||
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
|
||||
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
|
||||
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
|
||||
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
|
||||
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
|
||||
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NETIF_XEMACPSIF_H__
|
||||
#define __NETIF_XEMACPSIF_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "xstatus.h"
|
||||
#include "sleep.h"
|
||||
#include "xparameters.h"
|
||||
#include "xparameters_ps.h" /* defines XPAR values */
|
||||
#include "xil_types.h"
|
||||
#include "xil_assert.h"
|
||||
#include "xil_io.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xpseudo_asm.h"
|
||||
#include "xil_cache.h"
|
||||
#include "xil_printf.h"
|
||||
#include "xuartps.h"
|
||||
#include "xscugic.h"
|
||||
#include "xemacps.h" /* defines XEmacPs API */
|
||||
|
||||
//#include "netif/xpqueue.h"
|
||||
//#include "xlwipconfig.h"
|
||||
|
||||
void xemacpsif_setmac(uint32_t index, uint8_t *addr);
|
||||
uint8_t* xemacpsif_getmac(uint32_t index);
|
||||
//int xemacpsif_init(struct netif *netif);
|
||||
//int xemacpsif_input(struct netif *netif);
|
||||
#ifdef NOTNOW_BHILL
|
||||
unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);
|
||||
#endif
|
||||
|
||||
/* xaxiemacif_hw.c */
|
||||
void xemacps_error_handler(XEmacPs * Temac);
|
||||
|
||||
struct xBD_TYPE {
|
||||
uint32_t address;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Missing declaration in 'src/xemacps_hw.h' :
|
||||
* When set, the GEM DMA will automatically
|
||||
* discard receive packets from the receiver packet
|
||||
* buffer memory when no AHB resource is
|
||||
* available.
|
||||
* When low, then received packets will remain to be
|
||||
* stored in the SRAM based packet buffer until
|
||||
* AHB buffer resource next becomes available.
|
||||
*/
|
||||
#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK 0x01000000
|
||||
|
||||
#define EMAC_IF_RX_EVENT 1
|
||||
#define EMAC_IF_TX_EVENT 2
|
||||
#define EMAC_IF_ERR_EVENT 4
|
||||
#define EMAC_IF_ALL_EVENT 7
|
||||
|
||||
/* structure within each netif, encapsulating all information required for
|
||||
* using a particular temac instance
|
||||
*/
|
||||
typedef struct {
|
||||
XEmacPs emacps;
|
||||
|
||||
/* pointers to memory holding buffer descriptors (used only with SDMA) */
|
||||
struct xBD_TYPE *rxSegments;
|
||||
struct xBD_TYPE *txSegments;
|
||||
|
||||
unsigned char *tx_space;
|
||||
unsigned uTxUnitSize;
|
||||
|
||||
char *remain_mem;
|
||||
unsigned remain_siz;
|
||||
|
||||
volatile int rxHead, rxTail;
|
||||
volatile int txHead, txTail;
|
||||
|
||||
volatile int txBusy;
|
||||
|
||||
volatile uint32_t isr_events;
|
||||
|
||||
unsigned int last_rx_frms_cntr;
|
||||
|
||||
} xemacpsif_s;
|
||||
|
||||
//extern xemacpsif_s xemacpsif;
|
||||
|
||||
int is_tx_space_available(xemacpsif_s *emac);
|
||||
|
||||
/* xaxiemacif_dma.c */
|
||||
|
||||
struct xNETWORK_BUFFER;
|
||||
|
||||
int emacps_check_rx( xemacpsif_s *xemacpsif );
|
||||
void emacps_check_tx( xemacpsif_s *xemacpsif );
|
||||
int emacps_check_errors( xemacpsif_s *xemacps );
|
||||
void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );
|
||||
|
||||
extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );
|
||||
extern unsigned Phy_Setup( XEmacPs *xemacpsp );
|
||||
extern void setup_isr( xemacpsif_s *xemacpsif );
|
||||
extern XStatus init_dma( xemacpsif_s *xemacpsif );
|
||||
extern void start_emacps( xemacpsif_s *xemacpsif );
|
||||
|
||||
void EmacEnableIntr(void);
|
||||
void EmacDisableIntr(void);
|
||||
|
||||
XStatus init_axi_dma(xemacpsif_s *xemacpsif);
|
||||
void process_sent_bds( xemacpsif_s *xemacpsif );
|
||||
|
||||
void emacps_send_handler(void *arg);
|
||||
void emacps_recv_handler(void *arg);
|
||||
void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);
|
||||
void HandleTxErrors(xemacpsif_s *xemacpsif);
|
||||
XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);
|
||||
|
||||
void clean_dma_txdescs(xemacpsif_s *xemacpsif);
|
||||
void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NETIF_XAXIEMACIF_H__ */
|
||||
|
|
@ -0,0 +1,657 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 200417 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Zynq/x_emacpsif.h"
|
||||
#include "Zynq/x_topology.h"
|
||||
#include "xstatus.h"
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xparameters_ps.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xil_mmu.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
#include "uncached_memory.h"
|
||||
|
||||
/* Two defines used to set or clear the EMAC interrupt */
|
||||
#define INTC_BASE_ADDR XPAR_SCUGIC_CPU_BASEADDR
|
||||
#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_DIST_BASEADDR
|
||||
|
||||
|
||||
|
||||
#if( ipconfigPACKET_FILLER_SIZE != 2 )
|
||||
#error Please define ipconfigPACKET_FILLER_SIZE as the value '2'
|
||||
#endif
|
||||
#define TX_OFFSET ipconfigPACKET_FILLER_SIZE
|
||||
|
||||
/* Defined in NetworkInterface.c */
|
||||
extern TaskHandle_t xEMACTaskHandle;
|
||||
|
||||
/*
|
||||
pxDMA_tx_buffers: these are character arrays, each one is big enough to hold 1 MTU.
|
||||
The actual TX buffers are located in uncached RAM.
|
||||
*/
|
||||
static unsigned char *pxDMA_tx_buffers[ ipconfigNIC_N_TX_DESC ] = { NULL };
|
||||
|
||||
/*
|
||||
pxDMA_rx_buffers: these are pointers to 'NetworkBufferDescriptor_t'.
|
||||
Once a message has been received by the EMAC, the descriptor can be passed
|
||||
immediately to the IP-task.
|
||||
*/
|
||||
static NetworkBufferDescriptor_t *pxDMA_rx_buffers[ ipconfigNIC_N_RX_DESC ] = { NULL };
|
||||
|
||||
/*
|
||||
The FreeRTOS+TCP port is using a fixed 'topology', which is declared in
|
||||
./portable/NetworkInterface/Zynq/NetworkInterface.c
|
||||
*/
|
||||
extern struct xtopology_t xXTopology;
|
||||
|
||||
static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
|
||||
|
||||
/*
|
||||
The FreeRTOS+TCP port does not make use of "src/xemacps_bdring.c".
|
||||
In stead 'struct xemacpsif_s' has a "head" and a "tail" index.
|
||||
"head" is the next index to be written, used.
|
||||
"tail" is the next index to be read, freed.
|
||||
*/
|
||||
|
||||
int is_tx_space_available( xemacpsif_s *xemacpsif )
|
||||
{
|
||||
size_t uxCount;
|
||||
|
||||
if( xTXDescriptorSemaphore != NULL )
|
||||
{
|
||||
uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
|
||||
}
|
||||
else
|
||||
{
|
||||
uxCount = ( UBaseType_t ) 0u;
|
||||
}
|
||||
|
||||
return uxCount;
|
||||
}
|
||||
|
||||
void emacps_check_tx( xemacpsif_s *xemacpsif )
|
||||
{
|
||||
int tail = xemacpsif->txTail;
|
||||
int head = xemacpsif->txHead;
|
||||
size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
|
||||
|
||||
/* uxCount is the number of TX descriptors that are in use by the DMA. */
|
||||
/* When done, "TXBUF_USED" will be set. */
|
||||
|
||||
while( ( uxCount > 0 ) && ( ( xemacpsif->txSegments[ tail ].flags & XEMACPS_TXBUF_USED_MASK ) != 0 ) )
|
||||
{
|
||||
if( ( tail == head ) && ( uxCount != ipconfigNIC_N_TX_DESC ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
#warning ipconfigZERO_COPY_TX_DRIVER is defined
|
||||
{
|
||||
void *pvBuffer = pxDMA_tx_buffers[ tail ];
|
||||
NetworkBufferDescriptor_t *pxBuffer;
|
||||
|
||||
if( pvBuffer != NULL )
|
||||
{
|
||||
pxDMA_tx_buffers[ tail ] = NULL;
|
||||
pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer );
|
||||
if( pxBuffer != NULL )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxBuffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeRTOS_printf( ( "emacps_check_tx: Can not find network buffer\n" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Clear all but the "used" and "wrap" bits. */
|
||||
if( tail < ipconfigNIC_N_TX_DESC - 1 )
|
||||
{
|
||||
xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;
|
||||
}
|
||||
uxCount--;
|
||||
/* Tell the counting semaphore that one more TX descriptor is available. */
|
||||
xSemaphoreGive( xTXDescriptorSemaphore );
|
||||
if( ++tail == ipconfigNIC_N_TX_DESC )
|
||||
{
|
||||
tail = 0;
|
||||
}
|
||||
xemacpsif->txTail = tail;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void emacps_send_handler(void *arg)
|
||||
{
|
||||
xemacpsif_s *xemacpsif;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
xemacpsif = (xemacpsif_s *)(arg);
|
||||
|
||||
/* In this port for FreeRTOS+TCP, the EMAC interrupts will only set a bit in
|
||||
"isr_events". The task in NetworkInterface will wake-up and do the necessary work.
|
||||
*/
|
||||
xemacpsif->isr_events |= EMAC_IF_TX_EVENT;
|
||||
xemacpsif->txBusy = pdFALSE;
|
||||
|
||||
if( xEMACTaskHandle != NULL )
|
||||
{
|
||||
vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
|
||||
}
|
||||
|
||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
|
||||
static BaseType_t xValidLength( BaseType_t xLength )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
if( ( xLength >= ( BaseType_t ) sizeof( struct xARP_PACKET ) ) && ( ( ( uint32_t ) xLength ) <= ipTOTAL_ETHERNET_FRAME_SIZE ) )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
XStatus emacps_send_message(xemacpsif_s *xemacpsif, NetworkBufferDescriptor_t *pxBuffer, int iReleaseAfterSend )
|
||||
{
|
||||
int head = xemacpsif->txHead;
|
||||
int tail = xemacpsif->txTail;
|
||||
int iHasSent = 0;
|
||||
uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress;
|
||||
TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );
|
||||
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
{
|
||||
/* This driver wants to own all network buffers which are to be transmitted. */
|
||||
configASSERT( iReleaseAfterSend != pdFALSE );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Open a do {} while ( 0 ) loop to be able to call break. */
|
||||
do
|
||||
{
|
||||
uint32_t ulFlags = 0;
|
||||
|
||||
if( xValidLength( pxBuffer->xDataLength ) != pdTRUE )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( xTXDescriptorSemaphore == NULL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
|
||||
{
|
||||
FreeRTOS_printf( ( "emacps_send_message: Time-out waiting for TX buffer\n" ) );
|
||||
break;
|
||||
}
|
||||
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
/* Pass the pointer (and its ownership) directly to DMA. */
|
||||
pxDMA_tx_buffers[ head ] = pxBuffer->pucEthernetBuffer;
|
||||
if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
|
||||
{
|
||||
Xil_DCacheFlushRange( ( unsigned )pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
|
||||
}
|
||||
/* Buffer has been transferred, do not release it. */
|
||||
iReleaseAfterSend = pdFALSE;
|
||||
#else
|
||||
if( pxDMA_tx_buffers[ head ] == NULL )
|
||||
{
|
||||
FreeRTOS_printf( ( "emacps_send_message: pxDMA_tx_buffers[ %d ] == NULL\n", head ) );
|
||||
break;
|
||||
}
|
||||
/* Copy the message to unbuffered space in RAM. */
|
||||
memcpy( pxDMA_tx_buffers[ head ], pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
|
||||
#endif
|
||||
/* Packets will be sent one-by-one, so for each packet
|
||||
the TXBUF_LAST bit will be set. */
|
||||
ulFlags |= XEMACPS_TXBUF_LAST_MASK;
|
||||
ulFlags |= ( pxBuffer->xDataLength & XEMACPS_TXBUF_LEN_MASK );
|
||||
if( head == ( ipconfigNIC_N_TX_DESC - 1 ) )
|
||||
{
|
||||
ulFlags |= XEMACPS_TXBUF_WRAP_MASK;
|
||||
}
|
||||
|
||||
/* Copy the address of the buffer and set the flags. */
|
||||
xemacpsif->txSegments[ head ].address = ( uint32_t )pxDMA_tx_buffers[ head ];
|
||||
xemacpsif->txSegments[ head ].flags = ulFlags;
|
||||
|
||||
iHasSent = pdTRUE;
|
||||
if( ++head == ipconfigNIC_N_TX_DESC )
|
||||
{
|
||||
head = 0;
|
||||
}
|
||||
/* Update the TX-head index. These variable are declared volatile so they will be
|
||||
accessed as little as possible. */
|
||||
xemacpsif->txHead = head;
|
||||
} while( pdFALSE );
|
||||
|
||||
if( iReleaseAfterSend != pdFALSE )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxBuffer );
|
||||
pxBuffer = NULL;
|
||||
}
|
||||
|
||||
/* Data Synchronization Barrier */
|
||||
dsb();
|
||||
|
||||
if( iHasSent != pdFALSE )
|
||||
{
|
||||
/* Make STARTTX high */
|
||||
uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET);
|
||||
/* Start transmit */
|
||||
xemacpsif->txBusy = pdTRUE;
|
||||
XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) );
|
||||
}
|
||||
dsb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void emacps_recv_handler(void *arg)
|
||||
{
|
||||
xemacpsif_s *xemacpsif;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
xemacpsif = (xemacpsif_s *)(arg);
|
||||
xemacpsif->isr_events |= EMAC_IF_RX_EVENT;
|
||||
|
||||
if( xEMACTaskHandle != NULL )
|
||||
{
|
||||
vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
|
||||
}
|
||||
|
||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
|
||||
static NetworkBufferDescriptor_t *ethMsg = NULL;
|
||||
static NetworkBufferDescriptor_t *ethLast = NULL;
|
||||
|
||||
static void passEthMessages( void )
|
||||
{
|
||||
IPStackEvent_t xRxEvent;
|
||||
|
||||
xRxEvent.eEventType = eNetworkRxEvent;
|
||||
xRxEvent.pvData = ( void * ) ethMsg;
|
||||
|
||||
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )
|
||||
{
|
||||
/* The buffer could not be sent to the stack so must be released again.
|
||||
This is a deferred handler taskr, not a real interrupt, so it is ok to
|
||||
use the task level function here. */
|
||||
do
|
||||
{
|
||||
NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer;
|
||||
vReleaseNetworkBufferAndDescriptor( ethMsg );
|
||||
ethMsg = xNext;
|
||||
} while( ethMsg != NULL );
|
||||
|
||||
iptraceETHERNET_RX_EVENT_LOST();
|
||||
FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) );
|
||||
}
|
||||
|
||||
ethMsg = ethLast = NULL;
|
||||
}
|
||||
|
||||
int emacps_check_rx( xemacpsif_s *xemacpsif )
|
||||
{
|
||||
NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer;
|
||||
int rx_bytes;
|
||||
volatile int msgCount = 0;
|
||||
int head = xemacpsif->rxHead;
|
||||
|
||||
/* There seems to be an issue (SI# 692601), see comments below. */
|
||||
resetrx_on_no_rxdata(xemacpsif);
|
||||
|
||||
/* This FreeRTOS+TCP driver shall be compiled with the option
|
||||
"ipconfigUSE_LINKED_RX_MESSAGES" enabled. It allows the driver to send a
|
||||
chain of RX messages within one message to the IP-task. */
|
||||
for( ;; )
|
||||
{
|
||||
if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) ||
|
||||
( pxDMA_rx_buffers[ head ] == NULL ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pxNewBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 );
|
||||
if( pxNewBuffer == NULL )
|
||||
{
|
||||
/* A packet has been received, but there is no replacement for this Network Buffer.
|
||||
The packet will be dropped, and it Network Buffer will stay in place. */
|
||||
FreeRTOS_printf( ("emacps_check_rx: unable to allocate a Netwrok Buffer\n" ) );
|
||||
pxNewBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];
|
||||
|
||||
/* Just avoiding to use or refer to the same buffer again */
|
||||
pxDMA_rx_buffers[ head ] = pxNewBuffer;
|
||||
|
||||
/*
|
||||
* Adjust the buffer size to the actual number of bytes received.
|
||||
*/
|
||||
rx_bytes = xemacpsif->rxSegments[ head ].flags & XEMACPS_RXBUF_LEN_MASK;
|
||||
|
||||
pxBuffer->xDataLength = rx_bytes;
|
||||
|
||||
if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
|
||||
{
|
||||
Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)rx_bytes );
|
||||
}
|
||||
|
||||
/* store it in the receive queue, where it'll be processed by a
|
||||
different handler. */
|
||||
iptraceNETWORK_INTERFACE_RECEIVE();
|
||||
pxBuffer->pxNextBuffer = NULL;
|
||||
|
||||
if( ethMsg == NULL )
|
||||
{
|
||||
// Becomes the first message
|
||||
ethMsg = pxBuffer;
|
||||
}
|
||||
else if( ethLast != NULL )
|
||||
{
|
||||
// Add to the tail
|
||||
ethLast->pxNextBuffer = pxBuffer;
|
||||
}
|
||||
|
||||
ethLast = pxBuffer;
|
||||
msgCount++;
|
||||
}
|
||||
{
|
||||
if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 )
|
||||
{
|
||||
Xil_DCacheInvalidateRange( ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE );
|
||||
}
|
||||
{
|
||||
uint32_t addr = ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;
|
||||
if( head == ( ipconfigNIC_N_RX_DESC - 1 ) )
|
||||
{
|
||||
addr |= XEMACPS_RXBUF_WRAP_MASK;
|
||||
}
|
||||
/* Clearing 'XEMACPS_RXBUF_NEW_MASK' 0x00000001 *< Used bit.. */
|
||||
xemacpsif->rxSegments[ head ].address = addr;
|
||||
xemacpsif->rxSegments[ head ].flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( ++head == ipconfigNIC_N_RX_DESC )
|
||||
{
|
||||
head = 0;
|
||||
}
|
||||
xemacpsif->rxHead = head;
|
||||
}
|
||||
|
||||
if( ethMsg != NULL )
|
||||
{
|
||||
passEthMessages( );
|
||||
}
|
||||
|
||||
return msgCount;
|
||||
}
|
||||
|
||||
void clean_dma_txdescs(xemacpsif_s *xemacpsif)
|
||||
{
|
||||
int index;
|
||||
unsigned char *ucTxBuffer;
|
||||
|
||||
/* Clear all TX descriptors and assign uncached memory to each descriptor.
|
||||
"tx_space" points to the first available TX buffer. */
|
||||
ucTxBuffer = xemacpsif->tx_space;
|
||||
|
||||
for( index = 0; index < ipconfigNIC_N_TX_DESC; index++ )
|
||||
{
|
||||
xemacpsif->txSegments[ index ].address = ( uint32_t )ucTxBuffer;
|
||||
xemacpsif->txSegments[ index ].flags = XEMACPS_TXBUF_USED_MASK;
|
||||
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
|
||||
pxDMA_tx_buffers[ index ] = ( void* )NULL;
|
||||
#else
|
||||
pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET );
|
||||
#endif
|
||||
ucTxBuffer += xemacpsif->uTxUnitSize;
|
||||
}
|
||||
xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags =
|
||||
XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;
|
||||
}
|
||||
|
||||
XStatus init_dma(xemacpsif_s *xemacpsif)
|
||||
{
|
||||
NetworkBufferDescriptor_t *pxBuffer;
|
||||
|
||||
int iIndex;
|
||||
UBaseType_t xRxSize;
|
||||
UBaseType_t xTxSize;
|
||||
struct xtopology_t *xtopologyp = &xXTopology;
|
||||
|
||||
xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] );
|
||||
|
||||
xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] );
|
||||
|
||||
/* Also round-up to 4KB */
|
||||
xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful;
|
||||
/*
|
||||
* We allocate 65536 bytes for RX BDs which can accommodate a
|
||||
* maximum of 8192 BDs which is much more than any application
|
||||
* will ever need.
|
||||
*/
|
||||
xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize ) );
|
||||
xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) );
|
||||
xemacpsif->tx_space = ( unsigned char * )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) );
|
||||
|
||||
/* These variables will be used in XEmacPs_Start (see src/xemacps.c). */
|
||||
xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments;
|
||||
xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments;
|
||||
|
||||
if( xTXDescriptorSemaphore == NULL )
|
||||
{
|
||||
xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC );
|
||||
configASSERT( xTXDescriptorSemaphore );
|
||||
}
|
||||
/*
|
||||
* Allocate RX descriptors, 1 RxBD at a time.
|
||||
*/
|
||||
for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ )
|
||||
{
|
||||
pxBuffer = pxDMA_rx_buffers[ iIndex ];
|
||||
if( pxBuffer == NULL )
|
||||
{
|
||||
pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 );
|
||||
if( pxBuffer == NULL )
|
||||
{
|
||||
FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
xemacpsif->rxSegments[ iIndex ].flags = 0;
|
||||
xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;
|
||||
|
||||
pxDMA_rx_buffers[ iIndex ] = pxBuffer;
|
||||
/* Make sure this memory is not in cache for now. */
|
||||
if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
|
||||
{
|
||||
Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE,
|
||||
(unsigned)ipTOTAL_ETHERNET_FRAME_SIZE );
|
||||
}
|
||||
}
|
||||
|
||||
xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK;
|
||||
|
||||
memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize );
|
||||
|
||||
clean_dma_txdescs( xemacpsif );
|
||||
|
||||
{
|
||||
uint32_t value;
|
||||
value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET );
|
||||
|
||||
// 1xxxx: Attempt to use INCR16 AHB bursts
|
||||
value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST;
|
||||
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
|
||||
value |= XEMACPS_DMACR_TCPCKSUM_MASK;
|
||||
#else
|
||||
#warning Are you sure the EMAC should not calculate outgoing checksums?
|
||||
value &= ~XEMACPS_DMACR_TCPCKSUM_MASK;
|
||||
#endif
|
||||
XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value );
|
||||
}
|
||||
{
|
||||
uint32_t value;
|
||||
value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET );
|
||||
|
||||
/* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ).
|
||||
Now tell the EMAC that received messages should be stored at "address + 2". */
|
||||
value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000;
|
||||
|
||||
#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 )
|
||||
value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
|
||||
#else
|
||||
#warning Are you sure the EMAC should not calculate incoming checksums?
|
||||
value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK;
|
||||
#endif
|
||||
XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value );
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect the device driver handler that will be called when an
|
||||
* interrupt for the device occurs, the handler defined above performs
|
||||
* the specific interrupt processing for the device.
|
||||
*/
|
||||
XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
|
||||
(Xil_ExceptionHandler)XEmacPs_IntrHandler,
|
||||
(void *)&xemacpsif->emacps);
|
||||
/*
|
||||
* Enable the interrupt for emacps.
|
||||
*/
|
||||
EmacEnableIntr( );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* resetrx_on_no_rxdata():
|
||||
*
|
||||
* It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata
|
||||
* called by the user.
|
||||
* The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.
|
||||
* Under heavy Rx traffic because of the HW bug there are times when the Rx path
|
||||
* becomes unresponsive. The workaround for it is to check for the Rx path for
|
||||
* traffic (by reading the stats registers regularly). If the stats register
|
||||
* does not increment for sometime (proving no Rx traffic), the function resets
|
||||
* the Rx data path.
|
||||
*
|
||||
*/
|
||||
|
||||
void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
|
||||
{
|
||||
unsigned long regctrl;
|
||||
unsigned long tempcntr;
|
||||
|
||||
tempcntr = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET );
|
||||
if ( ( tempcntr == 0 ) && ( xemacpsif->last_rx_frms_cntr == 0 ) )
|
||||
{
|
||||
regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
|
||||
XEMACPS_NWCTRL_OFFSET);
|
||||
regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
|
||||
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
|
||||
XEMACPS_NWCTRL_OFFSET, regctrl);
|
||||
regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
|
||||
regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
|
||||
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
|
||||
}
|
||||
xemacpsif->last_rx_frms_cntr = tempcntr;
|
||||
}
|
||||
|
||||
void EmacDisableIntr(void)
|
||||
{
|
||||
XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);
|
||||
}
|
||||
|
||||
void EmacEnableIntr(void)
|
||||
{
|
||||
XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Xilinx, Inc.
|
||||
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
|
||||
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
|
||||
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
|
||||
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
|
||||
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
|
||||
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
|
||||
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
|
||||
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
|
||||
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
|
||||
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Zynq/x_emacpsif.h"
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
|
||||
///* FreeRTOS+TCP includes. */
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
extern TaskHandle_t xEMACTaskHandle;
|
||||
|
||||
/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
|
||||
*** to run it on a PEEP board
|
||||
***/
|
||||
|
||||
unsigned int link_speed = 100;
|
||||
|
||||
void setup_isr( xemacpsif_s *xemacpsif )
|
||||
{
|
||||
/*
|
||||
* Setup callbacks
|
||||
*/
|
||||
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
|
||||
(void *) emacps_send_handler,
|
||||
(void *) xemacpsif);
|
||||
|
||||
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
|
||||
(void *) emacps_recv_handler,
|
||||
(void *) xemacpsif);
|
||||
|
||||
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
|
||||
(void *) emacps_error_handler,
|
||||
(void *) xemacpsif);
|
||||
}
|
||||
|
||||
void start_emacps (xemacpsif_s *xemacps)
|
||||
{
|
||||
/* start the temac */
|
||||
XEmacPs_Start(&xemacps->emacps);
|
||||
}
|
||||
|
||||
extern struct xtopology_t xXTopology;
|
||||
|
||||
volatile int error_msg_count = 0;
|
||||
volatile const char *last_err_msg = "";
|
||||
|
||||
struct xERROR_MSG {
|
||||
void *arg;
|
||||
u8 Direction;
|
||||
u32 ErrorWord;
|
||||
};
|
||||
|
||||
static struct xERROR_MSG xErrorList[ 8 ];
|
||||
static BaseType_t xErrorHead, xErrorTail;
|
||||
|
||||
void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xemacpsif_s *xemacpsif;
|
||||
BaseType_t xNextHead = xErrorHead;
|
||||
|
||||
xemacpsif = (xemacpsif_s *)(arg);
|
||||
|
||||
if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
|
||||
{
|
||||
if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
|
||||
xNextHead = 0;
|
||||
if( xNextHead != xErrorTail )
|
||||
{
|
||||
|
||||
xErrorList[ xErrorHead ].arg = arg;
|
||||
xErrorList[ xErrorHead ].Direction = Direction;
|
||||
xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
|
||||
|
||||
xErrorHead = xNextHead;
|
||||
|
||||
xemacpsif = (xemacpsif_s *)(arg);
|
||||
xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
|
||||
}
|
||||
|
||||
if( xEMACTaskHandle != NULL )
|
||||
{
|
||||
vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
|
||||
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);
|
||||
|
||||
int emacps_check_errors( xemacpsif_s *xemacps )
|
||||
{
|
||||
int xResult;
|
||||
|
||||
( void ) xemacps;
|
||||
|
||||
if( xErrorHead == xErrorTail )
|
||||
{
|
||||
xResult = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xResult = 1;
|
||||
emacps_handle_error(
|
||||
xErrorList[ xErrorTail ].arg,
|
||||
xErrorList[ xErrorTail ].Direction,
|
||||
xErrorList[ xErrorTail ].ErrorWord );
|
||||
}
|
||||
|
||||
return xResult;
|
||||
}
|
||||
|
||||
BaseType_t xNetworkInterfaceInitialise( void );
|
||||
|
||||
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
|
||||
{
|
||||
xemacpsif_s *xemacpsif;
|
||||
struct xtopology_t *xtopologyp;
|
||||
XEmacPs *xemacps;
|
||||
|
||||
xemacpsif = (xemacpsif_s *)(arg);
|
||||
|
||||
xtopologyp = &xXTopology;
|
||||
|
||||
xemacps = &xemacpsif->emacps;
|
||||
|
||||
/* Do not appear to be used. */
|
||||
( void ) xemacps;
|
||||
( void ) xtopologyp;
|
||||
|
||||
last_err_msg = NULL;
|
||||
|
||||
if( ErrorWord != 0 )
|
||||
{
|
||||
switch (Direction) {
|
||||
case XEMACPS_RECV:
|
||||
if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
|
||||
{
|
||||
last_err_msg = "Receive DMA error";
|
||||
xNetworkInterfaceInitialise( );
|
||||
}
|
||||
if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
|
||||
{
|
||||
last_err_msg = "Receive over run";
|
||||
emacps_recv_handler(arg);
|
||||
}
|
||||
if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
|
||||
{
|
||||
last_err_msg = "Receive buffer not available";
|
||||
emacps_recv_handler(arg);
|
||||
}
|
||||
break;
|
||||
case XEMACPS_SEND:
|
||||
if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
|
||||
{
|
||||
last_err_msg = "Transmit DMA error";
|
||||
xNetworkInterfaceInitialise( );
|
||||
}
|
||||
if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
|
||||
{
|
||||
last_err_msg = "Transmit under run";
|
||||
HandleTxErrors( xemacpsif );
|
||||
}
|
||||
if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
|
||||
{
|
||||
last_err_msg = "Transmit buffer exhausted";
|
||||
HandleTxErrors( xemacpsif );
|
||||
}
|
||||
if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
|
||||
{
|
||||
last_err_msg = "Transmit retry excessed limits";
|
||||
HandleTxErrors( xemacpsif );
|
||||
}
|
||||
if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
|
||||
{
|
||||
last_err_msg = "Transmit collision";
|
||||
emacps_check_tx( xemacpsif );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Break on this statement and inspect error_msg if you like
|
||||
if( last_err_msg != NULL )
|
||||
{
|
||||
error_msg_count++;
|
||||
FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
|
||||
}
|
||||
}
|
||||
|
||||
extern XEmacPs_Config mac_config;
|
||||
|
||||
void HandleTxErrors(xemacpsif_s *xemacpsif)
|
||||
{
|
||||
u32 netctrlreg;
|
||||
|
||||
//taskENTER_CRITICAL()
|
||||
{
|
||||
netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
|
||||
XEMACPS_NWCTRL_OFFSET);
|
||||
netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
|
||||
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
|
||||
XEMACPS_NWCTRL_OFFSET, netctrlreg);
|
||||
|
||||
clean_dma_txdescs( xemacpsif );
|
||||
netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
|
||||
XEMACPS_NWCTRL_OFFSET);
|
||||
netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
|
||||
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
|
||||
XEMACPS_NWCTRL_OFFSET, netctrlreg);
|
||||
}
|
||||
//taskEXIT_CRITICAL( );
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Xilinx, Inc.
|
||||
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
|
||||
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
|
||||
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
|
||||
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
|
||||
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
|
||||
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
|
||||
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
|
||||
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
|
||||
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
|
||||
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XEMACPSIF_HW_H_
|
||||
#define __XEMACPSIF_HW_H_
|
||||
|
||||
#include "Zynq/x_emacpsif.h"
|
||||
//#include "lwip/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
XEmacPs_Config * lookup_config(unsigned mac_base);
|
||||
|
||||
//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);
|
||||
|
||||
int emacps_check_errors( xemacpsif_s *xemacps );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,585 @@
|
|||
/*
|
||||
* Copyright (c) 2007-2008, Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Advanced Micro Devices, Inc. nor the names
|
||||
* of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some portions copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Xilinx, Inc.
|
||||
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
|
||||
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
|
||||
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
|
||||
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
|
||||
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
|
||||
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
|
||||
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
|
||||
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
|
||||
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
|
||||
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Zynq/x_emacpsif.h"
|
||||
//#include "lwipopts.h"
|
||||
#include "xparameters_ps.h"
|
||||
#include "xparameters.h"
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
///* FreeRTOS+TCP includes. */
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
int phy_detected = 0;
|
||||
|
||||
/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
|
||||
*** to run it on a PEEP board
|
||||
***/
|
||||
|
||||
/* Advertisement control register. */
|
||||
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
|
||||
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
|
||||
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
|
||||
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
|
||||
|
||||
#define ADVERTISE_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \
|
||||
ADVERTISE_10HALF | ADVERTISE_100HALF)
|
||||
#define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF)
|
||||
#define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF)
|
||||
|
||||
#define ADVERTISE_1000 0x0300
|
||||
|
||||
|
||||
//#define PHY_REG_00_BMCR 0x00 // Basic mode control register
|
||||
//#define PHY_REG_01_BMSR 0x01 // Basic mode status register
|
||||
//#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
|
||||
//#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
|
||||
//#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
|
||||
|
||||
#define IEEE_CONTROL_REG_OFFSET 0
|
||||
#define IEEE_STATUS_REG_OFFSET 1
|
||||
#define IEEE_AUTONEGO_ADVERTISE_REG 4
|
||||
#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5
|
||||
#define IEEE_1000_ADVERTISE_REG_OFFSET 9
|
||||
#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10
|
||||
#define IEEE_COPPER_SPECIFIC_CONTROL_REG 16
|
||||
#define IEEE_SPECIFIC_STATUS_REG 17
|
||||
#define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19
|
||||
#define IEEE_CONTROL_REG_MAC 21
|
||||
#define IEEE_PAGE_ADDRESS_REGISTER 22
|
||||
|
||||
|
||||
#define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040
|
||||
#define IEEE_CTRL_LINKSPEED_MASK 0x0040
|
||||
#define IEEE_CTRL_LINKSPEED_1000M 0x0040
|
||||
#define IEEE_CTRL_LINKSPEED_100M 0x2000
|
||||
#define IEEE_CTRL_LINKSPEED_10M 0x0000
|
||||
#define IEEE_CTRL_RESET_MASK 0x8000
|
||||
#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#define IEEE_CTRL_RESET 0x9140
|
||||
#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
|
||||
#endif
|
||||
#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008
|
||||
#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020
|
||||
#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200
|
||||
#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100
|
||||
#define IEEE_AN1_ABILITY_MASK 0x1FE0
|
||||
#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00
|
||||
#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380
|
||||
#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060
|
||||
#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030
|
||||
|
||||
#define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800
|
||||
#define IEEE_PAUSE_MASK 0x0400
|
||||
#define IEEE_AUTONEG_ERROR_MASK 0x8000
|
||||
|
||||
#define PHY_DETECT_REG 1
|
||||
#define PHY_DETECT_MASK 0x1808
|
||||
|
||||
#define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140
|
||||
#define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100
|
||||
#define XEMACPS_GMII2RGMII_SPEED10_FD 0x100
|
||||
#define XEMACPS_GMII2RGMII_REG_NUM 0x10
|
||||
|
||||
/* Frequency setting */
|
||||
#define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4)
|
||||
#define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8)
|
||||
#define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)
|
||||
#define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)
|
||||
#ifdef PEEP
|
||||
#define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031
|
||||
#define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001
|
||||
#define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011
|
||||
#endif
|
||||
#define SLCR_LOCK_KEY_VALUE 0x767B
|
||||
#define SLCR_UNLOCK_KEY_VALUE 0xDF0D
|
||||
#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214)
|
||||
#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF
|
||||
|
||||
#define EMAC0_BASE_ADDRESS 0xE000B000
|
||||
#define EMAC1_BASE_ADDRESS 0xE000C000
|
||||
|
||||
static int detect_phy(XEmacPs *xemacpsp)
|
||||
{
|
||||
u16 phy_reg;
|
||||
u32 phy_addr;
|
||||
|
||||
for (phy_addr = 31; phy_addr > 0; phy_addr--) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
|
||||
&phy_reg);
|
||||
|
||||
if ((phy_reg != 0xFFFF) &&
|
||||
((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
|
||||
/* Found a valid PHY address */
|
||||
FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
|
||||
phy_addr));
|
||||
FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );
|
||||
phy_detected = phy_addr;
|
||||
return phy_addr;
|
||||
}
|
||||
}
|
||||
|
||||
FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\n" ) );
|
||||
|
||||
/* default to zero */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef PEEP
|
||||
unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
|
||||
{
|
||||
|
||||
u16 control;
|
||||
u16 status;
|
||||
u16 partner_capabilities;
|
||||
u16 partner_capabilities_1000;
|
||||
u16 phylinkspeed;
|
||||
u32 phy_addr = detect_phy(xemacpsp);
|
||||
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
|
||||
ADVERTISE_1000);
|
||||
/* Advertise PHY speed of 100 and 10 Mbps */
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
|
||||
ADVERTISE_100_AND_10);
|
||||
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
|
||||
&control);
|
||||
control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |
|
||||
IEEE_STAT_AUTONEGOTIATE_RESTART);
|
||||
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
|
||||
|
||||
/* Read PHY control and status registers is successful. */
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
|
||||
|
||||
if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &
|
||||
IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {
|
||||
|
||||
while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
|
||||
&status);
|
||||
}
|
||||
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
|
||||
&partner_capabilities);
|
||||
|
||||
if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,
|
||||
&partner_capabilities_1000);
|
||||
if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)
|
||||
return 1000;
|
||||
}
|
||||
|
||||
if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)
|
||||
return 100;
|
||||
if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)
|
||||
return 10;
|
||||
|
||||
xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",
|
||||
__FUNCTION__);
|
||||
return 10;
|
||||
|
||||
} else {
|
||||
|
||||
/* Update TEMAC speed accordingly */
|
||||
if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
|
||||
/* Get commanded link speed */
|
||||
phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;
|
||||
|
||||
switch (phylinkspeed) {
|
||||
case (IEEE_CTRL_LINKSPEED_1000M):
|
||||
return 1000;
|
||||
case (IEEE_CTRL_LINKSPEED_100M):
|
||||
return 100;
|
||||
case (IEEE_CTRL_LINKSPEED_10M):
|
||||
return 10;
|
||||
default:
|
||||
xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",
|
||||
__FUNCTION__, phylinkspeed);
|
||||
return 10;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else /* Zynq */
|
||||
unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
|
||||
{
|
||||
u16 temp;
|
||||
u16 control;
|
||||
u16 status;
|
||||
u16 partner_capabilities;
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
|
||||
#else
|
||||
u32 phy_addr = detect_phy(xemacpsp);
|
||||
#endif
|
||||
xil_printf("Start PHY autonegotiation \r\n");
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#else
|
||||
XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
|
||||
control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
|
||||
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
|
||||
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
|
||||
control |= IEEE_ASYMMETRIC_PAUSE_MASK;
|
||||
control |= IEEE_PAUSE_MASK;
|
||||
control |= ADVERTISE_100;
|
||||
control |= ADVERTISE_10;
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
|
||||
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
|
||||
&control);
|
||||
control |= ADVERTISE_1000;
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
|
||||
control);
|
||||
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
|
||||
&control);
|
||||
control |= (7 << 12); /* max number of gigabit attempts */
|
||||
control |= (1 << 11); /* enable downshift */
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
|
||||
control);
|
||||
#endif
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
|
||||
control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
|
||||
control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
control &= IEEE_CTRL_ISOLATE_DISABLE;
|
||||
#endif
|
||||
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
|
||||
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#else
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
|
||||
control |= IEEE_CTRL_RESET_MASK;
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
|
||||
|
||||
while (1) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
|
||||
if (control & IEEE_CTRL_RESET_MASK)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
|
||||
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
|
||||
while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
|
||||
sleep(1);
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#else
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
|
||||
&temp);
|
||||
if (temp & IEEE_AUTONEG_ERROR_MASK) {
|
||||
xil_printf("Auto negotiation error \r\n");
|
||||
}
|
||||
#endif
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
|
||||
&status);
|
||||
}
|
||||
|
||||
xil_printf("autonegotiation complete \r\n");
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#else
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);
|
||||
#endif
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
|
||||
while(!(temp & 0x8000)) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
|
||||
}
|
||||
if((temp & 0x0C00) == 0x0800) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
|
||||
return 1000;
|
||||
}
|
||||
else if((temp & 0x0C00) == 0x0400) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
|
||||
return 100;
|
||||
}
|
||||
else if((temp & 0x0C00) == 0x0000) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
|
||||
return 10;
|
||||
} else {
|
||||
xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);
|
||||
return 10;
|
||||
}
|
||||
#else
|
||||
if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */
|
||||
return 1000;
|
||||
else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */
|
||||
return 100;
|
||||
else /* 10Mbps */
|
||||
return 10;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)
|
||||
{
|
||||
u16 control;
|
||||
u32 phy_addr = detect_phy(xemacpsp);
|
||||
|
||||
XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
|
||||
control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
|
||||
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
|
||||
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
|
||||
control |= IEEE_ASYMMETRIC_PAUSE_MASK;
|
||||
control |= IEEE_PAUSE_MASK;
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
|
||||
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
|
||||
control &= ~IEEE_CTRL_LINKSPEED_1000M;
|
||||
control &= ~IEEE_CTRL_LINKSPEED_100M;
|
||||
control &= ~IEEE_CTRL_LINKSPEED_10M;
|
||||
|
||||
if (speed == 1000) {
|
||||
control |= IEEE_CTRL_LINKSPEED_1000M;
|
||||
}
|
||||
|
||||
else if (speed == 100) {
|
||||
control |= IEEE_CTRL_LINKSPEED_100M;
|
||||
/* Dont advertise PHY speed of 1000 Mbps */
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);
|
||||
/* Dont advertise PHY speed of 10 Mbps */
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
|
||||
ADVERTISE_100);
|
||||
}
|
||||
|
||||
else if (speed == 10) {
|
||||
control |= IEEE_CTRL_LINKSPEED_10M;
|
||||
/* Dont advertise PHY speed of 1000 Mbps */
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
|
||||
0);
|
||||
/* Dont advertise PHY speed of 100 Mbps */
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
|
||||
ADVERTISE_10);
|
||||
}
|
||||
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
|
||||
control | IEEE_CTRL_RESET_MASK);
|
||||
{
|
||||
volatile int wait;
|
||||
for (wait=0; wait < 100000; wait++);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SetUpSLCRDivisors(int mac_baseaddr, int speed)
|
||||
{
|
||||
volatile u32 slcrBaseAddress;
|
||||
#ifndef PEEP
|
||||
u32 SlcrDiv0;
|
||||
u32 SlcrDiv1=0;
|
||||
u32 SlcrTxClkCntrl;
|
||||
#endif
|
||||
|
||||
*(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
|
||||
|
||||
if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
|
||||
slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
|
||||
} else {
|
||||
slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
|
||||
}
|
||||
#ifdef PEEP
|
||||
if (speed == 1000) {
|
||||
*(volatile unsigned int *)(slcrBaseAddress) =
|
||||
SLCR_GEM_1G_CLK_CTRL_VALUE;
|
||||
} else if (speed == 100) {
|
||||
*(volatile unsigned int *)(slcrBaseAddress) =
|
||||
SLCR_GEM_100M_CLK_CTRL_VALUE;
|
||||
} else {
|
||||
*(volatile unsigned int *)(slcrBaseAddress) =
|
||||
SLCR_GEM_10M_CLK_CTRL_VALUE;
|
||||
}
|
||||
#else
|
||||
if (speed == 1000) {
|
||||
if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
|
||||
#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
|
||||
SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
|
||||
SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
|
||||
SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
|
||||
SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
|
||||
#endif
|
||||
}
|
||||
} else if (speed == 100) {
|
||||
if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
|
||||
#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
|
||||
SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
|
||||
SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
|
||||
SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
|
||||
SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
|
||||
#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
|
||||
SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
|
||||
SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
|
||||
SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
|
||||
SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);
|
||||
SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
|
||||
SlcrTxClkCntrl |= (SlcrDiv1 << 20);
|
||||
SlcrTxClkCntrl |= (SlcrDiv0 << 8);
|
||||
*(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;
|
||||
#endif
|
||||
*(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
unsigned link_speed;
|
||||
unsigned Phy_Setup (XEmacPs *xemacpsp)
|
||||
{
|
||||
unsigned long conv_present = 0;
|
||||
unsigned long convspeeddupsetting = 0;
|
||||
unsigned long convphyaddr = 0;
|
||||
|
||||
#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
|
||||
convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
|
||||
conv_present = 1;
|
||||
#else
|
||||
#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
|
||||
convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
|
||||
conv_present = 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ipconfigNIC_LINKSPEED_AUTODETECT
|
||||
link_speed = get_IEEE_phy_speed(xemacpsp);
|
||||
if (link_speed == 1000) {
|
||||
SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
|
||||
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
|
||||
} else if (link_speed == 100) {
|
||||
SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
|
||||
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
|
||||
} else {
|
||||
SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
|
||||
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
|
||||
}
|
||||
#elif defined(ipconfigNIC_LINKSPEED1000)
|
||||
SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
|
||||
link_speed = 1000;
|
||||
configure_IEEE_phy_speed(xemacpsp, link_speed);
|
||||
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
|
||||
sleep(1);
|
||||
#elif defined(ipconfigNIC_LINKSPEED100)
|
||||
SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
|
||||
link_speed = 100;
|
||||
configure_IEEE_phy_speed(xemacpsp, link_speed);
|
||||
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
|
||||
sleep(1);
|
||||
#elif defined(ipconfigNIC_LINKSPEED10)
|
||||
SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
|
||||
link_speed = 10;
|
||||
configure_IEEE_phy_speed(xemacpsp, link_speed);
|
||||
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
|
||||
sleep(1);
|
||||
#endif
|
||||
if (conv_present) {
|
||||
XEmacPs_PhyWrite(xemacpsp, convphyaddr,
|
||||
XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
|
||||
}
|
||||
|
||||
xil_printf("link speed: %d\r\n", link_speed);
|
||||
return link_speed;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Xilinx, Inc.
|
||||
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
|
||||
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
|
||||
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
|
||||
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
|
||||
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
|
||||
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
|
||||
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
|
||||
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
|
||||
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
|
||||
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XTOPOLOGY_H_
|
||||
#define __XTOPOLOGY_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };
|
||||
|
||||
struct xtopology_t {
|
||||
unsigned emac_baseaddr;
|
||||
enum xemac_types emac_type;
|
||||
unsigned intc_baseaddr;
|
||||
unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */
|
||||
unsigned scugic_baseaddr; /* valid only for Zynq */
|
||||
unsigned scugic_emac_intr; /* valid only for GEM */
|
||||
};
|
||||
|
||||
extern int x_topology_n_emacs;
|
||||
extern struct xtopology_t x_topology[];
|
||||
|
||||
int x_topology_find_index(unsigned base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_TCP_server.h"
|
||||
#include "FreeRTOS_server_private.h"
|
||||
|
||||
/* Remove the entire file if TCP is not being used. */
|
||||
#if( ipconfigUSE_TCP == 1 )
|
||||
|
||||
#if !defined( ARRAY_SIZE )
|
||||
#define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )
|
||||
#endif
|
||||
|
||||
|
||||
static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket );
|
||||
static char *strnew( const char *pcString );
|
||||
/* Remove slashes at the end of a path. */
|
||||
static void prvRemoveSlash( char *pcDir );
|
||||
|
||||
TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount )
|
||||
{
|
||||
TCPServer_t *pxServer;
|
||||
SocketSet_t xSocketSet;
|
||||
|
||||
/* Create a new server.
|
||||
xPort / xPortAlt : Make the service available on 1 or 2 public port numbers. */
|
||||
xSocketSet = FreeRTOS_CreateSocketSet();
|
||||
|
||||
if( xSocketSet != NULL )
|
||||
{
|
||||
BaseType_t xSize;
|
||||
|
||||
xSize = sizeof( *pxServer ) - sizeof( pxServer->xServers ) + xCount * sizeof( pxServer->xServers[ 0 ] );
|
||||
|
||||
pxServer = ( TCPServer_t * ) pvPortMallocLarge( xSize );
|
||||
if( pxServer != NULL )
|
||||
{
|
||||
struct freertos_sockaddr xAddress;
|
||||
BaseType_t xNoTimeout = 0;
|
||||
BaseType_t xIndex;
|
||||
|
||||
memset( pxServer, '\0', xSize );
|
||||
pxServer->xServerCount = xCount;
|
||||
pxServer->xSocketSet = xSocketSet;
|
||||
|
||||
for( xIndex = 0; xIndex < xCount; xIndex++ )
|
||||
{
|
||||
BaseType_t xPortNumber = pxConfigs[ xIndex ].xPortNumber;
|
||||
|
||||
if( xPortNumber > 0 )
|
||||
{
|
||||
Socket_t xSocket;
|
||||
|
||||
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
|
||||
FreeRTOS_printf( ( "TCP socket on port %d\n", ( int )xPortNumber ) );
|
||||
|
||||
if( xSocket != FREERTOS_NO_SOCKET )
|
||||
{
|
||||
xAddress.sin_addr = FreeRTOS_GetIPAddress(); // Single NIC, currently not used
|
||||
xAddress.sin_port = FreeRTOS_htons( xPortNumber );
|
||||
|
||||
FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );
|
||||
FreeRTOS_listen( xSocket, pxConfigs[ xIndex ].xBackLog );
|
||||
|
||||
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );
|
||||
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );
|
||||
|
||||
#if( ipconfigHTTP_RX_BUFSIZE > 0 )
|
||||
{
|
||||
if( pxConfigs[ xIndex ].eType == eSERVER_HTTP )
|
||||
{
|
||||
WinProperties_t xWinProps;
|
||||
|
||||
memset( &xWinProps, '\0', sizeof( xWinProps ) );
|
||||
/* The parent socket itself won't get connected. The properties below
|
||||
will be inherited by each new child socket. */
|
||||
xWinProps.lTxBufSize = ipconfigHTTP_TX_BUFSIZE;
|
||||
xWinProps.lTxWinSize = ipconfigHTTP_TX_WINSIZE;
|
||||
xWinProps.lRxBufSize = ipconfigHTTP_RX_BUFSIZE;
|
||||
xWinProps.lRxWinSize = ipconfigHTTP_RX_WINSIZE;
|
||||
|
||||
/* Set the window and buffer sizes. */
|
||||
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
FreeRTOS_FD_SET( xSocket, xSocketSet, eSELECT_READ|eSELECT_EXCEPT );
|
||||
pxServer->xServers[ xIndex ].xSocket = xSocket;
|
||||
pxServer->xServers[ xIndex ].eType = pxConfigs[ xIndex ].eType;
|
||||
pxServer->xServers[ xIndex ].pcRootDir = strnew( pxConfigs[ xIndex ].pcRootDir );
|
||||
prvRemoveSlash( ( char * ) pxServer->xServers[ xIndex ].pcRootDir );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Could not allocate the server, delete the socket set */
|
||||
FreeRTOS_DeleteSocketSet( xSocketSet );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Could not create a socket set, return NULL */
|
||||
pxServer = NULL;
|
||||
}
|
||||
|
||||
return pxServer;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket )
|
||||
{
|
||||
TCPClient_t *pxClient = NULL;
|
||||
BaseType_t xSize = 0;
|
||||
FTCPWorkFunction fWorkFunc = NULL;
|
||||
FTCPDeleteFunction fDeleteFunc = NULL;
|
||||
const char *pcType = "Unknown";
|
||||
|
||||
/*_RB_ Can the work and delete functions be part of the xSERVER_CONFIG structure
|
||||
becomes generic, with no pre-processing required? */
|
||||
#if( ipconfigUSE_HTTP != 0 )
|
||||
{
|
||||
if( pxServer->xServers[ xIndex ].eType == eSERVER_HTTP )
|
||||
{
|
||||
xSize = sizeof( HTTPClient_t );
|
||||
fWorkFunc = xHTTPClientWork;
|
||||
fDeleteFunc = vHTTPClientDelete;
|
||||
pcType = "HTTP";
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigUSE_HTTP != 0 */
|
||||
|
||||
#if( ipconfigUSE_FTP != 0 )
|
||||
{
|
||||
if( pxServer->xServers[ xIndex ].eType == eSERVER_FTP )
|
||||
{
|
||||
xSize = sizeof( FTPClient_t );
|
||||
fWorkFunc = xFTPClientWork;
|
||||
fDeleteFunc = vFTPClientDelete;
|
||||
pcType = "FTP";
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigUSE_FTP != 0 */
|
||||
|
||||
/* Malloc enough space for a new HTTP-client */
|
||||
if( xSize )
|
||||
{
|
||||
pxClient = ( TCPClient_t* ) pvPortMallocLarge( xSize );
|
||||
}
|
||||
|
||||
if( pxClient != NULL )
|
||||
{
|
||||
memset( pxClient, '\0', xSize );
|
||||
|
||||
/* Put the new client in front of the list. */
|
||||
pxClient->eType = pxServer->xServers[ xIndex ].eType;
|
||||
pxClient->pcRootDir = pxServer->xServers[ xIndex ].pcRootDir;
|
||||
pxClient->pxParent = pxServer;
|
||||
pxClient->xSocket = xNexSocket;
|
||||
pxClient->pxNextClient = pxServer->pxClients;
|
||||
pxClient->fWorkFunction = fWorkFunc;
|
||||
pxClient->fDeleteFunction = fDeleteFunc;
|
||||
pxServer->pxClients = pxClient;
|
||||
|
||||
FreeRTOS_FD_SET( xNexSocket, pxServer->xSocketSet, eSELECT_READ|eSELECT_EXCEPT );
|
||||
}
|
||||
else
|
||||
{
|
||||
pcType = "closed";
|
||||
FreeRTOS_closesocket( xNexSocket );
|
||||
}
|
||||
|
||||
FreeRTOS_printf( ( "TPC-server: new %s client\n", pcType ) );
|
||||
|
||||
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */
|
||||
( void ) pcType;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime )
|
||||
{
|
||||
TCPClient_t **ppxClient;
|
||||
BaseType_t xIndex;
|
||||
BaseType_t xRc;
|
||||
|
||||
/* Let the server do one working cycle */
|
||||
xRc = FreeRTOS_select( pxServer->xSocketSet, xBlockingTime );
|
||||
|
||||
if( xRc != 0 )
|
||||
{
|
||||
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
|
||||
{
|
||||
struct freertos_sockaddr xAddress;
|
||||
Socket_t xNexSocket;
|
||||
socklen_t xSocketLength;
|
||||
|
||||
if( pxServer->xServers[ xIndex ].xSocket == FREERTOS_NO_SOCKET )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
xSocketLength = sizeof( xAddress );
|
||||
xNexSocket = FreeRTOS_accept( pxServer->xServers[ xIndex ].xSocket, &xAddress, &xSocketLength);
|
||||
|
||||
if( ( xNexSocket != FREERTOS_NO_SOCKET ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) )
|
||||
{
|
||||
prvReceiveNewClient( pxServer, xIndex, xNexSocket );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ppxClient = &pxServer->pxClients;
|
||||
|
||||
while( ( * ppxClient ) != NULL )
|
||||
{
|
||||
TCPClient_t *pxThis = *ppxClient;
|
||||
|
||||
/* Almost C++ */
|
||||
xRc = pxThis->fWorkFunction( pxThis );
|
||||
|
||||
if (xRc < 0 )
|
||||
{
|
||||
*ppxClient = pxThis->pxNextClient;
|
||||
/* Close handles, resources */
|
||||
pxThis->fDeleteFunction( pxThis );
|
||||
/* Free the space */
|
||||
vPortFreeLarge( pxThis );
|
||||
}
|
||||
else
|
||||
{
|
||||
ppxClient = &( pxThis->pxNextClient );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static char *strnew( const char *pcString )
|
||||
{
|
||||
BaseType_t xLength;
|
||||
char *pxBuffer;
|
||||
|
||||
xLength = strlen( pcString ) + 1;
|
||||
pxBuffer = ( char * ) pvPortMalloc( xLength );
|
||||
if( pxBuffer != NULL )
|
||||
{
|
||||
memcpy( pxBuffer, pcString, xLength );
|
||||
}
|
||||
|
||||
return pxBuffer;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvRemoveSlash( char *pcDir )
|
||||
{
|
||||
BaseType_t xLength = strlen( pcDir );
|
||||
|
||||
while( ( xLength > 0 ) && ( pcDir[ xLength - 1 ] == '/' ) )
|
||||
{
|
||||
pcDir[ --xLength ] = '\0';
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigSUPPORT_SIGNALS != 0 )
|
||||
|
||||
/* FreeRTOS_TCPServerWork() calls select().
|
||||
The two functions below provide a possibility to interrupt
|
||||
the call to select(). After the interruption, resume
|
||||
by calling FreeRTOS_TCPServerWork() again. */
|
||||
BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer )
|
||||
{
|
||||
BaseType_t xIndex;
|
||||
BaseType_t xResult = pdFALSE;
|
||||
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
|
||||
{
|
||||
if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
|
||||
{
|
||||
FreeRTOS_SignalSocket( pxServer->xServers[ xIndex ].xSocket );
|
||||
xResult = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return xResult;
|
||||
}
|
||||
|
||||
#endif /* ipconfigSUPPORT_SIGNALS */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigSUPPORT_SIGNALS != 0 )
|
||||
|
||||
/* Same as above: this function may be called from an ISR,
|
||||
for instance a GPIO interrupt. */
|
||||
BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken )
|
||||
{
|
||||
BaseType_t xIndex;
|
||||
BaseType_t xResult = pdFALSE;
|
||||
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
|
||||
{
|
||||
if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
|
||||
{
|
||||
FreeRTOS_SignalSocketFromISR( pxServer->xServers[ xIndex ].xSocket, pxHigherPriorityTaskWoken );
|
||||
xResult = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return xResult;
|
||||
}
|
||||
#endif /* ipconfigSUPPORT_SIGNALS */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* ipconfigUSE_TCP != 1 */
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_FTP_commands.h"
|
||||
|
||||
const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ] =
|
||||
{
|
||||
/* cmdLen cmdName[7] cmdType checkLogin checkNullArg */
|
||||
{ 4, "USER", ECMD_USER, pdFALSE, pdFALSE },
|
||||
{ 4, "PASS", ECMD_PASS, pdFALSE, pdFALSE },
|
||||
{ 4, "ACCT", ECMD_ACCT, pdTRUE, pdFALSE },
|
||||
{ 3, "CWD", ECMD_CWD, pdTRUE, pdTRUE },
|
||||
{ 4, "CDUP", ECMD_CDUP, pdTRUE, pdFALSE },
|
||||
{ 4, "SMNT", ECMD_SMNT, pdTRUE, pdFALSE },
|
||||
{ 4, "QUIT", ECMD_QUIT, pdTRUE, pdFALSE },
|
||||
{ 4, "REIN", ECMD_REIN, pdTRUE, pdFALSE },
|
||||
{ 4, "PORT", ECMD_PORT, pdTRUE, pdFALSE },
|
||||
{ 4, "PASV", ECMD_PASV, pdTRUE, pdFALSE },
|
||||
{ 4, "TYPE", ECMD_TYPE, pdTRUE, pdFALSE },
|
||||
{ 4, "STRU", ECMD_STRU, pdTRUE, pdFALSE },
|
||||
{ 4, "MODE", ECMD_MODE, pdTRUE, pdFALSE },
|
||||
{ 4, "RETR", ECMD_RETR, pdTRUE, pdTRUE },
|
||||
{ 4, "STOR", ECMD_STOR, pdTRUE, pdTRUE },
|
||||
{ 4, "STOU", ECMD_STOU, pdTRUE, pdFALSE },
|
||||
{ 4, "APPE", ECMD_APPE, pdTRUE, pdFALSE },
|
||||
{ 4, "ALLO", ECMD_ALLO, pdTRUE, pdFALSE },
|
||||
{ 4, "REST", ECMD_REST, pdTRUE, pdFALSE },
|
||||
{ 4, "RNFR", ECMD_RNFR, pdTRUE, pdTRUE },
|
||||
{ 4, "RNTO", ECMD_RNTO, pdTRUE, pdTRUE },
|
||||
{ 4, "ABOR", ECMD_ABOR, pdTRUE, pdFALSE },
|
||||
{ 4, "SIZE", ECMD_SIZE, pdTRUE, pdTRUE },
|
||||
{ 4, "MDTM", ECMD_MDTM, pdTRUE, pdTRUE },
|
||||
{ 4, "DELE", ECMD_DELE, pdTRUE, pdTRUE },
|
||||
{ 3, "RMD", ECMD_RMD, pdTRUE, pdTRUE },
|
||||
{ 3, "MKD", ECMD_MKD, pdTRUE, pdTRUE },
|
||||
{ 3, "PWD", ECMD_PWD, pdTRUE, pdFALSE },
|
||||
{ 4, "LIST", ECMD_LIST, pdTRUE, pdFALSE },
|
||||
{ 4, "NLST", ECMD_NLST, pdTRUE, pdFALSE },
|
||||
{ 4, "SITE", ECMD_SITE, pdTRUE, pdFALSE },
|
||||
{ 4, "SYST", ECMD_SYST, pdFALSE, pdFALSE },
|
||||
{ 4, "FEAT", ECMD_FEAT, pdFALSE, pdFALSE },
|
||||
{ 4, "STAT", ECMD_STAT, pdTRUE, pdFALSE },
|
||||
{ 4, "HELP", ECMD_HELP, pdFALSE, pdFALSE },
|
||||
{ 4, "NOOP", ECMD_NOOP, pdFALSE, pdFALSE },
|
||||
{ 4, "EMPT", ECMD_EMPTY, pdFALSE, pdFALSE },
|
||||
{ 4, "CLOS", ECMD_CLOSE, pdTRUE, pdFALSE },
|
||||
{ 4, "UNKN", ECMD_UNKNOWN, pdFALSE, pdFALSE },
|
||||
};
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#include "FreeRTOS_HTTP_commands.h"
|
||||
|
||||
const struct xWEB_COMMAND xWebCommands[ WEB_CMD_COUNT ] =
|
||||
{
|
||||
{ 3, "GET", ECMD_GET },
|
||||
{ 4, "HEAD", ECMD_HEAD },
|
||||
{ 4, "POST", ECMD_POST },
|
||||
{ 3, "PUT", ECMD_PUT },
|
||||
{ 6, "DELETE", ECMD_DELETE },
|
||||
{ 5, "TRACE", ECMD_TRACE },
|
||||
{ 7, "OPTIONS", ECMD_OPTIONS },
|
||||
{ 7, "CONNECT", ECMD_CONNECT },
|
||||
{ 5, "PATCH", ECMD_PATCH },
|
||||
{ 4, "UNKN", ECMD_UNK },
|
||||
};
|
||||
|
||||
const char *webCodename (int aCode)
|
||||
{
|
||||
switch (aCode) {
|
||||
case WEB_REPLY_OK: // = 200,
|
||||
return "OK";
|
||||
case WEB_NO_CONTENT: // 204
|
||||
return "No content";
|
||||
case WEB_BAD_REQUEST: // = 400,
|
||||
return "Bad request";
|
||||
case WEB_UNAUTHORIZED: // = 401,
|
||||
return "Authorization Required";
|
||||
case WEB_NOT_FOUND: // = 404,
|
||||
return "Not Found";
|
||||
case WEB_GONE: // = 410,
|
||||
return "Done";
|
||||
case WEB_PRECONDITION_FAILED: // = 412,
|
||||
return "Precondition Failed";
|
||||
case WEB_INTERNAL_SERVER_ERROR: // = 500,
|
||||
return "Internal Server Error";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
/* FreeRTOS Protocol includes. */
|
||||
#include "FreeRTOS_HTTP_commands.h"
|
||||
#include "FreeRTOS_TCP_server.h"
|
||||
#include "FreeRTOS_server_private.h"
|
||||
|
||||
/* FreeRTOS+FAT includes. */
|
||||
#include "ff_stdio.h"
|
||||
|
||||
#ifndef HTTP_SERVER_BACKLOG
|
||||
#define HTTP_SERVER_BACKLOG ( 12 )
|
||||
#endif
|
||||
|
||||
#ifndef USE_HTML_CHUNKS
|
||||
#define USE_HTML_CHUNKS ( 0 )
|
||||
#endif
|
||||
|
||||
#if !defined( ARRAY_SIZE )
|
||||
#define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )
|
||||
#endif
|
||||
|
||||
/* Some defines to make the code more readbale */
|
||||
#define pcCOMMAND_BUFFER pxClient->pxParent->pcCommandBuffer
|
||||
#define pcNEW_DIR pxClient->pxParent->pcNewDir
|
||||
#define pcFILE_BUFFER pxClient->pxParent->pcFileBuffer
|
||||
|
||||
#ifndef ipconfigHTTP_REQUEST_CHARACTER
|
||||
#define ipconfigHTTP_REQUEST_CHARACTER '?'
|
||||
#endif
|
||||
|
||||
/*_RB_ Need comment block, although fairly self evident. */
|
||||
static void prvFileClose( HTTPClient_t *pxClient );
|
||||
static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex );
|
||||
static const char *pcGetContentsType( const char *apFname );
|
||||
static BaseType_t prvOpenURL( HTTPClient_t *pxClient );
|
||||
static BaseType_t prvSendFile( HTTPClient_t *pxClient );
|
||||
static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode );
|
||||
|
||||
static const char pcEmptyString[1] = { '\0' };
|
||||
|
||||
typedef struct xTYPE_COUPLE
|
||||
{
|
||||
const char *pcExtension;
|
||||
const char *pcType;
|
||||
} TypeCouple_t;
|
||||
|
||||
static TypeCouple_t pxTypeCouples[ ] =
|
||||
{
|
||||
{ "html", "text/html" },
|
||||
{ "css", "text/css" },
|
||||
{ "js", "text/javascript" },
|
||||
{ "png", "image/png" },
|
||||
{ "jpg", "image/jpeg" },
|
||||
{ "gif", "image/gif" },
|
||||
{ "txt", "text/plain" },
|
||||
{ "mp3", "audio/mpeg3" },
|
||||
{ "wav", "audio/wav" },
|
||||
{ "flac", "audio/ogg" },
|
||||
{ "pdf", "application/pdf" },
|
||||
{ "ttf", "application/x-font-ttf" },
|
||||
{ "ttc", "application/x-font-ttf" }
|
||||
};
|
||||
|
||||
void vHTTPClientDelete( TCPClient_t *pxTCPClient )
|
||||
{
|
||||
HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient;
|
||||
|
||||
/* This HTTP client stops, close / release all resources. */
|
||||
if( pxClient->xSocket != FREERTOS_NO_SOCKET )
|
||||
{
|
||||
FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_ALL );
|
||||
FreeRTOS_closesocket( pxClient->xSocket );
|
||||
pxClient->xSocket = FREERTOS_NO_SOCKET;
|
||||
}
|
||||
prvFileClose( pxClient );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvFileClose( HTTPClient_t *pxClient )
|
||||
{
|
||||
if( pxClient->pxFileHandle != NULL )
|
||||
{
|
||||
FreeRTOS_printf( ( "Closing file: %s\n", pxClient->pcCurrentFilename ) );
|
||||
ff_fclose( pxClient->pxFileHandle );
|
||||
pxClient->pxFileHandle = NULL;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode )
|
||||
{
|
||||
struct xTCP_SERVER *pxParent = pxClient->pxParent;
|
||||
BaseType_t xRc;
|
||||
|
||||
/* A normal command reply on the main socket (port 21). */
|
||||
char *pcBuffer = pxParent->pcFileBuffer;
|
||||
|
||||
xRc = snprintf( pcBuffer, sizeof( pxParent->pcFileBuffer ),
|
||||
"HTTP/1.1 %d %s\r\n"
|
||||
#if USE_HTML_CHUNKS
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
#endif
|
||||
"Content-Type: %s\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"%s\r\n",
|
||||
( int ) xCode,
|
||||
webCodename (xCode),
|
||||
pxParent->pcContentsType[0] ? pxParent->pcContentsType : "text/html",
|
||||
pxParent->pcExtraContents );
|
||||
|
||||
pxParent->pcContentsType[0] = '\0';
|
||||
pxParent->pcExtraContents[0] = '\0';
|
||||
|
||||
xRc = FreeRTOS_send( pxClient->xSocket, ( const void * ) pcBuffer, xRc, 0 );
|
||||
pxClient->bits.bReplySent = pdTRUE_UNSIGNED;
|
||||
|
||||
return xRc;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvSendFile( HTTPClient_t *pxClient )
|
||||
{
|
||||
size_t uxSpace;
|
||||
size_t uxCount;
|
||||
BaseType_t xRc = 0;
|
||||
|
||||
if( pxClient->bits.bReplySent == pdFALSE_UNSIGNED )
|
||||
{
|
||||
pxClient->bits.bReplySent = pdTRUE_UNSIGNED;
|
||||
|
||||
strcpy( pxClient->pxParent->pcContentsType, pcGetContentsType( pxClient->pcCurrentFilename ) );
|
||||
snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),
|
||||
"Content-Length: %d\r\n", ( int ) pxClient->uxBytesLeft );
|
||||
|
||||
/* "Requested file action OK". */
|
||||
xRc = prvSendReply( pxClient, WEB_REPLY_OK );
|
||||
}
|
||||
|
||||
if( xRc >= 0 ) do
|
||||
{
|
||||
uxSpace = FreeRTOS_tx_space( pxClient->xSocket );
|
||||
|
||||
if( pxClient->uxBytesLeft < uxSpace )
|
||||
{
|
||||
uxCount = pxClient->uxBytesLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
uxCount = uxSpace;
|
||||
}
|
||||
|
||||
if( uxCount > 0u )
|
||||
{
|
||||
if( uxCount > sizeof( pxClient->pxParent->pcFileBuffer ) )
|
||||
{
|
||||
uxCount = sizeof( pxClient->pxParent->pcFileBuffer );
|
||||
}
|
||||
ff_fread( pxClient->pxParent->pcFileBuffer, 1, uxCount, pxClient->pxFileHandle );
|
||||
pxClient->uxBytesLeft -= uxCount;
|
||||
|
||||
xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pxParent->pcFileBuffer, uxCount, 0 );
|
||||
if( xRc < 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while( uxCount > 0u );
|
||||
|
||||
if( pxClient->uxBytesLeft == 0u )
|
||||
{
|
||||
/* Writing is ready, no need for further 'eSELECT_WRITE' events. */
|
||||
FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
|
||||
prvFileClose( pxClient );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wake up the TCP task as soon as this socket may be written to. */
|
||||
FreeRTOS_FD_SET( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
|
||||
}
|
||||
|
||||
return xRc;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvOpenURL( HTTPClient_t *pxClient )
|
||||
{
|
||||
BaseType_t xRc;
|
||||
char pcSlash[ 2 ];
|
||||
|
||||
pxClient->bits.ulFlags = 0;
|
||||
|
||||
#if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )
|
||||
{
|
||||
if( strchr( pxClient->pcUrlData, ipconfigHTTP_REQUEST_CHARACTER ) != NULL )
|
||||
{
|
||||
size_t xResult;
|
||||
|
||||
xResult = uxApplicationHTTPHandleRequestHook( pxClient->pcUrlData, pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ) );
|
||||
if( xResult > 0 )
|
||||
{
|
||||
strcpy( pxClient->pxParent->pcContentsType, "text/html" );
|
||||
snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),
|
||||
"Content-Length: %d\r\n", ( int ) xResult );
|
||||
xRc = prvSendReply( pxClient, WEB_REPLY_OK ); /* "Requested file action OK" */
|
||||
if( xRc > 0 )
|
||||
{
|
||||
xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pcCurrentFilename, xResult, 0 );
|
||||
}
|
||||
/* Although against the coding standard of FreeRTOS, a return is
|
||||
done here to simplify this conditional code. */
|
||||
return xRc;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
|
||||
|
||||
if( pxClient->pcUrlData[ 0 ] != '/' )
|
||||
{
|
||||
/* Insert a slash before the file name. */
|
||||
pcSlash[ 0 ] = '/';
|
||||
pcSlash[ 1 ] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The browser provided a starting '/' already. */
|
||||
pcSlash[ 0 ] = '\0';
|
||||
}
|
||||
snprintf( pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ), "%s%s%s",
|
||||
pxClient->pcRootDir,
|
||||
pcSlash,
|
||||
pxClient->pcUrlData);
|
||||
|
||||
pxClient->pxFileHandle = ff_fopen( pxClient->pcCurrentFilename, "rb" );
|
||||
|
||||
FreeRTOS_printf( ( "Open file '%s': %s\n", pxClient->pcCurrentFilename,
|
||||
pxClient->pxFileHandle != NULL ? "Ok" : strerror( stdioGET_ERRNO() ) ) );
|
||||
|
||||
if( pxClient->pxFileHandle == NULL )
|
||||
{
|
||||
/* "404 File not found". */
|
||||
xRc = prvSendReply( pxClient, WEB_NOT_FOUND );
|
||||
}
|
||||
else
|
||||
{
|
||||
pxClient->uxBytesLeft = ( size_t ) pxClient->pxFileHandle->ulFileSize;
|
||||
xRc = prvSendFile( pxClient );
|
||||
}
|
||||
|
||||
return xRc;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex )
|
||||
{
|
||||
BaseType_t xResult = 0;
|
||||
|
||||
/* A new command has been received. Process it. */
|
||||
switch( xIndex )
|
||||
{
|
||||
case ECMD_GET:
|
||||
xResult = prvOpenURL( pxClient );
|
||||
break;
|
||||
|
||||
case ECMD_HEAD:
|
||||
case ECMD_POST:
|
||||
case ECMD_PUT:
|
||||
case ECMD_DELETE:
|
||||
case ECMD_TRACE:
|
||||
case ECMD_OPTIONS:
|
||||
case ECMD_CONNECT:
|
||||
case ECMD_PATCH:
|
||||
case ECMD_UNK:
|
||||
{
|
||||
FreeRTOS_printf( ( "prvProcessCmd: Not implemented: %s\n",
|
||||
xWebCommands[xIndex].pcCommandName ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return xResult;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xHTTPClientWork( TCPClient_t *pxTCPClient )
|
||||
{
|
||||
BaseType_t xRc;
|
||||
HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient;
|
||||
|
||||
if( pxClient->pxFileHandle != NULL )
|
||||
{
|
||||
prvSendFile( pxClient );
|
||||
}
|
||||
|
||||
xRc = FreeRTOS_recv( pxClient->xSocket, ( void * )pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), 0 );
|
||||
|
||||
if( xRc > 0 )
|
||||
{
|
||||
BaseType_t xIndex;
|
||||
const char *pcEndOfCmd;
|
||||
const struct xWEB_COMMAND *curCmd;
|
||||
char *pcBuffer = pcCOMMAND_BUFFER;
|
||||
|
||||
if( xRc < ( BaseType_t ) sizeof( pcCOMMAND_BUFFER ) )
|
||||
{
|
||||
pcBuffer[ xRc ] = '\0';
|
||||
}
|
||||
while( xRc && ( pcBuffer[ xRc - 1 ] == 13 || pcBuffer[ xRc - 1 ] == 10 ) )
|
||||
{
|
||||
pcBuffer[ --xRc ] = '\0';
|
||||
}
|
||||
pcEndOfCmd = pcBuffer + xRc;
|
||||
|
||||
curCmd = xWebCommands;
|
||||
|
||||
/* Pointing to "/index.html HTTP/1.1". */
|
||||
pxClient->pcUrlData = pcBuffer;
|
||||
|
||||
/* Pointing to "HTTP/1.1". */
|
||||
pxClient->pcRestData = pcEmptyString;
|
||||
|
||||
/* Last entry is "ECMD_UNK". */
|
||||
for( xIndex = 0; xIndex < WEB_CMD_COUNT - 1; xIndex++, curCmd++ )
|
||||
{
|
||||
BaseType_t xLength;
|
||||
|
||||
xLength = curCmd->xCommandLength;
|
||||
if( ( xRc >= xLength ) && ( memcmp( curCmd->pcCommandName, pcBuffer, xLength ) == 0 ) )
|
||||
{
|
||||
char *pcLastPtr;
|
||||
|
||||
pxClient->pcUrlData += xLength + 1;
|
||||
for( pcLastPtr = (char *)pxClient->pcUrlData; pcLastPtr < pcEndOfCmd; pcLastPtr++ )
|
||||
{
|
||||
char ch = *pcLastPtr;
|
||||
if( ( ch == '\0' ) || ( strchr( "\n\r \t", ch ) != NULL ) )
|
||||
{
|
||||
*pcLastPtr = '\0';
|
||||
pxClient->pcRestData = pcLastPtr + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( xIndex < ( WEB_CMD_COUNT - 1 ) )
|
||||
{
|
||||
xRc = prvProcessCmd( pxClient, xIndex );
|
||||
}
|
||||
}
|
||||
else if( xRc < 0 )
|
||||
{
|
||||
/* The connection will be closed and the client will be deleted. */
|
||||
FreeRTOS_printf( ( "xHTTPClientWork: rc = %ld\n", xRc ) );
|
||||
}
|
||||
return xRc;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static const char *pcGetContentsType (const char *apFname)
|
||||
{
|
||||
const char *slash = NULL;
|
||||
const char *dot = NULL;
|
||||
const char *ptr;
|
||||
const char *pcResult = "text/html";
|
||||
BaseType_t x;
|
||||
|
||||
for( ptr = apFname; *ptr; ptr++ )
|
||||
{
|
||||
if (*ptr == '.') dot = ptr;
|
||||
if (*ptr == '/') slash = ptr;
|
||||
}
|
||||
if( dot > slash )
|
||||
{
|
||||
dot++;
|
||||
for( x = 0; x < ARRAY_SIZE( pxTypeCouples ); x++ )
|
||||
{
|
||||
if( strcasecmp( dot, pxTypeCouples[ x ].pcExtension ) == 0 )
|
||||
{
|
||||
pcResult = pxTypeCouples[ x ].pcType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pcResult;
|
||||
}
|
||||
|
||||
472
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/NTP/NTPDemo.c
Normal file
472
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/NTP/NTPDemo.c
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* NTPDemo.c
|
||||
*
|
||||
* An example of how to lookup a domain using DNS
|
||||
* And also how to send and receive UDP messages to get the NTP time
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "FreeRTOS_Stream_Buffer.h"
|
||||
|
||||
/* Use the date & time functions from +FAT. */
|
||||
#include "ff_time.h"
|
||||
|
||||
#include "NTPDemo.h"
|
||||
#include "ntpClient.h"
|
||||
|
||||
#include "date_and_time.h"
|
||||
|
||||
enum EStatus {
|
||||
EStatusLookup,
|
||||
EStatusAsking,
|
||||
EStatusPause,
|
||||
EStatusFailed,
|
||||
};
|
||||
|
||||
static struct SNtpPacket xNTPPacket;
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS == 0 )
|
||||
static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ];
|
||||
#endif
|
||||
|
||||
static enum EStatus xStatus = EStatusLookup;
|
||||
|
||||
static const char *pcTimeServers[] = {
|
||||
"0.asia.pool.ntp.org",
|
||||
"0.europe.pool.ntp.org",
|
||||
"0.id.pool.ntp.org",
|
||||
"0.south-america.pool.ntp.org",
|
||||
"0.oceania.pool.ntp.org",
|
||||
"0.north-america.pool.ntp.org"
|
||||
};
|
||||
|
||||
static SemaphoreHandle_t xNTPWakeupSem = NULL;
|
||||
static uint32_t ulIPAddressFound;
|
||||
static Socket_t xUDPSocket = NULL;
|
||||
static TaskHandle_t xNTPTaskhandle = NULL;
|
||||
static TickType_t uxSendTime;
|
||||
|
||||
static void prvNTPTask( void *pvParameters );
|
||||
|
||||
static void vSignalTask( void )
|
||||
{
|
||||
#if( ipconfigUSE_CALLBACKS == 0 )
|
||||
if( xUDPSocket != NULL )
|
||||
{
|
||||
/* Send a signal to the socket so that the
|
||||
FreeRTOS_recvfrom will get interrupted. */
|
||||
FreeRTOS_SignalSocket( xUDPSocket );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if( xNTPWakeupSem != NULL )
|
||||
{
|
||||
xSemaphoreGive( xNTPWakeupSem );
|
||||
}
|
||||
}
|
||||
|
||||
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )
|
||||
{
|
||||
/* The only public function in this module: start a task to contact
|
||||
some NTP server. */
|
||||
|
||||
if( xNTPTaskhandle != NULL )
|
||||
{
|
||||
switch( xStatus )
|
||||
{
|
||||
case EStatusPause:
|
||||
xStatus = EStatusAsking;
|
||||
vSignalTask();
|
||||
break;
|
||||
case EStatusLookup:
|
||||
FreeRTOS_printf( ( "NTP looking up server\n" ) );
|
||||
break;
|
||||
case EStatusAsking:
|
||||
FreeRTOS_printf( ( "NTP still asking\n" ) );
|
||||
break;
|
||||
case EStatusFailed:
|
||||
FreeRTOS_printf( ( "NTP failed somehow\n" ) );
|
||||
ulIPAddressFound = 0ul;
|
||||
xStatus = EStatusLookup;
|
||||
vSignalTask();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xUDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
|
||||
if( xUDPSocket != NULL )
|
||||
{
|
||||
struct freertos_sockaddr xAddress;
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 );
|
||||
#else
|
||||
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );
|
||||
#endif
|
||||
|
||||
xAddress.sin_addr = 0ul;
|
||||
xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
|
||||
|
||||
FreeRTOS_bind( xUDPSocket, &xAddress, sizeof( xAddress ) );
|
||||
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
|
||||
xTaskCreate( prvNTPTask, /* The function that implements the task. */
|
||||
( const char * ) "NTP client", /* Just a text name for the task to aid debugging. */
|
||||
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
|
||||
NULL, /* The task parameter, not used in this case. */
|
||||
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
|
||||
&xNTPTaskhandle ); /* The task handle. */
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeRTOS_printf( ( "Creating socket failed\n" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vDNS_callback( const char *pcName, void *pvSearchID, uint32_t ulIPAddress )
|
||||
{
|
||||
char pcBuf[16];
|
||||
|
||||
/* The DNS lookup has a result, or it has reached the time-out. */
|
||||
FreeRTOS_inet_ntoa( ulIPAddress, pcBuf );
|
||||
FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) );
|
||||
if( ulIPAddressFound == 0ul )
|
||||
{
|
||||
ulIPAddressFound = ulIPAddress;
|
||||
}
|
||||
/* For testing: in case DNS doen't respond, still try some NTP server
|
||||
with a known IP-address. */
|
||||
if( ulIPAddressFound == 0ul )
|
||||
{
|
||||
ulIPAddressFound = FreeRTOS_inet_addr_quick( 184, 105, 182, 7 );
|
||||
/* ulIPAddressFound = FreeRTOS_inet_addr_quick( 103, 242, 70, 4 ); */
|
||||
}
|
||||
xStatus = EStatusAsking;
|
||||
|
||||
vSignalTask();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSwapFields( struct SNtpPacket *pxPacket)
|
||||
{
|
||||
/* NTP messages are big-endian */
|
||||
pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay );
|
||||
pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion );
|
||||
|
||||
pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds );
|
||||
pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction );
|
||||
|
||||
pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds );
|
||||
pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction );
|
||||
|
||||
pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds );
|
||||
pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction );
|
||||
|
||||
pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds );
|
||||
pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvNTPPacketInit( )
|
||||
{
|
||||
memset (&xNTPPacket, '\0', sizeof( xNTPPacket ) );
|
||||
|
||||
xNTPPacket.flags = 0xDB; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */
|
||||
xNTPPacket.poll = 10; /* 10 means 1 << 10 = 1024 seconds */
|
||||
xNTPPacket.precision = 0xFA; /* = 250 = 0.015625 seconds */
|
||||
xNTPPacket.rootDelay = 0x5D2E; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */
|
||||
xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912 seconds */
|
||||
|
||||
/* use the recorded NTP time */
|
||||
time_t uxSecs = FreeRTOS_time( NULL );/* apTime may be NULL, returns seconds */
|
||||
|
||||
xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */
|
||||
xNTPPacket.transmitTimestamp.seconds = uxSecs + 3;
|
||||
|
||||
/* Transform the contents of the fields from native to big endian. */
|
||||
prvSwapFields( &xNTPPacket );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvReadTime( struct SNtpPacket * pxPacket )
|
||||
{
|
||||
FF_TimeStruct_t xTimeStruct;
|
||||
time_t uxPreviousSeconds;
|
||||
time_t uxPreviousMS;
|
||||
|
||||
time_t uxCurrentSeconds;
|
||||
time_t uxCurrentMS;
|
||||
|
||||
const char *pcTimeUnit;
|
||||
int32_t ilDiff;
|
||||
TickType_t uxTravelTime;
|
||||
|
||||
uxTravelTime = xTaskGetTickCount() - uxSendTime;
|
||||
|
||||
/* Transform the contents of the fields from big to native endian. */
|
||||
prvSwapFields( pxPacket );
|
||||
|
||||
uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970;
|
||||
uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967;
|
||||
uxCurrentSeconds += uxCurrentMS / 1000;
|
||||
uxCurrentMS = uxCurrentMS % 1000;
|
||||
|
||||
// Get the last time recorded
|
||||
uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS );
|
||||
|
||||
// Set the new time with precision in msec. */
|
||||
FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS );
|
||||
|
||||
if( uxCurrentSeconds >= uxPreviousSeconds )
|
||||
{
|
||||
ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds );
|
||||
}
|
||||
else
|
||||
{
|
||||
ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds );
|
||||
}
|
||||
|
||||
if( ( ilDiff < -5 ) || ( ilDiff > 5 ) )
|
||||
{
|
||||
/* More than 5 seconds difference. */
|
||||
pcTimeUnit = "sec";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Less than or equal to 5 second difference. */
|
||||
pcTimeUnit = "ms";
|
||||
uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds;
|
||||
int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS;
|
||||
int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS;
|
||||
ilDiff = iCurMS - iPrevMS;
|
||||
}
|
||||
uxCurrentSeconds -= iTimeZone;
|
||||
|
||||
FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct );
|
||||
|
||||
/*
|
||||
378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms)
|
||||
379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms)
|
||||
*/
|
||||
|
||||
FreeRTOS_printf( ("NTP time: %d/%d/%02d %2d:%02d:%02d.%03u Diff %d %s (%lu ms)\n",
|
||||
xTimeStruct.tm_mday,
|
||||
xTimeStruct.tm_mon + 1,
|
||||
xTimeStruct.tm_year + 1900,
|
||||
xTimeStruct.tm_hour,
|
||||
xTimeStruct.tm_min,
|
||||
xTimeStruct.tm_sec,
|
||||
( unsigned )uxCurrentMS,
|
||||
( unsigned )ilDiff,
|
||||
pcTimeUnit,
|
||||
uxTravelTime ) );
|
||||
|
||||
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */
|
||||
( void ) pcTimeUnit;
|
||||
( void ) uxTravelTime;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
|
||||
static BaseType_t xOnUDPReceive( Socket_t xSocket, void * pvData, size_t xLength,
|
||||
const struct freertos_sockaddr *pxFrom, const struct freertos_sockaddr *pxDest )
|
||||
{
|
||||
if( xLength >= sizeof( xNTPPacket ) )
|
||||
{
|
||||
prvReadTime( ( struct SNtpPacket *)pvData );
|
||||
if( xStatus != EStatusPause )
|
||||
{
|
||||
xStatus = EStatusPause;
|
||||
}
|
||||
}
|
||||
vSignalTask();
|
||||
/* Tell the driver not to store the RX data */
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* ipconfigUSE_CALLBACKS != 0 */
|
||||
|
||||
static void prvNTPTask( void *pvParameters )
|
||||
{
|
||||
BaseType_t xServerIndex = 3;
|
||||
struct freertos_sockaddr xAddress;
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
F_TCP_UDP_Handler_t xHandler;
|
||||
#endif /* ipconfigUSE_CALLBACKS != 0 */
|
||||
|
||||
xStatus = EStatusLookup;
|
||||
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 )
|
||||
{
|
||||
xNTPWakeupSem = xSemaphoreCreateBinary();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
{
|
||||
memset( &xHandler, '\0', sizeof( xHandler ) );
|
||||
xHandler.pxOnUDPReceive = xOnUDPReceive;
|
||||
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );
|
||||
}
|
||||
#endif
|
||||
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
|
||||
{
|
||||
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) );
|
||||
}
|
||||
#endif
|
||||
for( ; ; )
|
||||
{
|
||||
switch( xStatus )
|
||||
{
|
||||
case EStatusLookup:
|
||||
if( ( ulIPAddressFound == 0ul ) || ( ulIPAddressFound == ~0ul ) )
|
||||
{
|
||||
if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) )
|
||||
{
|
||||
xServerIndex = 0;
|
||||
}
|
||||
FreeRTOS_printf( ( "Looking up server '%s'\n", pcTimeServers[ xServerIndex ] ) );
|
||||
FreeRTOS_gethostbyname_a( pcTimeServers[ xServerIndex ], vDNS_callback, (void *)NULL, 1200 );
|
||||
}
|
||||
else
|
||||
{
|
||||
xStatus = EStatusAsking;
|
||||
}
|
||||
break;
|
||||
|
||||
case EStatusAsking:
|
||||
{
|
||||
char pcBuf[16];
|
||||
|
||||
prvNTPPacketInit( );
|
||||
xAddress.sin_addr = ulIPAddressFound;
|
||||
xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
|
||||
|
||||
FreeRTOS_inet_ntoa( xAddress.sin_addr, pcBuf );
|
||||
FreeRTOS_printf( ( "Sending UDP message to %s:%u\n",
|
||||
pcBuf,
|
||||
FreeRTOS_ntohs( xAddress.sin_port ) ) );
|
||||
|
||||
uxSendTime = xTaskGetTickCount( );
|
||||
FreeRTOS_sendto( xUDPSocket, ( void * )&xNTPPacket, sizeof( xNTPPacket ), 0, &xAddress, sizeof( xAddress ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case EStatusPause:
|
||||
break;
|
||||
|
||||
case EStatusFailed:
|
||||
break;
|
||||
}
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
{
|
||||
xSemaphoreTake( xNTPWakeupSem, 5000 );
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint32_t xAddressSize;
|
||||
BaseType_t xReturned;
|
||||
|
||||
xAddressSize = sizeof( xAddress );
|
||||
xReturned = FreeRTOS_recvfrom( xUDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize );
|
||||
switch( xReturned )
|
||||
{
|
||||
case 0:
|
||||
case -pdFREERTOS_ERRNO_EAGAIN:
|
||||
case -pdFREERTOS_ERRNO_EINTR:
|
||||
break;
|
||||
default:
|
||||
if( xReturned < sizeof( xNTPPacket ) )
|
||||
{
|
||||
FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
prvReadTime( ( struct SNtpPacket *)cRecvBuffer );
|
||||
if( xStatus != EStatusPause )
|
||||
{
|
||||
xStatus = EStatusPause;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __FTPCMD_H__
|
||||
|
||||
#define __FTPCMD_H__
|
||||
|
||||
#define REPL_110 "110 Restart marker reply.\r\n"
|
||||
#define REPL_120 "120 Try again in 2 minutes.\r\n"
|
||||
#define REPL_125 "125 Data connection already open; transfer starting.\r\n"
|
||||
#define REPL_150 "150 File status okay; about to open data connection.\r\n"
|
||||
#define REPL_200 "200 NOOP command successful.\r\n"
|
||||
#define REPL_200_PROGRESS "200 NOOP: data transfer in progress.\r\n"
|
||||
#define REPL_202 "202 Command not implemented, superfluous at this site.\r\n"
|
||||
#define REPL_211 "221 System status, or system help reply.\r\n"
|
||||
#define REPL_211_STATUS "221-status of %s.\r\n"
|
||||
#define REPL_211_END "221 End of status.\r\n"
|
||||
#define REPL_212 "212 Directory status.\r\n"
|
||||
#define REPL_213 "213 File status.\r\n"
|
||||
#define REPL_214 "214 Help message.\r\n"
|
||||
#define REPL_214_END "214 End Help message.\r\n"
|
||||
#define REPL_215 "215 %s system type.\r\n"
|
||||
#define REPL_220 "220 Service ready for new user.\r\n"
|
||||
#define REPL_221 "221 Service closing control connection.\r\n"
|
||||
#define REPL_225 "225 Data connection open; no transfer in progress.\r\n"
|
||||
#define REPL_226 "226 Closing data connection.\r\n"
|
||||
#define REPL_227 "227 Entering Passive Mode (%s,%s,%s,%s,%s,%s).\r\n"
|
||||
#define REPL_227_D "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n"
|
||||
#define REPL_230 "230 User logged in, proceed.\r\n"
|
||||
#define REPL_250 "250 Requested file action okay, completed.\r\n"
|
||||
#define REPL_257 "257 %s created.\r\n"
|
||||
// #define REPL_257_PWD "257 \"%s\" is current working dir.\r\n"
|
||||
#define REPL_257_PWD "257 \"%s\"\r\n"
|
||||
#define REPL_331 "331 Only anonymous user is accepted.\r\n"
|
||||
#define REPL_331_ANON "331 Anonymous login okay\r\n"
|
||||
#define REPL_332 "332 Need account for login.\r\n"
|
||||
#define REPL_350 "350 Requested file action pending further information.\r\n"
|
||||
#define REPL_421 "421 Service not available, closing control connection.\r\n"
|
||||
#define REPL_425 "425 Can't open data connection.\r\n"
|
||||
#define REPL_426 "426 Connection closed; transfer aborted.\r\n"
|
||||
#define REPL_450 "450 Requested file action not taken.\r\n"
|
||||
#define REPL_451 "451 Requested action aborted. Local error in processing.\r\n"
|
||||
#define REPL_452 "452 Requested action not taken.\r\n"
|
||||
#define REPL_500 "500 Syntax error, command unrecognized.\r\n"
|
||||
#define REPL_501 "501 Syntax error in parameters or arguments.\r\n"
|
||||
#define REPL_502 "502 Command not implemented.\r\n"
|
||||
#define REPL_503 "503 Bad sequence of commands.\r\n"
|
||||
#define REPL_504 "504 Command not implemented for that parameter.\r\n"
|
||||
#define REPL_530 "530 Not logged in.\r\n"
|
||||
#define REPL_532 "532 Need account for storing files.\r\n"
|
||||
#define REPL_550 "550 Requested action not taken.\r\n"
|
||||
#define REPL_551 "551 Requested action aborted. Page type unknown.\r\n"
|
||||
#define REPL_552 "552 Requested file action aborted.\r\n"
|
||||
#define REPL_553 "553 Requested action not taken.\r\n"
|
||||
#define REPL_553_READ_ONLY "553 Read-only file-system.\r\n"
|
||||
|
||||
enum EFTPCommand {
|
||||
ECMD_USER,
|
||||
ECMD_PASS,
|
||||
ECMD_ACCT,
|
||||
ECMD_CWD,
|
||||
ECMD_CDUP,
|
||||
ECMD_SMNT,
|
||||
ECMD_QUIT,
|
||||
ECMD_REIN,
|
||||
ECMD_PORT,
|
||||
ECMD_PASV,
|
||||
ECMD_TYPE,
|
||||
ECMD_STRU,
|
||||
ECMD_MODE,
|
||||
ECMD_RETR,
|
||||
ECMD_STOR,
|
||||
ECMD_STOU,
|
||||
ECMD_APPE,
|
||||
ECMD_ALLO,
|
||||
ECMD_REST,
|
||||
ECMD_RNFR,
|
||||
ECMD_RNTO,
|
||||
ECMD_ABOR,
|
||||
ECMD_SIZE,
|
||||
ECMD_MDTM,
|
||||
ECMD_DELE,
|
||||
ECMD_RMD,
|
||||
ECMD_MKD,
|
||||
ECMD_PWD,
|
||||
ECMD_LIST,
|
||||
ECMD_NLST,
|
||||
ECMD_SITE,
|
||||
ECMD_SYST,
|
||||
ECMD_FEAT,
|
||||
ECMD_STAT,
|
||||
ECMD_HELP,
|
||||
ECMD_NOOP,
|
||||
ECMD_EMPTY,
|
||||
ECMD_CLOSE,
|
||||
ECMD_UNKNOWN,
|
||||
};
|
||||
|
||||
typedef struct xFTP_COMMAND {
|
||||
BaseType_t xCommandLength;
|
||||
const char pcCommandName[7];
|
||||
const unsigned char ucCommandType;
|
||||
const unsigned char checkLogin;
|
||||
const unsigned char checkNullArg;
|
||||
} FTPCommand_t;
|
||||
|
||||
#define FTP_CMD_COUNT (ECMD_UNKNOWN+1)
|
||||
|
||||
extern const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ];
|
||||
|
||||
#endif // __FTPCMD_H__
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
#ifndef FREERTOS_HTTP_COMMANDS_H
|
||||
#define FREERTOS_HTTP_COMMANDS_H
|
||||
|
||||
enum {
|
||||
WEB_REPLY_OK = 200,
|
||||
WEB_NO_CONTENT = 204,
|
||||
WEB_BAD_REQUEST = 400,
|
||||
WEB_UNAUTHORIZED = 401,
|
||||
WEB_NOT_FOUND = 404,
|
||||
WEB_GONE = 410,
|
||||
WEB_PRECONDITION_FAILED = 412,
|
||||
WEB_INTERNAL_SERVER_ERROR = 500,
|
||||
};
|
||||
|
||||
enum EWebCommand {
|
||||
ECMD_GET,
|
||||
ECMD_HEAD,
|
||||
ECMD_POST,
|
||||
ECMD_PUT,
|
||||
ECMD_DELETE,
|
||||
ECMD_TRACE,
|
||||
ECMD_OPTIONS,
|
||||
ECMD_CONNECT,
|
||||
ECMD_PATCH,
|
||||
ECMD_UNK,
|
||||
};
|
||||
|
||||
struct xWEB_COMMAND
|
||||
{
|
||||
BaseType_t xCommandLength;
|
||||
const char *pcCommandName;
|
||||
const unsigned char ucCommandType;
|
||||
};
|
||||
|
||||
#define WEB_CMD_COUNT (ECMD_UNK+1)
|
||||
|
||||
extern const struct xWEB_COMMAND xWebCommands[WEB_CMD_COUNT];
|
||||
|
||||
extern const char *webCodename (int aCode);
|
||||
|
||||
#endif /* FREERTOS_HTTP_COMMANDS_H */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Some code which is common to TCP servers like HTTP en FTP
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_TCP_SERVER_H
|
||||
#define FREERTOS_TCP_SERVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef FTP_SERVER_USES_RELATIVE_DIRECTORY
|
||||
#define FTP_SERVER_USES_RELATIVE_DIRECTORY 0
|
||||
#endif
|
||||
|
||||
enum eSERVER_TYPE
|
||||
{
|
||||
eSERVER_NONE,
|
||||
eSERVER_HTTP,
|
||||
eSERVER_FTP,
|
||||
};
|
||||
|
||||
struct xFTP_CLIENT;
|
||||
|
||||
#if( ipconfigFTP_HAS_RECEIVED_HOOK != 0 )
|
||||
extern void vApplicationFTPReceivedHook( const char *pcFileName, uint32_t ulSize, struct xFTP_CLIENT *pxFTPClient );
|
||||
extern void vFTPReplyMessage( struct xFTP_CLIENT *pxFTPClient, const char *pcMessage );
|
||||
#endif /* ipconfigFTP_HAS_RECEIVED_HOOK != 0 */
|
||||
|
||||
#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )
|
||||
/*
|
||||
* Function is called when a user name has been submitted.
|
||||
* The function may return a string such as: "331 Please enter your password"
|
||||
* or return NULL to use the default reply.
|
||||
*/
|
||||
extern const char *pcApplicationFTPUserHook( const char *pcUserName );
|
||||
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
|
||||
|
||||
#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )
|
||||
/*
|
||||
* Function is called when a password was received.
|
||||
* Return positive value to allow the user
|
||||
*/
|
||||
extern BaseType_t xApplicationFTPPasswordHook( const char *pcUserName, const char *pcPassword );
|
||||
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
|
||||
|
||||
#if( ipconfigFTP_HAS_USER_PROPERTIES_HOOK != 0 )
|
||||
/*
|
||||
* The FTP server is asking for user-specific properties
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t usPortNumber; /* For reference only. Host-endian. */
|
||||
const char *pcRootDir;
|
||||
BaseType_t xReadOnly;
|
||||
}
|
||||
FTPUserProperties_t;
|
||||
extern void vApplicationFTPUserPropertiesHook( const char *pcUserName, FTPUserProperties_t *pxProperties );
|
||||
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
|
||||
|
||||
#if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )
|
||||
/*
|
||||
* A GET request is received containing a special character,
|
||||
* usually a question mark.
|
||||
* const char *pcURLData; // A request, e.g. "/request?limit=75"
|
||||
* char *pcBuffer; // Here the answer can be written
|
||||
* size_t uxBufferLength; // Size of the buffer
|
||||
*
|
||||
*/
|
||||
extern size_t uxApplicationHTTPHandleRequestHook( const char *pcURLData, char *pcBuffer, size_t uxBufferLength );
|
||||
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
|
||||
|
||||
struct xSERVER_CONFIG
|
||||
{
|
||||
enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */
|
||||
BaseType_t xPortNumber; /* e.g. 80, 8080, 21 */
|
||||
BaseType_t xBackLog; /* e.g. 10, maximum number of connected TCP clients */
|
||||
const char * const pcRootDir; /* Treat this directory as the root directory */
|
||||
};
|
||||
|
||||
struct xTCP_SERVER;
|
||||
typedef struct xTCP_SERVER TCPServer_t;
|
||||
|
||||
TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount );
|
||||
void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime );
|
||||
|
||||
#if( ipconfigSUPPORT_SIGNALS != 0 )
|
||||
/* FreeRTOS_TCPServerWork() calls select().
|
||||
The two functions below provide a possibility to interrupt
|
||||
the call to select(). After the interruption, resume
|
||||
by calling FreeRTOS_TCPServerWork() again. */
|
||||
BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer );
|
||||
BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_TCP_SERVER_H */
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
|
||||
* Authors include Hein Tibosch and Richard Barry
|
||||
*
|
||||
*******************************************************************************
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*** ***
|
||||
*** ***
|
||||
*** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
|
||||
*** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
|
||||
*** download): ***
|
||||
*** ***
|
||||
*** FreeRTOS+TCP is functional and has been used in commercial products ***
|
||||
*** for some time. Be aware however that we are still refining its ***
|
||||
*** design, the source code does not yet quite conform to the strict ***
|
||||
*** coding and style standards mandated by Real Time Engineers ltd., and ***
|
||||
*** the documentation and testing is not necessarily complete. ***
|
||||
*** ***
|
||||
*** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
|
||||
*** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
|
||||
*** the sole discretion of Real Time Engineers Ltd., be offered versions ***
|
||||
*** under a license other than that described below. ***
|
||||
*** ***
|
||||
*** ***
|
||||
***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
|
||||
*******************************************************************************
|
||||
*
|
||||
* FreeRTOS+TCP can be used under two different free open source licenses. The
|
||||
* license that applies is dependent on the processor on which FreeRTOS+TCP is
|
||||
* executed, as follows:
|
||||
*
|
||||
* If FreeRTOS+TCP is executed on one of the processors listed under the Special
|
||||
* License Arrangements heading of the FreeRTOS+TCP license information web
|
||||
* page, then it can be used under the terms of the FreeRTOS Open Source
|
||||
* License. If FreeRTOS+TCP is used on any other processor, then it can be used
|
||||
* under the terms of the GNU General Public License V2. Links to the relevant
|
||||
* licenses follow:
|
||||
*
|
||||
* The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
|
||||
* The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
|
||||
* The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
|
||||
*
|
||||
* FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
|
||||
* use FreeRTOS+TCP unless you agree that you use the software 'as is'.
|
||||
* FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
|
||||
* implied, expressed, or statutory.
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://www.FreeRTOS.org/plus
|
||||
* http://www.FreeRTOS.org/labs
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Some code which is common to TCP servers like HTTP and FTP
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_SERVER_PRIVATE_H
|
||||
#define FREERTOS_SERVER_PRIVATE_H
|
||||
|
||||
#define FREERTOS_NO_SOCKET NULL
|
||||
|
||||
/* FreeRTOS+FAT */
|
||||
#include "ff_stdio.h"
|
||||
|
||||
/* Each HTTP server has 1, at most 2 sockets */
|
||||
#define HTTP_SOCKET_COUNT 2
|
||||
|
||||
/*
|
||||
* ipconfigTCP_COMMAND_BUFFER_SIZE sets the size of:
|
||||
* pcCommandBuffer': a buffer to receive and send TCP commands
|
||||
*
|
||||
* ipconfigTCP_FILE_BUFFER_SIZE sets the size of:
|
||||
* pcFileBuffer' : a buffer to access the file system: read or write data.
|
||||
*
|
||||
* The buffers are both used for FTP as well as HTTP.
|
||||
*/
|
||||
|
||||
#ifndef ipconfigTCP_COMMAND_BUFFER_SIZE
|
||||
#define ipconfigTCP_COMMAND_BUFFER_SIZE ( 2048 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigTCP_FILE_BUFFER_SIZE
|
||||
#define ipconfigTCP_FILE_BUFFER_SIZE ( 2048 )
|
||||
#endif
|
||||
|
||||
struct xTCP_CLIENT;
|
||||
|
||||
typedef BaseType_t ( * FTCPWorkFunction ) ( struct xTCP_CLIENT * /* pxClient */ );
|
||||
typedef void ( * FTCPDeleteFunction ) ( struct xTCP_CLIENT * /* pxClient */ );
|
||||
|
||||
#define TCP_CLIENT_FIELDS \
|
||||
enum eSERVER_TYPE eType; \
|
||||
struct xTCP_SERVER *pxParent; \
|
||||
Socket_t xSocket; \
|
||||
const char *pcRootDir; \
|
||||
FTCPWorkFunction fWorkFunction; \
|
||||
FTCPDeleteFunction fDeleteFunction; \
|
||||
struct xTCP_CLIENT *pxNextClient
|
||||
|
||||
typedef struct xTCP_CLIENT
|
||||
{
|
||||
/* This define contains fields which must come first within each of the client structs */
|
||||
TCP_CLIENT_FIELDS;
|
||||
/* --- Keep at the top --- */
|
||||
|
||||
} TCPClient_t;
|
||||
|
||||
struct xHTTP_CLIENT
|
||||
{
|
||||
/* This define contains fields which must come first within each of the client structs */
|
||||
TCP_CLIENT_FIELDS;
|
||||
/* --- Keep at the top --- */
|
||||
|
||||
const char *pcUrlData;
|
||||
const char *pcRestData;
|
||||
char pcCurrentFilename[ ffconfigMAX_FILENAME ];
|
||||
size_t uxBytesLeft;
|
||||
FF_FILE *pxFileHandle;
|
||||
union {
|
||||
struct {
|
||||
uint32_t
|
||||
bReplySent : 1;
|
||||
};
|
||||
uint32_t ulFlags;
|
||||
} bits;
|
||||
};
|
||||
|
||||
typedef struct xHTTP_CLIENT HTTPClient_t;
|
||||
|
||||
struct xFTP_CLIENT
|
||||
{
|
||||
/* This define contains fields which must come first within each of the client structs */
|
||||
TCP_CLIENT_FIELDS;
|
||||
/* --- Keep at the top --- */
|
||||
|
||||
uint32_t ulRestartOffset;
|
||||
uint32_t ulRecvBytes;
|
||||
size_t uxBytesLeft; /* Bytes left to send */
|
||||
uint32_t ulClientIP;
|
||||
TickType_t xStartTime;
|
||||
uint16_t usClientPort;
|
||||
Socket_t xTransferSocket;
|
||||
BaseType_t xTransType;
|
||||
BaseType_t xDirCount;
|
||||
FF_FindData_t xFindData;
|
||||
FF_FILE *pxReadHandle;
|
||||
FF_FILE *pxWriteHandle;
|
||||
char pcCurrentDir[ ffconfigMAX_FILENAME ];
|
||||
char pcFileName[ ffconfigMAX_FILENAME ];
|
||||
char pcConnectionAck[ 128 ];
|
||||
char pcClientAck[ 128 ];
|
||||
union {
|
||||
struct {
|
||||
uint32_t
|
||||
bHelloSent : 1,
|
||||
bLoggedIn : 1,
|
||||
bStatusUser : 1,
|
||||
bInRename : 1,
|
||||
bReadOnly : 1;
|
||||
};
|
||||
uint32_t ulFTPFlags;
|
||||
} bits;
|
||||
union {
|
||||
struct {
|
||||
uint32_t
|
||||
bIsListen : 1, /* pdTRUE for passive data connections (using list()). */
|
||||
bDirHasEntry : 1, /* pdTRUE if ff_findfirst() was successful. */
|
||||
bClientConnected : 1, /* pdTRUE after connect() or accept() has succeeded. */
|
||||
bEmptyFile : 1, /* pdTRUE if a connection-without-data was received. */
|
||||
bHadError : 1; /* pdTRUE if a transfer got aborted because of an error. */
|
||||
};
|
||||
uint32_t ulConnFlags;
|
||||
} bits1;
|
||||
};
|
||||
|
||||
typedef struct xFTP_CLIENT FTPClient_t;
|
||||
|
||||
BaseType_t xHTTPClientWork( TCPClient_t *pxClient );
|
||||
BaseType_t xFTPClientWork( TCPClient_t *pxClient );
|
||||
|
||||
void vHTTPClientDelete( TCPClient_t *pxClient );
|
||||
void vFTPClientDelete( TCPClient_t *pxClient );
|
||||
|
||||
BaseType_t xMakeAbsolute( struct xFTP_CLIENT *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName );
|
||||
BaseType_t xMakeRelative( FTPClient_t *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName );
|
||||
|
||||
struct xTCP_SERVER
|
||||
{
|
||||
SocketSet_t xSocketSet;
|
||||
/* A buffer to receive and send TCP commands, either HTTP of FTP. */
|
||||
char pcCommandBuffer[ ipconfigTCP_COMMAND_BUFFER_SIZE ];
|
||||
/* A buffer to access the file system: read or write data. */
|
||||
char pcFileBuffer[ ipconfigTCP_FILE_BUFFER_SIZE ];
|
||||
|
||||
#if( ipconfigUSE_FTP != 0 )
|
||||
char pcNewDir[ ffconfigMAX_FILENAME ];
|
||||
#endif
|
||||
#if( ipconfigUSE_HTTP != 0 )
|
||||
char pcContentsType[40]; /* Space for the msg: "text/javascript" */
|
||||
char pcExtraContents[40]; /* Space for the msg: "Content-Length: 346500" */
|
||||
#endif
|
||||
BaseType_t xServerCount;
|
||||
TCPClient_t *pxClients;
|
||||
struct xSERVER
|
||||
{
|
||||
enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */
|
||||
const char *pcRootDir;
|
||||
Socket_t xSocket;
|
||||
} xServers[ 1 ];
|
||||
};
|
||||
|
||||
#endif /* FREERTOS_SERVER_PRIVATE_H */
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// ntpClient.h
|
||||
//
|
||||
|
||||
#ifndef __NTPCLIENT_H__
|
||||
|
||||
#define __NTPCLIENT_H__
|
||||
|
||||
#define NTP_PORT 123
|
||||
|
||||
typedef uint32_t quint32;
|
||||
typedef int32_t qint32;
|
||||
typedef uint8_t quint8;
|
||||
typedef int8_t qint8;
|
||||
|
||||
typedef union _SNtpFlags SNtpFlags;
|
||||
|
||||
/**
|
||||
* 64-bit NTP timestamp.
|
||||
*/
|
||||
struct __attribute__ ((__packed__)) _SNtpTimestamp {
|
||||
/** Number of seconds passed since Jan 1 1900, in big-endian format. */
|
||||
quint32 seconds;
|
||||
|
||||
/** Fractional time part, in <tt>1/0xFFFFFFFF</tt>s of a second. */
|
||||
quint32 fraction;
|
||||
};
|
||||
|
||||
typedef struct _SNtpTimestamp SNtpTimestamp;
|
||||
/**
|
||||
* Mandatory part of an NTP packet
|
||||
*/
|
||||
struct SNtpPacket {
|
||||
/** Flags. */
|
||||
unsigned char flags; // value 0xDB : mode 3 (client), version 3, leap indicator unknown 3
|
||||
|
||||
/** Stratum of the clock. */
|
||||
quint8 stratum; // value 0 : unspecified
|
||||
|
||||
/** Maximum interval between successive messages, in log2 seconds. Note that the value is signed. */
|
||||
qint8 poll; // 10 means 1 << 10 = 1024 seconds
|
||||
|
||||
/** Precision of the clock, in log2 seconds. Note that the value is signed. */
|
||||
qint8 precision; // 0xFA = 250 = 0.015625 seconds
|
||||
|
||||
/** Round trip time to the primary reference source, in NTP short format. */
|
||||
qint32 rootDelay; // 0x5D2E = 23854 or (23854/65535)= 0.3640 sec
|
||||
|
||||
/** Nominal error relative to the primary reference source. */
|
||||
qint32 rootDispersion; // 0x0008 CAC8 = 8.7912 seconds
|
||||
|
||||
/** Reference identifier (either a 4 character string or an IP address). */
|
||||
qint8 referenceID[4]; // or just 0000
|
||||
|
||||
/** The time at which the clock was last set or corrected. */
|
||||
SNtpTimestamp referenceTimestamp; // Current time
|
||||
|
||||
/** The time at which the request departed the client for the server. */
|
||||
SNtpTimestamp originateTimestamp; // Keep 0
|
||||
|
||||
/** The time at which the request arrived at the server. */
|
||||
SNtpTimestamp receiveTimestamp; // Keep 0
|
||||
|
||||
/** The time at which the reply departed the server for client. */
|
||||
SNtpTimestamp transmitTimestamp;
|
||||
};
|
||||
|
||||
/* Add this number to get secs since 1-1-1900 */
|
||||
#define TIME1970 2208988800UL
|
||||
|
||||
#endif // __NTPCLIENT_H__
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* A simple demo for NTP using FreeRTOS+TCP
|
||||
*/
|
||||
|
||||
#ifndef NTPDEMO_H
|
||||
|
||||
#define NTPDEMO_H
|
||||
|
||||
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority );
|
||||
|
||||
#endif
|
||||
18
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/readme.txt
Normal file
18
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/readme.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
Contains the files that implement FreeRTOS+TCP.
|
||||
|
||||
User documentation, including an API reference is available on:
|
||||
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/
|
||||
|
||||
A description of the source code organisation is available on:
|
||||
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Networking_Tutorial.html
|
||||
|
||||
The porting guide is available on:
|
||||
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_TCP_Porting.html
|
||||
|
||||
License information is available on:
|
||||
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_Plus_TCP_License.html
|
||||
|
||||
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