1.将A27新UI文件夹重命名为CANUI 2.A272O新版本发布
This commit is contained in:
@ -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;
|
||||
}
|
@ -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 ) */
|
1335
MXC_A27-PCB4.5-CANUI/FreeRTOS-Plus/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
Normal file
1335
MXC_A27-PCB4.5-CANUI/FreeRTOS-Plus/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
2120
MXC_A27-PCB4.5-CANUI/FreeRTOS-Plus/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
Normal file
2120
MXC_A27-PCB4.5-CANUI/FreeRTOS-Plus/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
Normal file
File diff suppressed because it is too large
Load Diff
3425
MXC_A27-PCB4.5-CANUI/FreeRTOS-Plus/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
Normal file
3425
MXC_A27-PCB4.5-CANUI/FreeRTOS-Plus/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
@ -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;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
@ -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 */
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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
|
@ -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 */
|
@ -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 */
|
File diff suppressed because it is too large
Load Diff
@ -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 */
|
@ -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 ) */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 */
|
@ -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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
;
|
@ -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
|
@ -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;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
@ -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
|
||||
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
@ -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_ */
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
ðer_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"
|
||||
**********************************************************************************************************************/
|
@ -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 */
|
@ -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;
|
||||
}
|
@ -0,0 +1 @@
|
||||
Update NetworkInterface.c and include other files needed by FreeRTOS+TCP here.
|
@ -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 */
|
@ -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_ */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user