1.将A27新UI文件夹重命名为CANUI 2.A272O新版本发布

This commit is contained in:
2025-03-26 18:43:18 +08:00
parent 497f8eb1e1
commit 5bc7ee438c
13399 changed files with 58500 additions and 59183 deletions

View File

@ -0,0 +1,401 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/******************************************************************************
*
* 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;
uint32_t 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 != NULL );
if( xNetworkBufferSemaphore != NULL )
{
#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 */
vListInitialise( &xFreeBuffersList );
/* Initialise all the network buffers. No storage is allocated to
* the buffers yet. */
for( x = 0U; 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 != NULL );
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 <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) && ( xNetworkBufferSemaphore != NULL ) )
{
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 );
( void ) 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 > 0U )
{
/* 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
{
/* No action. */
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();
/*
* Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'.
* The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false.
*/
if( xListItemAlreadyInFreeList == pdFALSE )
{
if( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE )
{
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
}
else
{
/* No action. */
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;
}
( void ) memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );
vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
pxNetworkBuffer->pucEthernetBuffer = pucBuffer;
}
return pxNetworkBuffer;
}

View File

@ -0,0 +1,951 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file FreeRTOS_ARP.c
* @brief Implements the Address Resolution Protocol for the FreeRTOS+TCP network stack.
*/
/* 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 "NetworkBufferManagement.h"
#include "NetworkInterface.h"
/** @brief 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 )
/** @brief The time between gratuitous ARPs. */
#ifndef arpGRATUITOUS_ARP_PERIOD
#define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000U ) )
#endif
/*-----------------------------------------------------------*/
/*
* Lookup an MAC address in the ARP cache from the IP address.
*/
static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup,
MACAddress_t * const pxMACAddress );
/*-----------------------------------------------------------*/
/** @brief The ARP cache. */
_static ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ];
/** @brief 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
* gratuitous 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 gratuitous ARP message. */
BaseType_t xARPHadIPClash;
/* MAC-address of the other device containing the same IP-address. */
MACAddress_t xARPClashMacAddress;
#endif /* ipconfigARP_USE_CLASH_DETECTION */
/*-----------------------------------------------------------*/
/**
* @brief Process the ARP packets.
*
* @param[in] pxARPFrame: The ARP Frame (the ARP packet).
*
* @return An enum which says whether to return the frame or to release it.
*/
eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
{
eFrameProcessingResult_t eReturn = eReleaseBuffer;
ARPHeader_t * pxARPHeader;
uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
/* memcpy() helper variables for MISRA Rule 21.15 compliance*/
const void * pvCopySource;
void * pvCopyDest;
pxARPHeader = &( pxARPFrame->xARPHeader );
/* The field ulSenderProtocolAddress is badly aligned, copy byte-by-byte. */
/*
* Use helper variables for memcpy() to remain
* compliant with MISRA Rule 21.15. These should be
* optimized away.
*/
pvCopySource = pxARPHeader->ucSenderProtocolAddress;
pvCopyDest = &ulSenderProtocolAddress;
( void ) memcpy( pvCopyDest, pvCopySource, 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://printf("%s:%d dst:%08x src:%08x\r\n", __func__, __LINE__, ulTargetProtocolAddress, *ipLOCAL_IP_ADDRESS_POINTER);
/* 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 */
/*
* Use helper variables for memcpy() to remain
* compliant with MISRA Rule 21.15. These should be
* optimized away.
*/
pvCopySource = xBroadcastMACAddress.ucBytes;
pvCopyDest = pxARPFrame->xEthernetHeader.xSourceAddress.ucBytes;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( xBroadcastMACAddress ) );
( void ) memset( pxARPHeader->xTargetHardwareAddress.ucBytes, 0, sizeof( MACAddress_t ) );
pxARPHeader->ulTargetProtocolAddress = 0UL;
}
else
{
/*
* Use helper variables for memcpy() to remain
* compliant with MISRA Rule 21.15. These should be
* optimized away.
*/
pvCopySource = pxARPHeader->xSenderHardwareAddress.ucBytes;
pvCopyDest = pxARPHeader->xTargetHardwareAddress.ucBytes;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( MACAddress_t ) );
pxARPHeader->ulTargetProtocolAddress = ulSenderProtocolAddress;
}
/*
* Use helper variables for memcpy() to remain
* compliant with MISRA Rule 21.15. These should be
* optimized away.
*/
pvCopySource = ipLOCAL_MAC_ADDRESS;
pvCopyDest = pxARPHeader->xSenderHardwareAddress.ucBytes;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( MACAddress_t ) );
pvCopySource = ipLOCAL_IP_ADDRESS_POINTER;
pvCopyDest = pxARPHeader->ucSenderProtocolAddress;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( pxARPHeader->ucSenderProtocolAddress ) );
eReturn = eReturnEthernetFrame;
}
break;
case ipARP_REPLY:printf("%s:%d \r\n", __func__, __LINE__);
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;
/* Remember the MAC-address of the other device which has the same IP-address. */
( void ) 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 )
/**
* @brief Remove an ARP cache entry that matches with .pxMACAddress.
*
* @param[in] pxMACAddress: Pointer to the MAC address whose entry shall
* be removed..
* @return When the entry was found and remove: the IP-address, otherwise zero.
*/
uint32_t ulARPRemoveCacheEntryByMac( const MACAddress_t * pxMACAddress )
{
BaseType_t x;
uint32_t lResult = 0;
configASSERT( pxMACAddress != NULL );
/* 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;
( void ) memset( &xARPCache[ x ], 0, sizeof( xARPCache[ x ] ) );
break;
}
}
return lResult;
}
#endif /* ipconfigUSE_ARP_REMOVE_ENTRY != 0 */
/*-----------------------------------------------------------*/
/**
* @brief Add/update the ARP cache entry MAC-address to IP-address mapping.
*
* @param[in] pxMACAddress: Pointer to the MAC address whose mapping is being
* updated.
* @param[in] ulIPAddress: 32-bit representation of the IP-address whose mapping
* is being updated.
*/
void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress,
const uint32_t ulIPAddress )
{
BaseType_t x = 0;
BaseType_t xIpEntry = -1;
BaseType_t xMacEntry = -1;
BaseType_t 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++ )
{
BaseType_t xMatchingMAC;
if( pxMACAddress != NULL )
{
if( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 )
{
xMatchingMAC = pdTRUE;
}
else
{
xMatchingMAC = pdFALSE;
}
}
else
{
xMatchingMAC = pdFALSE;
}
/* 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( xMatchingMAC != pdFALSE )
{
/* 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( xMatchingMAC != pdFALSE )
{
/* 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 /* if ( ipconfigARP_STORES_REMOTE_ADDRESSES != 0 ) */
xMacEntry = x;
#endif /* if ( ipconfigARP_STORES_REMOTE_ADDRESSES != 0 ) */
}
/* _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;
}
else
{
/* Nothing happens to this cache entry for now. */
}
}
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 */
( void ) memset( &( xARPCache[ xIpEntry ] ), 0, sizeof( ARPCacheRow_t ) );
}
}
else if( xIpEntry >= 0 )
{
/* An entry containing the IP-address was found, but it had a different MAC address */
xUseEntry = xIpEntry;
}
else
{
/* No matching entry found. */
}
/* If the entry was not found, we use the oldest entry and set the IPaddress */
xARPCache[ xUseEntry ].ulIPAddress = ulIPAddress;
if( pxMACAddress != NULL )
{
( void ) 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;
}
else
{
/* Nothing will be stored. */
}
}
}
/*-----------------------------------------------------------*/
#if ( ipconfigUSE_ARP_REVERSED_LOOKUP == 1 )
/**
* @brief Retrieve an entry from the cache table
*
* @param[in] pxMACAddress: The MAC-address of the entry of interest.
* @param[out] pulIPAddress: set to the IP-address found, or unchanged when not found.
*
* @return Either eARPCacheMiss or eARPCacheHit.
*/
eARPLookupResult_t eARPGetCacheEntryByMac( MACAddress_t * const pxMACAddress,
uint32_t * pulIPAddress )
{
BaseType_t x;
eARPLookupResult_t eReturn = eARPCacheMiss;
configASSERT( pxMACAddress != NULL );
configASSERT( pulIPAddress != NULL );
/* 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 */
/*-----------------------------------------------------------*/
/**
* @brief Look for ulIPAddress in the ARP cache.
*
* @param[in,out] pulIPAddress: Pointer to the IP-address to be queried to the ARP cache.
* @param[in,out] pxMACAddress: Pointer to a MACAddress_t variable where the MAC address
* will be stored, if found.
*
* @return 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 )
{
eARPLookupResult_t eReturn;
uint32_t ulAddressToLookup;
ulAddressToLookup = *pulIPAddress;
#if ( ipconfigUSE_LLMNR == 1 )
if( ulAddressToLookup == ipLLMNR_IP_ADDR ) /* Is in network byte order. */
{
/* The LLMNR IP-address has a fixed virtual MAC address. */
( void ) memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit;
}
else
#endif
if( xIsIPv4Multicast( ulAddressToLookup ) != 0 )
{
/* Get the lowest 23 bits of the IP-address. */
vSetMultiCastIPv4MacAddress( ulAddressToLookup, pxMACAddress );
eReturn = eARPCacheHit;
}
else 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? */
{printf("This is a broadcast so it uses the broadcast MAC address\r\n");
/* This is a broadcast so it uses the broadcast MAC address. */
( void ) 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 ) )
{
/* No matching end-point is found, look for a gateway. */
#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 ( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 )
if( eReturn == eARPCacheMiss ) /*lint !e774: (Info -- Boolean within 'if' always evaluates to True, depending on configuration. */
#else
/* No cache look-up was done, so the result is still 'eARPCacheMiss'. */
#endif
{
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;
}
/*-----------------------------------------------------------*/
/**
* @brief Lookup an IP address in the ARP cache.
*
* @param[in] ulAddressToLookup: The 32-bit representation of an IP address to
* lookup.
* @param[out] pxMACAddress: A pointer to MACAddress_t variable where, if there
* is an ARP cache hit, the MAC address corresponding to
* the IP address will be stored.
*
* @return When the IP-address is found: eARPCacheHit, when not found: eARPCacheMiss,
* and when waiting for a ARP reply: eCantSendPacket.
*/
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. */
( void ) memcpy( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit;
}
break;
}
}
return eReturn;
}
/*-----------------------------------------------------------*/
/**
* @brief A call to this function will update (or 'Age') the ARP cache entries.
* The function will also try to prevent a removal of entry by sending
* an ARP query. It will also check whether we are waiting on an ARP
* reply - if we are, then an ARP request will be re-sent.
* In case an ARP entry has 'Aged' to 0, it will be removed from the ARP
* cache.
*/
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;
}
}
/*-----------------------------------------------------------*/
/**
* @brief Send a Gratuitous ARP packet to allow this node to announce the IP-MAC
* mapping to the entire network.
*/
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(). */
( void ) xSendEventToIPTask( eARPTimerEvent );
}
/*-----------------------------------------------------------*/
/**
* @brief Create and send an ARP request packet.
*
* @param[in] ulIPAddress: A 32-bit representation of the IP-address whose
* physical (MAC) address is required.
*/
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 ) 0U );
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 /* if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES ) */
if( xIsCallingFromIPTask() != 0 )
{
iptraceNETWORK_INTERFACE_OUTPUT( pxNetworkBuffer->xDataLength, pxNetworkBuffer->pucEthernetBuffer );
/* Only the IP-task is allowed to call this function directly. */
( void ) xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
}
else
{
IPStackEvent_t xSendEvent;
/* Send a message to the IP-task to send this ARP packet. */
xSendEvent.eEventType = eNetworkTxEvent;
xSendEvent.pvData = pxNetworkBuffer;
if( xSendEventStructToIPTask( &xSendEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
{
/* Failed to send the message, so release the network buffer. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
}
}
}
}
/*--------------------------------------*/
/**
* @brief Generate an ARP request packet by copying various constant details to
* the buffer.
*
* @param[in,out] pxNetworkBuffer: Pointer to the buffer which has to be filled with
* the ARP request packet details.
*/
void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
/* 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. */
};
ARPPacket_t * pxARPPacket;
/* memcpy() helper variables for MISRA Rule 21.15 compliance*/
const void * pvCopySource;
void * pvCopyDest;
/* Buffer allocation ensures that buffers always have space
* for an ARP packet. See buffer allocation implementations 1
* and 2 under portable/BufferManagement. */
configASSERT( pxNetworkBuffer != NULL );
configASSERT( pxNetworkBuffer->xDataLength >= sizeof( ARPPacket_t ) );
pxARPPacket = ipCAST_PTR_TO_TYPE_PTR( 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;
*/
/*
* Use helper variables for memcpy() to remain
* compliant with MISRA Rule 21.15. These should be
* optimized away.
*/
pvCopySource = xDefaultPartARPPacketHeader;
pvCopyDest = pxARPPacket;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( xDefaultPartARPPacketHeader ) );
pvCopySource = ipLOCAL_MAC_ADDRESS;
pvCopyDest = pxARPPacket->xEthernetHeader.xSourceAddress.ucBytes;
( void ) memcpy( pvCopyDest, pvCopySource, ipMAC_ADDRESS_LENGTH_BYTES );
pvCopySource = ipLOCAL_MAC_ADDRESS;
pvCopyDest = pxARPPacket->xARPHeader.xSenderHardwareAddress.ucBytes;
( void ) memcpy( pvCopyDest, pvCopySource, ipMAC_ADDRESS_LENGTH_BYTES );
pvCopySource = ipLOCAL_IP_ADDRESS_POINTER;
pvCopyDest = pxARPPacket->xARPHeader.ucSenderProtocolAddress;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( pxARPPacket->xARPHeader.ucSenderProtocolAddress ) );
pxARPPacket->xARPHeader.ulTargetProtocolAddress = pxNetworkBuffer->ulIPAddress;
pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t );
iptraceCREATING_ARP_REQUEST( pxNetworkBuffer->ulIPAddress );
}
/*-----------------------------------------------------------*/
/**
* @brief A call to this function will clear the ARP cache.
*/
void FreeRTOS_ClearARP( void )
{
( void ) memset( xARPCache, 0, sizeof( xARPCache ) );
}
/*-----------------------------------------------------------*/
#if 1
/**
* @brief This function will check if the target IP-address belongs to this device.
* If so, the packet will be passed to the IP-stack, who will answer it.
* The function is to be called within the function xNetworkInterfaceOutput().
*
* @param[in] pxDescriptor: The network buffer which is to be checked for loop-back.
* @param[in] bReleaseAfterSend: pdTRUE: Driver is allowed to transfer ownership of descriptor.
* pdFALSE: Driver is not allowed to take ownership of descriptor,
* make a copy of it.
*
* @return pdTRUE/pdFALSE: There is/isn't a loopback address in the packet.
*/
BaseType_t xCheckLoopback( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t bReleaseAfterSend )
{
BaseType_t xResult = pdFALSE;
NetworkBufferDescriptor_t * pxUseDescriptor = pxDescriptor;
const IPPacket_t * pxIPPacket = ipCAST_PTR_TO_TYPE_PTR( IPPacket_t, pxUseDescriptor->pucEthernetBuffer );
if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )
{
if( memcmp( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 )
{
xResult = pdTRUE;
if( bReleaseAfterSend == pdFALSE )
{
/* Driver is not allowed to transfer the ownership
* of descriptor, so make a copy of it */
pxUseDescriptor =
pxDuplicateNetworkBufferWithDescriptor( pxDescriptor, pxDescriptor->xDataLength );
}
if( pxUseDescriptor != NULL )
{
IPStackEvent_t xRxEvent;
xRxEvent.eEventType = eNetworkRxEvent;
xRxEvent.pvData = pxUseDescriptor;
if( xSendEventStructToIPTask( &xRxEvent, 0U ) != pdTRUE )
{
vReleaseNetworkBufferAndDescriptor( pxUseDescriptor );
iptraceETHERNET_RX_EVENT_LOST();
FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
}
}
}
}
return xResult;
}
#endif /* 0 */
/*-----------------------------------------------------------*/
#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 > ( uint8_t ) 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 ) */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,666 @@
/*
* porting from lwip
*/
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <FreeRTOS.h>
#include <task.h>
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_DHCP_Server.h"
#include "NetworkBufferManagement.h"
#if (DHCP_DEBUG == LWIP_DBG_ON)
#define debug(s, ...) printf("%s: " s "\n", "DHCP", ## __VA_ARGS__)
#else
#define debug(s, ...)
#endif
/* Grow the size of the lwip dhcp_msg struct's options field, as LWIP
defaults to a 68 octet options field for its DHCP client, and most
full-sized clients send us more than this. */
#define DHCP_OPTIONS_LEN 312
#define NETIF_MAX_HWADDR_LEN 6U
#define DHCP_FILE_LEN 128U
#define DHCP_SNAME_LEN 64U
#define DHCP_CHADDR_LEN 16U
#define LWIP_IANA_HWTYPE_ETHERNET 1
/* DHCP op codes */
#define DHCP_BOOTREQUEST 1
#define DHCP_BOOTREPLY 2
/* DHCP message types */
#define DHCP_DISCOVER 1
#define DHCP_OFFER 2
#define DHCP_REQUEST 3
#define DHCP_DECLINE 4
#define DHCP_ACK 5
#define DHCP_NAK 6
#define DHCP_RELEASE 7
#define DHCP_INFORM 8
#define DHCP_MAGIC_COOKIE 0x63825363UL
/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */
/* BootP options */
#define DHCP_OPTION_PAD 0
#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
#define DHCP_OPTION_ROUTER 3
#define DHCP_OPTION_DNS_SERVER 6
#define DHCP_OPTION_HOSTNAME 12
#define DHCP_OPTION_IP_TTL 23
#define DHCP_OPTION_MTU 26
#define DHCP_OPTION_BROADCAST 28
#define DHCP_OPTION_TCP_TTL 37
#define DHCP_OPTION_NTP 42
#define DHCP_OPTION_END 255
/* DHCP options */
#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */
#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */
#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */
#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */
#define DHCP_OPTION_MESSAGE_TYPE_LEN 1
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */
#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */
#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2
#define DHCP_OPTION_T1 58 /* T1 renewal time */
#define DHCP_OPTION_T2 59 /* T2 rebinding time */
#define DHCP_OPTION_US 60
#define DHCP_OPTION_CLIENT_ID 61
#define DHCP_OPTION_TFTP_SERVERNAME 66
#define DHCP_OPTION_BOOTFILE 67
/* possible combinations of overloading the file and sname fields with options */
#define DHCP_OVERLOAD_NONE 0
#define DHCP_OVERLOAD_FILE 1
#define DHCP_OVERLOAD_SNAME 2
#define DHCP_OVERLOAD_SNAME_FILE 3
#define IPADDR_ANY ((uint32_t)0x00000000UL)
#define ip4_addr_get_byte(ipaddr, idx) (((const uint8_t*)(&(ipaddr)->addr))[idx])
#define ip4_addr1(ipaddr) ip4_addr_get_byte(ipaddr, 0)
#define ip4_addr2(ipaddr) ip4_addr_get_byte(ipaddr, 1)
#define ip4_addr3(ipaddr) ip4_addr_get_byte(ipaddr, 2)
#define ip4_addr4(ipaddr) ip4_addr_get_byte(ipaddr, 3)
#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr)
#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0)
#define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY)
#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2)
#define swap16(A) ((((uint16_t)(A) & 0xff00) >> 8) | (((uint16_t)(A) & 0x00ff) << 8))
#define swap32(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \
(((uint32_t)(A) & 0x00ff0000) >> 8) | \
(((uint32_t)(A) & 0x0000ff00) << 8) | \
(((uint32_t)(A) & 0x000000ff) << 24))
#define IPADDR_BROADCAST ((uint32_t)0xffffffffUL)
static union {
char c[4];
unsigned long l;
} endian_test = {{ 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.l)
uint16_t htons(uint16_t hs)
{
return (ENDIANNESS=='l') ? swap16(hs): hs;
}
uint32_t htonl(uint32_t hl)
{
return (ENDIANNESS=='l') ? swap32(hl): hl;
}
uint16_t ntohs(uint16_t ns)
{
return (ENDIANNESS=='l') ? swap16(ns): ns;
}
uint32_t ntohl(uint32_t nl)
{
return (ENDIANNESS=='l') ? swap32(nl): nl;
}
#include "pack_struct_start.h"
struct ip4_addr {
uint32_t addr;
};
#include "pack_struct_end.h"
typedef struct ip4_addr ip4_addr_t;
typedef ip4_addr_t ip_addr_t;
#include "pack_struct_start.h"
struct dhcp_msg
{
uint8_t op;
uint8_t htype;
uint8_t hlen;
uint8_t hops;
uint32_t xid;
uint16_t secs;
uint16_t flags;
ip4_addr_t ciaddr;
ip4_addr_t yiaddr;
ip4_addr_t siaddr;
ip4_addr_t giaddr;
uint8_t chaddr[DHCP_CHADDR_LEN];
uint8_t sname[DHCP_SNAME_LEN];
uint8_t file[DHCP_FILE_LEN];
uint32_t cookie;
uint8_t options[DHCP_OPTIONS_LEN];
};
#include "pack_struct_end.h"
typedef struct {
uint8_t hwaddr[NETIF_MAX_HWADDR_LEN];
uint8_t active;
uint32_t expires;
} dhcp_lease_t;
typedef struct {
//struct netconn *nc;
Socket_t server_handle;
uint8_t max_leases;
ip4_addr_t first_client_addr;
//struct netif *server_if;
dhcp_lease_t *leases; /* length max_leases */
/* Optional router */
ip4_addr_t router;
/* Optional DNS server */
ip4_addr_t dns;
} server_state_t;
struct dhcp_client_ctx
{
int32_t tid;
ListItem_t item;
TimerHandle_t timer;
server_state_t* state;
struct dhcp_msg msg;
};
static TaskHandle_t dhcpserver_task_handle = NULL;
static server_state_t *gState;
static List_t gdhcp_client_list;
static uint32_t gDefaultIp = 0;
uint32_t FreeRTOS_GetIPAddressSafe( void )
{
uint32_t ip = FreeRTOS_GetIPAddress();
if (0 == ip) {
return gDefaultIp;
}
return ip;
}
/* Handlers for various kinds of incoming DHCP messages */
static void handle_dhcp_discover(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *received);
static void handle_dhcp_request(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg);
static void handle_dhcp_release(server_state_t* state, struct dhcp_msg *dhcpmsg);
static void send_dhcp_nak(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg);
static void dhcpserver_task(void *pxParameter);
/* Utility functions */
static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8_t min_length, uint8_t *length);
static uint8_t *add_dhcp_option_byte(uint8_t *opt, uint8_t type, uint8_t value);
static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, uint8_t len);
static dhcp_lease_t *find_lease_slot(server_state_t* state, uint8_t *hwaddr);
/* Copy IP address as dotted decimal to 'dest', must be at least 16 bytes long */
inline static void sprintf_ipaddr(const ip4_addr_t *addr, char *dest)
{
if (addr == NULL)
sprintf(dest, "NULL");
else
sprintf(dest, "%d.%d.%d.%d", ip4_addr1(addr),
ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr));
}
inline static void sprintf_ipaddr1(uint32_t addr, uint8_t *dest)
{
ip4_addr_t tmp = {0};
tmp.addr = addr;
sprintf_ipaddr(&tmp, (char*)dest);
}
void dhcpserver_start(const uint8_t ucIPAddress[4], uint32_t first_client_addr, uint8_t max_leases)
{
/* Stop any existing running dhcpserver */
if (dhcpserver_task_handle) {
return;
}
gDefaultIp = (ucIPAddress[0]) | (ucIPAddress[1] << 8) | (ucIPAddress[2] << 16) | (ucIPAddress[3] << 24);
printf("dhcpserver_start-->gDefaultIp:%x\r\n", gDefaultIp);
vListInitialise(&gdhcp_client_list);
gState = (server_state_t*)pvPortMalloc(sizeof(server_state_t));
memset(gState, 0, sizeof(*gState));
gState->max_leases = max_leases;
gState->leases = (dhcp_lease_t *)pvPortMalloc(max_leases * sizeof(dhcp_lease_t));
memset((void*)gState->leases, 0, max_leases * sizeof(dhcp_lease_t));
// state->server_if is assigned once the task is running - see comment in dhcpserver_task()
//ip4_addr_copy(gState->first_client_addr, *first_client_addr);
gState->first_client_addr.addr = first_client_addr;
/* Clear options */
ip4_addr_set_zero(&gState->router);
ip4_addr_set_zero(&gState->dns);
xTaskCreate(dhcpserver_task, "DHCP Server", configMINIMAL_STACK_SIZE * 4, (void*)gState, 5, &dhcpserver_task_handle);
}
void dhcpserver_stop(void)
{
if (dhcpserver_task_handle) {
vTaskDelete(dhcpserver_task_handle);
dhcpserver_task_handle = NULL;
vPortFree((void*)gState->leases);
vPortFree((void*)gState);
gState = NULL;
}
}
void dhcpserver_set_router(uint32_t router)
{
//ip4_addr_copy(gState->router, router);
gState->router.addr = router;
}
void dhcpserver_set_dns(uint32_t dns)
{
//ip4_addr_copy(gState->dns, dns);
gState->dns.addr = dns;
}
static void dhcpserver_task(void *pxParameter)
{
SocketSet_t xFD_Set;
BaseType_t xResult;
Socket_t xSockets;
struct freertos_sockaddr xAddress;
uint32_t xClientLength = sizeof( struct freertos_sockaddr );
int32_t lBytes;
const TickType_t xRxBlockTime = 0;
uint8_t rcv_buf[4096] = {0};
server_state_t* state = (server_state_t*)pxParameter;
uint8_t ipAddrStr[32] = {0};
xFD_Set = FreeRTOS_CreateSocketSet();
xSockets = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
xAddress.sin_port = FreeRTOS_htons( 67 );
FreeRTOS_bind(xSockets, &xAddress, sizeof( struct freertos_sockaddr ));
FreeRTOS_setsockopt(xSockets, 0, FREERTOS_SO_RCVTIMEO, &xRxBlockTime, sizeof( xRxBlockTime ));
state->server_handle = xSockets;
while(1) {
FreeRTOS_FD_CLR(xSockets, xFD_Set, eSELECT_READ);
FreeRTOS_FD_SET( xSockets, xFD_Set, eSELECT_READ );
xResult = FreeRTOS_select( xFD_Set, portMAX_DELAY );
if (xResult == 0) {
continue;
}
struct dhcp_msg received = { 0 };
/* Receive a DHCP packet */
if( !FreeRTOS_FD_ISSET ( xSockets, xFD_Set ) ) {
}
/* Read from the socket. */
lBytes = FreeRTOS_recvfrom( xSockets, (void*)rcv_buf, sizeof(rcv_buf), 0, &xAddress,
&xClientLength );
if (lBytes <= 0)
continue;
if (lBytes < (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN))
continue;
/* expire any leases that have passed */
uint32_t now = xTaskGetTickCount();
for (int i = 0; i < state->max_leases; i++) {
if (state->leases[i].active) {
uint32_t expires = state->leases[i].expires - now;
if (expires >= 0x80000000) {
state->leases[i].active = 0;
}
}
}
memcpy((void*)&received, (void*)rcv_buf, lBytes);
uint8_t *message_type = find_dhcp_option(&received, DHCP_OPTION_MESSAGE_TYPE,
DHCP_OPTION_MESSAGE_TYPE_LEN, NULL);
if(!message_type) {
debug("DHCP Server Error: No message type field found");
continue;
}
#if (DHCP_DEBUG == LWIP_DBG_ON)
sprintf_ipaddr1(xAddress.sin_addr, ipAddrStr);
debug("State dump. Message type %d from %s port:%d\r\n", *message_type, ipAddrStr, xAddress.sin_port);
for(int i = 0; i < state->max_leases; i++) {
#if 0
dhcp_lease_t *lease = &state->leases[i];
debug("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x \r\n", i, lease->expires, lease->hwaddr[0],
lease->hwaddr[1], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
lease->hwaddr[5]);
#endif
}
#endif
//xAddress.sin_addr = 0xffffffffUL;
//xAddress.sin_port = ( uint16_t ) 68;
switch(*message_type) {
case DHCP_DISCOVER:
printf("DHCP_DISCOVER\r\n");
handle_dhcp_discover(state, &xAddress, &received);
break;
case DHCP_REQUEST:
printf("DHCP_REQUEST\r\n");
handle_dhcp_request(state, &xAddress, &received);
break;
case DHCP_RELEASE:
printf("DHCP_RELEASE\r\n");
handle_dhcp_release(state, &received);
break;
default:
debug("DHCP Server Error: Unsupported message type %d\r\n", *message_type);
break;
}
}
}
/*static void send_dhcp_msg(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg)
{
NetworkBufferDescriptor_t * pxNetworkBuffer;
uint8_t * pucUDPPayloadBuffer = NULL;
uint32_t xClientLength = sizeof( struct freertos_sockaddr );
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + sizeof(struct dhcp_msg), 0U );
if( pxNetworkBuffer == NULL ) {
debug("DHCP Server: malloc net buf desc err.\r\n");
return;
}
pucUDPPayloadBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
memcpy(pucUDPPayloadBuffer, (void*)dhcpmsg, sizeof(struct dhcp_msg));
FreeRTOS_sendto(state->server_handle, (void*)pucUDPPayloadBuffer, sizeof(struct dhcp_msg), FREERTOS_ZERO_COPY, xaddr, xClientLength);
}*/
#define dhcpdTIMER_SCAN_FREQUENCY_MS pdMS_TO_TICKS( 300UL )
static void handle_dhcp_discover(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg)
{
uint32_t xClientLength = sizeof( struct freertos_sockaddr );
int32_t ret = -1;
struct dhcp_client_ctx *client = NULL;
if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET)
return;
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
return;
dhcp_lease_t *freelease = find_lease_slot(state, dhcpmsg->chaddr);
if(!freelease) {
debug("DHCP Server: All leases taken.\r\n");
return; /* Nothing available, so do nothing */
}
/* Reuse the DISCOVER buffer for the OFFER response */
dhcpmsg->op = DHCP_BOOTREPLY;
dhcpmsg->htype = LWIP_IANA_HWTYPE_ETHERNET;
//bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
memset((void *)dhcpmsg->options, 0, sizeof(dhcpmsg->options));
dhcpmsg->yiaddr.addr = FreeRTOS_htonl(FreeRTOS_ntohl(state->first_client_addr.addr) + (freelease - state->leases));
//dhcpmsg->yiaddr.addr = ((state->first_client_addr.addr) + (freelease - state->leases));
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_OFFER);
uint32_t ser_addr = FreeRTOS_GetIPAddressSafe();
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &ser_addr, 4);
uint32_t ser_netmask = FreeRTOS_GetNetmask();
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &ser_netmask, 4);//
uint32_t ser_broadcast = FreeRTOS_GetIPAddressSafe();
uint8_t* tmp_ptr_addr = (uint8_t*)&ser_broadcast;
*(tmp_ptr_addr + 3) = 0xff;
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_BROADCAST, &ser_broadcast, 4);
if (1) {
uint8_t addr_str[32] = {0};
sprintf_ipaddr1(ser_addr, addr_str);
debug("server ip:%s \r\n", addr_str);
sprintf_ipaddr1(xaddr->sin_addr, addr_str);
debug("##client ip:%s port:%d\r\n", addr_str, FreeRTOS_htons(xaddr->sin_port));
memset(addr_str, 0, sizeof(addr_str));
sprintf_ipaddr1(ser_netmask, addr_str);
debug("server netmask:%s \r\n", addr_str);
printf("send len:%d\r\n", sizeof(struct dhcp_msg));
}
//if (!ip4_addr_isany_val(state->router)) {
uint8_t addr_str11[32] = {0};
state->router.addr = FreeRTOS_GetGatewayAddress();
sprintf_ipaddr1(state->router.addr, addr_str11);
debug("router ip:%s \r\n", addr_str11);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
//}
//if (!ip4_addr_isany_val(state->dns)) {
state->dns.addr = FreeRTOS_GetGatewayAddress();
sprintf_ipaddr1(state->dns.addr, addr_str11);
debug("dns ip:%s \r\n", addr_str11);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
//}
uint32_t expiry = htonl(DHCPSERVER_LEASE_TIME);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
if (0) {
int i;
uint8_t *tmpp = (uint8_t *)dhcpmsg;
for (i = 0; i < sizeof(struct dhcp_msg); i++) {
printf("%02x ", tmpp[i]);
}printf("\r\n");
}
//xaddr->sin_addr = FreeRTOS_htonl(dhcpmsg->yiaddr.addr);
xaddr->sin_addr = 0xffffffff;//
xaddr->sin_port = ( uint16_t ) FreeRTOS_htons(68);
if (0 && NULL != client) {
memcpy((void *)&client->msg, (void *)dhcpmsg, sizeof(struct dhcp_msg));
client->state = state;
xTimerStart(client->timer, 0);
}
ret = FreeRTOS_sendto(state->server_handle, (void*)dhcpmsg, sizeof(struct dhcp_msg), 0, xaddr, xClientLength);
printf("len out:%d ret:%d\r\n", sizeof(struct dhcp_msg), ret);
if (ret != sizeof(struct dhcp_msg)) {
printf("udhcpd ret:%d\r\n", ret);
}
//send_dhcp_msg(state, xaddr, dhcpmsg);
}
static void handle_dhcp_request(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg)
{
uint32_t xClientLength = sizeof( struct freertos_sockaddr );
static char ipbuf[16];
if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET) {
debug("DHCP Server Error: htype err.\r\n");
return;
}
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN) {
debug("DHCP Server Error: hlen err.\r\n");
return;
}
ip4_addr_t requested_ip;
ip4_addr_t any_ip = {0};
any_ip.addr = IPADDR_ANY;
uint8_t *requested_ip_opt = find_dhcp_option(dhcpmsg, DHCP_OPTION_REQUESTED_IP, 4, NULL);
if (requested_ip_opt) {
memcpy(&requested_ip.addr, requested_ip_opt, 4);
} else if (ip4_addr_cmp(&requested_ip, &any_ip)) {
ip4_addr_copy(requested_ip, dhcpmsg->ciaddr);
} else {
debug("DHCP Server Error: No requested IP");
send_dhcp_nak(state, xaddr, dhcpmsg);
return;
}
/* Test the first 4 octets match */
if (ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
|| ip4_addr2(&requested_ip) != ip4_addr2(&state->first_client_addr)
|| ip4_addr3(&requested_ip) != ip4_addr3(&state->first_client_addr)) {
sprintf_ipaddr(&requested_ip, ipbuf);
debug("DHCP Server Error: %s not an allowed IP\r\n", ipbuf);
send_dhcp_nak(state, xaddr, dhcpmsg);
return;
}
/* Test the last octet is in the MAXCLIENTS range */
int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&state->first_client_addr);
if(octet_offs < 0 || octet_offs >= state->max_leases) {
debug("DHCP Server Error: Address out of range\r\n");
send_dhcp_nak(state, xaddr, dhcpmsg);
return;
}
dhcp_lease_t *requested_lease = state->leases + octet_offs;
if (requested_lease->active && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
{
debug("DHCP Server Error: Lease for address already taken\r\n");
send_dhcp_nak(state, xaddr, dhcpmsg);
return;
}
memcpy(requested_lease->hwaddr, dhcpmsg->chaddr, dhcpmsg->hlen);
sprintf_ipaddr(&requested_ip, ipbuf);
debug("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", ipbuf, requested_lease->hwaddr[0],
requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4],
requested_lease->hwaddr[5]);
uint32_t now = xTaskGetTickCount();
requested_lease->expires = now + DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
requested_lease->active = 1;
//sdk_wifi_softap_set_station_info(requested_lease->hwaddr, &requested_ip);
/* Reuse the REQUEST message as the ACK message */
dhcpmsg->op = DHCP_BOOTREPLY;
memset((void *)dhcpmsg->options, 0, sizeof(dhcpmsg->options));
ip4_addr_copy(dhcpmsg->yiaddr, requested_ip);
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_ACK);
uint32_t expiry = htonl(DHCPSERVER_LEASE_TIME);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4);
uint32_t ser_addr = FreeRTOS_GetIPAddressSafe();
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &ser_addr, 4);
uint32_t ser_netmask = FreeRTOS_GetNetmask();
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &ser_netmask, 4);
//if (!ip4_addr_isany_val(state->router)) {
state->router.addr = FreeRTOS_GetGatewayAddress();
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
//}
//if (!ip4_addr_isany_val(state->dns)) {
state->dns.addr = FreeRTOS_GetGatewayAddress();
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
//}
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
xaddr->sin_addr = 0xffffffff;
xaddr->sin_port = ( uint16_t ) FreeRTOS_htons(68);
FreeRTOS_sendto(state->server_handle, (void*)dhcpmsg, sizeof(struct dhcp_msg), 0, xaddr, xClientLength);
//send_dhcp_msg(state, xaddr, dhcpmsg);
}
static void handle_dhcp_release(server_state_t* state, struct dhcp_msg *dhcpmsg)
{
dhcp_lease_t *lease = find_lease_slot(state, dhcpmsg->chaddr);
if (lease) {
lease->active = 0;
lease->expires = 0;
}
}
static void send_dhcp_nak(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg)
{
uint32_t xClientLength = sizeof( struct freertos_sockaddr );
/* Reuse 'dhcpmsg' for the NAK */
dhcpmsg->op = DHCP_BOOTREPLY;
memset((void *)dhcpmsg->options, 0, sizeof(dhcpmsg->options));
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_NAK);
uint32_t ser_addr = FreeRTOS_GetIPAddressSafe();
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &ser_addr, 4);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
xaddr->sin_addr = 0xffffffff;
xaddr->sin_port = ( uint16_t ) FreeRTOS_htons(68);
FreeRTOS_sendto(state->server_handle, (void*)dhcpmsg, sizeof(struct dhcp_msg), 0, xaddr, xClientLength);
//send_dhcp_msg(state, xaddr, dhcpmsg);
}
static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8_t min_length, uint8_t *length)
{
uint8_t *start = (uint8_t *)&msg->options;
uint8_t *msg_end = (uint8_t *)msg + sizeof(struct dhcp_msg);
for (uint8_t *p = start; p < msg_end-2;) {
uint8_t type = *p++;
uint8_t len = *p++;
if (type == DHCP_OPTION_END)
return NULL;
if (p+len >= msg_end)
break; /* We've overrun our valid DHCP message size, or this isn't a valid option */
if (type == option_num) {
if (len < min_length)
break;
if (length)
*length = len;
return p; /* start of actual option data */
}
p += len;
}
return NULL; /* Not found */
}
static uint8_t *add_dhcp_option_byte(uint8_t *opt, uint8_t type, uint8_t value)
{
*opt++ = type;
*opt++ = 1;
*opt++ = value;
return opt;
}
static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, uint8_t len)
{
*opt++ = type;
if (len) {
*opt++ = len;
memcpy(opt, value, len);
}
return opt+len;
}
/* Find a free DHCP lease, or a lease already assigned to 'hwaddr' */
static dhcp_lease_t *find_lease_slot(server_state_t* state, uint8_t *hwaddr)
{
dhcp_lease_t *empty_lease = NULL;
for (int i = 0; i < state->max_leases; i++) {
if (!state->leases[i].active && !empty_lease)
empty_lease = &state->leases[i];
else if (memcmp(hwaddr, state->leases[i].hwaddr, 6) == 0)
return &state->leases[i];
}
return empty_lease;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file FreeRTOS_Stream_Buffer.c
* @brief Provides the API for managing/creating the stream buffers in the FreeRTOS+TCP network stack.
*/
/* 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"
/**
* @brief Adds data to a stream buffer.
*
* @param[in,out] pxBuffer: The buffer to which the bytes will be added.
* @param[in] uxOffset: If uxOffset > 0, data will be written at an offset from uxHead
* while uxHead will not be moved yet.
* @param[in] pucData: A pointer to the data to be added.
* @param[in] uxByteCount: The number of bytes to add.
*
* @return The number of bytes added to the buffer.
*/
size_t uxStreamBufferAdd( StreamBuffer_t * pxBuffer,
size_t uxOffset,
const uint8_t * pucData,
size_t uxByteCount )
{
size_t uxSpace, uxNextHead, uxFirst;
size_t uxCount = uxByteCount;
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. */
( void ) memcpy( &( 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. */
( void ) memcpy( 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;
}
/*-----------------------------------------------------------*/
/**
* @brief Read bytes from stream buffer.
*
* @param[in] pxBuffer: The buffer from which the bytes will be read.
* @param[in] uxOffset: can be used to read data located at a certain offset from 'lTail'.
* @param[in,out] pucData: If 'pucData' equals NULL, the function is called to advance 'lTail' only.
* @param[in] uxMaxCount: The number of bytes to read.
* @param[in] xPeek: if 'xPeek' is pdTRUE, or if 'uxOffset' is non-zero, the 'lTail' pointer will
* not be advanced.
*
* @return The count of the bytes read.
*/
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. */
( void ) 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. */
( void ) memcpy( &( pucData[ uxFirst ] ), pxBuffer->ucArray, uxCount - uxFirst );
}
}
if( ( xPeek == pdFALSE ) && ( uxOffset == 0UL ) )
{
/* Move the tail pointer to effectively remove the data read from
* the buffer. */
uxNextTail += uxCount;
if( uxNextTail >= pxBuffer->LENGTH )
{
uxNextTail -= pxBuffer->LENGTH;
}
pxBuffer->uxTail = uxNextTail;
}
}
return uxCount;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,448 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file FreeRTOS_UDP_IP.c
* @brief This file has the source code for the UDP-IP functionality of the FreeRTOS+TCP
* network stack.
*/
/* 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
/** @brief The expected IP version and header length coded into the IP header itself. */
#define ipIP_VERSION_AND_HEADER_LENGTH_BYTE ( ( uint8_t ) 0x45 )
/** @brief 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. */
/*lint -e708 (Info -- union initialization). */
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. */
}
};
/*-----------------------------------------------------------*/
/**
* @brief Process the generated UDP packet and do other checks before sending the
* packet such as ARP cache check and address resolution.
*
* @param[in] pxNetworkBuffer: The network buffer carrying the packet.
*/
void vProcessGeneratedUDPPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
UDPPacket_t * pxUDPPacket;
IPHeader_t * pxIPHeader;
eARPLookupResult_t eReturned;
uint32_t ulIPAddress = pxNetworkBuffer->ulIPAddress;
size_t uxPayloadSize;
/* memcpy() helper variables for MISRA Rule 21.15 compliance*/
const void * pvCopySource;
void * pvCopyDest;
/* Map the UDP packet onto the start of the frame. */
pxUDPPacket = ipCAST_PTR_TO_TYPE_PTR( UDPPacket_t, pxNetworkBuffer->pucEthernetBuffer );
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
if( pxNetworkBuffer->usPort == ( uint16_t ) ipPACKET_CONTAINS_ICMP_DATA )
{
uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( ICMPPacket_t );
}
else
#endif
{
uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
}
/* 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 != ( uint16_t ) 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 ) ( uxPayloadSize + 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
/*
* Offset the memcpy by the size of a MAC address to start at the packet's
* Ethernet header 'source' MAC address; the preceding 'destination' should not be altered.
*/
/*
* Use helper variables for memcpy() to remain
* compliant with MISRA Rule 21.15. These should be
* optimized away.
*/
pvCopySource = xDefaultPartUDPPacketHeader.ucBytes;
/* The Ethernet source address is at offset 6. */
pvCopyDest = &pxNetworkBuffer->pucEthernetBuffer[ sizeof( MACAddress_t ) ];
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( xDefaultPartUDPPacketHeader ) );
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
if( pxNetworkBuffer->usPort == ( uint16_t ) ipPACKET_CONTAINS_ICMP_DATA )
{
pxIPHeader->ucProtocol = ipPROTOCOL_ICMP;
pxIPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( IPHeader_t ) + sizeof( ICMPHeader_t ) );
}
else
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
{
pxIPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( IPHeader_t ) + sizeof( UDPHeader_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( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
if( ( ucSocketOptions & ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT ) != 0U )
{
( void ) usGenerateProtocolChecksum( ( uint8_t * ) pxUDPPacket, pxNetworkBuffer->xDataLength, pdTRUE );
}
else
{
pxUDPPacket->xUDPHeader.usChecksum = 0U;
}
}
#endif /* if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) */
}
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 /* if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES ) */
iptraceNETWORK_INTERFACE_OUTPUT( pxNetworkBuffer->xDataLength, pxNetworkBuffer->pucEthernetBuffer );
( void ) xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
}
else
{
/* The packet can't be sent (DHCP not completed?). Just drop the
* packet. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
}
}
/*-----------------------------------------------------------*/
/**
* @brief Process the received UDP packet.
*
* @param[in] pxNetworkBuffer: The network buffer carrying the UDP packet.
* @param[in] usPort: The port number on which this packet was received.
*
* @return pdPASS in case the UDP packet could be processed. Else pdFAIL is returned.
*/
BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t * pxNetworkBuffer,
uint16_t usPort )
{
BaseType_t xReturn = pdPASS;
FreeRTOS_Socket_t * pxSocket;
configASSERT( pxNetworkBuffer != NULL );
configASSERT( pxNetworkBuffer->pucEthernetBuffer != NULL );
/* Map the ethernet buffer to the UDPPacket_t struct for easy access to the fields. */
const UDPPacket_t * pxUDPPacket = ipCAST_CONST_PTR_TO_CONST_TYPE_PTR( UDPPacket_t, pxNetworkBuffer->pucEthernetBuffer );
/* Caller must check for minimum packet size. */
pxSocket = pxUDPSocketLookup( usPort );
if( pxSocket != NULL )
{
/* 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 = &( 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;
/* The value of 'xDataLength' was proven to be at least the size of a UDP packet in prvProcessIPPacket(). */
if( xHandler( ( Socket_t ) pxSocket,
( void * ) pcData,
( size_t ) ( pxNetworkBuffer->xDataLength - ipUDP_PAYLOAD_OFFSET_IPv4 ),
&( xSourceAddress ),
&( destinationAddress ) ) != 0 )
{
xReturn = pdFAIL; /* xHandler has consumed the data, do not add it to .xWaitingPacketsList'. */
}
}
}
#endif /* ipconfigUSE_CALLBACKS */
#if ( ipconfigUDP_MAX_RX_PACKETS > 0U )
{
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 ( ipconfigUDP_MAX_RX_PACKETS > 0U ) */
#if ( ipconfigUSE_CALLBACKS == 1 ) || ( ipconfigUDP_MAX_RX_PACKETS > 0U )
if( xReturn == pdPASS ) /*lint !e774: Boolean within 'if' always evaluates to True, depending on configuration. [MISRA 2012 Rule 14.3, required. */
#else
/* xReturn is still pdPASS. */
#endif
{
vTaskSuspendAll();
{
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();
}
( void ) xTaskResumeAll();
/* Set the socket's receive event */
if( pxSocket->xEventGroup != NULL )
{
( void ) xEventGroupSetBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_RECEIVE );
}
#if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_READ ) ) != 0U ) )
{
( void ) xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, ( EventBits_t ) eSELECT_READ );
}
}
#endif
#if ( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
{
if( pxSocket->pxUserSemaphore != NULL )
{
( void ) xSemaphoreGive( pxSocket->pxUserSemaphore );
}
}
#endif
#if ( ipconfigUSE_DHCP == 1 )
{
if( xIsDHCPSocket( pxSocket ) != 0 )
{
( void ) xSendDHCPEvent();
}
}
#endif
}
}
else
{
/* There is no socket listening to the target port, but still it might
* be for this node. */
#if ( ipconfigUSE_DNS == 1 ) && ( ipconfigDNS_USE_CALLBACKS == 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 ) == ( uint16_t ) 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;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,371 @@
/*
* FreeRTOS V202112.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/*
* A set of tasks are created that send TCP echo requests to the standard echo
* port (port 7) on the IP address set by the configECHO_SERVER_ADDR0 to
* configECHO_SERVER_ADDR3 constants, then wait for and verify the reply
* (another demo is available that demonstrates the reception being performed in
* a task other than that from with the request was made).
*
* See the following web page for essential demo usage and configuration
* details:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
/* Exclude the whole file if FreeRTOSIPConfig.h is configured to use UDP only. */
#if ( ipconfigUSE_TCP == 1 )
/* The echo tasks create a socket, send out a number of echo requests, listen
for the echo reply, then close the socket again before starting over. This
delay is used between each iteration to ensure the network does not get too
congested. */
#define echoLOOP_DELAY ( ( TickType_t ) 150 / portTICK_PERIOD_MS )
/* The echo server is assumed to be on port 7, which is the standard echo
protocol port. */
#define echoECHO_PORT ( 7 )
/* The size of the buffers is a multiple of the MSS - the length of the data
sent is a pseudo random size between 20 and echoBUFFER_SIZES. */
#define echoBUFFER_SIZE_MULTIPLIER ( 3 )
#define echoBUFFER_SIZES ( ipconfigTCP_MSS * echoBUFFER_SIZE_MULTIPLIER )
/* The number of instances of the echo client task to create. */
#define echoNUM_ECHO_CLIENTS ( 1 )
/*-----------------------------------------------------------*/
/*
* Uses a socket to send data to, then receive data from, the standard echo
* port number 7.
*/
static void prvEchoClientTask( void *pvParameters );
/*
* Creates a pseudo random sized buffer of data to send to the echo server.
*/
static BaseType_t prvCreateTxData( char *ucBuffer,
uint32_t ulBufferLength );
/*-----------------------------------------------------------*/
/* Rx and Tx time outs are used to ensure the sockets do not wait too long for
missing data. */
static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 4000 );
static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 2000 );
/* Counters for each created task - for inspection only. */
static uint32_t ulTxRxCycles[ echoNUM_ECHO_CLIENTS ] = { 0 },
ulTxRxFailures[ echoNUM_ECHO_CLIENTS ] = { 0 },
ulConnections[ echoNUM_ECHO_CLIENTS ] = { 0 };
/* Rx and Tx buffers for each created task. */
static char cTxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ],
cRxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ];
/*-----------------------------------------------------------*/
void vStartTCPEchoClientTasks_SingleTasks( uint16_t usTaskStackSize,
UBaseType_t uxTaskPriority )
{
BaseType_t x;
/* Create the echo client tasks. */
for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ )
{
xTaskCreate( prvEchoClientTask, /* The function that implements the task. */
"Echo0", /* Just a text name for the task to aid debugging. */
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
( void * ) x, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
NULL ); /* The task handle is not used. */
}
}
/*-----------------------------------------------------------*/
static void prvEchoClientTask( void *pvParameters )
{
Socket_t xSocket;
struct freertos_sockaddr xEchoServerAddress;
int32_t lLoopCount = 0UL;
const int32_t lMaxLoopCount = 1;
volatile uint32_t ulTxCount = 0UL;
BaseType_t xReceivedBytes, xReturned, xInstance;
BaseType_t lTransmitted, lStringLength;
char *pcTransmittedString, *pcReceivedString;
WinProperties_t xWinProps;
TickType_t xTimeOnEntering;
BaseType_t ret;
/* Fill in the buffer and window sizes that will be used by the socket. */
xWinProps.lTxBufSize = 6 * ipconfigTCP_MSS;
xWinProps.lTxWinSize = 3;
xWinProps.lRxBufSize = 6 * ipconfigTCP_MSS;
xWinProps.lRxWinSize = 3;
/* This task can be created a number of times. Each instance is numbered
to enable each instance to use a different Rx and Tx buffer. The number is
passed in as the task's parameter. */
xInstance = ( BaseType_t ) pvParameters;
/* Point to the buffers to be used by this instance of this task. */
pcTransmittedString = &( cTxBuffers[ xInstance ][ 0 ] );
pcReceivedString = &( cRxBuffers[ xInstance ][ 0 ] );
/* Echo requests are sent to the echo server. The address of the echo
server is configured by the constants configECHO_SERVER_ADDR0 to
configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */
xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT );
xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,
configECHO_SERVER_ADDR1,
configECHO_SERVER_ADDR2,
configECHO_SERVER_ADDR3 );
for( ; ; )
{
/* Create a TCP socket. */
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
/* Set a time out so a missing reply does not cause the task to block
indefinitely. */
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );
/* Set the window and buffer sizes. */
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
/* Connect to the echo server. */
printf( "connecting to echo server....\n" );
ret = FreeRTOS_connect( xSocket, &xEchoServerAddress, sizeof( xEchoServerAddress ) );
if( ret == 0 )
{
printf( "Connected to server.. \n" );
ulConnections[ xInstance ]++;
/* Send a number of echo requests. */
for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )
{
/* Create the string that is sent to the echo server. */
lStringLength = prvCreateTxData( pcTransmittedString, echoBUFFER_SIZES );
/* Add in some unique text at the front of the string. */
sprintf( pcTransmittedString, "TxRx message number %u", ulTxCount );
ulTxCount++;
printf( "sending data to the echo server \n" );
/* Send the string to the socket. */
lTransmitted = FreeRTOS_send( xSocket, /* The socket being sent to. */
( void * ) pcTransmittedString, /* The data being sent. */
lStringLength, /* The length of the data being sent. */
0 ); /* No flags. */
if( lTransmitted < 0 )
{
/* Error? */
break;
}
/* Clear the buffer into which the echoed string will be
placed. */
memset( ( void * ) pcReceivedString, 0x00, echoBUFFER_SIZES );
xReceivedBytes = 0;
/* Receive data echoed back to the socket. */
while( xReceivedBytes < lTransmitted )
{
xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */
&( pcReceivedString[ xReceivedBytes ] ), /* The buffer into which the received data will be written. */
lStringLength - xReceivedBytes, /* The size of the buffer provided to receive the data. */
0 ); /* No flags. */
if( xReturned < 0 )
{
/* Error occurred. Latch it so it can be detected
below. */
xReceivedBytes = xReturned;
break;
}
else if( xReturned == 0 )
{
/* Timed out. */
break;
}
else
{
/* Keep a count of the bytes received so far. */
xReceivedBytes += xReturned;
}
}
/* If an error occurred it will be latched in xReceivedBytes,
otherwise xReceived bytes will be just that - the number of
bytes received from the echo server. */
if( xReceivedBytes > 0 )
{
/* Compare the transmitted string to the received string. */
configASSERT( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 );
if( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 )
{
/* The echo reply was received without error. */
ulTxRxCycles[ xInstance ]++;
}
else
{
/* The received string did not match the transmitted
string. */
ulTxRxFailures[ xInstance ]++;
break;
}
}
else if( xReceivedBytes < 0 )
{
/* FreeRTOS_recv() returned an error. */
break;
}
else
{
/* Timed out without receiving anything? */
break;
}
}
/* Finished using the connected socket, initiate a graceful close:
FIN, FIN+ACK, ACK. */
FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );
/* Expect FreeRTOS_recv() to return an error once the shutdown is
complete. */
xTimeOnEntering = xTaskGetTickCount();
do
{
xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */
&( pcReceivedString[ 0 ] ), /* The buffer into which the received data will be written. */
echoBUFFER_SIZES, /* The size of the buffer provided to receive the data. */
0 );
if( xReturned < 0 )
{
break;
}
} while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut );
}
else
{
printf( "Could not connect to server %ld\n", ret );
}
/* Close this socket before looping back to create another. */
FreeRTOS_closesocket( xSocket );
/* Pause for a short while to ensure the network is not too
congested. */
vTaskDelay( echoLOOP_DELAY );
}
}
/*-----------------------------------------------------------*/
static BaseType_t prvCreateTxData( char *cBuffer,
uint32_t ulBufferLength )
{
BaseType_t lCharactersToAdd, lCharacter;
char cChar = '0';
const BaseType_t lMinimumLength = 60;
/* Randomise the number of characters that will be sent in the echo
request. */
do
{
lCharactersToAdd = ipconfigRAND32() % ( ulBufferLength - 20UL );
} while( ( lCharactersToAdd == 0 ) || ( lCharactersToAdd < lMinimumLength ) ); /* Must be at least enough to add the unique text to the start of the string later. */
/* Fill the buffer. */
for( lCharacter = 0; lCharacter < lCharactersToAdd; lCharacter++ )
{
cBuffer[ lCharacter ] = cChar;
cChar++;
if( cChar > '~' )
{
cChar = '0';
}
}
return lCharactersToAdd;
}
/*-----------------------------------------------------------*/
BaseType_t xAreSingleTaskTCPEchoClientsStillRunning( void )
{
static uint32_t ulLastEchoSocketCount[ echoNUM_ECHO_CLIENTS ] = { 0 }, ulLastConnections[ echoNUM_ECHO_CLIENTS ] = { 0 };
BaseType_t xReturn = pdPASS, x;
/* Return fail is the number of cycles does not increment between
consecutive calls. */
for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ )
{
if( ulTxRxCycles[ x ] == ulLastEchoSocketCount[ x ] )
{
xReturn = pdFAIL;
}
else
{
ulLastEchoSocketCount[ x ] = ulTxRxCycles[ x ];
}
if( ulConnections[ x ] == ulLastConnections[ x ] )
{
xReturn = pdFAIL;
}
else
{
ulConnections[ x ] = ulLastConnections[ x ];
}
}
return xReturn;
}
#endif /* ipconfigUSE_TCP */

View File

@ -0,0 +1,39 @@
/*
* FreeRTOS V202112.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef SINGLE_TASK_TCP_ECHO_CLIENTS_H
#define SINGLE_TASK_TCP_ECHO_CLIENTS_H
/*
* Create the TCP echo client tasks. This is the version where an echo request
* is made from the same task that listens for the echo reply.
*/
void vStartTCPEchoClientTasks_SingleTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority );
BaseType_t xAreSingleTaskTCPEchoClientsStillRunning( void );
#endif /* SINGLE_TASK_TCP_ECHO_CLIENTS_H */

View File

@ -0,0 +1,321 @@
/*
* FreeRTOS Kernel V10.4.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for configuration information.
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html
*
*****************************************************************************/
#ifndef FREERTOS_IP_CONFIG_H
#define FREERTOS_IP_CONFIG_H
/* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to
* 1 then FreeRTOS_debug_printf should be defined to the function used to print
* out the debugging messages. */
#define ipconfigHAS_DEBUG_PRINTF 0
#if ( ipconfigHAS_DEBUG_PRINTF == 1 )
#define FreeRTOS_debug_printf( X ) printf X
//configPRINTF( X )
#endif
/* Set to 1 to print out non debugging messages, for example the output of the
* FreeRTOS_netstat() command, and ping replies. If ipconfigHAS_PRINTF is set to 1
* then FreeRTOS_printf should be set to the function used to print out the
* messages. */
#define ipconfigHAS_PRINTF 1
#if ( ipconfigHAS_PRINTF == 1 )
#define FreeRTOS_printf( X ) configPRINTF( X )
#endif
/* Define the byte order of the target MCU (the MCU FreeRTOS+TCP is executing
* on). Valid options are pdFREERTOS_BIG_ENDIAN and pdFREERTOS_LITTLE_ENDIAN. */
#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN
/* If the network card/driver includes checksum offloading (IP/TCP/UDP checksums)
* then set ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM to 1 to prevent the software
* stack repeating the checksum calculations. */
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1
/* Several API's will block until the result is known, or the action has been
* performed, for example FreeRTOS_send() and FreeRTOS_recv(). The timeouts can be
* set per socket, using setsockopt(). If not set, the times below will be
* used as defaults. */
#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME ( 5000 )
#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME ( 5000 )
/* Include support for DNS caching. For TCP, having a small DNS cache is very
* useful. When a cache is present, ipconfigDNS_REQUEST_ATTEMPTS can be kept low
* and also DNS may use small timeouts. If a DNS reply comes in after the DNS
* socket has been destroyed, the result will be stored into the cache. The next
* call to FreeRTOS_gethostbyname() will return immediately, without even creating
* a socket.
*/
#define ipconfigUSE_DNS_CACHE ( 1 )
#define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ( 6 )
#define ipconfigDNS_REQUEST_ATTEMPTS ( 2 )
/* The IP stack executes it its own task (although any application task can make
* use of its services through the published sockets API). ipconfigUDP_TASK_PRIORITY
* sets the priority of the task that executes the IP stack. The priority is a
* standard FreeRTOS task priority so can take any value from 0 (the lowest
* priority) to (configMAX_PRIORITIES - 1) (the highest priority).
* configMAX_PRIORITIES is a standard FreeRTOS configuration parameter defined in
* FreeRTOSConfig.h, not FreeRTOSIPConfig.h. Consideration needs to be given as to
* the priority assigned to the task executing the IP stack relative to the
* priority assigned to tasks that use the IP stack. */
#define ipconfigIP_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )
/* The size, in words (not bytes), of the stack allocated to the FreeRTOS+TCP
* task. This setting is less important when the FreeRTOS Win32 simulator is used
* as the Win32 simulator only stores a fixed amount of information on the task
* stack. FreeRTOS includes optional stack overflow detection, see:
* http://www.freertos.org/Stacks-and-stack-overflow-checking.html. */
#define ipconfigIP_TASK_STACK_SIZE_WORDS ( configMINIMAL_STACK_SIZE * 5 )
/* ipconfigRAND32() is called by the IP stack to generate random numbers for
* things such as a DHCP transaction number or initial sequence number. Random
* number generation is performed via this macro to allow applications to use their
* own random number generation method. For example, it might be possible to
* generate a random number by sampling noise on an analogue input. */
extern uint32_t ulRand();
#define ipconfigRAND32() ulRand()
/* If ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 then FreeRTOS+TCP will call the
* network event hook at the appropriate times. If ipconfigUSE_NETWORK_EVENT_HOOK
* is not set to 1 then the network event hook will never be called. See:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/vApplicationIPNetworkEventHook.shtml.
*/
#define ipconfigUSE_NETWORK_EVENT_HOOK 0
/* Sockets have a send block time attribute. If FreeRTOS_sendto() is called but
* a network buffer cannot be obtained then the calling task is held in the Blocked
* state (so other tasks can continue to executed) until either a network buffer
* becomes available or the send block time expires. If the send block time expires
* then the send operation is aborted. The maximum allowable send block time is
* capped to the value set by ipconfigMAX_SEND_BLOCK_TIME_TICKS. Capping the
* maximum allowable send block time prevents prevents a deadlock occurring when
* all the network buffers are in use and the tasks that process (and subsequently
* free) the network buffers are themselves blocked waiting for a network buffer.
* ipconfigMAX_SEND_BLOCK_TIME_TICKS is specified in RTOS ticks. A time in
* milliseconds can be converted to a time in ticks by dividing the time in
* milliseconds by portTICK_PERIOD_MS. */
#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( 5000U / portTICK_PERIOD_MS )
/* If ipconfigUSE_DHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP
* address, netmask, DNS server address and gateway address from a DHCP server. If
* ipconfigUSE_DHCP is 0 then FreeRTOS+TCP will use a static IP address. The
* stack will revert to using the static IP address even when ipconfigUSE_DHCP is
* set to 1 if a valid configuration cannot be obtained from a DHCP server for any
* reason. The static configuration used is that passed into the stack by the
* FreeRTOS_IPInit() function call. */
#define ipconfigUSE_DHCP 1
#define ipconfigDHCP_REGISTER_HOSTNAME 0
#define ipconfigDHCP_USES_UNICAST 1
/* If ipconfigDHCP_USES_USER_HOOK is set to 1 then the application writer must
* provide an implementation of the DHCP callback function,
* xApplicationDHCPUserHook(). */
#define ipconfigUSE_DHCP_HOOK 1
/* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at
* increasing time intervals until either a reply is received from a DHCP server
* and accepted, or the interval between transmissions reaches
* ipconfigMAXIMUM_DISCOVER_TX_PERIOD. The IP stack will revert to using the
* static IP address passed as a parameter to FreeRTOS_IPInit() if the
* re-transmission time interval reaches ipconfigMAXIMUM_DISCOVER_TX_PERIOD without
* a DHCP reply being received. */
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD \
( 120000U / portTICK_PERIOD_MS )
/* The ARP cache is a table that maps IP addresses to MAC addresses. The IP
* stack can only send a UDP message to a remove IP address if it knowns the MAC
* address associated with the IP address, or the MAC address of the router used to
* contact the remote IP address. When a UDP message is received from a remote IP
* address the MAC address and IP address are added to the ARP cache. When a UDP
* message is sent to a remote IP address that does not already appear in the ARP
* cache then the UDP message is replaced by a ARP message that solicits the
* required MAC address information. ipconfigARP_CACHE_ENTRIES defines the maximum
* number of entries that can exist in the ARP table at any one time. */
#define ipconfigARP_CACHE_ENTRIES 6
/* ARP requests that do not result in an ARP response will be re-transmitted a
* maximum of ipconfigMAX_ARP_RETRANSMISSIONS times before the ARP request is
* aborted. */
#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 )
/* ipconfigMAX_ARP_AGE defines the maximum time between an entry in the ARP
* table being created or refreshed and the entry being removed because it is stale.
* New ARP requests are sent for ARP cache entries that are nearing their maximum
* age. ipconfigMAX_ARP_AGE is specified in tens of seconds, so a value of 150 is
* equal to 1500 seconds (or 25 minutes). */
#define ipconfigMAX_ARP_AGE 150
/* Implementing FreeRTOS_inet_addr() necessitates the use of string handling
* routines, which are relatively large. To save code space the full
* FreeRTOS_inet_addr() implementation is made optional, and a smaller and faster
* alternative called FreeRTOS_inet_addr_quick() is provided. FreeRTOS_inet_addr()
* takes an IP in decimal dot format (for example, "192.168.0.1") as its parameter.
* FreeRTOS_inet_addr_quick() takes an IP address as four separate numerical octets
* (for example, 192, 168, 0, 1) as its parameters. If
* ipconfigINCLUDE_FULL_INET_ADDR is set to 1 then both FreeRTOS_inet_addr() and
* FreeRTOS_indet_addr_quick() are available. If ipconfigINCLUDE_FULL_INET_ADDR is
* not set to 1 then only FreeRTOS_indet_addr_quick() is available. */
#define ipconfigINCLUDE_FULL_INET_ADDR 1
/* ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS defines the total number of network buffer that
* are available to the IP stack. The total number of network buffers is limited
* to ensure the total amount of RAM that can be consumed by the IP stack is capped
* to a pre-determinable value. */
#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 60
/* A FreeRTOS queue is used to send events from application tasks to the IP
* stack. ipconfigEVENT_QUEUE_LENGTH sets the maximum number of events that can
* be queued for processing at any one time. The event queue must be a minimum of
* 5 greater than the total number of network buffers. */
#define ipconfigEVENT_QUEUE_LENGTH \
( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 )
/* The address of a socket is the combination of its IP address and its port
* number. FreeRTOS_bind() is used to manually allocate a port number to a socket
* (to 'bind' the socket to a port), but manual binding is not normally necessary
* for client sockets (those sockets that initiate outgoing connections rather than
* wait for incoming connections on a known port number). If
* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 then calling
* FreeRTOS_sendto() on a socket that has not yet been bound will result in the IP
* stack automatically binding the socket to a port number from the range
* socketAUTO_PORT_ALLOCATION_START_NUMBER to 0xffff. If
* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 then calling FreeRTOS_sendto()
* on a socket that has not yet been bound will result in the send operation being
* aborted. */
#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1
/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */
#define ipconfigUDP_TIME_TO_LIVE 128
/* Also defined in FreeRTOSIPConfigDefaults.h. */
#define ipconfigTCP_TIME_TO_LIVE 128
/* USE_TCP: Use TCP and all its features. */
#define ipconfigUSE_TCP ( 1 )
/* USE_WIN: Let TCP use windowing mechanism. */
#define ipconfigUSE_TCP_WIN ( 1 )
/* The MTU is the maximum number of bytes the payload of a network frame can
* contain. For normal Ethernet V2 frames the maximum MTU is 1500. Setting a
* lower value can save RAM, depending on the buffer management scheme used. If
* ipconfigCAN_FRAGMENT_OUTGOING_PACKETS is 1 then (ipconfigNETWORK_MTU - 28) must
* be divisible by 8. */
#define ipconfigNETWORK_MTU 1500U
/* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver. DNS is used
* through the FreeRTOS_gethostbyname() API function. */
#define ipconfigUSE_DNS 0
/* If ipconfigREPLY_TO_INCOMING_PINGS is set to 1 then the IP stack will
* generate replies to incoming ICMP echo (ping) requests. */
#define ipconfigREPLY_TO_INCOMING_PINGS 1
/* If ipconfigSUPPORT_OUTGOING_PINGS is set to 1 then the
* FreeRTOS_SendPingRequest() API function is available. */
#define ipconfigSUPPORT_OUTGOING_PINGS 1
/* If ipconfigSUPPORT_SELECT_FUNCTION is set to 1 then the FreeRTOS_select()
* (and associated) API function is available. */
#define ipconfigSUPPORT_SELECT_FUNCTION 1
/* If ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is set to 1 then Ethernet frames
* that are not in Ethernet II format will be dropped. This option is included for
* potential future IP stack developments. */
#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1 then it is the
* responsibility of the Ethernet interface to filter out packets that are of no
* interest. If the Ethernet interface does not implement this functionality, then
* set ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES to 0 to have the IP stack
* perform the filtering instead (it is much less efficient for the stack to do it
* because the packet will already have been passed into the stack). If the
* Ethernet driver does all the necessary filtering in hardware then software
* filtering can be removed by using a value other than 1 or 0. */
#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1
/* The windows simulator cannot really simulate MAC interrupts, and needs to
* block occasionally to allow other tasks to run. */
#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ( 20 / portTICK_PERIOD_MS )
/* Advanced only: in order to access 32-bit fields in the IP packets with
* 32-bit memory instructions, all packets will be stored 32-bit-aligned,
* plus 16-bits. This has to do with the contents of the IP-packets: all
* 32-bit fields are 32-bit-aligned, plus 16-bit. */
#define ipconfigPACKET_FILLER_SIZE 2U
/* Define the size of the pool of TCP window descriptors. On the average, each
* TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6
* outstanding packets (for Rx and Tx). When using up to 10 TP sockets
* simultaneously, one could define TCP_WIN_SEG_COUNT as 120. */
#define ipconfigTCP_WIN_SEG_COUNT 240
/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed
* maximum size. Define the size of Rx buffer for TCP sockets. */
#define ipconfigTCP_RX_BUFFER_LENGTH ( 10000 )
/* Define the size of Tx buffer for TCP sockets. */
#define ipconfigTCP_TX_BUFFER_LENGTH ( 10000 )
/* When using call-back handlers, the driver may check if the handler points to
* real program memory (RAM or flash) or just has a random non-zero value. */
#define ipconfigIS_VALID_PROG_ADDRESS( x ) ( ( x ) != NULL )
/* Include support for TCP keep-alive messages. */
#define ipconfigTCP_KEEP_ALIVE ( 1 )
#define ipconfigTCP_KEEP_ALIVE_INTERVAL ( 20 ) /* Seconds. */
/* The socket semaphore is used to unblock the MQTT task. */
#define ipconfigSOCKET_HAS_USER_SEMAPHORE ( 1 )
#define ipconfigSOCKET_HAS_USER_WAKE_CALLBACK ( 1 )
#define ipconfigUSE_CALLBACKS ( 0 )
#define portINLINE inline
#define USE_IPERF 1
#define ipconfigIPERF_DOES_ECHO_UDP 1
#define ipconfigIPERF_VERSION 3
#define ipconfigIPERF_STACK_SIZE_IPERF_TASK 680
#define ipconfigIPERF_TX_BUFSIZE ( 26 * ipconfigTCP_MSS )
#define ipconfigIPERF_TX_WINSIZE ( 26 )
#define ipconfigIPERF_RX_BUFSIZE ( 48 * ipconfigTCP_MSS )
#define ipconfigIPERF_RX_WINSIZE ( 48 )
/* The iperf module declares a character buffer to store its send data. */
#define ipconfigIPERF_RECV_BUFFER_SIZE ( 36 * ipconfigTCP_MSS )
#define ipconfigSUPPORT_SIGNALS 1
#endif /* FREERTOS_IP_CONFIG_H */

View File

@ -0,0 +1,629 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#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. */
/* These macros are used to define away static keyword for CBMC proofs */
#ifndef _static
#define _static static
#endif
/* 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 superseded - 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 /* if ipconfigUSE_TCP */
/*
* For debugging/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
#ifndef ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS
#define ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS pdMS_TO_TICKS( 5000U )
#endif
#ifndef ipconfigDNS_SEND_BLOCK_TIME_TICKS
#define ipconfigDNS_SEND_BLOCK_TIME_TICKS pdMS_TO_TICKS( 500U )
#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( ipFALSE_BOOL )
#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( ipFALSE_BOOL )
#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( ipFALSE_BOOL )
#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 randomized 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( 20U ) )
#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 ipconfigUSE_LINKED_RX_MESSAGES
#define ipconfigUSE_LINKED_RX_MESSAGES 0
#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
/* Configuration to control whether packets with IP options,
* received over the network, should be passed up to the
* software stack OR should be dropped.
* If set to 1, the stack accepts IP packets that contain IP options, but does
* not process the options (IP options are not supported).
* If set to 0, the stack will drop IP packets that contain IP options.
*/
#ifndef ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS
#define ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS 1
#endif
/* Configuration to control whether UDP packets with
* checksum value of zero should be passed up the software
* stack OR should be dropped.
* If set to 1, the stack will accept UDP packets that have their checksum
* value set to 0.
* If set to 0, the stack will drop UDP packets that have their checksum value
* set to 0.
*/
#ifndef ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS
#define ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS 0
#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 positive 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
#else
#if ipconfigNETWORK_MTU > ( SIZE_MAX >> 1 )
#undef ipconfigNETWORK_MTU
#define ipconfigNETWORK_MTU ( SIZE_MAX >> 1 )
#endif
#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( 999U ) )
#else
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 30000U ) )
#endif /* _WINDOWS_ */
#endif /* ipconfigMAXIMUM_DISCOVER_TX_PERIOD */
#if ( ipconfigUSE_DNS == 0 )
/* The DNS module will not be included. */
#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 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
/* Per https://tools.ietf.org/html/rfc1035, 253 is the maximum string length
* of a DNS name. The following default accounts for a null terminator. */
#define ipconfigDNS_CACHE_NAME_LENGTH 254U
#endif
#ifndef ipconfigDNS_CACHE_ENTRIES
#define ipconfigDNS_CACHE_ENTRIES 1
#endif
#endif /* ipconfigUSE_DNS_CACHE != 0 */
/* When accessing services which have multiple IP addresses, setting this
* greater than 1 can improve reliability by returning different IP address
* answers on successive calls to FreeRTOS_gethostbyname(). */
#ifndef ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY
#define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY 1
#endif
#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
#ifndef ipconfigREPLY_TO_INCOMING_PINGS
#define ipconfigREPLY_TO_INCOMING_PINGS 1
#endif
#ifndef ipconfigSUPPORT_OUTGOING_PINGS
#define ipconfigSUPPORT_OUTGOING_PINGS 1
#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 ipconfigSOCKET_HAS_USER_WAKE_CALLBACK
#define ipconfigSOCKET_HAS_USER_WAKE_CALLBACK 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
/* As an attack surface reduction for ports that listen for inbound
* connections, hang protection can help reduce the impact of SYN floods. */
#ifndef ipconfigTCP_HANG_PROTECTION
#define ipconfigTCP_HANG_PROTECTION 1
#endif
/* Non-activity timeout is expressed in seconds. */
#ifndef ipconfigTCP_HANG_PROTECTION_TIME
#define ipconfigTCP_HANG_PROTECTION_TIME 30U
#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 0U
#endif
#ifndef ipconfigPACKET_FILLER_SIZE
#define ipconfigPACKET_FILLER_SIZE 2U
#endif
#ifndef ipconfigSELECT_USES_NOTIFY
#define ipconfigSELECT_USES_NOTIFY 0
#endif
#endif /* FREERTOS_DEFAULT_IP_CONFIG_H */

View File

@ -0,0 +1,147 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#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. */
/*-----------------------------------------------------------*/
/**
* Structure for one row in the ARP cache table.
*/
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;
/*
* 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 gratuitous 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 );
/* This function will check if the target IP-address belongs to this device.
* If so, the packet will be passed to the IP-stack, who will answer it.
* The function is to be called within the function xNetworkInterfaceOutput()
* in NetworkInterface.c as follows:
*
* if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )
* {
* / * The packet has been sent back to the IP-task.
* * The IP-task will further handle it.
* * Do not release the descriptor.
* * /
* return pdTRUE;
* }
* / * Send the packet as usual. * /
*/
BaseType_t xCheckLoopback( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t bReleaseAfterSend );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_ARP_H */

View File

@ -0,0 +1,122 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#ifndef FREERTOS_DHCP_H
#define FREERTOS_DHCP_H
#ifdef __cplusplus
extern "C" {
#endif
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "IPTraceMacroDefaults.h"
#if ( ipconfigUSE_DHCP_HOOK != 0 )
/* 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. */
eDHCPPhaseFinished
} 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;
#endif /* #if( ipconfigUSE_DHCP_HOOK != 0 ) */
/* DHCP state machine states. */
typedef enum
{
eInitialWait = 0, /**< Initial state: open a socket and wait a short time. */
eWaitingSendFirstDiscover, /**< Send a discover the first time it is called, and reset all timers. */
eWaitingOffer, /**< Either resend the discover, or, if the offer is forthcoming, send a request. */
eWaitingAcknowledge, /**< Either resend the request. */
eSendDHCPRequest, /**< Sendto failed earlier, resend the request to lease the IP-address offered. */
#if ( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
eGetLinkLayerAddress, /* When DHCP didn't respond, try to obtain a LinkLayer address 168.254.x.x. */
#endif
eLeasedAddress, /**< Resend the request at the appropriate time to renew the lease. */
eNotUsingLeasedAddress /**< DHCP failed, and a default IP address is being used. */
} eDHCPState_t;
/**
* Hold information in between steps in the DHCP state machine.
*/
struct xDHCP_DATA
{
uint32_t ulTransactionId; /**< The ID of the DHCP transaction */
uint32_t ulOfferedIPAddress; /**< The IP address offered by the DHCP server */
uint32_t ulDHCPServerAddress; /**< The IP address of the DHCP server */
uint32_t ulLeaseTime; /**< The time for which the current IP address is leased */
TickType_t xDHCPTxTime; /**< The time at which a DHCP request was sent. */
TickType_t xDHCPTxPeriod; /**< The maximum time that the client will wait for a reply. */
BaseType_t xUseBroadcast; /**< Try both without and with the broadcast flag */
eDHCPState_t eDHCPState; /**< Maintains the DHCP state machine state. */
};
typedef struct xDHCP_DATA DHCPData_t;
/* Returns the current state of a DHCP process. */
eDHCPState_t eGetDHCPState( void );
/*
* Send a message to the IP-task, which will call vDHCPProcess().
*
*/
BaseType_t xSendDHCPEvent( void );
/*
* NOT A PUBLIC API FUNCTION.
* It will be called when the DHCP timer expires, or when
* data has been received on the DHCP socket.
*/
void vDHCPProcess( BaseType_t xReset,
eDHCPState_t eExpectedState );
/* Internal call: returns true if socket is the current DHCP socket */
BaseType_t xIsDHCPSocket( Socket_t xSocket );
#if ( ipconfigUSE_DHCP_HOOK != 0 )
/* 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 );
#endif /* ( ipconfigUSE_DHCP_HOOK != 0 ) */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_DHCP_H */

View File

@ -0,0 +1,38 @@
#ifndef _DHCPSERVER_H
#define _DHCPSERVER_H
#ifndef DHCPSERVER_LEASE_TIME
#define DHCPSERVER_LEASE_TIME (864000)
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Start DHCP server.
Static IP of server should already be set and network interface enabled.
first_client_addr is the IP address of the first lease to be handed
to a client. Subsequent lease addresses are calculated by
incrementing the final octet of the IPv4 address, up to max_leases.
*/
void dhcpserver_start(const uint8_t ucIPAddress[4], uint32_t first_client_addr, uint8_t max_leases);
/* Stop DHCP server.
*/
void dhcpserver_stop(void);
/* Set a router address to send as an option. */
void dhcpserver_set_router(uint32_t router);
/* Set a DNS address to send as an option. */
void dhcpserver_set_dns(uint32_t dns);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,151 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#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 0xE00000FCUL
#else
#define ipLLMNR_IP_ADDR 0xFC0000E0UL
#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. */
#if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 )
/*
* 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 );
#endif /* ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 ) */
/*
* LLMNR is very similar to DNS, so is handled by the DNS routines.
*/
uint32_t ulDNSHandlePacket( const NetworkBufferDescriptor_t * pxNetworkBuffer );
#if ( ipconfigUSE_LLMNR == 1 )
/* The LLMNR MAC address is 01:00:5e:00:00:fc */
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 )
/* Look for the indicated host name in the DNS cache. Returns the IPv4
* address if present, or 0x0 otherwise. */
uint32_t FreeRTOS_dnslookup( const char * pcHostName );
/* Remove all entries from the DNS cache. */
void FreeRTOS_dnsclear( void );
#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 uxTimeout );
void FreeRTOS_gethostbyname_cancel( void * pvSearchID );
#endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */
/*
* Lookup a IPv4 node in a blocking-way.
* It returns a 32-bit IP-address, 0 when not found.
* gethostbyname() is already deprecated.
*/
uint32_t FreeRTOS_gethostbyname( const char * pcHostName );
#if ( ipconfigDNS_USE_CALLBACKS == 1 )
/*
* The function vDNSInitialise() initialises the DNS module.
* It will be called "internally", by the IP-task.
*/
void vDNSInitialise( void );
#endif /* ( ipconfigDNS_USE_CALLBACKS == 1 ) */
#if ( ipconfigDNS_USE_CALLBACKS == 1 )
/*
* A function local to the library.
*/
extern void vDNSCheckCallBack( void * pvSearchID );
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_DNS_H */

View File

@ -0,0 +1,434 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#ifndef FREERTOS_IP_H
#define FREERTOS_IP_H
#ifdef __cplusplus
extern "C" {
#endif
#include "FreeRTOS.h"
#include "task.h"
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "FreeRTOSIPConfigDefaults.h"
#include "IPTraceMacroDefaults.h"
/* Some constants defining the sizes of several parts of a packet.
* These defines come before including the configuration header files. */
/* The size of the Ethernet header is 14, meaning that 802.1Q VLAN tags
* are not ( yet ) supported. */
#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
#define ipSIZE_OF_IPv4_ADDRESS 4U
/*
* Generate a randomized TCP Initial Sequence Number per RFC.
* This function must be provided by the application builder.
*/
/* This function is defined generally by the application. */
extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
uint16_t usSourcePort,
uint32_t ulDestinationAddress,
uint16_t usDestinationPort );
/* 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 ( 1U )
#define ipPROTOCOL_IGMP ( 2U )
#define ipPROTOCOL_TCP ( 6U )
#define ipPROTOCOL_UDP ( 17U )
/* The character used to fill ICMP echo requests, and therefore also the
* character expected to fill ICMP echo replies. */
#define ipECHO_DATA_FILL_BYTE 'x'
/* 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 )
/* 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"
/**
* MAC address structure.
*/
struct xMAC_ADDRESS
{
uint8_t ucBytes[ ipMAC_ADDRESS_LENGTH_BYTES ]; /**< Byte array of the MAC address */
};
#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;
/* MISRA check: some modules refer to this typedef even though
* ipconfigSUPPORT_OUTGOING_PINGS is not enabled. */
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;
/**
* The software timer struct for various IP functions
*/
typedef struct xIP_TIMER
{
uint32_t
bActive : 1, /**< This timer is running and must be processed. */
bExpired : 1; /**< Timer has expired and a task must be processed. */
TimeOut_t xTimeOut; /**< The timeout value. */
TickType_t ulRemainingTime; /**< The amount of time remaining. */
TickType_t ulReloadTime; /**< The value of reload time. */
} IPTimer_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 /* ifndef FreeRTOS_htonl */
#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 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_min_BaseType( BaseType_t a,
BaseType_t b )
{
return ( a <= b ) ? a : b;
}
#else /* if ( ipconfigHAS_INLINE_FUNCTIONS == 1 ) */
#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: divide a by d and round=up the result. */
#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_min_BaseType( a, b ) ( ( ( BaseType_t ) ( a ) ) <= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) )
#endif /* ipconfigHAS_INLINE_FUNCTIONS */
#define ipMS_TO_MIN_TICKS( xTimeInMs ) ( ( pdMS_TO_TICKS( ( xTimeInMs ) ) < ( ( TickType_t ) 1U ) ) ? ( ( TickType_t ) 1U ) : pdMS_TO_TICKS( ( xTimeInMs ) ) )
/* For backward compatibility. */
#define pdMS_TO_MIN_TICKS( xTimeInMs ) ipMS_TO_MIN_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 ( 1U )
#define pdFALSE_UNSIGNED ( 0U )
#define ipTRUE_BOOL ( 1 == 1 )
#define ipFALSE_BOOL ( 1 == 2 )
#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 uxRequestedSizeBytes,
TickType_t uxBlockTimeTicks );
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 );
/* MISRA defining 'FreeRTOS_SendPingRequest' should be dependent on 'ipconfigSUPPORT_OUTGOING_PINGS'.
* In order not to break some existing project, define it unconditionally. */
BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress,
size_t uxNumberOfBytesToSend,
TickType_t uxBlockTimeTicks );
void FreeRTOS_ReleaseUDPPayloadBuffer( void const * pvBuffer );
const uint8_t * FreeRTOS_GetMACAddress( void );
void FreeRTOS_UpdateMACAddress( const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );
#if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )
/* This function shall be defined by the application. */
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
#endif
#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
void vApplicationPingReplyHook( ePingReplyStatus_t eStatus,
uint16_t usIdentifier );
#endif
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
#if ( ipconfigHAS_PRINTF != 0 )
extern void vPrintResourceStats( void );
#else
#define vPrintResourceStats() do {} while( ipFALSE_BOOL )
#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
*/
#if ( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) )
const char * FreeRTOS_GetTCPStateName( UBaseType_t ulState );
#endif
/* _HT_ Temporary: show all valid ARP entries
*/
#if ( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 )
void FreeRTOS_PrintARPCache( void );
#endif
void FreeRTOS_ClearARP( void );
/* Return pdTRUE if the IPv4 address is a multicast address. */
BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress );
/* Set the MAC-address that belongs to a given IPv4 multi-cast address. */
void vSetMultiCastIPv4MacAddress( uint32_t ulIPAddress,
MACAddress_t * pxMACAddress );
#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. */
/* Typically this function is defined in a user module. */
const char * pcApplicationHostnameHook( void );
#endif /* ipconfigDHCP_REGISTER_HOSTNAME */
/* This xApplicationGetRandomNumber() will set *pulNumber to a random number,
* and return pdTRUE. When the random number generator is broken, it shall return
* pdFALSE.
* The function is defined in 'iot_secure_sockets.c'.
* If that module is not included in the project, the application must provide an
* implementation of it.
* The macro's ipconfigRAND32() and configRAND32() are not in use anymore. */
/* "xApplicationGetRandomNumber" is declared but never defined, because it may
* be defined in a user module. */
extern BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber );
/* 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
void setDhcpClientState(BaseType_t on);
int getDhcpClientState();
void dump_net_pack(NetworkBufferDescriptor_t * pxNetworkBuffer, int port, int is_send);
#endif /* FREERTOS_IP_H */

View File

@ -0,0 +1,520 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#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 ( ( Socket_t ) ~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 ) /* Temporarily 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
#if ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
#define FREERTOS_SO_WAKEUP_CALLBACK ( 17 )
#endif
#define FREERTOS_SO_SET_LOW_HIGH_WATER ( 18 )
#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(). */
/**
* Structure to hold the properties of Tx/Rx buffers and windows.
*/
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;
/**
* Structure to pass for the 'FREERTOS_SO_SET_LOW_HIGH_WATER' option
*/
typedef struct xLOW_HIGH_WATER
{
size_t uxLittleSpace; /**< Send a STOP when buffer space drops below X bytes */
size_t uxEnoughSpace; /**< Send a GO when buffer space grows above X bytes */
} LowHighWater_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; /**< The port */
uint32_t sin_addr; /**< The IP address */
};
extern const char * FreeRTOS_inet_ntoa( uint32_t ulIPAddress,
char * pcBuffer );
#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 ) ) )
#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 ) ) )
#endif /* ipconfigBYTE_ORDER */
/* The socket type itself. */
struct xSOCKET;
typedef struct xSOCKET * Socket_t;
typedef struct xSOCKET const * ConstSocket_t;
static portINLINE BaseType_t xSocketValid( Socket_t xSocket )
{
BaseType_t xReturnValue = pdFALSE;
/*
* There are two values which can indicate an invalid socket:
* FREERTOS_INVALID_SOCKET and NULL. In order to compare against
* both values, the code cannot be compliant with rule 11.4,
* hence the Coverity suppression statement below.
*/
/* coverity[misra_c_2012_rule_11_4_violation] */
if( ( xSocket != FREERTOS_INVALID_SOCKET ) && ( xSocket != NULL ) )
{
xReturnValue = pdTRUE;
}
return xReturnValue;
}
#if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
/* The SocketSet_t type is the equivalent to the fd_set type used by the
* Berkeley API. */
struct xSOCKET_SET;
typedef struct xSOCKET_SET * SocketSet_t;
#endif /* ( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) */
/**
* 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 uxBufferLength,
BaseType_t xFlags,
struct freertos_sockaddr * pxSourceAddress,
socklen_t * pxSourceAddressLength );
int32_t FreeRTOS_sendto( Socket_t xSocket,
const void * pvBuffer,
size_t uxTotalDataLength,
BaseType_t xFlags,
const struct freertos_sockaddr * pxDestinationAddress,
socklen_t xDestinationAddressLength );
BaseType_t FreeRTOS_bind( Socket_t xSocket,
struct freertos_sockaddr const * pxAddress,
socklen_t xAddressLength );
/* function to get the local address and IP port */
size_t FreeRTOS_GetLocalAddress( ConstSocket_t xSocket,
struct freertos_sockaddr * pxAddress );
#if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
/* Returns true if an UDP socket exists bound to mentioned port number. */
BaseType_t xPortHasUDPSocket( uint16_t usPortNr );
#endif
#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 uxBufferLength,
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( ConstSocket_t xSocket,
struct freertos_sockaddr * pxAddress );
#if ( ipconfigUSE_TCP == 1 )
/* Returns pdTRUE if TCP socket is connected. */
BaseType_t FreeRTOS_issocketconnected( ConstSocket_t xSocket );
/* Returns the actual size of MSS being used. */
BaseType_t FreeRTOS_mss( ConstSocket_t xSocket );
#endif /* ( ipconfigUSE_TCP == 1 ) */
/* For internal use only: return the connection status. */
BaseType_t FreeRTOS_connstatus( ConstSocket_t xSocket );
/* Returns the number of bytes that may be added to txStream */
BaseType_t FreeRTOS_maywrite( ConstSocket_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
*/
#if ( ipconfigUSE_TCP == 1 )
BaseType_t FreeRTOS_rx_size( ConstSocket_t xSocket );
BaseType_t FreeRTOS_tx_space( ConstSocket_t xSocket );
BaseType_t FreeRTOS_tx_size( ConstSocket_t xSocket );
#endif
/* 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( ConstSocket_t xSocket,
BaseType_t * pxLength );
#endif /* ipconfigUSE_TCP */
#if ( ipconfigUSE_CALLBACKS != 0 )
/*
* 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 ) );
*/
#ifdef __COVERITY__
typedef void (* FOnConnected_t )( Socket_t xSocket,
BaseType_t ulConnected );
#else
typedef void (* FOnConnected_t )( Socket_t,
BaseType_t );
#endif
/*
* 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 uxLength )
* {
* // 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 ) );
*/
#ifdef __COVERITY__
typedef BaseType_t (* FOnTCPReceive_t )( Socket_t xSocket,
void * pData,
size_t xLength );
typedef void (* FOnTCPSent_t )( Socket_t xSocket,
size_t xLength );
#else
typedef BaseType_t (* FOnTCPReceive_t )( Socket_t,
void *,
size_t );
typedef void (* FOnTCPSent_t )( Socket_t,
size_t );
#endif /* ifdef __COVERITY__ */
/*
* 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
*/
#ifdef __COVERITY__
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 );
#else
typedef BaseType_t (* FOnUDPReceive_t ) ( Socket_t,
void *,
size_t,
const struct freertos_sockaddr *,
const struct freertos_sockaddr * );
typedef void (* FOnUDPSent_t )( Socket_t,
size_t );
#endif /* ifdef __COVERITY__ */
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;
#endif /* ( ipconfigUSE_CALLBACKS != 0 ) */
BaseType_t FreeRTOS_setsockopt( Socket_t xSocket,
int32_t lLevel,
int32_t lOptionName,
const void * pvOptionValue,
size_t uxOptionLength );
BaseType_t FreeRTOS_closesocket( Socket_t xSocket );
/* The following function header should be placed in FreeRTOS_DNS.h.
* It is kept here because some applications expect it in FreeRTOS_Sockets.h.*/
#ifndef __COVERITY__
uint32_t FreeRTOS_gethostbyname( const char * pcHostName );
#endif
BaseType_t FreeRTOS_inet_pton( BaseType_t xAddressFamily,
const char * pcSource,
void * pvDestination );
const char * FreeRTOS_inet_ntop( BaseType_t xAddressFamily,
const void * pvSource,
char * pcDestination,
socklen_t uxSize );
/* Convert a null-terminated string in dot-decimal-notation (d.d.d.d) to a 32-bit unsigned integer. */
uint32_t FreeRTOS_inet_addr( const char * pcIPAddress );
BaseType_t FreeRTOS_inet_pton4( const char * pcSource,
void * pvDestination );
const char * FreeRTOS_inet_ntop4( const void * pvSource,
char * pcDestination,
socklen_t uxSize );
/*
* 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( ConstSocket_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 */

View File

@ -0,0 +1,266 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*
* FreeRTOS_Stream_Buffer.h
*
* A circular character buffer
* An implementation of a circular buffer without a length field
* If LENGTH defines the size of the buffer, a maximum of (LENGTH-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
/**
* structure to store all the details of a stream buffer.
*/
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 ) ]; /**< array big enough to store any pointer address */
} 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 );
size_t uxMoveCount = uxCount;
if( uxMoveCount > uxSize )
{
uxMoveCount = uxSize;
}
pxBuffer->uxMid += uxMoveCount;
if( pxBuffer->uxMid >= pxBuffer->LENGTH )
{
pxBuffer->uxMid -= pxBuffer->LENGTH;
}
}
/*-----------------------------------------------------------*/
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 ) ? 1U : 0U ) ^ ( ( uxRight < uxTail ) ? 1U : 0U ) ) != 0U )
{
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 uxByteCount );
/*
* 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 ) */

View File

@ -0,0 +1,68 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#ifndef FREERTOS_TCP_IP_H
#define FREERTOS_TCP_IP_H
#ifdef __cplusplus
extern "C" {
#endif
BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t * pxDescriptor );
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, /* 9 (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
eLAST_ACK, /*10 (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, /*11 (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 */

View File

@ -0,0 +1,237 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*
* 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
/**
* The name xTCPTimer was already use as the name of an IP-timer.
*/
typedef struct xTCPTimerStruct
{
uint32_t ulBorn; /**< The time when this timer is created. */
} TCPTimer_t;
/**
* Structure to hold the information about a TCP segment.
*/
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; /**< Use a union to store the 32-bit flag field and the breakdown in the same location. */
#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 xSegmentItem; /**< With this item the segment can be connected to a list, depending on who is owning it */
#endif
} TCPSegment_t;
/**
* Structure to store the Rx/Tx window length.
*/
typedef struct xTCP_WINSIZE
{
uint32_t ulRxWindowLength; /**< The size of the receive window. */
uint32_t ulTxWindowLength; /**< The size of the send window. */
} 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 )
#define ipSIZE_TCP_OPTIONS 16U
#else
#define ipSIZE_TCP_OPTIONS 12U
#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; /**< Use a union to store the 32-bit flag field and the breakdown at the same place. */
TCPWinSize_t xSize; /**< Size of the TCP window. */
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 */
} rx, /**< Structure for the receiver for TCP. */
tx; /**< Structure for the transmitter for TCP. */
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 const * pxWindow );
/* Initialize a window */
void vTCPWindowInit( TCPWindow_t * pxWindow,
uint32_t ulAckNumber,
uint32_t ulSequenceNumber,
uint32_t ulMSS );
/* Clean up allocated segments. Should only be called when FreeRTOS+TCP will no longer be used. */
void vTCPSegmentCleanup( void );
/*=============================================================================
*
* 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 );
/* 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( const TCPWindow_t * pxWindow );
/*=============================================================================
*
* 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 const * 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( const TCPWindow_t * pxWindow );
/* Fetches data to be sent.
* plPosition 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 */

View File

@ -0,0 +1,43 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#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 */

View File

@ -0,0 +1,96 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#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_EAFNOSUPPORT 97 /* Address family not supported by protocol */
#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
#else /* ifndef pdFREERTOS_ERRNO_NONE */
#ifndef pdFREERTOS_ERRNO_EAFNOSUPPORT
#define pdFREERTOS_ERRNO_EAFNOSUPPORT 97 /* Address family not supported by protocol */
#endif /* pdFREERTOS_ERRNO_EAFNOSUPPORT */
#endif /* pdFREERTOS_ERRNO_NONE */
/* Translate a pdFREERTOS_ERRNO code to a human readable string. */
const char * FreeRTOS_strerror_r( BaseType_t xErrnum,
char * pcBuffer,
size_t uxLength );
#endif /* FREERTOS_ERRNO_TCP */

View File

@ -0,0 +1,243 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/* 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 iptraceNETWORK_INTERFACE_INPUT
/* An Ethernet packet has been received. */
#define iptraceNETWORK_INTERFACE_INPUT( uxDataLength, pucEthernetBuffer )
#endif
#ifndef iptraceNETWORK_INTERFACE_OUTPUT
/* An Ethernet packet will be sent. */
#define iptraceNETWORK_INTERFACE_OUTPUT( uxDataLength, pucEthernetBuffer )
#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
#ifndef ipconfigUSE_TCP_MEM_STATS
#define ipconfigUSE_TCP_MEM_STATS 0
#endif
#if ( ipconfigUSE_TCP_MEM_STATS == 0 )
/* See tools/tcp_mem_stat.c */
#ifndef iptraceMEM_STATS_CREATE
#define iptraceMEM_STATS_CREATE( xMemType, pxObject, uxSize )
#endif
#ifndef iptraceMEM_STATS_DELETE
#define iptraceMEM_STATS_DELETE( pxObject )
#endif
#ifndef iptraceMEM_STATS_CLOSE
#define iptraceMEM_STATS_CLOSE()
#endif
#endif /* ( ipconfigUSE_TCP_MEM_STATS != 0 ) */
#ifndef ipconfigUSE_DUMP_PACKETS
#define ipconfigUSE_DUMP_PACKETS 0
#endif
#if ( ipconfigUSE_DUMP_PACKETS == 0 )
/* See tools/tcp_dump_packets.c */
#ifndef iptraceDUMP_INIT
#define iptraceDUMP_INIT( pcFileName, pxEntries )
#endif
#ifndef iptraceDUMP_PACKET
#define iptraceDUMP_PACKET( pucBuffer, uxLength, xIncoming )
#endif
#endif /* ( ipconfigUSE_DUMP_PACKETS != 0 ) */
#endif /* UDP_TRACE_MACRO_DEFAULTS_H */

View File

@ -0,0 +1,76 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#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 );
/* The definition of the below function is only available if BufferAllocation_2.c has been linked into the source. */
NetworkBufferDescriptor_t * pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes );
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer );
/* The definition of the below function is only available if BufferAllocation_2.c has been linked into the source. */
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( const NetworkBufferDescriptor_t * const pxNetworkBuffer,
size_t uxNewLength );
/* 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 */

View File

@ -0,0 +1,48 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#ifndef NETWORK_INTERFACE_H
#define NETWORK_INTERFACE_H
#ifdef __cplusplus
extern "C" {
#endif
/* INTERNAL API FUNCTIONS. */
BaseType_t xNetworkInterfaceInitialise( void );
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
BaseType_t xReleaseAfterSend );
/* The following function is defined only when BufferAllocation_1.c is linked in the project. */
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] );
/* The following function is defined only when BufferAllocation_1.c is linked in the project. */
BaseType_t xGetPhyLinkStatus( void );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* NETWORK_INTERFACE_H */

View File

@ -0,0 +1,16 @@
/*
* iperf_task.c
*/
#ifndef IPERF_TASK_H_
#define IPERF_TASK_H_
/* This function will start a task that will handl all IPERF requests from outside.
Call it after the IP-stack is up and running. */
#define ipconfigIPERF_HAS_TCP 1
#define ipconfigIPERF_HAS_UDP 1
void vIPerfInstall( void );
#endif

View File

@ -0,0 +1,984 @@
/*
A FreeRTOS+TCP demo program:
A simple example of a TCP/UDP iperf server, see https://iperf.fr
It uses a single task which will store some client information in a:
List_t xTCPClientList;
The task will sleep constantly by calling:
xResult = FreeRTOS_select( xSocketSet, xBlockingTime );
Command examples for testing:
iperf3 -c 192.168.2.114 --port 5001 --bytes 100M
iperf3 -c 192.168.2.114 --port 5001 --bytes 100M -R
iperf3 -c fe80::8d11:cd9b:8b66:4a80 --port 5001 --bytes 1M
iperf3 -c fe80::8d11:cd9b:8b66:4a81 --port 5001 --bytes 1M
iperf3 -c fe80::6802:9887:8670:b37c --port 5001 --bytes 1M
ping fe80::8d11:cd9b:8b66:4a80
ping fe80::8d11:cd9b:8b66:4a81
iperf3 -s --port 5001
iperf3 -c zynq --port 5001 --bytes 1024
iperf3 -c laptop --port 5001 --bytes 1024
fe80::8d11:cd9b:8b66:4a80
TCP : iperf3 -c 192.168.2.116 --port 5001 --bytes 1024
UDP : iperf3 -c 192.168.2.116 --port 5001 --udp --bandwidth 50M --mss 1460 --bytes 1024
*/
/* Standard includes. */
#include <stdio.h>
#include <time.h>
/* FreeRTOS includes. */
#include <FreeRTOS.h>
#include "task.h"
#include "timers.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_TCP_IP.h"
#include "iperf_task.h"
/* Put the TCP server at this port number: */
#ifndef ipconfigIPERF_TCP_ECHO_PORT
/* 5001 seems to be the standard TCP server port number. */
#define ipconfigIPERF_TCP_ECHO_PORT 5001
#endif
/* Put the TCP server at this port number: */
#ifndef ipconfigIPERF_UDP_ECHO_PORT
/* 5001 seems to be the standard UDP server port number. */
#define ipconfigIPERF_UDP_ECHO_PORT 5001
#endif
#ifndef ipconfigIPERF_STACK_SIZE_IPERF_TASK
/* Stack size needed for vIPerfTask(), a bit of a guess: */
#define ipconfigIPERF_STACK_SIZE_IPERF_TASK 340
#endif
#ifndef ipconfigIPERF_PRIORITY_IPERF_TASK
/* The priority of vIPerfTask(). Should be lower than the IP-task
and the task running in NetworkInterface.c. */
#define ipconfigIPERF_PRIORITY_IPERF_TASK 3
#endif
#ifndef ipconfigIPERF_RECV_BUFFER_SIZE
/* Only used when ipconfigIPERF_USE_ZERO_COPY = 0.
Buffer size when reading from the sockets. */
#define ipconfigIPERF_RECV_BUFFER_SIZE ( 4 * ipconfigTCP_MSS )
#endif
#ifndef ipconfigIPERF_LOOP_BLOCKING_TIME_MS
/* Let the mainloop wake-up so now and then. */
#define ipconfigIPERF_LOOP_BLOCKING_TIME_MS 5000UL
#endif
#ifndef ipconfigIPERF_HAS_TCP
/* A TCP server socket will be created. */
#define ipconfigIPERF_HAS_TCP 1
#endif
#ifndef ipconfigIPERF_HAS_UDP
/* A UDP server socket will be created. */
#define ipconfigIPERF_HAS_UDP 1
#endif
#ifndef ipconfigIPERF_DOES_ECHO_UDP
/* By default, this server will echo UDP data as required by iperf. */
#define ipconfigIPERF_DOES_ECHO_UDP 1
#endif
#ifndef ipconfigIPERF_USE_ZERO_COPY
#define ipconfigIPERF_USE_ZERO_COPY 1
#endif
#ifndef ipconfigIPERF_TX_BUFSIZE
#define ipconfigIPERF_TX_BUFSIZE ( 65 * 1024 ) /* Units of bytes. */
#define ipconfigIPERF_TX_WINSIZE ( 4 ) /* Size in units of MSS */
#define ipconfigIPERF_RX_BUFSIZE ( ( 65 * 1024 ) - 1 ) /* Units of bytes. */
#define ipconfigIPERF_RX_WINSIZE ( 8 ) /* Size in units of MSS */
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (BaseType_t)(sizeof(x)/sizeof(x)[0])
#endif
void vIPerfTask( void *pvParameter );
/* As for now, still defined in 'FreeRTOS-Plus-TCP\FreeRTOS_TCP_WIN.c' : */
extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere );
static portINLINE void vListInsertFifo( List_t * const pxList, ListItem_t * const pxNewListItem )
{
vListInsertGeneric( pxList, pxNewListItem, &pxList->xListEnd );
}
#if( ipconfigIPERF_VERSION == 3 )
typedef enum
{
eTCP_0_WaitName, /* Expect a text like "osboxes.1460335312.612572.527642c36f" */
eTCP_1_WaitCount,
eTCP_2_WaitHeader,
eTCP_3_WaitOneTwo,
eTCP_4_WaitCount2,
eTCP_5_WaitHeader2,
eTCP_6_WaitDone,
eTCP_7_WaitTransfer
} eTCP_Server_Status_t;
#endif
typedef struct
{
Socket_t xServerSocket;
#if( ipconfigIPERF_VERSION == 3 )
struct {
uint32_t
bIsControl : 1,
bReverse : 1,
bTimed : 1, /* Reverse role, limited time. */
bTimedOut : 1, /* TIme is up. */
bHasShutdown : 1;
} bits;
eTCP_Server_Status_t eTCP_Status;
uint32_t ulSkipCount, ulAmount;
uint32_t xRemainingTime;
TimeOut_t xTimeOut;
#endif /* ipconfigIPERF_VERSION == 3 */
#if( ipconfigUSE_IPv6 != 0 )
struct freertos_sockaddr6 xRemoteAddr;
#else
struct freertos_sockaddr xRemoteAddr;
#endif
uint32_t ulRecvCount;
struct xLIST_ITEM xListItem; /* With this item the client will be bound to a List_t. */
} TcpClient_t;
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
struct xRawBuffer {
char pcBuffer[ ipconfigIPERF_RECV_BUFFER_SIZE ];
} *pxRawBuffer;
#define pcSendBuffer ( pxRawBuffer->pcBuffer )
static char *pcRecvBuffer;
#else
struct xRawBuffer {
char pcBuffer[ ipconfigIPERF_RECV_BUFFER_SIZE ];
} *pxRawBuffer;
#define pcRecvBuffer ( pxRawBuffer->pcBuffer )
#define pcSendBuffer ( pxRawBuffer->pcBuffer )
#endif
#if( ipconfigIPERF_VERSION == 3 )
char pcExpectedClient[ 80 ];
TcpClient_t *pxControlClient, *pxDataClient;
/*{"cpu_util_total":0,"cpu_util_user":0,"cpu_util_system":0,"sender_has_retransmits":-1,"streams":[{"id":1,"bytes":8760,"retransmits":-1,"jitter":0,"errors":0,"packets":0}]} */
#endif
static List_t xTCPClientList;
#if( ipconfigIPERF_HAS_UDP != 0 )
static uint32_t ulUDPRecvCount = 0, ulUDPRecvCountShown = 0, ulUDPRecvCountSeen = 0;
#endif
static SocketSet_t xSocketSet;
static TaskHandle_t pxIperfTask;
void vIPerfInstall( void )
{
if( pxRawBuffer == NULL )
{
pxRawBuffer = ( struct xRawBuffer * ) pvPortMalloc( sizeof *pxRawBuffer );
if( pxRawBuffer == NULL )
{
FreeRTOS_printf( ( "vIPerfInstall: malloc %u bytes failed.\n", (unsigned)sizeof *pxRawBuffer ) ) ;
return;
}
}
if( pxIperfTask == NULL )
{printf("start iperf\r\n");
/* Call this function once to start the test with FreeRTOS_accept(). */
xTaskCreate( vIPerfTask, "IPerf", ipconfigIPERF_STACK_SIZE_IPERF_TASK, NULL, ipconfigIPERF_PRIORITY_IPERF_TASK, &pxIperfTask );
}
}
static void vIPerfServerWork( Socket_t xSocket )
{
struct freertos_sockaddr xAddress;
socklen_t xSocketLength;
Socket_t xNexSocket;
xNexSocket = FreeRTOS_accept( xSocket, &xAddress, &xSocketLength);
if( ( xNexSocket != NULL ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) )
{
char pucBuffer[ 16 ];
TcpClient_t *pxClient;
pxClient = ( TcpClient_t * )pvPortMalloc( sizeof *pxClient );
memset( pxClient, '\0', sizeof *pxClient );
pxClient->xServerSocket = xNexSocket;
listSET_LIST_ITEM_OWNER( &( pxClient->xListItem ), ( void* ) pxClient );
#if( ipconfigUSE_IPv6 != 0 )
FreeRTOS_GetRemoteAddress( xNexSocket, ( struct freertos_sockaddr6 * ) &pxClient->xRemoteAddr );
#else
FreeRTOS_GetRemoteAddress( xNexSocket, ( struct freertos_sockaddr * ) &pxClient->xRemoteAddr );
FreeRTOS_inet_ntoa( pxClient->xRemoteAddr.sin_addr, pucBuffer );
FreeRTOS_printf( ( "vIPerfTask: Received a connection from %s:%u\n",
pucBuffer,
FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ) ) );
#endif
FreeRTOS_FD_SET( xNexSocket, xSocketSet, eSELECT_READ );
vListInsertFifo( &xTCPClientList, &( pxClient->xListItem ) );
}
}
static void vIPerfTCPClose( TcpClient_t *pxClient )
{
if( pxControlClient == pxClient )
{
pxControlClient = NULL;
}
if( pxDataClient == pxClient )
{
pxDataClient = NULL;
}
/* Remove server socket from the socket set. */
if( pxClient->xServerSocket != NULL )
{
char pucBuffer[ 16 ];
#if( ipconfigUSE_IPv6 == 0 )
FreeRTOS_inet_ntoa( pxClient->xRemoteAddr.sin_addr, pucBuffer );
FreeRTOS_printf( ( "vIPerfTCPClose: Closing server socket %s:%u after %lu bytes\n",
pucBuffer,
FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ),
pxClient->ulRecvCount ) );
#endif
FreeRTOS_FD_CLR( pxClient->xServerSocket, xSocketSet, eSELECT_ALL );
FreeRTOS_closesocket( pxClient->xServerSocket );
pxClient->xServerSocket = NULL;
}
/* Remove client socket from the socket set. */
{
if( pxClient->xServerSocket == NULL )
{
/* Remove this socket from the list. */
uxListRemove( &( pxClient->xListItem ) );
vPortFree( ( void * ) pxClient );
}
}
}
static int vIPerfTCPSend( TcpClient_t *pxClient )
{
BaseType_t xResult = 0;
do
{
size_t uxMaxSpace = (size_t) FreeRTOS_tx_space( pxClient->xServerSocket );
size_t uxSize = (size_t)FreeRTOS_min_uint32( uxMaxSpace, ( int32_t )sizeof( pcSendBuffer ) );
if( pxClient->bits.bTimed != pdFALSE_UNSIGNED )
{
if( xTaskCheckForTimeOut( &( pxClient->xTimeOut ), &( pxClient->xRemainingTime ) ) != pdFALSE )
{
/* Time is up. */
if( pxClient->bits.bTimedOut == pdFALSE_UNSIGNED )
{
FreeRTOS_shutdown( pxClient->xServerSocket, FREERTOS_SHUT_RDWR );
pxClient->bits.bTimedOut = pdTRUE_UNSIGNED;
}
break;
}
}
uxSize = FreeRTOS_min_uint32( uxSize, pxClient->ulAmount );
if( uxSize <= 0 )
{
break;
}
xResult = FreeRTOS_send( pxClient->xServerSocket, (const void *)pcSendBuffer, uxSize, 0 );
if( xResult < 0 )
{
break;
}
if( pxClient->bits.bTimed == pdFALSE_UNSIGNED )
{
pxClient->ulAmount -= uxSize;
if( pxClient->ulAmount == 0ul )
{
/* All data have been sent. No longer interested in eSELECT_WRITE events. */
FreeRTOS_FD_CLR( pxClient->xServerSocket, xSocketSet, eSELECT_WRITE );
}
}
if( uxSize > 0 )
{
xResult += uxSize;
}
}
while( 0 );
return xResult;
}
#if( ipconfigIPERF_VERSION == 3 )
static void handleRecvPacket( TcpClient_t *pxClient, char *pcReadBuffer, BaseType_t xRecvResult )
{
BaseType_t xRemaining = xRecvResult;
if( pxClient->eTCP_Status < eTCP_7_WaitTransfer )
{
FreeRTOS_printf( ( "TCP[ port %d ] recv[ %d ] %d\n", FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ), ( int ) pxClient->eTCP_Status, ( int )xRecvResult ) );
}
/*
2016-04-11 09:26:55.533 192.168.2.106 16.926.349 [] TCP recv[ 1 ] 4
2016-04-11 09:26:55.539 192.168.2.106 16.926.365 [] TCP skipcount 83 xRecvResult 4
2016-04-11 09:26:55.546 192.168.2.106 16.926.402 [] TCP recv[ 2 ] 4
2016-04-11 09:26:55.552 192.168.2.106 16.927.015 [] ipTCP_FLAG_PSH received
2016-04-11 09:26:55.560 192.168.2.106 16.927.085 [] TCP recv[ 2 ] 83
*/
switch( pxClient->eTCP_Status )
{
case eTCP_0_WaitName:
{
int rc;
if( pcExpectedClient[ 0 ] != '\0' )
{
/* Get a string like 'LAPTOP.1463928623.162445.0fbe105c6eb',
where 'LAPTOP' is the hostname. */
rc = strncmp( pcExpectedClient, pcReadBuffer, sizeof( pcExpectedClient ) );
}
else
{
rc = -1;
}
{
unsigned char tab[ 1 ] = { '\t' };
FreeRTOS_send( pxClient->xServerSocket, (const void *)tab, 1, 0 );
}
if( rc != 0 )
{
FreeRTOS_printf( ( "Got Control Socket: rc %d: exp: '%s' got: '%s'\n", rc, pcExpectedClient, pcReadBuffer ) );
strncpy( pcExpectedClient, pcReadBuffer, sizeof( pcExpectedClient ) );
pxControlClient = pxClient;
pxClient->bits.bIsControl = pdTRUE_UNSIGNED;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
else
{
FreeRTOS_printf( ( "Got expected client: rc %d: '%s'\n", rc, pcExpectedClient ) );
pcExpectedClient[ 0 ] = '\0';
pxDataClient = pxClient;
if( pxControlClient != NULL )
{
/* Transfer all properties to the data client. */
memcpy( &( pxDataClient->bits ), &( pxControlClient->bits ), sizeof( pxDataClient->bits ) );
pxDataClient->ulAmount = pxControlClient->ulAmount;
pxDataClient->xRemainingTime = pxControlClient->xRemainingTime;
vTaskSetTimeOutState( &( pxDataClient->xTimeOut ) );
if( pxDataClient->bits.bReverse != pdFALSE_UNSIGNED )
{
/* As this socket will only write data, set the WRITE select flag. */
FreeRTOS_FD_SET( pxClient->xServerSocket, xSocketSet, eSELECT_WRITE );
}
pxControlClient->bits.bIsControl = pdTRUE_UNSIGNED;
pxDataClient->bits.bIsControl = pdFALSE_UNSIGNED;
}
pxDataClient->eTCP_Status = eTCP_7_WaitTransfer;
}
}
break;
case eTCP_1_WaitCount:
if( xRemaining < 4 )
{
break;
}
{
pxClient->ulSkipCount =
( ( ( uint32_t ) pcReadBuffer[ 0 ] ) << 24 ) |
( ( ( uint32_t ) pcReadBuffer[ 1 ] ) << 16 ) |
( ( ( uint32_t ) pcReadBuffer[ 2 ] ) << 8 ) |
( ( ( uint32_t ) pcReadBuffer[ 3 ] ) << 0 );
/* Receive a number: an amount of bytes to be skipped. */
FreeRTOS_printf( ( "TCP skipcount %u xRecvResult %d\n", ( unsigned )pxClient->ulSkipCount, ( int )xRemaining ) );
pcReadBuffer += 4;
xRemaining -= 4;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
if( xRemaining == 0 )
{
break;
}
/* fall through */
case eTCP_2_WaitHeader:
{
if (xRemaining > 0) {
char *pcPtr;
pcReadBuffer[ xRemaining ] = '\0';
FreeRTOS_printf( ( "Control string: %s\n", pcReadBuffer ) );
for( pcPtr = pcReadBuffer; *pcPtr; pcPtr++ )
{
if( strncmp( pcPtr, "\"reverse\"", 9 ) == 0 )
{
pxClient->bits.bReverse = pcPtr[ 10 ] == 't';
}
else if( strncmp( pcPtr, "\"num\"", 5 ) == 0 )
{
uint32_t ulAmount;
if( sscanf( pcPtr + 6, "%lu", &( ulAmount ) ) > 0 )
{
pxClient->ulAmount = ulAmount;
}
}
else if( strncmp( pcPtr, "\"time\"", 6 ) == 0 )
{
uint32_t ulSeconds;
if( sscanf( pcPtr + 7, "%lu", &( ulSeconds ) ) > 0 )
{
pxClient->xRemainingTime = ulSeconds * 1000ul;
pxClient->bits.bTimed = pdTRUE_UNSIGNED;
}
}
}
if( pxClient->bits.bReverse != pdFALSE_UNSIGNED )
{
FreeRTOS_printf( ( "Reverse %d send %lu bytes timed %d: %lu\n",
pxClient->bits.bReverse, pxClient->ulAmount,
pxClient->bits.bTimed,
pxClient->xRemainingTime ) );
}
}
if( pxClient->ulSkipCount > ( uint32_t ) xRemaining )
{
pxClient->ulSkipCount -= ( uint32_t ) xRemaining;
}
else
{
unsigned char newline[ 1 ] = { '\n' };
unsigned char onetwo[ 2 ] = { '\1', '\2' };
FreeRTOS_send( pxClient->xServerSocket, (const void *)newline, sizeof( newline ), 0 );
FreeRTOS_send( pxClient->xServerSocket, (const void *)onetwo, sizeof( onetwo ), 0 );
pxClient->ulSkipCount = 0;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
}
break;
case eTCP_3_WaitOneTwo:
{
unsigned char ch = pcReadBuffer[ 0 ];
unsigned char cr[ 1 ] = { '\r' };
FreeRTOS_printf( ( "TCP[ port %d ] recv %d bytes: 0x%02X\n",
FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ), ( int )xRecvResult, ch ) );
ch = ch;
FreeRTOS_send( pxClient->xServerSocket, (const void *)cr, sizeof( cr ), 0 );
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
break;
case eTCP_4_WaitCount2:
if( xRemaining < 4 )
{
break;
}
{
pxClient->ulSkipCount =
( ( ( uint32_t ) pcReadBuffer[ 0 ] ) << 24 ) |
( ( ( uint32_t ) pcReadBuffer[ 1 ] ) << 16 ) |
( ( ( uint32_t ) pcReadBuffer[ 2 ] ) << 8 ) |
( ( ( uint32_t ) pcReadBuffer[ 3 ] ) << 0 );
FreeRTOS_printf( ( "TCP skipcount %lu xRecvResult %ld\n", pxClient->ulSkipCount, xRemaining ) );
pcReadBuffer += 4;
xRemaining -= 4;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
if( xRemaining == 0 )
{
break;
}
/* fall through */
case eTCP_5_WaitHeader2:
{
if( pxClient->ulSkipCount > ( uint32_t ) xRemaining )
{
pxClient->ulSkipCount -= xRemaining;
}
else
{
char pcResponse[ 200 ];
uint32_t ulLength, ulStore, ulCount = 0;
if( pxDataClient != NULL )
{
ulCount = pxDataClient->ulRecvCount;
}
ulLength = snprintf( pcResponse + 4, sizeof( pcResponse ) - 4,
"{"
"\"cpu_util_total\":0,"
"\"cpu_util_user\":0,"
"\"cpu_util_system\":0,"
"\"sender_has_retransmits\":-1,"
"\"streams\":["
"{"
"\"id\":1,"
"\"bytes\":%lu,"
"\"retransmits\":-1,"
"\"jitter\":0,"
"\"errors\":0,"
"\"packets\":0"
"}"
"]"
"}\xe",
ulCount );
ulStore = FreeRTOS_htonl( ulLength - 1 );
memcpy( pcResponse, &( ulStore ), sizeof ( ulStore ) );
FreeRTOS_send( pxClient->xServerSocket, (const void *)pcResponse, ulLength + 4, 0 );
pxClient->ulSkipCount = 0;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
}
break;
case eTCP_6_WaitDone:
break;
case eTCP_7_WaitTransfer:
break;
}
}
#endif /* ipconfigIPERF_VERSION == 3 */
static void vIPerfTCPWork( TcpClient_t *pxClient )
{
BaseType_t xRecvResult;
//#warning take away
//BaseType_t xLogged = pdFALSE;
if( pxClient->xServerSocket == NULL )
{
vIPerfTCPClose( pxClient );
return;
}
#if( ipconfigIPERF_VERSION == 3 )
/* Is this a data client with the -R reverse option ? */
if( ( pxClient->bits.bIsControl == pdFALSE_UNSIGNED ) && ( pxClient->bits.bReverse != pdFALSE_UNSIGNED ) )
{
if( ( pxClient->bits.bTimed == pdFALSE_UNSIGNED ) && ( pxClient->bits.bHasShutdown == pdFALSE_UNSIGNED ) && ( pxClient->ulAmount == (uint32_t)0u ) )
{
FreeRTOS_printf( ( "Shutdown connection\n" ) );
FreeRTOS_shutdown( pxClient->xServerSocket, FREERTOS_SHUT_RDWR );
pxClient->bits.bHasShutdown = pdTRUE_UNSIGNED;
}
}
#endif
for( ;; )
{
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
{
const BaseType_t xRecvSize = 0x10000;
xRecvResult = FreeRTOS_recv( pxClient->xServerSocket, /* The socket being received from. */
&pcRecvBuffer, /* The buffer into which the received data will be written. */
xRecvSize, /* Any size is OK here. */
FREERTOS_ZERO_COPY );
}
#else
{
const BaseType_t xRecvSize = sizeof pcRecvBuffer;
xRecvResult = FreeRTOS_recv( pxClient->xServerSocket, /* The socket being received from. */
pcRecvBuffer, /* The buffer into which the received data will be written. */
sizeof pcRecvBuffer, /* The size of the buffer provided to receive the data. */
0 );
}
#endif
if( xRecvResult <= 0 )
{
break;
}
pxClient->ulRecvCount += xRecvResult;
#if( ipconfigIPERF_VERSION == 3 )
if( pxClient->eTCP_Status < eTCP_6_WaitDone )
{
handleRecvPacket(pxClient, pcRecvBuffer, xRecvResult);
}
#endif /* ipconfigIPERF_VERSION == 3 */
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
{
FreeRTOS_recv( pxClient->xServerSocket, /* The socket being received from. */
NULL, /* The buffer into which the received data will be written. */
xRecvResult, /* This is important now. */
0 );
}
#endif
} /* for( ;; ) */
if( ( xRecvResult == 0 ) && ( pxClient->bits.bIsControl == pdFALSE_UNSIGNED ) && ( pxClient->bits.bReverse != pdFALSE_UNSIGNED ) )
{
xRecvResult = vIPerfTCPSend( pxClient );
}
if( ( xRecvResult < 0 ) && ( xRecvResult != -pdFREERTOS_ERRNO_EAGAIN ) )
{
vIPerfTCPClose( pxClient );
}
}
#if( ipconfigUSE_CALLBACKS == 0 ) && ( ipconfigIPERF_HAS_UDP != 0 )
static void vIPerfUDPWork( Socket_t xSocket )
{
BaseType_t xRecvResult;
struct freertos_sockaddr xAddress;
uint32_t xAddressLength;
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
{
xRecvResult = FreeRTOS_recvfrom( xSocket, ( void * ) &pcRecvBuffer, sizeof( pcRecvBuffer ),
FREERTOS_ZERO_COPY, &xAddress, &xAddressLength );
}
#else
{
xRecvResult = FreeRTOS_recvfrom( xSocket, ( void * ) pcRecvBuffer, sizeof( pcRecvBuffer ),
0, &xAddress, &xAddressLength );
}
#endif /* ipconfigIPERF_USE_ZERO_COPY */
if( xRecvResult > 0 )
{
ulUDPRecvCount += xRecvResult;
#if( ipconfigIPERF_DOES_ECHO_UDP != 0 )
{
FreeRTOS_sendto( xSocket, (const void *)pcRecvBuffer, xRecvResult, 0, &xAddress, sizeof( xAddress ) );
}
#endif /* ipconfigIPERF_DOES_ECHO_UDP */
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
{
FreeRTOS_ReleaseUDPPayloadBuffer( pcRecvBuffer );
}
#endif /* ipconfigIPERF_USE_ZERO_COPY */
}
}
#endif /* ipconfigUSE_CALLBACKS == 0 */
#if( ipconfigUSE_CALLBACKS != 0 ) && ( ipconfigIPERF_HAS_UDP != 0 )
static BaseType_t xOnUdpReceive( Socket_t xSocket, void * pvData, size_t xLength,
const struct freertos_sockaddr *pxFrom, const struct freertos_sockaddr *pxDest )
{
( void ) pvData;
( void ) pxFrom;
ulUDPRecvCount += xLength;
#if( ipconfigIPERF_DOES_ECHO_UDP != 0 )
{
FreeRTOS_sendto( xSocket, (const void *)pcRecvBuffer, xLength, 0, pxFrom, sizeof( *pxFrom ) );
}
#else /* ipconfigIPERF_DOES_ECHO_UDP */
{
( void ) xSocket;
}
#endif
/* Tell the driver not to store the RX data */
return 1;
}
#endif /* ipconfigUSE_CALLBACKS != 0 */
#if( ipconfigIPERF_HAS_TCP != 0 )
static Socket_t xCreateTCPServerSocket()
{
BaseType_t xBindResult, xListenResult;
struct freertos_sockaddr xEchoServerAddress;
Socket_t xTCPServerSocket;
TickType_t xNoTimeOut = 0;
xTCPServerSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
configASSERT( ( xTCPServerSocket != FREERTOS_INVALID_SOCKET ) && ( xTCPServerSocket != NULL ) );
memset( &xEchoServerAddress, '\0', sizeof xEchoServerAddress );
xEchoServerAddress.sin_port = FreeRTOS_htons( ipconfigIPERF_TCP_ECHO_PORT );
/* Set the receive time out to portMAX_DELAY.
Note that any TCP child connections will inherit this reception time-out. */
FreeRTOS_setsockopt( xTCPServerSocket, 0, FREERTOS_SO_RCVTIMEO, &xNoTimeOut, sizeof( xNoTimeOut ) );
{
WinProperties_t xWinProperties;
memset(&xWinProperties, '\0', sizeof xWinProperties);
xWinProperties.lTxBufSize = ipconfigIPERF_TX_BUFSIZE; /* Units of bytes. */
xWinProperties.lTxWinSize = ipconfigIPERF_TX_WINSIZE; /* Size in units of MSS */
xWinProperties.lRxBufSize = ipconfigIPERF_RX_BUFSIZE; /* Units of bytes. */
xWinProperties.lRxWinSize = ipconfigIPERF_RX_WINSIZE; /* Size in units of MSS */
FreeRTOS_setsockopt( xTCPServerSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProperties, sizeof( xWinProperties ) );
}
xBindResult = FreeRTOS_bind( xTCPServerSocket, &xEchoServerAddress, sizeof xEchoServerAddress );
xListenResult = FreeRTOS_listen( xTCPServerSocket, 4 );
FreeRTOS_FD_SET( xTCPServerSocket, xSocketSet, eSELECT_READ );
FreeRTOS_printf( ( "vIPerfTask: created TCP server socket %p bind port %u: %ld listen %ld\n",
xTCPServerSocket, ipconfigIPERF_TCP_ECHO_PORT, xBindResult, xListenResult ) );
xBindResult = xBindResult;
xListenResult = xListenResult;
return xTCPServerSocket;
}
#endif /* ipconfigIPERF_HAS_TCP */
#if( ipconfigIPERF_HAS_UDP != 0 )
static Socket_t xCreateUDPServerSocket()
{
BaseType_t xBindResult;
struct freertos_sockaddr xEchoServerAddress;
TickType_t xNoTimeOut = 0;
Socket_t xUDPServerSocket;
xUDPServerSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
configASSERT( ( xUDPServerSocket != FREERTOS_INVALID_SOCKET ) && ( xUDPServerSocket != NULL ) );
xEchoServerAddress.sin_port = FreeRTOS_htons( ipconfigIPERF_UDP_ECHO_PORT );
FreeRTOS_setsockopt( xUDPServerSocket, 0, FREERTOS_SO_RCVTIMEO, &xNoTimeOut, sizeof( xNoTimeOut ) );
xBindResult = FreeRTOS_bind( xUDPServerSocket, &xEchoServerAddress, sizeof xEchoServerAddress );
FreeRTOS_printf( ( "vIPerfTask: created UDP server socket %p bind port %u: %ld\n",
xUDPServerSocket, ipconfigIPERF_UDP_ECHO_PORT, xBindResult ) );
xBindResult = xBindResult;
#if( ipconfigUSE_CALLBACKS == 0 )
{
FreeRTOS_FD_SET( xUDPServerSocket, xSocketSet, eSELECT_READ );
}
#else
{
F_TCP_UDP_Handler_t xHandler;
memset( &xHandler, '\0', sizeof ( xHandler ) );
xHandler.pOnUdpReceive = xOnUdpReceive;
FreeRTOS_setsockopt( xUDPServerSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );
}
#endif /* ipconfigUSE_CALLBACKS */
return xUDPServerSocket;
}
#endif /* ipconfigIPERF_HAS_UDP */
void vIPerfTask( void *pvParameter )
{
#if( ipconfigIPERF_HAS_TCP != 0 )
Socket_t xTCPServerSocket;
#endif /* ipconfigIPERF_HAS_TCP */
#if( ipconfigIPERF_HAS_UDP != 0 )
Socket_t xUDPServerSocket;
#endif /* ipconfigIPERF_HAS_UDP */
( void ) pvParameter;
xSocketSet = FreeRTOS_CreateSocketSet( );
vListInitialise( &xTCPClientList );
#if( ipconfigIPERF_HAS_TCP != 0 )
{
xTCPServerSocket = xCreateTCPServerSocket();
}
#endif /* ipconfigIPERF_HAS_TCP */
#if( ipconfigIPERF_HAS_UDP != 0 )
{
xUDPServerSocket = xCreateUDPServerSocket();
(void)xUDPServerSocket;
}
#endif /* ipconfigIPERF_HAS_UDP */
FreeRTOS_printf( ( "Use for example:\n" ) );
FreeRTOS_printf( ( "iperf3 -c %lxip --port %u --bytes 100M [ -R ]\n",
FreeRTOS_htonl( FreeRTOS_GetIPAddress() ), ipconfigIPERF_UDP_ECHO_PORT ) );
#define HUNDREDTH_MB ( ( 1024 * 1024 ) / 100 )
for( ;; )
{
BaseType_t xResult;
const TickType_t xBlockingTime = pdMS_TO_TICKS( ipconfigIPERF_LOOP_BLOCKING_TIME_MS );
/* Wait at most 5 seconds. */
xResult = FreeRTOS_select( xSocketSet, xBlockingTime );
#if( ipconfigIPERF_HAS_TCP != 0 )
if( xResult != 0 )
{
const MiniListItem_t* pxEnd;
const ListItem_t *pxIterator;
pxEnd = ( const MiniListItem_t* ) listGET_END_MARKER( &xTCPClientList );
vIPerfServerWork( xTCPServerSocket );
/* Check all TCP clients: */
for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
pxIterator != ( const ListItem_t * ) pxEnd;
)
{
TcpClient_t *pxClient;
pxClient = ( TcpClient_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
/* Let the iterator point to the next element before the current element
removes itself from the list. */
pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator );
vIPerfTCPWork( pxClient );
}
}
#endif /* ipconfigIPERF_HAS_TCP */
#if( ipconfigIPERF_HAS_UDP != 0 )
#if( ipconfigUSE_CALLBACKS == 0 )
if( xResult != 0 )
{
vIPerfUDPWork( xUDPServerSocket );
}
else
#endif /* ipconfigUSE_CALLBACKS */
{
if( ulUDPRecvCountSeen != ulUDPRecvCount )
{
/* The amount is still changing, do not show it yet. */
ulUDPRecvCountSeen = ulUDPRecvCount;
}
else if( ulUDPRecvCountShown != ulUDPRecvCount )
{
uint32_t ulNewBytes = ulUDPRecvCount - ulUDPRecvCountShown;
uint32_t ulMB = (ulNewBytes + HUNDREDTH_MB/2) / HUNDREDTH_MB;
FreeRTOS_printf( ( "UDP received %lu + %lu (%lu.%02lu MB) = %lu\n",
ulUDPRecvCountShown,
ulNewBytes,
ulMB / 100,
ulMB % 100,
ulUDPRecvCount ) );
ulUDPRecvCountShown = ulUDPRecvCount;
ulMB = ulMB;
}
}
#endif /* ipconfigIPERF_HAS_UDP */
}
}
//<2F><><EFBFBD><EFBFBD>ͨWiFi<46><69>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>
#define IPERF_BUFSZ (4 * 1024)
typedef unsigned int u32_t;
static TaskHandle_t iperf_task_handle = NULL;
static int flag_start_iperf = 0;
static char gaddr[4] = {0};
static int gport = 0;
static u32_t sys_now(void)
{
return xTaskGetTickCount() * portTICK_PERIOD_MS;
}
static void iperf_client(const char * ipaddr, int port)
{
Socket_t sock;
int i;
//struct sockaddr_in client_addr;
struct freertos_sockaddr client_addr;
uint8_t* send_buf;
u32_t tick1, tick2;
uint64_t sentlen;
(void)ipaddr;
(void)port;
send_buf = (uint8_t *) pvPortMalloc(IPERF_BUFSZ);
if (!send_buf)
return ;
for(i = 0; i < IPERF_BUFSZ; i ++)
send_buf[i] = i & 0xff;
while(flag_start_iperf) {
sock = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
if (sock == FREERTOS_INVALID_SOCKET) {
printf("Socket error\r\n");
vTaskDelay(pdMS_TO_TICKS(100));
continue;
}
client_addr.sin_port = FreeRTOS_htons( gport );
client_addr.sin_addr = FreeRTOS_inet_addr_quick( gaddr[0],
gaddr[1],
gaddr[2],
gaddr[3] );
//memset(&(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero));
if (FreeRTOS_connect(sock, &client_addr, sizeof( struct freertos_sockaddr )) != 0) {
printf("Connect failed!\r\n");
FreeRTOS_closesocket(sock);
vTaskDelay(10);
continue;
}
printf("Connect to iperf server successful!\r\n");
tick1 = sys_now();
while (flag_start_iperf) {
tick2 = sys_now();
if(tick2 - tick1 >= configTICK_RATE_HZ * 5) {
float f;
f = (float)(sentlen * configTICK_RATE_HZ/125/(tick2 - tick1));
f /= 1000.0f;
printf("\r\nsend speed = %.4f Mbps!\r\n", f);
tick1 = tick2;
sentlen = 0;
}
if(FreeRTOS_send(sock, send_buf, IPERF_BUFSZ, 0) < 0) {
printf("FreeRTOS_send failed\r\n");
break;
} else {
sentlen += IPERF_BUFSZ;
}
}
FreeRTOS_closesocket(sock);
}
if (send_buf) {
vPortFree(send_buf);
}
}
static void iperf_task_proc(void* arg)
{
iperf_client(NULL, 0);
vTaskDelete(NULL);
}
void start_iperf_client(const char* ip, int port)
{
if (flag_start_iperf) {
printf("iperf client has been started");
return;
}
if (iperf_task_handle == NULL) {
sscanf(ip, "%d.%d.%d.%d", (int*)&gaddr[0], (int*)&gaddr[1], (int*)&gaddr[2], (int*)&gaddr[3]);
gport = port;
flag_start_iperf = 1;
xTaskCreate(iperf_task_proc, "iperf task task", 512, NULL, configMAX_PRIORITIES / 3, &iperf_task_handle);
}
}

View File

@ -0,0 +1,425 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/******************************************************************************
*
* 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( ipFALSE_BOOL )
#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 /* if ( ipconfigTCP_IP_SANITY != 0 ) */
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;
uint32_t 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 != NULL );
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 = 0U; 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 ) ) )
{
( void ) 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 */
}
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
}
else
{
/* lint wants to see at least a comment. */
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();
( void ) 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 ) );
}
else
{
/* 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() ) );
}
else
{
( void ) xSemaphoreGive( xNetworkBufferSemaphore );
prvShowWarnings();
}
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. */
pxNetworkBuffer->xDataLength = xNewSizeBytes;
return pxNetworkBuffer;
}
/*#endif */ /* ipconfigINCLUDE_TEST_CODE */

View File

@ -0,0 +1,33 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 2
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
;

View File

@ -0,0 +1,32 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
__packed

View File

@ -0,0 +1,767 @@
/*
* Handling of Ethernet PHY's
* PHY's communicate with an EMAC either through
* a Media-Independent Interface (MII), or a Reduced Media-Independent Interface (RMII).
* The EMAC can poll for PHY ports on 32 different addresses. Each of the PHY ports
* shall be treated independently.
*
*/
/* 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 "phyHandling.h"
#define phyMIN_PHY_ADDRESS 0
#define phyMAX_PHY_ADDRESS 31
#if defined( PHY_LS_HIGH_CHECK_TIME_MS ) || defined( PHY_LS_LOW_CHECK_TIME_MS )
#warning please use the new defines with 'ipconfig' prefix
#endif
#ifndef ipconfigPHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still high after 15 seconds of not
* receiving packets. */
#define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000UL
#endif
#ifndef ipconfigPHY_LS_LOW_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still low every second. */
#define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000UL
#endif
/* As the following 3 macro's are OK in most situations, and so they're not
* included in 'FreeRTOSIPConfigDefaults.h'.
* Users can change their values in the project's 'FreeRTOSIPConfig.h'. */
#ifndef phyPHY_MAX_RESET_TIME_MS
#define phyPHY_MAX_RESET_TIME_MS 1000UL
#endif
#ifndef phyPHY_MAX_NEGOTIATE_TIME_MS
#define phyPHY_MAX_NEGOTIATE_TIME_MS 3000UL
#endif
#ifndef phySHORT_DELAY_MS
#define phySHORT_DELAY_MS 50UL
#endif
/* Naming and numbering of basic PHY registers. */
#define phyREG_00_BMCR 0x00U /* Basic Mode Control Register. */
#define phyREG_01_BMSR 0x01U /* Basic Mode Status Register. */
#define phyREG_02_PHYSID1 0x02U /* PHYS ID 1 */
#define phyREG_03_PHYSID2 0x03U /* PHYS ID 2 */
#define phyREG_04_ADVERTISE 0x04U /* Advertisement control reg */
/* Naming and numbering of extended PHY registers. */
#define PHYREG_10_PHYSTS 0x10U /* 16 PHY status register Offset */
#define phyREG_19_PHYCR 0x19U /* 25 RW PHY Control Register */
#define phyREG_1F_PHYSPCS 0x1FU /* 31 RW PHY Special Control Status */
/* Bit fields for 'phyREG_00_BMCR', the 'Basic Mode Control Register'. */
#define phyBMCR_FULL_DUPLEX 0x0100U /* Full duplex. */
#define phyBMCR_AN_RESTART 0x0200U /* Auto negotiation restart. */
#define phyBMCR_ISOLATE 0x0400U /* 1 = Isolates 0 = Normal operation. */
#define phyBMCR_AN_ENABLE 0x1000U /* Enable auto negotiation. */
#define phyBMCR_SPEED_100 0x2000U /* Select 100Mbps. */
#define phyBMCR_RESET 0x8000U /* Reset the PHY. */
/* Bit fields for 'phyREG_19_PHYCR', the 'PHY Control Register'. */
#define PHYCR_MDIX_EN 0x8000U /* Enable Auto MDIX. */
#define PHYCR_MDIX_FORCE 0x4000U /* Force MDIX crossed. */
#define phyBMSR_AN_COMPLETE 0x0020U /* Auto-Negotiation process completed */
#define phyBMSR_LINK_STATUS 0x0004U
#define phyPHYSTS_LINK_STATUS 0x0001U /* PHY Link mask */
#define phyPHYSTS_SPEED_STATUS 0x0002U /* PHY Speed mask */
#define phyPHYSTS_DUPLEX_STATUS 0x0004U /* PHY Duplex mask */
/* Bit fields for 'phyREG_1F_PHYSPCS
* 001 = 10BASE-T half-duplex
* 101 = 10BASE-T full-duplex
* 010 = 100BASE-TX half-duplex
* 110 = 100BASE-TX full-duplex
*/
#define phyPHYSPCS_SPEED_MASK 0x000CU
#define phyPHYSPCS_SPEED_10 0x0004U
#define phyPHYSPCS_FULL_DUPLEX 0x0010U
/*
* Description of all capabilities that can be advertised to
* the peer (usually a switch or router).
*/
#define phyADVERTISE_CSMA 0x0001U /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */
#define phyADVERTISE_10HALF 0x0020U /* Try for 10mbps half-duplex. */
#define phyADVERTISE_10FULL 0x0040U /* Try for 10mbps full-duplex. */
#define phyADVERTISE_100HALF 0x0080U /* Try for 100mbps half-duplex. */
#define phyADVERTISE_100FULL 0x0100U /* Try for 100mbps full-duplex. */
#define phyADVERTISE_ALL \
( phyADVERTISE_10HALF | phyADVERTISE_10FULL | \
phyADVERTISE_100HALF | phyADVERTISE_100FULL | \
phyADVERTISE_CSMA )
/* Send a reset command to a set of PHY-ports. */
static uint32_t xPhyReset( EthernetPhy_t * pxPhyObject,
uint32_t ulPhyMask );
static BaseType_t xHas_1F_PHYSPCS( uint32_t ulPhyID )
{
BaseType_t xResult;
switch( ulPhyID )
{
case PHY_ID_LAN8720:
case PHY_ID_LAN8742A:
case PHY_ID_KSZ8041:
/*
* case PHY_ID_KSZ8051: // same ID as 8041
* case PHY_ID_KSZ8081: // same ID as 8041
*/
case PHY_ID_KSZ8081MNXIA:
case PHY_ID_KSZ8863:
default:
/* Most PHY's have a 1F_PHYSPCS */
xResult = pdTRUE;
break;
case PHY_ID_DP83848I:
xResult = pdFALSE;
break;
}
return xResult;
}
/*-----------------------------------------------------------*/
static BaseType_t xHas_19_PHYCR( uint32_t ulPhyID )
{
BaseType_t xResult;
switch( ulPhyID )
{
case PHY_ID_LAN8742A:
case PHY_ID_DP83848I:
xResult = pdTRUE;
break;
default:
/* Most PHY's do not have a 19_PHYCR */
xResult = pdFALSE;
break;
}
return xResult;
}
/*-----------------------------------------------------------*/
/* Initialise the struct and assign a PHY-read and -write function. */
void vPhyInitialise( EthernetPhy_t * pxPhyObject,
xApplicationPhyReadHook_t fnPhyRead,
xApplicationPhyWriteHook_t fnPhyWrite )
{
memset( ( void * ) pxPhyObject, 0, sizeof( *pxPhyObject ) );
pxPhyObject->fnPhyRead = fnPhyRead;
pxPhyObject->fnPhyWrite = fnPhyWrite;
}
/*-----------------------------------------------------------*/
/* Discover all PHY's connected by polling 32 indexes ( zero-based ) */
BaseType_t xPhyDiscover( EthernetPhy_t * pxPhyObject )
{
BaseType_t xPhyAddress;
pxPhyObject->xPortCount = 0;
for( xPhyAddress = phyMIN_PHY_ADDRESS; xPhyAddress <= phyMAX_PHY_ADDRESS; xPhyAddress++ )
{
uint32_t ulLowerID;
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID );
/* A valid PHY id can not be all zeros or all ones. */
if( ( ulLowerID != ( uint16_t ) ~0U ) && ( ulLowerID != ( uint16_t ) 0U ) )
{
uint32_t ulUpperID;
uint32_t ulPhyID;
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_02_PHYSID1, &ulUpperID );
ulPhyID = ( ( ( uint32_t ) ulUpperID ) << 16 ) | ( ulLowerID & 0xFFF0 );
pxPhyObject->ucPhyIndexes[ pxPhyObject->xPortCount ] = xPhyAddress;
pxPhyObject->ulPhyIDs[ pxPhyObject->xPortCount ] = ulPhyID;
pxPhyObject->xPortCount++;
/* See if there is more storage space. */
if( pxPhyObject->xPortCount == ipconfigPHY_MAX_PORTS )
{
break;
}
}
}
if( pxPhyObject->xPortCount > 0 )
{
FreeRTOS_printf( ( "PHY ID %lX\n", pxPhyObject->ulPhyIDs[ 0 ] ) );
}
return pxPhyObject->xPortCount;
}
/*-----------------------------------------------------------*/
/* Send a reset command to a set of PHY-ports. */
static uint32_t xPhyReset( EthernetPhy_t * pxPhyObject,
uint32_t ulPhyMask )
{
uint32_t ulDoneMask, ulConfig;
TickType_t xRemainingTime;
TimeOut_t xTimer;
BaseType_t xPhyIndex;
/* A bit-mask of PHY ports that are ready. */
ulDoneMask = 0UL;
/* Set the RESET bits high. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
/* Read Control register. */
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig | phyBMCR_RESET );
}
xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_RESET_TIME_MS );
vTaskSetTimeOutState( &xTimer );
/* The reset should last less than a second. */
for( ; ; )
{
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
if( ( ulConfig & phyBMCR_RESET ) == 0 )
{
FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET %d ready\n", ( int ) xPhyIndex ) );
ulDoneMask |= ( 1UL << xPhyIndex );
}
}
if( ulDoneMask == ulPhyMask )
{
break;
}
if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE )
{
FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) );
break;
}
/* Block for a while */
vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
}
/* Clear the reset bits. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
if( ( ulDoneMask & ( 1UL << xPhyIndex ) ) == 0UL )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
/* The reset operation timed out, clear the bit manually. */
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig & ~phyBMCR_RESET );
}
}
vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
return ulDoneMask;
}
/*-----------------------------------------------------------*/
BaseType_t xPhyConfigure( EthernetPhy_t * pxPhyObject,
const PhyProperties_t * pxPhyProperties )
{
uint32_t ulConfig, ulAdvertise;
BaseType_t xPhyIndex;
if( pxPhyObject->xPortCount < 1 )
{
FreeRTOS_printf( ( "xPhyConfigure: No PHY's detected.\n" ) );
return -1;
}
/* The expected ID for the 'LAN8742A' is 0x0007c130. */
/* The expected ID for the 'LAN8720' is 0x0007c0f0. */
/* The expected ID for the 'DP83848I' is 0x20005C90. */
/* Set advertise register. */
if( ( pxPhyProperties->ucSpeed == ( uint8_t ) PHY_SPEED_AUTO ) && ( pxPhyProperties->ucDuplex == ( uint8_t ) PHY_DUPLEX_AUTO ) )
{
ulAdvertise = phyADVERTISE_ALL;
/* Reset auto-negotiation capability. */
}
else
{
/* Always select protocol 802.3u. */
ulAdvertise = phyADVERTISE_CSMA;
if( pxPhyProperties->ucSpeed == ( uint8_t ) PHY_SPEED_AUTO )
{
if( pxPhyProperties->ucDuplex == ( uint8_t ) PHY_DUPLEX_FULL )
{
ulAdvertise |= phyADVERTISE_10FULL | phyADVERTISE_100FULL;
}
else
{
ulAdvertise |= phyADVERTISE_10HALF | phyADVERTISE_100HALF;
}
}
else if( pxPhyProperties->ucDuplex == ( uint8_t ) PHY_DUPLEX_AUTO )
{
if( pxPhyProperties->ucSpeed == ( uint8_t ) PHY_SPEED_10 )
{
ulAdvertise |= phyADVERTISE_10FULL | phyADVERTISE_10HALF;
}
else
{
ulAdvertise |= phyADVERTISE_100FULL | phyADVERTISE_100HALF;
}
}
else if( pxPhyProperties->ucSpeed == ( uint8_t ) PHY_SPEED_100 )
{
if( pxPhyProperties->ucDuplex == ( uint8_t ) PHY_DUPLEX_FULL )
{
ulAdvertise |= phyADVERTISE_100FULL;
}
else
{
ulAdvertise |= phyADVERTISE_100HALF;
}
}
else
{
if( pxPhyProperties->ucDuplex == ( uint8_t ) PHY_DUPLEX_FULL )
{
ulAdvertise |= phyADVERTISE_10FULL;
}
else
{
ulAdvertise |= phyADVERTISE_10HALF;
}
}
}
/* Send a reset command to a set of PHY-ports. */
xPhyReset( pxPhyObject, xPhyGetMask( pxPhyObject ) );
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];
/* Write advertise register. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_04_ADVERTISE, ulAdvertise );
/*
* AN_EN AN1 AN0 Forced Mode
* 0 0 0 10BASE-T, Half-Duplex
* 0 0 1 10BASE-T, Full-Duplex
* 0 1 0 100BASE-TX, Half-Duplex
* 0 1 1 100BASE-TX, Full-Duplex
* AN_EN AN1 AN0 Advertised Mode
* 1 0 0 10BASE-T, Half/Full-Duplex
* 1 0 1 100BASE-TX, Half/Full-Duplex
* 1 1 0 10BASE-T Half-Duplex
* 100BASE-TX, Half-Duplex
* 1 1 1 10BASE-T, Half/Full-Duplex
* 100BASE-TX, Half/Full-Duplex
*/
/* Read Control register. */
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
ulConfig &= ~( phyBMCR_SPEED_100 | phyBMCR_FULL_DUPLEX );
ulConfig |= phyBMCR_AN_ENABLE;
if( ( pxPhyProperties->ucSpeed == ( uint8_t ) PHY_SPEED_100 ) || ( pxPhyProperties->ucSpeed == ( uint8_t ) PHY_SPEED_AUTO ) )
{
ulConfig |= phyBMCR_SPEED_100;
}
else if( pxPhyProperties->ucSpeed == ( uint8_t ) PHY_SPEED_10 )
{
ulConfig &= ~phyBMCR_SPEED_100;
}
if( ( pxPhyProperties->ucDuplex == ( uint8_t ) PHY_DUPLEX_FULL ) || ( pxPhyProperties->ucDuplex == ( uint8_t ) PHY_DUPLEX_AUTO ) )
{
ulConfig |= phyBMCR_FULL_DUPLEX;
}
else if( pxPhyProperties->ucDuplex == ( uint8_t ) PHY_DUPLEX_HALF )
{
ulConfig &= ~phyBMCR_FULL_DUPLEX;
}
if( xHas_19_PHYCR( ulPhyID ) )
{
uint32_t ulPhyControl;
/* Read PHY Control register. */
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_19_PHYCR, &ulPhyControl );
/* Clear bits which might get set: */
ulPhyControl &= ~( PHYCR_MDIX_EN | PHYCR_MDIX_FORCE );
if( pxPhyProperties->ucMDI_X == PHY_MDIX_AUTO )
{
ulPhyControl |= PHYCR_MDIX_EN;
}
else if( pxPhyProperties->ucMDI_X == PHY_MDIX_CROSSED )
{
/* Force direct link = Use crossed RJ45 cable. */
ulPhyControl &= ~PHYCR_MDIX_FORCE;
}
else
{
/* Force crossed link = Use direct RJ45 cable. */
ulPhyControl |= PHYCR_MDIX_FORCE;
}
/* update PHY Control Register. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_19_PHYCR, ulPhyControl );
}
FreeRTOS_printf( ( "+TCP: advertise: %04lX config %04lX\n", ulAdvertise, ulConfig ) );
}
/* Keep these values for later use. */
pxPhyObject->ulBCRValue = ulConfig & ~phyBMCR_ISOLATE;
pxPhyObject->ulACRValue = ulAdvertise;
return 0;
}
/*-----------------------------------------------------------*/
/* xPhyFixedValue(): this function is called in case auto-negotiation is disabled.
* The caller has set the values in 'xPhyPreferences' (ucDuplex and ucSpeed).
* The PHY register phyREG_00_BMCR will be set for every connected PHY that matches
* with ulPhyMask. */
BaseType_t xPhyFixedValue( EthernetPhy_t * pxPhyObject,
uint32_t ulPhyMask )
{
BaseType_t xPhyIndex;
uint32_t ulValue, ulBitMask = ( uint32_t ) 1U;
ulValue = ( uint32_t ) 0U;
if( pxPhyObject->xPhyPreferences.ucDuplex == PHY_DUPLEX_FULL )
{
ulValue |= phyBMCR_FULL_DUPLEX;
}
if( pxPhyObject->xPhyPreferences.ucSpeed == PHY_SPEED_100 )
{
ulValue |= phyBMCR_SPEED_100;
}
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
if( ( ulPhyMask & ulBitMask ) != 0lu )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
/* Enable Auto-Negotiation. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulValue );
}
}
return 0;
}
/*-----------------------------------------------------------*/
/* xPhyStartAutoNegotiation() is the alternative xPhyFixedValue():
* It sets the BMCR_AN_RESTART bit and waits for the auto-negotiation completion
* ( phyBMSR_AN_COMPLETE ). */
BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t * pxPhyObject,
uint32_t ulPhyMask )
{
uint32_t xPhyIndex, ulDoneMask, ulBitMask;
uint32_t ulPHYLinkStatus, ulRegValue;
TickType_t xRemainingTime;
TimeOut_t xTimer;
if( ulPhyMask == ( uint32_t ) 0U )
{
return 0;
}
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++ )
{
if( ( ulPhyMask & ( 1lu << xPhyIndex ) ) != 0lu )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
/* Enable Auto-Negotiation. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_04_ADVERTISE, pxPhyObject->ulACRValue );
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue | phyBMCR_AN_RESTART );
}
}
xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_NEGOTIATE_TIME_MS );
vTaskSetTimeOutState( &xTimer );
ulDoneMask = 0;
/* Wait until the auto-negotiation will be completed */
for( ; ; )
{
ulBitMask = ( uint32_t ) 1U;
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
if( ( ulPhyMask & ulBitMask ) != 0lu )
{
if( ( ulDoneMask & ulBitMask ) == 0lu )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulRegValue );
if( ( ulRegValue & phyBMSR_AN_COMPLETE ) != 0 )
{
ulDoneMask |= ulBitMask;
}
}
}
}
if( ulPhyMask == ulDoneMask )
{
break;
}
if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE )
{
FreeRTOS_printf( ( "xPhyStartAutoNegotiation: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) );
break;
}
vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
}
if( ulDoneMask != ( uint32_t ) 0U )
{
ulBitMask = ( uint32_t ) 1U;
pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask );
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];
if( ( ulDoneMask & ulBitMask ) == ( uint32_t ) 0U )
{
continue;
}
/* Clear the 'phyBMCR_AN_RESTART' bit. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue );
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulRegValue );
if( ( ulRegValue & phyBMSR_LINK_STATUS ) != 0 )
{
ulPHYLinkStatus |= phyBMSR_LINK_STATUS;
pxPhyObject->ulLinkStatusMask |= ulBitMask;
}
else
{
ulPHYLinkStatus &= ~( phyBMSR_LINK_STATUS );
}
if( ulPhyID == PHY_ID_KSZ8081MNXIA )
{
uint32_t ulControlStatus;
pxPhyObject->fnPhyRead( xPhyAddress, 0x1E, &ulControlStatus );
switch( ulControlStatus & 0x07 )
{
case 0x01:
case 0x05:
/* [001] = 10BASE-T half-duplex */
/* [101] = 10BASE-T full-duplex */
/* 10 Mbps. */
ulRegValue |= phyPHYSTS_SPEED_STATUS;
break;
case 0x02:
case 0x06:
/* [010] = 100BASE-TX half-duplex */
/* [110] = 100BASE-TX full-duplex */
break;
}
switch( ulControlStatus & 0x07 )
{
case 0x05:
case 0x06:
/* [101] = 10BASE-T full-duplex */
/* [110] = 100BASE-TX full-duplex */
/* Full duplex. */
ulRegValue |= phyPHYSTS_DUPLEX_STATUS;
break;
case 0x01:
case 0x02:
/* [001] = 10BASE-T half-duplex */
/* [010] = 100BASE-TX half-duplex */
break;
}
}
else if( xHas_1F_PHYSPCS( ulPhyID ) )
{
/* 31 RW PHY Special Control Status */
uint32_t ulControlStatus;
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_1F_PHYSPCS, &ulControlStatus );
ulRegValue = 0;
if( ( ulControlStatus & phyPHYSPCS_FULL_DUPLEX ) != 0 )
{
ulRegValue |= phyPHYSTS_DUPLEX_STATUS;
}
if( ( ulControlStatus & phyPHYSPCS_SPEED_MASK ) == phyPHYSPCS_SPEED_10 )
{
ulRegValue |= phyPHYSTS_SPEED_STATUS;
}
}
else
{
/* Read the result of the auto-negotiation. */
pxPhyObject->fnPhyRead( xPhyAddress, PHYREG_10_PHYSTS, &ulRegValue );
}
FreeRTOS_printf( ( "Autonego ready: %08lx: %s duplex %u mbit %s status\n",
ulRegValue,
( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half",
( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100,
( ( ulPHYLinkStatus |= phyBMSR_LINK_STATUS ) != 0 ) ? "high" : "low" ) );
if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t ) 0U )
{
pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_FULL;
}
else
{
pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_HALF;
}
if( ( ulRegValue & phyPHYSTS_SPEED_STATUS ) != 0 )
{
pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_10;
}
else
{
pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_100;
}
}
} /* if( ulDoneMask != ( uint32_t) 0U ) */
return 0;
}
/*-----------------------------------------------------------*/
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t * pxPhyObject,
BaseType_t xHadReception )
{
uint32_t ulStatus, ulBitMask = 1U;
BaseType_t xPhyIndex;
BaseType_t xNeedCheck = pdFALSE;
if( xHadReception > 0 )
{
/* A packet was received. No need to check for the PHY status now,
* but set a timer to check it later on. */
vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0UL )
{
pxPhyObject->ulLinkStatusMask |= ulBitMask;
FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
xNeedCheck = pdTRUE;
}
}
}
else if( xTaskCheckForTimeOut( &( pxPhyObject->xLinkStatusTimer ), &( pxPhyObject->xLinkStatusRemaining ) ) != pdFALSE )
{
/* Frequent checking the PHY Link Status can affect for the performance of Ethernet controller.
* As long as packets are received, no polling is needed.
* Otherwise, polling will be done when the 'xLinkStatusTimer' expires. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
if( pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulStatus ) == 0 )
{
if( !!( pxPhyObject->ulLinkStatusMask & ulBitMask ) != !!( ulStatus & phyBMSR_LINK_STATUS ) )
{
if( ( ulStatus & phyBMSR_LINK_STATUS ) != 0 )
{
pxPhyObject->ulLinkStatusMask |= ulBitMask;
}
else
{
pxPhyObject->ulLinkStatusMask &= ~( ulBitMask );
}
FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
xNeedCheck = pdTRUE;
}
}
}
vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
if( ( pxPhyObject->ulLinkStatusMask & ( ulBitMask >> 1 ) ) != 0 )
{
/* The link status is high, so don't poll the PHY too often. */
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
}
else
{
/* The link status is low, polling may be done more frequently. */
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );
}
}
return xNeedCheck;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,263 @@
/***********************************************************************************************************************
* Copyright (C) 2021 Arkmicro Corporation. All rights reserved.
***********************************************************************************************************************/
/***********************************************************************************************************************
* File Name : NetworkInterface.c
* Device(s) : RTL8189FTV
* Description : Interfaces FreeRTOS TCP/IP stack to RX Ethernet driver.
***********************************************************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
/*#include "FreeRTOS_DNS.h" */
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "wifi_constants.h"
#include "net_stack_intf.h"
#include "FreeRTOS_ARP.h"
#include "wifi_conf.h"
#include "board.h"
//#define USE_AP 0
//#define DUMP_NETWORK_DATA
//#undef DUMP_NETWORK_DATA
#ifdef WIFI_SUPPORT
#if CONFIG_USB_DEVICE_CDC_NCM
#error "Do not choose USE_USB_DEVICE when use WIFI_SUPPORT"
#endif
#endif
typedef enum
{
eMACInit, /* Must initialise MAC. */
eMACPass, /* Initialisation was successful. */
eMACFailed, /* Initialisation failed. */
} eMAC_INIT_STATUS_TYPE;
static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
extern void cmd_test(const char* temp_uart_buf);
static int InitializeNetwork( void );
int g_ncm_register(const char *name);
/***********************************************************************************************************************
* Function Name: xNetworkInterfaceInitialise ()
* Description : Initialization of Ethernet driver.
* Arguments : none
* Return Value : pdPASS, pdFAIL
**********************************************************************************************************************/
BaseType_t xNetworkInterfaceInitialise( void )
{
BaseType_t xReturn;
if( xMacInitStatus == eMACInit )
{
//rltk_wlan_set_netif_info(0, NULL, "00:0c:29:5d:2e:05");
/*
* Perform the hardware specific network initialization here using the Ethernet driver library to initialize the
* Ethernet hardware, initialize DMA descriptors, and perform a PHY auto-negotiation to obtain a network link.
*
* InitialiseNetwork() uses Ethernet peripheral driver library function, and returns 0 if the initialization fails.
*/
if( InitializeNetwork() == pdFALSE )
{
xMacInitStatus = eMACFailed;
}
else
{
/* Indicate that the MAC initialisation succeeded. */
xMacInitStatus = eMACPass;
}
FreeRTOS_printf( ( "InitializeNetwork returns %s\n", ( xMacInitStatus == eMACPass ) ? "OK" : " Fail" ) );
}
if( xMacInitStatus == eMACPass )
{
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
FreeRTOS_printf( ( "xNetworkInterfaceInitialise returns %d\n", xReturn ) );
return xReturn;
} /* End of function xNetworkInterfaceInitialise() */
/***********************************************************************************************************************
* Function Name: xNetworkInterfaceOutput ()
* Description : Simple network output interface.
* Arguments : pxDescriptor, xReleaseAfterSend
* Return Value : pdTRUE, pdFALSE
**********************************************************************************************************************/
#if CONFIG_USB_DEVICE_CDC_NCM
void gether_send(NetworkBufferDescriptor_t * const pxDescriptor);
#endif
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t xReleaseAfterSend )
{
BaseType_t xReturn = pdFALSE;
#ifdef WIFI_SUPPORT
struct eth_drv_sg sg_list = {0};
#endif
#ifdef DUMP_NETWORK_DATA
if (1) {
int i;
char* tmp = (char *)pxDescriptor->pucEthernetBuffer;
printf("\r\nsend len:%d--> ", pxDescriptor->xDataLength);
for (i = 0; i < pxDescriptor->xDataLength; i++) {
printf("%02x ", tmp[i]);
}printf("send end\r\n");
}
#endif
#ifdef WIFI_SUPPORT
if (!rltk_wlan_running(0)) {
goto exit;
}
sg_list.buf = (unsigned int)pxDescriptor->pucEthernetBuffer;
sg_list.len = (unsigned int)pxDescriptor->xDataLength;
xReturn = (BaseType_t)rltk_wlan_send(0, &sg_list, 1, pxDescriptor->xDataLength);
#endif
xReturn = pdTRUE;
#if CONFIG_USB_DEVICE_CDC_NCM
NetworkBufferDescriptor_t *pxDescriptor_eth = pxDescriptor;
if (!xReleaseAfterSend) {
pxDescriptor_eth = pxDuplicateNetworkBufferWithDescriptor(pxDescriptor, pxDescriptor->xDataLength);
xReleaseAfterSend = pdFALSE;
} else {
xReleaseAfterSend = pdFALSE;//release at usb net driver
}
//print_hex(pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, NULL);
gether_send(pxDescriptor_eth);
#else
#ifdef WIFI_SUPPORT
exit:
#endif
#endif
if( xReleaseAfterSend != pdFALSE )
{
/* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
* buffer. The Ethernet buffer is therefore no longer needed, and must be
* freed for re-use. */
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
return xReturn;
} /* End of function xNetworkInterfaceOutput() */
/***********************************************************************************************************************
* Function Name: vNetworkInterfaceAllocateRAMToBuffers ()
* Description : .
* Arguments : pxNetworkBuffers
* Return Value : none
**********************************************************************************************************************/
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
} /* End of function vNetworkInterfaceAllocateRAMToBuffers() */
/***********************************************************************************************************************
* Function Name: InitializeNetwork ()
* Description :
* Arguments : none
* Return Value : pdTRUE, pdFALSE
**********************************************************************************************************************/
#include "wifi_structures.h"
#if 0
static rtw_result_t ark_rtw_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
{
char bssid[32] = {0};
char *ptr = (char *)malloced_scan_result->ap_details.BSSID.octet;
sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
printf("\r\nSSID:%s Bssid:%s Signal strength:%d DB\r\n", malloced_scan_result->ap_details.SSID.val, bssid,
malloced_scan_result->ap_details.signal_strength);
if (malloced_scan_result->scan_complete != 0) {
printf("scan complete!\r\n");
scan_comp_flag = 1;
}
return 0;
}
#endif
static int InitializeNetwork( void )
{
BaseType_t return_code = pdTRUE;
#if CONFIG_USB_DEVICE_CDC_NCM
g_ncm_register("ncm");
#endif
return return_code;
} /* End of function InitializeNetwork() */
/***********************************************************************************************************************
* End of file "NetworkInterface.c"
**********************************************************************************************************************/
static UBaseType_t ulNextRand;
BaseType_t xTotalSuccess = 0;
UBaseType_t uxRand( void )
{
const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
ulNextRand = portGET_RUN_TIME_COUNTER_VALUE();
ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
}
extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
uint16_t usSourcePort,
uint32_t ulDestinationAddress,
uint16_t usDestinationPort )
{
( void ) ulSourceAddress;
( void ) usSourcePort;
( void ) ulDestinationAddress;
( void ) usDestinationPort;
return uxRand();
}
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
{
*( pulNumber ) = uxRand();
return pdTRUE;
}
#if 0
void vApplicationPingReplyHook( ePingReplyStatus_t eStatus,
uint16_t usIdentifier )
{
//if( eStatus == eSuccess )
{
FreeRTOS_printf( ( "Ping response received. ID: %d\r\n", usIdentifier ) );
printf("Ping response received. ID: %d\r\n", usIdentifier);
/* Increment successful ping replies. */
xTotalSuccess++;
}
}
#endif

View File

@ -0,0 +1,281 @@
/***********************************************************************************************************************
* Copyright (C) 2021 Arkmicro Corporation. All rights reserved.
***********************************************************************************************************************/
/***********************************************************************************************************************
* File Name : NetworkInterface.c
* Device(s) : RTL8189FTV
* Description : Interfaces FreeRTOS TCP/IP stack to RX Ethernet driver.
***********************************************************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
/*#include "FreeRTOS_DNS.h" */
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "wifi_constants.h"
#include "net_stack_intf.h"
#define USE_AP 0
//#define DUMP_NETWORK_DATA
#undef DUMP_NETWORK_DATA
typedef enum
{
eMACInit, /* Must initialise MAC. */
eMACPass, /* Initialisation was successful. */
eMACFailed, /* Initialisation failed. */
} eMAC_INIT_STATUS_TYPE;
static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
extern void cmd_test(const char* temp_uart_buf);
static int InitializeNetwork( void );
static int scan_comp_flag = 0;
/***********************************************************************************************************************
* Function Name: xNetworkInterfaceInitialise ()
* Description : Initialization of Ethernet driver.
* Arguments : none
* Return Value : pdPASS, pdFAIL
**********************************************************************************************************************/
BaseType_t xNetworkInterfaceInitialise( void )
{
BaseType_t xReturn;
if( xMacInitStatus == eMACInit )
{
//rltk_wlan_set_netif_info(0, NULL, "00:0c:29:5d:2e:05");
/*
* Perform the hardware specific network initialization here using the Ethernet driver library to initialize the
* Ethernet hardware, initialize DMA descriptors, and perform a PHY auto-negotiation to obtain a network link.
*
* InitialiseNetwork() uses Ethernet peripheral driver library function, and returns 0 if the initialization fails.
*/
if( InitializeNetwork() == pdFALSE )
{
xMacInitStatus = eMACFailed;
}
else
{
/* Indicate that the MAC initialisation succeeded. */
xMacInitStatus = eMACPass;
}
FreeRTOS_printf( ( "InitializeNetwork returns %s\n", ( xMacInitStatus == eMACPass ) ? "OK" : " Fail" ) );
}
if( xMacInitStatus == eMACPass )
{
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
FreeRTOS_printf( ( "xNetworkInterfaceInitialise returns %d\n", xReturn ) );
return xReturn;
} /* End of function xNetworkInterfaceInitialise() */
/***********************************************************************************************************************
* Function Name: xNetworkInterfaceOutput ()
* Description : Simple network output interface.
* Arguments : pxDescriptor, xReleaseAfterSend
* Return Value : pdTRUE, pdFALSE
**********************************************************************************************************************/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t xReleaseAfterSend )
{
BaseType_t xReturn = pdFALSE;
struct eth_drv_sg sg_list = {0};
if (xCheckLoopback( pxDescriptor, xReleaseAfterSend ) != 0 ) {
return pdTRUE;
}
if (!rltk_wlan_running(0)) {
return pdFALSE;
}
sg_list.buf = (unsigned int)pxDescriptor->pucEthernetBuffer;
sg_list.len = (unsigned int)pxDescriptor->xDataLength;
#ifdef DUMP_NETWORK_DATA
if (1) {
int i;
char* tmp = (char *)pxDescriptor->pucEthernetBuffer;
printf("\r\n send:");
for (i = 0; i < sg_list.len; i++) {
printf("%02x ", tmp[i]);
}printf("send end\r\n");
}
#endif
xReturn = (BaseType_t)rltk_wlan_send(0, &sg_list, 1, pxDescriptor->xDataLength);
xReturn = pdTRUE;
if( xReleaseAfterSend != pdFALSE )
{
/* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
* buffer. The Ethernet buffer is therefore no longer needed, and must be
* freed for re-use. */
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
return xReturn;
} /* End of function xNetworkInterfaceOutput() */
/***********************************************************************************************************************
* Function Name: vNetworkInterfaceAllocateRAMToBuffers ()
* Description : .
* Arguments : pxNetworkBuffers
* Return Value : none
**********************************************************************************************************************/
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
} /* End of function vNetworkInterfaceAllocateRAMToBuffers() */
/***********************************************************************************************************************
* Function Name: InitializeNetwork ()
* Description :
* Arguments : none
* Return Value : pdTRUE, pdFALSE
**********************************************************************************************************************/
#include "wifi_structures.h"
static rtw_result_t ark_rtw_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
{
char bssid[32] = {0};
char *ptr = malloced_scan_result->ap_details.BSSID.octet;
sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
printf("\r\nSSID:%s Bssid:%s Signal strength:%d DB\r\n", malloced_scan_result->ap_details.SSID.val, bssid,
malloced_scan_result->ap_details.signal_strength);
if (malloced_scan_result->scan_complete != 0) {
printf("scan complete!\r\n");
scan_comp_flag = 1;
}
}
extern struct sdio_func *wifi_sdio_func;
int ark_wlan_init(void)
{
int return_code = 0;
char *ssid = "ap630";
//rltk_wlan_ctx_init();
#if USE_AP
/*if (wifi_on(RTW_MODE_AP) < 0) {
printf("\r\nopen wifi failed \r\n");
return return_code;
}
printf("\r\n wifi init finished!\r\n");*/
//wifi_start_ap(ssid, RTW_SECURITY_OPEN, NULL, strlen(ssid), 0, 1);
cmd_test("wifi_ap ap630 1");
printf("\r\n wifi start now!\r\n");
#else
//cmd_test("wifi_debug set_mac 000C295D2E05");//0x00, 0x0c, 0x29, 0x5d, 0x2e, 0x05
if (wifi_on(RTW_MODE_STA) < 0) {
printf("\r\nopen wifi failed \r\n");
return return_code;
}
scan_comp_flag = 0;
//wifi_set_mac_address("000c295d2e03");
wifi_scan_networks(ark_rtw_scan_result_handler, NULL);
while(scan_comp_flag == 0)
mdelay(500);
ssid = "ark-9528";
cmd_test("wifi_connect ark-9528 02345678");
#endif
return_code = 1;
return return_code;
}
static int InitializeNetwork( void )
{
BaseType_t return_code = pdFALSE;
return pdTRUE;
} /* End of function InitializeNetwork() */
/***********************************************************************************************************************
* End of file "NetworkInterface.c"
**********************************************************************************************************************/
static UBaseType_t ulNextRand;
BaseType_t xTotalSuccess = 0;
UBaseType_t uxRand( void )
{
const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
ulNextRand = portGET_RUN_TIME_COUNTER_VALUE();
ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
}
/*-----------------------------------------------------------*/
static void prvSRand( UBaseType_t ulSeed )
{
ulNextRand = ulSeed;
}
extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
uint16_t usSourcePort,
uint32_t ulDestinationAddress,
uint16_t usDestinationPort )
{
( void ) ulSourceAddress;
( void ) usSourcePort;
( void ) ulDestinationAddress;
( void ) usDestinationPort;
return uxRand();
}
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
{
*( pulNumber ) = uxRand();
return pdTRUE;
}
void vApplicationPingReplyHook( ePingReplyStatus_t eStatus,
uint16_t usIdentifier )
{
//if( eStatus == eSuccess )
{
FreeRTOS_printf( ( "Ping response received. ID: %d\r\n", usIdentifier ) );
printf("Ping response received. ID: %d\r\n", usIdentifier);
/* Increment successful ping replies. */
xTotalSuccess++;
}
}

View File

@ -0,0 +1,108 @@
/*
* FreeRTOS V1.4.8
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file aws_wifi_config.h
* @brief WiFi module configuration parameters.
*/
#ifndef _AWS_WIFI_CONFIG_H_
#define _AWS_WIFI_CONFIG_H_
/**
* @brief Maximum number of sockets that can be created simultaneously.
*/
#define wificonfigMAX_SOCKETS ( 4 )
/**
* @brief Maximum number of connection retries.
*/
#define wificonfigNUM_CONNECTION_RETRY ( 3 )
/**
* @brief Maximum number of connected station in Access Point mode.
*/
#define wificonfigMAX_CONNECTED_STATIONS ( 4 )
/**
* @brief Max number of network profiles stored in Non Volatile memory,
* set to zero if not supported.
*/
#define wificonfigMAX_NETWORK_PROFILES ( 0 )
/**
* @brief Max SSID length
*/
#define wificonfigMAX_SSID_LEN ( 32 )
/**
* @brief Max BSSID length
*/
#define wificonfigMAX_BSSID_LEN ( 6 )
/**
* @brief Max number of WEP keys supported.
*/
#define wificonfigMAX_WEPKEYS ( 4 )
/**
* @brief Max WEP key length
*/
#define wificonfigMAX_WEPKEY_LEN ( 26 )
/**
* @brief Max passphrase length
*/
#define wificonfigMAX_PASSPHRASE_LEN ( 32 )
/**
* @brief Soft Access point SSID
*/
#define wificonfigACCESS_POINT_SSID_PREFIX ( "Enter SSID for Soft AP" )
/**
* @brief Soft Access point Passkey
*/
#define wificonfigACCESS_POINT_PASSKEY ( "Enter Password for Soft AP" )
/**
* @brief Soft Access point Channel
*/
#define wificonfigACCESS_POINT_CHANNEL ( 11 )
/**
* @brief WiFi semaphore timeout
*/
#define wificonfigMAX_SEMAPHORE_WAIT_TIME_MS ( 60000 )
/**
* @brief Soft Access point security
* WPA2 Security, see WIFISecurity_t
* other values are - eWiFiSecurityOpen, eWiFiSecurityWEP, eWiFiSecurityWPA
*/
#define wificonfigACCESS_POINT_SECURITY ( eWiFiSecurityWPA2 )
#endif /* _AWS_WIFI_CONFIG_H_ */

View File

@ -0,0 +1,724 @@
/*
* FreeRTOS Wi-Fi V1.0.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file iot_wifi.c
* @brief Wi-Fi Interface.
*/
#include <stdbool.h>
/* Socket and Wi-Fi interface includes. */
#include "FreeRTOS.h"
#include "iot_wifi.h"
/* Wi-Fi configuration includes. */
#include "aws_wifi_config.h"
#include "wifi_constants.h"
#include "net_stack_intf.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "semphr.h"
#include "wifi_structures.h"
static rtw_mode_t g_wifi_mode = RTW_MODE_STA;
static SemaphoreHandle_t xWiFiSem;
static bool wifi_started;
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_On( void )
{
WIFIReturnCode_t ret = eWiFiFailure;
xSemaphoreTake(xWiFiSem, portMAX_DELAY );
if (wifi_started) {
ret = eWiFiSuccess;
goto exit;
}
if (wifi_on(g_wifi_mode) < 0) {
printf("\r\nopen wifi failed \r\n");
goto exit;
}
wifi_started = true;
ret = eWiFiSuccess;
exit:
xSemaphoreGive(xWiFiSem);
return ret;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_Off( void )
{
xSemaphoreTake(xWiFiSem, portMAX_DELAY );
wifi_off();
wifi_started = false;
xSemaphoreGive(xWiFiSem);
return eWiFiSuccess;
}
/*-----------------------------------------------------------*/
static rtw_security_t convertWIFISecurity2rtw_security(WIFISecurity_t type)
{
rtw_security_t security_type = RTW_MODE_NONE;
switch (type) {
case eWiFiSecurityOpen:
security_type = RTW_SECURITY_OPEN;
break;
case eWiFiSecurityWPA2:
security_type = RTW_SECURITY_WPA2_AES_PSK;
break;
default:
security_type = RTW_SECURITY_UNKNOWN;
break;
}
return security_type;
}
static WIFISecurity_t convertrtw_security2WIFISecurity(rtw_security_t type)
{
WIFISecurity_t security_type = eWiFiSecurityNotSupported;
switch (type) {
case RTW_SECURITY_OPEN:
security_type = eWiFiSecurityOpen;
break;
case RTW_SECURITY_WPA2_AES_PSK:
security_type = eWiFiSecurityWPA2;
break;
default:
break;
}
return security_type;
}
static rtw_mode_t convertWIFIDevMode2rtwMode(WIFIDeviceMode_t mode)
{
rtw_mode_t rtw_mode = RTW_MODE_NONE;
switch (mode) {
case eWiFiModeStation:
rtw_mode = RTW_MODE_STA;
break;
case eWiFiModeAP:
rtw_mode = RTW_MODE_AP;
break;
case eWiFiModeP2P:
rtw_mode = RTW_MODE_P2P;
break;
case eWiFiModeAPStation:
rtw_mode = RTW_MODE_STA_AP;
break;
case eWiFiModeNotSupported:
rtw_mode = RTW_MODE_NONE;
break;
default:
break;
}
return rtw_mode;
}
static WIFIDeviceMode_t convertrtwMode2WIFIDevMode(rtw_mode_t rtw_mode)
{
WIFIDeviceMode_t dev_mode = eWiFiModeNotSupported;
switch (rtw_mode) {
case RTW_MODE_STA:
dev_mode = eWiFiModeStation;
break;
case RTW_MODE_AP:
dev_mode = eWiFiModeAP;
break;
case RTW_MODE_P2P:
dev_mode = eWiFiModeP2P;
break;
case RTW_MODE_STA_AP:
dev_mode = eWiFiModeAPStation;
break;
case RTW_MODE_NONE:
dev_mode = eWiFiModeNotSupported;
break;
default:
break;
}
return dev_mode;
}
WIFIReturnCode_t WIFI_ConnectAP( const WIFINetworkParams_t * const pxNetworkParams )
{
rtw_security_t security_type;
rtw_result_t ret = RTW_UNSUPPORTED;
if (pxNetworkParams == NULL)
return eWiFiFailure;
xSemaphoreTake(xWiFiSem, portMAX_DELAY );
security_type = convertWIFISecurity2rtw_security(pxNetworkParams->xSecurity);
if (security_type == RTW_SECURITY_WPA2_AES_PSK) {
ret = wifi_connect(pxNetworkParams->ucSSID,
security_type,
pxNetworkParams->xPassword.xWPA.cPassphrase,
pxNetworkParams->ucSSIDLength,
pxNetworkParams->xPassword.xWPA.ucLength, 0, NULL);
} else if (security_type == RTW_SECURITY_OPEN) {
ret = wifi_connect(pxNetworkParams->ucSSID,
security_type,
pxNetworkParams->xPassword.xWPA.cPassphrase,
pxNetworkParams->ucSSIDLength,
RTW_MIN_PSK_LEN, 0, NULL);
}
xSemaphoreGive(xWiFiSem);
if (ret == RTW_TIMEOUT)
return eWiFiTimeout;
else if (ret != RTW_SUCCESS)
return eWiFiFailure;
return eWiFiSuccess;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_Disconnect( void )
{
xSemaphoreTake(xWiFiSem, portMAX_DELAY );
wifi_disconnect();
xSemaphoreGive(xWiFiSem);
return eWiFiSuccess;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_Reset( void )
{
return eWiFiSuccess;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_SetMode( WIFIDeviceMode_t xDeviceMode )
{
WIFIReturnCode_t ret = eWiFiNotSupported;
switch (xDeviceMode) {
case eWiFiModeStation:
ret = eWiFiSuccess;
g_wifi_mode = RTW_MODE_STA;
break;
case eWiFiModeAP:
ret = eWiFiSuccess;
g_wifi_mode = RTW_MODE_AP;
break;
default:
break;
}
return ret;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetMode( WIFIDeviceMode_t * pxDeviceMode )
{
WIFIReturnCode_t ret = eWiFiNotSupported;
if (NULL == pxDeviceMode)
return ret;
switch (g_wifi_mode) {
case RTW_MODE_STA:
ret = eWiFiSuccess;
*pxDeviceMode = eWiFiModeStation;
break;
case RTW_MODE_AP:
ret = eWiFiSuccess;
*pxDeviceMode = eWiFiModeAP;
break;
default:
break;
}
return ret;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_NetworkAdd( const WIFINetworkProfile_t * const pxNetworkProfile,
uint16_t * pusIndex )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_NetworkGet( WIFINetworkProfile_t * pxNetworkProfile,
uint16_t usIndex )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_NetworkDelete( uint16_t usIndex )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_Ping( uint8_t * pucIPAddr,
uint16_t usCount,
uint32_t ulIntervalMS )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetMAC( uint8_t * pucMac )
{
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetHostIP( char * pcHost,
uint8_t * pucIPAddr )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
struct scan_data_ctx
{
WIFIScanResult_t *result;
int index;
int max_num;
bool scan_stop;
QueueHandle_t sem;
};
static rtw_result_t WIFI_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
{
char bssid[32] = {0};
WIFIScanResult_t *result;
struct scan_data_ctx* pscan_data = (struct scan_data_ctx*)malloced_scan_result->user_data;
int len;
char *ptr = malloced_scan_result->ap_details.BSSID.octet;
sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
printf("\r\nSSID:%s Bssid:%s Signal strength:%d DB\r\n", malloced_scan_result->ap_details.SSID.val, bssid,
malloced_scan_result->ap_details.signal_strength);
if (pscan_data->scan_stop)
return RTW_SUCCESS;
if (pscan_data->index < pscan_data->max_num) {
result = pscan_data->result + pscan_data->index;
result->ucChannel = malloced_scan_result->ap_details.channel;
result->cRSSI = malloced_scan_result->ap_details.signal_strength;
result->xSecurity = convertrtw_security2WIFISecurity(malloced_scan_result->ap_details.security);
len = wificonfigMAX_SSID_LEN;
if (len < malloced_scan_result->ap_details.SSID.len)
len = malloced_scan_result->ap_details.SSID.len;
memcpy(result->ucSSID, malloced_scan_result->ap_details.SSID.val, len);
len = wificonfigMAX_BSSID_LEN;
if (len != sizeof(malloced_scan_result->ap_details.BSSID.octet))
printf("wrong bssid len\r\n");
memcpy(result->ucBSSID, malloced_scan_result->ap_details.BSSID.octet, len);
}
if (malloced_scan_result->scan_complete != 0) {
printf("scan complete!\r\n");
xQueueSend(pscan_data->sem, NULL, 0);
}
pscan_data->index++;
return RTW_SUCCESS;
}
WIFIReturnCode_t WIFI_Scan( WIFIScanResult_t * pxBuffer,
uint8_t ucNumNetworks )
{
WIFIReturnCode_t ret = eWiFiNotSupported;
struct scan_data_ctx scan_data = {0};
if (!wifi_started)
ret = WIFI_On();
scan_data.index = 0;
scan_data.scan_stop = false;
scan_data.max_num = ucNumNetworks;
scan_data.result = pxBuffer;
scan_data.sem = xQueueCreate(1, 0);
xSemaphoreTake(xWiFiSem, portMAX_DELAY );
wifi_scan_networks(WIFI_scan_result_handler, (void *)&scan_data);
ret = xQueueReceive(scan_data.sem, NULL, portMAX_DELAY);
if( ret != pdPASS ) {
ret = eWiFiFailure;
goto exit;
}
scan_data.scan_stop = true;
vSemaphoreDelete(scan_data.sem);
ret = eWiFiSuccess;
exit:
xSemaphoreGive(xWiFiSem);
return ret;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_StartAP( void )
{
WIFIReturnCode_t xWifiStatus;
WIFI_SetMode(eWiFiModeAP);
xWifiStatus = WIFI_On();
return xWifiStatus;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_StopAP( void )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_ConfigureAP( const WIFINetworkParams_t * const pxNetworkParams )
{
WIFIReturnCode_t xWifiStatus;
int ret = -1;
if (NULL == pxNetworkParams)
return eWiFiFailure;
if (eWiFiSecurityOpen == pxNetworkParams->xSecurity) {printf("WIFI_ConfigureAP channel:%d\r\n", pxNetworkParams->ucChannel);
ret = wifi_start_ap(pxNetworkParams->ucSSID, RTW_SECURITY_OPEN, NULL,
pxNetworkParams->ucSSIDLength, 0, pxNetworkParams->ucChannel);
} else if (eWiFiSecurityWPA2 == pxNetworkParams->xSecurity) {
ret = wifi_start_ap(pxNetworkParams->ucSSID, RTW_SECURITY_WPA2_AES_PSK,
pxNetworkParams->xPassword.xWPA.cPassphrase,
pxNetworkParams->ucSSIDLength, pxNetworkParams->xPassword.xWPA.ucLength,
pxNetworkParams->ucChannel);
}
if (ret < 0)
xWifiStatus = eWiFiFailure;
else
xWifiStatus = eWiFiSuccess;
return xWifiStatus;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_SetPMMode( WIFIPMMode_t xPMModeType,
const void * pvOptionValue )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetPMMode( WIFIPMMode_t * pxPMModeType,
void * pvOptionValue )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_RegisterEvent( WIFIEventType_t xEventType,
WIFIEventHandler_t xHandler )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
BaseType_t WIFI_IsConnected( const WIFINetworkParams_t * pxNetworkParams )
{
/* FIX ME. */
return pdFALSE;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_StartScan( WIFIScanConfig_t * pxScanConfig )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetScanResults( const WIFIScanResult_t ** pxBuffer,
uint16_t * ucNumNetworks )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_StartConnectAP( const WIFINetworkParams_t * pxNetworkParams )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_StartDisconnect( void )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetConnectionInfo( WIFIConnectionInfo_t * pxConnectionInfo )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetIPInfo( WIFIIPConfiguration_t * pxIPConfig )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetRSSI( int8_t * pcRSSI )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetStationList( WIFIStationInfo_t * pxStationList,
uint8_t * pcStationListSize )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_StartDisconnectStation( uint8_t * pucMac )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_SetMAC( uint8_t * pucMac )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_SetCountryCode( const char * pcCountryCode )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetCountryCode( char * pcCountryCode )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetStatistic( WIFIStatisticInfo_t * pxStats )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
WIFIReturnCode_t WIFI_GetCapability( WIFICapabilityInfo_t * pxCaps )
{
/* FIX ME. */
return eWiFiNotSupported;
}
/*-----------------------------------------------------------*/
int WIFI_Context_init()
{
if (xWiFiSem == NULL)
xWiFiSem = xSemaphoreCreateMutex();
return 0;
}
#define clientcredentialWIFI_SSID "ark-9528"
#define clientcredentialWIFI_PASSWORD "02345678"
#define ucNumNetworks 12
#define serverWIFI_SSID "ap630"
int wifi_sta_test_proc()
{
WIFINetworkParams_t xNetworkParams = {0};
WIFIReturnCode_t xWifiStatus;
WIFI_Context_init();
WIFI_SetMode(eWiFiModeStation);
printf("Turning on wifi...\r\n");
xWifiStatus = WIFI_On();
printf("Checking status...\r\n");
if( xWifiStatus == eWiFiSuccess ) {
printf("WiFi module initialized.\r\n");
} else {
printf("WiFi module failed to initialize.\r\n" );
// Handle module init failure
return -1;
}
/* Some boards might require additional initialization steps to use the Wi-Fi library. */
while (1) {
printf("Starting scan\r\n");
WIFIScanResult_t xScanResults[ ucNumNetworks ] = {0};
xWifiStatus = WIFI_Scan( xScanResults, ucNumNetworks ); // Initiate scan
printf("Scan started\r\n");
// For each scan result, print out the SSID and RSSI
if ( xWifiStatus == eWiFiSuccess ) {
printf("Scan success\r\n");
for ( uint8_t i=0; i<ucNumNetworks; i++ ) {
printf("%s : %d \r\n", xScanResults[i].ucSSID, xScanResults[i].cRSSI);
}
break;
} else {
printf("Scan failed, status code: %d\n", (int)xWifiStatus);
return -1;
}
vTaskDelay(200);
}
/* Setup parameters. */
memset(&xNetworkParams, 0, sizeof(xNetworkParams));
xNetworkParams.ucSSIDLength = strlen( clientcredentialWIFI_SSID );
memcpy(xNetworkParams.ucSSID, clientcredentialWIFI_SSID, xNetworkParams.ucSSIDLength);
xNetworkParams.xPassword.xWPA.ucLength = strlen( clientcredentialWIFI_PASSWORD );
memcpy(xNetworkParams.xPassword.xWPA.cPassphrase, clientcredentialWIFI_PASSWORD, xNetworkParams.ucSSIDLength);
xNetworkParams.xSecurity = eWiFiSecurityWPA2;
// Connect!
xWifiStatus = WIFI_ConnectAP( &( xNetworkParams ) );
if( xWifiStatus == eWiFiSuccess ){
printf( "WiFi Connected to AP.\r\n" );
} else {
printf( "WiFi failed to connect to AP.\r\n" );
// Handle connection failure
return -1;
}
return 0;
}
extern void cmd_test(const char* temp_uart_buf);
int wifi_ap_test_proc()
{
WIFINetworkParams_t xNetworkParams = {0};
WIFIReturnCode_t xWifiStatus;
WIFI_Context_init();
#if 0
WIFI_SetMode(eWiFiModeAP);
printf("Turning on wifi...\r\n");
xWifiStatus = WIFI_On();
vTaskDelay(pdMS_TO_TICKS(1000));
printf("Checking status...\r\n");
if( xWifiStatus == eWiFiSuccess ) {
printf("WiFi module initialized.\r\n");
} else {
printf("WiFi module failed to initialize.\r\n" );
// Handle module init failure
return -1;
}
//xNetworkParams.ucChannel = 1;
//xNetworkParams.ucSSIDLength = (uint8_t)strlen(serverWIFI_SSID);
//memcpy(xNetworkParams.ucSSID, serverWIFI_SSID, strlen(serverWIFI_SSID) + 1);
//xNetworkParams.xSecurity = eWiFiSecurityOpen;
//xWifiStatus = WIFI_ConfigureAP(&xNetworkParams);
//WIFINetworkParams_t *pxNetworkParams = &xNetworkParams;
//printf("WIFI_ConfigureAP channel:%d\r\n", pxNetworkParams->ucChannel);
//wifi_start_ap(pxNetworkParams->ucSSID, RTW_SECURITY_OPEN, NULL,
// pxNetworkParams->ucSSIDLength, 0, pxNetworkParams->ucChannel);
wifi_start_ap("ap630", RTW_SECURITY_OPEN, NULL, 5, 0, 1);
xWifiStatus = eWiFiSuccess;
if( xWifiStatus == eWiFiSuccess ){
printf( "WiFi Configure AP.\r\n" );
} else {
printf( "WiFi failed to Configure AP.\r\n" );
// Handle connection failure
return -1;
}
#else
#if 1
cmd_test("wifi_ap ap630 1");
#else
char *ssid = "ap630";
int channel = 1;
int timeout = 20;
wifi_off();
vTaskDelay(pdMS_TO_TICKS(20));
if (wifi_on(RTW_MODE_AP) < 0) {
printf("\r\nopen wifi failed \r\n");
return -1;
}
printf("\r\n wifi init finished!\r\n");
//wifi_start_ap(ssid, RTW_SECURITY_OPEN, NULL, strlen(ssid), 0, 1);
wifi_start_ap(ssid,
RTW_SECURITY_OPEN,
NULL,
strlen((const char *)ssid),
0,
channel
);
while(1) {
char essid[33];
if(wext_get_ssid("wlan0", (unsigned char *) essid) > 0) {
if(strcmp((const char *) essid, (const char *)ssid) == 0) {
printf("%s started\r\n", ssid);
break;
}
}
if(timeout == 0) {
printf("ERROR: Start AP timeout!\r\n");
break;
}
vTaskDelay(pdMS_TO_TICKS(1000));
timeout --;
}
#endif
#endif
return 0;
}

View File

@ -0,0 +1,571 @@
/***********************************************************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
* applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
* this software. By using this software, you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
*
* Copyright (C) 2020 Renesas Electronics Corporation. All rights reserved.
***********************************************************************************************************************/
/***********************************************************************************************************************
* File Name : NetworkInterface.c
* Device(s) : RX
* Description : Interfaces FreeRTOS TCP/IP stack to RX Ethernet driver.
***********************************************************************************************************************/
/***********************************************************************************************************************
* History : DD.MM.YYYY Version Description
* : 07.03.2018 0.1 Development
***********************************************************************************************************************/
/***********************************************************************************************************************
* Includes <System Includes> , "Project Includes"
***********************************************************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
/*#include "FreeRTOS_DNS.h" */
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "r_ether_rx_if.h"
#include "r_pinset.h"
/***********************************************************************************************************************
* Macro definitions
**********************************************************************************************************************/
#define ETHER_BUFSIZE_MIN 60
#if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) || defined( BSP_MCU_RX72M )
#if ETHER_CFG_MODE_SEL == 0
#define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC0_MII()
#elif ETHER_CFG_MODE_SEL == 1
#define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC0_RMII()
#endif
#elif defined( BSP_MCU_RX63N )
#if ETHER_CFG_MODE_SEL == 0
#define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC_MII()
#elif ETHER_CFG_MODE_SEL == 1
#define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC_RMII()
#endif
#endif /* if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) */
#ifndef PHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkSStatus in the PHY is still high after 2 seconds of not
* receiving packets. */
#define PHY_LS_HIGH_CHECK_TIME_MS 2000
#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
/***********************************************************************************************************************
* Private global variables and functions
**********************************************************************************************************************/
typedef enum
{
eMACInit, /* Must initialise MAC. */
eMACPass, /* Initialisation was successful. */
eMACFailed, /* Initialisation failed. */
} eMAC_INIT_STATUS_TYPE;
static TaskHandle_t ether_receive_check_task_handle = 0;
static TaskHandle_t xTaskToNotify = NULL;
static BaseType_t xPHYLinkStatus;
static BaseType_t xReportedStatus;
static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
static int16_t SendData( uint8_t * pucBuffer,
size_t length );
static int InitializeNetwork( void );
static void prvEMACDeferredInterruptHandlerTask( void * pvParameters );
static void clear_all_ether_rx_discriptors( uint32_t event );
int32_t callback_ether_regist( void );
void EINT_Trig_isr( void * );
void get_random_number( uint8_t * data,
uint32_t len );
void prvLinkStatusChange( BaseType_t xStatus );
/***********************************************************************************************************************
* Function Name: xNetworkInterfaceInitialise ()
* Description : Initialization of Ethernet driver.
* Arguments : none
* Return Value : pdPASS, pdFAIL
**********************************************************************************************************************/
BaseType_t xNetworkInterfaceInitialise( void )
{
BaseType_t xReturn;
if( xMacInitStatus == eMACInit )
{
/*
* Perform the hardware specific network initialization here using the Ethernet driver library to initialize the
* Ethernet hardware, initialize DMA descriptors, and perform a PHY auto-negotiation to obtain a network link.
*
* InitialiseNetwork() uses Ethernet peripheral driver library function, and returns 0 if the initialization fails.
*/
if( InitializeNetwork() == pdFALSE )
{
xMacInitStatus = eMACFailed;
}
else
{
/* Indicate that the MAC initialisation succeeded. */
xMacInitStatus = eMACPass;
}
FreeRTOS_printf( ( "InitializeNetwork returns %s\n", ( xMacInitStatus == eMACPass ) ? "OK" : " Fail" ) );
}
if( xMacInitStatus == eMACPass )
{
xReturn = xPHYLinkStatus;
}
else
{
xReturn = pdFAIL;
}
FreeRTOS_printf( ( "xNetworkInterfaceInitialise returns %d\n", xReturn ) );
return xReturn;
} /* End of function xNetworkInterfaceInitialise() */
/***********************************************************************************************************************
* Function Name: xNetworkInterfaceOutput ()
* Description : Simple network output interface.
* Arguments : pxDescriptor, xReleaseAfterSend
* Return Value : pdTRUE, pdFALSE
**********************************************************************************************************************/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t xReleaseAfterSend )
{
BaseType_t xReturn = pdFALSE;
/* Simple network interfaces (as opposed to more efficient zero copy network
* interfaces) just use Ethernet peripheral driver library functions to copy
* data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer.
* This example assumes SendData() is a peripheral driver library function that
* takes a pointer to the start of the data to be sent and the length of the
* data to be sent as two separate parameters. The start of the data is located
* by pxDescriptor->pucEthernetBuffer. The length of the data is located
* by pxDescriptor->xDataLength. */
if( xPHYLinkStatus != 0 )
{
if( SendData( pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ) >= 0 )
{
xReturn = pdTRUE;
/* Call the standard trace macro to log the send event. */
iptraceNETWORK_INTERFACE_TRANSMIT();
}
}
else
{
/* As the PHY Link Status is low, it makes no sense trying to deliver a packet. */
}
if( xReleaseAfterSend != pdFALSE )
{
/* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
* buffer. The Ethernet buffer is therefore no longer needed, and must be
* freed for re-use. */
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
return xReturn;
} /* End of function xNetworkInterfaceOutput() */
/***********************************************************************************************************************
* Function Name: prvEMACDeferredInterruptHandlerTask ()
* Description : The deferred interrupt handler is a standard RTOS task.
* Arguments : pvParameters
* Return Value : none
**********************************************************************************************************************/
static void prvEMACDeferredInterruptHandlerTask( void * pvParameters )
{
NetworkBufferDescriptor_t * pxBufferDescriptor;
int32_t xBytesReceived = 0;
/* Avoid compiler warning about unreferenced parameter. */
( void ) pvParameters;
/* Used to indicate that xSendEventStructToIPTask() is being called because
* of an Ethernet receive event. */
IPStackEvent_t xRxEvent;
uint8_t * buffer_pointer;
/* Some variables related to monitoring the PHY. */
TimeOut_t xPhyTime;
TickType_t xPhyRemTime;
const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
FreeRTOS_printf( ( "Deferred Interrupt Handler Task started\n" ) );
xTaskToNotify = ether_receive_check_task_handle;
for( ; ; )
{
#if ( ipconfigHAS_PRINTF != 0 )
{
/* Call a function that monitors resources: the amount of free network
* buffers and the amount of free space on the heap. See FreeRTOS_IP.c
* for more detailed comments. */
vPrintResourceStats();
}
#endif /* ( ipconfigHAS_PRINTF != 0 ) */
/* Wait for the Ethernet MAC interrupt to indicate that another packet
* has been received. */
if( xBytesReceived <= 0 )
{
ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
}
/* See how much data was received. */
xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );
if( xBytesReceived < 0 )
{
/* This is an error. Logged. */
FreeRTOS_printf( ( "R_ETHER_Read_ZC2: rc = %d\n", xBytesReceived ) );
}
else if( xBytesReceived > 0 )
{
/* Allocate a network buffer descriptor that points to a buffer
* large enough to hold the received frame. As this is the simple
* rather than efficient example the received data will just be copied
* into this buffer. */
pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ( size_t ) xBytesReceived, 0 );
if( pxBufferDescriptor != NULL )
{
/* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet
* buffer large enough to hold the received data. Copy the
* received data into pcNetworkBuffer->pucEthernetBuffer. Here it
* is assumed ReceiveData() is a peripheral driver function that
* copies the received data into a buffer passed in as the function's
* parameter. Remember! While is is a simple robust technique -
* it is not efficient. An example that uses a zero copy technique
* is provided further down this page. */
memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer_pointer, ( size_t ) xBytesReceived );
/*ReceiveData( pxBufferDescriptor->pucEthernetBuffer ); */
/* Set the actual packet length, in case a larger buffer was returned. */
pxBufferDescriptor->xDataLength = ( size_t ) xBytesReceived;
R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );
/* See if the data contained in the received Ethernet frame needs
* to be processed. NOTE! It is preferable to do this in
* the interrupt service routine itself, which would remove the need
* to unblock this task for packets that don't need processing. */
if( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer ) == eProcessBuffer )
{
/* The event about to be sent to the TCP/IP is an Rx event. */
xRxEvent.eEventType = eNetworkRxEvent;
/* pvData is used to point to the network buffer descriptor that
* now references the received data. */
xRxEvent.pvData = ( void * ) pxBufferDescriptor;
/* Send the data to the TCP/IP stack. */
if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
{
/* The buffer could not be sent to the IP task so the buffer must be released. */
vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
/* Make a call to the standard trace macro to log the occurrence. */
iptraceETHERNET_RX_EVENT_LOST();
clear_all_ether_rx_discriptors( 0 );
}
else
{
/* The message was successfully sent to the TCP/IP stack.
* Call the standard trace macro to log the occurrence. */
iptraceNETWORK_INTERFACE_RECEIVE();
R_BSP_NOP();
}
}
else
{
/* The Ethernet frame can be dropped, but the Ethernet buffer must be released. */
vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
}
}
else
{
/* The event was lost because a network buffer was not available.
* Call the standard trace macro to log the occurrence. */
iptraceETHERNET_RX_EVENT_LOST();
clear_all_ether_rx_discriptors( 1 );
FreeRTOS_printf( ( "R_ETHER_Read_ZC2: Cleared descriptors\n" ) );
}
}
if( xBytesReceived > 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 );
/* Indicate that the Link Status is high, so that
* xNetworkInterfaceOutput() can send packets. */
if( xPHYLinkStatus == 0 )
{
xPHYLinkStatus = 1;
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS assume %d\n", xPHYLinkStatus ) );
}
}
else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) || ( FreeRTOS_IsNetworkUp() == pdFALSE ) )
{
R_ETHER_LinkProcess( 0 );
if( xPHYLinkStatus != xReportedStatus )
{
xPHYLinkStatus = xReportedStatus;
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", xPHYLinkStatus ) );
}
vTaskSetTimeOutState( &xPhyTime );
if( xPHYLinkStatus != 0 )
{
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
}
else
{
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
}
}
}
} /* End of function prvEMACDeferredInterruptHandlerTask() */
/***********************************************************************************************************************
* Function Name: vNetworkInterfaceAllocateRAMToBuffers ()
* Description : .
* Arguments : pxNetworkBuffers
* Return Value : none
**********************************************************************************************************************/
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
uint32_t ul;
uint8_t * buffer_address;
R_BSP_SECTION_OPERATORS_INIT( B_ETHERNET_BUFFERS_1 )
buffer_address = R_BSP_SECTOP( B_ETHERNET_BUFFERS_1 );
for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
{
pxNetworkBuffers[ ul ].pucEthernetBuffer = ( buffer_address + ( ETHER_CFG_BUFSIZE * ul ) );
}
} /* End of function vNetworkInterfaceAllocateRAMToBuffers() */
/***********************************************************************************************************************
* Function Name: prvLinkStatusChange ()
* Description : Function will be called when the Link Status of the phy has changed ( see ether_callback.c )
* Arguments : xStatus : true when statyus has become high
* Return Value : void
**********************************************************************************************************************/
void prvLinkStatusChange( BaseType_t xStatus )
{
if( xReportedStatus != xStatus )
{
FreeRTOS_printf( ( "prvLinkStatusChange( %d )\n", xStatus ) );
xReportedStatus = xStatus;
}
}
/***********************************************************************************************************************
* Function Name: InitializeNetwork ()
* Description :
* Arguments : none
* Return Value : pdTRUE, pdFALSE
**********************************************************************************************************************/
static int InitializeNetwork( void )
{
ether_return_t eth_ret;
BaseType_t return_code = pdFALSE;
ether_param_t param;
uint8_t myethaddr[ 6 ] =
{
configMAC_ADDR0,
configMAC_ADDR1,
configMAC_ADDR2,
configMAC_ADDR3,
configMAC_ADDR4,
configMAC_ADDR5
}; /*XXX Fix me */
R_ETHER_PinSet_CHANNEL_0();
R_ETHER_Initial();
callback_ether_regist();
param.channel = ETHER_CHANNEL_0;
eth_ret = R_ETHER_Control( CONTROL_POWER_ON, param ); /* PHY mode settings, module stop cancellation */
if( ETHER_SUCCESS != eth_ret )
{
return pdFALSE;
}
eth_ret = R_ETHER_Open_ZC2( ETHER_CHANNEL_0, myethaddr, ETHER_FLAG_OFF );
if( ETHER_SUCCESS != eth_ret )
{
return pdFALSE;
}
return_code = xTaskCreate( prvEMACDeferredInterruptHandlerTask,
"ETHER_RECEIVE_CHECK_TASK",
512u,
0,
configMAX_PRIORITIES - 1,
&ether_receive_check_task_handle );
if( pdFALSE == return_code )
{
return pdFALSE;
}
return pdTRUE;
} /* End of function InitializeNetwork() */
/***********************************************************************************************************************
* Function Name: SendData ()
* Description :
* Arguments : pucBuffer, length
* Return Value : 0 success, negative fail
**********************************************************************************************************************/
static int16_t SendData( uint8_t * pucBuffer,
size_t length ) /*TODO complete stub function */
{
ether_return_t ret;
uint8_t * pwrite_buffer;
uint16_t write_buf_size;
/* (1) Retrieve the transmit buffer location controlled by the descriptor. */
ret = R_ETHER_Write_ZC2_GetBuf( ETHER_CHANNEL_0, ( void ** ) &pwrite_buffer, &write_buf_size );
if( ETHER_SUCCESS == ret )
{
if( write_buf_size >= length )
{
memcpy( pwrite_buffer, pucBuffer, length );
}
if( length < ETHER_BUFSIZE_MIN ) /*under minimum*/
{
memset( ( pwrite_buffer + length ), 0, ( ETHER_BUFSIZE_MIN - length ) ); /*padding*/
length = ETHER_BUFSIZE_MIN; /*resize*/
}
ret = R_ETHER_Write_ZC2_SetBuf( ETHER_CHANNEL_0, ( uint16_t ) length );
ret = R_ETHER_CheckWrite( ETHER_CHANNEL_0 );
}
if( ETHER_SUCCESS != ret )
{
return -5; /* XXX return meaningful value */
}
else
{
return 0;
}
} /* End of function SendData() */
/***********************************************************************************************************************
* Function Name: EINT_Trig_isr
* Description : Standard frame received interrupt handler
* Arguments : ectrl - EDMAC and ETHERC control structure
* Return Value : None
* Note : This callback function is executed when EINT0 interrupt occurred.
***********************************************************************************************************************/
void EINT_Trig_isr( void * ectrl )
{
ether_cb_arg_t * pdecode;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
pdecode = ( ether_cb_arg_t * ) ectrl;
if( pdecode->status_eesr & 0x00040000 ) /* EDMAC FR (Frame Receive Event) interrupt */
{
if( xTaskToNotify != NULL )
{
vTaskNotifyGiveFromISR( ether_receive_check_task_handle, &xHigherPriorityTaskWoken );
}
/* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
* should be performed to ensure the interrupt returns directly to the highest
* priority task. The macro used for this purpose is dependent on the port in
* use and may be called portEND_SWITCHING_ISR(). */
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
/*TODO complete interrupt handler for other events. */
}
} /* End of function EINT_Trig_isr() */
static void clear_all_ether_rx_discriptors( uint32_t event )
{
int32_t xBytesReceived;
uint8_t * buffer_pointer;
/* Avoid compiler warning about unreferenced parameter. */
( void ) event;
while( 1 )
{
/* See how much data was received. */
xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );
if( 0 > xBytesReceived )
{
/* This is an error. Ignored. */
}
else if( 0 < xBytesReceived )
{
R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );
iptraceETHERNET_RX_EVENT_LOST();
}
else
{
break;
}
}
}
/***********************************************************************************************************************
* End of file "NetworkInterface.c"
**********************************************************************************************************************/

View File

@ -0,0 +1,182 @@
/***********************************************************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
* applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
* this software. By using this software, you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
*
* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
***********************************************************************************************************************/
/***********************************************************************************************************************
* File Name : ether_callback.c
* Version : ----
* Description : This module solves all the world's problems
***********************************************************************************************************************/
/**********************************************************************************************************************
* History : DD.MM.YYYY Version Description
* : 05.01.2015 ---- Clean up source code.
***********************************************************************************************************************/
/***********************************************************************************************************************
* Includes <System Includes> , "Project Includes"
***********************************************************************************************************************/
#include "r_ether_rx_if.h"
/***********************************************************************************************************************
* Private global variables and functions
***********************************************************************************************************************/
int32_t callback_ether_regist( void );
void callback_ether( void * pparam );
static void callback_wakeon_lan( uint32_t channel );
static void callback_link_on( uint32_t channel );
static void callback_link_off( uint32_t channel );
volatile uint8_t pause_enable = ETHER_FLAG_OFF;
volatile uint8_t magic_packet_detect[ ETHER_CHANNEL_MAX ];
volatile uint8_t link_detect[ ETHER_CHANNEL_MAX ];
void EINT_Trig_isr( void * );
/*
* When that Link Status changes, the following function will be called:
*/
void prvLinkStatusChange( BaseType_t xStatus );
/***********************************************************************************************************************
* Function Name: callback_ether
* Description : Regist of callback function
* Arguments : -
* Return Value : 0: success, -1:failed
***********************************************************************************************************************/
int32_t callback_ether_regist( void )
{
ether_param_t param;
ether_cb_t cb_func;
int32_t ret;
/* Set the callback function (LAN cable connect/disconnect event) */
cb_func.pcb_func = &callback_ether;
param.ether_callback = cb_func;
ret = R_ETHER_Control( CONTROL_SET_CALLBACK, param );
if( ETHER_SUCCESS != ret )
{
return -1;
}
/* Set the callback function (Ether interrupt event) */
cb_func.pcb_int_hnd = &EINT_Trig_isr;
param.ether_callback = cb_func;
ret = R_ETHER_Control( CONTROL_SET_INT_HANDLER, param );
if( ETHER_SUCCESS != ret )
{
return -1;
}
return 0;
} /* End of function callback_ether_regist() */
/***********************************************************************************************************************
* Function Name: callback_ether
* Description : Sample of the callback function
* Arguments : pparam -
*
* Return Value : none
***********************************************************************************************************************/
void callback_ether( void * pparam )
{
ether_cb_arg_t * pdecode;
uint32_t channel;
pdecode = ( ether_cb_arg_t * ) pparam;
channel = pdecode->channel; /* Get Ethernet channel number */
switch( pdecode->event_id )
{
/* Callback function that notifies user to have detected magic packet. */
case ETHER_CB_EVENT_ID_WAKEON_LAN:
callback_wakeon_lan( channel );
break;
/* Callback function that notifies user to have become Link up. */
case ETHER_CB_EVENT_ID_LINK_ON:
callback_link_on( channel );
break;
/* Callback function that notifies user to have become Link down. */
case ETHER_CB_EVENT_ID_LINK_OFF:
callback_link_off( channel );
break;
default:
break;
}
} /* End of function callback_ether() */
/***********************************************************************************************************************
* Function Name: callback_wakeon_lan
* Description :
* Arguments : channel -
* Ethernet channel number
* Return Value : none
***********************************************************************************************************************/
static void callback_wakeon_lan( uint32_t channel )
{
if( ETHER_CHANNEL_MAX > channel )
{
magic_packet_detect[ channel ] = 1;
/* Please add necessary processing when magic packet is detected. */
}
} /* End of function callback_wakeon_lan() */
/***********************************************************************************************************************
* Function Name: callback_link_on
* Description :
* Arguments : channel -
* Ethernet channel number
* Return Value : none
***********************************************************************************************************************/
static void callback_link_on( uint32_t channel )
{
if( ETHER_CHANNEL_MAX > channel )
{
link_detect[ channel ] = ETHER_FLAG_ON_LINK_ON;
/* Please add necessary processing when becoming Link up. */
prvLinkStatusChange( 1 );
}
} /* End of function callback_link_on() */
/***********************************************************************************************************************
* Function Name: callback_link_off
* Description :
* Arguments : channel -
* Ethernet channel number
* Return Value : none
***********************************************************************************************************************/
static void callback_link_off( uint32_t channel )
{
if( ETHER_CHANNEL_MAX > channel )
{
link_detect[ channel ] = ETHER_FLAG_ON_LINK_OFF;
/* Please add necessary processing when becoming Link down. */
prvLinkStatusChange( 0 );
}
} /* End of function ether_cb_link_off() */
/* End of File */

View File

@ -0,0 +1,64 @@
/*
* FreeRTOS+TCP V2.3.2 LTS Patch 1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
* driver will filter incoming packets and only pass the stack those packets it
* considers need processing. */
#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
BaseType_t xNetworkInterfaceInitialise( void )
{
/* FIX ME. */
return pdFALSE;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
BaseType_t xReleaseAfterSend )
{
/* FIX ME. */
return pdFALSE;
}
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
/* FIX ME. */
}
BaseType_t xGetPhyLinkStatus( void )
{
/* FIX ME. */
return pdFALSE;
}

View File

@ -0,0 +1 @@
Update NetworkInterface.c and include other files needed by FreeRTOS+TCP here.

View File

@ -0,0 +1,128 @@
/*
* Handling of Ethernet PHY's
* PHY's communicate with an EMAC either through
* a Media-Independent Interface (MII), or a Reduced Media-Independent Interface (RMII).
* The EMAC can poll for PHY ports on 32 different addresses. Each of the PHY ports
* shall be treated independently.
*
*/
#ifndef PHYHANDLING_H
#define PHYHANDLING_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ipconfigPHY_MAX_PORTS
/* There can be at most 32 PHY ports, but in most cases there are 4 or less. */
#define ipconfigPHY_MAX_PORTS 4
#endif
/* A generic user-provided function that reads from the PHY-port at 'xAddress'( 0-based ). A 16-bit value shall be stored in
* '*pulValue'. xRegister is the register number ( 0 .. 31 ). In fact all PHY registers are 16-bit.
* Return non-zero in case the action failed. */
typedef BaseType_t ( * xApplicationPhyReadHook_t )( BaseType_t xAddress,
BaseType_t xRegister,
uint32_t * pulValue );
/* A generic user-provided function that writes 'ulValue' to the
* PHY-port at 'xAddress' ( 0-based ). xRegister is the register number ( 0 .. 31 ).
* Return non-zero in case the action failed. */
typedef BaseType_t ( * xApplicationPhyWriteHook_t )( BaseType_t xAddress,
BaseType_t xRegister,
uint32_t ulValue );
typedef struct xPhyProperties
{
uint8_t ucSpeed;
uint8_t ucMDI_X; /* MDI-X : Medium Dependent Interface - Crossover */
uint8_t ucDuplex;
uint8_t ucSpare;
} PhyProperties_t;
typedef struct xEthernetPhy
{
xApplicationPhyReadHook_t fnPhyRead;
xApplicationPhyWriteHook_t fnPhyWrite;
uint32_t ulPhyIDs[ ipconfigPHY_MAX_PORTS ];
uint8_t ucPhyIndexes[ ipconfigPHY_MAX_PORTS ];
TimeOut_t xLinkStatusTimer;
TickType_t xLinkStatusRemaining;
BaseType_t xPortCount;
uint32_t ulBCRValue;
uint32_t ulACRValue;
uint32_t ulLinkStatusMask;
PhyProperties_t xPhyPreferences;
PhyProperties_t xPhyProperties;
} EthernetPhy_t;
/* Some defines used internally here to indicate preferences about speed, MDIX
* (wired direct or crossed), and duplex (half or full). */
/* Values for PhyProperties_t::ucSpeed : */
#define PHY_SPEED_10 1
#define PHY_SPEED_100 2
#define PHY_SPEED_AUTO 3
/* Values for PhyProperties_t::ucMDI_X : */
#define PHY_MDIX_DIRECT 1
#define PHY_MDIX_CROSSED 2
#define PHY_MDIX_AUTO 3
/* Values for PhyProperties_t::ucDuplex : */
#define PHY_DUPLEX_HALF 1
#define PHY_DUPLEX_FULL 2
#define PHY_DUPLEX_AUTO 3
/* ID's of supported PHY's : */
#define PHY_ID_LAN8742A 0x0007c130
#define PHY_ID_LAN8720 0x0007c0f0
#define PHY_ID_KSZ8041 0x000010A1
#define PHY_ID_KSZ8051 0x000010A1
#define PHY_ID_KSZ8081 0x000010A1
#define PHY_ID_KSZ8863 0x00221430
#define PHY_ID_KSZ8081MNXIA 0x00221560
#define PHY_ID_DP83848I 0x20005C90
/* Initialise the struct and assign a PHY-read and -write function. */
void vPhyInitialise( EthernetPhy_t * pxPhyObject,
xApplicationPhyReadHook_t fnPhyRead,
xApplicationPhyWriteHook_t fnPhyWrite );
/* Discover all PHY's connected by polling 32 indexes ( zero-based ) */
BaseType_t xPhyDiscover( EthernetPhy_t * pxPhyObject );
/* Send a reset command to the connected PHY ports and send configuration. */
BaseType_t xPhyConfigure( EthernetPhy_t * pxPhyObject,
const PhyProperties_t * pxPhyProperties );
/* Give a command to start auto negotiation on a set of PHY port's. */
BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t * pxPhyObject,
uint32_t ulPhyMask );
/* Do not use auto negotiation but use predefined values from 'pxPhyObject->xPhyPreferences'. */
BaseType_t xPhyFixedValue( EthernetPhy_t * pxPhyObject,
uint32_t ulPhyMask );
/* Check the current Link Status.
* 'xHadReception' : make this true if a packet has been received since the
* last call to this function. */
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t * pxPhyObject,
BaseType_t xHadReception );
/* Get the bitmask of a given 'EthernetPhy_t'. */
#define xPhyGetMask( pxPhyObject ) \
( ( ( ( uint32_t ) 1u ) << ( pxPhyObject )->xPortCount ) - 1u )
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* ifndef PHYHANDLING_H */

View File

@ -0,0 +1,108 @@
/*
* FreeRTOS V1.4.8
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file aws_wifi_config.h
* @brief WiFi module configuration parameters.
*/
#ifndef _AWS_WIFI_CONFIG_H_
#define _AWS_WIFI_CONFIG_H_
/**
* @brief Maximum number of sockets that can be created simultaneously.
*/
#define wificonfigMAX_SOCKETS ( 4 )
/**
* @brief Maximum number of connection retries.
*/
#define wificonfigNUM_CONNECTION_RETRY ( 3 )
/**
* @brief Maximum number of connected station in Access Point mode.
*/
#define wificonfigMAX_CONNECTED_STATIONS ( 4 )
/**
* @brief Max number of network profiles stored in Non Volatile memory,
* set to zero if not supported.
*/
#define wificonfigMAX_NETWORK_PROFILES ( 0 )
/**
* @brief Max SSID length
*/
#define wificonfigMAX_SSID_LEN ( 32 )
/**
* @brief Max BSSID length
*/
#define wificonfigMAX_BSSID_LEN ( 6 )
/**
* @brief Max number of WEP keys supported.
*/
#define wificonfigMAX_WEPKEYS ( 4 )
/**
* @brief Max WEP key length
*/
#define wificonfigMAX_WEPKEY_LEN ( 26 )
/**
* @brief Max passphrase length
*/
#define wificonfigMAX_PASSPHRASE_LEN ( 32 )
/**
* @brief Soft Access point SSID
*/
#define wificonfigACCESS_POINT_SSID_PREFIX ( "Enter SSID for Soft AP" )
/**
* @brief Soft Access point Passkey
*/
#define wificonfigACCESS_POINT_PASSKEY ( "Enter Password for Soft AP" )
/**
* @brief Soft Access point Channel
*/
#define wificonfigACCESS_POINT_CHANNEL ( 11 )
/**
* @brief WiFi semaphore timeout
*/
#define wificonfigMAX_SEMAPHORE_WAIT_TIME_MS ( 60000 )
/**
* @brief Soft Access point security
* WPA2 Security, see WIFISecurity_t
* other values are - eWiFiSecurityOpen, eWiFiSecurityWEP, eWiFiSecurityWPA
*/
#define wificonfigACCESS_POINT_SECURITY ( eWiFiSecurityWPA2 )
#endif /* _AWS_WIFI_CONFIG_H_ */