POSIX code/demo initial commit.

This was the code we uploaded to freertos.org for 2018's reinvent. The todos for this version:
- Take out unnecessary demos and source files. This repo should only have POSIX source files, FreeRTOS files, Windows port, and demo project.
This commit is contained in:
Yuhui Zheng 2019-11-20 11:24:35 -08:00
commit 7fc9c915eb
1121 changed files with 463036 additions and 0 deletions

View File

@ -0,0 +1,353 @@
/*
* FreeRTOS+TCP V2.0.3
* 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
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_TCP_server.h"
#include "FreeRTOS_server_private.h"
/* Remove the entire file if TCP is not being used. */
#if( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) )
#if !defined( ARRAY_SIZE )
#define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )
#endif
static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket );
static char *strnew( const char *pcString );
/* Remove slashes at the end of a path. */
static void prvRemoveSlash( char *pcDir );
TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount )
{
TCPServer_t *pxServer;
SocketSet_t xSocketSet;
/* Create a new server.
xPort / xPortAlt : Make the service available on 1 or 2 public port numbers. */
xSocketSet = FreeRTOS_CreateSocketSet();
if( xSocketSet != NULL )
{
BaseType_t xSize;
xSize = sizeof( *pxServer ) - sizeof( pxServer->xServers ) + xCount * sizeof( pxServer->xServers[ 0 ] );
pxServer = ( TCPServer_t * ) pvPortMallocLarge( xSize );
if( pxServer != NULL )
{
struct freertos_sockaddr xAddress;
BaseType_t xNoTimeout = 0;
BaseType_t xIndex;
memset( pxServer, '\0', xSize );
pxServer->xServerCount = xCount;
pxServer->xSocketSet = xSocketSet;
for( xIndex = 0; xIndex < xCount; xIndex++ )
{
BaseType_t xPortNumber = pxConfigs[ xIndex ].xPortNumber;
if( xPortNumber > 0 )
{
Socket_t xSocket;
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
FreeRTOS_printf( ( "TCP socket on port %d\n", ( int )xPortNumber ) );
if( xSocket != FREERTOS_NO_SOCKET )
{
xAddress.sin_addr = FreeRTOS_GetIPAddress(); // Single NIC, currently not used
xAddress.sin_port = FreeRTOS_htons( xPortNumber );
FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );
FreeRTOS_listen( xSocket, pxConfigs[ xIndex ].xBackLog );
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );
#if( ipconfigHTTP_RX_BUFSIZE > 0 )
{
if( pxConfigs[ xIndex ].eType == eSERVER_HTTP )
{
WinProperties_t xWinProps;
memset( &xWinProps, '\0', sizeof( xWinProps ) );
/* The parent socket itself won't get connected. The properties below
will be inherited by each new child socket. */
xWinProps.lTxBufSize = ipconfigHTTP_TX_BUFSIZE;
xWinProps.lTxWinSize = ipconfigHTTP_TX_WINSIZE;
xWinProps.lRxBufSize = ipconfigHTTP_RX_BUFSIZE;
xWinProps.lRxWinSize = ipconfigHTTP_RX_WINSIZE;
/* Set the window and buffer sizes. */
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
}
}
#endif
FreeRTOS_FD_SET( xSocket, xSocketSet, eSELECT_READ|eSELECT_EXCEPT );
pxServer->xServers[ xIndex ].xSocket = xSocket;
pxServer->xServers[ xIndex ].eType = pxConfigs[ xIndex ].eType;
pxServer->xServers[ xIndex ].pcRootDir = strnew( pxConfigs[ xIndex ].pcRootDir );
prvRemoveSlash( ( char * ) pxServer->xServers[ xIndex ].pcRootDir );
}
}
}
}
else
{
/* Could not allocate the server, delete the socket set */
FreeRTOS_DeleteSocketSet( xSocketSet );
}
}
else
{
/* Could not create a socket set, return NULL */
pxServer = NULL;
}
return pxServer;
}
/*-----------------------------------------------------------*/
static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket )
{
TCPClient_t *pxClient = NULL;
BaseType_t xSize = 0;
FTCPWorkFunction fWorkFunc = NULL;
FTCPDeleteFunction fDeleteFunc = NULL;
const char *pcType = "Unknown";
/*_RB_ Can the work and delete functions be part of the xSERVER_CONFIG structure
becomes generic, with no pre-processing required? */
#if( ipconfigUSE_HTTP != 0 )
{
if( pxServer->xServers[ xIndex ].eType == eSERVER_HTTP )
{
xSize = sizeof( HTTPClient_t );
fWorkFunc = xHTTPClientWork;
fDeleteFunc = vHTTPClientDelete;
pcType = "HTTP";
}
}
#endif /* ipconfigUSE_HTTP != 0 */
#if( ipconfigUSE_FTP != 0 )
{
if( pxServer->xServers[ xIndex ].eType == eSERVER_FTP )
{
xSize = sizeof( FTPClient_t );
fWorkFunc = xFTPClientWork;
fDeleteFunc = vFTPClientDelete;
pcType = "FTP";
}
}
#endif /* ipconfigUSE_FTP != 0 */
/* Malloc enough space for a new HTTP-client */
if( xSize )
{
pxClient = ( TCPClient_t* ) pvPortMallocLarge( xSize );
}
if( pxClient != NULL )
{
memset( pxClient, '\0', xSize );
/* Put the new client in front of the list. */
pxClient->eType = pxServer->xServers[ xIndex ].eType;
pxClient->pcRootDir = pxServer->xServers[ xIndex ].pcRootDir;
pxClient->pxParent = pxServer;
pxClient->xSocket = xNexSocket;
pxClient->pxNextClient = pxServer->pxClients;
pxClient->fWorkFunction = fWorkFunc;
pxClient->fDeleteFunction = fDeleteFunc;
pxServer->pxClients = pxClient;
FreeRTOS_FD_SET( xNexSocket, pxServer->xSocketSet, eSELECT_READ|eSELECT_EXCEPT );
}
else
{
pcType = "closed";
FreeRTOS_closesocket( xNexSocket );
}
{
struct freertos_sockaddr xRemoteAddress;
FreeRTOS_GetRemoteAddress( pxClient->xSocket, &xRemoteAddress );
FreeRTOS_printf( ( "TPC-server: new %s client %xip\n", pcType, (unsigned)FreeRTOS_ntohl( xRemoteAddress.sin_addr ) ) );
}
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */
( void ) pcType;
}
/*-----------------------------------------------------------*/
void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime )
{
TCPClient_t **ppxClient;
BaseType_t xIndex;
BaseType_t xRc;
/* Let the server do one working cycle */
xRc = FreeRTOS_select( pxServer->xSocketSet, xBlockingTime );
if( xRc != 0 )
{
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
{
struct freertos_sockaddr xAddress;
Socket_t xNexSocket;
socklen_t xSocketLength;
if( pxServer->xServers[ xIndex ].xSocket == FREERTOS_NO_SOCKET )
{
continue;
}
xSocketLength = sizeof( xAddress );
xNexSocket = FreeRTOS_accept( pxServer->xServers[ xIndex ].xSocket, &xAddress, &xSocketLength);
if( ( xNexSocket != FREERTOS_NO_SOCKET ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) )
{
prvReceiveNewClient( pxServer, xIndex, xNexSocket );
}
}
}
ppxClient = &pxServer->pxClients;
while( ( * ppxClient ) != NULL )
{
TCPClient_t *pxThis = *ppxClient;
/* Almost C++ */
xRc = pxThis->fWorkFunction( pxThis );
if (xRc < 0 )
{
*ppxClient = pxThis->pxNextClient;
/* Close handles, resources */
pxThis->fDeleteFunction( pxThis );
/* Free the space */
vPortFreeLarge( pxThis );
}
else
{
ppxClient = &( pxThis->pxNextClient );
}
}
}
/*-----------------------------------------------------------*/
static char *strnew( const char *pcString )
{
BaseType_t xLength;
char *pxBuffer;
xLength = strlen( pcString ) + 1;
pxBuffer = ( char * ) pvPortMalloc( xLength );
if( pxBuffer != NULL )
{
memcpy( pxBuffer, pcString, xLength );
}
return pxBuffer;
}
/*-----------------------------------------------------------*/
static void prvRemoveSlash( char *pcDir )
{
BaseType_t xLength = strlen( pcDir );
while( ( xLength > 0 ) && ( pcDir[ xLength - 1 ] == '/' ) )
{
pcDir[ --xLength ] = '\0';
}
}
/*-----------------------------------------------------------*/
#if( ipconfigSUPPORT_SIGNALS != 0 )
/* FreeRTOS_TCPServerWork() calls select().
The two functions below provide a possibility to interrupt
the call to select(). After the interruption, resume
by calling FreeRTOS_TCPServerWork() again. */
BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer )
{
BaseType_t xIndex;
BaseType_t xResult = pdFALSE;
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
{
if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
{
FreeRTOS_SignalSocket( pxServer->xServers[ xIndex ].xSocket );
xResult = pdTRUE;
break;
}
}
return xResult;
}
#endif /* ipconfigSUPPORT_SIGNALS */
/*-----------------------------------------------------------*/
#if( ipconfigSUPPORT_SIGNALS != 0 )
/* Same as above: this function may be called from an ISR,
for instance a GPIO interrupt. */
BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken )
{
BaseType_t xIndex;
BaseType_t xResult = pdFALSE;
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
{
if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
{
FreeRTOS_SignalSocketFromISR( pxServer->xServers[ xIndex ].xSocket, pxHigherPriorityTaskWoken );
xResult = pdTRUE;
break;
}
}
return xResult;
}
#endif /* ipconfigSUPPORT_SIGNALS */
/*-----------------------------------------------------------*/
#endif /* ( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) ) */

View File

@ -0,0 +1,74 @@
/*
* FreeRTOS+TCP V2.0.3
* 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
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_FTP_commands.h"
const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ] =
{
/* cmdLen cmdName[7] cmdType checkLogin checkNullArg */
{ 4, "USER", ECMD_USER, pdFALSE, pdFALSE },
{ 4, "PASS", ECMD_PASS, pdFALSE, pdFALSE },
{ 4, "ACCT", ECMD_ACCT, pdTRUE, pdFALSE },
{ 3, "CWD", ECMD_CWD, pdTRUE, pdTRUE },
{ 4, "CDUP", ECMD_CDUP, pdTRUE, pdFALSE },
{ 4, "SMNT", ECMD_SMNT, pdTRUE, pdFALSE },
{ 4, "QUIT", ECMD_QUIT, pdTRUE, pdFALSE },
{ 4, "REIN", ECMD_REIN, pdTRUE, pdFALSE },
{ 4, "PORT", ECMD_PORT, pdTRUE, pdFALSE },
{ 4, "PASV", ECMD_PASV, pdTRUE, pdFALSE },
{ 4, "TYPE", ECMD_TYPE, pdTRUE, pdFALSE },
{ 4, "STRU", ECMD_STRU, pdTRUE, pdFALSE },
{ 4, "MODE", ECMD_MODE, pdTRUE, pdFALSE },
{ 4, "RETR", ECMD_RETR, pdTRUE, pdTRUE },
{ 4, "STOR", ECMD_STOR, pdTRUE, pdTRUE },
{ 4, "STOU", ECMD_STOU, pdTRUE, pdFALSE },
{ 4, "APPE", ECMD_APPE, pdTRUE, pdFALSE },
{ 4, "ALLO", ECMD_ALLO, pdTRUE, pdFALSE },
{ 4, "REST", ECMD_REST, pdTRUE, pdFALSE },
{ 4, "RNFR", ECMD_RNFR, pdTRUE, pdTRUE },
{ 4, "RNTO", ECMD_RNTO, pdTRUE, pdTRUE },
{ 4, "ABOR", ECMD_ABOR, pdTRUE, pdFALSE },
{ 4, "SIZE", ECMD_SIZE, pdTRUE, pdTRUE },
{ 4, "MDTM", ECMD_MDTM, pdTRUE, pdTRUE },
{ 4, "DELE", ECMD_DELE, pdTRUE, pdTRUE },
{ 3, "RMD", ECMD_RMD, pdTRUE, pdTRUE },
{ 3, "MKD", ECMD_MKD, pdTRUE, pdTRUE },
{ 3, "PWD", ECMD_PWD, pdTRUE, pdFALSE },
{ 4, "LIST", ECMD_LIST, pdTRUE, pdFALSE },
{ 4, "NLST", ECMD_NLST, pdTRUE, pdFALSE },
{ 4, "SITE", ECMD_SITE, pdTRUE, pdFALSE },
{ 4, "SYST", ECMD_SYST, pdFALSE, pdFALSE },
{ 4, "FEAT", ECMD_FEAT, pdFALSE, pdFALSE },
{ 4, "STAT", ECMD_STAT, pdTRUE, pdFALSE },
{ 4, "HELP", ECMD_HELP, pdFALSE, pdFALSE },
{ 4, "NOOP", ECMD_NOOP, pdFALSE, pdFALSE },
{ 4, "EMPT", ECMD_EMPTY, pdFALSE, pdFALSE },
{ 4, "CLOS", ECMD_CLOSE, pdTRUE, pdFALSE },
{ 4, "UNKN", ECMD_UNKNOWN, pdFALSE, pdFALSE },
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
/*
* FreeRTOS+TCP V2.0.3
* 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
*/
/* Standard includes. */
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "FreeRTOS_HTTP_commands.h"
const struct xWEB_COMMAND xWebCommands[ WEB_CMD_COUNT ] =
{
{ 3, "GET", ECMD_GET },
{ 4, "HEAD", ECMD_HEAD },
{ 4, "POST", ECMD_POST },
{ 3, "PUT", ECMD_PUT },
{ 6, "DELETE", ECMD_DELETE },
{ 5, "TRACE", ECMD_TRACE },
{ 7, "OPTIONS", ECMD_OPTIONS },
{ 7, "CONNECT", ECMD_CONNECT },
{ 5, "PATCH", ECMD_PATCH },
{ 4, "UNKN", ECMD_UNK },
};
const char *webCodename (int aCode)
{
switch (aCode) {
case WEB_REPLY_OK: // = 200,
return "OK";
case WEB_NO_CONTENT: // 204
return "No content";
case WEB_BAD_REQUEST: // = 400,
return "Bad request";
case WEB_UNAUTHORIZED: // = 401,
return "Authorization Required";
case WEB_NOT_FOUND: // = 404,
return "Not Found";
case WEB_GONE: // = 410,
return "Done";
case WEB_PRECONDITION_FAILED: // = 412,
return "Precondition Failed";
case WEB_INTERNAL_SERVER_ERROR: // = 500,
return "Internal Server Error";
}
return "Unknown";
}

View File

@ -0,0 +1,428 @@
/*
* FreeRTOS+TCP V2.0.3
* 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
*/
/* Standard includes. */
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
/* FreeRTOS Protocol includes. */
#include "FreeRTOS_HTTP_commands.h"
#include "FreeRTOS_TCP_server.h"
#include "FreeRTOS_server_private.h"
/* Remove the whole file if HTTP is not supported. */
#if( ipconfigUSE_HTTP == 1 )
/* FreeRTOS+FAT includes. */
#include "ff_stdio.h"
#ifndef HTTP_SERVER_BACKLOG
#define HTTP_SERVER_BACKLOG ( 12 )
#endif
#ifndef USE_HTML_CHUNKS
#define USE_HTML_CHUNKS ( 0 )
#endif
#if !defined( ARRAY_SIZE )
#define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )
#endif
/* Some defines to make the code more readbale */
#define pcCOMMAND_BUFFER pxClient->pxParent->pcCommandBuffer
#define pcNEW_DIR pxClient->pxParent->pcNewDir
#define pcFILE_BUFFER pxClient->pxParent->pcFileBuffer
#ifndef ipconfigHTTP_REQUEST_CHARACTER
#define ipconfigHTTP_REQUEST_CHARACTER '?'
#endif
/*_RB_ Need comment block, although fairly self evident. */
static void prvFileClose( HTTPClient_t *pxClient );
static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex );
static const char *pcGetContentsType( const char *apFname );
static BaseType_t prvOpenURL( HTTPClient_t *pxClient );
static BaseType_t prvSendFile( HTTPClient_t *pxClient );
static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode );
static const char pcEmptyString[1] = { '\0' };
typedef struct xTYPE_COUPLE
{
const char *pcExtension;
const char *pcType;
} TypeCouple_t;
static TypeCouple_t pxTypeCouples[ ] =
{
{ "html", "text/html" },
{ "css", "text/css" },
{ "js", "text/javascript" },
{ "png", "image/png" },
{ "jpg", "image/jpeg" },
{ "gif", "image/gif" },
{ "txt", "text/plain" },
{ "mp3", "audio/mpeg3" },
{ "wav", "audio/wav" },
{ "flac", "audio/ogg" },
{ "pdf", "application/pdf" },
{ "ttf", "application/x-font-ttf" },
{ "ttc", "application/x-font-ttf" }
};
void vHTTPClientDelete( TCPClient_t *pxTCPClient )
{
HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient;
/* This HTTP client stops, close / release all resources. */
if( pxClient->xSocket != FREERTOS_NO_SOCKET )
{
FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_ALL );
FreeRTOS_closesocket( pxClient->xSocket );
pxClient->xSocket = FREERTOS_NO_SOCKET;
}
prvFileClose( pxClient );
}
/*-----------------------------------------------------------*/
static void prvFileClose( HTTPClient_t *pxClient )
{
if( pxClient->pxFileHandle != NULL )
{
FreeRTOS_printf( ( "Closing file: %s\n", pxClient->pcCurrentFilename ) );
ff_fclose( pxClient->pxFileHandle );
pxClient->pxFileHandle = NULL;
}
}
/*-----------------------------------------------------------*/
static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode )
{
struct xTCP_SERVER *pxParent = pxClient->pxParent;
BaseType_t xRc;
/* A normal command reply on the main socket (port 21). */
char *pcBuffer = pxParent->pcFileBuffer;
xRc = snprintf( pcBuffer, sizeof( pxParent->pcFileBuffer ),
"HTTP/1.1 %d %s\r\n"
#if USE_HTML_CHUNKS
"Transfer-Encoding: chunked\r\n"
#endif
"Content-Type: %s\r\n"
"Connection: keep-alive\r\n"
"%s\r\n",
( int ) xCode,
webCodename (xCode),
pxParent->pcContentsType[0] ? pxParent->pcContentsType : "text/html",
pxParent->pcExtraContents );
pxParent->pcContentsType[0] = '\0';
pxParent->pcExtraContents[0] = '\0';
xRc = FreeRTOS_send( pxClient->xSocket, ( const void * ) pcBuffer, xRc, 0 );
pxClient->bits.bReplySent = pdTRUE_UNSIGNED;
return xRc;
}
/*-----------------------------------------------------------*/
static BaseType_t prvSendFile( HTTPClient_t *pxClient )
{
size_t uxSpace;
size_t uxCount;
BaseType_t xRc = 0;
if( pxClient->bits.bReplySent == pdFALSE_UNSIGNED )
{
pxClient->bits.bReplySent = pdTRUE_UNSIGNED;
strcpy( pxClient->pxParent->pcContentsType, pcGetContentsType( pxClient->pcCurrentFilename ) );
snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),
"Content-Length: %d\r\n", ( int ) pxClient->uxBytesLeft );
/* "Requested file action OK". */
xRc = prvSendReply( pxClient, WEB_REPLY_OK );
}
if( xRc >= 0 ) do
{
uxSpace = FreeRTOS_tx_space( pxClient->xSocket );
if( pxClient->uxBytesLeft < uxSpace )
{
uxCount = pxClient->uxBytesLeft;
}
else
{
uxCount = uxSpace;
}
if( uxCount > 0u )
{
if( uxCount > sizeof( pxClient->pxParent->pcFileBuffer ) )
{
uxCount = sizeof( pxClient->pxParent->pcFileBuffer );
}
ff_fread( pxClient->pxParent->pcFileBuffer, 1, uxCount, pxClient->pxFileHandle );
pxClient->uxBytesLeft -= uxCount;
xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pxParent->pcFileBuffer, uxCount, 0 );
if( xRc < 0 )
{
break;
}
}
} while( uxCount > 0u );
if( pxClient->uxBytesLeft == 0u )
{
/* Writing is ready, no need for further 'eSELECT_WRITE' events. */
FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
prvFileClose( pxClient );
}
else
{
/* Wake up the TCP task as soon as this socket may be written to. */
FreeRTOS_FD_SET( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
}
return xRc;
}
/*-----------------------------------------------------------*/
static BaseType_t prvOpenURL( HTTPClient_t *pxClient )
{
BaseType_t xRc;
char pcSlash[ 2 ];
pxClient->bits.ulFlags = 0;
#if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )
{
if( strchr( pxClient->pcUrlData, ipconfigHTTP_REQUEST_CHARACTER ) != NULL )
{
size_t xResult;
xResult = uxApplicationHTTPHandleRequestHook( pxClient->pcUrlData, pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ) );
if( xResult > 0 )
{
strcpy( pxClient->pxParent->pcContentsType, "text/html" );
snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),
"Content-Length: %d\r\n", ( int ) xResult );
xRc = prvSendReply( pxClient, WEB_REPLY_OK ); /* "Requested file action OK" */
if( xRc > 0 )
{
xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pcCurrentFilename, xResult, 0 );
}
/* Although against the coding standard of FreeRTOS, a return is
done here to simplify this conditional code. */
return xRc;
}
}
}
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
if( pxClient->pcUrlData[ 0 ] != '/' )
{
/* Insert a slash before the file name. */
pcSlash[ 0 ] = '/';
pcSlash[ 1 ] = '\0';
}
else
{
/* The browser provided a starting '/' already. */
pcSlash[ 0 ] = '\0';
}
snprintf( pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ), "%s%s%s",
pxClient->pcRootDir,
pcSlash,
pxClient->pcUrlData);
pxClient->pxFileHandle = ff_fopen( pxClient->pcCurrentFilename, "rb" );
FreeRTOS_printf( ( "Open file '%s': %s\n", pxClient->pcCurrentFilename,
pxClient->pxFileHandle != NULL ? "Ok" : strerror( stdioGET_ERRNO() ) ) );
if( pxClient->pxFileHandle == NULL )
{
/* "404 File not found". */
xRc = prvSendReply( pxClient, WEB_NOT_FOUND );
}
else
{
pxClient->uxBytesLeft = ( size_t ) pxClient->pxFileHandle->ulFileSize;
xRc = prvSendFile( pxClient );
}
return xRc;
}
/*-----------------------------------------------------------*/
static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex )
{
BaseType_t xResult = 0;
/* A new command has been received. Process it. */
switch( xIndex )
{
case ECMD_GET:
xResult = prvOpenURL( pxClient );
break;
case ECMD_HEAD:
case ECMD_POST:
case ECMD_PUT:
case ECMD_DELETE:
case ECMD_TRACE:
case ECMD_OPTIONS:
case ECMD_CONNECT:
case ECMD_PATCH:
case ECMD_UNK:
{
FreeRTOS_printf( ( "prvProcessCmd: Not implemented: %s\n",
xWebCommands[xIndex].pcCommandName ) );
}
break;
}
return xResult;
}
/*-----------------------------------------------------------*/
BaseType_t xHTTPClientWork( TCPClient_t *pxTCPClient )
{
BaseType_t xRc;
HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient;
if( pxClient->pxFileHandle != NULL )
{
prvSendFile( pxClient );
}
xRc = FreeRTOS_recv( pxClient->xSocket, ( void * )pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), 0 );
if( xRc > 0 )
{
BaseType_t xIndex;
const char *pcEndOfCmd;
const struct xWEB_COMMAND *curCmd;
char *pcBuffer = pcCOMMAND_BUFFER;
if( xRc < ( BaseType_t ) sizeof( pcCOMMAND_BUFFER ) )
{
pcBuffer[ xRc ] = '\0';
}
while( xRc && ( pcBuffer[ xRc - 1 ] == 13 || pcBuffer[ xRc - 1 ] == 10 ) )
{
pcBuffer[ --xRc ] = '\0';
}
pcEndOfCmd = pcBuffer + xRc;
curCmd = xWebCommands;
/* Pointing to "/index.html HTTP/1.1". */
pxClient->pcUrlData = pcBuffer;
/* Pointing to "HTTP/1.1". */
pxClient->pcRestData = pcEmptyString;
/* Last entry is "ECMD_UNK". */
for( xIndex = 0; xIndex < WEB_CMD_COUNT - 1; xIndex++, curCmd++ )
{
BaseType_t xLength;
xLength = curCmd->xCommandLength;
if( ( xRc >= xLength ) && ( memcmp( curCmd->pcCommandName, pcBuffer, xLength ) == 0 ) )
{
char *pcLastPtr;
pxClient->pcUrlData += xLength + 1;
for( pcLastPtr = (char *)pxClient->pcUrlData; pcLastPtr < pcEndOfCmd; pcLastPtr++ )
{
char ch = *pcLastPtr;
if( ( ch == '\0' ) || ( strchr( "\n\r \t", ch ) != NULL ) )
{
*pcLastPtr = '\0';
pxClient->pcRestData = pcLastPtr + 1;
break;
}
}
break;
}
}
if( xIndex < ( WEB_CMD_COUNT - 1 ) )
{
xRc = prvProcessCmd( pxClient, xIndex );
}
}
else if( xRc < 0 )
{
/* The connection will be closed and the client will be deleted. */
FreeRTOS_printf( ( "xHTTPClientWork: rc = %ld\n", xRc ) );
}
return xRc;
}
/*-----------------------------------------------------------*/
static const char *pcGetContentsType (const char *apFname)
{
const char *slash = NULL;
const char *dot = NULL;
const char *ptr;
const char *pcResult = "text/html";
BaseType_t x;
for( ptr = apFname; *ptr; ptr++ )
{
if (*ptr == '.') dot = ptr;
if (*ptr == '/') slash = ptr;
}
if( dot > slash )
{
dot++;
for( x = 0; x < ARRAY_SIZE( pxTypeCouples ); x++ )
{
if( strcasecmp( dot, pxTypeCouples[ x ].pcExtension ) == 0 )
{
pcResult = pxTypeCouples[ x ].pcType;
break;
}
}
}
return pcResult;
}
#endif /* ipconfigUSE_HTTP */

View File

@ -0,0 +1,440 @@
/*
* FreeRTOS+TCP V2.0.3
* 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
*/
/*
* NTPDemo.c
*
* An example of how to lookup a domain using DNS
* And also how to send and receive UDP messages to get the NTP time
*
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_Stream_Buffer.h"
/* Use the date & time functions from +FAT. */
#include "ff_time.h"
#include "NTPDemo.h"
#include "ntpClient.h"
#include "date_and_time.h"
enum EStatus {
EStatusLookup,
EStatusAsking,
EStatusPause,
EStatusFailed,
};
static struct SNtpPacket xNTPPacket;
#if( ipconfigUSE_CALLBACKS == 0 )
static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ];
#endif
static enum EStatus xStatus = EStatusLookup;
static const char *pcTimeServers[] = {
"0.asia.pool.ntp.org",
"0.europe.pool.ntp.org",
"0.id.pool.ntp.org",
"0.south-america.pool.ntp.org",
"0.oceania.pool.ntp.org",
"0.north-america.pool.ntp.org"
};
static SemaphoreHandle_t xNTPWakeupSem = NULL;
static uint32_t ulIPAddressFound;
static Socket_t xUDPSocket = NULL;
static TaskHandle_t xNTPTaskhandle = NULL;
static TickType_t uxSendTime;
static void prvNTPTask( void *pvParameters );
static void vSignalTask( void )
{
#if( ipconfigUSE_CALLBACKS == 0 )
if( xUDPSocket != NULL )
{
/* Send a signal to the socket so that the
FreeRTOS_recvfrom will get interrupted. */
FreeRTOS_SignalSocket( xUDPSocket );
}
else
#endif
if( xNTPWakeupSem != NULL )
{
xSemaphoreGive( xNTPWakeupSem );
}
}
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )
{
/* The only public function in this module: start a task to contact
some NTP server. */
if( xNTPTaskhandle != NULL )
{
switch( xStatus )
{
case EStatusPause:
xStatus = EStatusAsking;
vSignalTask();
break;
case EStatusLookup:
FreeRTOS_printf( ( "NTP looking up server\n" ) );
break;
case EStatusAsking:
FreeRTOS_printf( ( "NTP still asking\n" ) );
break;
case EStatusFailed:
FreeRTOS_printf( ( "NTP failed somehow\n" ) );
ulIPAddressFound = 0ul;
xStatus = EStatusLookup;
vSignalTask();
break;
}
}
else
{
xUDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
if( xUDPSocket != NULL )
{
struct freertos_sockaddr xAddress;
#if( ipconfigUSE_CALLBACKS != 0 )
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 );
#else
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );
#endif
xAddress.sin_addr = 0ul;
xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
FreeRTOS_bind( xUDPSocket, &xAddress, sizeof( xAddress ) );
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
xTaskCreate( prvNTPTask, /* The function that implements the task. */
( const char * ) "NTP client", /* Just a text name for the task to aid debugging. */
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
NULL, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
&xNTPTaskhandle ); /* The task handle. */
}
else
{
FreeRTOS_printf( ( "Creating socket failed\n" ) );
}
}
}
/*-----------------------------------------------------------*/
static void vDNS_callback( const char *pcName, void *pvSearchID, uint32_t ulIPAddress )
{
char pcBuf[16];
/* The DNS lookup has a result, or it has reached the time-out. */
FreeRTOS_inet_ntoa( ulIPAddress, pcBuf );
FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) );
if( ulIPAddressFound == 0ul )
{
ulIPAddressFound = ulIPAddress;
}
/* For testing: in case DNS doen't respond, still try some NTP server
with a known IP-address. */
if( ulIPAddressFound == 0ul )
{
ulIPAddressFound = FreeRTOS_inet_addr_quick( 184, 105, 182, 7 );
/* ulIPAddressFound = FreeRTOS_inet_addr_quick( 103, 242, 70, 4 ); */
}
xStatus = EStatusAsking;
vSignalTask();
}
/*-----------------------------------------------------------*/
static void prvSwapFields( struct SNtpPacket *pxPacket)
{
/* NTP messages are big-endian */
pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay );
pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion );
pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds );
pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction );
pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds );
pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction );
pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds );
pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction );
pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds );
pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction );
}
/*-----------------------------------------------------------*/
static void prvNTPPacketInit( )
{
memset (&xNTPPacket, '\0', sizeof( xNTPPacket ) );
xNTPPacket.flags = 0xDB; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */
xNTPPacket.poll = 10; /* 10 means 1 << 10 = 1024 seconds */
xNTPPacket.precision = 0xFA; /* = 250 = 0.015625 seconds */
xNTPPacket.rootDelay = 0x5D2E; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */
xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912 seconds */
/* use the recorded NTP time */
time_t uxSecs = FreeRTOS_time( NULL );/* apTime may be NULL, returns seconds */
xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */
xNTPPacket.transmitTimestamp.seconds = uxSecs + 3;
/* Transform the contents of the fields from native to big endian. */
prvSwapFields( &xNTPPacket );
}
/*-----------------------------------------------------------*/
static void prvReadTime( struct SNtpPacket * pxPacket )
{
FF_TimeStruct_t xTimeStruct;
time_t uxPreviousSeconds;
time_t uxPreviousMS;
time_t uxCurrentSeconds;
time_t uxCurrentMS;
const char *pcTimeUnit;
int32_t ilDiff;
TickType_t uxTravelTime;
uxTravelTime = xTaskGetTickCount() - uxSendTime;
/* Transform the contents of the fields from big to native endian. */
prvSwapFields( pxPacket );
uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970;
uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967;
uxCurrentSeconds += uxCurrentMS / 1000;
uxCurrentMS = uxCurrentMS % 1000;
// Get the last time recorded
uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS );
// Set the new time with precision in msec. */
FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS );
if( uxCurrentSeconds >= uxPreviousSeconds )
{
ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds );
}
else
{
ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds );
}
if( ( ilDiff < -5 ) || ( ilDiff > 5 ) )
{
/* More than 5 seconds difference. */
pcTimeUnit = "sec";
}
else
{
/* Less than or equal to 5 second difference. */
pcTimeUnit = "ms";
uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds;
int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS;
int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS;
ilDiff = iCurMS - iPrevMS;
}
uxCurrentSeconds -= iTimeZone;
FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct );
/*
378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms)
379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms)
*/
FreeRTOS_printf( ("NTP time: %d/%d/%02d %2d:%02d:%02d.%03u Diff %d %s (%lu ms)\n",
xTimeStruct.tm_mday,
xTimeStruct.tm_mon + 1,
xTimeStruct.tm_year + 1900,
xTimeStruct.tm_hour,
xTimeStruct.tm_min,
xTimeStruct.tm_sec,
( unsigned )uxCurrentMS,
( unsigned )ilDiff,
pcTimeUnit,
uxTravelTime ) );
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */
( void ) pcTimeUnit;
( void ) uxTravelTime;
}
/*-----------------------------------------------------------*/
#if( ipconfigUSE_CALLBACKS != 0 )
static BaseType_t xOnUDPReceive( Socket_t xSocket, void * pvData, size_t xLength,
const struct freertos_sockaddr *pxFrom, const struct freertos_sockaddr *pxDest )
{
if( xLength >= sizeof( xNTPPacket ) )
{
prvReadTime( ( struct SNtpPacket *)pvData );
if( xStatus != EStatusPause )
{
xStatus = EStatusPause;
}
}
vSignalTask();
/* Tell the driver not to store the RX data */
return 1;
}
/*-----------------------------------------------------------*/
#endif /* ipconfigUSE_CALLBACKS != 0 */
static void prvNTPTask( void *pvParameters )
{
BaseType_t xServerIndex = 3;
struct freertos_sockaddr xAddress;
#if( ipconfigUSE_CALLBACKS != 0 )
F_TCP_UDP_Handler_t xHandler;
#endif /* ipconfigUSE_CALLBACKS != 0 */
xStatus = EStatusLookup;
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 )
{
xNTPWakeupSem = xSemaphoreCreateBinary();
}
#endif
#if( ipconfigUSE_CALLBACKS != 0 )
{
memset( &xHandler, '\0', sizeof( xHandler ) );
xHandler.pxOnUDPReceive = xOnUDPReceive;
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );
}
#endif
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
{
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) );
}
#endif
for( ; ; )
{
switch( xStatus )
{
case EStatusLookup:
if( ( ulIPAddressFound == 0ul ) || ( ulIPAddressFound == ~0ul ) )
{
if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) )
{
xServerIndex = 0;
}
FreeRTOS_printf( ( "Looking up server '%s'\n", pcTimeServers[ xServerIndex ] ) );
FreeRTOS_gethostbyname_a( pcTimeServers[ xServerIndex ], vDNS_callback, (void *)NULL, 1200 );
}
else
{
xStatus = EStatusAsking;
}
break;
case EStatusAsking:
{
char pcBuf[16];
prvNTPPacketInit( );
xAddress.sin_addr = ulIPAddressFound;
xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
FreeRTOS_inet_ntoa( xAddress.sin_addr, pcBuf );
FreeRTOS_printf( ( "Sending UDP message to %s:%u\n",
pcBuf,
FreeRTOS_ntohs( xAddress.sin_port ) ) );
uxSendTime = xTaskGetTickCount( );
FreeRTOS_sendto( xUDPSocket, ( void * )&xNTPPacket, sizeof( xNTPPacket ), 0, &xAddress, sizeof( xAddress ) );
}
break;
case EStatusPause:
break;
case EStatusFailed:
break;
}
#if( ipconfigUSE_CALLBACKS != 0 )
{
xSemaphoreTake( xNTPWakeupSem, 5000 );
}
#else
{
uint32_t xAddressSize;
BaseType_t xReturned;
xAddressSize = sizeof( xAddress );
xReturned = FreeRTOS_recvfrom( xUDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize );
switch( xReturned )
{
case 0:
case -pdFREERTOS_ERRNO_EAGAIN:
case -pdFREERTOS_ERRNO_EINTR:
break;
default:
if( xReturned < sizeof( xNTPPacket ) )
{
FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) );
}
else
{
prvReadTime( ( struct SNtpPacket *)cRecvBuffer );
if( xStatus != EStatusPause )
{
xStatus = EStatusPause;
}
}
break;
}
}
#endif
}
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,133 @@
/*
* FreeRTOS+TCP V2.0.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
*/
#ifndef __FTPCMD_H__
#define __FTPCMD_H__
#define REPL_110 "110 Restart marker reply.\r\n"
#define REPL_120 "120 Try again in 2 minutes.\r\n"
#define REPL_125 "125 Data connection already open; transfer starting.\r\n"
#define REPL_150 "150 File status okay; about to open data connection.\r\n"
#define REPL_200 "200 NOOP command successful.\r\n"
#define REPL_200_PROGRESS "200 NOOP: data transfer in progress.\r\n"
#define REPL_202 "202 Command not implemented, superfluous at this site.\r\n"
#define REPL_211 "221 System status, or system help reply.\r\n"
#define REPL_211_STATUS "221-status of %s.\r\n"
#define REPL_211_END "221 End of status.\r\n"
#define REPL_212 "212 Directory status.\r\n"
#define REPL_213 "213 File status.\r\n"
#define REPL_214 "214 Help message.\r\n"
#define REPL_214_END "214 End Help message.\r\n"
#define REPL_215 "215 %s system type.\r\n"
#define REPL_220 "220 Service ready for new user.\r\n"
#define REPL_221 "221 Service closing control connection.\r\n"
#define REPL_225 "225 Data connection open; no transfer in progress.\r\n"
#define REPL_226 "226 Closing data connection.\r\n"
#define REPL_227 "227 Entering Passive Mode (%s,%s,%s,%s,%s,%s).\r\n"
#define REPL_227_D "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n"
#define REPL_230 "230 User logged in, proceed.\r\n"
#define REPL_250 "250 Requested file action okay, completed.\r\n"
#define REPL_257 "257 %s created.\r\n"
// #define REPL_257_PWD "257 \"%s\" is current working dir.\r\n"
#define REPL_257_PWD "257 \"%s\"\r\n"
#define REPL_331 "331 Only anonymous user is accepted.\r\n"
#define REPL_331_ANON "331 Anonymous login okay\r\n"
#define REPL_332 "332 Need account for login.\r\n"
#define REPL_350 "350 Requested file action pending further information.\r\n"
#define REPL_421 "421 Service not available, closing control connection.\r\n"
#define REPL_425 "425 Can't open data connection.\r\n"
#define REPL_426 "426 Connection closed; transfer aborted.\r\n"
#define REPL_450 "450 Requested file action not taken.\r\n"
#define REPL_451 "451 Requested action aborted. Local error in processing.\r\n"
#define REPL_452 "452 Requested action not taken.\r\n"
#define REPL_500 "500 Syntax error, command unrecognized.\r\n"
#define REPL_501 "501 Syntax error in parameters or arguments.\r\n"
#define REPL_502 "502 Command not implemented.\r\n"
#define REPL_503 "503 Bad sequence of commands.\r\n"
#define REPL_504 "504 Command not implemented for that parameter.\r\n"
#define REPL_530 "530 Not logged in.\r\n"
#define REPL_532 "532 Need account for storing files.\r\n"
#define REPL_550 "550 Requested action not taken.\r\n"
#define REPL_551 "551 Requested action aborted. Page type unknown.\r\n"
#define REPL_552 "552 Requested file action aborted.\r\n"
#define REPL_553 "553 Requested action not taken.\r\n"
#define REPL_553_READ_ONLY "553 Read-only file-system.\r\n"
enum EFTPCommand {
ECMD_USER,
ECMD_PASS,
ECMD_ACCT,
ECMD_CWD,
ECMD_CDUP,
ECMD_SMNT,
ECMD_QUIT,
ECMD_REIN,
ECMD_PORT,
ECMD_PASV,
ECMD_TYPE,
ECMD_STRU,
ECMD_MODE,
ECMD_RETR,
ECMD_STOR,
ECMD_STOU,
ECMD_APPE,
ECMD_ALLO,
ECMD_REST,
ECMD_RNFR,
ECMD_RNTO,
ECMD_ABOR,
ECMD_SIZE,
ECMD_MDTM,
ECMD_DELE,
ECMD_RMD,
ECMD_MKD,
ECMD_PWD,
ECMD_LIST,
ECMD_NLST,
ECMD_SITE,
ECMD_SYST,
ECMD_FEAT,
ECMD_STAT,
ECMD_HELP,
ECMD_NOOP,
ECMD_EMPTY,
ECMD_CLOSE,
ECMD_UNKNOWN,
};
typedef struct xFTP_COMMAND {
BaseType_t xCommandLength;
const char pcCommandName[7];
const unsigned char ucCommandType;
const unsigned char checkLogin;
const unsigned char checkNullArg;
} FTPCommand_t;
#define FTP_CMD_COUNT (ECMD_UNKNOWN+1)
extern const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ];
#endif // __FTPCMD_H__

View File

@ -0,0 +1,67 @@
/*
* FreeRTOS+TCP V2.0.3
* 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
*/
#ifndef FREERTOS_HTTP_COMMANDS_H
#define FREERTOS_HTTP_COMMANDS_H
enum {
WEB_REPLY_OK = 200,
WEB_NO_CONTENT = 204,
WEB_BAD_REQUEST = 400,
WEB_UNAUTHORIZED = 401,
WEB_NOT_FOUND = 404,
WEB_GONE = 410,
WEB_PRECONDITION_FAILED = 412,
WEB_INTERNAL_SERVER_ERROR = 500,
};
enum EWebCommand {
ECMD_GET,
ECMD_HEAD,
ECMD_POST,
ECMD_PUT,
ECMD_DELETE,
ECMD_TRACE,
ECMD_OPTIONS,
ECMD_CONNECT,
ECMD_PATCH,
ECMD_UNK,
};
struct xWEB_COMMAND
{
BaseType_t xCommandLength;
const char *pcCommandName;
const unsigned char ucCommandType;
};
#define WEB_CMD_COUNT (ECMD_UNK+1)
extern const struct xWEB_COMMAND xWebCommands[WEB_CMD_COUNT];
extern const char *webCodename (int aCode);
#endif /* FREERTOS_HTTP_COMMANDS_H */

View File

@ -0,0 +1,125 @@
/*
* FreeRTOS+TCP V2.0.3
* 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
*/
/*
Some code which is common to TCP servers like HTTP en FTP
*/
#ifndef FREERTOS_TCP_SERVER_H
#define FREERTOS_TCP_SERVER_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef FTP_SERVER_USES_RELATIVE_DIRECTORY
#define FTP_SERVER_USES_RELATIVE_DIRECTORY 0
#endif
enum eSERVER_TYPE
{
eSERVER_NONE,
eSERVER_HTTP,
eSERVER_FTP,
};
struct xFTP_CLIENT;
#if( ipconfigFTP_HAS_RECEIVED_HOOK != 0 )
extern void vApplicationFTPReceivedHook( const char *pcFileName, uint32_t ulSize, struct xFTP_CLIENT *pxFTPClient );
extern void vFTPReplyMessage( struct xFTP_CLIENT *pxFTPClient, const char *pcMessage );
#endif /* ipconfigFTP_HAS_RECEIVED_HOOK != 0 */
#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )
/*
* Function is called when a user name has been submitted.
* The function may return a string such as: "331 Please enter your password"
* or return NULL to use the default reply.
*/
extern const char *pcApplicationFTPUserHook( const char *pcUserName );
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )
/*
* Function is called when a password was received.
* Return positive value to allow the user
*/
extern BaseType_t xApplicationFTPPasswordHook( const char *pcUserName, const char *pcPassword );
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
#if( ipconfigFTP_HAS_USER_PROPERTIES_HOOK != 0 )
/*
* The FTP server is asking for user-specific properties
*/
typedef struct
{
uint16_t usPortNumber; /* For reference only. Host-endian. */
const char *pcRootDir;
BaseType_t xReadOnly;
}
FTPUserProperties_t;
extern void vApplicationFTPUserPropertiesHook( const char *pcUserName, FTPUserProperties_t *pxProperties );
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
#if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )
/*
* A GET request is received containing a special character,
* usually a question mark.
* const char *pcURLData; // A request, e.g. "/request?limit=75"
* char *pcBuffer; // Here the answer can be written
* size_t uxBufferLength; // Size of the buffer
*
*/
extern size_t uxApplicationHTTPHandleRequestHook( const char *pcURLData, char *pcBuffer, size_t uxBufferLength );
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
struct xSERVER_CONFIG
{
enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */
BaseType_t xPortNumber; /* e.g. 80, 8080, 21 */
BaseType_t xBackLog; /* e.g. 10, maximum number of connected TCP clients */
const char * const pcRootDir; /* Treat this directory as the root directory */
};
struct xTCP_SERVER;
typedef struct xTCP_SERVER TCPServer_t;
TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount );
void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime );
#if( ipconfigSUPPORT_SIGNALS != 0 )
/* FreeRTOS_TCPServerWork() calls select().
The two functions below provide a possibility to interrupt
the call to select(). After the interruption, resume
by calling FreeRTOS_TCPServerWork() again. */
BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer );
BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken );
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_TCP_SERVER_H */

View File

@ -0,0 +1,185 @@
/*
* FreeRTOS+TCP V2.0.3
* 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
*/
/*
Some code which is common to TCP servers like HTTP and FTP
*/
#ifndef FREERTOS_SERVER_PRIVATE_H
#define FREERTOS_SERVER_PRIVATE_H
#define FREERTOS_NO_SOCKET NULL
/* FreeRTOS+FAT */
#include "ff_stdio.h"
/* Each HTTP server has 1, at most 2 sockets */
#define HTTP_SOCKET_COUNT 2
/*
* ipconfigTCP_COMMAND_BUFFER_SIZE sets the size of:
* pcCommandBuffer': a buffer to receive and send TCP commands
*
* ipconfigTCP_FILE_BUFFER_SIZE sets the size of:
* pcFileBuffer' : a buffer to access the file system: read or write data.
*
* The buffers are both used for FTP as well as HTTP.
*/
#ifndef ipconfigTCP_COMMAND_BUFFER_SIZE
#define ipconfigTCP_COMMAND_BUFFER_SIZE ( 2048 )
#endif
#ifndef ipconfigTCP_FILE_BUFFER_SIZE
#define ipconfigTCP_FILE_BUFFER_SIZE ( 2048 )
#endif
struct xTCP_CLIENT;
typedef BaseType_t ( * FTCPWorkFunction ) ( struct xTCP_CLIENT * /* pxClient */ );
typedef void ( * FTCPDeleteFunction ) ( struct xTCP_CLIENT * /* pxClient */ );
#define TCP_CLIENT_FIELDS \
enum eSERVER_TYPE eType; \
struct xTCP_SERVER *pxParent; \
Socket_t xSocket; \
const char *pcRootDir; \
FTCPWorkFunction fWorkFunction; \
FTCPDeleteFunction fDeleteFunction; \
struct xTCP_CLIENT *pxNextClient
typedef struct xTCP_CLIENT
{
/* This define contains fields which must come first within each of the client structs */
TCP_CLIENT_FIELDS;
/* --- Keep at the top --- */
} TCPClient_t;
struct xHTTP_CLIENT
{
/* This define contains fields which must come first within each of the client structs */
TCP_CLIENT_FIELDS;
/* --- Keep at the top --- */
const char *pcUrlData;
const char *pcRestData;
char pcCurrentFilename[ ffconfigMAX_FILENAME ];
size_t uxBytesLeft;
FF_FILE *pxFileHandle;
union {
struct {
uint32_t
bReplySent : 1;
};
uint32_t ulFlags;
} bits;
};
typedef struct xHTTP_CLIENT HTTPClient_t;
struct xFTP_CLIENT
{
/* This define contains fields which must come first within each of the client structs */
TCP_CLIENT_FIELDS;
/* --- Keep at the top --- */
uint32_t ulRestartOffset;
uint32_t ulRecvBytes;
size_t uxBytesLeft; /* Bytes left to send */
uint32_t ulClientIP;
TickType_t xStartTime;
uint16_t usClientPort;
Socket_t xTransferSocket;
BaseType_t xTransType;
BaseType_t xDirCount;
FF_FindData_t xFindData;
FF_FILE *pxReadHandle;
FF_FILE *pxWriteHandle;
char pcCurrentDir[ ffconfigMAX_FILENAME ];
char pcFileName[ ffconfigMAX_FILENAME ];
char pcConnectionAck[ 128 ];
char pcClientAck[ 128 ];
union {
struct {
uint32_t
bHelloSent : 1,
bLoggedIn : 1,
bStatusUser : 1,
bInRename : 1,
bReadOnly : 1;
};
uint32_t ulFTPFlags;
} bits;
union {
struct {
uint32_t
bIsListen : 1, /* pdTRUE for passive data connections (using list()). */
bDirHasEntry : 1, /* pdTRUE if ff_findfirst() was successful. */
bClientConnected : 1, /* pdTRUE after connect() or accept() has succeeded. */
bEmptyFile : 1, /* pdTRUE if a connection-without-data was received. */
bHadError : 1; /* pdTRUE if a transfer got aborted because of an error. */
};
uint32_t ulConnFlags;
} bits1;
};
typedef struct xFTP_CLIENT FTPClient_t;
BaseType_t xHTTPClientWork( TCPClient_t *pxClient );
BaseType_t xFTPClientWork( TCPClient_t *pxClient );
void vHTTPClientDelete( TCPClient_t *pxClient );
void vFTPClientDelete( TCPClient_t *pxClient );
BaseType_t xMakeAbsolute( struct xFTP_CLIENT *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName );
BaseType_t xMakeRelative( FTPClient_t *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName );
struct xTCP_SERVER
{
SocketSet_t xSocketSet;
/* A buffer to receive and send TCP commands, either HTTP of FTP. */
char pcCommandBuffer[ ipconfigTCP_COMMAND_BUFFER_SIZE ];
/* A buffer to access the file system: read or write data. */
char pcFileBuffer[ ipconfigTCP_FILE_BUFFER_SIZE ];
#if( ipconfigUSE_FTP != 0 )
char pcNewDir[ ffconfigMAX_FILENAME ];
#endif
#if( ipconfigUSE_HTTP != 0 )
char pcContentsType[40]; /* Space for the msg: "text/javascript" */
char pcExtraContents[40]; /* Space for the msg: "Content-Length: 346500" */
#endif
BaseType_t xServerCount;
TCPClient_t *pxClients;
struct xSERVER
{
enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */
const char *pcRootDir;
Socket_t xSocket;
} xServers[ 1 ];
};
#endif /* FREERTOS_SERVER_PRIVATE_H */

View File

@ -0,0 +1,71 @@
//
// ntpClient.h
//
#ifndef __NTPCLIENT_H__
#define __NTPCLIENT_H__
#define NTP_PORT 123
typedef uint32_t quint32;
typedef int32_t qint32;
typedef uint8_t quint8;
typedef int8_t qint8;
typedef union _SNtpFlags SNtpFlags;
/**
* 64-bit NTP timestamp.
*/
struct __attribute__ ((__packed__)) _SNtpTimestamp {
/** Number of seconds passed since Jan 1 1900, in big-endian format. */
quint32 seconds;
/** Fractional time part, in <tt>1/0xFFFFFFFF</tt>s of a second. */
quint32 fraction;
};
typedef struct _SNtpTimestamp SNtpTimestamp;
/**
* Mandatory part of an NTP packet
*/
struct SNtpPacket {
/** Flags. */
unsigned char flags; // value 0xDB : mode 3 (client), version 3, leap indicator unknown 3
/** Stratum of the clock. */
quint8 stratum; // value 0 : unspecified
/** Maximum interval between successive messages, in log2 seconds. Note that the value is signed. */
qint8 poll; // 10 means 1 << 10 = 1024 seconds
/** Precision of the clock, in log2 seconds. Note that the value is signed. */
qint8 precision; // 0xFA = 250 = 0.015625 seconds
/** Round trip time to the primary reference source, in NTP short format. */
qint32 rootDelay; // 0x5D2E = 23854 or (23854/65535)= 0.3640 sec
/** Nominal error relative to the primary reference source. */
qint32 rootDispersion; // 0x0008 CAC8 = 8.7912 seconds
/** Reference identifier (either a 4 character string or an IP address). */
qint8 referenceID[4]; // or just 0000
/** The time at which the clock was last set or corrected. */
SNtpTimestamp referenceTimestamp; // Current time
/** The time at which the request departed the client for the server. */
SNtpTimestamp originateTimestamp; // Keep 0
/** The time at which the request arrived at the server. */
SNtpTimestamp receiveTimestamp; // Keep 0
/** The time at which the reply departed the server for client. */
SNtpTimestamp transmitTimestamp;
};
/* Add this number to get secs since 1-1-1900 */
#define TIME1970 2208988800UL
#endif // __NTPCLIENT_H__

View File

@ -0,0 +1,11 @@
/*
* A simple demo for NTP using FreeRTOS+TCP
*/
#ifndef NTPDEMO_H
#define NTPDEMO_H
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority );
#endif

View File

@ -0,0 +1,530 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* FreeRTOS+CLI includes. */
#include "FreeRTOS_CLI.h"
/* File system includes. */
#include "fat_sl.h"
#include "api_mdriver_ram.h"
#ifdef _WINDOWS_
#define snprintf _snprintf
#endif
#define cliNEW_LINE "\r\n"
/*******************************************************************************
* See the URL in the comments within main.c for the location of the online
* documentation.
******************************************************************************/
/*
* Print out information on a single file.
*/
static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct );
/*
* Copies an existing file into a newly created file.
*/
static BaseType_t prvPerformCopy( const char *pcSourceFile,
int32_t lSourceFileLength,
const char *pcDestinationFile,
char *pxWriteBuffer,
size_t xWriteBufferLen );
/*
* Implements the DIR command.
*/
static BaseType_t prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the CD command.
*/
static BaseType_t prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the DEL command.
*/
static BaseType_t prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the TYPE command.
*/
static BaseType_t prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the COPY command.
*/
static BaseType_t prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/* Structure that defines the DIR command line command, which lists all the
files in the current directory. */
static const CLI_Command_Definition_t xDIR =
{
"dir", /* The command string to type. */
"\r\ndir:\r\n Lists the files in the current directory\r\n",
prvDIRCommand, /* The function to run. */
0 /* No parameters are expected. */
};
/* Structure that defines the CD command line command, which changes the
working directory. */
static const CLI_Command_Definition_t xCD =
{
"cd", /* The command string to type. */
"\r\ncd <dir name>:\r\n Changes the working directory\r\n",
prvCDCommand, /* The function to run. */
1 /* One parameter is expected. */
};
/* Structure that defines the TYPE command line command, which prints the
contents of a file to the console. */
static const CLI_Command_Definition_t xTYPE =
{
"type", /* The command string to type. */
"\r\ntype <filename>:\r\n Prints file contents to the terminal\r\n",
prvTYPECommand, /* The function to run. */
1 /* One parameter is expected. */
};
/* Structure that defines the DEL command line command, which deletes a file. */
static const CLI_Command_Definition_t xDEL =
{
"del", /* The command string to type. */
"\r\ndel <filename>:\r\n deletes a file or directory\r\n",
prvDELCommand, /* The function to run. */
1 /* One parameter is expected. */
};
/* Structure that defines the COPY command line command, which deletes a file. */
static const CLI_Command_Definition_t xCOPY =
{
"copy", /* The command string to type. */
"\r\ncopy <source file> <dest file>:\r\n Copies <source file> to <dest file>\r\n",
prvCOPYCommand, /* The function to run. */
2 /* Two parameters are expected. */
};
/*-----------------------------------------------------------*/
void vRegisterFileSystemCLICommands( void )
{
/* Register all the command line commands defined immediately above. */
FreeRTOS_CLIRegisterCommand( &xDIR );
FreeRTOS_CLIRegisterCommand( &xCD );
FreeRTOS_CLIRegisterCommand( &xTYPE );
FreeRTOS_CLIRegisterCommand( &xDEL );
FreeRTOS_CLIRegisterCommand( &xCOPY );
}
/*-----------------------------------------------------------*/
static BaseType_t prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t xParameterStringLength, xReturn = pdTRUE;
static F_FILE *pxFile = NULL;
int iChar;
size_t xByte;
size_t xColumns = 50U;
/* Ensure there is always a null terminator after each character written. */
memset( pcWriteBuffer, 0x00, xWriteBufferLen );
/* Ensure the buffer leaves space for the \r\n. */
configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
xWriteBufferLen -= strlen( cliNEW_LINE );
if( xWriteBufferLen < xColumns )
{
/* Ensure the loop that uses xColumns as an end condition does not
write off the end of the buffer. */
xColumns = xWriteBufferLen;
}
if( pxFile == NULL )
{
/* The file has not been opened yet. Find the file name. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcParameter );
/* Attempt to open the requested file. */
pxFile = f_open( pcParameter, "r" );
}
if( pxFile != NULL )
{
/* Read the next chunk of data from the file. */
for( xByte = 0; xByte < xColumns; xByte++ )
{
iChar = f_getc( pxFile );
if( iChar == -1 )
{
/* No more characters to return. */
f_close( pxFile );
pxFile = NULL;
break;
}
else
{
pcWriteBuffer[ xByte ] = ( char ) iChar;
}
}
}
if( pxFile == NULL )
{
/* Either the file was not opened, or all the data from the file has
been returned and the file is now closed. */
xReturn = pdFALSE;
}
strcat( pcWriteBuffer, cliNEW_LINE );
return xReturn;
}
/*-----------------------------------------------------------*/
static BaseType_t prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t xParameterStringLength;
unsigned char ucReturned;
size_t xStringLength;
/* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcParameter );
/* Attempt to move to the requested directory. */
ucReturned = f_chdir( pcParameter );
if( ucReturned == F_NO_ERROR )
{
sprintf( pcWriteBuffer, "In: " );
xStringLength = strlen( pcWriteBuffer );
f_getcwd( &( pcWriteBuffer[ xStringLength ] ), ( unsigned char ) ( xWriteBufferLen - xStringLength ) );
}
else
{
sprintf( pcWriteBuffer, "Error" );
}
strcat( pcWriteBuffer, cliNEW_LINE );
return pdFALSE;
}
/*-----------------------------------------------------------*/
static BaseType_t prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
static F_FIND *pxFindStruct = NULL;
unsigned char ucReturned;
BaseType_t xReturn = pdFALSE;
/* This assumes pcWriteBuffer is long enough. */
( void ) pcCommandString;
/* Ensure the buffer leaves space for the \r\n. */
configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
xWriteBufferLen -= strlen( cliNEW_LINE );
if( pxFindStruct == NULL )
{
/* This is the first time this function has been executed since the Dir
command was run. Create the find structure. */
pxFindStruct = ( F_FIND * ) pvPortMalloc( sizeof( F_FIND ) );
if( pxFindStruct != NULL )
{
ucReturned = f_findfirst( "*.*", pxFindStruct );
if( ucReturned == F_NO_ERROR )
{
prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
xReturn = pdPASS;
}
else
{
snprintf( pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." );
}
}
else
{
snprintf( pcWriteBuffer, xWriteBufferLen, "Failed to allocate RAM (using heap_4.c will prevent fragmentation)." );
}
}
else
{
/* The find struct has already been created. Find the next file in
the directory. */
ucReturned = f_findnext( pxFindStruct );
if( ucReturned == F_NO_ERROR )
{
prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
xReturn = pdPASS;
}
else
{
/* There are no more files. Free the find structure. */
vPortFree( pxFindStruct );
pxFindStruct = NULL;
/* No string to return. */
pcWriteBuffer[ 0 ] = 0x00;
}
}
strcat( pcWriteBuffer, cliNEW_LINE );
return xReturn;
}
/*-----------------------------------------------------------*/
static BaseType_t prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t xParameterStringLength;
unsigned char ucReturned;
/* This function assumes xWriteBufferLen is large enough! */
( void ) xWriteBufferLen;
/* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcParameter );
/* Attempt to delete the file. */
ucReturned = f_delete( pcParameter );
if( ucReturned == F_NO_ERROR )
{
sprintf( pcWriteBuffer, "%s was deleted", pcParameter );
}
else
{
sprintf( pcWriteBuffer, "Error" );
}
strcat( pcWriteBuffer, cliNEW_LINE );
return pdFALSE;
}
/*-----------------------------------------------------------*/
static BaseType_t prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
char *pcSourceFile, *pcDestinationFile;
BaseType_t xParameterStringLength;
long lSourceLength, lDestinationLength = 0;
/* Obtain the name of the destination file. */
pcDestinationFile = ( char * ) FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
2, /* Return the second parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcDestinationFile );
/* Obtain the name of the source file. */
pcSourceFile = ( char * ) FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcSourceFile );
/* Terminate the string. */
pcSourceFile[ xParameterStringLength ] = 0x00;
/* See if the source file exists, obtain its length if it does. */
lSourceLength = f_filelength( pcSourceFile );
if( lSourceLength == 0 )
{
sprintf( pcWriteBuffer, "Source file does not exist" );
}
else
{
/* See if the destination file exists. */
lDestinationLength = f_filelength( pcDestinationFile );
if( lDestinationLength != 0 )
{
sprintf( pcWriteBuffer, "Error: Destination file already exists" );
}
}
/* Continue only if the source file exists and the destination file does
not exist. */
if( ( lSourceLength != 0 ) && ( lDestinationLength == 0 ) )
{
if( prvPerformCopy( pcSourceFile, lSourceLength, pcDestinationFile, pcWriteBuffer, xWriteBufferLen ) == pdPASS )
{
sprintf( pcWriteBuffer, "Copy made" );
}
else
{
sprintf( pcWriteBuffer, "Error during copy" );
}
}
strcat( pcWriteBuffer, cliNEW_LINE );
return pdFALSE;
}
/*-----------------------------------------------------------*/
static BaseType_t prvPerformCopy( const char *pcSourceFile,
int32_t lSourceFileLength,
const char *pcDestinationFile,
char *pxWriteBuffer,
size_t xWriteBufferLen )
{
int32_t lBytesRead = 0, lBytesToRead, lBytesRemaining;
F_FILE *pxFile;
BaseType_t xReturn = pdPASS;
/* NOTE: Error handling has been omitted for clarity. */
while( lBytesRead < lSourceFileLength )
{
/* How many bytes are left? */
lBytesRemaining = lSourceFileLength - lBytesRead;
/* How many bytes should be read this time around the loop. Can't
read more bytes than will fit into the buffer. */
if( lBytesRemaining > ( long ) xWriteBufferLen )
{
lBytesToRead = ( long ) xWriteBufferLen;
}
else
{
lBytesToRead = lBytesRemaining;
}
/* Open the source file, seek past the data that has already been
read from the file, read the next block of data, then close the
file again so the destination file can be opened. */
pxFile = f_open( pcSourceFile, "r" );
if( pxFile != NULL )
{
f_seek( pxFile, lBytesRead, F_SEEK_SET );
f_read( pxWriteBuffer, lBytesToRead, 1, pxFile );
f_close( pxFile );
}
else
{
xReturn = pdFAIL;
break;
}
/* Open the destination file and write the block of data to the end of
the file. */
pxFile = f_open( pcDestinationFile, "a" );
if( pxFile != NULL )
{
f_write( pxWriteBuffer, lBytesToRead, 1, pxFile );
f_close( pxFile );
}
else
{
xReturn = pdFAIL;
break;
}
lBytesRead += lBytesToRead;
}
return xReturn;
}
/*-----------------------------------------------------------*/
static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct )
{
const char *pcWritableFile = "writable file", *pcReadOnlyFile = "read only file", *pcDirectory = "directory";
const char * pcAttrib;
/* Point pcAttrib to a string that describes the file. */
if( ( pxFindStruct->attr & F_ATTR_DIR ) != 0 )
{
pcAttrib = pcDirectory;
}
else if( pxFindStruct->attr & F_ATTR_READONLY )
{
pcAttrib = pcReadOnlyFile;
}
else
{
pcAttrib = pcWritableFile;
}
/* Create a string that includes the file name, the file size and the
attributes string. */
sprintf( pcBuffer, "%s [%s] [size=%d]", pxFindStruct->filename, pcAttrib, ( int ) pxFindStruct->filesize );
}

View File

@ -0,0 +1,480 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/******************************************************************************
*
* http://www.FreeRTOS.org/cli
*
******************************************************************************/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* FreeRTOS+CLI includes. */
#include "FreeRTOS_CLI.h"
#ifndef configINCLUDE_TRACE_RELATED_CLI_COMMANDS
#define configINCLUDE_TRACE_RELATED_CLI_COMMANDS 0
#endif
#ifndef configINCLUDE_QUERY_HEAP_COMMAND
#define configINCLUDE_QUERY_HEAP_COMMAND 0
#endif
/*
* The function that registers the commands that are defined within this file.
*/
void vRegisterSampleCLICommands( void );
/*
* Implements the task-stats command.
*/
static BaseType_t prvTaskStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the run-time-stats command.
*/
#if( configGENERATE_RUN_TIME_STATS == 1 )
static BaseType_t prvRunTimeStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
#endif /* configGENERATE_RUN_TIME_STATS */
/*
* Implements the echo-three-parameters command.
*/
static BaseType_t prvThreeParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the echo-parameters command.
*/
static BaseType_t prvParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the "query heap" command.
*/
#if( configINCLUDE_QUERY_HEAP_COMMAND == 1 )
static BaseType_t prvQueryHeapCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
#endif
/*
* Implements the "trace start" and "trace stop" commands;
*/
#if( configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 )
static BaseType_t prvStartStopTraceCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
#endif
/* Structure that defines the "task-stats" command line command. This generates
a table that gives information on each task in the system. */
static const CLI_Command_Definition_t xTaskStats =
{
"task-stats", /* The command string to type. */
"\r\ntask-stats:\r\n Displays a table showing the state of each FreeRTOS task\r\n",
prvTaskStatsCommand, /* The function to run. */
0 /* No parameters are expected. */
};
/* Structure that defines the "echo_3_parameters" command line command. This
takes exactly three parameters that the command simply echos back one at a
time. */
static const CLI_Command_Definition_t xThreeParameterEcho =
{
"echo-3-parameters",
"\r\necho-3-parameters <param1> <param2> <param3>:\r\n Expects three parameters, echos each in turn\r\n",
prvThreeParameterEchoCommand, /* The function to run. */
3 /* Three parameters are expected, which can take any value. */
};
/* Structure that defines the "echo_parameters" command line command. This
takes a variable number of parameters that the command simply echos back one at
a time. */
static const CLI_Command_Definition_t xParameterEcho =
{
"echo-parameters",
"\r\necho-parameters <...>:\r\n Take variable number of parameters, echos each in turn\r\n",
prvParameterEchoCommand, /* The function to run. */
-1 /* The user can enter any number of commands. */
};
#if( configGENERATE_RUN_TIME_STATS == 1 )
/* Structure that defines the "run-time-stats" command line command. This
generates a table that shows how much run time each task has */
static const CLI_Command_Definition_t xRunTimeStats =
{
"run-time-stats", /* The command string to type. */
"\r\nrun-time-stats:\r\n Displays a table showing how much processing time each FreeRTOS task has used\r\n",
prvRunTimeStatsCommand, /* The function to run. */
0 /* No parameters are expected. */
};
#endif /* configGENERATE_RUN_TIME_STATS */
#if( configINCLUDE_QUERY_HEAP_COMMAND == 1 )
/* Structure that defines the "query_heap" command line command. */
static const CLI_Command_Definition_t xQueryHeap =
{
"query-heap",
"\r\nquery-heap:\r\n Displays the free heap space, and minimum ever free heap space.\r\n",
prvQueryHeapCommand, /* The function to run. */
0 /* The user can enter any number of commands. */
};
#endif /* configQUERY_HEAP_COMMAND */
#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1
/* Structure that defines the "trace" command line command. This takes a single
parameter, which can be either "start" or "stop". */
static const CLI_Command_Definition_t xStartStopTrace =
{
"trace",
"\r\ntrace [start | stop]:\r\n Starts or stops a trace recording for viewing in FreeRTOS+Trace\r\n",
prvStartStopTraceCommand, /* The function to run. */
1 /* One parameter is expected. Valid values are "start" and "stop". */
};
#endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */
/*-----------------------------------------------------------*/
void vRegisterSampleCLICommands( void )
{
/* Register all the command line commands defined immediately above. */
FreeRTOS_CLIRegisterCommand( &xTaskStats );
FreeRTOS_CLIRegisterCommand( &xThreeParameterEcho );
FreeRTOS_CLIRegisterCommand( &xParameterEcho );
#if( configGENERATE_RUN_TIME_STATS == 1 )
{
FreeRTOS_CLIRegisterCommand( &xRunTimeStats );
}
#endif
#if( configINCLUDE_QUERY_HEAP_COMMAND == 1 )
{
FreeRTOS_CLIRegisterCommand( &xQueryHeap );
}
#endif
#if( configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 )
{
FreeRTOS_CLIRegisterCommand( &xStartStopTrace );
}
#endif
}
/*-----------------------------------------------------------*/
static BaseType_t prvTaskStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *const pcHeader = " State Priority Stack #\r\n************************************************\r\n";
BaseType_t xSpacePadding;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
/* Generate a table of task stats. */
strcpy( pcWriteBuffer, "Task" );
pcWriteBuffer += strlen( pcWriteBuffer );
/* Minus three for the null terminator and half the number of characters in
"Task" so the column lines up with the centre of the heading. */
configASSERT( configMAX_TASK_NAME_LEN > 3 );
for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ )
{
/* Add a space to align columns after the task's name. */
*pcWriteBuffer = ' ';
pcWriteBuffer++;
/* Ensure always terminated. */
*pcWriteBuffer = 0x00;
}
strcpy( pcWriteBuffer, pcHeader );
vTaskList( pcWriteBuffer + strlen( pcHeader ) );
/* There is no more data to return after this single string, so return
pdFALSE. */
return pdFALSE;
}
/*-----------------------------------------------------------*/
#if( configINCLUDE_QUERY_HEAP_COMMAND == 1 )
static BaseType_t prvQueryHeapCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
sprintf( pcWriteBuffer, "Current free heap %d bytes, minimum ever free heap %d bytes\r\n", ( int ) xPortGetFreeHeapSize(), ( int ) xPortGetMinimumEverFreeHeapSize() );
/* There is no more data to return after this single string, so return
pdFALSE. */
return pdFALSE;
}
#endif /* configINCLUDE_QUERY_HEAP */
/*-----------------------------------------------------------*/
#if( configGENERATE_RUN_TIME_STATS == 1 )
static BaseType_t prvRunTimeStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char * const pcHeader = " Abs Time % Time\r\n****************************************\r\n";
BaseType_t xSpacePadding;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
/* Generate a table of task stats. */
strcpy( pcWriteBuffer, "Task" );
pcWriteBuffer += strlen( pcWriteBuffer );
/* Pad the string "task" with however many bytes necessary to make it the
length of a task name. Minus three for the null terminator and half the
number of characters in "Task" so the column lines up with the centre of
the heading. */
for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ )
{
/* Add a space to align columns after the task's name. */
*pcWriteBuffer = ' ';
pcWriteBuffer++;
/* Ensure always terminated. */
*pcWriteBuffer = 0x00;
}
strcpy( pcWriteBuffer, pcHeader );
vTaskGetRunTimeStats( pcWriteBuffer + strlen( pcHeader ) );
/* There is no more data to return after this single string, so return
pdFALSE. */
return pdFALSE;
}
#endif /* configGENERATE_RUN_TIME_STATS */
/*-----------------------------------------------------------*/
static BaseType_t prvThreeParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t xParameterStringLength, xReturn;
static UBaseType_t uxParameterNumber = 0;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
if( uxParameterNumber == 0 )
{
/* The first time the function is called after the command has been
entered just a header string is returned. */
sprintf( pcWriteBuffer, "The three parameters were:\r\n" );
/* Next time the function is called the first parameter will be echoed
back. */
uxParameterNumber = 1U;
/* There is more data to be returned as no parameters have been echoed
back yet. */
xReturn = pdPASS;
}
else
{
/* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
uxParameterNumber, /* Return the next parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcParameter );
/* Return the parameter string. */
memset( pcWriteBuffer, 0x00, xWriteBufferLen );
sprintf( pcWriteBuffer, "%d: ", ( int ) uxParameterNumber );
strncat( pcWriteBuffer, pcParameter, ( size_t ) xParameterStringLength );
strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) );
/* If this is the last of the three parameters then there are no more
strings to return after this one. */
if( uxParameterNumber == 3U )
{
/* If this is the last of the three parameters then there are no more
strings to return after this one. */
xReturn = pdFALSE;
uxParameterNumber = 0;
}
else
{
/* There are more parameters to return after this one. */
xReturn = pdTRUE;
uxParameterNumber++;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
static BaseType_t prvParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t xParameterStringLength, xReturn;
static UBaseType_t uxParameterNumber = 0;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
if( uxParameterNumber == 0 )
{
/* The first time the function is called after the command has been
entered just a header string is returned. */
sprintf( pcWriteBuffer, "The parameters were:\r\n" );
/* Next time the function is called the first parameter will be echoed
back. */
uxParameterNumber = 1U;
/* There is more data to be returned as no parameters have been echoed
back yet. */
xReturn = pdPASS;
}
else
{
/* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
uxParameterNumber, /* Return the next parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
if( pcParameter != NULL )
{
/* Return the parameter string. */
memset( pcWriteBuffer, 0x00, xWriteBufferLen );
sprintf( pcWriteBuffer, "%d: ", ( int ) uxParameterNumber );
strncat( pcWriteBuffer, ( char * ) pcParameter, ( size_t ) xParameterStringLength );
strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) );
/* There might be more parameters to return after this one. */
xReturn = pdTRUE;
uxParameterNumber++;
}
else
{
/* No more parameters were found. Make sure the write buffer does
not contain a valid string. */
pcWriteBuffer[ 0 ] = 0x00;
/* No more data to return. */
xReturn = pdFALSE;
/* Start over the next time this command is executed. */
uxParameterNumber = 0;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1
static BaseType_t prvStartStopTraceCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t lParameterStringLength;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
/* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */
&lParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcParameter );
/* There are only two valid parameter values. */
if( strncmp( pcParameter, "start", strlen( "start" ) ) == 0 )
{
/* Start or restart the trace. */
vTraceStop();
vTraceClear();
vTraceStart();
sprintf( pcWriteBuffer, "Trace recording (re)started.\r\n" );
}
else if( strncmp( pcParameter, "stop", strlen( "stop" ) ) == 0 )
{
/* End the trace, if one is running. */
vTraceStop();
sprintf( pcWriteBuffer, "Stopping trace recording.\r\n" );
}
else
{
sprintf( pcWriteBuffer, "Valid parameters are 'start' and 'stop'.\r\n" );
}
/* There is no more data to return after this single string, so return
pdFALSE. */
return pdFALSE;
}
#endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */

View File

@ -0,0 +1,226 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*
* NOTE: This file uses a third party USB CDC driver.
*/
/* Standard includes. */
#include "string.h"
#include "stdio.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* Example includes. */
#include "FreeRTOS_CLI.h"
/* Demo application includes. */
#include "serial.h"
/* Dimensions the buffer into which input characters are placed. */
#define cmdMAX_INPUT_SIZE 50
/* Dimentions a buffer to be used by the UART driver, if the UART driver uses a
buffer at all. */
#define cmdQUEUE_LENGTH 25
/* DEL acts as a backspace. */
#define cmdASCII_DEL ( 0x7F )
/* The maximum time to wait for the mutex that guards the UART to become
available. */
#define cmdMAX_MUTEX_WAIT pdMS_TO_TICKS( 300 )
#ifndef configCLI_BAUD_RATE
#define configCLI_BAUD_RATE 115200
#endif
/*-----------------------------------------------------------*/
/*
* The task that implements the command console processing.
*/
static void prvUARTCommandConsoleTask( void *pvParameters );
void vUARTCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority );
/*-----------------------------------------------------------*/
/* Const messages output by the command console. */
static const char * const pcWelcomeMessage = "FreeRTOS command server.\r\nType Help to view a list of registered commands.\r\n\r\n>";
static const char * const pcEndOfOutputMessage = "\r\n[Press ENTER to execute the previous command again]\r\n>";
static const char * const pcNewLine = "\r\n";
/* Used to guard access to the UART in case messages are sent to the UART from
more than one task. */
static SemaphoreHandle_t xTxMutex = NULL;
/* The handle to the UART port, which is not used by all ports. */
static xComPortHandle xPort = 0;
/*-----------------------------------------------------------*/
void vUARTCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority )
{
/* Create the semaphore used to access the UART Tx. */
xTxMutex = xSemaphoreCreateMutex();
configASSERT( xTxMutex );
/* Create that task that handles the console itself. */
xTaskCreate( prvUARTCommandConsoleTask, /* The task that implements the command console. */
"CLI", /* Text name assigned to the task. This is just to assist debugging. The kernel does not use this name itself. */
usStackSize, /* The size of the stack allocated to the task. */
NULL, /* The parameter is not used, so NULL is passed. */
uxPriority, /* The priority allocated to the task. */
NULL ); /* A handle is not required, so just pass NULL. */
}
/*-----------------------------------------------------------*/
static void prvUARTCommandConsoleTask( void *pvParameters )
{
signed char cRxedChar;
uint8_t ucInputIndex = 0;
char *pcOutputString;
static char cInputString[ cmdMAX_INPUT_SIZE ], cLastInputString[ cmdMAX_INPUT_SIZE ];
BaseType_t xReturned;
xComPortHandle xPort;
( void ) pvParameters;
/* Obtain the address of the output buffer. Note there is no mutual
exclusion on this buffer as it is assumed only one command console interface
will be used at any one time. */
pcOutputString = FreeRTOS_CLIGetOutputBuffer();
/* Initialise the UART. */
xPort = xSerialPortInitMinimal( configCLI_BAUD_RATE, cmdQUEUE_LENGTH );
/* Send the welcome message. */
vSerialPutString( xPort, ( signed char * ) pcWelcomeMessage, ( unsigned short ) strlen( pcWelcomeMessage ) );
for( ;; )
{
/* Wait for the next character. The while loop is used in case
INCLUDE_vTaskSuspend is not set to 1 - in which case portMAX_DELAY will
be a genuine block time rather than an infinite block time. */
while( xSerialGetChar( xPort, &cRxedChar, portMAX_DELAY ) != pdPASS );
/* Ensure exclusive access to the UART Tx. */
if( xSemaphoreTake( xTxMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
{
/* Echo the character back. */
xSerialPutChar( xPort, cRxedChar, portMAX_DELAY );
/* Was it the end of the line? */
if( cRxedChar == '\n' || cRxedChar == '\r' )
{
/* Just to space the output from the input. */
vSerialPutString( xPort, ( signed char * ) pcNewLine, ( unsigned short ) strlen( pcNewLine ) );
/* See if the command is empty, indicating that the last command
is to be executed again. */
if( ucInputIndex == 0 )
{
/* Copy the last command back into the input string. */
strcpy( cInputString, cLastInputString );
}
/* Pass the received command to the command interpreter. The
command interpreter is called repeatedly until it returns
pdFALSE (indicating there is no more output) as it might
generate more than one string. */
do
{
/* Get the next output string from the command interpreter. */
xReturned = FreeRTOS_CLIProcessCommand( cInputString, pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );
/* Write the generated string to the UART. */
vSerialPutString( xPort, ( signed char * ) pcOutputString, ( unsigned short ) strlen( pcOutputString ) );
} while( xReturned != pdFALSE );
/* All the strings generated by the input command have been
sent. Clear the input string ready to receive the next command.
Remember the command that was just processed first in case it is
to be processed again. */
strcpy( cLastInputString, cInputString );
ucInputIndex = 0;
memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
vSerialPutString( xPort, ( signed char * ) pcEndOfOutputMessage, ( unsigned short ) strlen( pcEndOfOutputMessage ) );
}
else
{
if( cRxedChar == '\r' )
{
/* Ignore the character. */
}
else if( ( cRxedChar == '\b' ) || ( cRxedChar == cmdASCII_DEL ) )
{
/* Backspace was pressed. Erase the last character in the
string - if any. */
if( ucInputIndex > 0 )
{
ucInputIndex--;
cInputString[ ucInputIndex ] = '\0';
}
}
else
{
/* A character was entered. Add it to the string entered so
far. When a \n is entered the complete string will be
passed to the command interpreter. */
if( ( cRxedChar >= ' ' ) && ( cRxedChar <= '~' ) )
{
if( ucInputIndex < cmdMAX_INPUT_SIZE )
{
cInputString[ ucInputIndex ] = cRxedChar;
ucInputIndex++;
}
}
}
}
/* Must ensure to give the mutex back. */
xSemaphoreGive( xTxMutex );
}
}
}
/*-----------------------------------------------------------*/
void vOutputString( const char * const pcMessage )
{
if( xSemaphoreTake( xTxMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
{
vSerialPutString( xPort, ( signed char * ) pcMessage, ( unsigned short ) strlen( pcMessage ) );
xSemaphoreGive( xTxMutex );
}
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,313 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/******************************************************************************
*
* See the following URL for information on the commands defined in this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Ethernet_Related_CLI_Commands.shtml
*
******************************************************************************/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS+CLI includes. */
#include "FreeRTOS_CLI.h"
/* FreeRTOS+UDP includes, just to make the stats available to the CLI
commands. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
/*
* Defines a command that prints out IP address information.
*/
static BaseType_t prvDisplayIPConfig( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Defines a command that prints out the gathered demo debug stats.
*/
static BaseType_t prvDisplayIPDebugStats( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Defines a command that sends an ICMP ping request to an IP address.
*/
static BaseType_t prvPingCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/* Structure that defines the "ip-config" command line command. */
static const CLI_Command_Definition_t xIPConfig =
{
"ip-config",
"ip-config:\r\n Displays IP address configuration\r\n\r\n",
prvDisplayIPConfig,
0
};
#if configINCLUDE_DEMO_DEBUG_STATS != 0
/* Structure that defines the "ip-debug-stats" command line command. */
static const CLI_Command_Definition_t xIPDebugStats =
{
"ip-debug-stats", /* The command string to type. */
"ip-debug-stats:\r\n Shows some IP stack stats useful for debug - an example only.\r\n\r\n",
prvDisplayIPDebugStats, /* The function to run. */
0 /* No parameters are expected. */
};
#endif /* configINCLUDE_DEMO_DEBUG_STATS */
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
/* Structure that defines the "ping" command line command. This takes an IP
address or host name and (optionally) the number of bytes to ping as
parameters. */
static const CLI_Command_Definition_t xPing =
{
"ping",
"ping <ipaddress> <optional:bytes to send>:\r\n for example, ping 192.168.0.3 8, or ping www.example.com\r\n\r\n",
prvPingCommand, /* The function to run. */
-1 /* Ping can take either one or two parameter, so the number of parameters has to be determined by the ping command implementation. */
};
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
/*-----------------------------------------------------------*/
void vRegisterUDPCLICommands( void )
{
/* Register all the command line commands defined immediately above. */
FreeRTOS_CLIRegisterCommand( &xIPConfig );
#if configINCLUDE_DEMO_DEBUG_STATS == 1
{
FreeRTOS_CLIRegisterCommand( &xIPDebugStats );
}
#endif /* configINCLUDE_DEMO_DEBUG_STATS */
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
{
FreeRTOS_CLIRegisterCommand( &xPing );
}
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
}
/*-----------------------------------------------------------*/
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
static BaseType_t prvPingCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
char * pcParameter;
BaseType_t lParameterStringLength, xReturn;
uint32_t ulIPAddress, ulBytesToPing;
const uint32_t ulDefaultBytesToPing = 8UL;
char cBuffer[ 16 ];
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
/* Start with an empty string. */
pcWriteBuffer[ 0 ] = 0x00;
/* Obtain the number of bytes to ping. */
pcParameter = ( char * ) FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
2, /* Return the second parameter. */
&lParameterStringLength /* Store the parameter string length. */
);
if( pcParameter == NULL )
{
/* The number of bytes was not specified, so default it. */
ulBytesToPing = ulDefaultBytesToPing;
}
else
{
ulBytesToPing = atol( pcParameter );
}
/* Obtain the IP address string. */
pcParameter = ( char * ) FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */
&lParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcParameter );
/* Attempt to obtain the IP address. If the first character is not a
digit, assume the host name has been passed in. */
if( ( *pcParameter >= '0' ) && ( *pcParameter <= '9' ) )
{
ulIPAddress = FreeRTOS_inet_addr( pcParameter );
}
else
{
/* Terminate the host name. */
pcParameter[ lParameterStringLength ] = 0x00;
/* Attempt to resolve host. */
ulIPAddress = FreeRTOS_gethostbyname( pcParameter );
}
/* Convert IP address, which may have come from a DNS lookup, to string. */
FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
if( ulIPAddress != 0 )
{
xReturn = FreeRTOS_SendPingRequest( ulIPAddress, ( uint16_t ) ulBytesToPing, portMAX_DELAY );
}
else
{
xReturn = pdFALSE;
}
if( xReturn == pdFALSE )
{
sprintf( pcWriteBuffer, "%s", "Could not send ping request\r\n" );
}
else
{
sprintf( pcWriteBuffer, "Ping sent to %s with identifier %d\r\n", cBuffer, ( int ) xReturn );
}
return pdFALSE;
}
/*-----------------------------------------------------------*/
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
#if configINCLUDE_DEMO_DEBUG_STATS != 0
static BaseType_t prvDisplayIPDebugStats( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
static BaseType_t xIndex = -1;
extern xExampleDebugStatEntry_t xIPTraceValues[];
BaseType_t xReturn;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
xIndex++;
if( xIndex < xExampleDebugStatEntries() )
{
sprintf( pcWriteBuffer, "%s %d\r\n", ( char * ) xIPTraceValues[ xIndex ].pucDescription, ( int ) xIPTraceValues[ xIndex ].ulData );
xReturn = pdPASS;
}
else
{
/* Reset the index for the next time it is called. */
xIndex = -1;
/* Ensure nothing remains in the write buffer. */
pcWriteBuffer[ 0 ] = 0x00;
xReturn = pdFALSE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
#endif /* configINCLUDE_DEMO_DEBUG_STATS */
static BaseType_t prvDisplayIPConfig( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
static BaseType_t xIndex = 0;
BaseType_t xReturn;
uint32_t ulAddress;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
switch( xIndex )
{
case 0 :
FreeRTOS_GetAddressConfiguration( &ulAddress, NULL, NULL, NULL );
sprintf( pcWriteBuffer, "\r\nIP address " );
xReturn = pdTRUE;
xIndex++;
break;
case 1 :
FreeRTOS_GetAddressConfiguration( NULL, &ulAddress, NULL, NULL );
sprintf( pcWriteBuffer, "\r\nNet mask " );
xReturn = pdTRUE;
xIndex++;
break;
case 2 :
FreeRTOS_GetAddressConfiguration( NULL, NULL, &ulAddress, NULL );
sprintf( pcWriteBuffer, "\r\nGateway address " );
xReturn = pdTRUE;
xIndex++;
break;
case 3 :
FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulAddress );
sprintf( pcWriteBuffer, "\r\nDNS server address " );
xReturn = pdTRUE;
xIndex++;
break;
default :
ulAddress = 0;
sprintf( pcWriteBuffer, "\r\n\r\n" );
xReturn = pdFALSE;
xIndex = 0;
break;
}
if( ulAddress != 0 )
{
FreeRTOS_inet_ntoa( ulAddress, ( &( pcWriteBuffer[ strlen( pcWriteBuffer ) ] ) ) );
}
return xReturn;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,321 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*******************************************************************************
* See the URL in the comments within main.c for the location of the online
* documentation.
******************************************************************************/
/* Standard includes. */
#include <stdio.h>
#include <string.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
/* File system includes. */
#include "fat_sl.h"
#include "api_mdriver_ram.h"
/* 8.3 format, plus null terminator. */
#define fsMAX_FILE_NAME_LEN 13
/* The number of bytes read/written to the example files at a time. */
#define fsRAM_BUFFER_SIZE 200
/* The number of bytes written to the file that uses f_putc() and f_getc(). */
#define fsPUTC_FILE_SIZE 100
/*-----------------------------------------------------------*/
/*
* Creates and verifies different files on the volume, demonstrating the use of
* various different API functions.
*/
void vCreateAndVerifySampleFiles( void );
/*
* Create a set of example files in the root directory of the volume using
* f_write().
*/
static void prvCreateDemoFilesUsing_f_write( void );
/*
* Use f_read() to read back and verify the files that were created by
* prvCreateDemoFilesUsing_f_write().
*/
static void prvVerifyDemoFileUsing_f_read( void );
/*
* Create an example file in a sub-directory using f_putc().
*/
static void prvCreateDemoFileUsing_f_putc( void );
/*
* Use f_getc() to read back and verify the file that was created by
* prvCreateDemoFileUsing_f_putc().
*/
static void prvVerifyDemoFileUsing_f_getc( void );
/*-----------------------------------------------------------*/
/* A buffer used to both create content to write to disk, and read content back
from a disk. Note there is no mutual exclusion on this buffer. */
static char cRAMBuffer[ fsRAM_BUFFER_SIZE ];
/* Names of directories that are created. */
static const char *pcRoot = "/", *pcDirectory1 = "SUB1", *pcDirectory2 = "SUB2", *pcFullPath = "/SUB1/SUB2";
/*-----------------------------------------------------------*/
void vCreateAndVerifySampleFiles( void )
{
unsigned char ucStatus;
/* First create the volume. */
ucStatus = f_initvolume( ram_initfunc );
/* It is expected that the volume is not formatted. */
if( ucStatus == F_ERR_NOTFORMATTED )
{
/* Format the created volume. */
ucStatus = f_format( F_FAT12_MEDIA );
}
if( ucStatus == F_NO_ERROR )
{
/* Create a set of files using f_write(). */
prvCreateDemoFilesUsing_f_write();
/* Read back and verify the files that were created using f_write(). */
prvVerifyDemoFileUsing_f_read();
/* Create sub directories two deep then create a file using putc. */
prvCreateDemoFileUsing_f_putc();
/* Read back and verify the file created by
prvCreateDemoFileUsing_f_putc(). */
prvVerifyDemoFileUsing_f_getc();
}
}
/*-----------------------------------------------------------*/
static void prvCreateDemoFilesUsing_f_write( void )
{
BaseType_t xFileNumber, xWriteNumber;
char cFileName[ fsMAX_FILE_NAME_LEN ];
const BaseType_t xMaxFiles = 5;
long lItemsWritten;
F_FILE *pxFile;
/* Create xMaxFiles files. Each created file will be
( xFileNumber * fsRAM_BUFFER_SIZE ) bytes in length, and filled
with a different repeating character. */
for( xFileNumber = 1; xFileNumber <= xMaxFiles; xFileNumber++ )
{
/* Generate a file name. */
sprintf( cFileName, "root%03d.txt", ( int ) xFileNumber );
/* Obtain the current working directory and print out the file name and
the directory into which the file is being written. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
/* Open the file, creating the file if it does not already exist. */
pxFile = f_open( cFileName, "w" );
configASSERT( pxFile );
/* Fill the RAM buffer with data that will be written to the file. This
is just a repeating ascii character that indicates the file number. */
memset( cRAMBuffer, ( int ) ( '0' + xFileNumber ), fsRAM_BUFFER_SIZE );
/* Write the RAM buffer to the opened file a number of times. The
number of times the RAM buffer is written to the file depends on the
file number, so the length of each created file will be different. */
for( xWriteNumber = 0; xWriteNumber < xFileNumber; xWriteNumber++ )
{
lItemsWritten = f_write( cRAMBuffer, fsRAM_BUFFER_SIZE, 1, pxFile );
configASSERT( lItemsWritten == 1 );
}
/* Close the file so another file can be created. */
f_close( pxFile );
}
}
/*-----------------------------------------------------------*/
static void prvVerifyDemoFileUsing_f_read( void )
{
BaseType_t xFileNumber, xReadNumber;
char cFileName[ fsMAX_FILE_NAME_LEN ];
const BaseType_t xMaxFiles = 5;
long lItemsRead, lChar;
F_FILE *pxFile;
/* Read back the files that were created by
prvCreateDemoFilesUsing_f_write(). */
for( xFileNumber = 1; xFileNumber <= xMaxFiles; xFileNumber++ )
{
/* Generate the file name. */
sprintf( cFileName, "root%03d.txt", ( int ) xFileNumber );
/* Obtain the current working directory and print out the file name and
the directory from which the file is being read. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
/* Open the file for reading. */
pxFile = f_open( cFileName, "r" );
configASSERT( pxFile );
/* Read the file into the RAM buffer, checking the file contents are as
expected. The size of the file depends on the file number. */
for( xReadNumber = 0; xReadNumber < xFileNumber; xReadNumber++ )
{
/* Start with the RAM buffer clear. */
memset( cRAMBuffer, 0x00, fsRAM_BUFFER_SIZE );
lItemsRead = f_read( cRAMBuffer, fsRAM_BUFFER_SIZE, 1, pxFile );
configASSERT( lItemsRead == 1 );
/* Check the RAM buffer is filled with the expected data. Each
file contains a different repeating ascii character that indicates
the number of the file. */
for( lChar = 0; lChar < fsRAM_BUFFER_SIZE; lChar++ )
{
configASSERT( cRAMBuffer[ lChar ] == ( '0' + ( char ) xFileNumber ) );
}
}
/* Close the file. */
f_close( pxFile );
}
}
/*-----------------------------------------------------------*/
static void prvCreateDemoFileUsing_f_putc( void )
{
unsigned char ucReturn;
int iByte, iReturned;
F_FILE *pxFile;
char cFileName[ fsMAX_FILE_NAME_LEN ];
/* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
/* Create a sub directory. */
ucReturn = f_mkdir( pcDirectory1 );
configASSERT( ucReturn == F_NO_ERROR );
/* Move into the created sub-directory. */
ucReturn = f_chdir( pcDirectory1 );
configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
/* Create a subdirectory in the new directory. */
ucReturn = f_mkdir( pcDirectory2 );
configASSERT( ucReturn == F_NO_ERROR );
/* Move into the directory just created - now two directories down from
the root. */
ucReturn = f_chdir( pcDirectory2 );
configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
configASSERT( strcmp( cRAMBuffer, pcFullPath ) == 0 );
/* Generate the file name. */
sprintf( cFileName, "%s.txt", pcDirectory2 );
/* Print out the file name and the directory into which the file is being
written. */
pxFile = f_open( cFileName, "w" );
/* Create a file 1 byte at a time. The file is filled with incrementing
ascii characters starting from '0'. */
for( iByte = 0; iByte < fsPUTC_FILE_SIZE; iByte++ )
{
iReturned = f_putc( ( ( int ) '0' + iByte ), pxFile );
configASSERT( iReturned == ( ( int ) '0' + iByte ) );
}
/* Finished so close the file. */
f_close( pxFile );
/* Move back to the root directory. */
ucReturn = f_chdir( "../.." );
configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
configASSERT( strcmp( cRAMBuffer, pcRoot ) == 0 );
}
/*-----------------------------------------------------------*/
static void prvVerifyDemoFileUsing_f_getc( void )
{
unsigned char ucReturn;
int iByte, iReturned;
F_FILE *pxFile;
char cFileName[ fsMAX_FILE_NAME_LEN ];
/* Move into the directory in which the file was created. */
ucReturn = f_chdir( pcFullPath );
configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
configASSERT( strcmp( cRAMBuffer, pcFullPath ) == 0 );
/* Generate the file name. */
sprintf( cFileName, "%s.txt", pcDirectory2 );
/* This time the file is opened for reading. */
pxFile = f_open( cFileName, "r" );
/* Read the file 1 byte at a time. */
for( iByte = 0; iByte < fsPUTC_FILE_SIZE; iByte++ )
{
iReturned = f_getc( pxFile );
configASSERT( iReturned == ( ( int ) '0' + iByte ) );
}
/* Finished so close the file. */
f_close( pxFile );
/* Move back to the root directory. */
ucReturn = f_chdir( "../.." );
configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
}

View File

@ -0,0 +1,664 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/******************************************************************************
*
* See the following URL for information on the commands defined in this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Ethernet_Related_CLI_Commands.shtml
*
******************************************************************************/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS+CLI includes. */
#include "FreeRTOS_CLI.h"
/* FreeRTOS+UDP includes, just to make the stats available to the CLI
commands. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
#ifndef configINCLUDE_TRACE_RELATED_CLI_COMMANDS
#define configINCLUDE_TRACE_RELATED_CLI_COMMANDS 0
#endif
/*
* Implements the run-time-stats command.
*/
static BaseType_t prvTaskStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the task-stats command.
*/
static BaseType_t prvRunTimeStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the echo-three-parameters command.
*/
static BaseType_t prvThreeParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the echo-parameters command.
*/
static BaseType_t prvParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Defines a command that prints out IP address information.
*/
static BaseType_t prvDisplayIPConfig( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Defines a command that prints out the gathered demo debug stats.
*/
static BaseType_t prvDisplayIPDebugStats( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Defines a command that sends an ICMP ping request to an IP address.
*/
static BaseType_t prvPingCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Implements the "trace start" and "trace stop" commands;
*/
#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1
static BaseType_t prvStartStopTraceCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
#endif
/* Structure that defines the "ip-config" command line command. */
static const CLI_Command_Definition_t xIPConfig =
{
"ip-config",
"ip-config:\r\n Displays IP address configuration\r\n\r\n",
prvDisplayIPConfig,
0
};
#if configINCLUDE_DEMO_DEBUG_STATS != 0
/* Structure that defines the "ip-debug-stats" command line command. */
static const CLI_Command_Definition_t xIPDebugStats =
{
"ip-debug-stats", /* The command string to type. */
"ip-debug-stats:\r\n Shows some IP stack stats useful for debug - an example only.\r\n\r\n",
prvDisplayIPDebugStats, /* The function to run. */
0 /* No parameters are expected. */
};
#endif /* configINCLUDE_DEMO_DEBUG_STATS */
/* Structure that defines the "run-time-stats" command line command. This
generates a table that shows how much run time each task has */
static const CLI_Command_Definition_t xRunTimeStats =
{
"run-time-stats", /* The command string to type. */
"run-time-stats:\r\n Displays a table showing how much processing time each FreeRTOS task has used\r\n\r\n",
prvRunTimeStatsCommand, /* The function to run. */
0 /* No parameters are expected. */
};
/* Structure that defines the "task-stats" command line command. This generates
a table that gives information on each task in the system. */
static const CLI_Command_Definition_t xTaskStats =
{
"task-stats", /* The command string to type. */
"task-stats:\r\n Displays a table showing the state of each FreeRTOS task\r\n\r\n",
prvTaskStatsCommand, /* The function to run. */
0 /* No parameters are expected. */
};
/* Structure that defines the "echo_3_parameters" command line command. This
takes exactly three parameters that the command simply echos back one at a
time. */
static const CLI_Command_Definition_t xThreeParameterEcho =
{
"echo-3-parameters",
"echo-3-parameters <param1> <param2> <param3>:\r\n Expects three parameters, echos each in turn\r\n\r\n",
prvThreeParameterEchoCommand, /* The function to run. */
3 /* Three parameters are expected, which can take any value. */
};
/* Structure that defines the "echo_parameters" command line command. This
takes a variable number of parameters that the command simply echos back one at
a time. */
static const CLI_Command_Definition_t xParameterEcho =
{
"echo-parameters",
"echo-parameters <...>:\r\n Take variable number of parameters, echos each in turn\r\n\r\n",
prvParameterEchoCommand, /* The function to run. */
-1 /* The user can enter any number of commands. */
};
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
/* Structure that defines the "ping" command line command. This takes an IP
address or host name and (optionally) the number of bytes to ping as
parameters. */
static const CLI_Command_Definition_t xPing =
{
"ping",
"ping <ipaddress> <optional:bytes to send>:\r\n for example, ping 192.168.0.3 8, or ping www.example.com\r\n\r\n",
prvPingCommand, /* The function to run. */
-1 /* Ping can take either one or two parameter, so the number of parameters has to be determined by the ping command implementation. */
};
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1
/* Structure that defines the "trace" command line command. This takes a single
parameter, which can be either "start" or "stop". */
static const CLI_Command_Definition_t xStartStopTrace =
{
"trace",
"trace [start | stop]:\r\n Starts or stops a trace recording for viewing in FreeRTOS+Trace\r\n\r\n",
prvStartStopTraceCommand, /* The function to run. */
1 /* One parameter is expected. Valid values are "start" and "stop". */
};
#endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */
/*-----------------------------------------------------------*/
void vRegisterCLICommands( void )
{
/* Register all the command line commands defined immediately above. */
FreeRTOS_CLIRegisterCommand( &xTaskStats );
FreeRTOS_CLIRegisterCommand( &xRunTimeStats );
FreeRTOS_CLIRegisterCommand( &xThreeParameterEcho );
FreeRTOS_CLIRegisterCommand( &xParameterEcho );
FreeRTOS_CLIRegisterCommand( &xIPDebugStats );
FreeRTOS_CLIRegisterCommand( &xIPConfig );
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
{
FreeRTOS_CLIRegisterCommand( &xPing );
}
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1
FreeRTOS_CLIRegisterCommand( & xStartStopTrace );
#endif
}
/*-----------------------------------------------------------*/
static BaseType_t prvTaskStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *const pcHeader = " State\tPriority\tStack\t#\r\n************************************************\r\n";
BaseType_t xSpacePadding;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
/* Generate a table of task stats. */
strcpy( pcWriteBuffer, "Task" );
pcWriteBuffer += strlen( pcWriteBuffer );
/* Pad the string "task" with however many bytes necessary to make it the
length of a task name. Minus three for the null terminator and half the
number of characters in "Task" so the column lines up with the centre of
the heading. */
for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ )
{
/* Add a space to align columns after the task's name. */
*pcWriteBuffer = ' ';
pcWriteBuffer++;
/* Ensure always terminated. */
*pcWriteBuffer = 0x00;
}
strcpy( pcWriteBuffer, pcHeader );
vTaskList( pcWriteBuffer + strlen( pcHeader ) );
/* There is no more data to return after this single string, so return
pdFALSE. */
return pdFALSE;
}
/*-----------------------------------------------------------*/
static BaseType_t prvRunTimeStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char * const pcHeader = " Abs Time % Time\r\n****************************************\r\n";
BaseType_t xSpacePadding;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
/* Generate a table of task stats. */
strcpy( pcWriteBuffer, "Task" );
pcWriteBuffer += strlen( pcWriteBuffer );
/* Pad the string "task" with however many bytes necessary to make it the
length of a task name. Minus three for the null terminator and half the
number of characters in "Task" so the column lines up with the centre of
the heading. */
for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ )
{
/* Add a space to align columns after the task's name. */
*pcWriteBuffer = ' ';
pcWriteBuffer++;
/* Ensure always terminated. */
*pcWriteBuffer = 0x00;
}
strcpy( pcWriteBuffer, pcHeader );
vTaskGetRunTimeStats( pcWriteBuffer + strlen( pcHeader ) );
/* There is no more data to return after this single string, so return
pdFALSE. */
return pdFALSE;
}
/*-----------------------------------------------------------*/
static BaseType_t prvThreeParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t xParameterStringLength, xReturn;
static BaseType_t lParameterNumber = 0;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
if( lParameterNumber == 0 )
{
/* The first time the function is called after the command has been
entered just a header string is returned. */
sprintf( pcWriteBuffer, "The three parameters were:\r\n" );
/* Next time the function is called the first parameter will be echoed
back. */
lParameterNumber = 1L;
/* There is more data to be returned as no parameters have been echoed
back yet. */
xReturn = pdPASS;
}
else
{
/* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
lParameterNumber, /* Return the next parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcParameter );
/* Return the parameter string. */
memset( pcWriteBuffer, 0x00, xWriteBufferLen );
sprintf( pcWriteBuffer, "%d: ", ( int ) lParameterNumber );
strncat( pcWriteBuffer, pcParameter, xParameterStringLength );
strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) );
/* If this is the last of the three parameters then there are no more
strings to return after this one. */
if( lParameterNumber == 3L )
{
/* If this is the last of the three parameters then there are no more
strings to return after this one. */
xReturn = pdFALSE;
lParameterNumber = 0L;
}
else
{
/* There are more parameters to return after this one. */
xReturn = pdTRUE;
lParameterNumber++;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
static BaseType_t prvParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t xParameterStringLength, xReturn;
static BaseType_t lParameterNumber = 0;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
if( lParameterNumber == 0 )
{
/* The first time the function is called after the command has been
entered just a header string is returned. */
sprintf( pcWriteBuffer, "The parameters were:\r\n" );
/* Next time the function is called the first parameter will be echoed
back. */
lParameterNumber = 1L;
/* There is more data to be returned as no parameters have been echoed
back yet. */
xReturn = pdPASS;
}
else
{
/* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
lParameterNumber, /* Return the next parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
if( pcParameter != NULL )
{
/* Return the parameter string. */
memset( pcWriteBuffer, 0x00, xWriteBufferLen );
sprintf( pcWriteBuffer, "%d: ", ( int ) lParameterNumber );
strncat( pcWriteBuffer, pcParameter, xParameterStringLength );
strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) );
/* There might be more parameters to return after this one. */
xReturn = pdTRUE;
lParameterNumber++;
}
else
{
/* No more parameters were found. Make sure the write buffer does
not contain a valid string. */
pcWriteBuffer[ 0 ] = 0x00;
/* No more data to return. */
xReturn = pdFALSE;
/* Start over the next time this command is executed. */
lParameterNumber = 0;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
static BaseType_t prvPingCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
char * pcParameter;
BaseType_t lParameterStringLength, xReturn;
uint32_t ulIPAddress, ulBytesToPing;
const uint32_t ulDefaultBytesToPing = 8UL;
char cBuffer[ 16 ];
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
/* Start with an empty string. */
pcWriteBuffer[ 0 ] = 0x00;
/* Obtain the number of bytes to ping. */
pcParameter = ( char * ) FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
2, /* Return the second parameter. */
&lParameterStringLength /* Store the parameter string length. */
);
if( pcParameter == NULL )
{
/* The number of bytes was not specified, so default it. */
ulBytesToPing = ulDefaultBytesToPing;
}
else
{
ulBytesToPing = atol( pcParameter );
}
/* Obtain the IP address string. */
pcParameter = ( char * ) FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */
&lParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcParameter );
/* Attempt to obtain the IP address. If the first character is not a
digit, assume the host name has been passed in. */
if( ( *pcParameter >= '0' ) && ( *pcParameter <= '9' ) )
{
ulIPAddress = FreeRTOS_inet_addr( pcParameter );
}
else
{
/* Terminate the host name. */
pcParameter[ lParameterStringLength ] = 0x00;
/* Attempt to resolve host. */
ulIPAddress = FreeRTOS_gethostbyname( pcParameter );
}
/* Convert IP address, which may have come from a DNS lookup, to string. */
FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
if( ulIPAddress != 0 )
{
xReturn = FreeRTOS_SendPingRequest( ulIPAddress, ( uint16_t ) ulBytesToPing, portMAX_DELAY );
}
else
{
xReturn = pdFALSE;
}
if( xReturn == pdFALSE )
{
sprintf( pcWriteBuffer, "%s", "Could not send ping request\r\n" );
}
else
{
sprintf( pcWriteBuffer, "Ping sent to %s with identifier %d\r\n", cBuffer, xReturn );
}
return pdFALSE;
}
/*-----------------------------------------------------------*/
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
#if configINCLUDE_DEMO_DEBUG_STATS != 0
static BaseType_t prvDisplayIPDebugStats( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
static BaseType_t xIndex = -1;
extern xExampleDebugStatEntry_t xIPTraceValues[];
BaseType_t xReturn;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
xIndex++;
if( xIndex < xExampleDebugStatEntries() )
{
sprintf( pcWriteBuffer, "%s %d\r\n", xIPTraceValues[ xIndex ].pucDescription, ( int ) xIPTraceValues[ xIndex ].ulData );
xReturn = pdPASS;
}
else
{
/* Reset the index for the next time it is called. */
xIndex = -1;
/* Ensure nothing remains in the write buffer. */
pcWriteBuffer[ 0 ] = 0x00;
xReturn = pdFALSE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
#endif /* configINCLUDE_DEMO_DEBUG_STATS */
static BaseType_t prvDisplayIPConfig( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
static BaseType_t xIndex = 0;
BaseType_t xReturn;
uint32_t ulAddress;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
switch( xIndex )
{
case 0 :
FreeRTOS_GetAddressConfiguration( &ulAddress, NULL, NULL, NULL );
sprintf( pcWriteBuffer, "\r\nIP address " );
xReturn = pdTRUE;
xIndex++;
break;
case 1 :
FreeRTOS_GetAddressConfiguration( NULL, &ulAddress, NULL, NULL );
sprintf( pcWriteBuffer, "\r\nNet mask " );
xReturn = pdTRUE;
xIndex++;
break;
case 2 :
FreeRTOS_GetAddressConfiguration( NULL, NULL, &ulAddress, NULL );
sprintf( pcWriteBuffer, "\r\nGateway address " );
xReturn = pdTRUE;
xIndex++;
break;
case 3 :
FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulAddress );
sprintf( pcWriteBuffer, "\r\nDNS server address " );
xReturn = pdTRUE;
xIndex++;
break;
default :
ulAddress = 0;
sprintf( pcWriteBuffer, "\r\n\r\n" );
xReturn = pdFALSE;
xIndex = 0;
break;
}
if( ulAddress != 0 )
{
FreeRTOS_inet_ntoa( ulAddress, &( pcWriteBuffer[ strlen( pcWriteBuffer ) ] ) );
}
return xReturn;
}
/*-----------------------------------------------------------*/
#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1
static BaseType_t prvStartStopTraceCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t lParameterStringLength;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
/* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */
&lParameterStringLength /* Store the parameter string length. */
);
/* Sanity check something was returned. */
configASSERT( pcParameter );
/* There are only two valid parameter values. */
if( strncmp( pcParameter, "start", strlen( "start" ) ) == 0 )
{
/* Start or restart the trace. */
vTraceStop();
vTraceClear();
vTraceStart();
sprintf( pcWriteBuffer, "Trace recording (re)started.\r\n" );
}
else if( strncmp( pcParameter, "stop", strlen( "stop" ) ) == 0 )
{
/* End the trace, if one is running. */
vTraceStop();
sprintf( pcWriteBuffer, "Stopping trace recording.\r\n" );
}
else
{
sprintf( pcWriteBuffer, "Valid parameters are 'start' and 'stop'.\r\n" );
}
/* There is no more data to return after this single string, so return
pdFALSE. */
return pdFALSE;
}
#endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */

View File

@ -0,0 +1,33 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef UDP_COMMAND_INTERPRETER_H
#define UDP_COMMAND_INTERPRETER_H
void vStartUDPCommandInterpreterTask( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority );
#endif /* UDP_COMMAND_INTERPRETER_H */

View File

@ -0,0 +1,206 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* FreeRTOS+CLI includes. */
#include "FreeRTOS_CLI.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
/* Demo app includes. */
#include "UDPCommandInterpreter.h"
/* Dimensions the buffer into which input characters are placed. */
#define cmdMAX_INPUT_SIZE 60
/* Dimensions the buffer into which string outputs can be placed. */
#define cmdMAX_OUTPUT_SIZE 1250
/* Dimensions the buffer passed to the recvfrom() call. */
#define cmdSOCKET_INPUT_BUFFER_SIZE 60
/*
* The task that runs FreeRTOS+CLI.
*/
void vUDPCommandInterpreterTask( void *pvParameters );
/*
* Open and configure the UDP socket.
*/
static xSocket_t prvOpenUDPServerSocket( uint16_t usPort );
/*-----------------------------------------------------------*/
void vStartUDPCommandInterpreterTask( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority )
{
xTaskCreate( vUDPCommandInterpreterTask, "CLI", usStackSize, ( void * ) ulPort, uxPriority, NULL );
}
/*-----------------------------------------------------------*/
/*
* Task that provides the input and output for the FreeRTOS+CLI command
* interpreter. In this case a UDP port is used. See the URL in the comments
* within main.c for the location of the online documentation.
*/
void vUDPCommandInterpreterTask( void *pvParameters )
{
long lBytes, lByte;
signed char cInChar, cInputIndex = 0;
static char cInputString[ cmdMAX_INPUT_SIZE ], cOutputString[ cmdMAX_OUTPUT_SIZE ], cLocalBuffer[ cmdSOCKET_INPUT_BUFFER_SIZE ];
BaseType_t xMoreDataToFollow;
struct freertos_sockaddr xClient;
socklen_t xClientAddressLength = 0; /* This is required as a parameter to maintain the sendto() Berkeley sockets API - but it is not actually used so can take any value. */
xSocket_t xSocket;
/* Just to prevent compiler warnings. */
( void ) pvParameters;
/* Attempt to open the socket. The port number is passed in the task
parameter. The strange casting is to remove compiler warnings on 32-bit
machines. */
xSocket = prvOpenUDPServerSocket( ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL );
if( xSocket != FREERTOS_INVALID_SOCKET )
{
for( ;; )
{
/* Wait for incoming data on the opened socket. */
lBytes = FreeRTOS_recvfrom( xSocket, ( void * ) cLocalBuffer, sizeof( cLocalBuffer ), 0, &xClient, &xClientAddressLength );
if( lBytes != FREERTOS_SOCKET_ERROR )
{
/* Process each received byte in turn. */
lByte = 0;
while( lByte < lBytes )
{
/* The next character in the input buffer. */
cInChar = cLocalBuffer[ lByte ];
lByte++;
/* Newline characters are taken as the end of the command
string. */
if( cInChar == '\n' )
{
/* Process the input string received prior to the
newline. */
do
{
/* Pass the string to FreeRTOS+CLI. */
xMoreDataToFollow = FreeRTOS_CLIProcessCommand( cInputString, cOutputString, cmdMAX_OUTPUT_SIZE );
/* Send the output generated by the command's
implementation. */
FreeRTOS_sendto( xSocket, cOutputString, strlen( cOutputString ), 0, &xClient, xClientAddressLength );
} while( xMoreDataToFollow != pdFALSE ); /* Until the command does not generate any more output. */
/* All the strings generated by the command processing
have been sent. Clear the input string ready to receive
the next command. */
cInputIndex = 0;
memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
/* Transmit a spacer, just to make the command console
easier to read. */
FreeRTOS_sendto( xSocket, "\r\n", strlen( "\r\n" ), 0, &xClient, xClientAddressLength );
}
else
{
if( cInChar == '\r' )
{
/* Ignore the character. Newlines are used to
detect the end of the input string. */
}
else if( cInChar == '\b' )
{
/* Backspace was pressed. Erase the last character
in the string - if any. */
if( cInputIndex > 0 )
{
cInputIndex--;
cInputString[ cInputIndex ] = '\0';
}
}
else
{
/* A character was entered. Add it to the string
entered so far. When a \n is entered the complete
string will be passed to the command interpreter. */
if( cInputIndex < cmdMAX_INPUT_SIZE )
{
cInputString[ cInputIndex ] = cInChar;
cInputIndex++;
}
}
}
}
}
}
}
else
{
/* The socket could not be opened. */
vTaskDelete( NULL );
}
}
/*-----------------------------------------------------------*/
static xSocket_t prvOpenUDPServerSocket( uint16_t usPort )
{
struct freertos_sockaddr xServer;
xSocket_t xSocket = FREERTOS_INVALID_SOCKET;
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
if( xSocket != FREERTOS_INVALID_SOCKET)
{
/* Zero out the server structure. */
memset( ( void * ) &xServer, 0x00, sizeof( xServer ) );
/* Set family and port. */
xServer.sin_port = FreeRTOS_htons( usPort );
/* Bind the address to the socket. */
if( FreeRTOS_bind( xSocket, &xServer, sizeof( xServer ) ) == -1 )
{
FreeRTOS_closesocket( xSocket );
xSocket = FREERTOS_INVALID_SOCKET;
}
}
return xSocket;
}

View File

@ -0,0 +1,359 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/******************************************************************************
*
* See the following web page for essential TwoEchoClient.c usage and
* configuration details:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Common_Echo_Clients.shtml
*
******************************************************************************/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
/* Small delay used between attempts to obtain a zero copy buffer. */
#define echoTINY_DELAY ( ( TickType_t ) 2 )
/* The echo tasks create a socket, send out a number of echo requests
(listening for each 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 ) 250 / portTICK_RATE_MS )
#if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1
/* When the trace recorder code is included user events are generated to
mark the sending and receiving of the echoed data (only in the zero copy
task. */
#define echoMARK_SEND_IN_TRACE_BUFFER( x ) vTraceUserEvent( x )
traceLabel xZeroCopySendEvent, xZeroCopyReceiveEvent;
#else
/* When the trace recorder code is not included just #define away the call
to post the user event. */
#define echoMARK_SEND_IN_TRACE_BUFFER( x )
#define xZeroCopySendEvent 0
#define xZeroCopyReceiveEvent 0
#endif
/* The echo server is assumed to be on port 7, which is the standard echo
protocol port. */
#define echoECHO_PORT ( 7 )
/*
* Uses a socket to send data to, then receive data from, the standard echo
* port number 7. prvEchoClientTask() uses the standard interface.
* prvZeroCopyEchoClientTask() uses the zero copy interface.
*/
static void prvEchoClientTask( void *pvParameters );
static void prvZeroCopyEchoClientTask( void *pvParameters );
/* The receive timeout is set shorter when the windows simulator is used
because simulated time is slower than real time. */
#ifdef _WINDOWS_
const TickType_t xReceiveTimeOut = 50 / portTICK_RATE_MS;
#else
const TickType_t xReceiveTimeOut = 500 / portTICK_RATE_MS;
#endif
/*-----------------------------------------------------------*/
void vStartEchoClientTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )
{
/* Create the echo client task that does not use the zero copy interface. */
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. */
NULL, /* 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. */
/* Create the echo client task that does use the zero copy interface. */
xTaskCreate( prvZeroCopyEchoClientTask, /* The function that implements the task. */
"Echo1", /* Just a text name for the task to aid debugging. */
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
NULL, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
NULL ); /* The task handle is not used. */
}
/*-----------------------------------------------------------*/
static void prvEchoClientTask( void *pvParameters )
{
xSocket_t xSocket;
struct freertos_sockaddr xEchoServerAddress;
char cTxString[ 25 ], cRxString[ 25 ]; /* Make sure the stack is large enough to hold these. Turn on stack overflow checking during debug to be sure. */
int32_t lLoopCount = 0UL;
const int32_t lMaxLoopCount = 50;
volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL;
uint32_t xAddressLength = sizeof( xEchoServerAddress );
/* Remove compiler warning about unused parameters. */
( void ) pvParameters;
/* 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 socket. */
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
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 ) );
/* Send a number of echo requests. */
for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )
{
/* Create the string that is sent to the echo server. */
sprintf( cTxString, "Message number %u\r\n", ( unsigned int ) ulTxCount );
/* Send the string to the socket. ulFlags is set to 0, so the zero
copy interface is not used. That means the data from cTxString is
copied into a network buffer inside FreeRTOS_sendto(), and cTxString
can be reused as soon as FreeRTOS_sendto() has returned. 1 is added
to ensure the NULL string terminator is sent as part of the message. */
FreeRTOS_sendto( xSocket, /* The socket being sent to. */
( void * ) cTxString, /* The data being sent. */
strlen( cTxString ) + 1,/* The length of the data being sent. */
0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */
&xEchoServerAddress, /* The destination address. */
sizeof( xEchoServerAddress ) );
/* Keep a count of how many echo requests have been transmitted so
it can be compared to the number of echo replies received. It would
be expected to loose at least one to an ARP message the first time
the connection is created. */
ulTxCount++;
/* Receive data echoed back to the socket. ulFlags is zero, so the
zero copy option is not being used and the received data will be
copied into the buffer pointed to by cRxString. xAddressLength is
not actually used (at the time of writing this comment, anyway) by
FreeRTOS_recvfrom(), but is set appropriately in case future
versions do use it. */
memset( ( void * ) cRxString, 0x00, sizeof( cRxString ) );
FreeRTOS_recvfrom( xSocket, /* The socket being received from. */
cRxString, /* The buffer into which the received data will be written. */
sizeof( cRxString ), /* The size of the buffer provided to receive the data. */
0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */
&xEchoServerAddress, /* The address from where the data was sent (the source address). */
&xAddressLength );
/* Compare the transmitted string to the received string. */
if( strcmp( cRxString, cTxString ) == 0 )
{
/* The echo reply was received without error. */
ulRxCount++;
}
};
/* Pause for a short while to ensure the network is not too
congested. */
vTaskDelay( echoLOOP_DELAY );
/* Close this socket before looping back to create another. */
FreeRTOS_closesocket( xSocket );
}
}
/*-----------------------------------------------------------*/
static void prvZeroCopyEchoClientTask( void *pvParameters )
{
xSocket_t xSocket;
struct freertos_sockaddr xEchoServerAddress;
static char cTxString[ 40 ];
int32_t lLoopCount = 0UL;
volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL;
uint32_t xAddressLength = sizeof( xEchoServerAddress );
int32_t lReturned;
uint8_t *pucUDPPayloadBuffer;
const int32_t lMaxLoopCount = 50;
const char * const pcStringToSend = "Zero copy message number";
/* The buffer is large enough to hold the string, a number, and the string terminator. */
const size_t xBufferLength = strlen( pcStringToSend ) + 15;
#if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1
{
/* When the trace recorder code is included user events are generated to
mark the sending and receiving of the echoed data (only in the zero copy
task). */
xZeroCopySendEvent = xTraceOpenLabel( "ZeroCopyTx" );
xZeroCopyReceiveEvent = xTraceOpenLabel( "ZeroCopyRx" );
}
#endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS */
/* Remove compiler warning about unused parameters. */
( void ) pvParameters;
/* Delay for a little while to ensure the task is out of synch with the
other echo task implemented above. */
vTaskDelay( echoLOOP_DELAY >> 1 );
/* 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 socket. */
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
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 ) );
/* Send a number of echo requests. */
for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )
{
/* This task is going to send using the zero copy interface. The
data being sent is therefore written directly into a buffer that is
passed by reference into the FreeRTOS_sendto() function. First
obtain a buffer of adequate size from the IP stack. Although a max
delay is used, the actual delay will be capped to
ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence the test to ensure a buffer
was actually obtained. */
pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xBufferLength, portMAX_DELAY );
if( pucUDPPayloadBuffer != NULL )
{
/* A buffer was successfully obtained. Create the string that is
sent to the echo server. Note the string is written directly
into the buffer obtained from the IP stack. */
sprintf( ( char * ) pucUDPPayloadBuffer, "%s %u\r\n", "Zero copy message number", ( unsigned int ) ulTxCount );
/* Also copy the string into a local buffer so it can be compared
with the string that is later received back from the echo server. */
strcpy( cTxString, ( char * ) pucUDPPayloadBuffer );
/* Pass the buffer into the send function. ulFlags has the
FREERTOS_ZERO_COPY bit set so the IP stack will take control of
the buffer, rather than copy data out of the buffer. */
echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopySendEvent );
lReturned = FreeRTOS_sendto( xSocket, /* The socket being sent to. */
( void * ) pucUDPPayloadBuffer, /* The buffer being passed into the IP stack. */
strlen( cTxString ) + 1, /* The length of the data being sent. Plus 1 to ensure the null terminator is part of the data. */
FREERTOS_ZERO_COPY, /* ulFlags with the zero copy bit is set. */
&xEchoServerAddress, /* Where the data is being sent. */
sizeof( xEchoServerAddress ) );
if( lReturned == 0 )
{
/* The send operation failed, so this task is still
responsible for the buffer obtained from the IP stack. To
ensure the buffer is not lost it must either be used again,
or, as in this case, returned to the IP stack using
FreeRTOS_ReleaseUDPPayloadBuffer(). pucUDPPayloadBuffer can
be safely re-used to receive from the socket below once the
buffer has been returned to the stack. */
FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
}
else
{
/* The send was successful so the IP stack is now managing
the buffer pointed to by pucUDPPayloadBuffer, and the IP
stack will return the buffer once it has been sent.
pucUDPPayloadBuffer can be safely re-used to receive from
the socket below. */
}
/* Keep a count of how many echo requests have been transmitted
so it can be compared to the number of echo replies received.
It would be expected to loose at least one to an ARP message the
first time the connection is created. */
ulTxCount++;
/* Receive data on the socket. ulFlags has the zero copy bit set
(FREERTOS_ZERO_COPY) indicating to the stack that a reference to
the received data should be passed out to this task using the
second parameter to the FreeRTOS_recvfrom() call. When this is
done the IP stack is no longer responsible for releasing the
buffer, and the task *must* return the buffer to the stack when
it is no longer needed. By default the receive block time is
portMAX_DELAY. */
echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopyReceiveEvent );
lReturned = FreeRTOS_recvfrom( xSocket, /* The socket to receive from. */
( void * ) &pucUDPPayloadBuffer, /* pucUDPPayloadBuffer will be set to point to the buffer that already contains the received data. */
0, /* Ignored because the zero copy interface is being used. */
FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */
&xEchoServerAddress, /* The address from which the data was sent. */
&xAddressLength );
if( lReturned > 0 )
{
/* Compare the string sent to the echo server with the string
received back from the echo server. */
if( strcmp( ( char * ) pucUDPPayloadBuffer, cTxString ) == 0 )
{
/* The strings matched. */
ulRxCount++;
}
/* The buffer that contains the data passed out of the stack
*must* be returned to the stack. */
FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );
}
}
}
/* Pause for a short while to ensure the network is not too
congested. */
vTaskDelay( echoLOOP_DELAY );
/* Close this socket before looping back to create another. */
FreeRTOS_closesocket( xSocket );
}
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,38 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef TWO_ECHO_CLIENTS_H
#define TWO_ECHO_CLIENTS_H
/*
* Create the two UDP echo client tasks. One task uses the standard interface
* to send to and receive from an echo server. The other task uses the zero
* copy interface to send to and receive from an echo server.
*/
void vStartEchoClientTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority );
#endif /* TWO_ECHO_CLIENTS_H */

View File

@ -0,0 +1,150 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*
* This file, along with DemoIPTrace.h, provides a basic example use of the
* FreeRTOS+UDP trace macros. The statistics gathered here can be viewed in
* the command line interface.
* See http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/UDP_IP_Trace.shtml
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* FreeRTOS+UDP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "DemoIPTrace.h"
/* It is possible to remove the trace macros using the
configINCLUDE_DEMO_DEBUG_STATS setting in FreeRTOSIPConfig.h. */
#if configINCLUDE_DEMO_DEBUG_STATS == 1
/*
* Each row in the xIPTraceValues[] table contains a pointer to a function that
* updates the value for that row. Rows that latch the lowest value point to
* this function (for example, this function can be used to latch the lowest
* number of network buffers that were available during the execution of the
* stack).
*/
static void prvStoreLowest( uint32_t *pulCurrentValue, uint32_t ulCount );
/*
* Each row in the xIPTraceValues[] table contains a pointer to a function that
* updates the value for that row. Rows that simply increment an event count
* point to this function.
*/
static void prvIncrementEventCount( uint32_t *pulCurrentValue, uint32_t ulCount );
xExampleDebugStatEntry_t xIPTraceValues[] =
{
/* Comment out array entries to remove individual trace items. */
{ iptraceID_NETWORK_INTERFACE_RECEIVE, ( const uint8_t * const ) "Packets received by the network interface", prvIncrementEventCount, 0 },
{ iptraceID_NETWORK_INTERFACE_TRANSMIT, ( const uint8_t * const ) "Count of transmitted packets", prvIncrementEventCount, 0 },
{ iptraceID_PACKET_DROPPED_TO_GENERATE_ARP, ( const uint8_t * const ) "Count of packets dropped to generate ARP", prvIncrementEventCount, 0 },
{ iptraceID_NETWORK_BUFFER_OBTAINED, ( const uint8_t * const ) "Lowest ever available network buffers", prvStoreLowest, 0xffffUL },
{ iptraceID_NETWORK_EVENT_RECEIVED, ( const uint8_t * const ) "Lowest ever free space in network event queue", prvStoreLowest, 0xffffUL },
{ iptraceID_FAILED_TO_OBTAIN_NETWORK_BUFFER, ( const uint8_t * const ) "Count of failed attempts to obtain a network buffer",prvIncrementEventCount, 0 },
{ iptraceID_ARP_TABLE_ENTRY_EXPIRED, ( const uint8_t * const ) "Count of expired ARP entries", prvIncrementEventCount, 0 },
{ iptraceID_FAILED_TO_CREATE_SOCKET, ( const uint8_t * const ) "Count of failures to create a socket", prvIncrementEventCount, 0 },
{ iptraceID_RECVFROM_DISCARDING_BYTES, ( const uint8_t * const ) "Count of times recvfrom() has discarding bytes", prvIncrementEventCount, 0 },
{ iptraceID_ETHERNET_RX_EVENT_LOST, ( const uint8_t * const ) "Count of lost Ethenret Rx events (event queue full?)",prvIncrementEventCount, 0 },
{ iptraceID_STACK_TX_EVENT_LOST, ( const uint8_t * const ) "Count of lost IP stack events (event queue full?)", prvIncrementEventCount, 0 },
{ ipconfigID_BIND_FAILED, ( const uint8_t * const ) "Count of failed calls to bind()", prvIncrementEventCount, 0 },
{ iptraceID_RECVFROM_TIMEOUT, ( const uint8_t * const ) "Count of receive timeouts", prvIncrementEventCount, 0 },
{ iptraceID_SENDTO_DATA_TOO_LONG, ( const uint8_t * const ) "Count of failed sends due to oversized payload", prvIncrementEventCount, 0 },
{ iptraceID_SENDTO_SOCKET_NOT_BOUND, ( const uint8_t * const ) "Count of failed sends due to unbound socket", prvIncrementEventCount, 0 },
{ iptraceID_NO_BUFFER_FOR_SENDTO, ( const uint8_t * const ) "Count of failed transmits due to timeout", prvIncrementEventCount, 0 },
{ iptraceID_WAIT_FOR_TX_DMA_DESCRIPTOR, ( const uint8_t * const ) "Number of times task had to wait to obtain a DMA Tx descriptor", prvIncrementEventCount, 0 },
{ iptraceID_FAILED_TO_NOTIFY_SELECT_GROUP, ( const uint8_t * const ) "Failed to notify select group", prvIncrementEventCount, 0 }
};
/*-----------------------------------------------------------*/
BaseType_t xExampleDebugStatEntries( void )
{
/* Return the number of entries in the xIPTraceValues[] table. */
return ( BaseType_t ) ( sizeof( xIPTraceValues ) / sizeof( xExampleDebugStatEntry_t ) );
}
/*-----------------------------------------------------------*/
void vExampleDebugStatUpdate( uint8_t ucIdentifier, uint32_t ulValue )
{
BaseType_t xIndex;
const BaseType_t xEntries = sizeof( xIPTraceValues ) / sizeof( xExampleDebugStatEntry_t );
/* Update an entry in the xIPTraceValues[] table. Each row in the table
includes a pointer to a function that performs the actual update. This
function just executes the update function from that table row. */
for( xIndex = 0; xIndex < xEntries; xIndex++ )
{
if( xIPTraceValues[ xIndex ].ucIdentifier == ucIdentifier )
{
xIPTraceValues[ xIndex ].vPerformAction( &( xIPTraceValues[ xIndex ].ulData ), ulValue );
break;
}
}
configASSERT( xIndex != xEntries );
}
/*-----------------------------------------------------------*/
static void prvIncrementEventCount( uint32_t *pulCurrentValue, uint32_t ulCount )
{
/* Each row in the xIPTraceValues[] table contains a pointer to a function
that updates the value for that row. Rows that simply increment an event
count point to this function. */
( void ) ulCount;
( *pulCurrentValue )++;
}
/*-----------------------------------------------------------*/
static void prvStoreLowest( uint32_t *pulCurrentValue, uint32_t ulCount )
{
/* Each row in the xIPTraceValues[] table contains a pointer to a function
that updates the value for that row. Rows that latch the lowest value
point to this function (for example, this function can be used to latch
the lowest number of network buffers that were available during the
execution of the stack). */
if( ulCount < *pulCurrentValue )
{
*pulCurrentValue = ulCount;
}
}
/*-----------------------------------------------------------*/
#endif /* configINCLUDE_DEMO_DEBUG_STATS == 1 */

View File

@ -0,0 +1,121 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*
* This file, along with DemoIPTrace.h, provides a basic example use of the
* FreeRTOS+UDP trace macros. The statistics gathered here can be viewed in
* the command line interface.
* See http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/UDP_IP_Trace.shtml
*/
#ifndef DEMO_IP_TRACE_MACROS_H
#define DEMO_IP_TRACE_MACROS_H
typedef void ( *vTraceAction_t )( uint32_t *, uint32_t );
/* Type that defines each statistic being gathered. */
typedef struct ExampleDebugStatEntry
{
uint8_t ucIdentifier; /* Unique identifier for statistic. */
const uint8_t * const pucDescription; /* Text description for the statistic. */
vTraceAction_t vPerformAction; /* Action to perform when the statistic is updated (increment counter, store minimum value, store maximum value, etc. */
uint32_t ulData; /* The meaning of this data is dependent on the trace macro ID. */
} xExampleDebugStatEntry_t;
/* Unique identifiers used to locate the entry for each trace macro in the
xIPTraceValues[] table defined in DemoIPTrace.c. */
#define iptraceID_NETWORK_INTERFACE_RECEIVE 0
#define iptraceID_NETWORK_INTERFACE_TRANSMIT 1
#define iptraceID_PACKET_DROPPED_TO_GENERATE_ARP 2
/* Do not change IDs above this line as the ID is shared with a FreeRTOS+Nabto
demo. */
#define iptraceID_NETWORK_BUFFER_OBTAINED 3
#define iptraceID_NETWORK_BUFFER_OBTAINED_FROM_ISR 4
#define iptraceID_NETWORK_EVENT_RECEIVED 5
#define iptraceID_FAILED_TO_OBTAIN_NETWORK_BUFFER 6
#define iptraceID_ARP_TABLE_ENTRY_EXPIRED 7
#define iptraceID_FAILED_TO_CREATE_SOCKET 8
#define iptraceID_RECVFROM_DISCARDING_BYTES 9
#define iptraceID_ETHERNET_RX_EVENT_LOST 10
#define iptraceID_STACK_TX_EVENT_LOST 11
#define ipconfigID_BIND_FAILED 12
#define iptraceID_RECVFROM_TIMEOUT 13
#define iptraceID_SENDTO_DATA_TOO_LONG 14
#define iptraceID_SENDTO_SOCKET_NOT_BOUND 15
#define iptraceID_NO_BUFFER_FOR_SENDTO 16
#define iptraceID_WAIT_FOR_TX_DMA_DESCRIPTOR 17
#define iptraceID_FAILED_TO_NOTIFY_SELECT_GROUP 18
/* It is possible to remove the trace macros using the
configINCLUDE_DEMO_DEBUG_STATS setting in FreeRTOSIPConfig.h. */
#if configINCLUDE_DEMO_DEBUG_STATS == 1
/* The trace macro definitions themselves. Any trace macros left undefined
will default to be empty macros. */
#define iptraceNETWORK_BUFFER_OBTAINED( pxBufferAddress ) vExampleDebugStatUpdate( iptraceID_NETWORK_BUFFER_OBTAINED, uxQueueMessagesWaiting( ( xQueueHandle ) xNetworkBufferSemaphore ) )
#define iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxBufferAddress ) vExampleDebugStatUpdate( iptraceID_NETWORK_BUFFER_OBTAINED, uxQueueMessagesWaiting( ( xQueueHandle ) xNetworkBufferSemaphore ) )
#define iptraceNETWORK_EVENT_RECEIVED( eEvent ) { \
uint16_t usSpace; \
usSpace = ( uint16_t ) uxQueueMessagesWaiting( xNetworkEventQueue ); \
/* Minus one as an event was removed before the space was queried. */ \
usSpace = ( ipconfigEVENT_QUEUE_LENGTH - usSpace ) - 1; \
vExampleDebugStatUpdate( iptraceID_NETWORK_EVENT_RECEIVED, usSpace ); \
}
#define iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER() vExampleDebugStatUpdate( iptraceID_FAILED_TO_OBTAIN_NETWORK_BUFFER, 0 )
#define iptraceARP_TABLE_ENTRY_EXPIRED( ulIPAddress ) vExampleDebugStatUpdate( iptraceID_ARP_TABLE_ENTRY_EXPIRED, 0 )
#define iptracePACKET_DROPPED_TO_GENERATE_ARP( ulIPAddress ) vExampleDebugStatUpdate( iptraceID_PACKET_DROPPED_TO_GENERATE_ARP, 0 )
#define iptraceFAILED_TO_CREATE_SOCKET() vExampleDebugStatUpdate( iptraceID_FAILED_TO_CREATE_SOCKET, 0 )
#define iptraceRECVFROM_DISCARDING_BYTES( xNumberOfBytesDiscarded ) vExampleDebugStatUpdate( iptraceID_RECVFROM_DISCARDING_BYTES, 0 )
#define iptraceETHERNET_RX_EVENT_LOST() vExampleDebugStatUpdate( iptraceID_ETHERNET_RX_EVENT_LOST, 0 )
#define iptraceSTACK_TX_EVENT_LOST( xEvent ) vExampleDebugStatUpdate( iptraceID_STACK_TX_EVENT_LOST, 0 )
#define iptraceBIND_FAILED( xSocket, usPort ) vExampleDebugStatUpdate( ipconfigID_BIND_FAILED, 0 )
#define iptraceNETWORK_INTERFACE_TRANSMIT() vExampleDebugStatUpdate( iptraceID_NETWORK_INTERFACE_TRANSMIT, 0 )
#define iptraceRECVFROM_TIMEOUT() vExampleDebugStatUpdate( iptraceID_RECVFROM_TIMEOUT, 0 )
#define iptraceSENDTO_DATA_TOO_LONG() vExampleDebugStatUpdate( iptraceID_SENDTO_DATA_TOO_LONG, 0 )
#define iptraceSENDTO_SOCKET_NOT_BOUND() vExampleDebugStatUpdate( iptraceID_SENDTO_SOCKET_NOT_BOUND, 0 )
#define iptraceNO_BUFFER_FOR_SENDTO() vExampleDebugStatUpdate( iptraceID_NO_BUFFER_FOR_SENDTO, 0 )
#define iptraceWAITING_FOR_TX_DMA_DESCRIPTOR() vExampleDebugStatUpdate( iptraceID_WAIT_FOR_TX_DMA_DESCRIPTOR, 0 )
#define iptraceFAILED_TO_NOTIFY_SELECT_GROUP( xSocket ) vExampleDebugStatUpdate( iptraceID_FAILED_TO_NOTIFY_SELECT_GROUP, 0 )
#define iptraceNETWORK_INTERFACE_RECEIVE() vExampleDebugStatUpdate( iptraceID_NETWORK_INTERFACE_RECEIVE, 0 )
/*
* The function that updates a line in the xIPTraceValues table.
*/
void vExampleDebugStatUpdate( uint8_t ucIdentifier, uint32_t ulValue );
/*
* Returns the number of entries in the xIPTraceValues table.
*/
BaseType_t xExampleDebugStatEntries( void );
#endif /* configINCLUDE_DEMO_DEBUG_STATS == 1 */
#endif /* DEMO_IP_TRACE_MACROS_H */

View File

@ -0,0 +1,119 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include <stdint.h>
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
* http://www.freertos.org/a00110.html
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 60 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the Win32 thread. */
#define configMAX_TASK_NAME_LEN ( 7 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_CO_ROUTINES 0
#define configUSE_MUTEXES 1
#define configCHECK_FOR_STACK_OVERFLOW 0 /* Not applicable to the Win32 port. */
#define configUSE_RECURSIVE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 0
#define configUSE_APPLICATION_TASK_TAG 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 0
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY 2
#define configTIMER_QUEUE_LENGTH 20
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
#define configMAX_PRIORITIES ( 7 )
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Hook functions */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTimerGetTimerTaskHandle 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xQueueGetMutexHolder 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xEventGroupSetBitsFromISR 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_xTaskAbortDelay 1
/* heap_4.c, */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 2048U * 1024U ) )
/* Allow RTOS objects to be created using RAM provided by the application writer. */
#define configSUPPORT_STATIC_ALLOCATION 1
/* Create RTOS objects using dynamically allocated RAM */
#define configSUPPORT_DYNAMIC_ALLOCATION 1
/* This demo makes use of one or more example stats formatting functions. These
format the raw data provided by the uxTaskGetSystemState() function in to human
readable ASCII form. See the notes in the implementation of vTaskList() within
FreeRTOS/Source/tasks.c for limitations. */
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
/* Run time stats gathering definitions. */
#define configGENERATE_RUN_TIME_STATS 0
/* Assert call defined for debug builds. */
extern void vAssertCalled(const char * pcFile, uint32_t ulLine);
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )
#endif /* FREERTOS_CONFIG_H */

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTOSDemo", "WIN32.vcxproj", "{C686325E-3261-42F7-AEB1-DDE5280E1CEB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|Win32.ActiveCfg = Debug|Win32
{C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|Win32.Build.0 = Debug|Win32
{C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|Win32.ActiveCfg = Release|Win32
{C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C686325E-3261-42F7-AEB1-DDE5280E1CEB}</ProjectGuid>
<ProjectName>RTOS_POSIX_Demo</ProjectName>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<TypeLibraryName>.\Debug/WIN32.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\FreeRTOS\Source\include;..\..\..\FreeRTOS\Source\portable\MSVC-MingW;..\..\..\FreeRTOS-Plus\Demo\FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator\lib\FreeRTOS-Plus-POSIX\include\portable\pc\windows;..\..\..\FreeRTOS-Plus\Demo\FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator\lib\FreeRTOS-Plus-POSIX\include\portable;..\..\..\FreeRTOS-Plus\Demo\FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator\lib\FreeRTOS-Plus-POSIX\include;..\..\..\FreeRTOS-Plus\Demo\FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator\lib\FreeRTOS-Plus-POSIX\source;..\..\..\FreeRTOS-Plus\Demo\FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator\lib\include\private;..\..\..\FreeRTOS-Plus\Demo\FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator\lib\third_party\win_pcap;..\..\..\FreeRTOS-Plus\Demo\FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator\lib\include;..\..\..\FreeRTOS-Plus\Demo\FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator;..\..\..\FreeRTOS\Demo\Common\ethernet\lwip-1.4.0\ports\win32\WinPCap;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0500;WINVER=0x400;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeaderOutputFile>.\Debug/WIN32.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
<ObjectFileName>.\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0c09</Culture>
</ResourceCompile>
<Link>
<OutputFile>.\Debug/RTOS_POSIX_demo.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Debug/WIN32.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Debug/WIN32.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<TypeLibraryName>.\Release/WIN32.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<PreprocessorDefinitions>_WINSOCKAPI_;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>.\Release/WIN32.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalIncludeDirectories>..\Common\Utils;..\Common\ethernet\lwip-1.4.0\ports\win32\WinPCap;..\Common\ethernet\lwip-1.4.0\src\include\ipv4;..\Common\ethernet\lwip-1.4.0\src\include;..\..\Source\include;..\..\Source\portable\MSVC-MingW;..\Common\ethernet\lwip-1.4.0\ports\win32\include;..\Common\Include;.\lwIP_Apps;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0c09</Culture>
</ResourceCompile>
<Link>
<OutputFile>.\Release/RTOSDemo.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ProgramDatabaseFile>.\Release/WIN32.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>..\Common\ethernet\lwip-1.4.0\ports\win32\WinPCap</AdditionalLibraryDirectories>
<AdditionalDependencies>wpcap.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release/WIN32.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\FreeRTOS\Source\croutine.c" />
<ClCompile Include="..\..\..\FreeRTOS\Source\event_groups.c" />
<ClCompile Include="..\..\..\FreeRTOS\Source\list.c" />
<ClCompile Include="..\..\..\FreeRTOS\Source\portable\MemMang\heap_4.c" />
<ClCompile Include="..\..\..\FreeRTOS\Source\portable\MSVC-MingW\port.c" />
<ClCompile Include="..\..\..\FreeRTOS\Source\queue.c" />
<ClCompile Include="..\..\..\FreeRTOS\Source\stream_buffer.c" />
<ClCompile Include="..\..\..\FreeRTOS\Source\tasks.c" />
<ClCompile Include="..\..\..\FreeRTOS\Source\timers.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_clock.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_mqueue.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_pthread.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_pthread_barrier.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_pthread_mutex.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_pthread_cond.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_sched.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_semaphore.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_timer.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_unistd.c" />
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_utils.c" />
<ClCompile Include="main.c">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="posix_demo.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\FreeRTOS\Source\portable\MSVC-MingW\portmacro.h" />
<ClInclude Include=".\lib\FreeRTOS-Plus-POSIX\include\FreeRTOS_POSIX.h" />
<ClInclude Include=".\lib\FreeRTOS-Plus-POSIX\include\FreeRTOS_POSIX_internal.h" />
<ClInclude Include=".\lib\FreeRTOS-Plus-POSIX\include\portable\FreeRTOS_POSIX_portable_default.h" />
<ClInclude Include=".\lib\FreeRTOS-Plus-POSIX\include\portable\pc\windows\FreeRTOS_POSIX_portable.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\errno.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\fcntl.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\mqueue.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\pthread.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\sched.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\semaphore.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\signal.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\sys\types.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\time.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\unistd.h" />
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\utils.h" />
<ClInclude Include=".\lib\include\private\aws_doubly_linked_list.h" />
<ClInclude Include="FreeRTOSConfig.h" />
<ClInclude Include="posix_demo.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="application_code">
<UniqueIdentifier>{34567deb-d5ab-4a56-8640-0aaec609521a}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
</Filter>
<Filter Include="lib">
<UniqueIdentifier>{e3396fdf-de1f-4cb9-975c-673cb9315287}</UniqueIdentifier>
</Filter>
<Filter Include="lib\include">
<UniqueIdentifier>{02f5b936-2f92-411d-89d3-985520c10e9d}</UniqueIdentifier>
</Filter>
<Filter Include="lib\include\FreeRTOS_POSIX">
<UniqueIdentifier>{1f6970f5-2901-4d3b-a119-86195fed3601}</UniqueIdentifier>
</Filter>
<Filter Include="lib\include\FreeRTOS_POSIX\sys">
<UniqueIdentifier>{63611657-d97d-479c-af87-69d6817b564d}</UniqueIdentifier>
</Filter>
<Filter Include="lib\FreeRTOS-Plus-POSIX">
<UniqueIdentifier>{7c2a7031-ca15-4d3e-838e-efe7b508f899}</UniqueIdentifier>
</Filter>
<Filter Include="lib\FreeRTOS-Plus-POSIX\include">
<UniqueIdentifier>{dddb94ad-d701-41db-ab34-8fd5b9b4d2db}</UniqueIdentifier>
</Filter>
<Filter Include="lib\FreeRTOS-Plus-POSIX\source">
<UniqueIdentifier>{db0fccd4-1177-4630-8a6d-b1ea48d0b0fa}</UniqueIdentifier>
</Filter>
<Filter Include="lib\FreeRTOS">
<UniqueIdentifier>{af3445a1-4908-4170-89ed-39345d90d30c}</UniqueIdentifier>
</Filter>
<Filter Include="lib\include\private">
<UniqueIdentifier>{26ccdf01-559e-4934-9311-bd1a25bdd658}</UniqueIdentifier>
</Filter>
<Filter Include="configuration_files">
<UniqueIdentifier>{19ff1a34-36de-4c48-9d10-3fb1fa0d1fa4}</UniqueIdentifier>
<Extensions>
</Extensions>
</Filter>
<Filter Include="lib\FreeRTOS\Portable">
<UniqueIdentifier>{88f409e6-d396-4ac5-94bd-7a99c914be46}</UniqueIdentifier>
</Filter>
<Filter Include="lib\FreeRTOS\Portable\MemMang">
<UniqueIdentifier>{a4b373f5-dc97-40ff-9b67-118253049621}</UniqueIdentifier>
</Filter>
<Filter Include="lib\FreeRTOS\Portable\MSVC-W">
<UniqueIdentifier>{0447c18c-e805-43d8-8b36-744f7c7fb88f}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>application_code</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_clock.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_mqueue.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_pthread.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_pthread_barrier.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_pthread_cond.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_pthread_mutex.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_sched.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_semaphore.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_timer.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_unistd.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include=".\lib\FreeRTOS-Plus-POSIX\source\FreeRTOS_POSIX_utils.c">
<Filter>lib\FreeRTOS-Plus-POSIX\source</Filter>
</ClCompile>
<ClCompile Include="..\..\..\FreeRTOS\Source\portable\MemMang\heap_4.c">
<Filter>lib\FreeRTOS\Portable\MemMang</Filter>
</ClCompile>
<ClCompile Include="..\..\..\FreeRTOS\Source\portable\MSVC-MingW\port.c">
<Filter>lib\FreeRTOS\Portable\MSVC-W</Filter>
</ClCompile>
<ClCompile Include="..\..\..\FreeRTOS\Source\croutine.c">
<Filter>lib\FreeRTOS</Filter>
</ClCompile>
<ClCompile Include="..\..\..\FreeRTOS\Source\event_groups.c">
<Filter>lib\FreeRTOS</Filter>
</ClCompile>
<ClCompile Include="..\..\..\FreeRTOS\Source\list.c">
<Filter>lib\FreeRTOS</Filter>
</ClCompile>
<ClCompile Include="..\..\..\FreeRTOS\Source\queue.c">
<Filter>lib\FreeRTOS</Filter>
</ClCompile>
<ClCompile Include="..\..\..\FreeRTOS\Source\stream_buffer.c">
<Filter>lib\FreeRTOS</Filter>
</ClCompile>
<ClCompile Include="..\..\..\FreeRTOS\Source\tasks.c">
<Filter>lib\FreeRTOS</Filter>
</ClCompile>
<ClCompile Include="..\..\..\FreeRTOS\Source\timers.c">
<Filter>lib\FreeRTOS</Filter>
</ClCompile>
<ClCompile Include="posix_demo.c">
<Filter>application_code</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="FreeRTOSConfig.h">
<Filter>configuration_files</Filter>
</ClInclude>
<ClInclude Include=".\lib\FreeRTOS-Plus-POSIX\include\FreeRTOS_POSIX.h">
<Filter>lib\FreeRTOS-Plus-POSIX\include</Filter>
</ClInclude>
<ClInclude Include=".\lib\FreeRTOS-Plus-POSIX\include\FreeRTOS_POSIX_internal.h">
<Filter>lib\FreeRTOS-Plus-POSIX\include</Filter>
</ClInclude>
<ClInclude Include=".\lib\FreeRTOS-Plus-POSIX\include\portable\pc\windows\FreeRTOS_POSIX_portable.h">
<Filter>lib\FreeRTOS-Plus-POSIX\include</Filter>
</ClInclude>
<ClInclude Include=".\lib\FreeRTOS-Plus-POSIX\include\portable\FreeRTOS_POSIX_portable_default.h">
<Filter>lib\FreeRTOS-Plus-POSIX\include</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\private\aws_doubly_linked_list.h">
<Filter>lib\include\private</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\errno.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\fcntl.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\mqueue.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\pthread.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\sched.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\semaphore.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\signal.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\time.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\unistd.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\utils.h">
<Filter>lib\include\FreeRTOS_POSIX</Filter>
</ClInclude>
<ClInclude Include=".\lib\include\FreeRTOS_POSIX\sys\types.h">
<Filter>lib\include\FreeRTOS_POSIX\sys</Filter>
</ClInclude>
<ClInclude Include="..\..\..\FreeRTOS\Source\portable\MSVC-MingW\portmacro.h">
<Filter>lib\FreeRTOS\Portable\MSVC-W</Filter>
</ClInclude>
<ClInclude Include="posix_demo.h">
<Filter>application_code</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>

View File

@ -0,0 +1,50 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX.h
* @brief FreeRTOS+POSIX header.
*
* This file must be included before all other FreeRTOS+POSIX includes.
*/
#ifndef _FREERTOS_POSIX_H_
#define _FREERTOS_POSIX_H_
/* FreeRTOS+POSIX platform-specific configuration headers. */
#include "FreeRTOS_POSIX_portable.h"
#include "portable/FreeRTOS_POSIX_portable_default.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "event_groups.h"
#include "semphr.h"
#include "task.h"
/* FreeRTOS+POSIX data types and internal structs. */
#include "FreeRTOS_POSIX/sys/types.h"
#include "FreeRTOS_POSIX_internal.h"
#endif /* _FREERTOS_POSIX_H_ */

View File

@ -0,0 +1,95 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_INTERNAL_H_
#define _FREERTOS_POSIX_INTERNAL_H_
/**
* @file FreeRTOS_POSIX_internal.h
* @brief Internal structs and initializers for FreeRTOS+POSIX.
*/
/* Amazon FreeRTOS includes. */
#include "aws_doubly_linked_list.h"
/**
* @brief Mutex attribute object.
*/
typedef struct pthread_mutexattr_internal
{
int iType; /**< Mutex type. */
} pthread_mutexattr_internal_t;
/**
* @brief Mutex.
*/
typedef struct pthread_mutex_internal
{
BaseType_t xIsInitialized; /**< Set to pdTRUE if this mutex is initialized, pdFALSE otherwise. */
StaticSemaphore_t xMutex; /**< FreeRTOS mutex. */
TaskHandle_t xTaskOwner; /**< Owner; used for deadlock detection and permission checks. */
pthread_mutexattr_internal_t xAttr; /**< Mutex attributes. */
} pthread_mutex_internal_t;
/**
* @brief Compile-time initializer of pthread_mutex_internal_t.
*/
#define FREERTOS_POSIX_MUTEX_INITIALIZER \
( &( ( pthread_mutex_internal_t ) \
{ \
.xIsInitialized = pdFALSE, \
.xMutex = { { 0 } }, \
.xTaskOwner = NULL, \
.xAttr = { .iType = 0 } \
} \
) \
)
/**
* @brief Condition variable.
*/
typedef struct pthread_cond_internal
{
BaseType_t xIsInitialized; /**< Set to pdTRUE if this condition variable is initialized, pdFALSE otherwise. */
StaticSemaphore_t xCondMutex; /**< Prevents concurrent accesses to iWaitingThreads. */
StaticSemaphore_t xCondWaitSemaphore; /**< Threads block on this semaphore in pthread_cond_wait. */
int iWaitingThreads; /**< The number of threads currently waiting on this condition variable. */
} pthread_cond_internal_t;
/**
* @brief Compile-time initializer of pthread_cond_internal_t.
*/
#define FREERTOS_POSIX_COND_INITIALIZER \
( &( ( pthread_cond_internal_t ) \
{ \
.xIsInitialized = pdFALSE, \
.xCondMutex = { { 0 } }, \
.xCondWaitSemaphore = { { 0 } },\
.iWaitingThreads = 0 \
} \
) \
)
#endif /* _FREERTOS_POSIX_INTERNAL_H_ */

View File

@ -0,0 +1,138 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_portable_default.h
* @brief Defaults for port-specific configuration of FreeRTOS+POSIX.
*/
#ifndef _FREERTOS_POSIX_PORTABLE_DEFAULT_H_
#define _FREERTOS_POSIX_PORTABLE_DEFAULT_H_
/**
* @brief The FreeRTOS task name given to pthreads.
*/
#ifndef posixconfigPTHREAD_TASK_NAME
#define posixconfigPTHREAD_TASK_NAME "pthread"
#endif
/**
* @brief the FreeRTOS timer name given to POSIX timers.
*/
#ifndef posixconfigTIMER_NAME
#define posixconfigTIMER_NAME "timer"
#endif
/**
* @defgroup Defaults for POSIX message queue implementation.
*/
/**@{ */
#ifndef posixconfigMQ_MAX_MESSAGES
#define posixconfigMQ_MAX_MESSAGES 10 /**< Maximum number of messages in an mq at one time. */
#endif
#ifndef posixconfigMQ_MAX_SIZE
#define posixconfigMQ_MAX_SIZE 128 /**< Maximum size (in bytes) of each message. */
#endif
/**@} */
/**
* @defgroup POSIX implementation-dependent constants usually defined in limits.h.
*
* They are defined here to provide portability between platforms.
*/
/**@{ */
#ifndef PTHREAD_STACK_MIN
#define PTHREAD_STACK_MIN configMINIMAL_STACK_SIZE * sizeof( StackType_t ) /**< Minimum size in bytes of thread stack storage. */
#endif
#ifndef NAME_MAX
#define NAME_MAX 64 /**< Maximum number of bytes in a filename (not including terminating null). */
#endif
#ifndef SEM_VALUE_MAX
#define SEM_VALUE_MAX 0xFFFFU /**< Maximum value of a sem_t. */
#endif
/**@} */
/**
* @defgroup Enable typedefs of POSIX types.
*
* Set these values to 1 or 0 to enable or disable the typedefs, respectively.
* These typedefs should only be disabled if they conflict with system typedefs.
*/
/**@{ */
#ifndef posixconfigENABLE_CLOCK_T
#define posixconfigENABLE_CLOCK_T 1 /**< clock_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_CLOCKID_T
#define posixconfigENABLE_CLOCKID_T 1 /**< clockid_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_MODE_T
#define posixconfigENABLE_MODE_T 1 /**< mode_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_PID_T
#define posixconfigENABLE_PID_T 1 /**< pid_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_PTHREAD_ATTR_T
#define posixconfigENABLE_PTHREAD_ATTR_T 1 /**< pthread_attr_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_PTHREAD_COND_T
#define posixconfigENABLE_PTHREAD_COND_T 1 /**< pthread_cond_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_PTHREAD_CONDATTR_T
#define posixconfigENABLE_PTHREAD_CONDATTR_T 1 /**< pthread_condattr_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_PTHREAD_MUTEX_T
#define posixconfigENABLE_PTHREAD_MUTEX_T 1 /**< pthread_mutex_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_PTHREAD_MUTEXATTR_T
#define posixconfigENABLE_PTHREAD_MUTEXATTR_T 1 /**< pthread_mutexattr_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_PTHREAD_T
#define posixconfigENABLE_PTHREAD_T 1 /**< pthread_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_SSIZE_T
#define posixconfigENABLE_SSIZE_T 1 /**< ssize_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_TIME_T
#define posixconfigENABLE_TIME_T 1 /**< time_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_TIMER_T
#define posixconfigENABLE_TIMER_T 1 /**< timer_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_USECONDS_T
#define posixconfigENABLE_USECONDS_T 1 /**< useconds_t in sys/types.h */
#endif
#ifndef posixconfigENABLE_TIMESPEC
#define posixconfigENABLE_TIMESPEC 1 /**< struct timespec in time.h */
#endif
#ifndef posixconfigENABLE_ITIMERSPEC
#define posixconfigENABLE_ITIMERSPEC 1 /**< struct itimerspec in time.h */
#endif
#ifndef posixconfigENABLE_TM
#define posixconfigENABLE_TM 1 /**< struct tm in time.h */
#endif
/**@} */
#endif /* ifndef _FREERTOS_POSIX_PORTABLE_DEFAULT_H_ */

View File

@ -0,0 +1,53 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_portable.h
* @brief Port-specific configuration of FreeRTOS+POSIX.
*/
#ifndef _FREERTOS_POSIX_PORTABLE_H_
#define _FREERTOS_POSIX_PORTABLE_H_
/* ESP-IDF already defines the following types. */
#define posixconfigENABLE_CLOCK_T 0
#define posixconfigENABLE_CLOCKID_T 0
#define posixconfigENABLE_MODE_T 0
#define posixconfigENABLE_PTHREAD_ATTR_T 0
#define posixconfigENABLE_PTHREAD_COND_T 0
#define posixconfigENABLE_PTHREAD_CONDATTR_T 0
#define posixconfigENABLE_PTHREAD_MUTEX_T 0
#define posixconfigENABLE_PTHREAD_MUTEXATTR_T 0
#define posixconfigENABLE_PTHREAD_T 0
#define posixconfigENABLE_TIME_T 0
#define posixconfigENABLE_TIMER_T 0
#define posixconfigENABLE_TIMESPEC 0
#define posixconfigENABLE_ITIMERSPEC 0
/* ESP-IDF already provides the header sched.h. Exclude them by
* activating the double inclusion guards. */
#define _FREERTOS_POSIX_SCHED_H_
#endif /* _FREERTOS_POSIX_PORTABLE_H_ */

View File

@ -0,0 +1,50 @@
/*
* Amazon FreeRTOS+POSIX V1.0.1
* Copyright (C) 2018 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_POSIX_portable.h
* @brief Port-specific configuration of FreeRTOS+POSIX.
*/
#ifndef _FREERTOS_POSIX_PORTABLE_H_
#define _FREERTOS_POSIX_PORTABLE_H_
/* Microchip includes. */
#include <sys/types.h>
/* Microchip already typedefs the following types. */
#define posixconfigENABLE_MODE_T 0
#define posixconfigENABLE_PID_T 0
#define posixconfigENABLE_SSIZE_T 0
#define posixconfigENABLE_USECONDS_T 0
/* Microchip -mnewlib compiler option supports these types. */
#define posixconfigENABLE_TIMESPEC 0
#define posixconfigENABLE_ITIMERSPEC 0
#define posixconfigENABLE_CLOCKID_T 0
#define posixconfigENABLE_TIME_T 0
#define posixconfigENABLE_TIMER_T 0
#endif /* _FREERTOS_POSIX_PORTABLE_H_ */

View File

@ -0,0 +1,37 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_portable.h
* @brief Port-specific configuration of FreeRTOS+POSIX.
*/
#ifndef _FREERTOS_POSIX_PORTABLE_H_
#define _FREERTOS_POSIX_PORTABLE_H_
/* This port uses the defaults in FreeRTOS_POSIX_portable_default.h, so this
* file is empty. */
#endif /* _FREERTOS_POSIX_PORTABLE_H_ */

View File

@ -0,0 +1,37 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_portable.h
* @brief Port-specific configuration of FreeRTOS+POSIX.
*/
#ifndef _FREERTOS_POSIX_PORTABLE_H_
#define _FREERTOS_POSIX_PORTABLE_H_
/* This port uses the defaults in FreeRTOS_POSIX_portable_default.h, so this
* file is empty. */
#endif /* _FREERTOS_POSIX_PORTABLE_H_ */

View File

@ -0,0 +1,37 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_portable.h
* @brief Port-specific configuration of FreeRTOS+POSIX.
*/
#ifndef _FREERTOS_POSIX_PORTABLE_H_
#define _FREERTOS_POSIX_PORTABLE_H_
/* This port uses the defaults in FreeRTOS_POSIX_portable_default.h, so this
* file is empty. */
#endif /* _FREERTOS_POSIX_PORTABLE_H_ */

View File

@ -0,0 +1,37 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_portable.h
* @brief Port-specific configuration of FreeRTOS+POSIX.
*/
#ifndef _FREERTOS_POSIX_PORTABLE_H_
#define _FREERTOS_POSIX_PORTABLE_H_
/* This port uses the defaults in FreeRTOS_POSIX_portable_default.h, so this
* file is empty. */
#endif /* _FREERTOS_POSIX_PORTABLE_H_ */

View File

@ -0,0 +1,291 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_clock.c
* @brief Implementation of clock functions in time.h
*/
/* C standard library includes. */
#include <stddef.h>
#include <string.h>
#include <stdio.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/errno.h"
#include "FreeRTOS_POSIX/time.h"
#include "FreeRTOS_POSIX/utils.h"
/*-----------------------------------------------------------*/
clock_t clock( void )
{
/* Return the amount of time since the scheduler started that wasn't spent
* in the idle task. */
return ( clock_t ) ( xTaskGetTickCount() - xTaskGetIdleTickCount() );
}
/*-----------------------------------------------------------*/
int clock_getcpuclockid( pid_t pid,
clockid_t * clock_id )
{
/* Silence warnings about unused parameters. */
( void ) pid;
( void ) clock_id;
return EPERM;
}
/*-----------------------------------------------------------*/
int clock_getres( clockid_t clock_id,
struct timespec * res )
{
/* Silence warnings about unused parameters. */
( void ) clock_id;
/* Convert FreeRTOS tick resolution as timespec. */
if( res != NULL )
{
res->tv_sec = 0;
res->tv_nsec = NANOSECONDS_PER_TICK;
}
return 0;
}
/*-----------------------------------------------------------*/
int clock_gettime( clockid_t clock_id,
struct timespec * tp )
{
TimeOut_t xCurrentTime = { 0 };
int iStatus = 0;
/* Intermediate variable used to convert TimeOut_t to struct timespec.
* Also used to detect overflow issues. It must be unsigned because the
* behavior of signed integer overflow is undefined. */
uint64_t ullTickCount = 0ULL;
/* Silence warnings about unused parameters. */
( void ) clock_id;
if( iStatus == 0 )
{
/* Get the current tick count and overflow count. vTaskSetTimeOutState()
* is used to get these values because they are both static in tasks.c. */
vTaskSetTimeOutState( &xCurrentTime );
/* Adjust the tick count for the number of times a TickType_t has overflowed.
* portMAX_DELAY should be the maximum value of a TickType_t. */
ullTickCount = ( uint64_t ) ( xCurrentTime.xOverflowCount ) << ( sizeof( TickType_t ) * 8 );
/* Add the current tick count. */
ullTickCount += xCurrentTime.xTimeOnEntering;
/* Convert ullTickCount to timespec. */
UTILS_NanosecondsToTimespec( ( int64_t ) ullTickCount * NANOSECONDS_PER_TICK, tp );
}
return iStatus;
}
/*-----------------------------------------------------------*/
int clock_nanosleep( clockid_t clock_id,
int flags,
const struct timespec * rqtp,
struct timespec * rmtp )
{
int iStatus = 0;
TickType_t xSleepTime = 0;
/* Silence warnings about unused parameters. */
( void ) clock_id;
( void ) rmtp;
( void ) flags; /* This is only ignored if INCLUDE_vTaskDelayUntil is 0. */
/* Check rqtp. */
if( UTILS_ValidateTimespec( rqtp ) == false )
{
iStatus = EINVAL;
}
if( iStatus == 0 )
{
/* Check for absolute time sleep. */
if( ( flags & TIMER_ABSTIME ) == TIMER_ABSTIME )
{
/* Get number of ticks until absolute time. */
if( UTILS_AbsoluteTimespecToTicks( rqtp, &xSleepTime ) == 0 )
{
/* Delay until absolute time if vTaskDelayUntil is available. */
#if ( INCLUDE_vTaskDelayUntil == 1 )
/* Get the current tick count. This variable isn't declared
* at the top of the function because it's only used and needed
* if vTaskDelayUntil is available. */
TickType_t xCurrentTicks = xTaskGetTickCount();
/* Delay until absolute time. */
vTaskDelayUntil( &xCurrentTicks, xSleepTime );
#else
/* If vTaskDelayUntil isn't available, ignore the TIMER_ABSTIME flag
* and sleep for a relative time. */
vTaskDelay( xSleepTime );
#endif
}
}
else
{
/* If TIMER_ABSTIME isn't specified, convert rqtp to ticks and
* sleep for a relative time. */
if( UTILS_TimespecToTicks( rqtp, &xSleepTime ) == 0 )
{
vTaskDelay( xSleepTime );
}
}
}
return iStatus;
}
/*-----------------------------------------------------------*/
int clock_settime( clockid_t clock_id,
const struct timespec * tp )
{
/* Silence warnings about unused parameters. */
( void ) clock_id;
( void ) tp;
/* This function is currently unsupported. It will always return -1 and
* set errno to EPERM. */
errno = EPERM;
return -1;
}
/*-----------------------------------------------------------*/
struct tm * localtime_r( const time_t * timer,
struct tm * result )
{
/* Silence warnings about unused parameters. */
( void ) timer;
( void ) result;
/* This function is only supported if the "custom" FreeRTOS+POSIX tm struct
* is used. */
#if ( posixconfigENABLE_TM == 0 )
errno = ENOTSUP;
return NULL;
#else
/* Zero the tm, then store the FreeRTOS tick count. The input parameter
* timer isn't used. */
( void ) memset( result, 0x00, sizeof( struct tm ) );
result->tm_tick = ( time_t ) xTaskGetTickCount();
return result;
#endif
}
/*-----------------------------------------------------------*/
int nanosleep( const struct timespec * rqtp,
struct timespec * rmtp )
{
int iStatus = 0;
TickType_t xSleepTime = 0;
/* Silence warnings about unused parameters. */
( void ) rmtp;
/* Check rqtp. */
if( UTILS_ValidateTimespec( rqtp ) == false )
{
errno = EINVAL;
iStatus = -1;
}
if( iStatus == 0 )
{
/* Convert rqtp to ticks and delay. */
if( UTILS_TimespecToTicks( rqtp, &xSleepTime ) == 0 )
{
vTaskDelay( xSleepTime );
}
}
return iStatus;
}
/*-----------------------------------------------------------*/
size_t strftime( char * s,
size_t maxsize,
const char * format,
const struct tm * timeptr )
{
int iStatus = 0;
size_t bytesPrinted = 0;
/* Silence warnings about unused parameters. */
( void ) format;
/* Print the time in the buffer. */
iStatus = snprintf( s, maxsize, "%ld", ( long int ) timeptr->tm_tick );
/* Check for encoding and size errors. */
if( ( iStatus > 0 ) && ( ( size_t ) iStatus < maxsize ) )
{
bytesPrinted = ( size_t ) iStatus;
}
return bytesPrinted;
}
/*-----------------------------------------------------------*/
time_t time( time_t * tloc )
{
/* Read the current FreeRTOS tick count and convert it to seconds. */
time_t xCurrentTime = ( time_t ) ( xTaskGetTickCount() / configTICK_RATE_HZ );
/* Set the output parameter if provided. */
if( tloc != NULL )
{
*tloc = xCurrentTime;
}
return xCurrentTime;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,885 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_mqueue.c
* @brief Implementation of message queue functions in mqueue.h
*/
/* C standard library includes. */
#include <string.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/errno.h"
#include "FreeRTOS_POSIX/fcntl.h"
#include "FreeRTOS_POSIX/mqueue.h"
#include "FreeRTOS_POSIX/utils.h"
/**
* @brief Element of the FreeRTOS queues that store mq data.
*/
typedef struct QueueElement
{
char * pcData; /**< Data in queue. Type char* to match msg_ptr. */
size_t xDataSize; /**< Size of data pointed by pcData. */
} QueueElement_t;
/**
* @brief Data structure of an mq.
*
* FreeRTOS isn't guaranteed to have a file-like abstraction, so message
* queues in this implementation are stored as a linked list (in RAM).
*/
typedef struct QueueListElement
{
Link_t xLink; /**< Pointer to the next element in the list. */
QueueHandle_t xQueue; /**< FreeRTOS queue handle. */
size_t xOpenDescriptors; /**< Number of threads that have opened this queue. */
char * pcName; /**< Null-terminated queue name. */
struct mq_attr xAttr; /**< Queue attibutes. */
BaseType_t xPendingUnlink; /**< If pdTRUE, this queue will be unlinked once all descriptors close. */
} QueueListElement_t;
/*-----------------------------------------------------------*/
/**
* @brief Convert an absolute timespec into a tick timeout, taking into account
* queue flags.
*
* @param[in] lMessageQueueFlags Message queue flags to consider.
* @param[in] pxAbsoluteTimeout The absolute timespec to convert.
* @param[out] pxTimeoutTicks Output parameter of the timeout in ticks.
*
* @return 0 if successful; EINVAL if pxAbsoluteTimeout is invalid, or ETIMEDOUT
* if pxAbsoluteTimeout is in the past.
*/
static int prvCalculateTickTimeout( long lMessageQueueFlags,
const struct timespec * const pxAbsoluteTimeout,
TickType_t * pxTimeoutTicks );
/**
* @brief Add a new queue to the queue list.
*
* @param[out] ppxMessageQueue Pointer to new queue.
* @param[in] pxAttr mq_attr of the new queue.
* @param[in] pcName Name of new queue.
* @param[in] xNameLength Length of pcName.
*
* @return pdTRUE if the queue is found; pdFALSE otherwise.
*/
static BaseType_t prvCreateNewMessageQueue( QueueListElement_t ** ppxMessageQueue,
const struct mq_attr * const pxAttr,
const char * const pcName,
size_t xNameLength );
/**
* @brief Free all the resources used by a message queue.
*
* @param[out] pxMessageQueue Pointer to queue to free.
*
* @return nothing
*/
static void prvDeleteMessageQueue( const QueueListElement_t * const pxMessageQueue );
/**
* @brief Attempt to find the queue identified by pcName or xMqId in the queue list.
*
* Matches queues by pcName first; if pcName is NULL, matches by xMqId.
* @param[out] ppxQueueListElement Output parameter set when queue is found.
* @param[in] pcName A queue name to match.
* @param[in] xMessageQueueDescriptor A queue descriptor to match.
*
* @return pdTRUE if the queue is found; pdFALSE otherwise.
*/
static BaseType_t prvFindQueueInList( QueueListElement_t ** const ppxQueueListElement,
const char * const pcName,
mqd_t xMessageQueueDescriptor );
/**
* @brief Initialize the queue list.
*
* Performs initialization of the queue list mutex and queue list head.
*
* @return nothing
*/
static void prvInitializeQueueList( void );
/**
* @brief Checks that pcName is a valid name for a message queue.
*
* Also outputs the length of pcName.
* @param[in] pcName The name to check.
* @param[out] pxNameLength Output parameter for name length.
*
* @return pdTRUE if the name is valid; pdFALSE otherwise.
*/
static BaseType_t prvValidateQueueName( const char * const pcName,
size_t * pxNameLength );
/**
* @brief Guards access to the list of message queues.
*/
static StaticSemaphore_t xQueueListMutex = { { 0 } };
/**
* @brief Head of the linked list of queues.
*/
static Link_t xQueueListHead = { 0 };
/*-----------------------------------------------------------*/
static int prvCalculateTickTimeout( long lMessageQueueFlags,
const struct timespec * const pxAbsoluteTimeout,
TickType_t * pxTimeoutTicks )
{
int iStatus = 0;
/* Check for nonblocking queue. */
if( lMessageQueueFlags & O_NONBLOCK )
{
/* No additional checks are done for nonblocking queues. Timeout is 0. */
*pxTimeoutTicks = 0;
}
else
{
/* No absolute timeout given. Block forever. */
if( pxAbsoluteTimeout == NULL )
{
*pxTimeoutTicks = portMAX_DELAY;
}
else
{
/* Check that the given timespec is valid. */
if( UTILS_ValidateTimespec( pxAbsoluteTimeout ) == false )
{
iStatus = EINVAL;
}
/* Convert absolute timespec to ticks. */
if( ( iStatus == 0 ) &&
( UTILS_AbsoluteTimespecToTicks( pxAbsoluteTimeout, pxTimeoutTicks ) != 0 ) )
{
iStatus = ETIMEDOUT;
}
}
}
return iStatus;
}
/*-----------------------------------------------------------*/
static BaseType_t prvCreateNewMessageQueue( QueueListElement_t ** ppxMessageQueue,
const struct mq_attr * const pxAttr,
const char * const pcName,
size_t xNameLength )
{
BaseType_t xStatus = pdTRUE;
/* Allocate space for a new queue element. */
*ppxMessageQueue = pvPortMalloc( sizeof( QueueListElement_t ) );
/* Check that memory allocation succeeded. */
if( *ppxMessageQueue == NULL )
{
xStatus = pdFALSE;
}
/* Create the FreeRTOS queue. */
if( xStatus == pdTRUE )
{
( *ppxMessageQueue )->xQueue =
xQueueCreate( pxAttr->mq_maxmsg, sizeof( QueueElement_t ) );
/* Check that queue creation succeeded. */
if( ( *ppxMessageQueue )->xQueue == NULL )
{
vPortFree( *ppxMessageQueue );
xStatus = pdFALSE;
}
}
if( xStatus == pdTRUE )
{
/* Allocate space for the queue name plus null-terminator. */
( *ppxMessageQueue )->pcName = pvPortMalloc( xNameLength + 1 );
/* Check that memory was successfully allocated for queue name. */
if( ( *ppxMessageQueue )->pcName == NULL )
{
vQueueDelete( ( *ppxMessageQueue )->xQueue );
vPortFree( *ppxMessageQueue );
xStatus = pdFALSE;
}
else
{
/* Copy queue name. Copying xNameLength+1 will cause strncpy to add
* the null-terminator. */
( void ) strncpy( ( *ppxMessageQueue )->pcName, pcName, xNameLength + 1 );
}
}
if( xStatus == pdTRUE )
{
/* Copy attributes. */
( *ppxMessageQueue )->xAttr = *pxAttr;
/* A newly-created queue will have 1 open descriptor for it. */
( *ppxMessageQueue )->xOpenDescriptors = 1;
/* A newly-created queue will not be pending unlink. */
( *ppxMessageQueue )->xPendingUnlink = pdFALSE;
/* Add the new queue to the list. */
listADD( &xQueueListHead, &( *ppxMessageQueue )->xLink );
}
return xStatus;
}
/*-----------------------------------------------------------*/
static void prvDeleteMessageQueue( const QueueListElement_t * const pxMessageQueue )
{
QueueElement_t xQueueElement = { 0 };
/* Free all data in the queue. It's assumed that no more data will be added
* to the queue, so xQueueReceive does not block. */
while( xQueueReceive( pxMessageQueue->xQueue,
( void * ) &xQueueElement,
0 ) == pdTRUE )
{
vPortFree( xQueueElement.pcData );
}
/* Free memory used by this message queue. */
vQueueDelete( pxMessageQueue->xQueue );
vPortFree( ( void * ) pxMessageQueue->pcName );
vPortFree( ( void * ) pxMessageQueue );
}
/*-----------------------------------------------------------*/
static BaseType_t prvFindQueueInList( QueueListElement_t ** const ppxQueueListElement,
const char * const pcName,
mqd_t xMessageQueueDescriptor )
{
Link_t * pxQueueListLink = NULL;
QueueListElement_t * pxMessageQueue = NULL;
BaseType_t xQueueFound = pdFALSE;
/* Iterate through the list of queues. */
listFOR_EACH( pxQueueListLink, &xQueueListHead )
{
pxMessageQueue = listCONTAINER( pxQueueListLink, QueueListElement_t, xLink );
/* Match by name first if provided. */
if( ( pcName != NULL ) && ( strcmp( pxMessageQueue->pcName, pcName ) == 0 ) )
{
xQueueFound = pdTRUE;
break;
}
/* If name doesn't match, match by descriptor. */
else
{
if( ( mqd_t ) pxMessageQueue == xMessageQueueDescriptor )
{
xQueueFound = pdTRUE;
break;
}
}
}
/* If the queue was found, set the output parameter. */
if( ( xQueueFound == pdTRUE ) && ( ppxQueueListElement != NULL ) )
{
*ppxQueueListElement = pxMessageQueue;
}
return xQueueFound;
}
/*-----------------------------------------------------------*/
static void prvInitializeQueueList( void )
{
/* Keep track of whether the queue list has been initialized. */
static BaseType_t xQueueListInitialized = pdFALSE;
/* Check if queue list needs to be initialized. */
if( xQueueListInitialized == pdFALSE )
{
/* Initialization must be in a critical section to prevent two threads
* from initializing at the same time. */
taskENTER_CRITICAL();
/* Check again that queue list is still uninitialized, i.e. it wasn't
* initialized while this function was waiting to enter the critical
* section. */
if( xQueueListInitialized == pdFALSE )
{
/* Initialize the queue list mutex and list head. */
( void ) xSemaphoreCreateMutexStatic( &xQueueListMutex );
listINIT_HEAD( &xQueueListHead );
xQueueListInitialized = pdTRUE;
}
/* Exit the critical section. */
taskEXIT_CRITICAL();
}
}
/*-----------------------------------------------------------*/
static BaseType_t prvValidateQueueName( const char * const pcName,
size_t * pxNameLength )
{
BaseType_t xStatus = pdTRUE;
size_t xNameLength = 0;
/* All message queue names must start with '/'. */
if( pcName[ 0 ] != '/' )
{
xStatus = pdFALSE;
}
else
{
/* Get the length of pcName, excluding the first '/' and null-terminator. */
xNameLength = UTILS_strnlen( pcName, NAME_MAX + 2 );
if( xNameLength == NAME_MAX + 2 )
{
/* Name too long. */
xStatus = pdFALSE;
}
else
{
/* Name length passes, set output parameter. */
*pxNameLength = xNameLength;
}
}
return xStatus;
}
/*-----------------------------------------------------------*/
int mq_close( mqd_t mqdes )
{
int iStatus = 0;
QueueListElement_t * pxMessageQueue = ( QueueListElement_t * ) mqdes;
BaseType_t xQueueRemoved = pdFALSE;
/* Initialize the queue list, if needed. */
prvInitializeQueueList();
/* Lock the mutex that guards access to the queue list. This call will
* never fail because it blocks forever. */
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &xQueueListMutex, portMAX_DELAY );
/* Attempt to find the message queue based on the given descriptor. */
if( prvFindQueueInList( NULL, NULL, mqdes ) == pdTRUE )
{
/* Decrement the number of open descriptors. */
if(pxMessageQueue->xOpenDescriptors > 0)
{
pxMessageQueue->xOpenDescriptors--;
}
/* Check if the queue has any more open descriptors. */
if( pxMessageQueue->xOpenDescriptors == 0 )
{
/* If no open descriptors remain and mq_unlink has already been called,
* remove the queue. */
if( pxMessageQueue->xPendingUnlink == pdTRUE )
{
listREMOVE( &pxMessageQueue->xLink );
/* Set the flag to delete the queue. Deleting the queue is deferred
* until xQueueListMutex is released. */
xQueueRemoved = pdTRUE;
}
/* Otherwise, wait for the call to mq_unlink. */
else
{
pxMessageQueue->xPendingUnlink = pdTRUE;
}
}
}
else
{
/* Queue not found; bad descriptor. */
errno = EBADF;
iStatus = -1;
}
/* Release the mutex protecting the queue list. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &xQueueListMutex );
/* Delete all resources used by the queue if needed. */
if( xQueueRemoved == pdTRUE )
{
prvDeleteMessageQueue( pxMessageQueue );
}
return iStatus;
}
/*-----------------------------------------------------------*/
int mq_getattr( mqd_t mqdes,
struct mq_attr * mqstat )
{
int iStatus = 0;
QueueListElement_t * pxMessageQueue = ( QueueListElement_t * ) mqdes;
/* Lock the mutex that guards access to the queue list. This call will
* never fail because it blocks forever. */
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &xQueueListMutex, portMAX_DELAY );
/* Find the mq referenced by mqdes. */
if( prvFindQueueInList( NULL, NULL, mqdes ) == pdTRUE )
{
/* Update the number of messages in the queue and copy the attributes
* into mqstat. */
pxMessageQueue->xAttr.mq_curmsgs = ( long ) uxQueueMessagesWaiting( pxMessageQueue->xQueue );
*mqstat = pxMessageQueue->xAttr;
}
else
{
/* Queue not found; bad descriptor. */
errno = EBADF;
iStatus = -1;
}
/* Release the mutex protecting the queue list. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &xQueueListMutex );
return iStatus;
}
/*-----------------------------------------------------------*/
mqd_t mq_open( const char * name,
int oflag,
mode_t mode,
struct mq_attr * attr )
{
mqd_t xMessageQueue = NULL;
size_t xNameLength = 0;
/* Default mq_attr. */
struct mq_attr xQueueCreationAttr =
{
.mq_flags = 0,
.mq_maxmsg = posixconfigMQ_MAX_MESSAGES,
.mq_msgsize = posixconfigMQ_MAX_SIZE,
.mq_curmsgs = 0
};
/* Silence warnings about unused parameters. */
( void ) mode;
/* Initialize the queue list, if needed. */
prvInitializeQueueList();
/* Check queue name. */
if( prvValidateQueueName( name, &xNameLength ) == pdFALSE )
{
/* Invalid name. */
errno = EINVAL;
xMessageQueue = ( mqd_t ) -1;
}
/* Check attributes, if O_CREATE is specified and attr is given. */
if( xMessageQueue == NULL )
{
if( ( oflag & O_CREAT ) && ( attr != NULL ) && ( ( attr->mq_maxmsg <= 0 ) || ( attr->mq_msgsize <= 0 ) ) )
{
/* Invalid mq_attr.mq_maxmsg or mq_attr.mq_msgsize. */
errno = EINVAL;
xMessageQueue = ( mqd_t ) -1;
}
}
if( xMessageQueue == NULL )
{
/* Lock the mutex that guards access to the queue list. This call will
* never fail because it blocks forever. */
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &xQueueListMutex, portMAX_DELAY );
/* Search the queue list to check if the queue exists. */
if( prvFindQueueInList( ( QueueListElement_t ** ) &xMessageQueue,
name,
( mqd_t ) NULL ) == pdTRUE )
{
/* If the mq exists, check that this function wasn't called with
* O_CREAT and O_EXCL. */
if( ( oflag & O_EXCL ) && ( oflag & O_CREAT ) )
{
errno = EEXIST;
xMessageQueue = ( mqd_t ) -1;
}
else
{
/* Check if the mq has been unlinked and is pending removal. */
if( ( ( QueueListElement_t * ) xMessageQueue )->xPendingUnlink == pdTRUE )
{
/* Queue pending deletion. Don't allow it to be re-opened. */
errno = EINVAL;
xMessageQueue = ( mqd_t ) -1;
}
else
{
/* Increase count of open file descriptors for queue. */
( ( QueueListElement_t * ) xMessageQueue )->xOpenDescriptors++;
}
}
}
/* Queue does not exist. */
else
{
/* Only create the new queue if O_CREAT was specified. */
if( oflag & O_CREAT )
{
/* Copy attributes if provided. */
if( attr != NULL )
{
xQueueCreationAttr = *attr;
}
/* Copy oflags. */
xQueueCreationAttr.mq_flags = ( long ) oflag;
/* Create the new message queue. */
if( prvCreateNewMessageQueue( ( QueueListElement_t ** ) &xMessageQueue,
&xQueueCreationAttr,
name,
xNameLength ) == pdFALSE )
{
errno = ENOSPC;
xMessageQueue = ( mqd_t ) -1;
}
}
else
{
errno = ENOENT;
xMessageQueue = ( mqd_t ) -1;
}
}
/* Release the mutex protecting the queue list. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &xQueueListMutex );
}
return xMessageQueue;
}
/*-----------------------------------------------------------*/
ssize_t mq_receive( mqd_t mqdes,
char * msg_ptr,
size_t msg_len,
unsigned int * msg_prio )
{
return mq_timedreceive( mqdes, msg_ptr, msg_len, msg_prio, NULL );
}
/*-----------------------------------------------------------*/
int mq_send( mqd_t mqdes,
const char * msg_ptr,
size_t msg_len,
unsigned msg_prio )
{
return mq_timedsend( mqdes, msg_ptr, msg_len, msg_prio, NULL );
}
/*-----------------------------------------------------------*/
ssize_t mq_timedreceive( mqd_t mqdes,
char * msg_ptr,
size_t msg_len,
unsigned * msg_prio,
const struct timespec * abstime )
{
ssize_t xStatus = 0;
int iCalculateTimeoutReturn = 0;
TickType_t xTimeoutTicks = 0;
QueueListElement_t * pxMessageQueue = ( QueueListElement_t * ) mqdes;
QueueElement_t xReceiveData = { 0 };
/* Silence warnings about unused parameters. */
( void ) msg_prio;
/* Lock the mutex that guards access to the queue list. This call will
* never fail because it blocks forever. */
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &xQueueListMutex, portMAX_DELAY );
/* Find the mq referenced by mqdes. */
if( prvFindQueueInList( NULL, NULL, mqdes ) == pdFALSE )
{
/* Queue not found; bad descriptor. */
errno = EBADF;
xStatus = -1;
}
/* Verify that msg_len is large enough. */
if( xStatus == 0 )
{
if( msg_len < ( size_t ) pxMessageQueue->xAttr.mq_msgsize )
{
/* msg_len too small. */
errno = EMSGSIZE;
xStatus = -1;
}
}
if( xStatus == 0 )
{
/* Convert abstime to a tick timeout. */
iCalculateTimeoutReturn = prvCalculateTickTimeout( pxMessageQueue->xAttr.mq_flags,
abstime,
&xTimeoutTicks );
if( iCalculateTimeoutReturn != 0 )
{
errno = iCalculateTimeoutReturn;
xStatus = -1;
}
}
/* Release the mutex protecting the queue list. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &xQueueListMutex );
if( xStatus == 0 )
{
/* Receive data from the FreeRTOS queue. */
if( xQueueReceive( pxMessageQueue->xQueue,
&xReceiveData,
xTimeoutTicks ) == pdFALSE )
{
/* If queue receive fails, set the appropriate errno. */
if( pxMessageQueue->xAttr.mq_flags & O_NONBLOCK )
{
/* Set errno to EAGAIN for nonblocking mq. */
errno = EAGAIN;
}
else
{
/* Otherwise, set errno to ETIMEDOUT. */
errno = ETIMEDOUT;
}
xStatus = -1;
}
}
if( xStatus == 0 )
{
/* Get the length of data for return value. */
xStatus = ( ssize_t ) xReceiveData.xDataSize;
/* Copy received data into given buffer, then free it. */
( void ) memcpy( msg_ptr, xReceiveData.pcData, xReceiveData.xDataSize );
vPortFree( xReceiveData.pcData );
}
return xStatus;
}
/*-----------------------------------------------------------*/
int mq_timedsend( mqd_t mqdes,
const char * msg_ptr,
size_t msg_len,
unsigned int msg_prio,
const struct timespec * abstime )
{
int iStatus = 0, iCalculateTimeoutReturn = 0;
TickType_t xTimeoutTicks = 0;
QueueListElement_t * pxMessageQueue = ( QueueListElement_t * ) mqdes;
QueueElement_t xSendData = { 0 };
/* Silence warnings about unused parameters. */
( void ) msg_prio;
/* Lock the mutex that guards access to the queue list. This call will
* never fail because it blocks forever. */
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &xQueueListMutex, portMAX_DELAY );
/* Find the mq referenced by mqdes. */
if( prvFindQueueInList( NULL, NULL, mqdes ) == pdFALSE )
{
/* Queue not found; bad descriptor. */
errno = EBADF;
iStatus = -1;
}
/* Verify that mq_msgsize is large enough. */
if( iStatus == 0 )
{
if( msg_len > ( size_t ) pxMessageQueue->xAttr.mq_msgsize )
{
/* msg_len too large. */
errno = EMSGSIZE;
iStatus = -1;
}
}
if( iStatus == 0 )
{
/* Convert abstime to a tick timeout. */
iCalculateTimeoutReturn = prvCalculateTickTimeout( pxMessageQueue->xAttr.mq_flags,
abstime,
&xTimeoutTicks );
if( iCalculateTimeoutReturn != 0 )
{
errno = iCalculateTimeoutReturn;
iStatus = -1;
}
}
/* Release the mutex protecting the queue list. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &xQueueListMutex );
/* Allocate memory for the message. */
if( iStatus == 0 )
{
xSendData.xDataSize = msg_len;
xSendData.pcData = pvPortMalloc( msg_len );
/* Check that memory allocation succeeded. */
if( xSendData.pcData == NULL )
{
/* msg_len too large. */
errno = EMSGSIZE;
iStatus = -1;
}
else
{
/* Copy the data to send. */
( void ) memcpy( xSendData.pcData, msg_ptr, msg_len );
}
}
if( iStatus == 0 )
{
/* Send data to the FreeRTOS queue. */
if( xQueueSend( pxMessageQueue->xQueue,
&xSendData,
xTimeoutTicks ) == pdFALSE )
{
/* If queue send fails, set the appropriate errno. */
if( pxMessageQueue->xAttr.mq_flags & O_NONBLOCK )
{
/* Set errno to EAGAIN for nonblocking mq. */
errno = EAGAIN;
}
else
{
/* Otherwise, set errno to ETIMEDOUT. */
errno = ETIMEDOUT;
}
/* Free the allocated queue data. */
vPortFree( xSendData.pcData );
iStatus = -1;
}
}
return iStatus;
}
/*-----------------------------------------------------------*/
int mq_unlink( const char * name )
{
int iStatus = 0;
size_t xNameSize = 0;
BaseType_t xQueueRemoved = pdFALSE;
QueueListElement_t * pxMessageQueue = NULL;
/* Initialize the queue list, if needed. */
prvInitializeQueueList();
/* Check queue name. */
if( prvValidateQueueName( name, &xNameSize ) == pdFALSE )
{
/* Error with mq name. */
errno = EINVAL;
iStatus = -1;
}
if( iStatus == 0 )
{
/* Lock the mutex that guards access to the queue list. This call will
* never fail because it blocks forever. */
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &xQueueListMutex, portMAX_DELAY );
/* Check if the named queue exists. */
if( prvFindQueueInList( &pxMessageQueue, name, ( mqd_t ) NULL ) == pdTRUE )
{
/* If the queue exists and there are no open descriptors to it,
* remove it from the list. */
if( pxMessageQueue->xOpenDescriptors == 0 )
{
listREMOVE( &pxMessageQueue->xLink );
/* Set the flag to delete the queue. Deleting the queue is deferred
* until xQueueListMutex is released. */
xQueueRemoved = pdTRUE;
}
else
{
/* If the queue has open descriptors, set the pending unlink flag
* so that mq_close will free its resources. */
pxMessageQueue->xPendingUnlink = pdTRUE;
}
}
else
{
/* The named message queue doesn't exist. */
errno = ENOENT;
iStatus = -1;
}
/* Release the mutex protecting the queue list. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &xQueueListMutex );
}
/* Delete all resources used by the queue if needed. */
if( xQueueRemoved == pdTRUE )
{
prvDeleteMessageQueue( pxMessageQueue );
}
return iStatus;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,485 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_pthread.c
* @brief Implementation of thread functions in pthread.h
*/
/* C standard library includes. */
#include <stddef.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/errno.h"
#include "FreeRTOS_POSIX/pthread.h"
/**
* @brief Thread attribute object.
*/
typedef struct pthread_attr_internal
{
size_t xStackSize; /**< Stack size. */
int iDetachState; /**< Detach state: joinable or detached. */
struct sched_param xSchedParam; /**< Scheduler parameters. */
} pthread_attr_internal_t;
/**
* @brief Thread object.
*/
typedef struct pthread_internal
{
pthread_attr_internal_t xAttr; /**< Thread attributes. */
void * ( *pvStartRoutine )( void * ); /**< Application thread function. */
void * xTaskArg; /**< Arguments for application thread function. */
TaskHandle_t xTaskHandle; /**< FreeRTOS task handle. */
StaticSemaphore_t xJoinBarrier; /**< Synchronizes the two callers of pthread_join. */
StaticSemaphore_t xJoinMutex; /**< Ensures that only one other thread may join this thread. */
void * xReturn; /**< Return value of pvStartRoutine. */
} pthread_internal_t;
/**
* @brief Terminates the calling thread.
*
* For joinable threads, this function waits for pthread_join. Otherwise,
* it deletes the thread and frees up resources used by the thread.
*
* @return This function does not return.
*/
static void prvExitThread( void );
/**
* @brief Wrapper function for the user's thread routine.
*
* This function is executed as a FreeRTOS task function.
* @param[in] pxArg A pointer to a pthread_internal_t.
*
* @return nothing
*/
static void prvRunThread( void * pxArg );
/**
* @brief Default pthread_attr_t.
*/
static const pthread_attr_internal_t xDefaultThreadAttributes =
{
.xStackSize = PTHREAD_STACK_MIN,
.iDetachState = PTHREAD_CREATE_JOINABLE,
.xSchedParam = { .sched_priority = tskIDLE_PRIORITY }
};
/*-----------------------------------------------------------*/
static void prvExitThread( void )
{
pthread_internal_t * pxThread = ( pthread_internal_t * ) pthread_self();
/* If this thread is joinable, wait for a call to pthread_join. */
if( pxThread->xAttr.iDetachState == PTHREAD_CREATE_JOINABLE )
{
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxThread->xJoinBarrier );
/* Suspend until the call to pthread_join. The caller of pthread_join
* will perform cleanup. */
vTaskSuspend( NULL );
}
else
{
/* For a detached thread, perform cleanup of thread object. */
vPortFree( pxThread );
vTaskDelete( NULL );
}
}
/*-----------------------------------------------------------*/
static void prvRunThread( void * pxArg )
{
pthread_internal_t * pxThread = ( pthread_internal_t * ) pxArg;
/* Run the thread routine. */
pxThread->xReturn = pxThread->pvStartRoutine( ( void * ) pxThread->xTaskArg );
/* Exit once finished. This function does not return. */
prvExitThread();
}
/*-----------------------------------------------------------*/
int pthread_attr_destroy( pthread_attr_t * attr )
{
int iStatus = 0;
vPortFree( *attr );
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_attr_getdetachstate( const pthread_attr_t * attr,
int * detachstate )
{
pthread_attr_internal_t * pxAttr = ( pthread_attr_internal_t * ) ( *attr );
*detachstate = pxAttr->iDetachState;
return 0;
}
/*-----------------------------------------------------------*/
int pthread_attr_getschedparam( const pthread_attr_t * attr,
struct sched_param * param )
{
pthread_attr_internal_t * pxAttr = ( pthread_attr_internal_t * ) ( *attr );
*param = pxAttr->xSchedParam;
return 0;
}
/*-----------------------------------------------------------*/
int pthread_attr_getstacksize( const pthread_attr_t * attr,
size_t * stacksize )
{
pthread_attr_internal_t * pxAttr = ( pthread_attr_internal_t * ) ( *attr );
*stacksize = pxAttr->xStackSize;
return 0;
}
/*-----------------------------------------------------------*/
int pthread_attr_init( pthread_attr_t * attr )
{
int iStatus = 0;
/* Allocate memory for a new thread attributes object. */
*attr = pvPortMalloc( sizeof( pthread_attr_internal_t ) );
/* Check that thread attributes object was successfully allocated. */
if( *attr == NULL )
{
iStatus = ENOMEM;
}
/* Copy the default values into the new thread attributes object. */
if( iStatus == 0 )
{
*( ( pthread_attr_internal_t * ) ( *attr ) ) = xDefaultThreadAttributes;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_attr_setdetachstate( pthread_attr_t * attr,
int detachstate )
{
int iStatus = 0;
pthread_attr_internal_t * pxAttr = ( pthread_attr_internal_t * ) ( *attr );
if( ( detachstate != PTHREAD_CREATE_DETACHED ) && ( detachstate != PTHREAD_CREATE_JOINABLE ) )
{
iStatus = EINVAL;
}
else
{
pxAttr->iDetachState = detachstate;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_attr_setschedparam( pthread_attr_t * attr,
const struct sched_param * param )
{
int iStatus = 0;
pthread_attr_internal_t * pxAttr = ( pthread_attr_internal_t * ) ( *attr );
/* Check for NULL param. */
if( param == NULL )
{
iStatus = EINVAL;
}
/* Ensure that param.sched_priority is valid. */
if( ( iStatus == 0 ) &&
( ( param->sched_priority > sched_get_priority_max( SCHED_OTHER ) ) ||
( param->sched_priority < 0 ) ) )
{
iStatus = ENOTSUP;
}
/* Set the sched_param. */
if( iStatus == 0 )
{
pxAttr->xSchedParam = *param;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_attr_setstacksize( pthread_attr_t * attr,
size_t stacksize )
{
int iStatus = 0;
pthread_attr_internal_t * pxAttr = ( pthread_attr_internal_t * ) ( *attr );
if( stacksize < PTHREAD_STACK_MIN )
{
iStatus = EINVAL;
}
else
{
pxAttr->xStackSize = stacksize;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_create( pthread_t * thread,
const pthread_attr_t * attr,
void *( *startroutine )( void * ),
void * arg )
{
int iStatus = 0;
pthread_internal_t * pxThread = NULL;
/* Allocate memory for new thread object. */
pxThread = ( pthread_internal_t * ) pvPortMalloc( sizeof( pthread_internal_t ) );
if( pxThread == NULL )
{
/* No memory. */
iStatus = EAGAIN;
}
if( iStatus == 0 )
{
/* No attributes given, use default attributes. */
if( attr == NULL )
{
pxThread->xAttr = xDefaultThreadAttributes;
}
/* Otherwise, use provided attributes. */
else
{
pxThread->xAttr = *( ( pthread_attr_internal_t * ) ( *attr ) );
}
/* Set argument and start routine. */
pxThread->xTaskArg = arg;
pxThread->pvStartRoutine = startroutine;
/* If this thread is joinable, create the synchronization mechanisms for
* pthread_join. */
if( pxThread->xAttr.iDetachState == PTHREAD_CREATE_JOINABLE )
{
/* These calls will not fail when their arguments aren't NULL. */
( void ) xSemaphoreCreateMutexStatic( &pxThread->xJoinMutex );
( void ) xSemaphoreCreateBinaryStatic( &pxThread->xJoinBarrier );
}
}
if( iStatus == 0 )
{
/* Suspend all tasks to create a critical section. This ensures that
* the new thread doesn't exit before a tag is assigned. */
vTaskSuspendAll();
/* Create the FreeRTOS task that will run the pthread. */
if( xTaskCreate( prvRunThread,
posixconfigPTHREAD_TASK_NAME,
( uint16_t ) ( pxThread->xAttr.xStackSize / sizeof( StackType_t ) ),
( void * ) pxThread,
pxThread->xAttr.xSchedParam.sched_priority,
&pxThread->xTaskHandle ) != pdPASS )
{
/* Task creation failed, no memory. */
vPortFree( pxThread );
iStatus = EAGAIN;
}
else
{
/* Store the pointer to the thread object in the task tag. */
vTaskSetApplicationTaskTag( pxThread->xTaskHandle, ( TaskHookFunction_t ) pxThread );
/* Set the thread object for the user. */
*thread = ( pthread_t ) pxThread;
}
/* End the critical section. */
xTaskResumeAll();
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_getschedparam( pthread_t thread,
int * policy,
struct sched_param * param )
{
pthread_internal_t * pxThread = ( pthread_internal_t * ) thread;
*policy = SCHED_OTHER;
*param = pxThread->xAttr.xSchedParam;
return 0;
}
/*-----------------------------------------------------------*/
int pthread_equal( pthread_t t1,
pthread_t t2 )
{
return t1 == t2;
}
/*-----------------------------------------------------------*/
void pthread_exit( void * value_ptr )
{
pthread_internal_t * pxThread = ( pthread_internal_t * ) pthread_self();
/* Set the return value. */
pxThread->xReturn = value_ptr;
/* Exit this thread. */
prvExitThread();
}
/*-----------------------------------------------------------*/
int pthread_join( pthread_t pthread,
void ** retval )
{
int iStatus = 0;
pthread_internal_t * pxThread = ( pthread_internal_t * ) pthread;
/* Make sure pthread is joinable. Otherwise, this function would block
* forever waiting for an unjoinable thread. */
if( pxThread->xAttr.iDetachState != PTHREAD_CREATE_JOINABLE )
{
iStatus = EDEADLK;
}
/* Only one thread may attempt to join another. Lock the join mutex
* to prevent other threads from calling pthread_join on the same thread. */
if( iStatus == 0 )
{
if( xSemaphoreTake( ( SemaphoreHandle_t ) &pxThread->xJoinMutex, 0 ) != pdPASS )
{
/* Another thread has already joined the requested thread, which would
* cause this thread to wait forever. */
iStatus = EDEADLK;
}
}
/* Attempting to join the calling thread would cause a deadlock. */
if( iStatus == 0 )
{
if( pthread_equal( pthread_self(), pthread ) != 0 )
{
iStatus = EDEADLK;
}
}
if( iStatus == 0 )
{
/* Wait for the joining thread to finish. Because this call waits forever,
* it should never fail. */
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxThread->xJoinBarrier, portMAX_DELAY );
/* Create a critical section to clean up the joined thread. */
vTaskSuspendAll();
/* Release xJoinBarrier and delete it. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxThread->xJoinBarrier );
vSemaphoreDelete( ( SemaphoreHandle_t ) &pxThread->xJoinBarrier );
/* Release xJoinMutex and delete it. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxThread->xJoinMutex );
vSemaphoreDelete( ( SemaphoreHandle_t ) &pxThread->xJoinMutex );
/* Delete the FreeRTOS task that ran the thread. */
vTaskDelete( pxThread->xTaskHandle );
/* Set the return value. */
if( retval != NULL )
{
*retval = pxThread->xReturn;
}
/* Free the thread object. */
vPortFree( pxThread );
/* End the critical section. */
xTaskResumeAll();
}
return iStatus;
}
/*-----------------------------------------------------------*/
pthread_t pthread_self( void )
{
/* Return a reference to this pthread object, which is stored in the
* FreeRTOS task tag. */
return ( pthread_t ) xTaskGetApplicationTaskTag( NULL );
}
/*-----------------------------------------------------------*/
int pthread_setschedparam( pthread_t thread,
int policy,
const struct sched_param * param )
{
pthread_internal_t * pxThread = ( pthread_internal_t * ) thread;
/* Silence compiler warnings about unused parameters. */
( void ) policy;
/* Copy the give sched_param. */
pxThread->xAttr.xSchedParam = *param;
/* Change the priority of the FreeRTOS task. */
vTaskPrioritySet( pxThread->xTaskHandle, pxThread->xAttr.xSchedParam.sched_priority );
return 0;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,204 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_pthread_barrier.c
* @brief Implementation of barrier functions in pthread.h
*/
/* C standard library includes. */
#include <stddef.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/errno.h"
#include "FreeRTOS_POSIX/pthread.h"
/*
* Barriers are implemented on FreeRTOS event groups, of which 8 bits are usable
* when configUSE_16_BIT_TICKS is 1. Otherwise, 24 bits are usable.
*/
#if ( configUSE_16_BIT_TICKS == 1 )
#define posixPTHREAD_BARRIER_MAX_COUNT ( 8 )
#else
#define posixPTHREAD_BARRIER_MAX_COUNT ( 24 )
#endif
/**
* @brief Barrier object.
*/
typedef struct pthread_barrier_internal
{
unsigned uThreadCount; /**< Current number of threads that have entered barrier. */
unsigned uThreshold; /**< The count argument of pthread_barrier_init. */
StaticSemaphore_t xThreadCountMutex; /**< Guards access to uThreadCount. */
StaticSemaphore_t xThreadCountSemaphore; /**< Prevents more than uThreshold threads from exiting pthread_barrier_wait at once. */
StaticEventGroup_t xBarrierEventGroup; /**< FreeRTOS event group that blocks to wait on threads entering barrier. */
} pthread_barrier_internal_t;
/*-----------------------------------------------------------*/
int pthread_barrier_destroy( pthread_barrier_t * barrier )
{
pthread_barrier_internal_t * pxBarrier = ( pthread_barrier_internal_t * ) ( *barrier );
/* Free all resources used by the barrier. */
( void ) vEventGroupDelete( ( EventGroupHandle_t ) &pxBarrier->xBarrierEventGroup );
( void ) vSemaphoreDelete( ( SemaphoreHandle_t ) &pxBarrier->xThreadCountMutex );
( void ) vSemaphoreDelete( ( SemaphoreHandle_t ) &pxBarrier->xThreadCountSemaphore );
vPortFree( *barrier );
return 0;
}
/*-----------------------------------------------------------*/
int pthread_barrier_init( pthread_barrier_t * barrier,
const pthread_barrierattr_t * attr,
unsigned count )
{
int iStatus = 0;
pthread_barrier_internal_t * pxNewBarrier = NULL;
/* Silence warnings about unused parameters. */
( void ) attr;
/* Ensure count is greater than 0. */
if( count == 0 )
{
iStatus = EINVAL;
}
/* Ensure that count will fit in a FreeRTOS event group. */
if( iStatus == 0 )
{
if( count > posixPTHREAD_BARRIER_MAX_COUNT )
{
/* No memory exists in the event group for more than
* posixPTHREAD_BARRIER_MAX_COUNT threads. */
iStatus = ENOMEM;
}
}
/* Allocate memory for a new barrier. */
if( iStatus == 0 )
{
pxNewBarrier = pvPortMalloc( sizeof( pthread_barrier_internal_t ) );
if( pxNewBarrier == NULL )
{
/* No memory. */
iStatus = ENOMEM;
}
}
if( iStatus == 0 )
{
/* Set the current thread count and threshold. */
pxNewBarrier->uThreadCount = 0;
pxNewBarrier->uThreshold = count;
/* Create the FreeRTOS event group. This call will not fail when its
* argument isn't NULL. */
( void ) xEventGroupCreateStatic( &pxNewBarrier->xBarrierEventGroup );
/* Create the mutex that guards access to uThreadCount. This call
* will not fail when its argument isn't NULL. */
( void ) xSemaphoreCreateMutexStatic( &pxNewBarrier->xThreadCountMutex );
/* Create the semaphore that prevents more than count threads from being
* unblocked by a single successful pthread_barrier_wait. This semaphore
* counts down from count and cannot decrement below 0. */
( void ) xSemaphoreCreateCountingStatic( ( UBaseType_t ) count, /* Max count. */
( UBaseType_t ) count, /* Initial count. */
&pxNewBarrier->xThreadCountSemaphore );
/* Set output parameter. */
*barrier = pxNewBarrier;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_barrier_wait( pthread_barrier_t * barrier )
{
int iStatus = 0;
unsigned i = 0; /* Loop iterator. */
pthread_barrier_internal_t * pxBarrier = ( pthread_barrier_internal_t * ) ( *barrier );
unsigned uThreadNumber = 0;
/* Decrement the number of threads waiting on this barrier. This will prevent more
* than pxBarrier->uThreshold threads from being unblocked by a single successful
* pthread_barrier_wait call.
*
* This call will never fail because it blocks forever.
*/
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxBarrier->xThreadCountSemaphore, portMAX_DELAY );
/* Lock the mutex so that this thread can change uThreadCount. This call will
* never fail because it blocks forever.*/
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxBarrier->xThreadCountMutex, portMAX_DELAY );
/* Increment thread count. This is the order that this thread entered the
* barrier, i.e. uThreadNumber-1 threads entered the barrier before this one. */
pxBarrier->uThreadCount++;
uThreadNumber = pxBarrier->uThreadCount;
configASSERT( uThreadNumber > 0 );
/* Unlock the thread count mutex to allow other threads to change thread count.
* This call will never fail because xThreadCountMutex is owned by this thread. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxBarrier->xThreadCountMutex );
/* Set the bit in the event group representing this thread, then wait for the other
* threads to set their bit. This call should wait forever until all threads have set
* their bit, so the return value is ignored. */
( void ) xEventGroupSync( ( EventGroupHandle_t ) &pxBarrier->xBarrierEventGroup,
1 << ( uThreadNumber - 1 ), /* Which bit in the event group to set. */
( 1 << pxBarrier->uThreshold ) - 1, /* Wait for all threads to set their bits. */
portMAX_DELAY );
/* The first thread to enter the barrier gets PTHREAD_BARRIER_SERIAL_THREAD as its
* return value and resets xThreadCountSemaphore. */
if( uThreadNumber == 1 )
{
iStatus = PTHREAD_BARRIER_SERIAL_THREAD;
/* uThreadCount can be safely changed without locking xThreadCountMutex
* because xThreadCountSemaphore is currently 0. */
pxBarrier->uThreadCount = 0;
/* Reset xThreadCountSemaphore. This allows more threads to enter the
* barrier, starting a new cycle. */
for( i = 0; i < pxBarrier->uThreshold; i++ )
{
xSemaphoreGive( ( SemaphoreHandle_t ) &pxBarrier->xThreadCountSemaphore );
}
}
return iStatus;
}

View File

@ -0,0 +1,250 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_pthread_cond.c
* @brief Implementation of condition variable functions in pthread.h
*/
/* C standard library includes. */
#include <limits.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/errno.h"
#include "FreeRTOS_POSIX/pthread.h"
#include "FreeRTOS_POSIX/utils.h"
/**
* @brief Initialize a PTHREAD_COND_INITIALIZER cond.
*
* PTHREAD_COND_INITIALIZER sets a flag for a cond to be initialized later.
* This function performs the initialization.
* @param[in] pxCond The cond to initialize.
*
* @return nothing
*/
static void prvInitializeStaticCond( pthread_cond_internal_t * pxCond );
/*-----------------------------------------------------------*/
static void prvInitializeStaticCond( pthread_cond_internal_t * pxCond )
{
/* Check if the condition variable needs to be initialized. */
if( pxCond->xIsInitialized == pdFALSE )
{
/* Cond initialization must be in a critical section to prevent two threads
* from initializing it at the same time. */
taskENTER_CRITICAL();
/* Check again that the cond is still uninitialized, i.e. it wasn't
* initialized while this function was waiting to enter the critical
* section. */
if( pxCond->xIsInitialized == pdFALSE )
{
/* Set the members of the cond. The semaphore create calls will never fail
* when their arguments aren't NULL. */
pxCond->xIsInitialized = pdTRUE;
( void ) xSemaphoreCreateMutexStatic( &pxCond->xCondMutex );
( void ) xSemaphoreCreateCountingStatic( INT_MAX, 0U, &pxCond->xCondWaitSemaphore );
pxCond->iWaitingThreads = 0;
}
/* Exit the critical section. */
taskEXIT_CRITICAL();
}
}
/*-----------------------------------------------------------*/
int pthread_cond_broadcast( pthread_cond_t * cond )
{
int i = 0;
pthread_cond_internal_t * pxCond = ( pthread_cond_internal_t * ) ( *cond );
/* If the cond is uninitialized, perform initialization. */
prvInitializeStaticCond( pxCond );
/* Lock xCondMutex to protect access to iWaitingThreads.
* This call will never fail because it blocks forever. */
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxCond->xCondMutex, portMAX_DELAY );
/* Unblock all threads waiting on this condition variable. */
for( i = 0; i < pxCond->iWaitingThreads; i++ )
{
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxCond->xCondWaitSemaphore );
}
/* All threads were unblocked, set waiting threads to 0. */
pxCond->iWaitingThreads = 0;
/* Release xCondMutex. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxCond->xCondMutex );
return 0;
}
/*-----------------------------------------------------------*/
int pthread_cond_destroy( pthread_cond_t * cond )
{
pthread_cond_internal_t * pxCond = ( pthread_cond_internal_t * ) ( *cond );
/* Free all resources in use by the cond. */
vSemaphoreDelete( ( SemaphoreHandle_t ) &pxCond->xCondMutex );
vSemaphoreDelete( ( SemaphoreHandle_t ) &pxCond->xCondWaitSemaphore );
vPortFree( pxCond );
return 0;
}
/*-----------------------------------------------------------*/
int pthread_cond_init( pthread_cond_t * cond,
const pthread_condattr_t * attr )
{
int iStatus = 0;
pthread_cond_internal_t * pxCond = NULL;
/* Silence warnings about unused parameters. */
( void ) attr;
pxCond = pvPortMalloc( sizeof( pthread_cond_internal_t ) );
if( pxCond == NULL )
{
iStatus = ENOMEM;
}
if( iStatus == 0 )
{
/* Set the members of the cond. The semaphore create calls will never fail
* when their arguments aren't NULL. */
pxCond->xIsInitialized = pdTRUE;
( void ) xSemaphoreCreateMutexStatic( &pxCond->xCondMutex );
( void ) xSemaphoreCreateCountingStatic( INT_MAX, 0U, &pxCond->xCondWaitSemaphore );
pxCond->iWaitingThreads = 0;
/* Set the output. */
*cond = pxCond;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_cond_signal( pthread_cond_t * cond )
{
pthread_cond_internal_t * pxCond = ( pthread_cond_internal_t * ) ( *cond );
/* If the cond is uninitialized, perform initialization. */
prvInitializeStaticCond( pxCond );
/* Check that at least one thread is waiting for a signal. */
if( pxCond->iWaitingThreads > 0 )
{
/* Lock xCondMutex to protect access to iWaitingThreads.
* This call will never fail because it blocks forever. */
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxCond->xCondMutex, portMAX_DELAY );
/* Check again that at least one thread is waiting for a signal after
* taking xCondMutex. If so, unblock it. */
if( pxCond->iWaitingThreads > 0 )
{
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxCond->xCondWaitSemaphore );
/* Decrease the number of waiting threads. */
pxCond->iWaitingThreads--;
}
/* Release xCondMutex. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxCond->xCondMutex );
}
return 0;
}
/*-----------------------------------------------------------*/
int pthread_cond_timedwait( pthread_cond_t * cond,
pthread_mutex_t * mutex,
const struct timespec * abstime )
{
int iStatus = 0;
pthread_cond_internal_t * pxCond = ( pthread_cond_internal_t * ) ( *cond );
TickType_t xDelay = portMAX_DELAY;
/* If the cond is uninitialized, perform initialization. */
prvInitializeStaticCond( pxCond );
/* Convert abstime to a delay in TickType_t if provided. */
if( abstime != NULL )
{
iStatus = UTILS_AbsoluteTimespecToTicks( abstime, &xDelay );
}
/* Increase the counter of threads blocking on condition variable, then
* unlock mutex. */
if( iStatus == 0 )
{
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxCond->xCondMutex, portMAX_DELAY );
pxCond->iWaitingThreads++;
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxCond->xCondMutex );
iStatus = pthread_mutex_unlock( mutex );
}
/* Wait on the condition variable. */
if( iStatus == 0 )
{
if( xSemaphoreTake( ( SemaphoreHandle_t ) &pxCond->xCondWaitSemaphore,
xDelay ) == pdPASS )
{
/* When successful, relock mutex. */
iStatus = pthread_mutex_lock( mutex );
}
else
{
/* Timeout. Relock mutex and decrement number of waiting threads. */
iStatus = ETIMEDOUT;
( void ) pthread_mutex_lock( mutex );
( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxCond->xCondMutex, portMAX_DELAY );
pxCond->iWaitingThreads--;
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxCond->xCondMutex );
}
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_cond_wait( pthread_cond_t * cond,
pthread_mutex_t * mutex )
{
return pthread_cond_timedwait( cond, mutex, NULL );
}

View File

@ -0,0 +1,378 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_pthread_mutex.c
* @brief Implementation of mutex functions in pthread.h
*/
/* C standard library includes. */
#include <stddef.h>
#include <stdbool.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/errno.h"
#include "FreeRTOS_POSIX/pthread.h"
#include "FreeRTOS_POSIX/utils.h"
/**
* @brief Initialize a PTHREAD_MUTEX_INITIALIZER mutex.
*
* PTHREAD_MUTEX_INITIALIZER sets a flag for a mutex to be initialized later.
* This function performs the initialization.
* @param[in] pxMutex The mutex to initialize.
*
* @return nothing
*/
static void prvInitializeStaticMutex( pthread_mutex_internal_t * pxMutex );
/**
* @brief Default pthread_mutexattr_t.
*/
static const pthread_mutexattr_internal_t xDefaultMutexAttributes =
{
.iType = PTHREAD_MUTEX_DEFAULT,
};
/*-----------------------------------------------------------*/
static void prvInitializeStaticMutex( pthread_mutex_internal_t * pxMutex )
{
/* Check if the mutex needs to be initialized. */
if( pxMutex->xIsInitialized == pdFALSE )
{
/* Mutex initialization must be in a critical section to prevent two threads
* from initializing it at the same time. */
taskENTER_CRITICAL();
/* Check again that the mutex is still uninitialized, i.e. it wasn't
* initialized while this function was waiting to enter the critical
* section. */
if( pxMutex->xIsInitialized == pdFALSE )
{
/* Set the mutex as the default type. */
pxMutex->xAttr.iType = PTHREAD_MUTEX_DEFAULT;
/* Call the correct FreeRTOS mutex initialization function based on
* the mutex type. */
#if PTHREAD_MUTEX_DEFAULT == PTHREAD_MUTEX_RECURSIVE
( void ) xSemaphoreCreateRecursiveMutexStatic( &pxMutex->xMutex );
#else
( void ) xSemaphoreCreateMutexStatic( &pxMutex->xMutex );
#endif
pxMutex->xIsInitialized = pdTRUE;
}
/* Exit the critical section. */
taskEXIT_CRITICAL();
}
}
/*-----------------------------------------------------------*/
int pthread_mutex_destroy( pthread_mutex_t * mutex )
{
pthread_mutex_internal_t * pxMutex = ( pthread_mutex_internal_t * ) ( *mutex );
/* Free resources in use by the mutex. */
if( pxMutex->xTaskOwner == NULL )
{
vSemaphoreDelete( ( SemaphoreHandle_t ) &pxMutex->xMutex );
vPortFree( pxMutex );
}
return 0;
}
/*-----------------------------------------------------------*/
int pthread_mutex_init( pthread_mutex_t * mutex,
const pthread_mutexattr_t * attr )
{
int iStatus = 0;
pthread_mutex_internal_t * pxMutex = NULL;
/* Allocate memory for new mutex object. */
pxMutex = ( pthread_mutex_internal_t * ) pvPortMalloc( sizeof( pthread_mutex_internal_t ) );
if( pxMutex == NULL )
{
/* No memory. */
iStatus = ENOMEM;
}
if( iStatus == 0 )
{
/* Clear the newly-allocated mutex. */
( void ) memset( pxMutex, 0x00, sizeof( pthread_mutex_internal_t ) );
/* No attributes given, use default attributes. */
if( attr == NULL )
{
pxMutex->xAttr = xDefaultMutexAttributes;
}
/* Otherwise, use provided attributes. */
else
{
pxMutex->xAttr = *( ( pthread_mutexattr_internal_t * ) ( *attr ) );
}
/* Call the correct FreeRTOS mutex creation function based on mutex type. */
if( pxMutex->xAttr.iType == PTHREAD_MUTEX_RECURSIVE )
{
/* Recursive mutex. */
( void ) xSemaphoreCreateRecursiveMutexStatic( &pxMutex->xMutex );
}
else
{
/* All other mutex types. */
( void ) xSemaphoreCreateMutexStatic( &pxMutex->xMutex );
}
/* Ensure that the FreeRTOS mutex was successfully created. */
if( ( SemaphoreHandle_t ) &pxMutex->xMutex == NULL )
{
/* Failed to create mutex. Set error EAGAIN and free mutex object. */
iStatus = EAGAIN;
vPortFree( pxMutex );
}
else
{
/* Mutex successfully created. */
pxMutex->xIsInitialized = pdTRUE;
*mutex = ( pthread_mutex_t ) pxMutex;
}
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_mutex_lock( pthread_mutex_t * mutex )
{
return pthread_mutex_timedlock( mutex, NULL );
}
/*-----------------------------------------------------------*/
int pthread_mutex_timedlock( pthread_mutex_t * mutex,
const struct timespec * abstime )
{
int iStatus = 0;
pthread_mutex_internal_t * pxMutex = ( pthread_mutex_internal_t * ) ( *mutex );
TickType_t xDelay = portMAX_DELAY;
BaseType_t xFreeRTOSMutexTakeStatus = pdFALSE;
/* If mutex in uninitialized, perform initialization. */
prvInitializeStaticMutex( pxMutex );
/* At this point, the mutex should be initialized. */
configASSERT( pxMutex->xIsInitialized == pdTRUE );
/* Convert abstime to a delay in TickType_t if provided. */
if( abstime != NULL )
{
iStatus = UTILS_AbsoluteTimespecToTicks( abstime, &xDelay );
/* If abstime was in the past, still attempt to lock the mutex without
* blocking, per POSIX spec. */
if( iStatus == ETIMEDOUT )
{
xDelay = 0;
iStatus = 0;
}
}
/* Check if trying to lock a currently owned mutex. */
if( ( iStatus == 0 ) &&
( pxMutex->xAttr.iType == PTHREAD_MUTEX_ERRORCHECK ) && /* Only PTHREAD_MUTEX_ERRORCHECK type detects deadlock. */
( pxMutex->xTaskOwner == xTaskGetCurrentTaskHandle() ) ) /* Check if locking a currently owned mutex. */
{
iStatus = EDEADLK;
}
if( iStatus == 0 )
{
/* Call the correct FreeRTOS mutex take function based on mutex type. */
if( pxMutex->xAttr.iType == PTHREAD_MUTEX_RECURSIVE )
{
xFreeRTOSMutexTakeStatus = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) &pxMutex->xMutex, xDelay );
}
else
{
xFreeRTOSMutexTakeStatus = xSemaphoreTake( ( SemaphoreHandle_t ) &pxMutex->xMutex, xDelay );
}
/* If the mutex was successfully taken, set its owner. */
if( xFreeRTOSMutexTakeStatus == pdPASS )
{
pxMutex->xTaskOwner = xTaskGetCurrentTaskHandle();
}
/* Otherwise, the mutex take timed out. */
else
{
iStatus = ETIMEDOUT;
}
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_mutex_trylock( pthread_mutex_t * mutex )
{
int iStatus = 0;
struct timespec xTimeout =
{
.tv_sec = 0,
.tv_nsec = 0
};
/* Attempt to lock with no timeout. */
iStatus = pthread_mutex_timedlock( mutex, &xTimeout );
/* POSIX specifies that this function should return EBUSY instead of
* ETIMEDOUT for attempting to lock a locked mutex. */
if( iStatus == ETIMEDOUT )
{
iStatus = EBUSY;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_mutex_unlock( pthread_mutex_t * mutex )
{
int iStatus = 0;
pthread_mutex_internal_t * pxMutex = ( pthread_mutex_internal_t * ) ( *mutex );
/* If mutex in uninitialized, perform initialization. */
prvInitializeStaticMutex( pxMutex );
/* Check if trying to unlock an unowned mutex. */
if( ( ( pxMutex->xAttr.iType == PTHREAD_MUTEX_ERRORCHECK ) ||
( pxMutex->xAttr.iType == PTHREAD_MUTEX_RECURSIVE ) ) &&
( pxMutex->xTaskOwner != xTaskGetCurrentTaskHandle() ) )
{
iStatus = EPERM;
}
if( iStatus == 0 )
{
/* Call the correct FreeRTOS mutex unlock function based on mutex type. */
if( pxMutex->xAttr.iType == PTHREAD_MUTEX_RECURSIVE )
{
( void ) xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) &pxMutex->xMutex );
}
else
{
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxMutex->xMutex );
}
/* Update the owner of the mutex. A recursive mutex may still have an
* owner, so it should be updated with xSemaphoreGetMutexHolder. */
pxMutex->xTaskOwner = xSemaphoreGetMutexHolder( ( SemaphoreHandle_t ) &pxMutex->xMutex );
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_mutexattr_destroy( pthread_mutexattr_t * attr )
{
/* Free mutex attributes object. */
vPortFree( *attr );
return 0;
}
/*-----------------------------------------------------------*/
int pthread_mutexattr_gettype( const pthread_mutexattr_t * attr,
int * type )
{
pthread_mutexattr_internal_t * pxAttr = ( pthread_mutexattr_internal_t * ) ( *attr );
*type = pxAttr->iType;
return 0;
}
/*-----------------------------------------------------------*/
int pthread_mutexattr_init( pthread_mutexattr_t * attr )
{
int iStatus = 0;
/* Allocate memory for new mutex attributes object. */
*attr = pvPortMalloc( sizeof( pthread_mutexattr_internal_t ) );
if( *attr == NULL )
{
/* No memory. */
iStatus = ENOMEM;
}
/* Set the mutex attributes to default values. */
if( iStatus == 0 )
{
*( ( pthread_mutexattr_internal_t * ) ( *attr ) ) = xDefaultMutexAttributes;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int pthread_mutexattr_settype( pthread_mutexattr_t * attr,
int type )
{
int iStatus = 0;
pthread_mutexattr_internal_t * pxAttr = ( pthread_mutexattr_internal_t * ) ( *attr );
switch( type )
{
case PTHREAD_MUTEX_NORMAL:
case PTHREAD_MUTEX_RECURSIVE:
case PTHREAD_MUTEX_ERRORCHECK:
pxAttr->iType = type;
break;
default:
iStatus = EINVAL;
break;
}
return iStatus;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,52 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_sched.c
* @brief Implementation of scheduler functions in sched.h
*/
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/sched.h"
/*-----------------------------------------------------------*/
int sched_get_priority_max( int policy )
{
/* Silence warnings about unused parameters. */
( void ) policy;
return configMAX_PRIORITIES - 1;
}
/*-----------------------------------------------------------*/
int sched_yield( void )
{
taskYIELD();
return 0;
}

View File

@ -0,0 +1,204 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_semaphore.c
* @brief Implementation of functions in semaphore.h
*/
/* C standard library includes. */
#include <stddef.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/errno.h"
#include "FreeRTOS_POSIX/semaphore.h"
#include "FreeRTOS_POSIX/utils.h"
/**
* @brief Semaphore type.
*/
typedef struct
{
StaticSemaphore_t xSemaphore; /**< FreeRTOS semaphore. */
} sem_internal_t;
/*-----------------------------------------------------------*/
int sem_destroy( sem_t * sem )
{
sem_internal_t * pxSem = ( sem_internal_t * ) ( *sem );
/* Free the resources in use by the semaphore. */
vSemaphoreDelete( ( SemaphoreHandle_t ) &pxSem->xSemaphore );
vPortFree( pxSem );
return 0;
}
/*-----------------------------------------------------------*/
int sem_getvalue( sem_t * sem,
int * sval )
{
sem_internal_t * pxSem = ( sem_internal_t * ) ( *sem );
/* Get the semaphore count using the FreeRTOS API. */
*sval = ( int ) uxSemaphoreGetCount( ( SemaphoreHandle_t ) &pxSem->xSemaphore );
return 0;
}
/*-----------------------------------------------------------*/
int sem_init( sem_t * sem,
int pshared,
unsigned value )
{
int iStatus = 0;
sem_internal_t * pxSem = NULL;
/* Silence warnings about unused parameters. */
( void ) pshared;
/* Check value parameter. */
if( value > SEM_VALUE_MAX )
{
errno = EINVAL;
iStatus = -1;
}
/* Allocate memory for a new semaphore. */
if( iStatus == 0 )
{
pxSem = pvPortMalloc( sizeof( sem_internal_t ) );
if( pxSem == NULL )
{
errno = ENOSPC;
iStatus = -1;
}
}
/* Create the FreeRTOS semaphore. This call will not fail because the
* memory for the semaphore has already been allocated. */
if( iStatus == 0 )
{
( void ) xSemaphoreCreateCountingStatic( SEM_VALUE_MAX, value, &pxSem->xSemaphore );
*sem = pxSem;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int sem_post( sem_t * sem )
{
sem_internal_t * pxSem = ( sem_internal_t * ) ( *sem );
/* Give the semaphore using the FreeRTOS API. */
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxSem->xSemaphore );
return 0;
}
/*-----------------------------------------------------------*/
int sem_timedwait( sem_t * sem,
const struct timespec * abstime )
{
int iStatus = 0;
sem_internal_t * pxSem = ( sem_internal_t * ) ( *sem );
TickType_t xDelay = portMAX_DELAY;
if( abstime != NULL )
{
/* If the provided timespec is invalid, still attempt to take the
* semaphore without blocking, per POSIX spec. */
if( UTILS_ValidateTimespec( abstime ) == false )
{
xDelay = 0;
iStatus = EINVAL;
}
else
{
iStatus = UTILS_AbsoluteTimespecToTicks( abstime, &xDelay );
/* If abstime was in the past, still attempt to take the semaphore without
* blocking, per POSIX spec. */
if( iStatus == ETIMEDOUT )
{
xDelay = 0;
}
}
}
/* Take the semaphore using the FreeRTOS API. */
if( xSemaphoreTake( ( SemaphoreHandle_t ) &pxSem->xSemaphore,
xDelay ) != pdTRUE )
{
errno = iStatus;
iStatus = -1;
}
else
{
iStatus = 0;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int sem_trywait( sem_t * sem )
{
int iStatus = 0;
/* Setting an absolute timeout of 0 (i.e. in the past) will cause sem_timedwait
* to not block. */
struct timespec xTimeout = { 0 };
iStatus = sem_timedwait( sem, &xTimeout );
/* POSIX specifies that this function should set errno to EAGAIN and not
* ETIMEDOUT. */
if( ( iStatus == -1 ) && ( errno == ETIMEDOUT ) )
{
errno = EAGAIN;
}
return iStatus;
}
/*-----------------------------------------------------------*/
int sem_wait( sem_t * sem )
{
return sem_timedwait( sem, NULL );
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,323 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_timer.c
* @brief Implementation of timer functions in time.h
*/
/* C standard library includes. */
#include <stddef.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/errno.h"
#include "FreeRTOS_POSIX/pthread.h"
#include "FreeRTOS_POSIX/signal.h"
#include "FreeRTOS_POSIX/time.h"
#include "FreeRTOS_POSIX/utils.h"
/* FreeRTOS timer include. */
#include "timers.h"
/**
* #brief Timespec zero check macros.
*/
/**@{ */
#define TIMESPEC_IS_ZERO( xTimespec ) ( xTimespec.tv_sec == 0 && xTimespec.tv_nsec == 0 ) /**< Check for 0. */
#define TIMESPEC_IS_NOT_ZERO( xTimespec ) ( !( TIMESPEC_IS_ZERO( xTimespec ) ) ) /**< Check for not 0. */
/**@} */
/**
* @brief Internal timer structure.
*/
typedef struct timer_internal
{
StaticTimer_t xTimerBuffer; /**< Memory that holds the FreeRTOS timer. */
struct sigevent xTimerEvent; /**< What to do when this timer expires. */
TickType_t xTimerPeriod; /**< Period of this timer. */
} timer_internal_t;
/*-----------------------------------------------------------*/
void prvTimerCallback( TimerHandle_t xTimerHandle )
{
timer_internal_t * pxTimer = ( timer_internal_t * ) pvTimerGetTimerID( xTimerHandle );
pthread_t xTimerNotificationThread;
pthread_attr_t xThreadAttributes;
/* The value of the timer ID, set in timer_create, should not be NULL. */
configASSERT( pxTimer != NULL );
/* A value of SIGEV_SIGNAL isn't supported and should not have been successfully
* set. */
configASSERT( pxTimer->xTimerEvent.sigev_notify != SIGEV_SIGNAL );
/* Update the timer period, which may need to be set to an it_interval
* argument. This call should not block. */
if( pxTimer->xTimerPeriod > 0 )
{
xTimerChangePeriod( xTimerHandle, pxTimer->xTimerPeriod, 0 );
}
/* Create the timer notification thread if requested. */
if( pxTimer->xTimerEvent.sigev_notify == SIGEV_THREAD )
{
/* By default, create a detached thread. But if the user has provided
* thread attributes, use the provided attributes. */
if( pxTimer->xTimerEvent.sigev_notify_attributes == NULL )
{
if( pthread_attr_init( &xThreadAttributes ) == 0 )
{
if( pthread_attr_setdetachstate( &xThreadAttributes,
PTHREAD_CREATE_DETACHED ) == 0 )
{
( void ) pthread_create( &xTimerNotificationThread,
&xThreadAttributes,
( void * ( * )( void * ) )pxTimer->xTimerEvent.sigev_notify_function,
pxTimer->xTimerEvent.sigev_value.sival_ptr );
}
( void ) pthread_attr_destroy( &xThreadAttributes );
}
}
else
{
( void ) pthread_create( &xTimerNotificationThread,
pxTimer->xTimerEvent.sigev_notify_attributes,
( void * ( * )( void * ) )pxTimer->xTimerEvent.sigev_notify_function,
pxTimer->xTimerEvent.sigev_value.sival_ptr );
}
}
}
/*-----------------------------------------------------------*/
int timer_create( clockid_t clockid,
struct sigevent * evp,
timer_t * timerid )
{
int iStatus = 0;
timer_internal_t * pxTimer = NULL;
/* Silence warnings about unused parameters. */
( void ) clockid;
/* POSIX specifies that when evp is NULL, the behavior shall be as is
* sigev_notify is SIGEV_SIGNAL. SIGEV_SIGNAL is currently not supported. */
if( ( evp == NULL ) || ( evp->sigev_notify == SIGEV_SIGNAL ) )
{
errno = ENOTSUP;
iStatus = -1;
}
/* Allocate memory for a new timer object. */
if( iStatus == 0 )
{
pxTimer = pvPortMalloc( sizeof( timer_internal_t ) );
if( pxTimer == NULL )
{
errno = EAGAIN;
iStatus = -1;
}
}
if( iStatus == 0 )
{
/* Copy the event notification structure and set the current timer period. */
pxTimer->xTimerEvent = *evp;
pxTimer->xTimerPeriod = 0;
/* Create a new FreeRTOS timer. This call will not fail because the
* memory for it has already been allocated, so the output parameter is
* also set. */
*timerid = ( timer_t ) xTimerCreateStatic( posixconfigTIMER_NAME, /* Timer name. */
portMAX_DELAY, /* Initial timer period. Timers are created disarmed. */
pdFALSE, /* Don't auto-reload timer. */
( void * ) pxTimer, /* Timer id. */
prvTimerCallback, /* Timer expiration callback. */
&pxTimer->xTimerBuffer ); /* Pre-allocated memory for timer. */
}
return iStatus;
}
/*-----------------------------------------------------------*/
int timer_delete( timer_t timerid )
{
TimerHandle_t xTimerHandle = timerid;
timer_internal_t * pxTimer = ( timer_internal_t * ) pvTimerGetTimerID( xTimerHandle );
/* The value of the timer ID, set in timer_create, should not be NULL. */
configASSERT( pxTimer != NULL );
/* Stop the FreeRTOS timer. Because the timer is statically allocated, no call
* to xTimerDelete is necessary. The timer is stopped so that it's not referenced
* anywhere. xTimerStop will not fail when it has unlimited block time. */
( void ) xTimerStop( xTimerHandle, portMAX_DELAY );
/* Wait until the timer stop command is processed. */
while( xTimerIsTimerActive( xTimerHandle ) == pdTRUE )
{
vTaskDelay( 1 );
}
/* Free the memory in use by the timer. */
vPortFree( pxTimer );
return 0;
}
/*-----------------------------------------------------------*/
int timer_getoverrun( timer_t timerid )
{
( void ) timerid;
return 0;
}
/*-----------------------------------------------------------*/
int timer_settime( timer_t timerid,
int flags,
const struct itimerspec * value,
struct itimerspec * ovalue )
{
int iStatus = 0;
TimerHandle_t xTimerHandle = timerid;
timer_internal_t * pxTimer = ( timer_internal_t * ) pvTimerGetTimerID( xTimerHandle );
TickType_t xNextTimerExpiration = 0, xTimerExpirationPeriod = 0;
/* Validate the value argument, but only if the timer isn't being disarmed. */
if( TIMESPEC_IS_NOT_ZERO( value->it_value ) )
{
if( ( UTILS_ValidateTimespec( &value->it_interval ) == false ) ||
( UTILS_ValidateTimespec( &value->it_value ) == false ) )
{
errno = EINVAL;
iStatus = -1;
}
}
/* Set ovalue, if given. */
if( ovalue != NULL )
{
( void ) timer_gettime( timerid, ovalue );
}
/* Stop the timer if it's currently active. */
if( ( iStatus == 0 ) && xTimerIsTimerActive( xTimerHandle ) )
{
( void ) xTimerStop( xTimerHandle, portMAX_DELAY );
}
/* Only restart the timer if it_value is not zero. */
if( ( iStatus == 0 ) && TIMESPEC_IS_NOT_ZERO( value->it_value ) )
{
/* Convert it_interval to ticks, but only if it_interval is not 0. If
* it_interval is 0, then the timer is not periodic. */
if( TIMESPEC_IS_NOT_ZERO( value->it_interval ) )
{
( void ) UTILS_TimespecToTicks( &value->it_interval, &xTimerExpirationPeriod );
}
/* Set the new timer period. A non-periodic timer will have its period set
* to portMAX_DELAY. */
pxTimer->xTimerPeriod = xTimerExpirationPeriod;
/* Convert it_value to ticks, but only if it_value is not 0. If it_value
* is 0, then the timer will remain disarmed. */
if( TIMESPEC_IS_NOT_ZERO( value->it_value ) )
{
/* Absolute timeout. */
if( ( flags & TIMER_ABSTIME ) == TIMER_ABSTIME )
{
( void ) UTILS_AbsoluteTimespecToTicks( &value->it_value, &xNextTimerExpiration );
}
/* Relative timeout. */
else
{
( void ) UTILS_TimespecToTicks( &value->it_value, &xNextTimerExpiration );
}
}
/* If xNextTimerExpiration is still 0, that means that it_value specified
* an absolute timeout in the past. Per POSIX spec, a notification should be
* triggered immediately. */
if( xNextTimerExpiration == 0 )
{
prvTimerCallback( xTimerHandle );
}
else
{
/* Set the timer to expire at the it_value, then start it. */
( void ) xTimerChangePeriod( xTimerHandle, xNextTimerExpiration, portMAX_DELAY );
( void ) xTimerStart( xTimerHandle, xNextTimerExpiration );
}
}
return iStatus;
}
/*-----------------------------------------------------------*/
int timer_gettime( timer_t timerid,
struct itimerspec * value )
{
TimerHandle_t xTimerHandle = timerid;
timer_internal_t * pxTimer = ( timer_internal_t * ) pvTimerGetTimerID( xTimerHandle );
TickType_t xNextExpirationTime = xTimerGetExpiryTime( xTimerHandle ) - xTaskGetTickCount(),
xTimerExpirationPeriod = pxTimer->xTimerPeriod;
/* Set it_value only if the timer is armed. Otherwise, set it to 0. */
if( xTimerIsTimerActive( xTimerHandle ) != pdFALSE )
{
value->it_value.tv_sec = ( time_t ) ( xNextExpirationTime / configTICK_RATE_HZ );
value->it_value.tv_nsec = ( long ) ( ( xNextExpirationTime % configTICK_RATE_HZ ) * NANOSECONDS_PER_TICK );
}
else
{
value->it_value.tv_sec = 0;
value->it_value.tv_nsec = 0;
}
/* Set it_interval only if the timer is periodic. Otherwise, set it to 0. */
if( xTimerExpirationPeriod != portMAX_DELAY )
{
value->it_interval.tv_sec = ( time_t ) ( xTimerExpirationPeriod / configTICK_RATE_HZ );
value->it_interval.tv_nsec = ( long ) ( ( xTimerExpirationPeriod % configTICK_RATE_HZ ) * NANOSECONDS_PER_TICK );
}
else
{
value->it_interval.tv_sec = 0;
value->it_interval.tv_nsec = 0;
}
return 0;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,54 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_unistd.c
* @brief Implementation of functions in unistd.h
*/
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/unistd.h"
/*-----------------------------------------------------------*/
unsigned sleep( unsigned seconds )
{
vTaskDelay( pdMS_TO_TICKS( seconds * 1000 ) );
return 0;
}
/*-----------------------------------------------------------*/
int usleep( useconds_t usec )
{
/* To avoid delaying for less than usec, always round up. */
vTaskDelay( pdMS_TO_TICKS( usec / 1000 + ( usec % 1000 != 0 ) ) );
return 0;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,251 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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_POSIX_utils.c
* @brief Implementation of utility functions in utils.h
*/
/* C standard library includes. */
#include <stddef.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX.h"
#include "FreeRTOS_POSIX/errno.h"
#include "FreeRTOS_POSIX/utils.h"
/*-----------------------------------------------------------*/
size_t UTILS_strnlen( const char * const pcString,
size_t xMaxLength )
{
const char * pcCharPointer = pcString;
size_t xLength = 0;
if( pcString != NULL )
{
while( ( *pcCharPointer != '\0' ) && ( xLength < xMaxLength ) )
{
xLength++;
pcCharPointer++;
}
}
return xLength;
}
/*-----------------------------------------------------------*/
int UTILS_AbsoluteTimespecToTicks( const struct timespec * const pxAbsoluteTime,
TickType_t * const pxResult )
{
int iStatus = 0;
struct timespec xCurrentTime = { 0 }, xDifference = { 0 };
/* Check parameters. */
if( ( pxAbsoluteTime == NULL ) || ( pxResult == NULL ) )
{
iStatus = EINVAL;
}
/* Get the current time. */
if( iStatus == 0 )
{
if( clock_gettime( CLOCK_REALTIME, &xCurrentTime ) != 0 )
{
iStatus = errno;
}
}
/* Calculate the difference between the current time and pxAbsoluteTime. */
if( iStatus == 0 )
{
if( UTILS_TimespecSubtract( &xDifference, pxAbsoluteTime, &xCurrentTime ) != 0 )
{
/* pxAbsoluteTime was in the past. */
iStatus = ETIMEDOUT;
}
}
/* Convert the time difference to ticks. */
if( iStatus == 0 )
{
iStatus = UTILS_TimespecToTicks( &xDifference, pxResult );
}
return iStatus;
}
/*-----------------------------------------------------------*/
int UTILS_TimespecToTicks( const struct timespec * const pxTimespec,
TickType_t * const pxResult )
{
int iStatus = 0;
uint64_t ullTotalTicks = 0;
long lNanoseconds = 0;
/* Check parameters. */
if( ( pxTimespec == NULL ) || ( pxResult == NULL ) )
{
iStatus = EINVAL;
}
else if( ( pxTimespec != NULL ) && ( UTILS_ValidateTimespec( pxTimespec ) == false ) )
{
iStatus = EINVAL;
}
if( iStatus == 0 )
{
/* Convert timespec.tv_sec to ticks. */
ullTotalTicks = ( uint64_t ) configTICK_RATE_HZ * ( uint64_t ) ( pxTimespec->tv_sec );
/* Convert timespec.tv_nsec to ticks. This value does not have to be checked
* for overflow because a valid timespec has 0 <= tv_nsec < 1000000000 and
* NANOSECONDS_PER_TICK > 1. */
lNanoseconds = pxTimespec->tv_nsec / ( long ) NANOSECONDS_PER_TICK + /* Whole nanoseconds. */
( long ) ( pxTimespec->tv_nsec % ( long ) NANOSECONDS_PER_TICK != 0 ); /* Add 1 to round up if needed. */
/* Add the nanoseconds to the total ticks. */
ullTotalTicks += ( uint64_t ) lNanoseconds;
/* Write result. */
*pxResult = ( TickType_t ) ullTotalTicks;
}
return iStatus;
}
/*-----------------------------------------------------------*/
void UTILS_NanosecondsToTimespec( int64_t llSource,
struct timespec * const pxDestination )
{
long lCarrySec = 0;
/* Convert to timespec. */
pxDestination->tv_sec = ( time_t ) ( llSource / NANOSECONDS_PER_SECOND );
pxDestination->tv_nsec = ( long ) ( llSource % NANOSECONDS_PER_SECOND );
/* Subtract from tv_sec if tv_nsec < 0. */
if( pxDestination->tv_nsec < 0L )
{
/* Compute the number of seconds to carry. */
lCarrySec = ( pxDestination->tv_nsec / ( long ) NANOSECONDS_PER_SECOND ) + 1L;
pxDestination->tv_sec -= ( time_t ) ( lCarrySec );
pxDestination->tv_nsec += lCarrySec * ( long ) NANOSECONDS_PER_SECOND;
}
}
/*-----------------------------------------------------------*/
int UTILS_TimespecAdd( struct timespec * const pxResult,
const struct timespec * const x,
const struct timespec * const y )
{
int64_t llResult64 = 0;
/* Check parameters. */
if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) )
{
return -1;
}
/* Perform addition. */
llResult64 = ( ( ( int64_t ) ( x->tv_sec ) * NANOSECONDS_PER_SECOND ) + ( int64_t ) ( x->tv_nsec ) )
+ ( ( ( int64_t ) ( y->tv_sec ) * NANOSECONDS_PER_SECOND ) + ( int64_t ) ( y->tv_nsec ) );
/* Convert result to timespec. */
UTILS_NanosecondsToTimespec( llResult64, pxResult );
return ( int ) ( llResult64 < 0LL );
}
/*-----------------------------------------------------------*/
int UTILS_TimespecAddNanoseconds( struct timespec * const pxResult,
const struct timespec * const x,
int64_t llNanoseconds )
{
struct timespec y = { .tv_sec = ( time_t ) 0, .tv_nsec = 0L };
/* Check parameters. */
if( ( pxResult == NULL ) || ( x == NULL ) )
{
return -1;
}
/* Convert llNanoseconds to a timespec. */
UTILS_NanosecondsToTimespec( llNanoseconds, &y );
/* Perform addition. */
return UTILS_TimespecAdd( pxResult, x, &y );
}
/*-----------------------------------------------------------*/
int UTILS_TimespecSubtract( struct timespec * const pxResult,
const struct timespec * const x,
const struct timespec * const y )
{
int64_t llResult64 = 0;
/* Check parameters. */
if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) )
{
return -1;
}
/* Perform addition. */
llResult64 = ( ( ( int64_t ) ( x->tv_sec ) * NANOSECONDS_PER_SECOND ) + ( int64_t ) ( x->tv_nsec ) )
- ( ( ( int64_t ) ( y->tv_sec ) * NANOSECONDS_PER_SECOND ) + ( int64_t ) ( y->tv_nsec ) );
/* Convert result to timespec. */
UTILS_NanosecondsToTimespec( llResult64, pxResult );
return ( int ) ( llResult64 < 0LL );
}
/*-----------------------------------------------------------*/
bool UTILS_ValidateTimespec( const struct timespec * const pxTimespec )
{
bool xReturn = false;
if( pxTimespec != NULL )
{
/* Verify 0 <= tv_nsec < 1000000000. */
if( ( pxTimespec->tv_nsec >= 0 ) &&
( pxTimespec->tv_nsec < NANOSECONDS_PER_SECOND ) )
{
xReturn = true;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,97 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 errno.h
* @brief System error numbers.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
*
* The values defined in this file may not be compatible with the strerror
* function provided by this system.
*/
#ifndef _FREERTOS_POSIX_ERRNO_H_
#define _FREERTOS_POSIX_ERRNO_H_
/* Undefine all errnos to avoid redefinition errors with system errnos. */
#undef EPERM
#undef ENOENT
#undef EBADF
#undef EAGAIN
#undef ENOMEM
#undef EEXIST
#undef EBUSY
#undef EINVAL
#undef ENOSPC
#undef ERANGE
#undef ENAMETOOLONG
#undef EDEADLK
#undef EOVERFLOW
#undef ENOSYS
#undef EMSGSIZE
#undef ENOTSUP
#undef ETIMEDOUT
/**
* @brief posix_errno Definition of POSIX errnos.
*/
/**@{ */
#define EPERM 1 /**< Operation not permitted. */
#define ENOENT 2 /**< No such file or directory. */
#define EBADF 9 /**< Bad file descriptor. */
#define EAGAIN 11 /**< Resource unavailable, try again. */
#define ENOMEM 12 /**< Not enough space. */
#define EEXIST 17 /**< File exists. */
#define EBUSY 16 /**< Device or resource busy. */
#define EINVAL 22 /**< Invalid argument. */
#define ENOSPC 28 /**< No space left on device. */
#define ERANGE 34 /**< Result too large. */
#define ENAMETOOLONG 36 /**< File name too long. */
#define EDEADLK 45 /**< Resource deadlock would occur. */
#define EOVERFLOW 75 /**< Value too large to be stored in data type. */
#define ENOSYS 88 /**< Function not supported. */
#define EMSGSIZE 90 /**< Message too long. */
#define ENOTSUP 95 /**< Operation not supported. */
#define ETIMEDOUT 116 /**< Connection timed out. */
/**@} */
/**
* @name System Variable
*
* @brief Define FreeRTOS+POSIX errno, if enabled.
* Set configUSE_POSIX_ERRNO to enable, and clear to disable. See FreeRTOS.h.
*
* @{
*/
#if ( configUSE_POSIX_ERRNO == 1 )
extern int FreeRTOS_errno;
#ifndef errno
#define errno FreeRTOS_errno
#endif
#endif
/**@} */
#endif /* ifndef _FREERTOS_POSIX_ERRNO_H_ */

View File

@ -0,0 +1,82 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 fcntl.h
* @brief File control options.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html
*/
#ifndef _FREERTOS_POSIX_FCNTL_H_
#define _FREERTOS_POSIX_FCNTL_H_
/**
* @name File creation flags for use in the oflag value to open() and openat().
*
* @{
*/
#define O_CLOEXEC 0x0001 /**< Close the file descriptor upon exec(). */
#define O_CREAT 0x0002 /**< Create file if it does not exist. */
#define O_DIRECTORY 0x0004 /**< Fail if file is a non-directory file. */
#define O_EXCL 0x0008 /**< Exclusive use flag. */
#define O_NOCTTY 0x0010 /**< Do not assign controlling terminal. */
#define O_NOFOLLOW 0x0020 /**< Do not follow symbolic links. */
#define O_TRUNC 0x0040 /**< Truncate flag. */
#define O_TTY_INIT 0x0080 /**< termios structure provides conforming behavior. */
/**@} */
/**
* @name File status flags for open(), openat(), and fcntl().
*
* @{
*/
#define O_APPEND 0x0100 /**< Set append mode. */
#define O_DSYNC 0x0200 /**< Write according to synchronized I/O data integrity completion. */
#define O_NONBLOCK 0x0400 /**< Non-blocking mode. */
#define O_RSYNC 0x0800 /**< Synchronized read I/O operations. */
#define O_SYNC 0x0200 /**< Write according to synchronized I/O file integrity completion. */
/**@} */
/**
* @name Mask for file access modes.
*
* @{
*/
#define O_ACCMODE 0xF000
/**
* @name File access modes for open(), openat(), and fcntl().
*
* @{
*/
#define O_EXEC 0x1000 /**< Open for execute only (non-directory files). */
#define O_RDONLY 0x2000 /**< Open for reading only. */
#define O_RDWR 0xA000 /**< Open for reading and writing. */
#define O_SEARCH 0x4000 /**< Open directory for search only. */
#define O_WRONLY 0x8000 /**< Open for writing only. */
/**@} */
#endif /* ifndef _FREERTOS_POSIX_FCNTL_H_ */

View File

@ -0,0 +1,252 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 mqueue.h
* @brief Message queues.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/mqueue.h.html
*/
#ifndef _FREERTOS_POSIX_MQUEUE_H_
#define _FREERTOS_POSIX_MQUEUE_H_
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX/time.h"
/**
* @brief Message queue descriptor.
*/
typedef void * mqd_t;
/**
* @brief Message queue attributes.
*/
struct mq_attr
{
long mq_flags; /**< Message queue flags. */
long mq_maxmsg; /**< Maximum number of messages. */
long mq_msgsize; /**< Maximum message size. */
long mq_curmsgs; /**< Number of messages currently queued. */
};
/**
* @brief Close a message queue.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html
*
* @retval 0 - Upon successful completion
* @retval -1 - A error occurred. errno is also set.
*
* \sideeffect Possible errno values
* <br>
* EBADF - The mqdes argument is not a valid message queue descriptor.
*/
int mq_close( mqd_t mqdes );
/**
* @brief Get message queue attributes.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html
*
* @retval 0 - Upon successful completion
* @retval -1 - A error occurred. errno is also set.
*
* \sideeffect Possible errno values
* <br>
* DBADF - The mqdes argument is not a valid message queue descriptor.
*/
int mq_getattr( mqd_t mqdes,
struct mq_attr * mqstat );
/**
* @brief Open a message queue.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html
*
* @note Supported name pattern: leading &lt;slash&gt; character in name is always required;
* the maximum length (excluding null-terminator) of the name argument can be NAME_MAX.
* The default value of NAME_MAX in FreeRTOS_POSIX_portable_default.h is 64, which can be
* overwritten by user.
* @note mode argument is not supported.
* @note Supported oflags: O_RDWR, O_CREAT, O_EXCL, and O_NONBLOCK.
*
* @retval Message queue descriptor -- Upon successful completion
* @retval (mqd_t) - 1 -- An error occurred. errno is also set.
*
* \sideeffect Possible errno values
* <br>
* EINVAL - name argument is invalid (not following name pattern),
* OR if O_CREAT is specified in oflag with attr argument not NULL and either mq_maxmsg or mq_msgsize is equal to or less than zero,
* OR either O_CREAT or O_EXCL is not set and a queue with the same name is unlinked but pending to be removed.
* <br>
* EEXIST - O_CREAT and O_EXCL are set and the named message queue already exists.
* <br>
* ENOSPC - There is insufficient space for the creation of the new message queue.
* <br>
* ENOENT - O_CREAT is not set and the named message queue does not exist.
*/
mqd_t mq_open( const char * name,
int oflag,
mode_t mode,
struct mq_attr * attr );
/**
* @brief Receive a message from a message queue.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html
*
* @note msg_prio argument is not supported. Messages are not checked for corruption.
*
* @retval The length of the selected message in bytes - Upon successful completion.
* The message is removed from the queue
* @retval -1 - An error occurred. errno is also set.
*
* \sideeffect Possible errno values
* <br>
* EBADF - The mqdes argument is not a valid message queue descriptor open for reading.
* <br>
* EMSGSIZE - The specified message buffer size, msg_len, is less than the message size attribute of the message queue.
* <br>
* ETIMEDOUT - The O_NONBLOCK flag was not set when the message queue was opened,
* but no message arrived on the queue before the specified timeout expired.
* <br>
* EAGAIN - O_NONBLOCK was set in the message description associated with mqdes, and the specified message queue is empty.
*/
ssize_t mq_receive( mqd_t mqdes,
char * msg_ptr,
size_t msg_len,
unsigned int * msg_prio );
/**
* @brief Send a message to a message queue.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html
*
* @note msg_prio argument is not supported.
*
* @retval 0 - Upon successful completion.
* @retval -1 - An error occurred. errno is also set.
*
* \sideeffect Possible errno values
* <br>
* EBADF - The mqdes argument is not a valid message queue descriptor open for writing.
* <br>
* EMSGSIZE - The specified message length, msg_len, exceeds the message size attribute of the message queue,
* OR insufficient memory for the message to be sent.
* <br>
* ETIMEDOUT - The O_NONBLOCK flag was not set when the message queue was opened,
* but the timeout expired before the message could be added to the queue.
* <br>
* EAGAIN - The O_NONBLOCK flag is set in the message queue description associated with mqdes,
* and the specified message queue is full.
*
*/
int mq_send( mqd_t mqdes,
const char * msg_ptr,
size_t msg_len,
unsigned msg_prio );
/**
* @brief Receive a message from a message queue with timeout.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_timedreceive.html
*
* @note msg_prio argument is not supported. Messages are not checked for corruption.
*
* @retval The length of the selected message in bytes - Upon successful completion.
* The message is removed from the queue
* @retval -1 - An error occurred. errno is also set.
*
* \sideeffect Possible errno values
* <br>
* EBADF - The mqdes argument is not a valid message queue descriptor open for reading.
* <br>
* EMSGSIZE - The specified message buffer size, msg_len, is less than the message size attribute of the message queue.
* <br>
* EINVAL - The process or thread would have blocked, and the abstime parameter specified a nanoseconds field value
* less than zero or greater than or equal to 1000 million.
* <br>
* ETIMEDOUT - The O_NONBLOCK flag was not set when the message queue was opened,
* but no message arrived on the queue before the specified timeout expired.
* <br>
* EAGAIN - O_NONBLOCK was set in the message description associated with mqdes, and the specified message queue is empty.
*/
ssize_t mq_timedreceive( mqd_t mqdes,
char * msg_ptr,
size_t msg_len,
unsigned * msg_prio,
const struct timespec * abstime );
/**
* @brief Send a message to a message queue with timeout.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_timedsend.html
*
* @note msg_prio argument is not supported.
*
* @retval 0 - Upon successful completion.
* @retval -1 - An error occurred. errno is also set.
*
* \sideeffect Possible errno values
* <br>
* EBADF - The mqdes argument is not a valid message queue descriptor open for writing.
* <br>
* EMSGSIZE - The specified message length, msg_len, exceeds the message size attribute of the message queue,
* OR insufficient memory for the message to be sent.
* <br>
* EINVAL - The process or thread would have blocked, and the abstime parameter specified a nanoseconds field
* value less than zero or greater than or equal to 1000 million.
* <br>
* ETIMEDOUT - The O_NONBLOCK flag was not set when the message queue was opened,
* but the timeout expired before the message could be added to the queue.
* <br>
* EAGAIN - The O_NONBLOCK flag is set in the message queue description associated with mqdes,
* and the specified message queue is full.
*
*/
int mq_timedsend( mqd_t mqdes,
const char * msg_ptr,
size_t msg_len,
unsigned msg_prio,
const struct timespec * abstime );
/**
* @brief Remove a message queue.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html
*
* @retval 0 - Upon successful completion.
* @retval -1 - An error occurred. errno is also set.
*
* \sideeffect Possible errno values
* <br>
* EINVAL - name argument is invalid. Refer to requirements on name argument in mq_open().
* <br>
* ENOENT - The named message queue does not exist.
*/
int mq_unlink( const char * name );
#endif /* ifndef _FREERTOS_POSIX_MQUEUE_H_ */

View File

@ -0,0 +1,479 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 pthread.h
* @brief Threads.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html
*/
#ifndef _FREERTOS_POSIX_PTHREAD_H_
#define _FREERTOS_POSIX_PTHREAD_H_
/* FreeRTOS+POSIX includes. POSIX states that this header shall make symbols
* defined in sched.h and time.h visible. */
#include "FreeRTOS_POSIX/sched.h"
#include "FreeRTOS_POSIX/time.h"
/**
* @brief pthread detach state.
*/
/**@{ */
#define PTHREAD_CREATE_DETACHED 0 /**< Detached. */
#define PTHREAD_CREATE_JOINABLE 1 /**< Joinable (default). */
/**@} */
/**
* @brief Returned to a single thread after a successful pthread_barrier_wait.
*
* POSIX specifies that "The constant PTHREAD_BARRIER_SERIAL_THREAD is defined in <pthread.h> and its value shall be distinct from any other value returned by pthread_barrier_wait()."
* So it's defined as negative to distinguish it from the errnos, which are positive.
*/
#define PTHREAD_BARRIER_SERIAL_THREAD ( -2 )
/**
* @brief Mutex types.
*/
/**@{ */
#ifndef PTHREAD_MUTEX_NORMAL
#define PTHREAD_MUTEX_NORMAL 0 /**< Non-robust, deadlock on relock, does not remember owner. */
#endif
#ifndef PTHREAD_MUTEX_ERRORCHECK
#define PTHREAD_MUTEX_ERRORCHECK 1 /**< Non-robust, error on relock, remembers owner. */
#endif
#ifndef PTHREAD_MUTEX_RECURSIVE
#define PTHREAD_MUTEX_RECURSIVE 2 /**< Non-robust, recursive relock, remembers owner. */
#endif
#ifndef PTHREAD_MUTEX_DEFAULT
#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL /**< PTHREAD_MUTEX_NORMAL (default). */
#endif
/**@} */
/**
* @brief Compile-time initializers.
*/
/**@{ */
#define PTHREAD_COND_INITIALIZER FREERTOS_POSIX_COND_INITIALIZER /**< pthread_cond_t. */
#if posixconfigENABLE_PTHREAD_MUTEX_T == 1
/**
* @brief To use this initializer, posixconfigENABLE_PTHREAD_MUTEX_T needs to be set to 1 in FreeRTOS_POSIX_portable_default.h.
*/
#define PTHREAD_MUTEX_INITIALIZER FREERTOS_POSIX_MUTEX_INITIALIZER /**< pthread_mutex_t. */
#endif
/**@} */
/**
* @brief Destroy the thread attributes object.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_destroy.html
*
* @retval 0 - Upon successful completion
*/
int pthread_attr_destroy( pthread_attr_t * attr );
/**
* @brief Get detachstate attribute.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getdetachstate.html
*
* @retval 0 - Upon successful completion
*
*/
int pthread_attr_getdetachstate( const pthread_attr_t * attr,
int * detachstate );
/**
* @brief Get schedparam attribute.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getschedparam.html
*
* @retval 0 - Upon successful completion
*/
int pthread_attr_getschedparam( const pthread_attr_t * attr,
struct sched_param * param );
/**
* @brief Get stacksize attribute.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getstacksize.html
*
* @retval 0 - Upon successful completion
*/
int pthread_attr_getstacksize( const pthread_attr_t * attr,
size_t * stacksize );
/**
* @brief Initialize the thread attributes object.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_init.html
*
* @retval 0 - Upon successful completion
* @retval ENOMEM - Insufficient memory exists to initialize the thread attributes object.
*
* @note Currently, only stack size, sched param, and detach state attributes
* are supported. Also see pthread_attr_get*() and pthread_attr_set*().
*/
int pthread_attr_init( pthread_attr_t * attr );
/**
* @brief Set detachstate attribute.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setdetachstate.html
*
* @retval 0 - Upon successful completion
* @retval EINVAL - The value of detachstate was not valid. Currently, supported detach states are -- PTHREAD_CREATE_DETACHED and PTHREAD_CREATE_JOINABLE.
*/
int pthread_attr_setdetachstate( pthread_attr_t * attr,
int detachstate );
/**
* @brief Set schedparam attribute.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setschedparam.html
*
* @retval 0 - Upon successful completion
* @retval EINVAL - The value of param is not valid.
* @retval ENOTSUP - An attempt was made to set the attribute to an unsupported value.
*/
int pthread_attr_setschedparam( pthread_attr_t * attr,
const struct sched_param * param );
/**
* @brief Set stacksize attribute.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setstacksize.html
*
* @retval 0 - Upon successful completion
* @retval EINVAL - The value of stacksize is less than {PTHREAD_STACK_MIN}
*/
int pthread_attr_setstacksize( pthread_attr_t * attr,
size_t stacksize );
/**
* @brief Destroy a barrier object.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_barrier_destroy.html
*
* @retval 0 - Upon successful completion
*
* @note This function does not validate whether there is any thread blocking on the barrier before destroying.
*/
int pthread_barrier_destroy( pthread_barrier_t * barrier );
/**
* @brief Initialize a barrier object.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_barrier_init.html
*
* @retval 0 - Upon successful completion
* @retval EINVAL - The value specified by count is equal to zero.
* @retval ENOMEM - count cannot fit into FreeRTOS event group type OR insufficient memory exists to initialize the barrier.
*
* @note attr is ignored.
*
* @note pthread_barrier_init() is implemented with FreeRTOS event group.
* To ensure count fits in event group, count may be at most 8 when configUSE_16_BIT_TICKS is 1; it may be at most 24 otherwise.
* configUSE_16_BIT_TICKS is configured in application FreeRTOSConfig.h file, which defines how many bits tick count type has.
* See further details and limitation about event group and configUSE_16_BIT_TICKS in FreeRTOS site.
*/
int pthread_barrier_init( pthread_barrier_t * barrier,
const pthread_barrierattr_t * attr,
unsigned count );
/**
* @brief Synchronize at a barrier.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_barrier_wait.html
*
* @retval PTHREAD_BARRIER_SERIAL_THREAD - Upon successful completion, the first thread.
* @retval 0 - Upon successful completion, other thread(s).
*/
int pthread_barrier_wait( pthread_barrier_t * barrier );
/**
* @brief Thread creation.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html
*
* @retval 0 - Upon successful completion
* @retval EAGAIN - Insufficient memory for either thread structure or task creation.
*/
int pthread_create( pthread_t * thread,
const pthread_attr_t * attr,
void *( *startroutine )( void * ),
void * arg );
/**
* @brief Broadcast a condition.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_broadcast.html
*
* @retval 0 - Upon successful completion
*/
int pthread_cond_broadcast( pthread_cond_t * cond );
/**
* @brief Destroy condition variables.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_destroy.html
*
* @retval 0 - Upon successful completion
*/
int pthread_cond_destroy( pthread_cond_t * cond );
/**
* @brief Initialize condition variables.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_init.html
*
* @retval 0 - Upon successful completion
* @retval ENOMEM - Insufficient memory exists to initialize the condition variable.
*
* @note attr is ignored and treated as NULL. Default setting is always used.
*/
int pthread_cond_init( pthread_cond_t * cond,
const pthread_condattr_t * attr );
/**
* @brief Signal a condition.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_signal.html
*
* @retval 0 - Upon successful completion
*/
int pthread_cond_signal( pthread_cond_t * cond );
/**
* @brief Wait on a condition with a timeout.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html
*
* @retval 0 - Upon successful completion
* @retval EINVAL - The abstime argument passed in does not refer to an initialized structure OR
* the abstime parameter specified a nanoseconds field value less than zero or greater than or equal to 1000 million.
* @retval ETIMEDOUT - The time specified by abstime to pthread_cond_timedwait() has passed.
*/
int pthread_cond_timedwait( pthread_cond_t * cond,
pthread_mutex_t * mutex,
const struct timespec * abstime );
/**
* @brief Wait on a condition.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_wait.html
*
* @retval 0 - Upon successful completion
*/
int pthread_cond_wait( pthread_cond_t * cond,
pthread_mutex_t * mutex );
/**
* @brief Compare thread IDs.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_equal.html
*
* @retval 0 - t1 and t2 are both not NULL && equal
* @retval non-zero - otherwise
*/
int pthread_equal( pthread_t t1,
pthread_t t2 );
/**
* @brief Thread termination.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_exit.html
*
* @retval void - this function cannot return to its caller.
*/
void pthread_exit( void * value_ptr );
/**
* @brief Dynamic thread scheduling parameters access.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getschedparam.html
*
* @retval 0 - Upon successful completion
*
* @note policy is always set to SCHED_OTHER by this function.
*/
int pthread_getschedparam( pthread_t thread,
int * policy,
struct sched_param * param );
/**
* @brief Wait for thread termination.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html
*
* @retval 0 - Upon successful completion
* @retval EDEADLK - The value specified by the thread argument to pthread_join() does not refer to
* a joinable thread OR multiple simultaneous calls to pthread_join() specifying the same target thread OR
* the value specified by the thread argument to pthread_join() refers to the calling thread.
*/
int pthread_join( pthread_t thread,
void ** retval );
/**
* @brief Destroy a mutex.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_destroy.html
*
* @retval 0 - Upon successful completion
*
* @note If there exists a thread holding this mutex, this function returns 0 with mutex not being destroyed.
*
*/
int pthread_mutex_destroy( pthread_mutex_t * mutex );
/**
* @brief Initialize a mutex.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_init.html
*
* @retval 0 - Upon successful completion
* @retval ENOMEM - Insufficient memory exists to initialize the mutex structure.
* @retval EAGAIN - Unable to initialize the mutex structure member(s).
*/
int pthread_mutex_init( pthread_mutex_t * mutex,
const pthread_mutexattr_t * attr );
/**
* @brief Lock a mutex.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html
*
* @retval 0 - Upon successful completion
* @retval EINVAL - the abstime parameter specified a nanoseconds field value less than zero or greater than or equal to 1000 million.
* @retval EDEADLK - The mutex type is PTHREAD_MUTEX_ERRORCHECK and the current thread already owns the mutex.
*
*/
int pthread_mutex_lock( pthread_mutex_t * mutex );
/**
* @brief Lock a mutex with timeout.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_timedlock.html
*
* @retval 0 - Upon successful completion
* @retval EINVAL - The abstime argument passed in does not refer to an initialized structure OR
* the abstime parameter specified a nanoseconds field value less than zero or greater than or equal to 1000 million.
* @retval EDEADLK - The mutex type is PTHREAD_MUTEX_ERRORCHECK and the current thread already owns the mutex.
* @retval ETIMEDOUT - The mutex could not be locked before the specified timeout expired.
*
*/
int pthread_mutex_timedlock( pthread_mutex_t * mutex,
const struct timespec * abstime );
/**
* @brief Attempt to lock a mutex. Fail immediately if mutex is already locked.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_trylock.html
*
* @retval 0 - Upon successful completion
* @retval EINVAL - the abstime parameter specified a nanoseconds field value less than zero or greater than or equal to 1000 million.
* @retval EDEADLK - The mutex type is PTHREAD_MUTEX_ERRORCHECK and the current thread already owns the mutex.
* @retval EBUSY - The mutex could not be acquired because it was already locked.
*
*/
int pthread_mutex_trylock( pthread_mutex_t * mutex );
/**
* @brief Unlock a mutex.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html
*
* @retval 0 - Upon successful completion
* @retval EPERM - The mutex type is PTHREAD_MUTEX_ERRORCHECK or PTHREAD_MUTEX_RECURSIVE, and the current thread does not own the mutex.
*/
int pthread_mutex_unlock( pthread_mutex_t * mutex );
/**
* @brief Destroy the mutex attributes object.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_destroy.html
*
* @retval 0 - Upon successful completion
*/
int pthread_mutexattr_destroy( pthread_mutexattr_t * attr );
/**
* @brief Get the mutex type attribute.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_gettype.html
*
* @retval 0 - Upon successful completion
*/
int pthread_mutexattr_gettype( const pthread_mutexattr_t * attr,
int * type );
/**
* @brief Initialize the mutex attributes object.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_init.html
*
* @retval 0 - Upon successful completion
* @retval ENOMEM - Insufficient memory exists to initialize the mutex attributes object.
*
* @note Currently, only the type attribute is supported. Also see pthread_mutexattr_settype() and pthread_mutexattr_gettype().
*/
int pthread_mutexattr_init( pthread_mutexattr_t * attr );
/**
* @brief Set the mutex type attribute.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_settype.html
*
* @retval 0 - Upon successful completion
* @retval EINVAL - The value type is invalid.
*/
int pthread_mutexattr_settype( pthread_mutexattr_t * attr,
int type );
/**
* @brief Get the calling thread ID.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html
*
* @retval the thread ID of the calling thread.
*/
pthread_t pthread_self( void );
/**
* @brief Dynamic thread scheduling parameters access.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_setschedparam.html
*
* @retval 0 - Upon successful completion
*
* @note policy is ignored; only priority (param.sched_priority) may be changed.
*/
int pthread_setschedparam( pthread_t thread,
int policy,
const struct sched_param * param );
#endif /* _FREERTOS_POSIX_PTHREAD_H_ */

View File

@ -0,0 +1,75 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 sched.h
* @brief Execution scheduling.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sched.h.html
*/
#ifndef _FREERTOS_POSIX_SCHED_H_
#define _FREERTOS_POSIX_SCHED_H_
/**
* @brief Scheduling Policies
*/
/**@{ */
#define SCHED_OTHER 0 /**< Another scheduling policy. */
/**@} */
/**
* @brief Scheduling parameters required for implementation of each supported
* scheduling policy.
*/
struct sched_param
{
int sched_priority; /**< Process or thread execution scheduling priority. */
};
/**
* @brief Get priority limit.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_get_priority_max.html
*
* @note policy is ignored.
*
* @return the maxium priority value (0-based) system configuration allows.
* <br>
* e.g. if configMAX_PRIORITIES == 7, this function returns (configMAX_PRIORITIES - 1).
* configMAX_PRIORITIES is configured in appication FreeRTOSConfig.h file.
*/
int sched_get_priority_max( int policy );
/**
* @brief Yield the processor.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html
*
* @retval 0 - Upon successful completion
*/
int sched_yield( void );
#endif /* ifndef _FREERTOS_POSIX_SCHED_H_ */

View File

@ -0,0 +1,143 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 semaphore.h
* @brief Semaphores.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/semaphore.h.html
*/
#ifndef _FREERTOS_POSIX_SEMAPHORE_H_
#define _FREERTOS_POSIX_SEMAPHORE_H_
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX/time.h"
/**
* @brief Semaphore type.
*/
typedef void * sem_t;
/**
* @brief Destroy an unnamed semaphore.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html
*
* @retval 0 - upon successful completion
*
* @note Semaphore is destroyed regardless of whether there is any thread currently blocked on this semaphore.
*/
int sem_destroy( sem_t * sem );
/**
* @brief Get the value of a semaphore.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html
*
* @retval 0 - Upon successful completion
*
* @note If sem is locked, then the object to which sval points is set to zero.
*/
int sem_getvalue( sem_t * sem,
int * sval );
/**
* @brief Initialize an unnamed semaphore.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html
*
* @note pshared is ignored. Semaphores will always be considered "shared".
*
* @retval 0 - upon successful completion
* @retval -1 - otherwise. System error variable errno is also set in this case.
*
* \sideeffect Possible errno values
* <br>
* EINVAL - The value argument exceeds {SEM_VALUE_MAX}.
* <br>
* ENOSPC - A resource required to initialize the semaphore has been exhausted.
*
*/
int sem_init( sem_t * sem,
int pshared,
unsigned value );
/**
* @brief Unlock a semaphore.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html
*
* @retval 0 - upon successful completion
*/
int sem_post( sem_t * sem );
/**
* @brief Lock a semaphore with timeout.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html
*
* @retval 0 - upon successful completion
* @retval -1 - otherwise. System error variable errno is also set in this case.
*
* \sideeffect Possible errno values
* <br>
* EINVAL - parameter specified a nanoseconds field value less than zero or greater
* than or equal to 1000 million
* <br>
* ETIMEDOUT - The semaphore could not be locked before the specified timeout expired.
*
* @note Deadlock detection is not implemented.
*/
int sem_timedwait( sem_t * sem,
const struct timespec * abstime );
/**
* @brief Lock a semaphore if available.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html
*
* @retval 0 - upon successful completion
* @retval -1 - otherwise. System error variable errno is also set in this case.
*
* \sideeffect Possible errno values
* <br>
* EAGAIN - The semaphore was already locked, so it cannot be immediately locked by the sem_trywait() operation.
*/
int sem_trywait( sem_t * sem );
/**
* @brief Lock a semaphore.
*
* @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_wait.html
*
* @retval 0 - upon successful completion
* @retval -1 - otherwise. System error variable errno is also set in this case.
*
* @note Deadlock detection is not implemented.
*/
int sem_wait( sem_t * sem );
#endif /* ifndef _FREERTOS_POSIX_SEMAPHORE_H_ */

View File

@ -0,0 +1,70 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 signal.h
* @brief Signals.
*
* Signals are currently not implemented in FreeRTOS+POSIX. This header only
* defines the signal data structures used elsewhere.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
*/
#ifndef _FREERTOS_POSIX_SIGNAL_H_
#define _FREERTOS_POSIX_SIGNAL_H_
/**
* @brief Values of sigev_notify.
*/
/**@{ */
#define SIGEV_NONE 0 /**< No asynchronous notification is delivered when the event of interest occurs. */
#define SIGEV_SIGNAL 1 /**< A queued signal, with an application-defined value, is generated when the event of interest occurs. Not supported. */
#define SIGEV_THREAD 2 /**< A notification function is called to perform notification. */
/**@} */
/**
* @brief Signal value.
*/
union sigval
{
int sival_int; /**< Integer signal value. */
void * sival_ptr; /**< Pointer signal value. */
};
/**
* @brief Signal event structure.
*/
struct sigevent
{
int sigev_notify; /**< Notification type. A value of SIGEV_SIGNAL is not supported. */
int sigev_signo; /**< Signal number. This member is ignored. */
union sigval sigev_value; /**< Signal value. Only the sival_ptr member is used. */
void ( * sigev_notify_function ) ( union sigval ); /**< Notification function. */
pthread_attr_t * sigev_notify_attributes; /**< Notification attributes. */
};
#endif /* ifndef _FREERTOS_POSIX_SIGNAL_H_ */

View File

@ -0,0 +1,161 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 sys/types.h
* @brief Data types.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html
*/
#ifndef _FREERTOS_POSIX_TYPES_H_
#define _FREERTOS_POSIX_TYPES_H_
/* C standard library includes. */
#include <stdint.h>
/**
* @brief Used for system times in clock ticks or CLOCKS_PER_SEC.
* Enabled/disabled by posixconfigENABLE_CLOCK_T.
*/
#if !defined( posixconfigENABLE_CLOCK_T ) || ( posixconfigENABLE_CLOCK_T == 1 )
typedef uint32_t clock_t;
#endif
/**
* @brief Used for clock ID type in the clock and timer functions.
* Enabled/disabled by posixconfigENABLE_CLOCKID_T.
*/
#if !defined( posixconfigENABLE_CLOCKID_T ) || ( posixconfigENABLE_CLOCKID_T == 1 )
typedef int clockid_t;
#endif
/**
* @brief Used for some file attributes.
* Enabled/disabled by posixconfigENABLE_MODE_T.
*/
#if !defined( posixconfigENABLE_MODE_T ) || ( posixconfigENABLE_MODE_T == 1 )
typedef int mode_t;
#endif
/**
* @brief Used for process IDs and process group IDs.
* Enabled/disabled by posixconfigENABLE_PID_T.
*/
#if !defined( posixconfigENABLE_PID_T ) || ( posixconfigENABLE_PID_T == 1 )
typedef int pid_t;
#endif
/**
* @brief Used to identify a thread attribute object.
* Enabled/disabled by posixconfigENABLE_PTHREAD_ATTR_T.
*/
#if !defined( posixconfigENABLE_PTHREAD_ATTR_T ) || ( posixconfigENABLE_PTHREAD_ATTR_T == 1 )
typedef void * pthread_attr_t;
#endif
/**
* @brief Used to identify a barrier.
*/
typedef void * pthread_barrier_t;
/**
* @brief Used to define a barrier attributes object.
*/
typedef void * pthread_barrierattr_t;
/**
* @brief Used for condition variables.
* Enabled/disabled by posixconfigENABLE_PTHREAD_COND_T.
*/
#if !defined( posixconfigENABLE_PTHREAD_COND_T ) || ( posixconfigENABLE_PTHREAD_COND_T == 1 )
typedef void * pthread_cond_t;
#endif
/**
* @brief Used to identify a condition attribute object.
* Enabled/disabled by posixconfigENABLE_PTHREAD_CONDATTR_T.
*/
#if !defined( posixconfigENABLE_PTHREAD_CONDATTR_T ) || ( posixconfigENABLE_PTHREAD_CONDATTR_T == 1 )
typedef void * pthread_condattr_t;
#endif
/**
* @brief Used for mutexes.
* Enabled/disabled by posixconfigENABLE_PTHREAD_MUTEX_T.
*/
#if !defined( posixconfigENABLE_PTHREAD_MUTEX_T ) || ( posixconfigENABLE_PTHREAD_MUTEX_T == 1 )
typedef void * pthread_mutex_t;
#endif
/**
* @brief Used to identify a mutex attribute object.
* Enabled/disabled by posixconfigENABLE_PTHREAD_MUTEXATTR_T.
*/
#if !defined( posixconfigENABLE_PTHREAD_MUTEXATTR_T ) || ( posixconfigENABLE_PTHREAD_MUTEXATTR_T == 1 )
typedef void * pthread_mutexattr_t;
#endif
/**
* @brief Used to identify a thread.
* Enabled/disabled by posixconfigENABLE_PTHREAD_T
*/
#if !defined( posixconfigENABLE_PTHREAD_T ) || ( posixconfigENABLE_PTHREAD_T == 1 )
typedef void * pthread_t;
#endif
/**
* @brief Used for a count of bytes or an error indication.
* Enabled/disabled by posixconfigENABLE_SSIZE_T.
*/
#if !defined( posixconfigENABLE_SSIZE_T ) || ( posixconfigENABLE_SSIZE_T == 1 )
typedef int ssize_t;
#endif
/**
* @brief Used for time in seconds.
* Enabled/disabled by posixconfigENABLE_TIME_T.
*/
#if !defined( posixconfigENABLE_TIME_T ) || ( posixconfigENABLE_TIME_T == 1 )
typedef int64_t time_t;
#endif
/**
* @brief Used for timer ID returned by timer_create().
* Enabled/disabled by posixconfigENABLE_TIMER_T.
*/
#if !defined( posixconfigENABLE_TIMER_T ) || ( posixconfigENABLE_TIMER_T == 1 )
typedef void * timer_t;
#endif
/**
* @brief Used for time in microseconds.
* Enabled/disabled by posixconfigENABLE_USECONDS_T.
*/
#if !defined( posixconfigENABLE_USECONDS_T ) || ( posixconfigENABLE_USECONDS_T == 1 )
typedef unsigned long useconds_t;
#endif
#endif /* ifndef _FREERTOS_POSIX_TYPES_H_ */

View File

@ -0,0 +1,318 @@
/*
* Amazon FreeRTOS POSIX V1.0.0
* Copyright (C) 2018 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 time.h
* @brief Time types.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html
*/
#ifndef _FREERTOS_POSIX_TIME_H_
#define _FREERTOS_POSIX_TIME_H_
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX/sys/types.h"
#include "FreeRTOS_POSIX/signal.h"
/**
* @brief Unit conversion constants.
*/
/**@{ */
#define MICROSECONDS_PER_SECOND ( 1000000LL ) /**< Microseconds per second. */
#define NANOSECONDS_PER_SECOND ( 1000000000LL ) /**< Nanoseconds per second. */
#define NANOSECONDS_PER_TICK ( NANOSECONDS_PER_SECOND / configTICK_RATE_HZ ) /**< Nanoseconds per FreeRTOS tick. */
/**@} */
/**
* @brief Clock identifiers.
*/
/**@{ */
#define CLOCK_REALTIME 0 /**< The identifier of the system-wide clock measuring real time. */
#define CLOCK_MONOTONIC 1 /**< The identifier for the system-wide monotonic clock.*/
/**@} */
/**
* @brief A number used to convert the value returned by the clock() function into seconds.
*/
#define CLOCKS_PER_SEC ( ( clock_t ) configTICK_RATE_HZ )
/**
* @brief Flag indicating time is absolute.
*
* For functions taking timer objects, this refers to the clock associated with the timer.
*/
#define TIMER_ABSTIME 0x01
#if !defined( posixconfigENABLE_TIMESPEC ) || ( posixconfigENABLE_TIMESPEC == 1 )
/**
* @brief represents an elapsed time
*/
struct timespec
{
time_t tv_sec; /**< Seconds. */
long tv_nsec; /**< Nanoseconds. */
};
#endif
#if !defined( posixconfigENABLE_ITIMERSPEC ) || ( posixconfigENABLE_ITIMERSPEC == 1 )
/**
* @brief timer
*/
struct itimerspec
{
struct timespec it_interval; /**< Timer period. */
struct timespec it_value; /**< Timer expiration. */
};
#endif
#if !defined( posixconfigENABLE_TM ) || ( posixconfigENABLE_TM == 1 )
/**
* @brief calendar representation of time
*/
struct tm
{
time_t tm_tick; /**< FreeRTOS tick count. */
int tm_sec; /**< Seconds [0,60]. Not used. */
int tm_min; /**< Minutes [0,59]. Not used. */
int tm_hour; /**< Hour [0,23]. Not used. */
int tm_mday; /**< Day of month [1,31]. Not used. */
int tm_mon; /**< Month of year [0,11]. Not used. */
int tm_year; /**< Years since 1900. Not used. */
int tm_wday; /**< Day of week [0,6] (Sunday=0). Not used. */
int tm_yday; /**< Day of year [0,365]. Not used. */
int tm_isdst; /**< Daylight Savings flag. Not used. */
};
#endif
/**
* @brief Report CPU time used.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock.html
*
* @return The number of FreeRTOS ticks since the scheduler
* was started minus the ticks spent in the idle task.
*
* @note This function does NOT report the number of ticks spent by the calling thread.
*/
clock_t clock( void );
/**
* @brief Access a process CPU-time clock.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getcpuclockid.html
*
* @retval EPERM
*
* @note This function is currently unsupported.
*
*/
int clock_getcpuclockid( pid_t pid,
clockid_t * clock_id );
/**
* @brief Returns the resolution of a clock.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html
*
* @note clock_id is ignored
* @note This function stores the resolution of the FreeRTOS tick count in the object res points to.
*
* @retval 0 - Upon successful execution
*/
int clock_getres( clockid_t clock_id,
struct timespec * res );
/**
* @brief Returns the current value for the specified clock, clock_id.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html
*
* @note clock_id is ignored
* @note this function does not check for overflows of time_t.
*
* @retval 0 - Upon successful completion.
*
*/
int clock_gettime( clockid_t clock_id,
struct timespec * tp );
/**
* @brief High resolution sleep with specifiable clock.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_nanosleep.html
*
* @note clock_id is ignored, as this function uses the FreeRTOS tick count as its clock.
* @note flags is ignored, if INCLUDE_vTaskDelayUntil is 0. i.e. the FreeRTOS function vTaskDelayUntil isn't available.
* @note rmtp is also ignored, as signals are not implemented.
*
* @retval 0 - Upon successful completion.
* @retval EINVAL - The rqtp argument specified a nanosecond value less than zero or greater than or equal to 1000 million.
*/
int clock_nanosleep( clockid_t clock_id,
int flags,
const struct timespec * rqtp,
struct timespec * rmtp );
/**
* @brief Sets the time for the specified clock.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_settime.html
*
* @retval -1 with errno set to EPERM.
*
* @note This function is currently unsupported, as FreeRTOS does not provide a function to modify the tick count.
*/
int clock_settime( clockid_t clock_id,
const struct timespec * tp );
/**
* @brief Convert a time value to a broken-down local time.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/localtime_r.html
*
* @note timer is ignored
*
* @note This function can only store the time as tm.tm_tick. All other members of
* the struct will be set to 0.
*
* @note In order to store tm.tm_tick in result, posixconfgENABLE_TM needs to be set to 1.
* See FreeRTOS_POSIX_portable_default.h for porting configurations.
*
* @return Upon successful completion, returns a pointer points to the object holding structure of type tm.
* @return If any error, rutrns NULL, with errno set to ENOTSUP.
*/
struct tm * localtime_r( const time_t * timer,
struct tm * result );
/**
* @brief High resolution sleep.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/nanosleep.html
*
* @note rmtp is ignored, as signals are not implemented.
*
* @retval 0 - Upon successful completion.
* @retval -1 - The rqtp argument is invalid OR the rqtp argument specified a nanosecond value less than zero or greater than or equal to 1000 million.
*
*/
int nanosleep( const struct timespec * rqtp,
struct timespec * rmtp );
/**
* @brief Convert date and time to a string.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html
*
* @note format is ignored.
*
* @retval the number of bytes placed into the array pointed to by s,
* if the total number of resulting bytes including the terminating null byte is not more than maxsize.
* @retval 0, otherwise. In this case, the array pointed to by s contains partially copied data.
*/
size_t strftime( char * s,
size_t maxsize,
const char * format,
const struct tm * timeptr );
/**
* @brief Get time.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/time.html
*
* @note This function returns the FreeRTOS tick count, not the seconds since UNIX epoch.
*
* @retval FreeRTOS tick count - upon successful completion
*/
time_t time( time_t * tloc );
/**
* @brief Create a per-process timer.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_create.html
*
* @note clock_id is ignored, as this function used the FreeRTOS tick count as its clock.
* @note evp.sigev_notify must be set to SIGEV_THREAD, since signals are currently not supported.
*
* @retval 0 - Upon successful completion, with location referenced by timerid updated.
* @retval -1 - If an error occurs. errno is also set.
*
* \sideeffect Possible errno values
* <br>
* ENOTSUP - If evp is NULL OR evp->sigen_notify == SIGEV_SIGNAL.
* <br>
* EAGAIN - The system lacks sufficient signal queuing resources to honor the request.
*/
int timer_create( clockid_t clockid,
struct sigevent * evp,
timer_t * timerid );
/**
* @brief Delete a per-process timer.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_delete.html
*
* @retval 0 - Upon successful completion.
*/
int timer_delete( timer_t timerid );
/**
* @brief Get the timer overrun count.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html
*
* @retval 0 - Always return 0, since signals are not supported.
*/
int timer_getoverrun( timer_t timerid );
/**
* @brief Get the amount of time until the timer expires.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_gettime.html
*
* @retval 0 - Upon successful completion.
*/
int timer_gettime( timer_t timerid,
struct itimerspec * value );
/**
* @brief Set the time until the next expiration of the timer.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_settime.html
*
* @retval 0 - Upon successful completion.
* @retval -1 - An error occured, errno is also set.
*
* \sideeffect Possible errno values
* <br>
* EINVAL - A value structure specified a nanosecond value less than zero or greater than or equal to 1000 million,
* AND the it_value member of that structure did not specify zero seconds and nanoseconds.
*/
int timer_settime( timer_t timerid,
int flags,
const struct itimerspec * value,
struct itimerspec * ovalue );
#endif /* ifndef _FREERTOS_POSIX_TIME_H_ */

View File

@ -0,0 +1,59 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 unistd.h
* @brief Standard symbolic constants and types
*
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html
*/
#ifndef _FREERTOS_POSIX_UNISTD_H_
#define _FREERTOS_POSIX_UNISTD_H_
/**
* @brief Suspend execution for an interval of time.
*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html
*
* @param[in] seconds The number of seconds to suspend execution.
*
* @retval 0 - Upon successful completion.
*
* @note Return value of a positive number is not yet supported.
*/
unsigned sleep( unsigned seconds );
/**
* @brief Suspend execution for microsecond intervals.
*
* This is a useful, non-POSIX function.
* @param[in] usec The number of microseconds to suspend execution.
*
* @retval 0 - Upon successful cocmpletion.
*/
int usleep( useconds_t usec );
#endif /* ifndef _FREERTOS_POSIX_UNISTD_H_ */

View File

@ -0,0 +1,140 @@
/*
* Amazon FreeRTOS+POSIX V1.0.0
* Copyright (C) 2018 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 utils.h
* @brief Utility functions used by FreeRTOS+POSIX.
*/
#ifndef _FREERTOS_POSIX_UTILS_
#define _FREERTOS_POSIX_UTILS_
/* C standard library includes. */
#include <stdbool.h>
#include <stdint.h>
/* FreeRTOS+POSIX includes. */
#include "FreeRTOS_POSIX/time.h"
/**
* @brief Calculates the length of pcString, up to xMaxLength.
*
* @param[in] pcString The string to find the length of.
* @param[in] xMaxLength The limit when searching for the end of pcString.
*
* @return 0 if pcString is NULL; otherwise, the length of pcString or xMaxLength,
* whichever is smaller.
*/
size_t UTILS_strnlen( const char * const pcString,
size_t xMaxLength );
/**
* @brief Calculates the number of ticks between now and a given timespec.
*
* @param[in] pxAbsoluteTime A time in the future, specified as seconds and
* nanoseconds since CLOCK_REALTIME's 0.
* @param[out] pxResult Where the result of the conversion is stored. The result
* is rounded up for fractional ticks.
*
* @return 0 on success. Otherwise, ETIMEDOUT if pxAbsoluteTime is in the past,
* or EINVAL for invalid parameters.
*/
int UTILS_AbsoluteTimespecToTicks( const struct timespec * const pxAbsoluteTime,
TickType_t * const pxResult );
/**
* @brief Converts a struct timespec to FreeRTOS ticks.
*
* @param[in] pxTimespec The timespec to convert.
* @param[out] pxResult Where the result of the conversion is stored. The result is rounded
* up for fractional ticks.
*
* @return 0 on success. Otherwise, EINVAL for invalid parameters.
*/
int UTILS_TimespecToTicks( const struct timespec * const pxTimespec,
TickType_t * const pxResult );
/**
* @brief Converts an integer value to a timespec.
*
* @param[in] llSource The value to convert.
* @param[out] pxDestination Where to store the converted value.
*
* @return No return value.
*/
void UTILS_NanosecondsToTimespec( int64_t llSource,
struct timespec * const pxDestination );
/**
* @brief Calculates pxResult = x + y.
*
* @param[out] pxResult Where the result of the calculation is stored.
* @param[in] x The first argument for addition.
* @param[in] y The second argument for addition.
*
* @return -1 if any argument was NULL; 1 if result is negative; otherwise, 0.
*/
int UTILS_TimespecAdd( struct timespec * const pxResult,
const struct timespec * const x,
const struct timespec * const y );
/**
* @brief Calculates pxResult = x + ( struct timespec ) nanosec.
*
* @param[out] pxResult Where the result of the calculation is stored.
* @param[in] x The first argument for addition.
* @param[in] llNanoseconds The second argument for addition.
*
* @return -1 if pxResult or x was NULL; 1 if result is negative; otherwise, 0.
*/
int UTILS_TimespecAddNanoseconds( struct timespec * const pxResult,
const struct timespec * const x,
int64_t llNanoseconds );
/**
* @brief Calculates pxResult = x - y.
*
* @param[out] pxResult Where the result of the calculation is stored.
* @param[in] x The first argument for subtraction.
* @param[in] y The second argument for subtraction.
*
* @return -1 if any argument was NULL; 1 if result is negative; otherwise, 0.
*/
int UTILS_TimespecSubtract( struct timespec * const pxResult,
const struct timespec * const x,
const struct timespec * const y );
/**
* @brief Checks that a timespec conforms to POSIX.
*
* A valid timespec must have 0 <= tv_nsec < 1000000000.
*
* @param[in] pxTimespec The timespec to validate.
*
* @return true if the pxTimespec is valid, false otherwise.
*/
bool UTILS_ValidateTimespec(const struct timespec * const pxTimespec);
#endif /* ifndef _FREERTOS_POSIX_UTILS_ */

View File

@ -0,0 +1,243 @@
/*
* Amazon FreeRTOS
* 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
*/
/**
* @file aws_doubly_linked_list.h
* @brief Doubly Linked List implementation.
*
* A generic implementation of circular Doubly Linked List which consists of a
* list head and some list entries (zero in case of an empty list).
*
* To start with, a structure of type Link_t should be embedded in the structure
* which is to be organized as doubly linked list.
* @code
* typedef struct UserStruct
* {
* uint32_t ulField1;
* uint32_t ulField2;
* Link_t xLink;
* } UserStruct_t;
* @endcode
*
* A List head should then be defined and initialized.
* @code
* Link_t xListHead;
* listINIT_HEAD( &xListHead );
* @endcode
*
* listADD can then be used to add nodes to the list.
* @code
* listADD( &( xListHead ), &( pxUserStruct->xLink ) );
* @endcode
*
* listFOR_EACH can be used for traversing the list.
* @code
* Link_t *pxLink;
* UserStruct_t *pxUserStruct;
* listFOR_EACH( pxLink, &( xListHead ) )
* {
* pxUserStruct = listCONTAINER( pxLink, UserStruct_t, xLink );
* }
* @endcode
*
* listFOR_EACH_SAFE should be used if you want to perform destructive operations
* (like free) on nodes while traversing the list.
* @code
* Link_t *pxLink, *pxTempLink;
* UserStruct_t *pxUserStruct;
* listFOR_EACH( pxLink, pxTempLink, &( xListHead ) )
* {
* pxUserStruct = listCONTAINER( pxLink, UserStruct_t, xLink );
* free( pxUserStruct );
* }
* @endcode
*/
#ifndef _AWS_DOUBLY_LINKED_LIST_H_
#define _AWS_DOUBLY_LINKED_LIST_H_
#include <stddef.h>
#include <stdint.h>
/**
* @brief Struct embedded in any struct to make it a doubly linked
* list.
*
* pxNext in the head points to the first node in the list and pxPrev
* in the head points to the last node in the list. In case of empty
* list, both pxPrev and pxNext in the head point to the head node itself.
*/
typedef struct Link
{
struct Link * pxPrev; /**< Pointer to the previous node. */
struct Link * pxNext; /**< Pointer to the next node. */
} Link_t;
/**
* @brief Initializes the given list head to an empty list.
*
* @param[in] pxHead The given list head to initialize.
*/
#define listINIT_HEAD( pxHead ) \
{ \
( pxHead )->pxPrev = ( pxHead ); \
( pxHead )->pxNext = ( pxHead ); \
}
/**
* @brief Adds the given new node to the given list.
*
* @param[in] pxHead The head of the given list.
* @param[in] pxLink The given new node to be added to the given
* list.
*/
#define listADD( pxHead, pxLink ) \
{ \
Link_t * pxPrevLink = ( pxHead ); \
Link_t * pxNextLink = ( ( pxHead )->pxNext ); \
\
( pxLink )->pxNext = pxNextLink; \
pxNextLink->pxPrev = ( pxLink ); \
pxPrevLink->pxNext = ( pxLink ); \
( pxLink )->pxPrev = ( pxPrevLink ); \
}
/**
* @brief Removes the given node from the list it is part of.
*
* If the given node is not a part of any list (i.e. next and previous
* nodes are NULL), nothing happens.
*
* @param[in] pxLink The given node to remove from the list.
*/
#define listREMOVE( pxLink ) \
{ \
/* If the link is part of a list, remove it from the list. */ \
if( ( pxLink )->pxNext != NULL && ( pxLink )->pxPrev != NULL ) \
{ \
( pxLink )->pxPrev->pxNext = ( pxLink )->pxNext; \
( pxLink )->pxNext->pxPrev = ( pxLink )->pxPrev; \
} \
\
/* Make sure that this link is not part of any list anymore. */ \
( pxLink )->pxPrev = NULL; \
( pxLink )->pxNext = NULL; \
}
/**
* @brief Given the head of a list, checks if the list is empty.
*
* @param[in] pxHead The head of the given list.
*/
#define listIS_EMPTY( pxHead ) ( ( ( pxHead ) == NULL ) || ( ( pxHead )->pxNext == ( pxHead ) ) )
/**
* @brief Removes the first node from the given list and returns it.
*
* Removes the first node from the given list and assigns it to the
* pxLink parameter. If the list is empty, it assigns NULL to the
* pxLink.
*
* @param[in] pxHead The head of the list from which to remove the
* first node.
* @param[out] pxLink The output parameter to receive the removed
* node.
*/
#define listPOP( pxHead, pxLink ) \
{ \
if( listIS_EMPTY( ( pxHead ) ) ) \
{ \
( pxLink ) = NULL; \
} \
else \
{ \
( pxLink ) = ( pxHead )->pxNext; \
/* If the link is part of a list, remove it from the list. */ \
if( ( pxLink )->pxNext != NULL && ( pxLink )->pxPrev != NULL ) \
{ \
( pxLink )->pxPrev->pxNext = ( pxLink )->pxNext; \
( pxLink )->pxNext->pxPrev = ( pxLink )->pxPrev; \
} \
\
/* Make sure that this link is not part of any list anymore. */ \
( pxLink )->pxPrev = NULL; \
( pxLink )->pxNext = NULL; \
} \
}
/**
* @brief Merges a list into a given list.
*
* @param[in] pxHeadResultList The head of the given list into which the
* other list should be merged.
* @param[in] pxHeadListToMerge The head of the list to be merged into the
* given list.
*/
#define listMERGE( pxHeadResultList, pxHeadListToMerge ) \
{ \
if( !listIS_EMPTY( ( pxHeadListToMerge ) ) ) \
{ \
/* Setup links between last node of listToMerge and first node of resultList. */ \
( pxHeadListToMerge )->pxPrev->pxNext = ( pxHeadResultList )->pxNext; \
( pxHeadResultList )->pxNext->pxPrev = ( pxHeadListToMerge )->pxPrev; \
\
/* Setup links between first node of listToMerge and the head of resultList. */ \
( pxHeadListToMerge )->pxNext->pxPrev = ( pxHeadResultList ); \
( pxHeadResultList )->pxNext = ( pxHeadListToMerge )->pxNext; \
/* Empty the merged list. */ \
listINIT_HEAD( ( pxHeadListToMerge ) ); \
} \
}
/**
* @brief Helper macro to iterate over a list. pxLink contains the link node
* in each iteration.
*/
#define listFOR_EACH( pxLink, pxHead ) \
for( ( pxLink ) = ( pxHead )->pxNext; \
( pxLink ) != ( pxHead ); \
( pxLink ) = ( pxLink )->pxNext )
/**
* @brief Helper macro to iterate over a list. It is safe to destroy/free the
* nodes while iterating. pxLink contains the link node in each iteration.
*/
#define listFOR_EACH_SAFE( pxLink, pxTempLink, pxHead ) \
for( ( pxLink ) = ( pxHead )->pxNext, ( pxTempLink ) = ( pxLink )->pxNext; \
( pxLink ) != ( pxHead ); \
( pxLink ) = ( pxTempLink ), ( pxTempLink ) = ( pxLink )->pxNext )
/**
* @brief Given the pointer to the link member (of type Link_t) in a struct,
* extracts the pointer to the containing struct.
*
* @param[in] pxLink The pointer to the link member.
* @param[in] type The type of the containing struct.
* @param[in] member Name of the link member in the containing struct.
*/
#define listCONTAINER( pxLink, type, member ) ( ( type * ) ( ( uint8_t * ) ( pxLink ) - ( uint8_t * ) ( &( ( type * ) 0 )->member ) ) )
#endif /* _AWS_DOUBLY_LINKED_LIST_H_ */

View File

@ -0,0 +1,197 @@
/*
* FreeRTOS POSIX Demo V1.0.0
* 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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*
******************************************************************************
* -NOTE- The Win32 port is a simulation (or is that emulation?) only! Do not
* expect to get real time behaviour from the Win32 port or this demo
* application. It is provided as a convenient development and demonstration
* test bed only. This was tested using Windows 10 with Intel Core i7-6700 CPU.
*
* Windows will not be running the FreeRTOS simulator threads continuously, so
* the timing information has no meaningful units. See the documentation page for
* the Windows simulator for an explanation of the slow timing:
* http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html
* - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT -
*
* Documentation for this demo can be found on:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_POSIX/demo/posix_demo.html
******************************************************************************
*
*
* /* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* System headers */
#include <stdio.h>
/* demo include */
#include "posix_demo.h"
/* Demo task priority */
#define mainPOSIX_DEMO_PRIORITY ( tskIDLE_PRIORITY + 4 )
/*-----------------------------------------------------------*/
int main( void )
{
configASSERT( ( mainPOSIX_DEMO_PRIORITY < configMAX_PRIORITIES ) );
const uint32_t ulLongTime_ms = pdMS_TO_TICKS( 1000UL );
printf( "FreeRTOS POSIX demo\n" );
/* Start the task to run POSIX demo */
xTaskCreate( vStartPOSIXDemo,
"posix",
configMINIMAL_STACK_SIZE,
NULL,
mainPOSIX_DEMO_PRIORITY,
NULL );
vTaskStartScheduler();
/* If all is well, the scheduler will now be running, and the following
* line will never be reached. If the following line does execute, then
* there was insufficient FreeRTOS heap memory available for the idle and/or
* timer tasks to be created. See the memory management section on the
* FreeRTOS web site for more details (this is standard text that is not
* really applicable to the Win32 simulator port). */
for( ; ; )
{
Sleep( ulLongTime_ms );
}
return 0;
}
/*-----------------------------------------------------------*/
void vAssertCalled( const char * pcFile,
uint32_t ulLine )
{
const uint32_t ulLongSleep = 1000UL;
volatile uint32_t ulBlockVariable = 0UL;
volatile char * pcFileName = ( volatile char * ) pcFile;
volatile uint32_t ulLineNumber = ulLine;
( void ) pcFileName;
( void ) ulLineNumber;
printf( "vAssertCalled %s, %ld\n", pcFile, ( long ) ulLine );
fflush( stdout );
/* Setting ulBlockVariable to a non-zero value in the debugger will allow
* this function to be exited. */
taskDISABLE_INTERRUPTS();
{
while( ulBlockVariable == 0UL )
{
Sleep( ulLongSleep );
}
}
taskENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
* implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
* used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize )
{
/* If the buffers to be provided to the Idle task are declared inside this
* function then they must be declared static - otherwise they will be allocated on
* the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
/* Pass out a pointer to the StaticTask_t structure in which the Idle
* task's state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
* Note that, as the array is necessarily of type StackType_t,
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
* application must provide an implementation of vApplicationGetTimerTaskMemory()
* to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
StackType_t ** ppxTimerTaskStackBuffer,
uint32_t * pulTimerTaskStackSize )
{
/* If the buffers to be provided to the Timer task are declared inside this
* function then they must be declared static - otherwise they will be allocated on
* the stack and so not exists after this function exits. */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
/* Pass out a pointer to the StaticTask_t structure in which the Timer
* task's state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
* Note that, as the array is necessarily of type StackType_t,
* configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
/*-----------------------------------------------------------*/
/**
* @brief Warn user if pvPortMalloc fails.
*
* Called if a call to pvPortMalloc() fails because there is insufficient
* free memory available in the FreeRTOS heap. pvPortMalloc() is called
* internally by FreeRTOS API functions that create tasks, queues, software
* timers, and semaphores. The size of the FreeRTOS heap is set by the
* configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h.
*
*/
void vApplicationMallocFailedHook()
{
taskDISABLE_INTERRUPTS();
for( ; ; )
{
}
}

View File

@ -0,0 +1,366 @@
/*
* FreeRTOS POSIX Demo V1.0.0
* 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
*/
/**
* @brief Demo intro: job distribution with actor model.
*
* This demo simulates job distribution with actor model.
* https://en.wikipedia.org/wiki/Actor_model
*
* In this demo, vStartPOSIXDemo() first creates all mailboxes
* which will be used by actors to send and receive messages.
* Then it spins up two types of actors -- Dispatcher and Workers.
*
* Dispatcher -- Distributing sub-tasks to workers.
* Distribution is done by putting messages into each worker's inbox,
* which is essentially an mqueue. Dispatcher keeps distributing tasks
* until all intended tasks are distributed.
*
* Workers -- Take sub-tasks and perform predefined routine for each type of tasks.
*
* Upon finishing distributing all tasks, Dispatcher will send a "terminate" message to
* each worker. vStartPOSIXDemo() will then join all actor threads and clean up mailboxes.
*
* @note A few assumptions are made in this demo, which a user might have to alter
* if to adopt this model in a new application:
*
* - The upper limit for MQUEUE_NUMBER_OF_WORKERS is set to 10.
* This is not due to physical constraint (e.g. memory), rather to make queue
* names end with a single digit number.
*
* - Message enum is cast to char/uint8_t directly, with the assumption that
* the system is not going to have more than 254 messages, which is often true
* in practice. Could extend bits used in a message to either have more messages
* or include additional arguments for a message. Proper typecasting is needed
* in that case.
*
* - The philosophy is "failure is expected". It is shown in both the way dispatcher
* delivers messages (i.e. messages can be dropped by worker(s)), and also the
* way workers process messages (i.e. workers do not inform dispatcher success or
* failure).
*
* - Following the philosophy, dispatcher shall never use blocking calls to distribute
* tasks. The only exception made here is that dispatcher needs to make sure the
* successful delivery of "terminate" messages. So that, main thread could join
* all actor threads and finish the demo.
*/
/* FreeRTOS includes. */
#include "FreeRTOS_POSIX.h"
/* System headers. */
#include <stdbool.h>
#include <string.h>
/* Demo includes. */
#include "posix_demo.h"
/* FreeRTOS+POSIX. */
#include "FreeRTOS_POSIX/pthread.h"
#include "FreeRTOS_POSIX/mqueue.h"
#include "FreeRTOS_POSIX/time.h"
#include "FreeRTOS_POSIX/fcntl.h"
#include "FreeRTOS_POSIX/errno.h"
/* Constants. */
#define LINE_BREAK "\r\n"
/**
* @brief Control messages.
*
* uint8_t is sufficient for this enum, that we are going to cast to char directly.
* If ever needed, implement a function to properly typecast.
*/
/**@{ */
typedef enum ControlMessage
{
eMSG_LOWER_INAVLID = 0x00, /**< Guard, let's not use 0x00 for messages. */
eWORKER_CTRL_MSG_CONTINUE = 0x01, /**< Dispatcher to worker, distributing another job. */
eWORKER_CTRL_MSG_EXIT = 0x02, /**< Dispatcher to worker, all jobs are finished and the worker receiving such can exit. */
/* define additional messages here */
eMSG_UPPER_INVALID = 0xFF /**< Guard, additional tasks shall be defined above. */
} eControlMessage;
/**@} */
/**
* @defgroup Configuration constants for the dispatcher-worker demo.
*/
/**@{ */
#define MQUEUE_NUMBER_OF_WORKERS ( 4 ) /**< The number of worker threads, each thread has one queue which is used as income box. */
#if ( MQUEUE_NUMBER_OF_WORKERS > 10 )
#error "Please keep MQUEUE_NUMBER_OF_WORKERS < 10."
#endif
#define MQUEUE_WORKER_QNAME_BASE "/qNode0" /**< Queue name base. */
#define MQUEUE_WORKER_QNAME_BASE_LEN ( 6 ) /** Queue name base length. */
#define MQUEUE_TIMEOUT_SECONDS ( 1 ) /**< Relative timeout for mqueue functions. */
#define MQUEUE_MAX_NUMBER_OF_MESSAGES_WORKER ( 1 ) /**< Maximum number of messages in a queue. */
#define MQUEUE_MSG_WORKER_CTRL_MSG_SIZE sizeof( uint8_t ) /**< Control message size. */
#define DEMO_ERROR ( -1 ) /**< Any non-zero value would work. */
/**@} */
/**
* @brief Structure used by Worker thread.
*/
/**@{ */
typedef struct WorkerThreadResources
{
pthread_t pxID; /**< thread ID. */
mqd_t xInboxID; /**< mqueue inbox ID. */
} WorkerThreadResources_t;
/**@} */
/**
* @brief Structure used by Dispatcher thread.
*/
/**@{ */
typedef struct DispatcherThreadResources
{
pthread_t pxID; /**< thread ID. */
mqd_t * pOutboxID; /**< a list of mqueue outbox ID. */
} DispatcherThreadResources_t;
/**@} */
/*-----------------------------------------------------------*/
static void * prvWorkerThread( void * pvArgs )
{
WorkerThreadResources_t pArgList = *( WorkerThreadResources_t * ) pvArgs;
printf( "Worker thread #[%d] - start %s", ( int ) pArgList.pxID, LINE_BREAK );
struct timespec xReceiveTimeout = { 0 };
ssize_t xMessageSize = 0;
char pcReceiveBuffer[ MQUEUE_MSG_WORKER_CTRL_MSG_SIZE ] = { 0 };
/* This is a worker thread that reacts based on what is sent to its inbox (mqueue). */
while( true )
{
clock_gettime( CLOCK_REALTIME, &xReceiveTimeout );
xReceiveTimeout.tv_sec += MQUEUE_TIMEOUT_SECONDS;
xMessageSize = mq_receive( pArgList.xInboxID,
pcReceiveBuffer,
MQUEUE_MSG_WORKER_CTRL_MSG_SIZE,
0 );
/* Parse messages */
if( xMessageSize == MQUEUE_MSG_WORKER_CTRL_MSG_SIZE )
{
switch( ( int ) pcReceiveBuffer[ 0 ] )
{
case eWORKER_CTRL_MSG_CONTINUE:
/* Task branch, currently only prints message to screen. */
/* Could perform tasks here. Could also notify dispatcher upon completion, if desired. */
printf( "Worker thread #[%d] -- Received eWORKER_CTRL_MSG_CONTINUE %s", ( int ) pArgList.pxID, LINE_BREAK );
break;
case eWORKER_CTRL_MSG_EXIT:
printf( "Worker thread #[%d] -- Finished. Exit now. %s", ( int ) pArgList.pxID, LINE_BREAK );
return NULL;
default:
/* Received a message that we don't care or not defined. */
break;
}
}
else
{
/* Invalid message. Error handling can be done here, if desired. */
}
}
/* You should never hit here. */
/* return NULL; */
}
/*-----------------------------------------------------------*/
static void * prvDispatcherThread( void * pvArgs )
{
DispatcherThreadResources_t pArgList = *( DispatcherThreadResources_t * ) pvArgs;
printf( "Dispatcher thread - start %s", LINE_BREAK );
struct timespec xSendTimeout = { 0 };
ssize_t xMessageSize = 0;
char pcSendBuffer[ MQUEUE_MSG_WORKER_CTRL_MSG_SIZE ] = { 0 };
/* Just for fun, let threads do a total of 100 independent tasks. */
int i = 0;
const int totalNumOfJobsPerThread = 100;
/* Distribute 1000 independent tasks to workers, in round-robin fashion. */
pcSendBuffer[ 0 ] = ( char ) eWORKER_CTRL_MSG_CONTINUE;
for( i = 0; i < totalNumOfJobsPerThread; i++ )
{
clock_gettime( CLOCK_REALTIME, &xSendTimeout );
xSendTimeout.tv_sec += MQUEUE_TIMEOUT_SECONDS;
printf( "Dispatcher iteration #[%d] -- Sending msg to worker thread #[%d]. %s", i, ( int ) pArgList.pOutboxID[ i % MQUEUE_NUMBER_OF_WORKERS ], LINE_BREAK );
xMessageSize = mq_timedsend( pArgList.pOutboxID[ i % MQUEUE_NUMBER_OF_WORKERS ],
pcSendBuffer,
MQUEUE_MSG_WORKER_CTRL_MSG_SIZE,
0,
&xSendTimeout );
if( xMessageSize != 0 )
{
/* This error is acceptable in our setup.
* Since inbox for each thread fits only one message.
* In reality, balance inbox size, message arrival rate, and message drop rate. */
printf( "An acceptable failure -- dispatcher failed to send eWORKER_CTRL_MSG_CONTINUE to outbox ID: %x. errno %d %s",
( int ) pArgList.pOutboxID[ i % MQUEUE_NUMBER_OF_WORKERS ], errno, LINE_BREAK );
}
}
/* Control thread is now done with distributing jobs. Tell workers they are done. */
pcSendBuffer[ 0 ] = ( char ) eWORKER_CTRL_MSG_EXIT;
for( i = 0; i < MQUEUE_NUMBER_OF_WORKERS; i++ )
{
printf( "Dispatcher [%d] -- Sending eWORKER_CTRL_MSG_EXIT to worker thread #[%d]. %s", i, ( int ) pArgList.pOutboxID[ i % MQUEUE_NUMBER_OF_WORKERS ], LINE_BREAK );
/* This is a blocking call, to guarantee worker thread exits. */
xMessageSize = mq_send( pArgList.pOutboxID[ i % MQUEUE_NUMBER_OF_WORKERS ],
pcSendBuffer,
MQUEUE_MSG_WORKER_CTRL_MSG_SIZE,
0 );
}
return NULL;
}
/*-----------------------------------------------------------*/
/**
* @brief Job distribution with actor model.
*
* See the top of this file for detailed description.
*/
void vStartPOSIXDemo( void )
{
int i = 0;
int iStatus = 0;
/* Handles of the threads and related resources. */
DispatcherThreadResources_t pxDispatcher = { 0 };
WorkerThreadResources_t pxWorkers[ MQUEUE_NUMBER_OF_WORKERS ] = { { 0 } };
mqd_t workerMqueues[ MQUEUE_NUMBER_OF_WORKERS ] = { 0 };
struct mq_attr xQueueAttributesWorker =
{
.mq_flags = 0,
.mq_maxmsg = MQUEUE_MAX_NUMBER_OF_MESSAGES_WORKER,
.mq_msgsize = MQUEUE_MSG_WORKER_CTRL_MSG_SIZE,
.mq_curmsgs = 0
};
pxDispatcher.pOutboxID = workerMqueues;
/* Create message queues for each worker thread. */
for( i = 0; i < MQUEUE_NUMBER_OF_WORKERS; i++ )
{
/* Prepare a unique queue name for each worker. */
char qName[] = MQUEUE_WORKER_QNAME_BASE;
qName[ MQUEUE_WORKER_QNAME_BASE_LEN - 1 ] = qName[ MQUEUE_WORKER_QNAME_BASE_LEN - 1 ] + i;
/* Open a queue with --
* O_CREAT -- create a message queue.
* O_RDWR -- both receiving and sending messages.
*/
pxWorkers[ i ].xInboxID = mq_open( qName,
O_CREAT | O_RDWR,
( mode_t ) 0,
&xQueueAttributesWorker );
if( pxWorkers[ i ].xInboxID == ( mqd_t ) -1 )
{
printf( "Invalid inbox (mqueue) for worker. %s", LINE_BREAK );
iStatus = DEMO_ERROR;
break;
}
/* Outboxes of dispatcher thread is the inboxes of all worker threads. */
pxDispatcher.pOutboxID[ i ] = pxWorkers[ i ].xInboxID;
}
/* Create and start Worker threads. */
if( iStatus == 0 )
{
for( i = 0; i < MQUEUE_NUMBER_OF_WORKERS; i++ )
{
( void ) pthread_create( &( pxWorkers[ i ].pxID ), NULL, prvWorkerThread, &pxWorkers[ i ] );
}
/* Create and start dispatcher thread. */
( void ) pthread_create( &( pxDispatcher.pxID ), NULL, prvDispatcherThread, &pxDispatcher );
/* Actors will do predefined tasks in threads. Current implementation is that
* dispatcher actor notifies worker actors to terminate upon finishing distributing tasks. */
/* Wait for worker threads to join. */
for( i = 0; i < MQUEUE_NUMBER_OF_WORKERS; i++ )
{
( void ) pthread_join( pxWorkers[ i ].pxID, NULL );
}
/* Wait for dispatcher thread to join. */
( void ) pthread_join( pxDispatcher.pxID, NULL );
}
/* Close and unlink worker message queues. */
for( i = 0; i < MQUEUE_NUMBER_OF_WORKERS; i++ )
{
char qName[] = MQUEUE_WORKER_QNAME_BASE;
qName[ MQUEUE_WORKER_QNAME_BASE_LEN - 1 ] = qName[ MQUEUE_WORKER_QNAME_BASE_LEN - 1 ] + i;
if( pxWorkers[ i ].xInboxID != NULL )
{
( void ) mq_close( pxWorkers[ i ].xInboxID );
( void ) mq_unlink( qName );
}
}
/* Have something on console. */
if( iStatus == 0 )
{
printf( "All threads finished. %s", LINE_BREAK );
}
else
{
printf( "Queues did not get initialized properly. Did not run demo. %s", LINE_BREAK );
}
}

View File

@ -0,0 +1,32 @@
/*
* FreeRTOS Kernel V10.0.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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef _POSIX_DEMO_H_
#define _POSIX_DEMO_H_
void vStartPOSIXDemo( void * pvParameters );
#endif /* _POSIX_DEMO_H_ */

View File

@ -0,0 +1,6 @@
Directories:
+ FreeRTOS-Plus\Demo\FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator
contains a FreeRTOS windows simulator demo project for FreeRTOS+POSIX.
See http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_POSIX/ for information about this project.

9
FreeRTOS-Plus/Demo/readme.txt Executable file
View File

@ -0,0 +1,9 @@
Directories:
+ The FreeRTOS-Plus/Demo directory contains a demo application for every most of
the FreeRTOS+ components. Lots of the demo applications use the FreeRTOS
Windows simulator for easy evaluation. Be aware that FreeRTOS is much slower
and not deterministic when executed in a simulated environment.
+ See http://www.freertos.org/plus

View File

@ -0,0 +1,351 @@
/*
* FreeRTOS+CLI V1.0.4
* 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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
#include <string.h>
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* Utils includes. */
#include "FreeRTOS_CLI.h"
/* If the application writer needs to place the buffer used by the CLI at a
fixed address then set configAPPLICATION_PROVIDES_cOutputBuffer to 1 in
FreeRTOSConfig.h, then declare an array with the following name and size in
one of the application files:
char cOutputBuffer[ configCOMMAND_INT_MAX_OUTPUT_SIZE ];
*/
#ifndef configAPPLICATION_PROVIDES_cOutputBuffer
#define configAPPLICATION_PROVIDES_cOutputBuffer 0
#endif
typedef struct xCOMMAND_INPUT_LIST
{
const CLI_Command_Definition_t *pxCommandLineDefinition;
struct xCOMMAND_INPUT_LIST *pxNext;
} CLI_Definition_List_Item_t;
/*
* The callback function that is executed when "help" is entered. This is the
* only default command that is always present.
*/
static BaseType_t prvHelpCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Return the number of parameters that follow the command name.
*/
static int8_t prvGetNumberOfParameters( const char *pcCommandString );
/* The definition of the "help" command. This command is always at the front
of the list of registered commands. */
static const CLI_Command_Definition_t xHelpCommand =
{
"help",
"\r\nhelp:\r\n Lists all the registered commands\r\n\r\n",
prvHelpCommand,
0
};
/* The definition of the list of commands. Commands that are registered are
added to this list. */
static CLI_Definition_List_Item_t xRegisteredCommands =
{
&xHelpCommand, /* The first command in the list is always the help command, defined in this file. */
NULL /* The next pointer is initialised to NULL, as there are no other registered commands yet. */
};
/* A buffer into which command outputs can be written is declared here, rather
than in the command console implementation, to allow multiple command consoles
to share the same buffer. For example, an application may allow access to the
command interpreter by UART and by Ethernet. Sharing a buffer is done purely
to save RAM. Note, however, that the command console itself is not re-entrant,
so only one command interpreter interface can be used at any one time. For that
reason, no attempt at providing mutual exclusion to the cOutputBuffer array is
attempted.
configAPPLICATION_PROVIDES_cOutputBuffer is provided to allow the application
writer to provide their own cOutputBuffer declaration in cases where the
buffer needs to be placed at a fixed address (rather than by the linker). */
#if( configAPPLICATION_PROVIDES_cOutputBuffer == 0 )
static char cOutputBuffer[ configCOMMAND_INT_MAX_OUTPUT_SIZE ];
#else
extern char cOutputBuffer[ configCOMMAND_INT_MAX_OUTPUT_SIZE ];
#endif
/*-----------------------------------------------------------*/
BaseType_t FreeRTOS_CLIRegisterCommand( const CLI_Command_Definition_t * const pxCommandToRegister )
{
static CLI_Definition_List_Item_t *pxLastCommandInList = &xRegisteredCommands;
CLI_Definition_List_Item_t *pxNewListItem;
BaseType_t xReturn = pdFAIL;
/* Check the parameter is not NULL. */
configASSERT( pxCommandToRegister );
/* Create a new list item that will reference the command being registered. */
pxNewListItem = ( CLI_Definition_List_Item_t * ) pvPortMalloc( sizeof( CLI_Definition_List_Item_t ) );
configASSERT( pxNewListItem );
if( pxNewListItem != NULL )
{
taskENTER_CRITICAL();
{
/* Reference the command being registered from the newly created
list item. */
pxNewListItem->pxCommandLineDefinition = pxCommandToRegister;
/* The new list item will get added to the end of the list, so
pxNext has nowhere to point. */
pxNewListItem->pxNext = NULL;
/* Add the newly created list item to the end of the already existing
list. */
pxLastCommandInList->pxNext = pxNewListItem;
/* Set the end of list marker to the new list item. */
pxLastCommandInList = pxNewListItem;
}
taskEXIT_CRITICAL();
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t FreeRTOS_CLIProcessCommand( const char * const pcCommandInput, char * pcWriteBuffer, size_t xWriteBufferLen )
{
static const CLI_Definition_List_Item_t *pxCommand = NULL;
BaseType_t xReturn = pdTRUE;
const char *pcRegisteredCommandString;
size_t xCommandStringLength;
/* Note: This function is not re-entrant. It must not be called from more
thank one task. */
if( pxCommand == NULL )
{
/* Search for the command string in the list of registered commands. */
for( pxCommand = &xRegisteredCommands; pxCommand != NULL; pxCommand = pxCommand->pxNext )
{
pcRegisteredCommandString = pxCommand->pxCommandLineDefinition->pcCommand;
xCommandStringLength = strlen( pcRegisteredCommandString );
/* To ensure the string lengths match exactly, so as not to pick up
a sub-string of a longer command, check the byte after the expected
end of the string is either the end of the string or a space before
a parameter. */
if( ( pcCommandInput[ xCommandStringLength ] == ' ' ) || ( pcCommandInput[ xCommandStringLength ] == 0x00 ) )
{
if( strncmp( pcCommandInput, pcRegisteredCommandString, xCommandStringLength ) == 0 )
{
/* The command has been found. Check it has the expected
number of parameters. If cExpectedNumberOfParameters is -1,
then there could be a variable number of parameters and no
check is made. */
if( pxCommand->pxCommandLineDefinition->cExpectedNumberOfParameters >= 0 )
{
if( prvGetNumberOfParameters( pcCommandInput ) != pxCommand->pxCommandLineDefinition->cExpectedNumberOfParameters )
{
xReturn = pdFALSE;
}
}
break;
}
}
}
}
if( ( pxCommand != NULL ) && ( xReturn == pdFALSE ) )
{
/* The command was found, but the number of parameters with the command
was incorrect. */
strncpy( pcWriteBuffer, "Incorrect command parameter(s). Enter \"help\" to view a list of available commands.\r\n\r\n", xWriteBufferLen );
pxCommand = NULL;
}
else if( pxCommand != NULL )
{
/* Call the callback function that is registered to this command. */
xReturn = pxCommand->pxCommandLineDefinition->pxCommandInterpreter( pcWriteBuffer, xWriteBufferLen, pcCommandInput );
/* If xReturn is pdFALSE, then no further strings will be returned
after this one, and pxCommand can be reset to NULL ready to search
for the next entered command. */
if( xReturn == pdFALSE )
{
pxCommand = NULL;
}
}
else
{
/* pxCommand was NULL, the command was not found. */
strncpy( pcWriteBuffer, "Command not recognised. Enter 'help' to view a list of available commands.\r\n\r\n", xWriteBufferLen );
xReturn = pdFALSE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
char *FreeRTOS_CLIGetOutputBuffer( void )
{
return cOutputBuffer;
}
/*-----------------------------------------------------------*/
const char *FreeRTOS_CLIGetParameter( const char *pcCommandString, UBaseType_t uxWantedParameter, BaseType_t *pxParameterStringLength )
{
UBaseType_t uxParametersFound = 0;
const char *pcReturn = NULL;
*pxParameterStringLength = 0;
while( uxParametersFound < uxWantedParameter )
{
/* Index the character pointer past the current word. If this is the start
of the command string then the first word is the command itself. */
while( ( ( *pcCommandString ) != 0x00 ) && ( ( *pcCommandString ) != ' ' ) )
{
pcCommandString++;
}
/* Find the start of the next string. */
while( ( ( *pcCommandString ) != 0x00 ) && ( ( *pcCommandString ) == ' ' ) )
{
pcCommandString++;
}
/* Was a string found? */
if( *pcCommandString != 0x00 )
{
/* Is this the start of the required parameter? */
uxParametersFound++;
if( uxParametersFound == uxWantedParameter )
{
/* How long is the parameter? */
pcReturn = pcCommandString;
while( ( ( *pcCommandString ) != 0x00 ) && ( ( *pcCommandString ) != ' ' ) )
{
( *pxParameterStringLength )++;
pcCommandString++;
}
if( *pxParameterStringLength == 0 )
{
pcReturn = NULL;
}
break;
}
}
else
{
break;
}
}
return pcReturn;
}
/*-----------------------------------------------------------*/
static BaseType_t prvHelpCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
static const CLI_Definition_List_Item_t * pxCommand = NULL;
BaseType_t xReturn;
( void ) pcCommandString;
if( pxCommand == NULL )
{
/* Reset the pxCommand pointer back to the start of the list. */
pxCommand = &xRegisteredCommands;
}
/* Return the next command help string, before moving the pointer on to
the next command in the list. */
strncpy( pcWriteBuffer, pxCommand->pxCommandLineDefinition->pcHelpString, xWriteBufferLen );
pxCommand = pxCommand->pxNext;
if( pxCommand == NULL )
{
/* There are no more commands in the list, so there will be no more
strings to return after this one and pdFALSE should be returned. */
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
static int8_t prvGetNumberOfParameters( const char *pcCommandString )
{
int8_t cParameters = 0;
BaseType_t xLastCharacterWasSpace = pdFALSE;
/* Count the number of space delimited words in pcCommandString. */
while( *pcCommandString != 0x00 )
{
if( ( *pcCommandString ) == ' ' )
{
if( xLastCharacterWasSpace != pdTRUE )
{
cParameters++;
xLastCharacterWasSpace = pdTRUE;
}
}
else
{
xLastCharacterWasSpace = pdFALSE;
}
pcCommandString++;
}
/* If the command string ended with spaces, then there will have been too
many parameters counted. */
if( xLastCharacterWasSpace == pdTRUE )
{
cParameters--;
}
/* The value returned is one less than the number of space delimited words,
as the first word should be the command itself. */
return cParameters;
}

View File

@ -0,0 +1,105 @@
/*
* FreeRTOS+CLI V1.0.4
* 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://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef COMMAND_INTERPRETER_H
#define COMMAND_INTERPRETER_H
/* The prototype to which callback functions used to process command line
commands must comply. pcWriteBuffer is a buffer into which the output from
executing the command can be written, xWriteBufferLen is the length, in bytes of
the pcWriteBuffer buffer, and pcCommandString is the entire string as input by
the user (from which parameters can be extracted).*/
typedef BaseType_t (*pdCOMMAND_LINE_CALLBACK)( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/* The structure that defines command line commands. A command line command
should be defined by declaring a const structure of this type. */
typedef struct xCOMMAND_LINE_INPUT
{
const char * const pcCommand; /* The command that causes pxCommandInterpreter to be executed. For example "help". Must be all lower case. */
const char * const pcHelpString; /* String that describes how to use the command. Should start with the command itself, and end with "\r\n". For example "help: Returns a list of all the commands\r\n". */
const pdCOMMAND_LINE_CALLBACK pxCommandInterpreter; /* A pointer to the callback function that will return the output generated by the command. */
int8_t cExpectedNumberOfParameters; /* Commands expect a fixed number of parameters, which may be zero. */
} CLI_Command_Definition_t;
/* For backward compatibility. */
#define xCommandLineInput CLI_Command_Definition_t
/*
* Register the command passed in using the pxCommandToRegister parameter.
* Registering a command adds the command to the list of commands that are
* handled by the command interpreter. Once a command has been registered it
* can be executed from the command line.
*/
BaseType_t FreeRTOS_CLIRegisterCommand( const CLI_Command_Definition_t * const pxCommandToRegister );
/*
* Runs the command interpreter for the command string "pcCommandInput". Any
* output generated by running the command will be placed into pcWriteBuffer.
* xWriteBufferLen must indicate the size, in bytes, of the buffer pointed to
* by pcWriteBuffer.
*
* FreeRTOS_CLIProcessCommand should be called repeatedly until it returns pdFALSE.
*
* pcCmdIntProcessCommand is not reentrant. It must not be called from more
* than one task - or at least - by more than one task at a time.
*/
BaseType_t FreeRTOS_CLIProcessCommand( const char * const pcCommandInput, char * pcWriteBuffer, size_t xWriteBufferLen );
/*-----------------------------------------------------------*/
/*
* A buffer into which command outputs can be written is declared in the
* main command interpreter, rather than in the command console implementation,
* to allow application that provide access to the command console via multiple
* interfaces to share a buffer, and therefore save RAM. Note, however, that
* the command interpreter itself is not re-entrant, so only one command
* console interface can be used at any one time. For that reason, no attempt
* is made to provide any mutual exclusion mechanism on the output buffer.
*
* FreeRTOS_CLIGetOutputBuffer() returns the address of the output buffer.
*/
char *FreeRTOS_CLIGetOutputBuffer( void );
/*
* Return a pointer to the xParameterNumber'th word in pcCommandString.
*/
const char *FreeRTOS_CLIGetParameter( const char *pcCommandString, UBaseType_t uxWantedParameter, BaseType_t *pxParameterStringLength );
#endif /* COMMAND_INTERPRETER_H */

View File

@ -0,0 +1,32 @@
Changes between V1.0.3 and V1.0.4 released
+ Update to use stdint and the FreeRTOS specific typedefs that were
introduced in FreeRTOS V8.0.0.
Changes between V1.0.2 and V1.0.3 released
+ Previously, and in line with good software engineering practice, the
FreeRTOS coding standard did not permit the use of char types that were
not explicitly qualified as either signed or unsigned. As a result char
pointers used to reference strings required casts, as did the use of any
standard string handling functions. The casts ensured compiler warnings
were not generated by compilers that defaulted unqualified char types to
be signed or compilers that defaulted unqualified char types to be
unsigned. As it has in later MISRA standards, this rule has now been
relaxed, and unqualified char types are now permitted, but only when:
1) The char is used to point to a human readable text string.
2) The char is used to hold a single ASCII character.
Changes between V1.0.1 and V1.0.2 released 14/10/2013
+ Changed double quotes (") to single quotes (') in the help string to
allow the strings to be used with JSON in FreeRTOS+Nabto.
Changes between V1.0.0 and V1.0.1 released 05/07/2012
+ Change the name of the structure used to map a function that implements
a CLI command to the string used to call the command from
xCommandLineInput to CLI_Command_Definition_t, as it was always intended
to be. A #define was added to map the old name to the new name for
reasons of backward compatibility.

View File

@ -0,0 +1,19 @@
FreeRTOS+CLI is released under the following MIT license.
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.

View File

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

View File

@ -0,0 +1,4 @@
Contains source and header files that implement FreeRTOS+CLI. See
http://www.FreeRTOS.org/cli for documentation and license information.

View File

@ -0,0 +1,5 @@
[InternetShortcut]
URL=http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_IO/Demo_Applications/LPCXpresso_LPC1769/NXP_LPC1769_Demo_Description.shtml
IDList=
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2

View File

@ -0,0 +1,7 @@
It is not possible to create an example FreeRTOS+IO project for the Windows
simulator. FreeRTOS+IO information can be found on http://www.FreeRTOS.org/IO.
A featured demo that includes telnet like functionality, a web server,
a command line interface (using FreeRTOS+CLI) and a FAT file system is
described on
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_IO/Demo_Applications/LPCXpresso_LPC1769/NXP_LPC1769_Demo_Description.shtml

View File

@ -0,0 +1,653 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#if( ipconfigUSE_LLMNR == 1 )
#include "FreeRTOS_DNS.h"
#endif /* ipconfigUSE_LLMNR */
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
/* When the age of an entry in the ARP table reaches this value (it counts down
to zero, so this is an old entry) an ARP request will be sent to see if the
entry is still valid and can therefore be refreshed. */
#define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ( 3 )
/* The time between gratuitous ARPs. */
#ifndef arpGRATUITOUS_ARP_PERIOD
#define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000 ) )
#endif
/*-----------------------------------------------------------*/
/*
* Lookup an MAC address in the ARP cache from the IP address.
*/
static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress );
/*-----------------------------------------------------------*/
/* The ARP cache. */
static ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ];
/* The time at which the last gratuitous ARP was sent. Gratuitous ARPs are used
to ensure ARP tables are up to date and to detect IP address conflicts. */
static TickType_t xLastGratuitousARPTime = ( TickType_t ) 0;
/*
* IP-clash detection is currently only used internally. When DHCP doesn't respond, the
* driver can try out a random LinkLayer IP address (169.254.x.x). It will send out a
* gratuitos ARP message and, after a period of time, check the variables here below:
*/
#if( ipconfigARP_USE_CLASH_DETECTION != 0 )
/* Becomes non-zero if another device responded to a gratuitos ARP message. */
BaseType_t xARPHadIPClash;
/* MAC-address of the other device containing the same IP-address. */
MACAddress_t xARPClashMacAddress;
#endif /* ipconfigARP_USE_CLASH_DETECTION */
/* Part of the Ethernet and ARP headers are always constant when sending an IPv4
ARP packet. This array defines the constant parts, allowing this part of the
packet to be filled in using a simple memcpy() instead of individual writes. */
static const uint8_t xDefaultPartARPPacketHeader[] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Ethernet destination address. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Ethernet source address. */
0x08, 0x06, /* Ethernet frame type (ipARP_FRAME_TYPE). */
0x00, 0x01, /* usHardwareType (ipARP_HARDWARE_TYPE_ETHERNET). */
0x08, 0x00, /* usProtocolType. */
ipMAC_ADDRESS_LENGTH_BYTES, /* ucHardwareAddressLength. */
ipIP_ADDRESS_LENGTH_BYTES, /* ucProtocolAddressLength. */
0x00, 0x01, /* usOperation (ipARP_REQUEST). */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* xSenderHardwareAddress. */
0x00, 0x00, 0x00, 0x00, /* ulSenderProtocolAddress. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* xTargetHardwareAddress. */
};
/*-----------------------------------------------------------*/
eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
{
eFrameProcessingResult_t eReturn = eReleaseBuffer;
ARPHeader_t *pxARPHeader;
uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
pxARPHeader = &( pxARPFrame->xARPHeader );
/* The field ulSenderProtocolAddress is badly aligned, copy byte-by-byte. */
memcpy( ( void *)&( ulSenderProtocolAddress ), ( void * )pxARPHeader->ucSenderProtocolAddress, sizeof( ulSenderProtocolAddress ) );
/* The field ulTargetProtocolAddress is well-aligned, a 32-bits copy. */
ulTargetProtocolAddress = pxARPHeader->ulTargetProtocolAddress;
traceARP_PACKET_RECEIVED();
/* Don't do anything if the local IP address is zero because
that means a DHCP request has not completed. */
if( *ipLOCAL_IP_ADDRESS_POINTER != 0UL )
{
switch( pxARPHeader->usOperation )
{
case ipARP_REQUEST :
/* The packet contained an ARP request. Was it for the IP
address of the node running this code? */
if( ulTargetProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )
{
iptraceSENDING_ARP_REPLY( ulSenderProtocolAddress );
/* The request is for the address of this node. Add the
entry into the ARP cache, or refresh the entry if it
already exists. */
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );
/* Generate a reply payload in the same buffer. */
pxARPHeader->usOperation = ( uint16_t ) ipARP_REPLY;
if( ulTargetProtocolAddress == ulSenderProtocolAddress )
{
/* A double IP address is detected! */
/* Give the sources MAC address the value of the broadcast address, will be swapped later */
memcpy( pxARPFrame->xEthernetHeader.xSourceAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( xBroadcastMACAddress ) );
memset( pxARPHeader->xTargetHardwareAddress.ucBytes, '\0', sizeof( MACAddress_t ) );
pxARPHeader->ulTargetProtocolAddress = 0UL;
}
else
{
memcpy( pxARPHeader->xTargetHardwareAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( MACAddress_t ) );
pxARPHeader->ulTargetProtocolAddress = ulSenderProtocolAddress;
}
memcpy( pxARPHeader->xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
memcpy( ( void* )pxARPHeader->ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPHeader->ucSenderProtocolAddress ) );
eReturn = eReturnEthernetFrame;
}
break;
case ipARP_REPLY :
iptracePROCESSING_RECEIVED_ARP_REPLY( ulTargetProtocolAddress );
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );
/* Process received ARP frame to see if there is a clash. */
#if( ipconfigARP_USE_CLASH_DETECTION != 0 )
{
if( ulSenderProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )
{
xARPHadIPClash = pdTRUE;
memcpy( xARPClashMacAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( xARPClashMacAddress.ucBytes ) );
}
}
#endif /* ipconfigARP_USE_CLASH_DETECTION */
break;
default :
/* Invalid. */
break;
}
}
return eReturn;
}
/*-----------------------------------------------------------*/
#if( ipconfigUSE_ARP_REMOVE_ENTRY != 0 )
uint32_t ulARPRemoveCacheEntryByMac( const MACAddress_t * pxMACAddress )
{
BaseType_t x;
uint32_t lResult = 0;
/* For each entry in the ARP cache table. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{
if( ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )
{
lResult = xARPCache[ x ].ulIPAddress;
memset( &xARPCache[ x ], '\0', sizeof( xARPCache[ x ] ) );
break;
}
}
return lResult;
}
#endif /* ipconfigUSE_ARP_REMOVE_ENTRY != 0 */
/*-----------------------------------------------------------*/
void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress, const uint32_t ulIPAddress )
{
BaseType_t x = 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++ )
{
/* Does this line in the cache table hold an entry for the IP
address being queried? */
if( xARPCache[ x ].ulIPAddress == ulIPAddress )
{
if( pxMACAddress == NULL )
{
/* In case the parameter pxMACAddress is NULL, an entry will be reserved to
indicate that there is an outstanding ARP request, This entry will have
"ucValid == pdFALSE". */
xIpEntry = x;
break;
}
/* See if the MAC-address also matches. */
if( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 )
{
/* This function will be called for each received packet
As this is by far the most common path the coding standard
is relaxed in this case and a return is permitted as an
optimisation. */
xARPCache[ x ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
xARPCache[ x ].ucValid = ( uint8_t ) pdTRUE;
return;
}
/* Found an entry containing ulIPAddress, but the MAC address
doesn't match. Might be an entry with ucValid=pdFALSE, waiting
for an ARP reply. Still want to see if there is match with the
given MAC address.ucBytes. If found, either of the two entries
must be cleared. */
xIpEntry = x;
}
else if( ( pxMACAddress != NULL ) && ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )
{
/* Found an entry with the given MAC-address, but the IP-address
is different. Continue looping to find a possible match with
ulIPAddress. */
#if( ipconfigARP_STORES_REMOTE_ADDRESSES != 0 )
/* If ARP stores the MAC address of IP addresses outside the
network, than the MAC address of the gateway should not be
overwritten. */
BaseType_t bIsLocal[ 2 ];
bIsLocal[ 0 ] = ( ( xARPCache[ x ].ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );
bIsLocal[ 1 ] = ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );
if( bIsLocal[ 0 ] == bIsLocal[ 1 ] )
{
xMacEntry = x;
}
#else
xMacEntry = x;
#endif
}
/* _HT_
Shouldn't we test for xARPCache[ x ].ucValid == pdFALSE here ? */
else if( xARPCache[ x ].ucAge < ucMinAgeFound )
{
/* As the table is traversed, remember the table row that
contains the oldest entry (the lowest age count, as ages are
decremented to zero) so the row can be re-used if this function
needs to add an entry that does not already exist. */
ucMinAgeFound = xARPCache[ x ].ucAge;
xUseEntry = x;
}
}
if( xMacEntry >= 0 )
{
xUseEntry = xMacEntry;
if( xIpEntry >= 0 )
{
/* Both the MAC address as well as the IP address were found in
different locations: clear the entry which matches the
IP-address */
memset( &xARPCache[ xIpEntry ], '\0', sizeof( xARPCache[ xIpEntry ] ) );
}
}
else if( xIpEntry >= 0 )
{
/* An entry containing the IP-address was found, but it had a different MAC address */
xUseEntry = xIpEntry;
}
/* If the entry was not found, we use the oldest entry and set the IPaddress */
xARPCache[ xUseEntry ].ulIPAddress = ulIPAddress;
if( pxMACAddress != NULL )
{
memcpy( xARPCache[ xUseEntry ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) );
iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, (*pxMACAddress) );
/* And this entry does not need immediate attention */
xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdTRUE;
}
else if( xIpEntry < 0 )
{
xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_RETRANSMISSIONS;
xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdFALSE;
}
}
}
/*-----------------------------------------------------------*/
#if( ipconfigUSE_ARP_REVERSED_LOOKUP == 1 )
eARPLookupResult_t eARPGetCacheEntryByMac( MACAddress_t * const pxMACAddress, uint32_t *pulIPAddress )
{
BaseType_t x;
eARPLookupResult_t eReturn = eARPCacheMiss;
/* Loop through each entry in the ARP cache. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{
/* Does this row in the ARP cache table hold an entry for the MAC
address being searched? */
if( memcmp( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
{
*pulIPAddress = xARPCache[ x ].ulIPAddress;
eReturn = eARPCacheHit;
break;
}
}
return eReturn;
}
#endif /* ipconfigUSE_ARP_REVERSED_LOOKUP */
/*-----------------------------------------------------------*/
eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * const pxMACAddress )
{
eARPLookupResult_t eReturn;
uint32_t ulAddressToLookup;
#if( ipconfigUSE_LLMNR == 1 )
if( *pulIPAddress == ipLLMNR_IP_ADDR ) /* Is in network byte order. */
{
/* The LLMNR IP-address has a fixed virtual MAC address. */
memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit;
}
else
#endif
if( ( *pulIPAddress == ipBROADCAST_IP_ADDRESS ) || /* Is it the general broadcast address 255.255.255.255? */
( *pulIPAddress == xNetworkAddressing.ulBroadcastAddress ) )/* Or a local broadcast address, eg 192.168.1.255? */
{
/* This is a broadcast so uses the broadcast MAC address. */
memcpy( pxMACAddress->ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit;
}
else if( *ipLOCAL_IP_ADDRESS_POINTER == 0UL )
{
/* The IP address has not yet been assigned, so there is nothing that
can be done. */
eReturn = eCantSendPacket;
}
else
{
eReturn = eARPCacheMiss;
if( ( *pulIPAddress & xNetworkAddressing.ulNetMask ) != ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) )
{
#if( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 )
eReturn = prvCacheLookup( *pulIPAddress, pxMACAddress );
if( eReturn == eARPCacheHit )
{
/* The stack is configured to store 'remote IP addresses', i.e. addresses
belonging to a different the netmask. prvCacheLookup() returned a hit, so
the MAC address is known */
}
else
#endif
{
/* The IP address is off the local network, so look up the
hardware address of the router, if any. */
if( xNetworkAddressing.ulGatewayAddress != ( uint32_t )0u )
{
ulAddressToLookup = xNetworkAddressing.ulGatewayAddress;
}
else
{
ulAddressToLookup = *pulIPAddress;
}
}
}
else
{
/* The IP address is on the local network, so lookup the requested
IP address directly. */
ulAddressToLookup = *pulIPAddress;
}
if( eReturn == eARPCacheMiss )
{
if( ulAddressToLookup == 0UL )
{
/* The address is not on the local network, and there is not a
router. */
eReturn = eCantSendPacket;
}
else
{
eReturn = prvCacheLookup( ulAddressToLookup, pxMACAddress );
if( eReturn == eARPCacheMiss )
{
/* It might be that the ARP has to go to the gateway. */
*pulIPAddress = ulAddressToLookup;
}
}
}
}
return eReturn;
}
/*-----------------------------------------------------------*/
static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress )
{
BaseType_t x;
eARPLookupResult_t eReturn = eARPCacheMiss;
/* Loop through each entry in the ARP cache. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{
/* Does this row in the ARP cache table hold an entry for the IP address
being queried? */
if( xARPCache[ x ].ulIPAddress == ulAddressToLookup )
{
/* A matching valid entry was found. */
if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE )
{
/* This entry is waiting an ARP reply, so is not valid. */
eReturn = eCantSendPacket;
}
else
{
/* A valid entry was found. */
memcpy( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit;
}
break;
}
}
return eReturn;
}
/*-----------------------------------------------------------*/
void vARPAgeCache( void )
{
BaseType_t x;
TickType_t xTimeNow;
/* Loop through each entry in the ARP cache. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{
/* If the entry is valid (its age is greater than zero). */
if( xARPCache[ x ].ucAge > 0U )
{
/* Decrement the age value of the entry in this ARP cache table row.
When the age reaches zero it is no longer considered valid. */
( xARPCache[ x ].ucAge )--;
/* If the entry is not yet valid, then it is waiting an ARP
reply, and the ARP request should be retransmitted. */
if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE )
{
FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );
}
else if( xARPCache[ x ].ucAge <= ( uint8_t ) arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST )
{
/* This entry will get removed soon. See if the MAC address is
still valid to prevent this happening. */
iptraceARP_TABLE_ENTRY_WILL_EXPIRE( xARPCache[ x ].ulIPAddress );
FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );
}
else
{
/* The age has just ticked down, with nothing to do. */
}
if( xARPCache[ x ].ucAge == 0u )
{
/* The entry is no longer valid. Wipe it out. */
iptraceARP_TABLE_ENTRY_EXPIRED( xARPCache[ x ].ulIPAddress );
xARPCache[ x ].ulIPAddress = 0UL;
}
}
}
xTimeNow = xTaskGetTickCount ();
if( ( xLastGratuitousARPTime == ( TickType_t ) 0 ) || ( ( xTimeNow - xLastGratuitousARPTime ) > ( TickType_t ) arpGRATUITOUS_ARP_PERIOD ) )
{
FreeRTOS_OutputARPRequest( *ipLOCAL_IP_ADDRESS_POINTER );
xLastGratuitousARPTime = xTimeNow;
}
}
/*-----------------------------------------------------------*/
void vARPSendGratuitous( void )
{
/* Setting xLastGratuitousARPTime to 0 will force a gratuitous ARP the next
time vARPAgeCache() is called. */
xLastGratuitousARPTime = ( TickType_t ) 0;
/* Let the IP-task call vARPAgeCache(). */
xSendEventToIPTask( eARPTimerEvent );
}
/*-----------------------------------------------------------*/
void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress )
{
NetworkBufferDescriptor_t *pxNetworkBuffer;
/* This is called from the context of the IP event task, so a block time
must not be used. */
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( ARPPacket_t ), ( TickType_t ) 0 );
if( pxNetworkBuffer != NULL )
{
pxNetworkBuffer->ulIPAddress = ulIPAddress;
vARPGenerateRequestPacket( pxNetworkBuffer );
#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
{
if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )
{
BaseType_t xIndex;
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{
pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
}
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
}
}
#endif
xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
}
}
void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
ARPPacket_t *pxARPPacket;
pxARPPacket = ( ARPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
/* memcpy the const part of the header information into the correct
location in the packet. This copies:
xEthernetHeader.ulDestinationAddress
xEthernetHeader.usFrameType;
xARPHeader.usHardwareType;
xARPHeader.usProtocolType;
xARPHeader.ucHardwareAddressLength;
xARPHeader.ucProtocolAddressLength;
xARPHeader.usOperation;
xARPHeader.xTargetHardwareAddress;
*/
memcpy( ( void * ) pxARPPacket, ( void * ) xDefaultPartARPPacketHeader, sizeof( xDefaultPartARPPacketHeader ) );
memcpy( ( void * ) pxARPPacket->xEthernetHeader.xSourceAddress.ucBytes , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
memcpy( ( void * ) pxARPPacket->xARPHeader.xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
memcpy( ( void* )pxARPPacket->xARPHeader.ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPPacket->xARPHeader.ucSenderProtocolAddress ) );
pxARPPacket->xARPHeader.ulTargetProtocolAddress = pxNetworkBuffer->ulIPAddress;
pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t );
iptraceCREATING_ARP_REQUEST( pxNetworkBuffer->ulIPAddress );
}
/*-----------------------------------------------------------*/
void FreeRTOS_ClearARP( void )
{
memset( xARPCache, '\0', sizeof( xARPCache ) );
}
/*-----------------------------------------------------------*/
#if( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 )
void FreeRTOS_PrintARPCache( void )
{
BaseType_t x, xCount = 0;
/* Loop through each entry in the ARP cache. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{
if( ( xARPCache[ x ].ulIPAddress != 0ul ) && ( xARPCache[ x ].ucAge > 0U ) )
{
/* See if the MAC-address also matches, and we're all happy */
FreeRTOS_printf( ( "Arp %2ld: %3u - %16lxip : %02x:%02x:%02x : %02x:%02x:%02x\n",
x,
xARPCache[ x ].ucAge,
xARPCache[ x ].ulIPAddress,
xARPCache[ x ].xMACAddress.ucBytes[0],
xARPCache[ x ].xMACAddress.ucBytes[1],
xARPCache[ x ].xMACAddress.ucBytes[2],
xARPCache[ x ].xMACAddress.ucBytes[3],
xARPCache[ x ].xMACAddress.ucBytes[4],
xARPCache[ x ].xMACAddress.ucBytes[5] ) );
xCount++;
}
}
FreeRTOS_printf( ( "Arp has %ld entries\n", xCount ) );
}
#endif /* ( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 ) */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
/*
* uxStreamBufferAdd( )
* Adds data to a stream buffer. If uxOffset > 0, data will be written at
* an offset from uxHead while uxHead will not be moved yet. This possibility
* will be used when TCP data is received while earlier data is still missing.
* If 'pucData' equals NULL, the function is called to advance 'uxHead' only.
*/
size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount )
{
size_t uxSpace, uxNextHead, uxFirst;
uxSpace = uxStreamBufferGetSpace( pxBuffer );
/* If uxOffset > 0, items can be placed in front of uxHead */
if( uxSpace > uxOffset )
{
uxSpace -= uxOffset;
}
else
{
uxSpace = 0u;
}
/* The number of bytes that can be written is the minimum of the number of
bytes requested and the number available. */
uxCount = FreeRTOS_min_uint32( uxSpace, uxCount );
if( uxCount != 0u )
{
uxNextHead = pxBuffer->uxHead;
if( uxOffset != 0u )
{
/* ( uxOffset > 0 ) means: write in front if the uxHead marker */
uxNextHead += uxOffset;
if( uxNextHead >= pxBuffer->LENGTH )
{
uxNextHead -= pxBuffer->LENGTH;
}
}
if( pucData != NULL )
{
/* Calculate the number of bytes that can be added in the first
write - which may be less than the total number of bytes that need
to be added if the buffer will wrap back to the beginning. */
uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextHead, uxCount );
/* Write as many bytes as can be written in the first write. */
memcpy( ( void* ) ( pxBuffer->ucArray + uxNextHead ), pucData, uxFirst );
/* If the number of bytes written was less than the number that
could be written in the first write... */
if( uxCount > uxFirst )
{
/* ...then write the remaining bytes to the start of the
buffer. */
memcpy( ( void * )pxBuffer->ucArray, pucData + uxFirst, uxCount - uxFirst );
}
}
if( uxOffset == 0u )
{
/* ( uxOffset == 0 ) means: write at uxHead position */
uxNextHead += uxCount;
if( uxNextHead >= pxBuffer->LENGTH )
{
uxNextHead -= pxBuffer->LENGTH;
}
pxBuffer->uxHead = uxNextHead;
}
if( xStreamBufferLessThenEqual( pxBuffer, pxBuffer->uxFront, uxNextHead ) != pdFALSE )
{
/* Advance the front pointer */
pxBuffer->uxFront = uxNextHead;
}
}
return uxCount;
}
/*-----------------------------------------------------------*/
/*
* uxStreamBufferGet( )
* 'uxOffset' can be used to read data located at a certain offset from 'lTail'.
* If 'pucData' equals NULL, the function is called to advance 'lTail' only.
* if 'xPeek' is pdTRUE, or if 'uxOffset' is non-zero, the 'lTail' pointer will
* not be advanced.
*/
size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek )
{
size_t uxSize, uxCount, uxFirst, uxNextTail;
/* How much data is available? */
uxSize = uxStreamBufferGetSize( pxBuffer );
if( uxSize > uxOffset )
{
uxSize -= uxOffset;
}
else
{
uxSize = 0u;
}
/* Use the minimum of the wanted bytes and the available bytes. */
uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount );
if( uxCount > 0u )
{
uxNextTail = pxBuffer->uxTail;
if( uxOffset != 0u )
{
uxNextTail += uxOffset;
if( uxNextTail >= pxBuffer->LENGTH )
{
uxNextTail -= pxBuffer->LENGTH;
}
}
if( pucData != NULL )
{
/* Calculate the number of bytes that can be read - which may be
less than the number wanted if the data wraps around to the start of
the buffer. */
uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextTail, uxCount );
/* Obtain the number of bytes it is possible to obtain in the first
read. */
memcpy( pucData, pxBuffer->ucArray + uxNextTail, uxFirst );
/* If the total number of wanted bytes is greater than the number
that could be read in the first read... */
if( uxCount > uxFirst )
{
/*...then read the remaining bytes from the start of the buffer. */
memcpy( pucData + uxFirst, pxBuffer->ucArray, uxCount - uxFirst );
}
}
if( ( xPeek == pdFALSE ) && ( uxOffset == 0UL ) )
{
/* Move the tail pointer to effecively remove the data read from
the buffer. */
uxNextTail += uxCount;
if( uxNextTail >= pxBuffer->LENGTH )
{
uxNextTail -= pxBuffer->LENGTH;
}
pxBuffer->uxTail = uxNextTail;
}
}
return uxCount;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#if( ipconfigUSE_DNS == 1 )
#include "FreeRTOS_DNS.h"
#endif
/* The expected IP version and header length coded into the IP header itself. */
#define ipIP_VERSION_AND_HEADER_LENGTH_BYTE ( ( uint8_t ) 0x45 )
/* Part of the Ethernet and IP headers are always constant when sending an IPv4
UDP packet. This array defines the constant parts, allowing this part of the
packet to be filled in using a simple memcpy() instead of individual writes. */
UDPPacketHeader_t xDefaultPartUDPPacketHeader =
{
/* .ucBytes : */
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Ethernet source MAC address. */
0x08, 0x00, /* Ethernet frame type. */
ipIP_VERSION_AND_HEADER_LENGTH_BYTE, /* ucVersionHeaderLength. */
0x00, /* ucDifferentiatedServicesCode. */
0x00, 0x00, /* usLength. */
0x00, 0x00, /* usIdentification. */
0x00, 0x00, /* usFragmentOffset. */
ipconfigUDP_TIME_TO_LIVE, /* ucTimeToLive */
ipPROTOCOL_UDP, /* ucProtocol. */
0x00, 0x00, /* usHeaderChecksum. */
0x00, 0x00, 0x00, 0x00 /* Source IP address. */
}
};
/*-----------------------------------------------------------*/
void vProcessGeneratedUDPPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
UDPPacket_t *pxUDPPacket;
IPHeader_t *pxIPHeader;
eARPLookupResult_t eReturned;
uint32_t ulIPAddress = pxNetworkBuffer->ulIPAddress;
/* Map the UDP packet onto the start of the frame. */
pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
/* Determine the ARP cache status for the requested IP address. */
eReturned = eARPGetCacheEntry( &( ulIPAddress ), &( pxUDPPacket->xEthernetHeader.xDestinationAddress ) );
if( eReturned != eCantSendPacket )
{
if( eReturned == eARPCacheHit )
{
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
uint8_t ucSocketOptions;
#endif
iptraceSENDING_UDP_PACKET( pxNetworkBuffer->ulIPAddress );
/* Create short cuts to the data within the packet. */
pxIPHeader = &( pxUDPPacket->xIPHeader );
#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
/* Is it possible that the packet is not actually a UDP packet
after all, but an ICMP packet. */
if( pxNetworkBuffer->usPort != ipPACKET_CONTAINS_ICMP_DATA )
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
{
UDPHeader_t *pxUDPHeader;
pxUDPHeader = &( pxUDPPacket->xUDPHeader );
pxUDPHeader->usDestinationPort = pxNetworkBuffer->usPort;
pxUDPHeader->usSourcePort = pxNetworkBuffer->usBoundPort;
pxUDPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( UDPHeader_t ) );
pxUDPHeader->usLength = FreeRTOS_htons( pxUDPHeader->usLength );
pxUDPHeader->usChecksum = 0u;
}
/* memcpy() the constant parts of the header information into
the correct location within the packet. This fills in:
xEthernetHeader.xSourceAddress
xEthernetHeader.usFrameType
xIPHeader.ucVersionHeaderLength
xIPHeader.ucDifferentiatedServicesCode
xIPHeader.usLength
xIPHeader.usIdentification
xIPHeader.usFragmentOffset
xIPHeader.ucTimeToLive
xIPHeader.ucProtocol
and
xIPHeader.usHeaderChecksum
*/
/* Save options now, as they will be overwritten by memcpy */
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
ucSocketOptions = pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ];
#endif
/*
* 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.
*/
char *pxUdpSrcAddrOffset = ( char *) pxUDPPacket + sizeof( MACAddress_t );
memcpy( pxUdpSrcAddrOffset, xDefaultPartUDPPacketHeader.ucBytes, sizeof( xDefaultPartUDPPacketHeader ) );
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA )
{
pxIPHeader->ucProtocol = ipPROTOCOL_ICMP;
pxIPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( IPHeader_t ) );
}
else
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
{
pxIPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( IPHeader_t ) + sizeof( UDPHeader_t ) );
}
/* The total transmit size adds on the Ethernet header. */
pxNetworkBuffer->xDataLength = pxIPHeader->usLength + sizeof( EthernetHeader_t );
pxIPHeader->usLength = FreeRTOS_htons( pxIPHeader->usLength );
/* HT:endian: changed back to network endian */
pxIPHeader->ulDestinationIPAddress = pxNetworkBuffer->ulIPAddress;
#if( ipconfigUSE_LLMNR == 1 )
{
/* LLMNR messages are typically used on a LAN and they're
* not supposed to cross routers */
if( pxNetworkBuffer->ulIPAddress == ipLLMNR_IP_ADDR )
{
pxIPHeader->ucTimeToLive = 0x01;
}
}
#endif
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
{
pxIPHeader->usHeaderChecksum = 0u;
pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
if( ( ucSocketOptions & ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT ) != 0u )
{
usGenerateProtocolChecksum( (uint8_t*)pxUDPPacket, pxNetworkBuffer->xDataLength, pdTRUE );
}
else
{
pxUDPPacket->xUDPHeader.usChecksum = 0u;
}
}
#endif
}
else if( eReturned == eARPCacheMiss )
{
/* Add an entry to the ARP table with a null hardware address.
This allows the ARP timer to know that an ARP reply is
outstanding, and perform retransmissions if necessary. */
vARPRefreshCacheEntry( NULL, ulIPAddress );
/* Generate an ARP for the required IP address. */
iptracePACKET_DROPPED_TO_GENERATE_ARP( pxNetworkBuffer->ulIPAddress );
pxNetworkBuffer->ulIPAddress = ulIPAddress;
vARPGenerateRequestPacket( pxNetworkBuffer );
}
else
{
/* The lookup indicated that an ARP request has already been
sent out for the queried IP address. */
eReturned = eCantSendPacket;
}
}
if( eReturned != eCantSendPacket )
{
/* The network driver is responsible for freeing the network buffer
after the packet has been sent. */
#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
{
if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )
{
BaseType_t xIndex;
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{
pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
}
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
}
}
#endif
xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
}
else
{
/* The packet can't be sent (DHCP not completed?). Just drop the
packet. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
}
}
/*-----------------------------------------------------------*/
BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort )
{
BaseType_t xReturn = pdPASS;
FreeRTOS_Socket_t *pxSocket;
UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
/* Caller must check for minimum packet size. */
pxSocket = pxUDPSocketLookup( usPort );
if( pxSocket )
{
/* When refreshing the ARP cache with received UDP packets we must be
careful; hundreds of broadcast messages may pass and if we're not
handling them, no use to fill the ARP cache with those IP addresses. */
vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
#if( ipconfigUSE_CALLBACKS == 1 )
{
/* Did the owner of this socket register a reception handler ? */
if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleReceive ) )
{
struct freertos_sockaddr xSourceAddress, destinationAddress;
void *pcData = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
FOnUDPReceive_t xHandler = ( FOnUDPReceive_t ) pxSocket->u.xUDP.pxHandleReceive;
xSourceAddress.sin_port = pxNetworkBuffer->usPort;
xSourceAddress.sin_addr = pxNetworkBuffer->ulIPAddress;
destinationAddress.sin_port = usPort;
destinationAddress.sin_addr = pxUDPPacket->xIPHeader.ulDestinationIPAddress;
if( xHandler( ( Socket_t * ) pxSocket, ( void* ) pcData, ( size_t ) pxNetworkBuffer->xDataLength,
&xSourceAddress, &destinationAddress ) )
{
xReturn = pdFAIL; /* FAIL means that we did not consume or release the buffer */
}
}
}
#endif /* ipconfigUSE_CALLBACKS */
#if( ipconfigUDP_MAX_RX_PACKETS > 0 )
{
if( xReturn == pdPASS )
{
if ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) >= pxSocket->u.xUDP.uxMaxPackets )
{
FreeRTOS_debug_printf( ( "xProcessReceivedUDPPacket: buffer full %ld >= %ld port %u\n",
listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ),
pxSocket->u.xUDP.uxMaxPackets, pxSocket->usLocalPort ) );
xReturn = pdFAIL; /* we did not consume or release the buffer */
}
}
}
#endif
if( xReturn == pdPASS )
{
vTaskSuspendAll();
{
if( xReturn == pdPASS )
{
taskENTER_CRITICAL();
{
/* Add the network packet to the list of packets to be
processed by the socket. */
vListInsertEnd( &( pxSocket->u.xUDP.xWaitingPacketsList ), &( pxNetworkBuffer->xBufferListItem ) );
}
taskEXIT_CRITICAL();
}
}
xTaskResumeAll();
/* Set the socket's receive event */
if( pxSocket->xEventGroup != NULL )
{
xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
}
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) )
{
xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_READ );
}
}
#endif
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
{
if( pxSocket->pxUserSemaphore != NULL )
{
xSemaphoreGive( pxSocket->pxUserSemaphore );
}
}
#endif
#if( ipconfigUSE_DHCP == 1 )
{
if( xIsDHCPSocket( pxSocket ) )
{
xSendEventToIPTask( eDHCPEvent );
}
}
#endif
}
}
else
{
/* There is no socket listening to the target port, but still it might
be for this node. */
#if( ipconfigUSE_LLMNR == 1 )
/* a LLMNR request, check for the destination port. */
if( ( usPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) ||
( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) )
{
vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer );
}
else
#endif /* ipconfigUSE_LLMNR */
#if( ipconfigUSE_NBNS == 1 )
/* a NetBIOS request, check for the destination port */
if( ( usPort == FreeRTOS_ntohs( ipNBNS_PORT ) ) ||
( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipNBNS_PORT ) ) )
{
vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
xReturn = ( BaseType_t )ulNBNSHandlePacket( pxNetworkBuffer );
}
else
#endif /* ipconfigUSE_NBNS */
{
xReturn = pdFAIL;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,187 @@
Changes between 160919 and 180821 releases:
+ Multiple security improvements and fixes in packet parsing routines, DNS
caching, and TCP sequence number and ID generation.
+ Disable NBNS and LLMNR by default.
+ Add TCP hang protection by default.
We thank Ori Karliner of Zimperium zLabs Team for reporting these issues.
+ Update FreeRTOS_gethostbyname() to allow an IP address to be passed in -
in which case it is just returned as a uint32_t.
+ Introduce ipconfigSOCKET_HAS_USER_WAKE_CALLBACK to FreeRTOS_Sockets.c to
allow a user supposed callback function to be executed when socket events
occur in the same way that the socket semaphore is currently used.
+ Update xNetworkBuffersInitialise() to ensure the semaphore created by the
function is not accessed until after the NULL check.
+ Improve print messages output by the Win32 port layer version of
prvPrintAvailableNetworkInterfaces().
Changes between 160908 and 160919 releases:
+ Add a NULL check before attempting to close the DHCP socket. [Prior to
160823 the IP task closed the DHCP socket by calling a public API function
- which checked for the socket being NULL. This was changed to call a
local private function, which did not have a NULL check, in place of the
public API function.]
+ Various [internal only] naming changes to better comply with the FreeRTOS
naming conventions.
+ Improvements to the Zynq network driver. DMA transmission buffers now use
a counting semaphore. When all TX-buffers are in-use, the IP-task will
block momentarily until a TX-buffer becomes available.
+ Experimental implementation of the TCP window scaling protocol. The
scaling option will always be offered, at least with a factor 1. If the
TCP sliding window size becomes more than 64KB, the factor will increase
automatically.
+ ipconfigETHERNET_MINIMUM_PACKET_BYTES is now applied for every protocol:
TCP, UDP, and ARP.
+ Updated the Zynq project to use BufferAllocation_1.c rather than
BufferAllocation_2.c - which is a requirement with its current
configuration (due to the alignment requirements on the combined cache and
DMA configuration).
Changes between 160823 and 160908 releases:
+ Use ipconfigZERO_COPY_TX_DRIVER as the xReleaseAfterSend() parameter where
prvTCPReturnPacket() is called in prvSendData() to prevent unnecessary
copying of data.
+ Remove the use of the uxGetRxEventCount variable, which was used to give
priority to incoming messages, but could result in the IP task starving
application tasks of processing time.
Changes between 160112 and 160823 releases
NOTE: The 160908 release is a maintenance release for the 160112 single
interface labs release - not a release of the current development branch.
+ Various minor stability enhancements, including the ability to work with
configTICK_RATE_HZ set to less than 1KHz, closing DHCP sockets directly
rather than via FreeRTOS_closesocket(), and better handling of unknown
TCP packets before an IP address has been assigned.
+ ipBUFFER_PADDING is now configurable through the ipconfigBUFFER_PADDING
constant to improve network buffer alignment handling capabilities (expert
users/driver writers only).
+ Multiple improvements to the FTP server, including to how read only and
zero length files are handled.
+ ipconfigFTP_HAS_USER_PROPERTIES_HOOK (to allow each user to have a
different root directory and access rights) and
ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK (to handle AJAX style data)
introduced, although these are not yet fully tested and the constant names
are likely to change.
+ Introduce ipconfigHAS_TX_CRC_OFFLOADING.
+ ipconfigUSE_DHCP_HOOK is now called ipconfigUSE_DHCP_HOOK, and the name
of the callback function has also changed. See the web documentation for
details.
+ ipconfigTCP_RX_BUF_LEN is now ipconfigTCP_RX_BUFFER_LENGTH, and
ipconfigTCP_TX_BUF_LEN is now ipconfigTCP_TX_BUFFER_LENGTH, which is
actually how they have always been documented.
+ Added example TFTP server capable of receiving (not sending) files.
Intended for bootloader type functionality.
+ Various variable name changes for consistency (mainly ensuring UDP, TCP,
DNS, etc. always use the same case letters, and type prefixes are correct).
+ Various minor edits to improve types used by internal variables.
+ Simplified mapping of standard library functions to their Visual Studio
equivalents.
+ Improve robustness of network drivers.
+ Introduce pxResizeNetworkBufferWithDescriptor().
+ Removed obsolete FreeRTOSIPConfig.h constants from
FreeRTOSIPConfigDefaults.h.
+ Added additional asserts() - predominantly to catch incorrect structure
packing.
Changes between 160112 and 160111 releases
+ Updated the STM32 network driver so checksums are calculated by the
hardware.
+ Implemented a simple "quit" command in the TCP command console.
Changes between 150825 and 160111 releases
+ New device support: Demo applications and example drivers are provided
for Atmel SAM4E and ST STM32F4 microcontrollers.
+ Various updates to improve compliance with the FreeRTOS coding standard.
+ Added a command console example that uses TCP/IP for input and output (the
pre-existing command console example uses UDP/IP).
+ Updated the UDP logging example so it will send log messages to the local
UDP broadcast address if a specific IP address is not provided. This
simplifies configuration, but note not all switches and routers will pass
broadcast messages.
+ Add TCP echo client and TCP echo server examples to the Zynq demo.
+ Minor updates to the Zynq network driver.
+ Update the Zynq project to use version 2015.4 of the Xilinx SDK.
+ Introduce FreeRTOS_SignalSocket(), which can be used to interrupt a task
that is blocked while reading from a socket ( FreeRTOS_recv[from] ).
+ Make use of FreeRTOS_SignalSocket() in the FTP and HTTP servers.
+ Major updates to the NTP client, although this is not included in any of
the pre-configured demo applications yet.
+ Added support for DHCP zero pad option.
+ Added uxGetMinimumIPQueueSpace(), a function to monitor the minimum amount
of space on the message queue.
+ Better handling of zero length files in the FTP server.
+ Fixed a bug reported by Andrey Ivanov from swissEmbedded that affects
users of 'ipconfigZERO_COPY_TX_DRIVER'.
Changes between 150825 150825 (?)
+ Added xApplicationDHCPUserHook() so a user defined hook will be
called at certain points in the DHCP process if
ipconfigDHCP_USES_USER_HOOK is set to 1.
+ Added FreeRTOS_get_tx_head() to improve TCP zero copy behaviour - for
expert use only.
+ RST is no longer sent if only the ACK flag is set.
+ Previously, an immediate ACK was only sent when buffer space was
exhausted. Now, to improve performance, it is possible to send an
immediate ACK earlier - dependent on the ipconfigTCP_ACK_EARLIER_PACKET
setting.
+ LLMNR and NBNS requests can now be sent to locate other devices -
previously these protocols would only be replied to, not generated.
+ Added Auto-IP functionality (still in test) in case DHCP fails. Dependent
on the ipconfigDHCP_FALL_BACK_LINK_LAYER_ADDRESS and
ipconfigARP_USE_CLASH_DETECTION settings.
+ Added NTP code and demo.
+ FTP can now STOR and RETR zero-length files.
+ Added LLMNR demo to Win32 demo - so now the Win32 responds to
"ping RTOSDemo".
Changes between 141019 and 150825
+ Added FTP server, which uses the new FreeRTOS+FAT component.
+ Added basic HTTP server, which uses the new FreeRTOS+FAT component.
+ Multiple definitions that are now common with FreeRTOS+FAT have been moved
into FreeRTOS's ProjDefs.h header file, and so prefixed with 'pd'.
+ Introduced ipconfigZERO_COPY_TX_DRIVER, which defines who is responsible
for freeing a buffer sent to to the MAC driver for transmission, and
facilitates the development of zero copy drivers.
+ Introduced the FREERTOS_MSG_DONTWAIT flag. The flag can be used as a
simpler and faster alternative to using FreeRTOS_setsockopt() to set the
send or receive timeout to 0.
+ A few functions that were previously all lower case are now mixed case, as
lower case function names are only used when they are equivalent to a
a Berkeley sockets API function of the same name.
+ Introduced uxGetMinimumFreeNetworkBuffers() to return the minimum number
of network buffers that have ever existed since the application started
executing.
+ Introduce ipconfigETHERNET_MINIMUM_PACKET_BYTES to allow the application
writer to set their own minimum buffer size should the hardware not be
capable of padding under-sized Ethernet frames.
+ vNetworkBufferRelease() renamed vReleaseNetworkBuffer() - just for
consistency with the names of other functions in the same file.
+ Grouped DHCP status data into a structure.
+ DHCP is now tried both with and without the broadcast flag.
+ Replaced occurrences of configASSERT_VOID() with configASSERT().
+ ipconfigDNS_USE_CALLBACKS introduced to allow FreeRTOS_gethostbyname() to
be used without blocking.
+ Fix: LLMNR and NBNS behaviour when the reply is in a larger buffer than the
request, and BufferAllocation_2 was used.
+ Introduced ipMAX_IP_TASK_SLEEP_TIME to allow the application writer to
override the default value of 10 seconds.
+ Fix: Correct error in *pxUDPPayloadBuffer_to_NetworkBuffer().
+ FreeRTOS_recv() now recognises the FREERTOS_ZERO_COPY flag, which, when
set, the void *pvBuffer parameter is interpreted as void **pvBuffer.
+ FreeRTOS_listen() now returns an error code. Previously it always
returned 0.
+ Fix: Previously if a listening socket was reused, and a connection
failed, the TCP/IP stack closed the socket, now the socket is correctly
left unclosed as it is owned by the application.
+ Various other formatting and minor fix alterations.

View File

@ -0,0 +1,19 @@
FreeRTOS+TCP is released under the following MIT license.
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.

View File

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

View File

@ -0,0 +1,560 @@
/*
* FreeRTOS+TCP V2.0.7
* 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://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. */
/* Ensure defined configuration constants are using the most up to date naming. */
#ifdef tcpconfigIP_TIME_TO_LIVE
#error now called: ipconfigTCP_TIME_TO_LIVE
#endif
#ifdef updconfigIP_TIME_TO_LIVE
#error now called: ipconfigUDP_TIME_TO_LIVE
#endif
#ifdef ipFILLER_SIZE
#error now called: ipconfigPACKET_FILLER_SIZE
#endif
#ifdef dnsMAX_REQUEST_ATTEMPTS
#error now called: ipconfigDNS_REQUEST_ATTEMPTS
#endif
#ifdef ipconfigUDP_TASK_PRIORITY
#error now called: ipconfigIP_TASK_PRIORITY
#endif
#ifdef ipconfigUDP_TASK_STACK_SIZE_WORDS
#error now called: ipconfigIP_TASK_STACK_SIZE_WORDS
#endif
#ifdef ipconfigDRIVER_INCLUDED_RX_IP_FILTERING
#error now called: ipconfigETHERNET_DRIVER_FILTERS_PACKETS
#endif
#ifdef ipconfigMAX_SEND_BLOCK_TIME_TICKS
#error now called: ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS
#endif
#ifdef ipconfigUSE_RECEIVE_CONNECT_CALLBACKS
#error now called: ipconfigUSE_CALLBACKS
#endif
#ifdef ipconfigNUM_NETWORK_BUFFERS
#error now called: ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS
#endif
#ifdef ipconfigTCP_HANG_PROT
#error now called: ipconfigTCP_HANG_PROTECTION
#endif
#ifdef ipconfigTCP_HANG_PROT_TIME
#error now called: ipconfigTCP_HANG_PROTECTION_TIME
#endif
#ifdef FreeRTOS_lprintf
#error now called: FreeRTOS_debug_printf
#endif
#if ( ipconfigEVENT_QUEUE_LENGTH < ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 ) )
#error The ipconfigEVENT_QUEUE_LENGTH parameter must be at least ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5
#endif
#if ( ipconfigNETWORK_MTU < 46 )
#error ipconfigNETWORK_MTU must be at least 46.
#endif
#ifdef ipconfigBUFFER_ALLOC_FIXED_SIZE
#error ipconfigBUFFER_ALLOC_FIXED_SIZE was dropped and replaced by a const value, declared in BufferAllocation[12].c
#endif
#ifdef ipconfigNIC_SEND_PASSES_DMA
#error now called: ipconfigZERO_COPY_TX_DRIVER
#endif
#ifdef HAS_TX_CRC_OFFLOADING
/* _HT_ As these macro names have changed, throw an error
if they're still defined. */
#error now called: ipconfigHAS_TX_CRC_OFFLOADING
#endif
#ifdef HAS_RX_CRC_OFFLOADING
#error now called: ipconfigHAS_RX_CRC_OFFLOADING
#endif
#ifdef ipconfigTCP_RX_BUF_LEN
#error ipconfigTCP_RX_BUF_LEN is now called ipconfigTCP_RX_BUFFER_LENGTH
#endif
#ifdef ipconfigTCP_TX_BUF_LEN
#error ipconfigTCP_TX_BUF_LEN is now called ipconfigTCP_TX_BUFFER_LENGTH
#endif
#ifdef ipconfigDHCP_USES_USER_HOOK
#error ipconfigDHCP_USES_USER_HOOK and its associated callback have been superceeded - see http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK
#endif
#ifndef ipconfigUSE_TCP
#define ipconfigUSE_TCP ( 1 )
#endif
#if ipconfigUSE_TCP
/* Include support for TCP scaling windows */
#ifndef ipconfigUSE_TCP_WIN
#define ipconfigUSE_TCP_WIN ( 1 )
#endif
#ifndef ipconfigTCP_WIN_SEG_COUNT
#define ipconfigTCP_WIN_SEG_COUNT ( 256 )
#endif
#ifndef ipconfigIGNORE_UNKNOWN_PACKETS
/* When non-zero, TCP will not send RST packets in reply to
TCP packets which are unknown, or out-of-order. */
#define ipconfigIGNORE_UNKNOWN_PACKETS ( 0 )
#endif
#endif
/*
* For debuging/logging: check if the port number is used for telnet
* Some events will not be logged for telnet connections
* because it would produce logging about the transmission of the logging...
* This macro will only be used if FreeRTOS_debug_printf() is defined for logging
*/
#ifndef ipconfigTCP_MAY_LOG_PORT
#define ipconfigTCP_MAY_LOG_PORT(xPort) ( ( xPort ) != 23u )
#endif
#ifndef ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME
#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME portMAX_DELAY
#endif
#ifndef ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME
#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME portMAX_DELAY
#endif
/*
* FreeRTOS debug logging routine (proposal)
* The macro will be called in the printf() style. Users can define
* their own logging routine as:
*
* #define FreeRTOS_debug_printf( MSG ) my_printf MSG
*
* The FreeRTOS_debug_printf() must be thread-safe but does not have to be
* interrupt-safe.
*/
#ifdef ipconfigHAS_DEBUG_PRINTF
#if( ipconfigHAS_DEBUG_PRINTF == 0 )
#ifdef FreeRTOS_debug_printf
#error Do not define FreeRTOS_debug_print if ipconfigHAS_DEBUG_PRINTF is set to 0
#endif /* ifdef FreeRTOS_debug_printf */
#endif /* ( ipconfigHAS_DEBUG_PRINTF == 0 ) */
#endif /* ifdef ipconfigHAS_DEBUG_PRINTF */
#ifndef FreeRTOS_debug_printf
#define FreeRTOS_debug_printf( MSG ) do{} while(0)
#define ipconfigHAS_DEBUG_PRINTF 0
#endif
/*
* FreeRTOS general logging routine (proposal)
* Used in some utility functions such as FreeRTOS_netstat() and FreeRTOS_PrintARPCache()
*
* #define FreeRTOS_printf( MSG ) my_printf MSG
*
* The FreeRTOS_printf() must be thread-safe but does not have to be interrupt-safe
*/
#ifdef ipconfigHAS_PRINTF
#if( ipconfigHAS_PRINTF == 0 )
#ifdef FreeRTOS_printf
#error Do not define FreeRTOS_print if ipconfigHAS_PRINTF is set to 0
#endif /* ifdef FreeRTOS_debug_printf */
#endif /* ( ipconfigHAS_PRINTF == 0 ) */
#endif /* ifdef ipconfigHAS_PRINTF */
#ifndef FreeRTOS_printf
#define FreeRTOS_printf( MSG ) do{} while(0)
#define ipconfigHAS_PRINTF 0
#endif
/*
* In cases where a lot of logging is produced, FreeRTOS_flush_logging( )
* will be called to give the logging module a chance to flush the data
* An example of this is the netstat command, which produces many lines of logging
*/
#ifndef FreeRTOS_flush_logging
#define FreeRTOS_flush_logging( ) do{} while(0)
#endif
/* Malloc functions. Within most applications of FreeRTOS, the couple
* pvPortMalloc()/vPortFree() will be used.
* If there is also SDRAM, the user may decide to use a different memory
* allocator:
* MallocLarge is used to allocate large TCP buffers (for Rx/Tx)
* MallocSocket is used to allocate the space for the sockets
*/
#ifndef pvPortMallocLarge
#define pvPortMallocLarge( x ) pvPortMalloc( x )
#endif
#ifndef vPortFreeLarge
#define vPortFreeLarge(ptr) vPortFree(ptr)
#endif
#ifndef pvPortMallocSocket
#define pvPortMallocSocket( x ) pvPortMalloc( x )
#endif
#ifndef vPortFreeSocket
#define vPortFreeSocket(ptr) vPortFree(ptr)
#endif
/*
* At several places within the library, random numbers are needed:
* - DHCP: For creating a DHCP transaction number
* - TCP: Set the Initial Sequence Number: this is the value of the first outgoing
* sequence number being used when connecting to a peer.
* Having a well randomised ISN is important to avoid spoofing
* - UDP/TCP: for setting the first port number to be used, in case a socket
* uses a 'random' or anonymous port number
*/
#ifndef ipconfigRAND32
#define ipconfigRAND32() rand()
#endif
/* --------------------------------------------------------
* End of: HT Added some macro defaults for the PLUS-UDP project
* -------------------------------------------------------- */
#ifndef ipconfigUSE_NETWORK_EVENT_HOOK
#define ipconfigUSE_NETWORK_EVENT_HOOK 0
#endif
#ifndef ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS
#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( pdMS_TO_TICKS( 20 ) )
#endif
#ifndef ipconfigARP_CACHE_ENTRIES
#define ipconfigARP_CACHE_ENTRIES 10
#endif
#ifndef ipconfigMAX_ARP_RETRANSMISSIONS
#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5u )
#endif
#ifndef ipconfigMAX_ARP_AGE
#define ipconfigMAX_ARP_AGE 150u
#endif
#ifndef ipconfigUSE_ARP_REVERSED_LOOKUP
#define ipconfigUSE_ARP_REVERSED_LOOKUP 0
#endif
#ifndef ipconfigUSE_ARP_REMOVE_ENTRY
#define ipconfigUSE_ARP_REMOVE_ENTRY 0
#endif
#ifndef ipconfigINCLUDE_FULL_INET_ADDR
#define ipconfigINCLUDE_FULL_INET_ADDR 1
#endif
#ifndef ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS
#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 45
#endif
#ifndef ipconfigEVENT_QUEUE_LENGTH
#define ipconfigEVENT_QUEUE_LENGTH ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 )
#endif
#ifndef ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND
#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1
#endif
#ifndef ipconfigUDP_TIME_TO_LIVE
#define ipconfigUDP_TIME_TO_LIVE 128
#endif
#ifndef ipconfigTCP_TIME_TO_LIVE
#define ipconfigTCP_TIME_TO_LIVE 128
#endif
#ifndef ipconfigUDP_MAX_RX_PACKETS
/* Make postive to define the maximum number of packets which will be buffered
* for each UDP socket.
* Can be overridden with the socket option FREERTOS_SO_UDP_MAX_RX_PACKETS
*/
#define ipconfigUDP_MAX_RX_PACKETS 0u
#endif
#ifndef ipconfigUSE_DHCP
#define ipconfigUSE_DHCP 1
#endif
#ifndef ipconfigUSE_DHCP_HOOK
#define ipconfigUSE_DHCP_HOOK 0
#endif
#ifndef ipconfigDHCP_FALL_BACK_AUTO_IP
/*
* Only applicable when DHCP is in use:
* If no DHCP server responds, use "Auto-IP" : the
* device will allocate a random LinkLayer IP address.
*/
#define ipconfigDHCP_FALL_BACK_AUTO_IP ( 0 )
#endif
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
#define ipconfigARP_USE_CLASH_DETECTION 1
#endif
#ifndef ipconfigARP_USE_CLASH_DETECTION
#define ipconfigARP_USE_CLASH_DETECTION 0
#endif
#ifndef ipconfigNETWORK_MTU
#define ipconfigNETWORK_MTU 1500
#endif
#ifndef ipconfigTCP_MSS
#define ipconfigTCP_MSS ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_TCP_HEADER )
#endif
/* Each TCP socket has circular stream buffers for Rx and Tx, which
* have a fixed maximum size.
* The defaults for these size are defined here, although
* they can be overridden at runtime by using the setsockopt() call */
#ifndef ipconfigTCP_RX_BUFFER_LENGTH
#define ipconfigTCP_RX_BUFFER_LENGTH ( 4u * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
#endif
/* Define the size of Tx stream buffer for TCP sockets */
#ifndef ipconfigTCP_TX_BUFFER_LENGTH
# define ipconfigTCP_TX_BUFFER_LENGTH ( 4u * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
#endif
#ifndef ipconfigMAXIMUM_DISCOVER_TX_PERIOD
#ifdef _WINDOWS_
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 999 ) )
#else
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 30000 ) )
#endif /* _WINDOWS_ */
#endif /* ipconfigMAXIMUM_DISCOVER_TX_PERIOD */
#ifndef ipconfigUSE_DNS
#define ipconfigUSE_DNS 1
#endif
#ifndef ipconfigDNS_REQUEST_ATTEMPTS
#define ipconfigDNS_REQUEST_ATTEMPTS 5
#endif
#ifndef ipconfigUSE_DNS_CACHE
#define ipconfigUSE_DNS_CACHE 0
#endif
#if( ipconfigUSE_DNS_CACHE != 0 )
#ifndef ipconfigDNS_CACHE_NAME_LENGTH
/* 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 254
#endif
#ifndef ipconfigDNS_CACHE_ENTRIES
#define ipconfigDNS_CACHE_ENTRIES 1
#endif
#endif /* ipconfigUSE_DNS_CACHE != 0 */
#ifndef ipconfigCHECK_IP_QUEUE_SPACE
#define ipconfigCHECK_IP_QUEUE_SPACE 0
#endif
#ifndef ipconfigUSE_LLMNR
/* Include support for LLMNR: Link-local Multicast Name Resolution (non-Microsoft) */
#define ipconfigUSE_LLMNR ( 0 )
#endif
#if( !defined( ipconfigUSE_DNS ) )
#if( ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) )
/* LLMNR and NBNS depend on DNS because those protocols share a lot of code. */
#error When either LLMNR or NBNS is used, ipconfigUSE_DNS must be defined
#endif
#endif
#ifndef ipconfigREPLY_TO_INCOMING_PINGS
#define ipconfigREPLY_TO_INCOMING_PINGS 1
#endif
#ifndef ipconfigSUPPORT_OUTGOING_PINGS
#define ipconfigSUPPORT_OUTGOING_PINGS 0
#endif
#ifndef ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES
#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1
#endif
#ifndef ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES
#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1
#endif
#ifndef configINCLUDE_TRACE_RELATED_CLI_COMMANDS
#define ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS 0
#else
#define ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS configINCLUDE_TRACE_RELATED_CLI_COMMANDS
#endif
#ifndef ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ( 0 )
#endif
#ifndef ipconfigETHERNET_DRIVER_FILTERS_PACKETS
#define ipconfigETHERNET_DRIVER_FILTERS_PACKETS ( 0 )
#endif
#ifndef ipconfigWATCHDOG_TIMER
/* This macro will be called in every loop the IP-task makes. It may be
replaced by user-code that triggers a watchdog */
#define ipconfigWATCHDOG_TIMER()
#endif
#ifndef ipconfigUSE_CALLBACKS
#define ipconfigUSE_CALLBACKS ( 0 )
#endif
#if( ipconfigUSE_CALLBACKS != 0 )
#ifndef ipconfigIS_VALID_PROG_ADDRESS
/* Replace this macro with a test returning non-zero if the memory pointer to by x
* is valid memory which can contain executable code
* In fact this is an extra safety measure: if a handler points to invalid memory,
* it will not be called
*/
#define ipconfigIS_VALID_PROG_ADDRESS(x) ( ( x ) != NULL )
#endif
#endif
#ifndef ipconfigHAS_INLINE_FUNCTIONS
#define ipconfigHAS_INLINE_FUNCTIONS ( 1 )
#endif
#ifndef portINLINE
#define portINLINE inline
#endif
#ifndef ipconfigZERO_COPY_TX_DRIVER
/* When non-zero, the buffers passed to the SEND routine may be passed
to DMA. As soon as sending is ready, the buffers must be released by
calling vReleaseNetworkBufferAndDescriptor(), */
#define ipconfigZERO_COPY_TX_DRIVER ( 0 )
#endif
#ifndef ipconfigZERO_COPY_RX_DRIVER
/* This define doesn't mean much to the driver, except that it makes
sure that pxPacketBuffer_to_NetworkBuffer() will be included. */
#define ipconfigZERO_COPY_RX_DRIVER ( 0 )
#endif
#ifndef ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM
#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 0
#endif
#ifndef ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 0
#endif
#ifndef ipconfigDHCP_REGISTER_HOSTNAME
#define ipconfigDHCP_REGISTER_HOSTNAME 0
#endif
#ifndef ipconfigSOCKET_HAS_USER_SEMAPHORE
#define ipconfigSOCKET_HAS_USER_SEMAPHORE 0
#endif
#ifndef 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 30
#endif
#ifndef ipconfigTCP_IP_SANITY
#define ipconfigTCP_IP_SANITY 0
#endif
#ifndef ipconfigARP_STORES_REMOTE_ADDRESSES
#define ipconfigARP_STORES_REMOTE_ADDRESSES 0
#endif
#ifndef ipconfigBUFFER_PADDING
/* Expert option: define a value for 'ipBUFFER_PADDING'.
When 'ipconfigBUFFER_PADDING' equals 0,
'ipBUFFER_PADDING' will get a default value of 8 + 2 bytes. */
#define ipconfigBUFFER_PADDING 0
#endif
#ifndef ipconfigPACKET_FILLER_SIZE
#define ipconfigPACKET_FILLER_SIZE 2
#endif
#endif /* FREERTOS_DEFAULT_IP_CONFIG_H */

View File

@ -0,0 +1,141 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef FREERTOS_ARP_H
#define FREERTOS_ARP_H
#ifdef __cplusplus
extern "C" {
#endif
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "FreeRTOSIPConfigDefaults.h"
#include "IPTraceMacroDefaults.h"
/*-----------------------------------------------------------*/
/* Miscellaneous structure and definitions. */
/*-----------------------------------------------------------*/
typedef struct xARP_CACHE_TABLE_ROW
{
uint32_t ulIPAddress; /* The IP address of an ARP cache entry. */
MACAddress_t xMACAddress; /* The MAC address of an ARP cache entry. */
uint8_t ucAge; /* A value that is periodically decremented but can also be refreshed by active communication. The ARP cache entry is removed if the value reaches zero. */
uint8_t ucValid; /* pdTRUE: xMACAddress is valid, pdFALSE: waiting for ARP reply */
} ARPCacheRow_t;
typedef enum
{
eARPCacheMiss = 0, /* 0 An ARP table lookup did not find a valid entry. */
eARPCacheHit, /* 1 An ARP table lookup found a valid entry. */
eCantSendPacket /* 2 There is no IP address, or an ARP is still in progress, so the packet cannot be sent. */
} eARPLookupResult_t;
typedef enum
{
eNotFragment = 0, /* The IP packet being sent is not part of a fragment. */
eFirstFragment, /* The IP packet being sent is the first in a set of fragmented packets. */
eFollowingFragment /* The IP packet being sent is part of a set of fragmented packets. */
} eIPFragmentStatus_t;
/*
* If ulIPAddress is already in the ARP cache table then reset the age of the
* entry back to its maximum value. If ulIPAddress is not already in the ARP
* cache table then add it - replacing the oldest current entry if there is not
* a free space available.
*/
void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress, const uint32_t ulIPAddress );
#if( ipconfigARP_USE_CLASH_DETECTION != 0 )
/* Becomes non-zero if another device responded to a gratuitos ARP message. */
extern BaseType_t xARPHadIPClash;
/* MAC-address of the other device containing the same IP-address. */
extern MACAddress_t xARPClashMacAddress;
#endif /* ipconfigARP_USE_CLASH_DETECTION */
#if( ipconfigUSE_ARP_REMOVE_ENTRY != 0 )
/*
* In some rare cases, it might be useful to remove a ARP cache entry of a
* known MAC address to make sure it gets refreshed.
*/
uint32_t ulARPRemoveCacheEntryByMac( const MACAddress_t * pxMACAddress );
#endif /* ipconfigUSE_ARP_REMOVE_ENTRY != 0 */
/*
* Look for ulIPAddress in the ARP cache. If the IP address exists, copy the
* associated MAC address into pxMACAddress, refresh the ARP cache entry's
* age, and return eARPCacheHit. If the IP address does not exist in the ARP
* cache return eARPCacheMiss. If the packet cannot be sent for any reason
* (maybe DHCP is still in process, or the addressing needs a gateway but there
* isn't a gateway defined) then return eCantSendPacket.
*/
eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * const pxMACAddress );
#if( ipconfigUSE_ARP_REVERSED_LOOKUP != 0 )
/* Lookup an IP-address if only the MAC-address is known */
eARPLookupResult_t eARPGetCacheEntryByMac( MACAddress_t * const pxMACAddress, uint32_t *pulIPAddress );
#endif
/*
* Reduce the age count in each entry within the ARP cache. An entry is no
* longer considered valid and is deleted if its age reaches zero.
*/
void vARPAgeCache( void );
/*
* Send out an ARP request for the IP address contained in pxNetworkBuffer, and
* add an entry into the ARP table that indicates that an ARP reply is
* outstanding so re-transmissions can be generated.
*/
void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );
/*
* After DHCP is ready and when changing IP address, force a quick send of our new IP
* address
*/
void vARPSendGratuitous( void );
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FREERTOS_ARP_H */

View File

@ -0,0 +1,87 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef FREERTOS_DHCP_H
#define FREERTOS_DHCP_H
#ifdef __cplusplus
extern "C" {
#endif
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "IPTraceMacroDefaults.h"
/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
typedef enum eDHCP_PHASE
{
eDHCPPhasePreDiscover, /* Driver is about to send a DHCP discovery. */
eDHCPPhasePreRequest, /* Driver is about to request DHCP an IP address. */
#if( ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP != 0 )
eDHCPPhasePreLLA, /* Driver is about to try get an LLA address */
#endif /* ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP */
} eDHCPCallbackPhase_t;
/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
typedef enum eDHCP_ANSWERS
{
eDHCPContinue, /* Continue the DHCP process */
eDHCPUseDefaults, /* Stop DHCP and use the static defaults. */
eDHCPStopNoChanges, /* Stop DHCP and continue with current settings. */
} eDHCPCallbackAnswer_t;
/*
* NOT A PUBLIC API FUNCTION.
*/
void vDHCPProcess( BaseType_t xReset );
/* Internal call: returns true if socket is the current DHCP socket */
BaseType_t xIsDHCPSocket( Socket_t xSocket );
/* Prototype of the hook (or callback) function that must be provided by the
application if ipconfigUSE_DHCP_HOOK is set to 1. See the following URL for
usage information:
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK
*/
eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase, uint32_t ulIPAddress );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_DHCP_H */

View File

@ -0,0 +1,133 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef FREERTOS_DNS_H
#define FREERTOS_DNS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "IPTraceMacroDefaults.h"
/* The Link-local Multicast Name Resolution (LLMNR)
* is included.
* Note that a special MAC address is required in addition to the NIC's actual
* MAC address: 01:00:5E:00:00:FC
*
* The target IP address will be 224.0.0.252
*/
#if( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )
#define ipLLMNR_IP_ADDR 0xE00000FC
#else
#define ipLLMNR_IP_ADDR 0xFC0000E0
#endif /* ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN */
#define ipLLMNR_PORT 5355 /* Standard LLMNR port. */
#define ipDNS_PORT 53 /* Standard DNS port. */
#define ipDHCP_CLIENT 67
#define ipDHCP_SERVER 68
#define ipNBNS_PORT 137 /* NetBIOS Name Service. */
#define ipNBDGM_PORT 138 /* Datagram Service, not included. */
/*
* The following function should be provided by the user and return true if it
* matches the domain name.
*/
extern BaseType_t xApplicationDNSQueryHook( const char *pcName );
/*
* LLMNR is very similar to DNS, so is handled by the DNS routines.
*/
uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
#if( ipconfigUSE_LLMNR == 1 )
extern const MACAddress_t xLLMNR_MacAdress;
#endif /* ipconfigUSE_LLMNR */
#if( ipconfigUSE_NBNS != 0 )
/*
* Inspect a NetBIOS Names-Service message. If the name matches with ours
* (xApplicationDNSQueryHook returns true) an answer will be sent back.
* Note that LLMNR is a better protocol for name services on a LAN as it is
* less polluted
*/
uint32_t ulNBNSHandlePacket (NetworkBufferDescriptor_t *pxNetworkBuffer );
#endif /* ipconfigUSE_NBNS */
#if( ipconfigUSE_DNS_CACHE != 0 )
uint32_t FreeRTOS_dnslookup( const char *pcHostName );
#endif /* ipconfigUSE_DNS_CACHE != 0 */
#if( ipconfigDNS_USE_CALLBACKS != 0 )
/*
* Users may define this type of function as a callback.
* It will be called when a DNS reply is received or when a timeout has been reached.
*/
typedef void (* FOnDNSEvent ) ( const char * /* pcName */, void * /* pvSearchID */, uint32_t /* ulIPAddress */ );
/*
* Asynchronous version of gethostbyname()
* xTimeout is in units of ms.
*/
uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, FOnDNSEvent pCallback, void *pvSearchID, TickType_t xTimeout );
void FreeRTOS_gethostbyname_cancel( void *pvSearchID );
#endif
/*
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
* FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:
* _TBD_ Add URL
*/
uint32_t FreeRTOS_gethostbyname( const char *pcHostName );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_DNS_H */

View File

@ -0,0 +1,328 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef FREERTOS_IP_H
#define FREERTOS_IP_H
#ifdef __cplusplus
extern "C" {
#endif
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "FreeRTOSIPConfigDefaults.h"
#include "IPTraceMacroDefaults.h"
/* Some constants defining the sizes of several parts of a packet */
#define ipSIZE_OF_ETH_HEADER 14u
#define ipSIZE_OF_IPv4_HEADER 20u
#define ipSIZE_OF_IGMP_HEADER 8u
#define ipSIZE_OF_ICMP_HEADER 8u
#define ipSIZE_OF_UDP_HEADER 8u
#define ipSIZE_OF_TCP_HEADER 20u
/* The number of octets in the MAC and IP addresses respectively. */
#define ipMAC_ADDRESS_LENGTH_BYTES ( 6 )
#define ipIP_ADDRESS_LENGTH_BYTES ( 4 )
/* IP protocol definitions. */
#define ipPROTOCOL_ICMP ( 1 )
#define ipPROTOCOL_IGMP ( 2 )
#define ipPROTOCOL_TCP ( 6 )
#define ipPROTOCOL_UDP ( 17 )
/* Dimensions the buffers that are filled by received Ethernet frames. */
#define ipSIZE_OF_ETH_CRC_BYTES ( 4UL )
#define ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES ( 4UL )
#define ipTOTAL_ETHERNET_FRAME_SIZE ( ( ( uint32_t ) ipconfigNETWORK_MTU ) + ( ( uint32_t ) ipSIZE_OF_ETH_HEADER ) + ipSIZE_OF_ETH_CRC_BYTES + ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES )
/*_RB_ Comment may need updating. */
/* Space left at the beginning of a network buffer storage area to store a
pointer back to the network buffer. Should be a multiple of 8 to ensure 8 byte
alignment is maintained on architectures that require it.
In order to get a 32-bit alignment of network packets, an offset of 2 bytes
would be desirable, as defined by ipconfigPACKET_FILLER_SIZE. So the malloc'd
buffer will have the following contents:
uint32_t pointer; // word-aligned
uchar_8 filler[6];
<< ETH-header >> // half-word-aligned
uchar_8 dest[6]; // start of pucEthernetBuffer
uchar_8 dest[6];
uchar16_t type;
<< IP-header >> // word-aligned
uint8_t ucVersionHeaderLength;
etc
*/
#if( ipconfigBUFFER_PADDING != 0 )
#define ipBUFFER_PADDING ipconfigBUFFER_PADDING
#else
#define ipBUFFER_PADDING ( 8u + ipconfigPACKET_FILLER_SIZE )
#endif
/* The structure used to store buffers and pass them around the network stack.
Buffers can be in use by the stack, in use by the network interface hardware
driver, or free (not in use). */
typedef struct xNETWORK_BUFFER
{
ListItem_t xBufferListItem; /* Used to reference the buffer form the free buffer list or a socket. */
uint32_t ulIPAddress; /* Source or destination IP address, depending on usage scenario. */
uint8_t *pucEthernetBuffer; /* Pointer to the start of the Ethernet frame. */
size_t xDataLength; /* Starts by holding the total Ethernet frame length, then the UDP/TCP payload length. */
uint16_t usPort; /* Source or destination port, depending on usage scenario. */
uint16_t usBoundPort; /* The port to which a transmitting socket is bound. */
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
struct xNETWORK_BUFFER *pxNextBuffer; /* Possible optimisation for expert users - requires network driver support. */
#endif
} NetworkBufferDescriptor_t;
#include "pack_struct_start.h"
struct xMAC_ADDRESS
{
uint8_t ucBytes[ ipMAC_ADDRESS_LENGTH_BYTES ];
}
#include "pack_struct_end.h"
typedef struct xMAC_ADDRESS MACAddress_t;
typedef enum eNETWORK_EVENTS
{
eNetworkUp, /* The network is configured. */
eNetworkDown /* The network connection has been lost. */
} eIPCallbackEvent_t;
typedef enum ePING_REPLY_STATUS
{
eSuccess = 0, /* A correct reply has been received for an outgoing ping. */
eInvalidChecksum, /* A reply was received for an outgoing ping but the checksum of the reply was incorrect. */
eInvalidData /* A reply was received to an outgoing ping but the payload of the reply was not correct. */
} ePingReplyStatus_t;
typedef enum eNETWORK_ADDRESS_TYPE
{
eNetWorkAddressTypeIPV4,
eNetWorkAddressTypeIPV6,
eNetWorkAddressTypeHostName
} eNetWorkAddressType_t;
/* Endian related definitions. */
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
/* FreeRTOS_htons / FreeRTOS_htonl: some platforms might have built-in versions
using a single instruction so allow these versions to be overridden. */
#ifndef FreeRTOS_htons
#define FreeRTOS_htons( usIn ) ( (uint16_t) ( ( ( usIn ) << 8U ) | ( ( usIn ) >> 8U ) ) )
#endif
#ifndef FreeRTOS_htonl
#define FreeRTOS_htonl( ulIn ) \
( \
( uint32_t ) \
( \
( ( ( ( uint32_t ) ( ulIn ) ) ) << 24 ) | \
( ( ( ( uint32_t ) ( ulIn ) ) & 0x0000ff00UL ) << 8 ) | \
( ( ( ( uint32_t ) ( ulIn ) ) & 0x00ff0000UL ) >> 8 ) | \
( ( ( ( uint32_t ) ( ulIn ) ) ) >> 24 ) \
) \
)
#endif
#else /* ipconfigBYTE_ORDER */
#define FreeRTOS_htons( x ) ( ( uint16_t ) ( x ) )
#define FreeRTOS_htonl( x ) ( ( uint32_t ) ( x ) )
#endif /* ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN */
#define FreeRTOS_ntohs( x ) FreeRTOS_htons( x )
#define FreeRTOS_ntohl( x ) FreeRTOS_htonl( x )
#if( ipconfigHAS_INLINE_FUNCTIONS == 1 )
static portINLINE int32_t FreeRTOS_max_int32 (int32_t a, int32_t b);
static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b);
static portINLINE int32_t FreeRTOS_min_int32 (int32_t a, int32_t b);
static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b);
static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d);
static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d);
static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b);
static portINLINE BaseType_t FreeRTOS_max_BaseType (BaseType_t a, BaseType_t b);
static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b);
static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t a, UBaseType_t b);
static portINLINE int32_t FreeRTOS_max_int32 (int32_t a, int32_t b) { return a >= b ? a : b; }
static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b) { return a >= b ? a : b; }
static portINLINE int32_t FreeRTOS_min_int32 (int32_t a, int32_t b) { return a <= b ? a : b; }
static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b) { return a <= b ? a : b; }
static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d) { return d * ( ( a + d - 1u ) / d ); }
static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d) { return d * ( a / d ); }
static portINLINE BaseType_t FreeRTOS_max_BaseType (BaseType_t a, BaseType_t b) { return a >= b ? a : b; }
static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b) { return a >= b ? a : b; }
static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b) { return a <= b ? a : b; }
static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t a, UBaseType_t b) { return a <= b ? a : b; }
#else
#define FreeRTOS_max_int32(a,b) ( ( ( int32_t ) ( a ) ) >= ( ( int32_t ) ( b ) ) ? ( ( int32_t ) ( a ) ) : ( ( int32_t ) ( b ) ) )
#define FreeRTOS_max_uint32(a,b) ( ( ( uint32_t ) ( a ) ) >= ( ( uint32_t ) ( b ) ) ? ( ( uint32_t ) ( a ) ) : ( ( uint32_t ) ( b ) ) )
#define FreeRTOS_min_int32(a,b) ( ( ( int32_t ) a ) <= ( ( int32_t ) b ) ? ( ( int32_t ) a ) : ( ( int32_t ) b ) )
#define FreeRTOS_min_uint32(a,b) ( ( ( uint32_t ) a ) <= ( ( uint32_t ) b ) ? ( ( uint32_t ) a ) : ( ( uint32_t ) b ) )
/* Round-up: a = d * ( ( a + d - 1 ) / d ) */
#define FreeRTOS_round_up(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( ( uint32_t ) ( a ) ) + ( ( uint32_t ) ( d ) ) - 1UL ) / ( ( uint32_t ) ( d ) ) ) )
#define FreeRTOS_round_down(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( uint32_t ) ( a ) ) / ( ( uint32_t ) ( d ) ) ) )
#define FreeRTOS_ms_to_tick(ms) ( ( ms * configTICK_RATE_HZ + 500 ) / 1000 )
#define FreeRTOS_max_BaseType(a, b) ( ( ( BaseType_t ) ( a ) ) >= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) )
#define FreeRTOS_max_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) >= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )
#define FreeRTOS_min_BaseType(a, b) ( ( ( BaseType_t ) ( a ) ) <= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) )
#define FreeRTOS_min_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) <= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )
#endif /* ipconfigHAS_INLINE_FUNCTIONS */
#define pdMS_TO_MIN_TICKS( xTimeInMs ) ( pdMS_TO_TICKS( ( xTimeInMs ) ) < ( ( TickType_t ) 1 ) ? ( ( TickType_t ) 1 ) : pdMS_TO_TICKS( ( xTimeInMs ) ) )
#ifndef pdTRUE_SIGNED
/* Temporary solution: eventually the defines below will appear in 'Source\include\projdefs.h' */
#define pdTRUE_SIGNED pdTRUE
#define pdFALSE_SIGNED pdFALSE
#define pdTRUE_UNSIGNED ( ( UBaseType_t ) 1u )
#define pdFALSE_UNSIGNED ( ( UBaseType_t ) 0u )
#endif
/*
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
* FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_TCP_API_Functions.html
*/
BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );
void * FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks );
void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress );
void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint32_t *pulNetMask, const uint32_t *pulGatewayAddress, const uint32_t *pulDNSServerAddress );
BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, TickType_t xBlockTimeTicks );
void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer );
const uint8_t * FreeRTOS_GetMACAddress( void );
void FreeRTOS_UpdateMACAddress( const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES] );
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier );
uint32_t FreeRTOS_GetIPAddress( void );
void FreeRTOS_SetIPAddress( uint32_t ulIPAddress );
void FreeRTOS_SetNetmask( uint32_t ulNetmask );
void FreeRTOS_SetGatewayAddress( uint32_t ulGatewayAddress );
uint32_t FreeRTOS_GetGatewayAddress( void );
uint32_t FreeRTOS_GetDNSServerAddress( void );
uint32_t FreeRTOS_GetNetmask( void );
void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress );
BaseType_t FreeRTOS_IsNetworkUp( void );
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
UBaseType_t uxGetMinimumIPQueueSpace( void );
#endif
/*
* Defined in FreeRTOS_Sockets.c
* //_RB_ Don't think this comment is correct. If this is for internal use only it should appear after all the public API functions and not start with FreeRTOS_.
* Socket has had activity, reset the timer so it will not be closed
* because of inactivity
*/
const char *FreeRTOS_GetTCPStateName( UBaseType_t ulState);
/* _HT_ Temporary: show all valid ARP entries
*/
void FreeRTOS_PrintARPCache( void );
void FreeRTOS_ClearARP( void );
#if( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
/* DHCP has an option for clients to register their hostname. It doesn't
have much use, except that a device can be found in a router along with its
name. If this option is used the callback below must be provided by the
application writer to return a const string, denoting the device's name. */
const char *pcApplicationHostnameHook( void );
#endif /* ipconfigDHCP_REGISTER_HOSTNAME */
/* For backward compatibility define old structure names to the newer equivalent
structure name. */
#ifndef ipconfigENABLE_BACKWARD_COMPATIBILITY
#define ipconfigENABLE_BACKWARD_COMPATIBILITY 1
#endif
#if( ipconfigENABLE_BACKWARD_COMPATIBILITY == 1 )
#define xIPStackEvent_t IPStackEvent_t
#define xNetworkBufferDescriptor_t NetworkBufferDescriptor_t
#define xMACAddress_t MACAddress_t
#define xWinProperties_t WinProperties_t
#define xSocket_t Socket_t
#define xSocketSet_t SocketSet_t
#define ipSIZE_OF_IP_HEADER ipSIZE_OF_IPv4_HEADER
/* Since August 2016, the public types and fields below have changed name:
abbreviations TCP/UDP are now written in capitals, and type names now end with "_t". */
#define FOnConnected FOnConnected_t
#define FOnTcpReceive FOnTCPReceive_t
#define FOnTcpSent FOnTCPSent_t
#define FOnUdpReceive FOnUDPReceive_t
#define FOnUdpSent FOnUDPSent_t
#define pOnTcpConnected pxOnTCPConnected
#define pOnTcpReceive pxOnTCPReceive
#define pOnTcpSent pxOnTCPSent
#define pOnUdpReceive pxOnUDPReceive
#define pOnUdpSent pxOnUDPSent
#define FOnUdpSent FOnUDPSent_t
#define FOnTcpSent FOnTCPSent_t
#endif /* ipconfigENABLE_BACKWARD_COMPATIBILITY */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_IP_H */

View File

@ -0,0 +1,827 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef FREERTOS_IP_PRIVATE_H
#define FREERTOS_IP_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "FreeRTOSIPConfigDefaults.h"
#include "FreeRTOS_Sockets.h"
#include "IPTraceMacroDefaults.h"
#include "FreeRTOS_Stream_Buffer.h"
#if( ipconfigUSE_TCP == 1 )
#include "FreeRTOS_TCP_WIN.h"
#include "FreeRTOS_TCP_IP.h"
#endif
#include "event_groups.h"
typedef struct xNetworkAddressingParameters
{
uint32_t ulDefaultIPAddress;
uint32_t ulNetMask;
uint32_t ulGatewayAddress;
uint32_t ulDNSServerAddress;
uint32_t ulBroadcastAddress;
} NetworkAddressingParameters_t;
extern BaseType_t xTCPWindowLoggingLevel;
/*-----------------------------------------------------------*/
/* Protocol headers. */
/*-----------------------------------------------------------*/
#include "pack_struct_start.h"
struct xETH_HEADER
{
MACAddress_t xDestinationAddress; /* 0 + 6 = 6 */
MACAddress_t xSourceAddress; /* 6 + 6 = 12 */
uint16_t usFrameType; /* 12 + 2 = 14 */
}
#include "pack_struct_end.h"
typedef struct xETH_HEADER EthernetHeader_t;
#include "pack_struct_start.h"
struct xARP_HEADER
{
uint16_t usHardwareType; /* 0 + 2 = 2 */
uint16_t usProtocolType; /* 2 + 2 = 4 */
uint8_t ucHardwareAddressLength; /* 4 + 1 = 5 */
uint8_t ucProtocolAddressLength; /* 5 + 1 = 6 */
uint16_t usOperation; /* 6 + 2 = 8 */
MACAddress_t xSenderHardwareAddress; /* 8 + 6 = 14 */
uint8_t ucSenderProtocolAddress[ 4 ]; /* 14 + 4 = 18 */
MACAddress_t xTargetHardwareAddress; /* 18 + 6 = 24 */
uint32_t ulTargetProtocolAddress; /* 24 + 4 = 28 */
}
#include "pack_struct_end.h"
typedef struct xARP_HEADER ARPHeader_t;
#include "pack_struct_start.h"
struct xIP_HEADER
{
uint8_t ucVersionHeaderLength; /* 0 + 1 = 1 */
uint8_t ucDifferentiatedServicesCode; /* 1 + 1 = 2 */
uint16_t usLength; /* 2 + 2 = 4 */
uint16_t usIdentification; /* 4 + 2 = 6 */
uint16_t usFragmentOffset; /* 6 + 2 = 8 */
uint8_t ucTimeToLive; /* 8 + 1 = 9 */
uint8_t ucProtocol; /* 9 + 1 = 10 */
uint16_t usHeaderChecksum; /* 10 + 2 = 12 */
uint32_t ulSourceIPAddress; /* 12 + 4 = 16 */
uint32_t ulDestinationIPAddress; /* 16 + 4 = 20 */
}
#include "pack_struct_end.h"
typedef struct xIP_HEADER IPHeader_t;
#include "pack_struct_start.h"
struct xIGMP_HEADER
{
uint8_t ucVersionType; /* 0 + 1 = 1 */
uint8_t ucMaxResponseTime; /* 1 + 1 = 2 */
uint16_t usChecksum; /* 2 + 2 = 4 */
uint32_t usGroupAddress; /* 4 + 4 = 8 */
}
#include "pack_struct_end.h"
typedef struct xIGMP_HEADER IGMPHeader_t;
#include "pack_struct_start.h"
struct xICMP_HEADER
{
uint8_t ucTypeOfMessage; /* 0 + 1 = 1 */
uint8_t ucTypeOfService; /* 1 + 1 = 2 */
uint16_t usChecksum; /* 2 + 2 = 4 */
uint16_t usIdentifier; /* 4 + 2 = 6 */
uint16_t usSequenceNumber; /* 6 + 2 = 8 */
}
#include "pack_struct_end.h"
typedef struct xICMP_HEADER ICMPHeader_t;
#include "pack_struct_start.h"
struct xUDP_HEADER
{
uint16_t usSourcePort; /* 0 + 2 = 2 */
uint16_t usDestinationPort; /* 2 + 2 = 4 */
uint16_t usLength; /* 4 + 2 = 6 */
uint16_t usChecksum; /* 6 + 2 = 8 */
}
#include "pack_struct_end.h"
typedef struct xUDP_HEADER UDPHeader_t;
#include "pack_struct_start.h"
struct xTCP_HEADER
{
uint16_t usSourcePort; /* + 2 = 2 */
uint16_t usDestinationPort; /* + 2 = 4 */
uint32_t ulSequenceNumber; /* + 4 = 8 */
uint32_t ulAckNr; /* + 4 = 12 */
uint8_t ucTCPOffset; /* + 1 = 13 */
uint8_t ucTCPFlags; /* + 1 = 14 */
uint16_t usWindow; /* + 2 = 15 */
uint16_t usChecksum; /* + 2 = 18 */
uint16_t usUrgent; /* + 2 = 20 */
#if ipconfigUSE_TCP == 1
/* the option data is not a part of the TCP header */
uint8_t ucOptdata[ipSIZE_TCP_OPTIONS]; /* + 12 = 32 */
#endif
}
#include "pack_struct_end.h"
typedef struct xTCP_HEADER TCPHeader_t;
#include "pack_struct_start.h"
struct xPSEUDO_HEADER
{
uint32_t ulSourceAddress;
uint32_t ulDestinationAddress;
uint8_t ucZeros;
uint8_t ucProtocol;
uint16_t usUDPLength;
}
#include "pack_struct_end.h"
typedef struct xPSEUDO_HEADER PseudoHeader_t;
/*-----------------------------------------------------------*/
/* Nested protocol packets. */
/*-----------------------------------------------------------*/
#include "pack_struct_start.h"
struct xARP_PACKET
{
EthernetHeader_t xEthernetHeader; /* 0 + 14 = 14 */
ARPHeader_t xARPHeader; /* 14 + 28 = 42 */
}
#include "pack_struct_end.h"
typedef struct xARP_PACKET ARPPacket_t;
#include "pack_struct_start.h"
struct xIP_PACKET
{
EthernetHeader_t xEthernetHeader;
IPHeader_t xIPHeader;
}
#include "pack_struct_end.h"
typedef struct xIP_PACKET IPPacket_t;
#include "pack_struct_start.h"
struct xICMP_PACKET
{
EthernetHeader_t xEthernetHeader;
IPHeader_t xIPHeader;
ICMPHeader_t xICMPHeader;
}
#include "pack_struct_end.h"
typedef struct xICMP_PACKET ICMPPacket_t;
#include "pack_struct_start.h"
struct xUDP_PACKET
{
EthernetHeader_t xEthernetHeader; /* 0 + 14 = 14 */
IPHeader_t xIPHeader; /* 14 + 20 = 34 */
UDPHeader_t xUDPHeader; /* 34 + 8 = 42 */
}
#include "pack_struct_end.h"
typedef struct xUDP_PACKET UDPPacket_t;
#include "pack_struct_start.h"
struct xTCP_PACKET
{
EthernetHeader_t xEthernetHeader; /* 0 + 14 = 14 */
IPHeader_t xIPHeader; /* 14 + 20 = 34 */
TCPHeader_t xTCPHeader; /* 34 + 32 = 66 */
}
#include "pack_struct_end.h"
typedef struct xTCP_PACKET TCPPacket_t;
typedef union XPROT_PACKET
{
ARPPacket_t xARPPacket;
TCPPacket_t xTCPPacket;
UDPPacket_t xUDPPacket;
ICMPPacket_t xICMPPacket;
} ProtocolPacket_t;
/* The maximum UDP payload length. */
#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER ) - ipSIZE_OF_UDP_HEADER )
typedef enum
{
eReleaseBuffer = 0, /* Processing the frame did not find anything to do - just release the buffer. */
eProcessBuffer, /* An Ethernet frame has a valid address - continue process its contents. */
eReturnEthernetFrame, /* The Ethernet frame contains an ARP or ICMP packet that can be returned to its source. */
eFrameConsumed /* Processing the Ethernet packet contents resulted in the payload being sent to the stack. */
} eFrameProcessingResult_t;
typedef enum
{
eNoEvent = -1,
eNetworkDownEvent, /* 0: The network interface has been lost and/or needs [re]connecting. */
eNetworkRxEvent, /* 1: The network interface has queued a received Ethernet frame. */
eARPTimerEvent, /* 2: The ARP timer expired. */
eStackTxEvent, /* 3: The software stack has queued a packet to transmit. */
eDHCPEvent, /* 4: Process the DHCP state machine. */
eTCPTimerEvent, /* 5: See if any TCP socket needs attention. */
eTCPAcceptEvent, /* 6: Client API FreeRTOS_accept() waiting for client connections. */
eTCPNetStat, /* 7: IP-task is asked to produce a netstat listing. */
eSocketBindEvent, /* 8: Send a message to the IP-task to bind a socket to a port. */
eSocketCloseEvent, /* 9: Send a message to the IP-task to close a socket. */
eSocketSelectEvent, /*10: Send a message to the IP-task for select(). */
eSocketSignalEvent, /*11: A socket must be signalled. */
} eIPEvent_t;
typedef struct IP_TASK_COMMANDS
{
eIPEvent_t eEventType;
void *pvData;
} IPStackEvent_t;
#define ipBROADCAST_IP_ADDRESS 0xffffffffUL
/* Offset into the Ethernet frame that is used to temporarily store information
on the fragmentation status of the packet being sent. The value is important,
as it is past the location into which the destination address will get placed. */
#define ipFRAGMENTATION_PARAMETERS_OFFSET ( 6 )
#define ipSOCKET_OPTIONS_OFFSET ( 6 )
/* Only used when outgoing fragmentation is being used (FreeRTOSIPConfig.h
setting. */
#define ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT( usFragmentOffset ) ( ( ( usFragmentOffset ) == 0 ) ? ipUDP_PAYLOAD_OFFSET_IPv4 : ipIP_PAYLOAD_OFFSET )
/* The offset into a UDP packet at which the UDP data (payload) starts. */
#define ipUDP_PAYLOAD_OFFSET_IPv4 ( sizeof( UDPPacket_t ) )
/* The offset into an IP packet into which the IP data (payload) starts. */
#define ipIP_PAYLOAD_OFFSET ( sizeof( IPPacket_t ) )
#include "pack_struct_start.h"
struct xUDP_IP_FRAGMENT_PARAMETERS
{
uint8_t ucSocketOptions;
uint8_t ucPadFor16BitAlignment;
uint16_t usFragmentedPacketOffset;
uint16_t usFragmentLength;
uint16_t usPayloadChecksum;
}
#include "pack_struct_end.h"
typedef struct xUDP_IP_FRAGMENT_PARAMETERS IPFragmentParameters_t;
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
/* Ethernet frame types. */
#define ipARP_FRAME_TYPE ( 0x0608U )
#define ipIPv4_FRAME_TYPE ( 0x0008U )
/* ARP related definitions. */
#define ipARP_PROTOCOL_TYPE ( 0x0008U )
#define ipARP_HARDWARE_TYPE_ETHERNET ( 0x0100U )
#define ipARP_REQUEST ( 0x0100U )
#define ipARP_REPLY ( 0x0200U )
#else
/* Ethernet frame types. */
#define ipARP_FRAME_TYPE ( 0x0806U )
#define ipIPv4_FRAME_TYPE ( 0x0800U )
/* ARP related definitions. */
#define ipARP_PROTOCOL_TYPE ( 0x0800U )
#define ipARP_HARDWARE_TYPE_ETHERNET ( 0x0001U )
#define ipARP_REQUEST ( 0x0001 )
#define ipARP_REPLY ( 0x0002 )
#endif /* ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN */
/* For convenience, a MAC address of all zeros and another of all 0xffs are
defined const for quick reference. */
extern const MACAddress_t xBroadcastMACAddress; /* all 0xff's */
extern uint16_t usPacketIdentifier;
/* Define a default UDP packet header (declared in FreeRTOS_UDP_IP.c) */
typedef union xUDPPacketHeader
{
uint8_t ucBytes[24];
uint32_t ulWords[6];
} UDPPacketHeader_t;
extern UDPPacketHeader_t xDefaultPartUDPPacketHeader;
/* Structure that stores the netmask, gateway address and DNS server addresses. */
extern NetworkAddressingParameters_t xNetworkAddressing;
/* Structure that stores the defaults for netmask, gateway address and DNS.
These values will be copied to 'xNetworkAddressing' in case DHCP is not used,
and also in case DHCP does not lead to a confirmed request. */
extern NetworkAddressingParameters_t xDefaultAddressing;
/* True when BufferAllocation_1.c was included, false for BufferAllocation_2.c */
extern const BaseType_t xBufferAllocFixedSize;
/* Defined in FreeRTOS_Sockets.c */
#if ( ipconfigUSE_TCP == 1 )
extern List_t xBoundTCPSocketsList;
#endif
/* The local IP address is accessed from within xDefaultPartUDPPacketHeader,
rather than duplicated in its own variable. */
#define ipLOCAL_IP_ADDRESS_POINTER ( ( uint32_t * ) &( xDefaultPartUDPPacketHeader.ulWords[ 20u / sizeof(uint32_t) ] ) )
/* The local MAC address is accessed from within xDefaultPartUDPPacketHeader,
rather than duplicated in its own variable. */
#define ipLOCAL_MAC_ADDRESS ( &xDefaultPartUDPPacketHeader.ucBytes[0] )
/* ICMP packets are sent using the same function as UDP packets. The port
number is used to distinguish between the two, as 0 is an invalid UDP port. */
#define ipPACKET_CONTAINS_ICMP_DATA ( 0 )
/* For now, the lower 8 bits in 'xEventBits' will be reserved for the above
socket events. */
#define SOCKET_EVENT_BIT_COUNT 8
#define vSetField16( pxBase, xType, xField, usValue ) \
{ \
( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( usValue ) >> 8 ); \
( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xff ); \
}
#define vSetField32( pxBase, xType, xField, ulValue ) \
{ \
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( ulValue ) >> 24 ); \
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( ( ulValue ) >> 16 ) & 0xff ); \
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 2 ] = ( uint8_t ) ( ( ( ulValue ) >> 8 ) & 0xff ); \
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 3 ] = ( uint8_t ) ( ( ulValue ) & 0xff ); \
}
#define vFlip_16( left, right ) \
do { \
uint16_t tmp = (left); \
(left) = (right); \
(right) = tmp; \
} while (0)
#define vFlip_32( left, right ) \
do { \
uint32_t tmp = (left); \
(left) = (right); \
(right) = tmp; \
} while (0)
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (BaseType_t)(sizeof(x)/sizeof(x)[0])
#endif
/*
* A version of FreeRTOS_GetReleaseNetworkBuffer() that can be called from an
* interrupt. If a non zero value is returned, then the calling ISR should
* perform a context switch before exiting the ISR.
*/
BaseType_t FreeRTOS_ReleaseFreeNetworkBufferFromISR( void );
/*
* Create a message that contains a command to initialise the network interface.
* This is used during initialisation, and at any time the network interface
* goes down thereafter. The network interface hardware driver is responsible
* for sending the message that contains the network interface down command/
* event.
*
* Only use the FreeRTOS_NetworkDownFromISR() version if the function is to be
* called from an interrupt service routine. If FreeRTOS_NetworkDownFromISR()
* returns a non-zero value then a context switch should be performed ebfore
* the interrupt is exited.
*/
void FreeRTOS_NetworkDown( void );
BaseType_t FreeRTOS_NetworkDownFromISR( void );
/*
* Processes incoming ARP packets.
*/
eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame );
/*
* Inspect an Ethernet frame to see if it contains data that the stack needs to
* process. eProcessBuffer is returned if the frame should be processed by the
* stack. eReleaseBuffer is returned if the frame should be discarded.
*/
eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucEthernetBuffer );
/*
* Return the checksum generated over xDataLengthBytes from pucNextData.
*/
uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes );
/* Socket related private functions. */
/*
* The caller must ensure that pxNetworkBuffer->xDataLength is the UDP packet
* payload size (excluding packet headers) and that the packet in pucEthernetBuffer
* is at least the size of UDPPacket_t.
*/
BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort );
/*
* Initialize the socket list data structures for TCP and UDP.
*/
BaseType_t vNetworkSocketsInit( void );
/*
* Returns pdTRUE if the IP task has been created and is initialised. Otherwise
* returns pdFALSE.
*/
BaseType_t xIPIsNetworkTaskReady( void );
#if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
struct XSOCKET;
typedef void (*SocketWakeupCallback_t)( struct XSOCKET * pxSocket );
#endif
#if( ipconfigUSE_TCP == 1 )
/*
* Actually a user thing, but because xBoundTCPSocketsList, let it do by the
* IP-task
*/
void vTCPNetStat( void );
/*
* At least one socket needs to check for timeouts
*/
TickType_t xTCPTimerCheck( BaseType_t xWillSleep );
/* Every TCP socket has a buffer space just big enough to store
the last TCP header received.
As a reference of this field may be passed to DMA, force the
alignment to 8 bytes. */
typedef union
{
struct
{
/* Increase the alignment of this union by adding a 64-bit variable. */
uint64_t ullAlignmentWord;
} a;
struct
{
/* The next field only serves to give 'ucLastPacket' a correct
alignment of 8 + 2. See comments in FreeRTOS_IP.h */
uint8_t ucFillPacket[ ipconfigPACKET_FILLER_SIZE ];
uint8_t ucLastPacket[ sizeof( TCPPacket_t ) ];
} u;
} LastTCPPacket_t;
/*
* Note that the values of all short and long integers in these structs
* are being stored in the native-endian way
* Translation should take place when accessing any structure which defines
* network packets, such as IPHeader_t and TCPHeader_t
*/
typedef struct TCPSOCKET
{
uint32_t ulRemoteIP; /* IP address of remote machine */
uint16_t usRemotePort; /* Port on remote machine */
struct {
/* Most compilers do like bit-flags */
uint32_t
bMssChange : 1, /* This socket has seen a change in MSS */
bPassAccept : 1, /* when true, this socket may be returned in a call to accept() */
bPassQueued : 1, /* when true, this socket is an orphan until it gets connected
* Why an orphan? Because it may not be returned in a accept() call until it
* gets the state eESTABLISHED */
bReuseSocket : 1, /* When a listening socket gets a connection, do not create a new instance but keep on using it */
bCloseAfterSend : 1,/* As soon as the last byte has been transmitted, finalise the connection
* Useful in e.g. FTP connections, where the last data bytes are sent along with the FIN flag */
bUserShutdown : 1, /* User requesting a graceful shutdown */
bCloseRequested : 1,/* Request to finalise the connection */
bLowWater : 1, /* high-water level has been reached. Cleared as soon as 'rx-count < lo-water' */
bWinChange : 1, /* The value of bLowWater has changed, must send a window update */
bSendKeepAlive : 1, /* When this flag is true, a TCP keep-alive message must be send */
bWaitKeepAlive : 1, /* When this flag is true, a TCP keep-alive reply is expected */
bConnPrepared : 1, /* Connecting socket: Message has been prepared */
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
bConnPassed : 1, /* Connecting socket: Socket has been passed in a successful select() */
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
bFinAccepted : 1, /* This socket has received (or sent) a FIN and accepted it */
bFinSent : 1, /* We've sent out a FIN */
bFinRecv : 1, /* We've received a FIN from our peer */
bFinAcked : 1, /* Our FIN packet has been acked */
bFinLast : 1, /* The last ACK (after FIN and FIN+ACK) has been sent or will be sent by the peer */
bRxStopped : 1, /* Application asked to temporarily stop reception */
bMallocError : 1, /* There was an error allocating a stream */
bWinScaling : 1; /* A TCP-Window Scaling option was offered and accepted in the SYN phase. */
} bits;
uint32_t ulHighestRxAllowed;
/* The highest sequence number that we can receive at any moment */
uint16_t usTimeout; /* Time (in ticks) after which this socket needs attention */
uint16_t usCurMSS; /* Current Maximum Segment Size */
uint16_t usInitMSS; /* Initial maximum segment Size */
uint16_t usChildCount; /* In case of a listening socket: number of connections on this port number */
uint16_t usBacklog; /* In case of a listening socket: maximum number of concurrent connections on this port number */
uint8_t ucRepCount; /* Send repeat count, for retransmissions
* This counter is separate from the xmitCount in the
* TCP win segments */
uint8_t ucTCPState; /* TCP state: see eTCP_STATE */
struct XSOCKET *pxPeerSocket; /* for server socket: child, for child socket: parent */
#if( ipconfigTCP_KEEP_ALIVE == 1 )
uint8_t ucKeepRepCount;
TickType_t xLastAliveTime;
#endif /* ipconfigTCP_KEEP_ALIVE */
#if( ipconfigTCP_HANG_PROTECTION == 1 )
TickType_t xLastActTime;
#endif /* ipconfigTCP_HANG_PROTECTION */
size_t uxLittleSpace;
size_t uxEnoughSpace;
size_t uxRxStreamSize;
size_t uxTxStreamSize;
StreamBuffer_t *rxStream;
StreamBuffer_t *txStream;
#if( ipconfigUSE_TCP_WIN == 1 )
NetworkBufferDescriptor_t *pxAckMessage;
#endif /* ipconfigUSE_TCP_WIN */
/* Buffer space to store the last TCP header received. */
LastTCPPacket_t xPacket;
uint8_t tcpflags; /* TCP flags */
#if( ipconfigUSE_TCP_WIN != 0 )
uint8_t ucMyWinScaleFactor;
uint8_t ucPeerWinScaleFactor;
#endif
#if( ipconfigUSE_CALLBACKS == 1 )
FOnTCPReceive_t pxHandleReceive; /*
* In case of a TCP socket:
* typedef void (* FOnTCPReceive_t) (Socket_t xSocket, void *pData, size_t xLength );
*/
FOnTCPSent_t pxHandleSent;
FOnConnected_t pxHandleConnected; /* Actually type: typedef void (* FOnConnected_t) (Socket_t xSocket, BaseType_t ulConnected ); */
#endif /* ipconfigUSE_CALLBACKS */
uint32_t ulWindowSize; /* Current Window size advertised by peer */
uint32_t ulRxCurWinSize; /* Constantly changing: this is the current size available for data reception */
size_t uxRxWinSize; /* Fixed value: size of the TCP reception window */
size_t uxTxWinSize; /* Fixed value: size of the TCP transmit window */
TCPWindow_t xTCPWindow;
} IPTCPSocket_t;
#endif /* ipconfigUSE_TCP */
typedef struct UDPSOCKET
{
List_t xWaitingPacketsList; /* Incoming packets */
#if( ipconfigUDP_MAX_RX_PACKETS > 0 )
UBaseType_t uxMaxPackets; /* Protection: limits the number of packets buffered per socket */
#endif /* ipconfigUDP_MAX_RX_PACKETS */
#if( ipconfigUSE_CALLBACKS == 1 )
FOnUDPReceive_t pxHandleReceive; /*
* In case of a UDP socket:
* typedef void (* FOnUDPReceive_t) (Socket_t xSocket, void *pData, size_t xLength, struct freertos_sockaddr *pxAddr );
*/
FOnUDPSent_t pxHandleSent;
#endif /* ipconfigUSE_CALLBACKS */
} IPUDPSocket_t;
typedef enum eSOCKET_EVENT {
eSOCKET_RECEIVE = 0x0001,
eSOCKET_SEND = 0x0002,
eSOCKET_ACCEPT = 0x0004,
eSOCKET_CONNECT = 0x0008,
eSOCKET_BOUND = 0x0010,
eSOCKET_CLOSED = 0x0020,
eSOCKET_INTR = 0x0040,
eSOCKET_ALL = 0x007F,
} eSocketEvent_t;
typedef struct XSOCKET
{
EventBits_t xEventBits;
EventGroupHandle_t xEventGroup;
ListItem_t xBoundSocketListItem; /* Used to reference the socket from a bound sockets list. */
TickType_t xReceiveBlockTime; /* if recv[to] is called while no data is available, wait this amount of time. Unit in clock-ticks */
TickType_t xSendBlockTime; /* if send[to] is called while there is not enough space to send, wait this amount of time. Unit in clock-ticks */
uint16_t usLocalPort; /* Local port on this machine */
uint8_t ucSocketOptions;
uint8_t ucProtocol; /* choice of FREERTOS_IPPROTO_UDP/TCP */
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
SemaphoreHandle_t pxUserSemaphore;
#endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
#if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
SocketWakeupCallback_t pxUserWakeCallback;
#endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
struct xSOCKET_SET *pxSocketSet;
/* User may indicate which bits are interesting for this socket. */
EventBits_t xSelectBits;
/* These bits indicate the events which have actually occurred.
They are maintained by the IP-task */
EventBits_t xSocketBits;
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
/* TCP/UDP specific fields: */
/* Before accessing any member of this structure, it should be confirmed */
/* that the protocol corresponds with the type of structure */
union
{
IPUDPSocket_t xUDP;
#if( ipconfigUSE_TCP == 1 )
IPTCPSocket_t xTCP;
/* Make sure that xTCP is 8-bytes aligned by
declaring a 64-bit variable in the same union */
uint64_t ullTCPAlignment;
#endif /* ipconfigUSE_TCP */
} u;
} FreeRTOS_Socket_t;
#if( ipconfigUSE_TCP == 1 )
/*
* Lookup a TCP socket, using a multiple matching: both port numbers and
* return IP address.
*/
FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort );
#endif /* ipconfigUSE_TCP */
/*
* Look up a local socket by finding a match with the local port.
*/
FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort );
/*
* Called when the application has generated a UDP packet to send.
*/
void vProcessGeneratedUDPPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );
/*
* Calculate the upper-layer checksum
* Works both for UDP, ICMP and TCP packages
* bOut = true: checksum will be set in outgoing packets
* bOut = false: checksum will be calculated for incoming packets
* returning 0xffff means: checksum was correct
*/
uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, size_t uxBufferLength, BaseType_t xOutgoingPacket );
/*
* An Ethernet frame has been updated (maybe it was an ARP request or a PING
* request?) and is to be sent back to its source.
*/
void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t xReleaseAfterSend );
/*
* The internal version of bind()
* If 'ulInternal' is true, it is called by the driver
* The TCP driver needs to bind a socket at the moment a listening socket
* creates a new connected socket
*/
BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal );
/*
* Internal function to add streaming data to a TCP socket. If ulIn == true,
* data will be added to the rxStream, otherwise to the tXStream. Normally data
* will be written with ulOffset == 0, meaning: at the end of the FIFO. When
* packet come in out-of-order, an offset will be used to put it in front and
* the head will not change yet.
*/
int32_t lTCPAddRxdata(FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount);
/*
* Currently called for any important event.
*/
void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket );
/*
* Some helping function, their meaning should be clear
*/
static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr);
static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr)
{
return ( ( ( uint32_t )apChr[0] ) << 24) |
( ( ( uint32_t )apChr[1] ) << 16) |
( ( ( uint32_t )apChr[2] ) << 8) |
( ( ( uint32_t )apChr[3] ) );
}
static portINLINE uint16_t usChar2u16 (const uint8_t *apChr);
static portINLINE uint16_t usChar2u16 (const uint8_t *apChr)
{
return ( uint16_t )
( ( ( ( uint32_t )apChr[0] ) << 8) |
( ( ( uint32_t )apChr[1] ) ) );
}
/* Check a single socket for retransmissions and timeouts */
BaseType_t xTCPSocketCheck( FreeRTOS_Socket_t *pxSocket );
BaseType_t xTCPCheckNewClient( FreeRTOS_Socket_t *pxSocket );
/* Defined in FreeRTOS_Sockets.c
* Close a socket
*/
void *vSocketClose( FreeRTOS_Socket_t *pxSocket );
/*
* Send the event eEvent to the IP task event queue, using a block time of
* zero. Return pdPASS if the message was sent successfully, otherwise return
* pdFALSE.
*/
BaseType_t xSendEventToIPTask( eIPEvent_t eEvent );
/*
* The same as above, but a struct as a parameter, containing:
* eIPEvent_t eEventType;
* void *pvData;
*/
BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t xTimeout );
/*
* Returns a pointer to the original NetworkBuffer from a pointer to a UDP
* payload buffer.
*/
NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer );
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
/*
* For the case where the network driver passes a buffer directly to a DMA
* descriptor, this function can be used to translate a 'network buffer' to
* a 'network buffer descriptor'.
*/
NetworkBufferDescriptor_t *pxPacketBuffer_to_NetworkBuffer( const void *pvBuffer );
#endif
/*
* Internal: Sets a new state for a TCP socket and performs the necessary
* actions like calling a OnConnected handler to notify the socket owner.
*/
#if( ipconfigUSE_TCP == 1 )
void vTCPStateChange( FreeRTOS_Socket_t *pxSocket, enum eTCP_STATE eTCPState );
#endif /* ipconfigUSE_TCP */
/*_RB_ Should this be part of the public API? */
void FreeRTOS_netstat( void );
/* Returns pdTRUE is this function is called from the IP-task */
BaseType_t xIsCallingFromIPTask( void );
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
typedef struct xSOCKET_SET
{
EventGroupHandle_t xSelectGroup;
BaseType_t bApiCalled; /* True if the API was calling the private vSocketSelect */
FreeRTOS_Socket_t *pxSocket;
} SocketSelect_t;
extern void vSocketSelect( SocketSelect_t *pxSocketSelect );
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
void vIPSetDHCPTimerEnableState( BaseType_t xEnableState );
void vIPReloadDHCPTimer( uint32_t ulLeaseTime );
#if( ipconfigDNS_USE_CALLBACKS != 0 )
void vIPReloadDNSTimer( uint32_t ulCheckTime );
void vIPSetDnsTimerEnableState( BaseType_t xEnableState );
#endif
/* Send the network-up event and start the ARP timer. */
void vIPNetworkUpCalls( void );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_IP_PRIVATE_H */

View File

@ -0,0 +1,393 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef FREERTOS_SOCKETS_H
#define FREERTOS_SOCKETS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Standard includes. */
#include <string.h>
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#ifndef FREERTOS_IP_CONFIG_H
#error FreeRTOSIPConfig.h has not been included yet
#endif
/* Event bit definitions are required by the select functions. */
#include "event_groups.h"
#ifndef INC_FREERTOS_H
#error FreeRTOS.h must be included before FreeRTOS_Sockets.h.
#endif
#ifndef INC_TASK_H
#ifndef TASK_H /* For compatibility with older FreeRTOS versions. */
#error The FreeRTOS header file task.h must be included before FreeRTOS_Sockets.h.
#endif
#endif
/* Assigned to an Socket_t variable when the socket is not valid, probably
because it could not be created. */
#define FREERTOS_INVALID_SOCKET ( ( void * ) ~0U )
/* API function error values. As errno is supported, the FreeRTOS sockets
functions return error codes rather than just a pass or fail indication. */
/* HT: Extended the number of error codes, gave them positive values and if possible
the corresponding found in errno.h
In case of an error, API's will still return negative numbers, e.g.
return -pdFREERTOS_ERRNO_EWOULDBLOCK;
in case an operation would block */
/* The following defines are obsolete, please use -pdFREERTOS_ERRNO_Exxx */
#define FREERTOS_SOCKET_ERROR ( -1 )
#define FREERTOS_EWOULDBLOCK ( - pdFREERTOS_ERRNO_EWOULDBLOCK )
#define FREERTOS_EINVAL ( - pdFREERTOS_ERRNO_EINVAL )
#define FREERTOS_EADDRNOTAVAIL ( - pdFREERTOS_ERRNO_EADDRNOTAVAIL )
#define FREERTOS_EADDRINUSE ( - pdFREERTOS_ERRNO_EADDRINUSE )
#define FREERTOS_ENOBUFS ( - pdFREERTOS_ERRNO_ENOBUFS )
#define FREERTOS_ENOPROTOOPT ( - pdFREERTOS_ERRNO_ENOPROTOOPT )
#define FREERTOS_ECLOSED ( - pdFREERTOS_ERRNO_ENOTCONN )
/* Values for the parameters to FreeRTOS_socket(), inline with the Berkeley
standard. See the documentation of FreeRTOS_socket() for more information. */
#define FREERTOS_AF_INET ( 2 )
#define FREERTOS_AF_INET6 ( 10 )
#define FREERTOS_SOCK_DGRAM ( 2 )
#define FREERTOS_IPPROTO_UDP ( 17 )
#define FREERTOS_SOCK_STREAM ( 1 )
#define FREERTOS_IPPROTO_TCP ( 6 )
/* IP packet of type "Any local network"
* can be used in stead of TCP for testing with sockets in raw mode
*/
#define FREERTOS_IPPROTO_USR_LAN ( 63 )
/* A bit value that can be passed into the FreeRTOS_sendto() function as part of
the flags parameter. Setting the FREERTOS_ZERO_COPY in the flags parameter
indicates that the zero copy interface is being used. See the documentation for
FreeRTOS_sockets() for more information. */
#define FREERTOS_ZERO_COPY ( 1 )
/* Values that can be passed in the option name parameter of calls to
FreeRTOS_setsockopt(). */
#define FREERTOS_SO_RCVTIMEO ( 0 ) /* Used to set the receive time out. */
#define FREERTOS_SO_SNDTIMEO ( 1 ) /* Used to set the send time out. */
#define FREERTOS_SO_UDPCKSUM_OUT ( 2 ) /* Used to turn the use of the UDP checksum by a socket on or off. This also doubles as part of an 8-bit bitwise socket option. */
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
#define FREERTOS_SO_SET_SEMAPHORE ( 3 ) /* Used to set a user's semaphore */
#endif
#define FREERTOS_SO_SNDBUF ( 4 ) /* Set the size of the send buffer (TCP only) */
#define FREERTOS_SO_RCVBUF ( 5 ) /* Set the size of the receive buffer (TCP only) */
#if ipconfigUSE_CALLBACKS == 1
#define FREERTOS_SO_TCP_CONN_HANDLER ( 6 ) /* Install a callback for (dis) connection events. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
#define FREERTOS_SO_TCP_RECV_HANDLER ( 7 ) /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
#define FREERTOS_SO_TCP_SENT_HANDLER ( 8 ) /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
#define FREERTOS_SO_UDP_RECV_HANDLER ( 9 ) /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
#define FREERTOS_SO_UDP_SENT_HANDLER ( 10 ) /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
#endif /* ipconfigUSE_CALLBACKS */
#define FREERTOS_SO_REUSE_LISTEN_SOCKET ( 11 ) /* When a listening socket gets connected, do not create a new one but re-use it */
#define FREERTOS_SO_CLOSE_AFTER_SEND ( 12 ) /* As soon as the last byte has been transmitted, finalise the connection */
#define FREERTOS_SO_WIN_PROPERTIES ( 13 ) /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
#define FREERTOS_SO_SET_FULL_SIZE ( 14 ) /* Refuse to send packets smaller than MSS */
#define FREERTOS_SO_STOP_RX ( 15 ) /* 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_NOT_LAST_IN_FRAGMENTED_PACKET ( 0x80 ) /* For internal use only, but also part of an 8-bit bitwise value. */
#define FREERTOS_FRAGMENTED_PACKET ( 0x40 ) /* For internal use only, but also part of an 8-bit bitwise value. */
/* Values for flag for FreeRTOS_shutdown(). */
#define FREERTOS_SHUT_RD ( 0 ) /* Not really at this moment, just for compatibility of the interface */
#define FREERTOS_SHUT_WR ( 1 )
#define FREERTOS_SHUT_RDWR ( 2 )
/* Values for flag for FreeRTOS_recv(). */
#define FREERTOS_MSG_OOB ( 2 ) /* process out-of-band data */
#define FREERTOS_MSG_PEEK ( 4 ) /* peek at incoming message */
#define FREERTOS_MSG_DONTROUTE ( 8 ) /* send without using routing tables */
#define FREERTOS_MSG_DONTWAIT ( 16 ) /* Can be used with recvfrom(), sendto(), recv(), and send(). */
typedef struct xWIN_PROPS {
/* Properties of the Tx buffer and Tx window */
int32_t lTxBufSize; /* Unit: bytes */
int32_t lTxWinSize; /* Unit: MSS */
/* Properties of the Rx buffer and Rx window */
int32_t lRxBufSize; /* Unit: bytes */
int32_t lRxWinSize; /* Unit: MSS */
} WinProperties_t;
/* For compatibility with the expected Berkeley sockets naming. */
#define socklen_t uint32_t
/* For this limited implementation, only two members are required in the
Berkeley style sockaddr structure. */
struct freertos_sockaddr
{
/* _HT_ On 32- and 64-bit architectures, the addition of the two uint8_t
fields doesn't make the structure bigger, due to alignment.
The fields are inserted as a preparation for IPv6. */
/* sin_len and sin_family not used in the IPv4-only release. */
uint8_t sin_len; /* length of this structure. */
uint8_t sin_family; /* FREERTOS_AF_INET. */
uint16_t sin_port;
uint32_t sin_addr;
};
#if ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN
#define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \
( ( ( ( uint32_t ) ( ucOctet3 ) ) << 24UL ) | \
( ( ( uint32_t ) ( ucOctet2 ) ) << 16UL ) | \
( ( ( uint32_t ) ( ucOctet1 ) ) << 8UL ) | \
( ( uint32_t ) ( ucOctet0 ) ) )
#define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer ) \
sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \
( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ), \
( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \
( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\
( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ) )
#else /* ipconfigBYTE_ORDER */
#define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \
( ( ( ( uint32_t ) ( ucOctet0 ) ) << 24UL ) | \
( ( ( uint32_t ) ( ucOctet1 ) ) << 16UL ) | \
( ( ( uint32_t ) ( ucOctet2 ) ) << 8UL ) | \
( ( uint32_t ) ( ucOctet3 ) ) )
#define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer ) \
sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \
( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ), \
( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\
( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \
( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ) )
#endif /* ipconfigBYTE_ORDER */
/* The socket type itself. */
typedef void *Socket_t;
/* The SocketSet_t type is the equivalent to the fd_set type used by the
Berkeley API. */
typedef void *SocketSet_t;
/**
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
* FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_TCP_API_Functions.html
*/
Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol );
int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength );
int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength );
BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );
/* function to get the local address and IP port */
size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );
/* Made available when ipconfigETHERNET_DRIVER_FILTERS_PACKETS is set to 1. */
BaseType_t xPortHasUDPSocket( uint16_t usPortNr );
#if ipconfigUSE_TCP == 1
BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );
BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog );
BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags );
BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags );
Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength );
BaseType_t FreeRTOS_shutdown (Socket_t xSocket, BaseType_t xHow);
#if( ipconfigSUPPORT_SIGNALS != 0 )
/* Send a signal to the task which is waiting for a given socket. */
BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket );
/* Send a signal to the task which reads from this socket (FromISR
version). */
BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken );
#endif /* ipconfigSUPPORT_SIGNALS */
/* Return the remote address and IP port. */
BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );
/* returns pdTRUE if TCP socket is connected */
BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket );
/* returns the actual size of MSS being used */
BaseType_t FreeRTOS_mss( Socket_t xSocket );
/* for internal use only: return the connection status */
BaseType_t FreeRTOS_connstatus( Socket_t xSocket );
/* Returns the number of bytes that may be added to txStream */
BaseType_t FreeRTOS_maywrite( Socket_t xSocket );
/*
* Two helper functions, mostly for testing
* rx_size returns the number of bytes available in the Rx buffer
* tx_space returns the free space in the Tx buffer
*/
BaseType_t FreeRTOS_rx_size( Socket_t xSocket );
BaseType_t FreeRTOS_tx_space( Socket_t xSocket );
BaseType_t FreeRTOS_tx_size( Socket_t xSocket );
/* Returns the number of outstanding bytes in txStream. */
/* The function FreeRTOS_outstanding() was already implemented
FreeRTOS_tx_size(). */
#define FreeRTOS_outstanding( xSocket ) FreeRTOS_tx_size( xSocket )
/* Returns the number of bytes in the socket's rxStream. */
/* The function FreeRTOS_recvcount() was already implemented
FreeRTOS_rx_size(). */
#define FreeRTOS_recvcount( xSocket ) FreeRTOS_rx_size( xSocket )
/*
* For advanced applications only:
* Get a direct pointer to the circular transmit buffer.
* '*pxLength' will contain the number of bytes that may be written.
*/
uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength );
#endif /* ipconfigUSE_TCP */
/*
* Connect / disconnect handler for a TCP socket
* For example:
* static void vMyConnectHandler (Socket_t xSocket, BaseType_t ulConnected)
* {
* }
* F_TCP_UDP_Handler_t xHnd = { vMyConnectHandler };
* FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_CONN_HANDLER, ( void * ) &xHnd, sizeof( xHnd ) );
*/
typedef void (* FOnConnected_t )( Socket_t /* xSocket */, BaseType_t /* ulConnected */ );
/*
* Reception handler for a TCP socket
* A user-proved function will be called on reception of a message
* If the handler returns a positive number, the messages will not be stored
* For example:
* static BaseType_t xOnTCPReceive( Socket_t xSocket, void * pData, size_t xLength )
* {
* // handle the message
* return 1;
* }
* F_TCP_UDP_Handler_t xHand = { xOnTCPReceive };
* FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_RECV_HANDLER, ( void * ) &xHand, sizeof( xHand ) );
*/
typedef BaseType_t (* FOnTCPReceive_t )( Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */ );
typedef void (* FOnTCPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ );
/*
* Reception handler for a UDP socket
* A user-proved function will be called on reception of a message
* If the handler returns a positive number, the messages will not be stored
*/
typedef BaseType_t (* FOnUDPReceive_t ) (Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */,
const struct freertos_sockaddr * /* pxFrom */, const struct freertos_sockaddr * /* pxDest */ );
typedef void (* FOnUDPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ );
typedef union xTCP_UDP_HANDLER
{
FOnConnected_t pxOnTCPConnected; /* FREERTOS_SO_TCP_CONN_HANDLER */
FOnTCPReceive_t pxOnTCPReceive; /* FREERTOS_SO_TCP_RECV_HANDLER */
FOnTCPSent_t pxOnTCPSent; /* FREERTOS_SO_TCP_SENT_HANDLER */
FOnUDPReceive_t pxOnUDPReceive; /* FREERTOS_SO_UDP_RECV_HANDLER */
FOnUDPSent_t pxOnUDPSent; /* FREERTOS_SO_UDP_SENT_HANDLER */
} F_TCP_UDP_Handler_t;
BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength );
BaseType_t FreeRTOS_closesocket( Socket_t xSocket );
uint32_t FreeRTOS_gethostbyname( const char *pcHostName );
uint32_t FreeRTOS_inet_addr( const char * pcIPAddress );
/*
* For the web server: borrow the circular Rx buffer for inspection
* HTML driver wants to see if a sequence of 13/10/13/10 is available
*/
const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket );
void FreeRTOS_netstat( void );
#if ipconfigSUPPORT_SELECT_FUNCTION == 1
/* For FD_SET and FD_CLR, a combination of the following bits can be used: */
typedef enum eSELECT_EVENT {
eSELECT_READ = 0x0001,
eSELECT_WRITE = 0x0002,
eSELECT_EXCEPT = 0x0004,
eSELECT_INTR = 0x0008,
eSELECT_ALL = 0x000F,
/* Reserved for internal use: */
eSELECT_CALL_IP = 0x0010,
/* end */
} eSelectEvent_t;
SocketSet_t FreeRTOS_CreateSocketSet( void );
void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet );
void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xBitsToSet );
void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xBitsToClear );
EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet );
BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks );
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FREERTOS_SOCKETS_H */

View File

@ -0,0 +1,256 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
/*
* FreeRTOS_Stream_Buffer.h
*
* A cicular character buffer
* An implementation of a circular buffer without a length field
* If LENGTH defines the size of the buffer, a maximum of (LENGT-1) bytes can be stored
* In order to add or read data from the buffer, memcpy() will be called at most 2 times
*/
#ifndef FREERTOS_STREAM_BUFFER_H
#define FREERTOS_STREAM_BUFFER_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct xSTREAM_BUFFER {
volatile size_t uxTail; /* next item to read */
volatile size_t uxMid; /* iterator within the valid items */
volatile size_t uxHead; /* next position store a new item */
volatile size_t uxFront; /* iterator within the free space */
size_t LENGTH; /* const value: number of reserved elements */
uint8_t ucArray[ sizeof( size_t ) ];
} StreamBuffer_t;
static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer );
static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer )
{
/* Make the circular buffer empty */
pxBuffer->uxHead = 0u;
pxBuffer->uxTail = 0u;
pxBuffer->uxFront = 0u;
pxBuffer->uxMid = 0u;
}
/*-----------------------------------------------------------*/
static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );
static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )
{
/* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */
size_t uxCount;
uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1u;
if( uxCount >= pxBuffer->LENGTH )
{
uxCount -= pxBuffer->LENGTH;
}
return uxCount;
}
/*-----------------------------------------------------------*/
static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );
static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )
{
/* Returns the distance between uxLower and uxUpper */
size_t uxCount;
uxCount = pxBuffer->LENGTH + uxUpper - uxLower;
if ( uxCount >= pxBuffer->LENGTH )
{
uxCount -= pxBuffer->LENGTH;
}
return uxCount;
}
/*-----------------------------------------------------------*/
static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer );
static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer )
{
/* Returns the number of items which can still be added to uxHead
before hitting on uxTail */
size_t uxHead = pxBuffer->uxHead;
size_t uxTail = pxBuffer->uxTail;
return uxStreamBufferSpace( pxBuffer, uxHead, uxTail );
}
/*-----------------------------------------------------------*/
static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer );
static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer )
{
/* Distance between uxFront and uxTail
or the number of items which can still be added to uxFront,
before hitting on uxTail */
size_t uxFront = pxBuffer->uxFront;
size_t uxTail = pxBuffer->uxTail;
return uxStreamBufferSpace( pxBuffer, uxFront, uxTail );
}
/*-----------------------------------------------------------*/
static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer );
static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer )
{
/* Returns the number of items which can be read from uxTail
before reaching uxHead */
size_t uxHead = pxBuffer->uxHead;
size_t uxTail = pxBuffer->uxTail;
return uxStreamBufferDistance( pxBuffer, uxTail, uxHead );
}
/*-----------------------------------------------------------*/
static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer );
static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer )
{
/* Returns the distance between uxHead and uxMid */
size_t uxHead = pxBuffer->uxHead;
size_t uxMid = pxBuffer->uxMid;
return uxStreamBufferDistance( pxBuffer, uxMid, uxHead );
}
/*-----------------------------------------------------------*/
static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount );
static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount )
{
/* Increment uxMid, but no further than uxHead */
size_t uxSize = uxStreamBufferMidSpace( pxBuffer );
if( uxCount > uxSize )
{
uxCount = uxSize;
}
pxBuffer->uxMid += uxCount;
if( pxBuffer->uxMid >= pxBuffer->LENGTH )
{
pxBuffer->uxMid -= pxBuffer->LENGTH;
}
}
/*-----------------------------------------------------------*/
static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer );
static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer )
{
BaseType_t xReturn;
/* True if no item is available */
if( pxBuffer->uxHead == pxBuffer->uxTail )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer );
static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer )
{
/* True if the available space equals zero. */
return ( BaseType_t ) ( uxStreamBufferGetSpace( pxBuffer ) == 0u );
}
/*-----------------------------------------------------------*/
static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight );
static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight )
{
BaseType_t xReturn;
size_t uxTail = pxBuffer->uxTail;
/* Returns true if ( uxLeft < uxRight ) */
if( ( uxLeft < uxTail ) ^ ( uxRight < uxTail ) )
{
if( uxRight < uxTail )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
}
else
{
if( uxLeft <= uxRight )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData );
static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData )
{
size_t uxNextTail = pxBuffer->uxTail;
size_t uxSize = uxStreamBufferGetSize( pxBuffer );
*ppucData = pxBuffer->ucArray + uxNextTail;
return FreeRTOS_min_uint32( uxSize, pxBuffer->LENGTH - uxNextTail );
}
/*
* Add bytes to a stream buffer.
*
* pxBuffer - The buffer to which the bytes will be added.
* uxOffset - If uxOffset > 0, data will be written at an offset from uxHead
* while uxHead will not be moved yet.
* pucData - A pointer to the data to be added.
* uxCount - The number of bytes to add.
*/
size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount );
/*
* Read bytes from a stream buffer.
*
* pxBuffer - The buffer from which the bytes will be read.
* uxOffset - Can be used to read data located at a certain offset from 'uxTail'.
* pucData - A pointer to the buffer into which data will be read.
* uxMaxCount - The number of bytes to read.
* xPeek - If set to pdTRUE the data will remain in the buffer.
*/
size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* !defined( FREERTOS_STREAM_BUFFER_H ) */

View File

@ -0,0 +1,80 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef FREERTOS_TCP_IP_H
#define FREERTOS_TCP_IP_H
#ifdef __cplusplus
extern "C" {
#endif
BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
typedef enum eTCP_STATE {
/* Comments about the TCP states are borrowed from the very useful
* Wiki page:
* http://en.wikipedia.org/wiki/Transmission_Control_Protocol */
eCLOSED = 0u, /* 0 (server + client) no connection state at all. */
eTCP_LISTEN, /* 1 (server) waiting for a connection request
from any remote TCP and port. */
eCONNECT_SYN, /* 2 (client) internal state: socket wants to send
a connect */
eSYN_FIRST, /* 3 (server) Just created, must ACK the SYN request. */
eSYN_RECEIVED, /* 4 (server) waiting for a confirming connection request
acknowledgement after having both received and sent a connection request. */
eESTABLISHED, /* 5 (server + client) an open connection, data received can be
delivered to the user. The normal state for the data transfer phase of the connection. */
eFIN_WAIT_1, /* 6 (server + client) waiting for a connection termination request from the remote TCP,
or an acknowledgement of the connection termination request previously sent. */
eFIN_WAIT_2, /* 7 (server + client) waiting for a connection termination request from the remote TCP. */
eCLOSE_WAIT, /* 8 (server + client) waiting for a connection termination request from the local user. */
eCLOSING, /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
eLAST_ACK, /* 9 (server + client) waiting for an acknowledgement of the connection termination request
previously sent to the remote TCP
(which includes an acknowledgement of its connection termination request). */
eTIME_WAIT, /* 10 (either server or client) waiting for enough time to pass to be sure the remote TCP received the
acknowledgement of its connection termination request. [According to RFC 793 a connection can
stay in TIME-WAIT for a maximum of four minutes known as a MSL (maximum segment lifetime).] */
} eIPTCPState_t;
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FREERTOS_TCP_IP_H */

View File

@ -0,0 +1,210 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
/*
* FreeRTOS_TCP_WIN.c
* Module which handles the TCP windowing schemes for FreeRTOS-PLUS-TCP
*/
#ifndef FREERTOS_TCP_WIN_H
#define FREERTOS_TCP_WIN_H
#ifdef __cplusplus
extern "C" {
#endif
extern BaseType_t xTCPWindowLoggingLevel;
typedef struct xTCPTimer
{
uint32_t ulBorn;
} TCPTimer_t;
typedef struct xTCP_SEGMENT
{
uint32_t ulSequenceNumber; /* The sequence number of the first byte in this packet */
int32_t lMaxLength; /* Maximum space, number of bytes which can be stored in this segment */
int32_t lDataLength; /* Actual number of bytes */
int32_t lStreamPos; /* reference to the [t|r]xStream of the socket */
TCPTimer_t xTransmitTimer; /* saves a timestamp at the moment this segment gets transmitted (TX only) */
union
{
struct
{
uint32_t
ucTransmitCount : 8,/* Number of times the segment has been transmitted, used to calculate the RTT */
ucDupAckCount : 8, /* Counts the number of times that a higher segment was ACK'd. After 3 times a Fast Retransmission takes place */
bOutstanding : 1, /* It the peer's turn, we're just waiting for an ACK */
bAcked : 1, /* This segment has been acknowledged */
bIsForRx : 1; /* pdTRUE if segment is used for reception */
} bits;
uint32_t ulFlags;
} u;
#if( ipconfigUSE_TCP_WIN != 0 )
struct xLIST_ITEM xQueueItem; /* TX only: segments can be linked in one of three queues: xPriorityQueue, xTxQueue, and xWaitQueue */
struct xLIST_ITEM xListItem; /* With this item the segment can be connected to a list, depending on who is owning it */
#endif
} TCPSegment_t;
typedef struct xTCP_WINSIZE
{
uint32_t ulRxWindowLength;
uint32_t ulTxWindowLength;
} TCPWinSize_t;
/*
* If TCP time-stamps are being used, they will occupy 12 bytes in
* each packet, and thus the message space will become smaller
*/
/* Keep this as a multiple of 4 */
#if( ipconfigUSE_TCP_WIN == 1 )
#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;
TCPWinSize_t xSize;
struct
{
uint32_t ulFirstSequenceNumber; /* Logging & debug: the first segment received/sent in this connection
* for Tx: initial send sequence number (ISS)
* for Rx: initial receive sequence number (IRS) */
uint32_t ulCurrentSequenceNumber;/* Tx/Rx: the oldest sequence number not yet confirmed, also SND.UNA / RCV.NXT
* In other words: the sequence number of the left side of the sliding window */
uint32_t ulFINSequenceNumber; /* The sequence number which carried the FIN flag */
uint32_t ulHighestSequenceNumber;/* Sequence number of the right-most byte + 1 */
} rx, tx;
uint32_t ulOurSequenceNumber; /* The SEQ number we're sending out */
uint32_t ulUserDataLength; /* Number of bytes in Rx buffer which may be passed to the user, after having received a 'missing packet' */
uint32_t ulNextTxSequenceNumber; /* The sequence number given to the next byte to be added for transmission */
int32_t lSRTT; /* Smoothed Round Trip Time, it may increment quickly and it decrements slower */
uint8_t ucOptionLength; /* Number of valid bytes in ulOptionsData[] */
#if( ipconfigUSE_TCP_WIN == 1 )
List_t xPriorityQueue; /* Priority queue: segments which must be sent immediately */
List_t xTxQueue; /* Transmit queue: segments queued for transmission */
List_t xWaitQueue; /* Waiting queue: outstanding segments */
TCPSegment_t *pxHeadSegment; /* points to a segment which has not been transmitted and it's size is still growing (user data being added) */
uint32_t ulOptionsData[ipSIZE_TCP_OPTIONS/sizeof(uint32_t)]; /* Contains the options we send out */
List_t xTxSegments; /* A linked list of all transmission segments, sorted on sequence number */
List_t xRxSegments; /* A linked list of reception segments, order depends on sequence of arrival */
#else
/* For tiny TCP, there is only 1 outstanding TX segment */
TCPSegment_t xTxSegment; /* Priority queue */
#endif
uint16_t usOurPortNumber; /* Mostly for debugging/logging: our TCP port number */
uint16_t usPeerPortNumber; /* debugging/logging: the peer's TCP port number */
uint16_t usMSS; /* Current accepted MSS */
uint16_t usMSSInit; /* MSS as configured by the socket owner */
} TCPWindow_t;
/*=============================================================================
*
* Creation and destruction
*
*=============================================================================*/
/* Create and initialize a window */
void vTCPWindowCreate( TCPWindow_t *pxWindow, uint32_t ulRxWindowLength,
uint32_t ulTxWindowLength, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS );
/* Destroy a window (always returns NULL)
* It will free some resources: a collection of segments */
void vTCPWindowDestroy( TCPWindow_t *pxWindow );
/* Initialize a window */
void vTCPWindowInit( TCPWindow_t *pxWindow, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS );
/*=============================================================================
*
* Rx functions
*
*=============================================================================*/
/* if true may be passed directly to user (segment expected and window is empty)
* But pxWindow->ackno should always be used to set "BUF->ackno" */
int32_t lTCPWindowRxCheck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength, uint32_t ulSpace );
/* When lTCPWindowRxCheck returned false, please call store for this unexpected data */
BaseType_t xTCPWindowRxStore( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength );
/* This function will be called as soon as a FIN is received. It will return true
* if there are no 'open' reception segments */
BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow );
/* _HT_ Temporary function for testing/debugging
* Not used at this moment */
void vTCPWinShowSegments( TCPWindow_t *pxWindow, BaseType_t bForRx );
/*=============================================================================
*
* Tx functions
*
*=============================================================================*/
/* Adds data to the Tx-window */
int32_t lTCPWindowTxAdd( TCPWindow_t *pxWindow, uint32_t ulLength, int32_t lPosition, int32_t lMax );
/* Check data to be sent and calculate the time period we may sleep */
BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay );
/* See if anything is left to be sent
* Function will be called when a FIN has been received. Only when the TX window is clean,
* it will return pdTRUE */
BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow );
/* Fetches data to be sent.
* apPos will point to a location with the circular data buffer: txStream */
uint32_t ulTCPWindowTxGet( TCPWindow_t *pxWindow, uint32_t ulWindowSize, int32_t *plPosition );
/* Receive a normal ACK */
uint32_t ulTCPWindowTxAck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber );
/* Receive a SACK option */
uint32_t ulTCPWindowTxSack( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_TCP_WIN_H */

View File

@ -0,0 +1,56 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef FREERTOS_UDP_IP_H
#define FREERTOS_UDP_IP_H
#ifdef __cplusplus
extern "C" {
#endif
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "FreeRTOSIPConfigDefaults.h"
#include "IPTraceMacroDefaults.h"
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FREERTOS_UDP_IP_H */

View File

@ -0,0 +1,90 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef FREERTOS_ERRNO_TCP
#define FREERTOS_ERRNO_TCP
/* The following definitions will be included in the core FreeRTOS code in
future versions of FreeRTOS - hence the 'pd' (ProjDefs) prefix - at which time
this file will be removed. */
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
itself. */
/* For future compatibility (see comment above), check the definitions have not
already been made. */
#ifndef pdFREERTOS_ERRNO_NONE
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
itself. */
#define pdFREERTOS_LITTLE_ENDIAN 0
#define pdFREERTOS_BIG_ENDIAN 1
#endif /* pdFREERTOS_ERRNO_NONE */
#endif /* FREERTOS_ERRNO_TCP */

View File

@ -0,0 +1,193 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
/* This file provides default (empty) implementations for any IP trace macros
that are not defined by the user. See
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Trace.html */
#ifndef UDP_TRACE_MACRO_DEFAULTS_H
#define UDP_TRACE_MACRO_DEFAULTS_H
#ifndef iptraceNETWORK_DOWN
#define iptraceNETWORK_DOWN()
#endif
#ifndef iptraceNETWORK_BUFFER_RELEASED
#define iptraceNETWORK_BUFFER_RELEASED( pxBufferAddress )
#endif
#ifndef iptraceNETWORK_BUFFER_OBTAINED
#define iptraceNETWORK_BUFFER_OBTAINED( pxBufferAddress )
#endif
#ifndef iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR
#define iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxBufferAddress )
#endif
#ifndef iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER
#define iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER()
#endif
#ifndef iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR
#define iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR()
#endif
#ifndef iptraceCREATING_ARP_REQUEST
#define iptraceCREATING_ARP_REQUEST( ulIPAddress )
#endif
#ifndef iptraceARP_TABLE_ENTRY_WILL_EXPIRE
#define iptraceARP_TABLE_ENTRY_WILL_EXPIRE( ulIPAddress )
#endif
#ifndef iptraceARP_TABLE_ENTRY_EXPIRED
#define iptraceARP_TABLE_ENTRY_EXPIRED( ulIPAddress )
#endif
#ifndef iptraceARP_TABLE_ENTRY_CREATED
#define iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, ucMACAddress )
#endif
#ifndef iptraceSENDING_UDP_PACKET
#define iptraceSENDING_UDP_PACKET( ulIPAddress )
#endif
#ifndef iptracePACKET_DROPPED_TO_GENERATE_ARP
#define iptracePACKET_DROPPED_TO_GENERATE_ARP( ulIPAddress )
#endif
#ifndef iptraceICMP_PACKET_RECEIVED
#define iptraceICMP_PACKET_RECEIVED()
#endif
#ifndef iptraceSENDING_PING_REPLY
#define iptraceSENDING_PING_REPLY( ulIPAddress )
#endif
#ifndef traceARP_PACKET_RECEIVED
#define traceARP_PACKET_RECEIVED()
#endif
#ifndef iptracePROCESSING_RECEIVED_ARP_REPLY
#define iptracePROCESSING_RECEIVED_ARP_REPLY( ulIPAddress )
#endif
#ifndef iptraceSENDING_ARP_REPLY
#define iptraceSENDING_ARP_REPLY( ulIPAddress )
#endif
#ifndef iptraceFAILED_TO_CREATE_SOCKET
#define iptraceFAILED_TO_CREATE_SOCKET()
#endif
#ifndef iptraceFAILED_TO_CREATE_EVENT_GROUP
#define iptraceFAILED_TO_CREATE_EVENT_GROUP()
#endif
#ifndef iptraceRECVFROM_DISCARDING_BYTES
#define iptraceRECVFROM_DISCARDING_BYTES( xNumberOfBytesDiscarded )
#endif
#ifndef iptraceETHERNET_RX_EVENT_LOST
#define iptraceETHERNET_RX_EVENT_LOST()
#endif
#ifndef iptraceSTACK_TX_EVENT_LOST
#define iptraceSTACK_TX_EVENT_LOST( xEvent )
#endif
#ifndef iptraceNETWORK_EVENT_RECEIVED
#define iptraceNETWORK_EVENT_RECEIVED( eEvent )
#endif
#ifndef iptraceBIND_FAILED
#define iptraceBIND_FAILED( xSocket, usPort )
#endif
#ifndef iptraceDHCP_REQUESTS_FAILED_USING_DEFAULT_IP_ADDRESS
#define iptraceDHCP_REQUESTS_FAILED_USING_DEFAULT_IP_ADDRESS( ulIPAddress )
#endif
#ifndef iptraceSENDING_DHCP_DISCOVER
#define iptraceSENDING_DHCP_DISCOVER()
#endif
#ifndef iptraceSENDING_DHCP_REQUEST
#define iptraceSENDING_DHCP_REQUEST()
#endif
#ifndef iptraceDHCP_SUCCEDEED
#define iptraceDHCP_SUCCEDEED( address )
#endif
#ifndef iptraceNETWORK_INTERFACE_TRANSMIT
#define iptraceNETWORK_INTERFACE_TRANSMIT()
#endif
#ifndef iptraceNETWORK_INTERFACE_RECEIVE
#define iptraceNETWORK_INTERFACE_RECEIVE()
#endif
#ifndef iptraceSENDING_DNS_REQUEST
#define iptraceSENDING_DNS_REQUEST()
#endif
#ifndef iptraceWAITING_FOR_TX_DMA_DESCRIPTOR
#define iptraceWAITING_FOR_TX_DMA_DESCRIPTOR()
#endif
#ifndef ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS
#define ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS 0
#endif
#ifndef iptraceFAILED_TO_NOTIFY_SELECT_GROUP
#define iptraceFAILED_TO_NOTIFY_SELECT_GROUP( xSocket )
#endif
#ifndef pvPortMallocSocket
#define pvPortMallocSocket(xSize) pvPortMalloc( ( xSize ) )
#endif
#ifndef iptraceRECVFROM_TIMEOUT
#define iptraceRECVFROM_TIMEOUT()
#endif
#ifndef iptraceRECVFROM_INTERRUPTED
#define iptraceRECVFROM_INTERRUPTED()
#endif
#ifndef iptraceNO_BUFFER_FOR_SENDTO
#define iptraceNO_BUFFER_FOR_SENDTO()
#endif
#ifndef iptraceSENDTO_SOCKET_NOT_BOUND
#define iptraceSENDTO_SOCKET_NOT_BOUND()
#endif
#ifndef iptraceSENDTO_DATA_TOO_LONG
#define iptraceSENDTO_DATA_TOO_LONG()
#endif
#endif /* UDP_TRACE_MACRO_DEFAULTS_H */

View File

@ -0,0 +1,70 @@
/*
* FreeRTOS+TCP V2.0.7
* 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
*/
#ifndef NETWORK_BUFFER_MANAGEMENT_H
#define NETWORK_BUFFER_MANAGEMENT_H
#ifdef __cplusplus
extern "C" {
#endif
/* NOTE PUBLIC API FUNCTIONS. */
BaseType_t xNetworkBuffersInitialise( void );
NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks );
NetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes );
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer );
BaseType_t vNetworkBufferReleaseFromISR( NetworkBufferDescriptor_t * const pxNetworkBuffer );
uint8_t *pucGetNetworkBuffer( size_t *pxRequestedSizeBytes );
void vReleaseNetworkBuffer( uint8_t *pucEthernetBuffer );
/* Get the current number of free network buffers. */
UBaseType_t uxGetNumberOfFreeNetworkBuffers( void );
/* Get the lowest number of free network buffers. */
UBaseType_t uxGetMinimumFreeNetworkBuffers( void );
/* Copy a network buffer into a bigger buffer. */
NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer,
BaseType_t xNewLength);
/* Increase the size of a Network Buffer.
In case BufferAllocation_2.c is used, the new space must be allocated. */
NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer,
size_t xNewSizeBytes );
#if ipconfigTCP_IP_SANITY
/*
* Check if an address is a valid pointer to a network descriptor
* by looking it up in the array of network descriptors
*/
UBaseType_t bIsValidNetworkDescriptor (const NetworkBufferDescriptor_t * pxDesc);
BaseType_t prvIsFreeBuffer( const NetworkBufferDescriptor_t *pxDescr );
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* NETWORK_BUFFER_MANAGEMENT_H */

Some files were not shown because too many files have changed in this diff Show More