[修改] 增加freeRTOS

1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
2023-05-06 16:43:01 +00:00
commit a345df017b
20944 changed files with 11094377 additions and 0 deletions

View File

@ -0,0 +1,100 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* 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
*/
/*
* dump_packets.c
* Used in the PC/Win project to dump Ethernet packets, along with some description.
*/
#ifndef DUMP_PACKETS_H
#define DUMP_PACKETS_H
#ifndef dumpMAX_DUMP_ENTRIES
#define dumpMAX_DUMP_ENTRIES 16
#endif
#define flag_ICMP4 0x00000001UL
#define flag_ICMP6 0x00000002UL
#define flag_UDP 0x00000004UL
#define flag_TCP 0x00000008UL
#define flag_DNS 0x00000010UL
#define flag_REPLY 0x00000020UL
#define flag_REQUEST 0x00000040UL
#define flag_SYN 0x00000080UL
#define flag_FIN 0x00000100UL
#define flag_RST 0x00000200UL
#define flag_ACK 0x00000400UL
#define flag_IN 0x00000800UL
#define flag_OUT 0x00001000UL
#define flag_FRAME_ARP 0x00002000UL
#define flag_ARP 0x00004000UL
#define flag_UNKNOWN 0x00008000UL
#define flag_FRAME_4 0x00010000UL
#define flag_FRAME_6 0x00020000UL
#define flag_Unknown_FRAME 0x00040000UL
/**
* Structure to hold information about one dump entry.
*/
typedef struct xDumpEntry
{
uint32_t ulMask; /**< The mask of the entry */
size_t uxMax; /**< The max value of the entry */
size_t uxCount; /**< The count of the entry */
} DumpEntry_t;
/**
* Structure to hold information of all the entries in this data dump.
*/
typedef struct xDumpEntries
{
size_t uxEntryCount; /**< The number of entries*/
DumpEntry_t xEntries[ dumpMAX_DUMP_ENTRIES ]; /**< Array of struct for all the entries */
} DumpEntries_t;
/*
*
*/
#if ( ipconfigUSE_DUMP_PACKETS != 0 )
extern void dump_packet_init( const char * pcFileName,
DumpEntries_t * pxEntries );
#define iptraceDUMP_INIT( pcFileName, pxEntries ) \
dump_packet_init( pcFileName, pxEntries )
extern void dump_packet( const uint8_t * pucBuffer,
size_t uxLength,
BaseType_t xIncoming );
#define iptraceDUMP_PACKET( pucBuffer, uxLength, xIncoming ) \
dump_packet( pucBuffer, uxLength, xIncoming )
#endif /* if ( ipconfigUSE_DUMP_PACKETS != 0 ) */
#endif /* ifndef DUMP_PACKETS_H */

View File

@ -0,0 +1,80 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* 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
*/
/*
* tcp_mem_stats.h
*/
#ifndef TCP_MEM_STATS_H
#define TCP_MEM_STATS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum xTCP_MEMORY
{
tcpSOCKET_TCP,
tcpSOCKET_UDP,
tcpSOCKET_SET,
tcpSEMAPHORE,
tcpRX_STREAM_BUFFER,
tcpTX_STREAM_BUFFER,
tcpNETWORK_BUFFER,
} TCP_MEMORY_t;
#if ( ipconfigUSE_TCP_MEM_STATS != 0 )
void vTCPMemStatCreate( TCP_MEMORY_t xMemType,
void * pxObject,
size_t uxSize );
void vTCPMemStatDelete( void * pxObject );
void vTCPMemStatClose( void );
#define iptraceMEM_STATS_CREATE( xMemType, pxObject, uxSize ) \
vTCPMemStatCreate( xMemType, pxObject, uxSize )
#define iptraceMEM_STATS_DELETE( pxObject ) \
vTCPMemStatDelete( pxObject )
#define iptraceMEM_STATS_CLOSE() \
vTCPMemStatClose()
#else /* if ( ipconfigUSE_TCP_MEM_STATS != 0 ) */
/* The header file 'IPTraceMacroDefaults.h' will define the default empty macro's. */
#endif /* ipconfigUSE_TCP_MEM_STATS != 0 */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* TCP_MEM_STATS_H */

View File

@ -0,0 +1,120 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* 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
*/
/*
* TCP_NETSTAT.c
* Some function to get a list of sockets and active port numbers.
*/
#ifndef TCP_NETSTAT_H
#define TCP_NETSTAT_H
#ifndef nstatMAX_UDP_PORTS
#define nstatMAX_UDP_PORTS 12U
#endif
#ifndef nstatMAX_TCP_PORTS
#define nstatMAX_TCP_PORTS 12U
#endif
#ifndef nstatMAX_UDP_SOCKETS
#define nstatMAX_UDP_SOCKETS 12U
#endif
#ifndef nstatMAX_TCP_SOCKETS
#define nstatMAX_TCP_SOCKETS 12U
#endif
typedef struct xIOCounters
{
size_t uxByteCount;
size_t uxPacketCount;
} IOCounters_t;
extern IOCounters_t xInputCounters, xOutputCounters;
typedef struct
{
uint16_t usUDPPortList[ nstatMAX_UDP_PORTS ];
size_t uxCount;
} UDPPortList_t;
typedef struct
{
uint16_t usTCPPortList[ nstatMAX_TCP_PORTS ];
size_t uxCount;
} TCPPortList_t;
typedef struct
{
uint16_t usLocalPort;
uint16_t usRemotePort;
uint32_t ulRemoteIP;
} TCPEntry_t;
typedef struct
{
TCPEntry_t xTCPList[ nstatMAX_TCP_SOCKETS ];
size_t uxCount;
} TCPSocketList_t;
typedef struct
{
uint16_t usLocalPort;
} UDPEntry_t;
typedef struct
{
UDPEntry_t xUDPList[ nstatMAX_UDP_SOCKETS ];
size_t uxCount;
} UDPSocketList_t;
typedef struct
{
UDPPortList_t xUDPPortList;
TCPPortList_t xTCPPortList;
TCPSocketList_t xTCPSocketList;
UDPSocketList_t xUDPSocketList;
IOCounters_t xInput;
IOCounters_t xOutput;
} MetricsType_t;
extern BaseType_t vGetMetrics( MetricsType_t * pxMetrics );
extern void vShowMetrics( const MetricsType_t * pxMetrics );
#define iptraceNETWORK_INTERFACE_INPUT( uxDataLength, pucEthernetBuffer ) \
xInputCounters.uxByteCount += uxDataLength; \
xInputCounters.uxPacketCount++;
#define iptraceNETWORK_INTERFACE_OUTPUT( uxDataLength, pucEthernetBuffer ) \
xOutputCounters.uxByteCount += uxDataLength; \
xOutputCounters.uxPacketCount++;
#endif /* TCP_NETSTAT_H */

View File

@ -0,0 +1,706 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* 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
*/
/*
* tcp_dump_packets.c
* Used in the PC/Win project to dump Ethernet packets, along with some description.
* See tools/tcp_dump_packets.md for further description.
*/
/* Standard includes. */
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <ctype.h>
/* FreeRTOS includes. */
#include <FreeRTOS.h>
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_Stream_Buffer.h"
#include "FreeRTOS_IP_Private.h"
#if ( ipconfigUSE_DUMP_PACKETS != 0 )
#include "tcp_dump_packets.h"
/* The priority of the windows thread. */
#define dumpPROCESS_THREAD_PRIORITY THREAD_PRIORITY_NORMAL
/* There is a stream buffer between the FreeRTOS tasks sending network packets,
* and the Windows thread that writes these packets to disk. The macro 'dumpITEM_COUNT'
* determines the number of full-size packets that can be stored in this stream buffer. */
#ifndef dumpITEM_COUNT
#define dumpITEM_COUNT 32
#endif
/* Packets are written in hex notation, no more than 16 bytes on a row. */
#ifndef dumpBYTES_PER_ROW
#define dumpBYTES_PER_ROW 16
#endif
/* The TCP port number reserved for a DNS server. */
#define dnsDNS_PORT 0x0035u
/* Some const values describing the 'flags' in a TCP packet. */
#define tcpTCP_FLAG_FIN 0x0001u /* No more data from sender */
#define tcpTCP_FLAG_SYN 0x0002u /* Synchronize sequence numbers */
#define tcpTCP_FLAG_RST 0x0004u /* Reset the connection */
#define tcpTCP_FLAG_PSH 0x0008u /* Push function: please push buffered data to the recv application */
#define tcpTCP_FLAG_ACK 0x0010u /* Acknowledgment field is significant */
/* A macro to add a type, both as a numeric value, as well as a string. */
#define ADD_TYPE( FLAGS ) \
vAddType( flag_ ## FLAGS, # FLAGS )
/*-----------------------------------------------------------*/
static char pcTypeString[ 255 ];
static uint32_t ulTypeMask;
/* The name of the C source file to be written. */
static char pcCodeFileName[ MAX_PATH ];
/* The name of the header file to be written. */
static char pcHeaderFileName[ MAX_PATH ];
/* A stream buffer between the FreeRTOS tasks and the Windows thread. */
static StreamBuffer_t * xPacketBuffer;
/* A process handle of the Windows thread. */
static HANDLE pvProcessHandle;
static UBaseType_t uxNextPacketNumber;
static BaseType_t xFirstPacket = 1;
/* Boolean 'xDumpingReady' becomes true once all desired packet have been collected.
* Further packets will be dropped (ignored). */
static volatile BaseType_t xDumpingReady = pdFALSE;
static DumpEntries_t * pxCurrentEntries;
static uint16_t usSourcePort;
static uint16_t usDestinationPort;
typedef struct xBufferheader
{
size_t uxLength;
UBaseType_t bIncoming : 1;
} Bufferheader_t;
static DumpEntries_t xExampleEntries =
{
.uxEntryCount = 4, /* No more than 'dumpMAX_DUMP_ENTRIES' elements. */
.xEntries =
{
{ .ulMask = flag_IN | flag_UDP, .uxMax = 2u },
{ .ulMask = flag_IN | flag_ARP, .uxMax = 2u },
{ .ulMask = flag_IN | flag_TCP, .uxMax = 5u },
{ .ulMask = flag_IN | flag_SYN, .uxMax = 1u },
}
};
const char pcHeaderCode[] =
"/*\n"
" * This file was created automatically by 'dump_packets.c'\n"
" */\n"
"\n"
"/* Standard includes. */\n"
"#include <stdio.h>\n"
"#include <stdint.h>\n"
"#include <stdarg.h>\n"
"#include <io.h>\n"
"#include <ctype.h>\n"
"\n"
"/* FreeRTOS includes. */\n"
"#include <FreeRTOS.h>\n"
"#include <task.h>\n\n"
"#include \"%s\"\n\n";
const char pcHeaderHeader[] =
"/*\n"
" * This file was created automatically by 'dump_packets.c'\n"
" */\n"
"\n"
"#ifndef PACKET_LIST_H\n\n"
"#define PACKET_LIST_H\n\n"
"typedef struct xDumpPacket\n"
"{\n"
" const uint8_t *pucData;\n"
" size_t uxLength;\n"
" uint32_t ulType;\n"
" uint16_t usSource;\n"
" uint16_t usDestination;\n"
"} DumpPacket_t;\n\n";
/*-----------------------------------------------------------*/
/* The Windows thread that actually writes the network packets to a C source and header file. */
static DWORD WINAPI prvWritePackets( LPVOID lpParameter );
static void vAddProtocolTags( uint8_t * pucEthernetBuffer,
BaseType_t xIPType );
static void vDetermineMessageType( uint8_t * pucBuffer,
BaseType_t xIncoming );
static void vActualDump( uint8_t * pucBuffer,
size_t uxLength,
BaseType_t xIncoming );
static void vAddType( uint32_t ulFlags,
const char * pcFlagName );
static void vWriteHeaderFile( void );
/*-----------------------------------------------------------*/
void dump_packet_init( const char * pcFileName,
DumpEntries_t * pxEntries )
{
size_t uxIndex;
snprintf( pcCodeFileName, sizeof pcCodeFileName, "%s.c", pcFileName );
snprintf( pcHeaderFileName, sizeof pcHeaderFileName, "%s.h", pcFileName );
if( pxEntries == NULL )
{
pxEntries = &( xExampleEntries );
}
configASSERT( pxEntries->uxEntryCount > 0 );
configASSERT( pxEntries->uxEntryCount <= dumpMAX_DUMP_ENTRIES );
for( uxIndex = 0; uxIndex < pxEntries->uxEntryCount; uxIndex++ )
{
pxEntries->xEntries[ uxIndex ].uxCount = 0;
}
pxCurrentEntries = pxEntries;
if( xPacketBuffer == NULL )
{
size_t uxLength, uxSize;
/* Enough space for e.g. 32 buffers and length words. */
uxLength = dumpITEM_COUNT * ( sizeof( void * ) + ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER );
uxSize = ( sizeof( *xPacketBuffer ) + uxLength ) - sizeof( xPacketBuffer->ucArray );
xPacketBuffer = ( StreamBuffer_t * ) pvPortMalloc( uxSize );
configASSERT( xPacketBuffer != NULL );
vStreamBufferClear( xPacketBuffer );
xPacketBuffer->LENGTH = uxLength;
}
if( pvProcessHandle == NULL )
{
pvProcessHandle = CreateThread( NULL, 0, prvWritePackets, NULL, CREATE_SUSPENDED, NULL );
if( pvProcessHandle != NULL )
{
SetThreadPriority( pvProcessHandle, dumpPROCESS_THREAD_PRIORITY );
SetThreadPriorityBoost( pvProcessHandle, TRUE );
SetThreadAffinityMask( pvProcessHandle, 0x0E );
ResumeThread( pvProcessHandle );
}
}
}
/*-----------------------------------------------------------*/
void dump_packet( const uint8_t * pucBuffer,
size_t uxLength,
BaseType_t xIncoming )
{
/* This function shall be called from a normal FreeRTOS task only. */
if( xPacketBuffer != NULL )
{
if( xDumpingReady == pdFALSE )
{
size_t uxSpace = uxStreamBufferGetSpace( xPacketBuffer );
size_t uxNeeded = uxLength + sizeof( size_t );
if( uxNeeded < uxSpace )
{
Bufferheader_t xheader;
xheader.uxLength = uxLength;
xheader.bIncoming = xIncoming;
uxStreamBufferAdd( xPacketBuffer, 0u, ( const uint8_t * ) &( xheader ), sizeof( xheader ) );
uxStreamBufferAdd( xPacketBuffer, 0u, pucBuffer, uxLength );
}
else
{
/* Drop this packet. */
}
}
else
{
/* The Windows thread 'prvWritePackets()' had received enough packets.
* The packet buffer may be freed. */
vPortFree( xPacketBuffer );
xPacketBuffer = NULL;
}
}
}
/*-----------------------------------------------------------*/
static DWORD WINAPI prvWritePackets( LPVOID lpParameter )
{
/* This is a Windows thread, not a FreeRTOS task. FreeRTOS API's may not be called. */
for( ; ; )
{
Sleep( 100 );
while( ( xPacketBuffer != NULL ) && ( xDumpingReady == pdFALSE ) )
{
Bufferheader_t xHeader;
size_t uxBytes = uxStreamBufferGetSize( xPacketBuffer );
if( uxBytes <= sizeof( xHeader ) )
{
break;
}
/* Peek the number of bytes available. */
uxStreamBufferGet( xPacketBuffer, 0u, ( uint8_t * ) &( xHeader ), sizeof( xHeader ), pdTRUE );
if( uxBytes >= sizeof( xHeader ) + xHeader.uxLength )
{
}
{
size_t xBytesRead;
uint8_t pcBuffer[ ipconfigNETWORK_MTU ];
size_t xActualCount;
uxStreamBufferGet( xPacketBuffer, 0u, NULL, sizeof( xHeader ), pdFALSE );
xActualCount = uxStreamBufferGet( xPacketBuffer, 0u, pcBuffer, xHeader.uxLength, pdFALSE );
vActualDump( pcBuffer, xActualCount, xHeader.bIncoming );
}
}
}
}
/*-----------------------------------------------------------*/
static int _fprintf( FILE * pxHandle,
const char * pcFormat,
... )
{
char pcString[ 255 ];
BaseType_t iCount;
va_list args;
va_start( args, pcFormat );
iCount = vsnprintf( pcString, sizeof pcString, pcFormat, args );
va_end( args );
fwrite( pcString, 1u, iCount, pxHandle );
return iCount;
}
/*-----------------------------------------------------------*/
static void vWriteHeaderFile( void )
{
FILE * outfile;
outfile = fopen( pcHeaderFileName, "w" );
if( outfile != NULL )
{
fwrite( pcHeaderHeader, 1u, sizeof( pcHeaderHeader ) - 1u, outfile );
_fprintf( outfile, "#define dumpPACKET_COUNT %lu\n\n",
( uxNextPacketNumber < 1u ) ? 1u : uxNextPacketNumber );
_fprintf( outfile, "extern DumpPacket_t *xPacketList[ dumpPACKET_COUNT ];\n\n" );
_fprintf( outfile, "#endif PACKET_LIST_H\n" );
fclose( outfile );
}
}
/*-----------------------------------------------------------*/
static void vAddType( uint32_t ulFlags,
const char * pcFlagName )
{
size_t uxLength = strlen( pcTypeString );
char pcString[ 64 ];
BaseType_t iCount;
ulTypeMask |= ulFlags;
if( uxLength == 0 )
{
snprintf( pcTypeString, sizeof pcTypeString, "%s", pcFlagName );
}
else
{
snprintf( pcTypeString + uxLength, sizeof pcTypeString - 1, " | %s", pcFlagName );
}
}
/*-----------------------------------------------------------*/
static void vAddProtocolTags( uint8_t * pucEthernetBuffer,
BaseType_t xIPType )
{
ProtocolHeaders_t * pxProtocolHeaders;
#if ( ipconfigUSE_IPv6 != 0 )
const IPHeader_IPv6_t * pxIPHeader_IPv6;
#endif
UBaseType_t uxHeaderLength;
uint8_t ucProtocol;
IPPacket_t * pxIPPacket;
IPHeader_t * pxIPHeader;
pxIPPacket = ( IPPacket_t * ) pucEthernetBuffer;
pxIPHeader = &( pxIPPacket->xIPHeader );
#if ( ipconfigUSE_IPv6 != 0 )
pxIPHeader_IPv6 = ( const IPHeader_IPv6_t * ) &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] );
if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE )
{
uxHeaderLength = ipSIZE_OF_IPv6_HEADER;
ucProtocol = pxIPHeader_IPv6->ucNextHeader;
pxProtocolHeaders = ( ProtocolHeaders_t * ) &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER ] );
}
else
#endif
{
size_t uxLength = ( size_t ) pxIPHeader->ucVersionHeaderLength;
/* Check if the IP headers are acceptable and if it has our destination.
* The lowest four bits of 'ucVersionHeaderLength' indicate the IP-header
* length in multiples of 4. */
uxHeaderLength = ( size_t ) ( ( uxLength & 0x0Fu ) << 2 );
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
pxProtocolHeaders = ( ProtocolHeaders_t * ) &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxHeaderLength ] );
}
switch( ucProtocol )
{
case ipPROTOCOL_ICMP:
ADD_TYPE( ICMP4 );
break;
#if ( ipconfigUSE_IPv6 != 0 )
case ipPROTOCOL_ICMP_IPv6:
ADD_TYPE( ICMP6 );
break;
#endif
case ipPROTOCOL_UDP:
ADD_TYPE( UDP );
usSourcePort = pxProtocolHeaders->xUDPHeader.usSourcePort;
usDestinationPort = pxProtocolHeaders->xUDPHeader.usDestinationPort;
if( usSourcePort == FreeRTOS_htons( dnsDNS_PORT ) )
{
ADD_TYPE( DNS );
ADD_TYPE( REPLY );
}
else if( usDestinationPort == FreeRTOS_htons( dnsDNS_PORT ) )
{
ADD_TYPE( DNS );
ADD_TYPE( REQUEST );
}
break;
#if ipconfigUSE_TCP == 1
case ipPROTOCOL_TCP:
ADD_TYPE( TCP );
usSourcePort = pxProtocolHeaders->xTCPHeader.usSourcePort;
usDestinationPort = pxProtocolHeaders->xTCPHeader.usDestinationPort;
if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_SYN ) != 0u )
{
ADD_TYPE( SYN );
}
if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_FIN ) != 0u )
{
ADD_TYPE( FIN );
}
if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_RST ) != 0u )
{
ADD_TYPE( RST );
}
if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_ACK ) != 0u )
{
ADD_TYPE( ACK );
}
break;
#endif /* if ipconfigUSE_TCP == 1 */
}
}
/*-----------------------------------------------------------*/
static void vDetermineMessageType( uint8_t * pucBuffer,
BaseType_t xIncoming )
{
EthernetHeader_t * pxEthernetHeader;
if( xIncoming != 0 )
{
ADD_TYPE( IN );
}
else
{
ADD_TYPE( OUT );
}
pxEthernetHeader = ( EthernetHeader_t * ) pucBuffer;
/* Interpret the received Ethernet packet. */
switch( pxEthernetHeader->usFrameType )
{
case ipARP_FRAME_TYPE:
{
ARPPacket_t * pxARPFrame;
ARPHeader_t * pxARPHeader;
/* The Ethernet frame contains an ARP packet. */
ADD_TYPE( FRAME_ARP );
pxARPFrame = ( ARPPacket_t * ) pucBuffer;
pxARPHeader = &( pxARPFrame->xARPHeader );
ADD_TYPE( ARP );
switch( pxARPHeader->usOperation )
{
case ipARP_REQUEST:
ADD_TYPE( REQUEST );
break;
case ipARP_REPLY:
ADD_TYPE( REPLY );
break;
default:
ADD_TYPE( UNKNOWN );
break;
}
}
break;
case ipIPv4_FRAME_TYPE:
ADD_TYPE( FRAME_4 );
vAddProtocolTags( pucBuffer, 4 );
break;
#if ( ipconfigUSE_IPv6 != 0 )
case ipIPv6_FRAME_TYPE:
ADD_TYPE( FRAME_6 );
vAddProtocolTags( pucBuffer, 6 );
break;
#endif
default:
/* No other packet types are handled. Nothing to do. */
ADD_TYPE( Unknown_FRAME );
break;
}
}
/*-----------------------------------------------------------*/
static void vActualDump( uint8_t * pucBuffer,
size_t uxLength,
BaseType_t xIncoming )
{
char pcString[ 513 ];
size_t uxOffset;
size_t uxIndex;
size_t uxCompleteCount = 0;
BaseType_t xUseIt = pdFALSE;
usSourcePort = 0u;
usDestinationPort = 0u;
pcTypeString[ 0 ] = 0;
ulTypeMask = 0uL;
if( pxCurrentEntries == NULL )
{
return;
}
vDetermineMessageType( pucBuffer, xIncoming );
for( uxIndex = 0; uxIndex < pxCurrentEntries->uxEntryCount; uxIndex++ )
{
if( pxCurrentEntries->xEntries[ uxIndex ].uxCount < pxCurrentEntries->xEntries[ uxIndex ].uxMax )
{
uint32_t ulMask = pxCurrentEntries->xEntries[ uxIndex ].ulMask;
if( ( ulMask & ulTypeMask ) == ulMask )
{
pxCurrentEntries->xEntries[ uxIndex ].uxCount++;
xUseIt = pdTRUE;
}
}
else
{
uxCompleteCount++;
}
}
FreeRTOS_printf( ( "prvWritePackets: done %d/%d : (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
uxCompleteCount,
pxCurrentEntries->uxEntryCount,
pxCurrentEntries->xEntries[ 0 ].uxCount, pxCurrentEntries->xEntries[ 0 ].uxMax,
pxCurrentEntries->xEntries[ 1 ].uxCount, pxCurrentEntries->xEntries[ 1 ].uxMax,
pxCurrentEntries->xEntries[ 2 ].uxCount, pxCurrentEntries->xEntries[ 2 ].uxMax,
pxCurrentEntries->xEntries[ 3 ].uxCount, pxCurrentEntries->xEntries[ 3 ].uxMax ) );
if( uxCompleteCount >= pxCurrentEntries->uxEntryCount )
{
FreeRTOS_printf( ( "prvWritePackets: all %lu packets have been collected\n", pxCurrentEntries->uxEntryCount ) );
if( pxCurrentEntries != NULL )
{
FILE * outfile = fopen( pcCodeFileName, ( xFirstPacket != 0 ) ? "w" : "a+" );
if( outfile == NULL )
{
FreeRTOS_printf( ( "Can not create '%s'\n", pcCodeFileName ) );
}
else
{
/*
* Create a list with pointers to each network packet.
* DumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =
* {
* &xPacket_0000,
* &xPacket_0001,
* &xPacket_0002,
* &xPacket_0003,
* }
*/
_fprintf( outfile, "\nDumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =\n{\n" );
for( uxIndex = 0; uxIndex < uxNextPacketNumber; uxIndex++ )
{
_fprintf( outfile, "\t&xPacket_%04lu,\n", uxIndex );
}
_fprintf( outfile, "};\n" );
fclose( outfile );
vWriteHeaderFile();
}
pxCurrentEntries = NULL;
/* Tell the thread and the function dump_packet() that packet
* dumping is ready. */
xDumpingReady = pdTRUE;
}
return;
}
if( xUseIt == pdFALSE )
{
return;
}
printf( "prvWritePackets: Read %lu bytes, type %s\n", uxLength, pcTypeString );
FILE * outfile = fopen( pcCodeFileName, ( xFirstPacket != 0 ) ? "w" : "a+" );
if( outfile == NULL )
{
FreeRTOS_printf( ( "Can not create '%s'\n", pcCodeFileName ) );
return;
}
if( xFirstPacket != 0 )
{
char * pcPtr;
size_t xLength;
vWriteHeaderFile( pcHeaderFileName );
xLength = snprintf( pcString, sizeof pcString, pcHeaderCode, pcHeaderFileName );
fwrite( pcString, 1u, xLength, outfile );
xFirstPacket = pdFALSE;
}
_fprintf( outfile, "\n/* Packet_%04d */\n", uxNextPacketNumber );
_fprintf( outfile, "uint8_t ucPacket_%04lx[ %lu ] =\n{\n", uxNextPacketNumber, uxLength );
for( uxOffset = 0u; uxOffset < uxLength; )
{
size_t uxCurLength = 0u;
size_t uxLast = uxOffset + dumpBYTES_PER_ROW;
BaseType_t xFirst = pdTRUE;
if( uxLast > uxLength )
{
uxLast = uxLength;
}
while( uxOffset < uxLast )
{
uxCurLength += snprintf( pcString + uxCurLength, sizeof pcString - uxCurLength, "%s0x%02x",
( uxCurLength == 0 ) ? "\t" : ", ", pucBuffer[ uxOffset ] );
uxOffset++;
}
if( uxCurLength != 0u )
{
uxCurLength += snprintf( pcString + uxCurLength, sizeof pcString - uxCurLength, "%s\n",
( uxOffset == uxLength ) ? "\n};" : "," );
fwrite( pcString, 1u, uxCurLength, outfile );
}
}
_fprintf( outfile, "\n" );
_fprintf( outfile,
"DumpPacket_t xPacket_%04lx =\n{\n"
"\t.pucData = ucPacket_%04lx,\n"
"\t.uxLength = %lu,\n"
"\t.ulType = 0x%lX, /* %s */\n",
uxNextPacketNumber, uxNextPacketNumber, uxLength, ulTypeMask, pcTypeString );
if( usSourcePort != 0u )
{
_fprintf( outfile,
"\t.usSource = %u,\n", FreeRTOS_ntohs( usSourcePort ) );
}
if( usSourcePort != 0u )
{
_fprintf( outfile,
"\t.usDestination = %u,\n", FreeRTOS_ntohs( usDestinationPort ) );
}
_fprintf( outfile,
"};\n"
"/*-----------------------------------------------------------*/\n\n" );
fclose( outfile );
uxNextPacketNumber++;
}
/*-----------------------------------------------------------*/
#endif /* ( ipconfigUSE_DUMP_PACKETS != 0 ) */

View File

@ -0,0 +1,72 @@
tcp_dump_packets.c dumps network packets in a C source file.
It is written to be added to the "pc" project ( Windows simulator ). It uses the file system to write 2 C source files:
PacketList.c
PacketList.h
How to include 'tcp_dump_packets' into a project:
● Make sure that tools/tcp_dump_packets.c is added to the source files
● See if Network Interface has been adapted to call:
`iptraceDUMP_PACKET( ucBuffer, xLength, pdTRUE ); /* Incoming packet. */`
`iptraceDUMP_PACKET( ucBuffer, xLength, pdFALSE ); /* Outgoing packet. */`
● Once the network is up, call `dump_packet_init()` with a file name and a pointer to
`DumpEntries_t`, which contains the requirements. For instance like this:
static DumpEntries_t xExampleEntries = {
.uxEntryCount = 4, /* No more than 'dumpMAX_DUMP_ENTRIES' elements. */
.xEntries = {
{ .ulMask = flag_IN | flag_UDP, .uxMax = 2u },
{ .ulMask = flag_IN | flag_ARP, .uxMax = 2u },
{ .ulMask = flag_IN | flag_TCP, .uxMax = 5u },
{ .ulMask = flag_IN | flag_SYN, .uxMax = 1u },
}
};
● Add the following lines to FreeRTOSIPConfig.h :
#define ipconfigUSE_DUMP_PACKETS ( 1 )
#include "../tools/tcp_dump_packets.h"
Later on, the module can disabled by simply setting `ipconfigUSE_DUMP_PACKETS` to `0`.
Here is some contents of the output file:
/* Packet_0001 */
uint8_t ucPacket_0001[ 60 ] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x74, 0xb5, 0x7e, 0xf0, 0x47, 0xee, 0x08, 0x06, 0x00, 0x01,
0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x74, 0xb5, 0x7e, 0xf0, 0x47, 0xee, 0xc0, 0xa8, 0x02, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
DumpPacket_t xPacket_0001 =
{
.pucData = ucPacket_0001,
.uxLength = 60,
.ulType = 0x6840, /* IN | FRAME_ARP | ARP | REQUEST */
};
/*-----------------------------------------------------------*/
tcp_dump_packets has an enum of all possible properties of network packets:
ICMP4, ICMP6, UDP, TCP, DNS, REPLY, REQUEST, SYN,
FIN, RST, ACK, IN, OUT, ARP, FRAME_ARP, FRAME_4, and FRAME_6
Each property is defined as a bit so they can be combined as in:
.ulType = 0x6840, /* IN | FRAME_ARP | ARP | REQUEST */
Finishing: when there are enough packets of all required types, an array is added to the C-source output:
DumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =
{
&xPacket_0000,
&xPacket_0001,
&xPacket_0002,
&xPacket_0003,
&xPacket_0004,
&xPacket_0005,
&xPacket_0006,
&xPacket_0007,
&xPacket_0008,
};
The new source file PacketList.{c, h} can be used in testing software as sample packets.

View File

@ -0,0 +1,465 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* 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
*/
/*
* tcp_mem_stats.c
* Used to create a CSV file with detailed information about the memory usage of FreeRTOS+TCP.
* See tools/tcp_mem_stats.md for further description.
*/
/* Standard includes. */
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
/* FreeRTOS includes. */
#include <FreeRTOS.h>
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_Stream_Buffer.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_IP_Private.h"
#include "tcp_mem_stats.h"
#if ( ipconfigUSE_TCP_MEM_STATS != 0 )
#ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION
/* Define the maximum number of objects ( memory allocations by
* the IP-stack ) that will be recorded. */
#define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u
/* If you don't want to see this pragma message, you can either
* remove it or define 'ipconfigTCP_MEM_STATS_MAX_ALLOCATION' in
* your freeRTOSIPConfig.h. */
#pragma message ("ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?")
#endif
/* When a streambuffer is allocated, 4 extra bytes will be reserved. */
#define STREAM_BUFFER_ROUNDUP_BYTES 4
#define STATS_PRINTF( MSG ) \
xCurrentLine++; \
configPRINTF( MSG )
#define ETH_MAX_PACKET_SIZE ( ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER + ipBUFFER_PADDING + 31 ) & ~0x1FuL )
/*-----------------------------------------------------------*/
/* Objects are allocated and deleted. This structure stores the type
* and the size of the object. */
typedef struct xTCP_ALLOCATION
{
TCP_MEMORY_t xMemType;
void * pxObject;
UBaseType_t uxNumber;
size_t uxSize;
} TCP_ALLOCATION_t;
/*-----------------------------------------------------------*/
static void vWriteHeader( void );
static size_t uxCurrentMallocSize;
static TCP_ALLOCATION_t xAllocations[ ipconfigTCP_MEM_STATS_MAX_ALLOCATION ];
static size_t uxAllocationCount;
static BaseType_t xFirstItem = pdTRUE;
UBaseType_t uxNextObjectNumber;
static BaseType_t xCurrentLine = 0;
static BaseType_t xFirstDumpLine = 0;
static BaseType_t xLastHeaderLineNr = 0;
static BaseType_t xLoggingStopped = 0;
/*-----------------------------------------------------------*/
static void vAddAllocation( TCP_MEMORY_t xMemType,
void * pxObject,
size_t uxSize )
{
size_t uxIndex;
vTaskSuspendAll();
{
for( uxIndex = 0; uxIndex < uxAllocationCount; uxIndex++ )
{
if( xAllocations[ uxIndex ].pxObject == pxObject )
{
/* Already added, strange. */
FreeRTOS_printf( ( "vAddAllocation: Pointer %p already added\n", pxObject ) );
break;
}
}
/* If the object has not been found,
* and if there is still space, add the object. */
if( ( uxIndex == uxAllocationCount ) &&
( uxAllocationCount < ipconfigTCP_MEM_STATS_MAX_ALLOCATION ) )
{
xAllocations[ uxIndex ].pxObject = pxObject;
xAllocations[ uxIndex ].xMemType = xMemType;
xAllocations[ uxIndex ].uxSize = uxSize;
xAllocations[ uxIndex ].uxNumber = uxNextObjectNumber++;
uxAllocationCount++;
}
}
xTaskResumeAll();
}
/*-----------------------------------------------------------*/
static TCP_ALLOCATION_t * pxRemoveAllocation( void * pxObject )
{
size_t uxSource = 0, uxTarget = 0;
static TCP_ALLOCATION_t xAllocation = { 0 };
BaseType_t xFound = pdFALSE;
TCP_ALLOCATION_t * pxReturn;
vTaskSuspendAll();
{
for( ; uxSource < uxAllocationCount; uxSource++ )
{
if( xAllocations[ uxSource ].pxObject == pxObject )
{
/* This is entry will be removed. */
( void ) memcpy( &( xAllocation ), &( xAllocations[ uxSource ] ), sizeof xAllocation );
xFound = pdTRUE;
}
else
{
xAllocations[ uxTarget ] = xAllocations[ uxSource ];
uxTarget++;
}
}
if( xFound != pdFALSE )
{
uxAllocationCount--;
pxReturn = &( xAllocation );
}
else
{
pxReturn = NULL;
}
}
xTaskResumeAll();
return pxReturn;
}
/*-----------------------------------------------------------*/
static const char * pcTypeName( TCP_MEMORY_t xMemType )
{
switch( xMemType )
{
case tcpSOCKET_TCP:
return "TCP-Socket";
case tcpSOCKET_UDP:
return "UDP-Socket";
case tcpSOCKET_SET:
return "SocketSet";
case tcpSEMAPHORE:
return "Semaphore";
case tcpRX_STREAM_BUFFER:
return "RX-Buffer";
case tcpTX_STREAM_BUFFER:
return "TX-Buffer";
case tcpNETWORK_BUFFER:
return "networkBuffer";
}
return "Unknown object";
}
/*-----------------------------------------------------------*/
static void vWriteHeader()
{
size_t uxPacketSize;
size_t uxTXSize;
size_t uxStaticSize = 0;
BaseType_t xFirstLineNr = 0;
char pucComment[ 64 ] = "";
StreamBuffer_t * pxBuffer = NULL;
size_t uxTara = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray );
/* The approximate size of a buffer for a Network Packet. */
STATS_PRINTF( ( "TCPMemStat,Some important ipconfig items:\n" ) );
STATS_PRINTF( ( "TCPMemStat,ipconfig item,Value,Comment\n" ) );
STATS_PRINTF( ( "TCPMemStat,NETWORK_MTU,%u\n", ipconfigNETWORK_MTU ) );
STATS_PRINTF( ( "TCPMemStat,TCP_MSS,%u\n", ipconfigTCP_MSS ) );
STATS_PRINTF( ( "TCPMemStat,USE_TCP,%u\n", ipconfigUSE_TCP ) );
STATS_PRINTF( ( "TCPMemStat,USE_TCP_WIN,%u\n", ipconfigUSE_TCP_WIN ) );
uxTXSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
STATS_PRINTF( ( "TCPMemStat,TCP_RX_BUFFER_LENGTH,%u,Plus %u bytes\n", ipconfigTCP_RX_BUFFER_LENGTH, uxTara + STREAM_BUFFER_ROUNDUP_BYTES ) );
if( uxTXSize > ipconfigTCP_TX_BUFFER_LENGTH )
{
snprintf( pucComment, sizeof pucComment, ",Rounded up to %u x MSS (plus %u bytes)", uxTXSize / ipconfigTCP_MSS, uxTara + STREAM_BUFFER_ROUNDUP_BYTES );
}
STATS_PRINTF( ( "TCPMemStat,TCP_TX_BUFFER_LENGTH,%u%s\n", ipconfigTCP_TX_BUFFER_LENGTH, pucComment ) );
STATS_PRINTF( ( "TCPMemStat,USE_DHCP,%u\n", ipconfigUSE_DHCP ) );
/*
* Start of fixed RAM allocations.
*/
STATS_PRINTF( ( "TCPMemStat,\n" ) );
STATS_PRINTF( ( "TCPMemStat,RAM that is always allocated either statically or on the heap:\n" ) );
STATS_PRINTF( ( "TCPMemStat,ipconfig item,Value,PerUnit,Total\n" ) );
xFirstLineNr = xCurrentLine;
if( xBufferAllocFixedSize != 0 )
{
size_t uxBytes;
/* Using BufferAllocation_1.c */
uxPacketSize = ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER + ipBUFFER_PADDING + 31 ) & ~0x1FuL;
uxBytes = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ( uxPacketSize + sizeof( NetworkBufferDescriptor_t ) );
STATS_PRINTF( ( "TCPMemStat,NUM_NETWORK_BUFFER_DESCRIPTORS,%u,%u,=B%d*C%d,Descriptors + buffers\n",
ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS,
uxPacketSize + sizeof( NetworkBufferDescriptor_t ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
}
else
{
size_t uxBytes;
/* Using BufferAllocation_2.c */
uxBytes = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * sizeof( NetworkBufferDescriptor_t );
STATS_PRINTF( ( "TCPMemStat,NUM_NETWORK_BUFFER_DESCRIPTORS,%u,%u,=B%d*C%d,Descriptors only\n",
ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS,
sizeof( NetworkBufferDescriptor_t ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
}
{
#if ( ipconfigUSE_TCP_WIN != 0 )
{
STATS_PRINTF( ( "TCPMemStat,TCP_WIN_SEG_COUNT,%u,%u,=B%d*C%d\n",
ipconfigTCP_WIN_SEG_COUNT, sizeof( TCPSegment_t ), xCurrentLine, xCurrentLine ) );
}
#else
{
STATS_PRINTF( ( "TCPMemStat,TCP_WIN_SEG_COUNT,%u,%u\n", 0, 0 ) );
}
#endif
}
{
size_t uxBytes;
size_t uxEntrySize;
uxBytes = ipconfigEVENT_QUEUE_LENGTH * sizeof( IPStackEvent_t );
STATS_PRINTF( ( "TCPMemStat,EVENT_QUEUE_LENGTH,%u,%u,=B%d*C%d\n",
ipconfigEVENT_QUEUE_LENGTH,
sizeof( IPStackEvent_t ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
uxBytes = ipconfigIP_TASK_STACK_SIZE_WORDS * sizeof( void * );
STATS_PRINTF( ( "TCPMemStat,IP_TASK_STACK_SIZE_WORDS,%u,%u,=B%d*C%d\n",
ipconfigIP_TASK_STACK_SIZE_WORDS,
sizeof( void * ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
uxBytes = ipconfigARP_CACHE_ENTRIES * sizeof( ARPCacheRow_t );
STATS_PRINTF( ( "TCPMemStat,ARP_CACHE_ENTRIES,%u,%u,=B%d*C%d\n",
ipconfigARP_CACHE_ENTRIES,
sizeof( ARPCacheRow_t ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
#if ( ipconfigUSE_DNS_CACHE == 1 )
{
uxEntrySize = 3u * sizeof( uint32_t ) + ( ( ipconfigDNS_CACHE_NAME_LENGTH + 3 ) & ~0x3u );
STATS_PRINTF( ( "TCPMemStat,DNS_CACHE_ENTRIES,%u,%u,=B%d*C%d\n",
ipconfigDNS_CACHE_ENTRIES,
uxEntrySize,
xCurrentLine,
xCurrentLine ) );
}
#endif
}
/*
* End of fixed RAM allocations.
*/
if( xBufferAllocFixedSize != 0 )
{
pucComment[ 0 ] = 0;
}
else
{
size_t uxBytes;
/* BufferAllocation_2.c uses HEAP to store network packets. */
uxPacketSize = ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER + ipBUFFER_PADDING + 3 ) & ~0x03uL;
uxBytes = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * uxPacketSize;
STATS_PRINTF( ( "TCPMemStat,Network buffers in HEAP,%u,%u,=B%d*C%d\n",
ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS,
uxPacketSize,
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
snprintf( pucComment, sizeof pucComment, "Actual size fluctuates because BufferAllocation_2.c is used" );
}
xLastHeaderLineNr = xCurrentLine;
STATS_PRINTF( ( "TCPMemStat,Total,,,=SUM(D%d:D%d),%s\n", xFirstLineNr + 1, xLastHeaderLineNr, pucComment ) );
STATS_PRINTF( ( "TCPMemStat,\n" ) );
STATS_PRINTF( ( "TCPMemStat,\n" ) );
STATS_PRINTF( ( "TCPMemStat,The following allocations are done on the heap while running:\n" ) );
STATS_PRINTF( ( "TCPMemStat,Create/Remove,Object,Size,Heap use,Pointer,Heap-min,Heap-Cur,comment\n" ) );
}
/*-----------------------------------------------------------*/
void vTCPMemStatCreate( TCP_MEMORY_t xMemType,
void * pxObject,
size_t uxSize )
{
if( xLoggingStopped == pdFALSE )
{
StreamBuffer_t * pxBuffer = NULL;
char pcExtra[ 81 ] = "";
if( xFirstItem != pdFALSE )
{
xFirstItem = pdFALSE;
vWriteHeader();
}
if( ( xMemType == tcpRX_STREAM_BUFFER ) || ( xMemType == tcpTX_STREAM_BUFFER ) )
{
size_t uxTara = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray );
size_t uxNett = uxSize - uxTara;
snprintf( pcExtra, sizeof pcExtra, ",%u nett", uxNett );
}
if( xFirstDumpLine == 0 )
{
xFirstDumpLine = xCurrentLine + 1;
}
xCurrentLine++;
configPRINTF( ( "TCPMemStat,CREATE,%s,%lu,%lu,%u,%u,%u%s\n",
pcTypeName( xMemType ),
uxSize,
uxCurrentMallocSize + uxSize,
uxNextObjectNumber,
xPortGetMinimumEverFreeHeapSize(),
xPortGetFreeHeapSize(),
pcExtra ) );
uxCurrentMallocSize += uxSize;
vAddAllocation( xMemType, pxObject, uxSize );
}
}
/*-----------------------------------------------------------*/
void vTCPMemStatDelete( void * pxObject )
{
if( xLoggingStopped == pdFALSE )
{
TCP_ALLOCATION_t * pxFound = pxRemoveAllocation( pxObject );
if( xFirstDumpLine == 0 )
{
xFirstDumpLine = xCurrentLine + 1;
}
if( pxFound == NULL )
{
FreeRTOS_printf( ( "TCPMemStat: can not find pointer %p\n", pxObject ) );
}
else
{
xCurrentLine++;
configPRINTF( ( "TCPMemStat,REMOVE,%s,-%lu,%lu,%x,%u,%u\n",
pcTypeName( pxFound->xMemType ),
pxFound->uxSize,
uxCurrentMallocSize - pxFound->uxSize,
pxFound->uxNumber,
xPortGetMinimumEverFreeHeapSize(),
xPortGetFreeHeapSize() ) );
if( uxCurrentMallocSize < pxFound->uxSize )
{
uxCurrentMallocSize = 0uL;
}
else
{
uxCurrentMallocSize -= pxFound->uxSize;
}
}
}
}
/*-----------------------------------------------------------*/
void vTCPMemStatClose()
{
if( xLoggingStopped == pdFALSE )
{
/* name;object;size;Heap;Ppointer;HeapMin;HeapDur;Comment */
BaseType_t xLastLineNr = xCurrentLine;
xLoggingStopped = pdTRUE;
STATS_PRINTF( ( "TCPMemStat,Totals,,,=MAX(D%d:D%d),,=MIN(F%d:F%d),=MAX(G%d:G%d)\n",
xFirstDumpLine,
xLastLineNr,
xFirstDumpLine,
xLastLineNr,
xFirstDumpLine,
xLastLineNr ) );
STATS_PRINTF( ( "TCPMemStat,Maximum RAM usage:,,,=SUM(D%d;D%d)\n",
xLastHeaderLineNr + 1,
xLastLineNr + 1 ) );
}
}
/*-----------------------------------------------------------*/
#endif /* ( ipconfigUSE_TCP_MEM_STATS != 0 ) */

View File

@ -0,0 +1,45 @@
tcp_mem_stats.c : FreeRTOS+TCP Memory Statistics
This module can be used in any project on any platform that uses FreeRTOS+TCP.
It creates an overview of the memory usage of FreeRTOS+TCP.
It reports the static use of RAM, and also the dynamic usage ( heap ).
It relates these numbers to the macro's defined `FreeRTOSIPConfig.h`.
It writes CSV records to the logging with configPRINTF().
The resulting log can be filtered by e.g.:
cat logging.txt | grep ".*TCPMemStat," | sed "s/.*TCPMemStat,//"
The resulting text can be imported into any spreadsheet at cell "A1" ( top-left ):
ipconfig item,Value,PerUnit,Total
NUM_NETWORK_BUFFER_DESCRIPTORS,12,60,=B13*C13,Descriptors only
TCP_WIN_SEG_COUNT,32,64,=B14*C14
EVENT_QUEUE_LENGTH,17,8,=B15*C15
IP_TASK_STACK_SIZE_WORDS,300,4,=B16*C16
When the CSV-records are imported at another row or column than "A1", the formulas will be incorrect.
How to include 'tcp_mem_stats' into a project:
● Add tools/tcp_sources/tcp_mem_stats.c to the sources
● Add the following lines to FreeRTOSIPConfig.h :
#define ipconfigUSE_TCP_MEM_STATS ( 1 )
#define ipconfigTCP_MEM_STATS_MAX_ALLOCATION ( 128 )
#include "tools/tcp_sources/include/tcp_mem_stats.h"
Later on, the module can disabled by setting `#define ipconfigUSE_TCP_MEM_STATS 0`.
`ipconfigTCP_MEM_STATS_MAX_ALLOCATION` is the maximum number of objects that can be followed at any time.
A socket that has 2 stream buffers counts as 3 objects ( needing 3 x 16 = 48 bytes to store their properties ).
The **summary** at the bottom will only be written when `iptraceMEM_STATS_CLOSE()` is called.
The application is responsible for calling `iptraceMEM_STATS_CLOSE()`.
The summary at the bottom looks like this:
Totals,,,=MAX(D25:D31),,=MIN(F25:F31),=MAX(G25:G31)
Maximum RAM usage:,,,=SUM(D20;D32)
The spreadsheet can be edited further to make estimations with different macro values.

View File

@ -0,0 +1,197 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* 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 "tcp_netstat.h"
extern List_t xBoundUDPSocketsList;
#if ( ipconfigUSE_TCP == 1 )
extern List_t xBoundTCPSocketsList;
#endif /* ipconfigUSE_TCP == 1 */
IOCounters_t xInputCounters = { 0U };
IOCounters_t xOutputCounters = { 0U };
BaseType_t vGetMetrics( MetricsType_t * pxMetrics )
{
BaseType_t xResult = 0;
/* Show a simple listing of all created sockets and their connections */
const ListItem_t * pxIterator;
uint16_t usLastPort;
memset( pxMetrics, 0, sizeof *pxMetrics );
pxMetrics->xInput = xInputCounters;
pxMetrics->xOutput = xOutputCounters;
if( !listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) )
{
FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
xResult = -1;
}
else
{
#if ( ipconfigUSE_TCP == 1 )
const ListItem_t * pxEndTCP = listGET_END_MARKER( &xBoundTCPSocketsList );
#endif
const ListItem_t * pxEndUDP = listGET_END_MARKER( &xBoundUDPSocketsList );
usLastPort = 0U;
#if ( ipconfigUSE_TCP == 1 )
{
vTaskSuspendAll();
{
for( pxIterator = listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
pxIterator != pxEndTCP;
pxIterator = listGET_NEXT( pxIterator ) )
{
const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
if( pxMetrics->xTCPPortList.uxCount < nstatMAX_TCP_PORTS )
{
if( usLastPort != pxSocket->usLocalPort )
{
pxMetrics->xTCPPortList.usTCPPortList[ pxMetrics->xTCPPortList.uxCount ] = pxSocket->usLocalPort;
pxMetrics->xTCPPortList.uxCount++;
usLastPort = pxSocket->usLocalPort;
}
}
if( pxMetrics->xTCPSocketList.uxCount < nstatMAX_TCP_PORTS )
{
size_t uxCount = pxMetrics->xTCPSocketList.uxCount;
pxMetrics->xTCPSocketList.xTCPList[ uxCount ].usLocalPort = pxSocket->usLocalPort;
pxMetrics->xTCPSocketList.xTCPList[ uxCount ].ulRemoteIP = pxSocket->u.xTCP.ulRemoteIP;
pxMetrics->xTCPSocketList.xTCPList[ uxCount ].usRemotePort = pxSocket->u.xTCP.usRemotePort;
pxMetrics->xTCPSocketList.uxCount++;
}
}
}
if( xTaskResumeAll() == 0 )
{
taskYIELD();
}
}
#endif /* ( ipconfigUSE_TCP == 1 ) */
vTaskSuspendAll();
{
for( pxIterator = listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
pxIterator != pxEndUDP;
pxIterator = listGET_NEXT( pxIterator ) )
{
const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
if( pxMetrics->xUDPPortList.uxCount < nstatMAX_UDP_PORTS )
{
pxMetrics->xUDPPortList.usUDPPortList[ pxMetrics->xUDPPortList.uxCount ] = pxSocket->usLocalPort;
pxMetrics->xUDPPortList.uxCount++;
}
if( pxMetrics->xUDPSocketList.uxCount < nstatMAX_UDP_PORTS )
{
size_t uxCount = pxMetrics->xUDPSocketList.uxCount;
pxMetrics->xUDPSocketList.xUDPList[ uxCount ].usLocalPort = pxSocket->usLocalPort;
pxMetrics->xUDPSocketList.uxCount++;
}
}
}
( void ) xTaskResumeAll();
}
return xResult;
}
void vShowMetrics( const MetricsType_t * pxMetrics )
{
size_t uxIndex;
FreeRTOS_printf( ( "Bytes in/out:\n" ) );
FreeRTOS_printf( ( " Input : %5lu packets, %5lu bytes\n",
pxMetrics->xInput.uxPacketCount,
pxMetrics->xInput.uxByteCount ) );
FreeRTOS_printf( ( " Output : %5lu packets, %5lu bytes\n",
pxMetrics->xOutput.uxPacketCount,
pxMetrics->xOutput.uxByteCount ) );
#if ( ipconfigUSE_TCP == 1 )
{
FreeRTOS_printf( ( "TCP ports:\n" ) );
for( uxIndex = 0; uxIndex < pxMetrics->xTCPPortList.uxCount; uxIndex++ )
{
FreeRTOS_printf( ( " local port: %u\n",
pxMetrics->xTCPPortList.usTCPPortList[ uxIndex ] ) );
}
FreeRTOS_printf( ( "TCP sockets:\n" ) );
for( uxIndex = 0; uxIndex < pxMetrics->xTCPSocketList.uxCount; uxIndex++ )
{
FreeRTOS_printf( ( " local port: %u remote IP %xip:%u\n",
pxMetrics->xTCPSocketList.xTCPList[ uxIndex ].usLocalPort,
pxMetrics->xTCPSocketList.xTCPList[ uxIndex ].ulRemoteIP,
pxMetrics->xTCPSocketList.xTCPList[ uxIndex ].usRemotePort ) );
}
}
#endif /* ( ipconfigUSE_TCP == 1 ) */
FreeRTOS_printf( ( "UDP ports:\n" ) );
for( uxIndex = 0; uxIndex < pxMetrics->xUDPPortList.uxCount; uxIndex++ )
{
FreeRTOS_printf( ( " local port: %u\n",
pxMetrics->xUDPPortList.usUDPPortList[ uxIndex ] ) );
}
FreeRTOS_printf( ( "UDP sockets:\n" ) );
for( uxIndex = 0; uxIndex < pxMetrics->xUDPSocketList.uxCount; uxIndex++ )
{
FreeRTOS_printf( ( " local port: %u\n",
pxMetrics->xUDPSocketList.xUDPList[ uxIndex ].usLocalPort ) );
}
}

View File

@ -0,0 +1,19 @@
tcp_netstat.c : it introduces the following function:
`BaseType_t vGetMetrics( MetricsType_t * pxMetrics )`
It collects information: all port numbers in use, all UDP sockets, all TCP sockets and their connections.
Make sure that your FreeRTOSIPConfig.h includes tools/tcp_utilities/include/tcp_netstat.h:
`@include "tcp_netstat.h"`
because it will define 2 important macro's:
#define iptraceNETWORK_INTERFACE_INPUT( uxDataLength, pucEthernetBuffer )
#define iptraceNETWORK_INTERFACE_OUTPUT( uxDataLength, pucEthernetBuffer )
These macro's will be called when an Ethernet packet has been received or sent.
When collecting socket and port information, it will iterate through the list of sockets, filling arrays of structures.

View File

@ -0,0 +1,160 @@
# Uncrustify-0.67
input_tab_size = 4 # unsigned number
output_tab_size = 4 # unsigned number
sp_arith = force # ignore/add/remove/force
sp_assign = force # ignore/add/remove/force
sp_assign_default = force # ignore/add/remove/force
sp_before_assign = force # ignore/add/remove/force
sp_after_assign = force # ignore/add/remove/force
sp_enum_assign = force # ignore/add/remove/force
sp_enum_before_assign = force # ignore/add/remove/force
sp_enum_after_assign = force # ignore/add/remove/force
sp_pp_stringify = add # ignore/add/remove/force
sp_bool = force # ignore/add/remove/force
sp_compare = force # ignore/add/remove/force
sp_inside_paren = force # ignore/add/remove/force
sp_paren_paren = force # ignore/add/remove/force
sp_paren_brace = force # ignore/add/remove/force
sp_before_ptr_star = force # ignore/add/remove/force
sp_before_unnamed_ptr_star = force # ignore/add/remove/force
sp_between_ptr_star = remove # ignore/add/remove/force
sp_after_ptr_star = force # ignore/add/remove/force
sp_before_byref = force # ignore/add/remove/force
sp_after_byref = remove # ignore/add/remove/force
sp_after_byref_func = remove # ignore/add/remove/force
sp_before_angle = remove # ignore/add/remove/force
sp_inside_angle = remove # ignore/add/remove/force
sp_after_angle = force # ignore/add/remove/force
sp_before_sparen = remove # ignore/add/remove/force
sp_inside_sparen = force # ignore/add/remove/force
sp_after_sparen = force # ignore/add/remove/force
sp_sparen_brace = force # ignore/add/remove/force
sp_before_semi_for = remove # ignore/add/remove/force
sp_before_semi_for_empty = add # ignore/add/remove/force
sp_after_semi_for_empty = force # ignore/add/remove/force
sp_before_square = remove # ignore/add/remove/force
sp_before_squares = remove # ignore/add/remove/force
sp_inside_square = force # ignore/add/remove/force
sp_after_comma = force # ignore/add/remove/force
sp_after_cast = force # ignore/add/remove/force
sp_inside_paren_cast = force # ignore/add/remove/force
sp_sizeof_paren = remove # ignore/add/remove/force
sp_inside_braces_enum = force # ignore/add/remove/force
sp_inside_braces_struct = force # ignore/add/remove/force
sp_inside_braces = force # ignore/add/remove/force
sp_inside_braces_empty = remove # ignore/add/remove/force
sp_type_func = force # ignore/add/remove/force
sp_func_proto_paren = remove # ignore/add/remove/force
sp_func_def_paren = remove # ignore/add/remove/force
sp_inside_fparens = remove # ignore/add/remove/force
sp_inside_fparen = force # ignore/add/remove/force
sp_fparen_brace = add # ignore/add/remove/force
sp_func_call_paren = remove # ignore/add/remove/force
sp_func_class_paren = remove # ignore/add/remove/force
sp_return_paren = remove # ignore/add/remove/force
sp_attribute_paren = remove # ignore/add/remove/force
sp_defined_paren = remove # ignore/add/remove/force
sp_macro = force # ignore/add/remove/force
sp_macro_func = force # ignore/add/remove/force
sp_brace_typedef = force # ignore/add/remove/force
sp_before_dc = remove # ignore/add/remove/force
sp_after_dc = remove # ignore/add/remove/force
sp_cond_colon = force # ignore/add/remove/force
sp_cond_question = force # ignore/add/remove/force
sp_case_label = force # ignore/add/remove/force
sp_endif_cmt = force # ignore/add/remove/force
sp_before_tr_emb_cmt = force # ignore/add/remove/force
sp_num_before_tr_emb_cmt = 1 # unsigned number
indent_columns = 4 # unsigned number
indent_with_tabs = 0 # unsigned number
indent_align_string = true # false/true
indent_class = true # false/true
indent_class_colon = true # false/true
indent_member = 3 # unsigned number
indent_switch_case = 4 # unsigned number
indent_case_brace = 3 # number
nl_assign_leave_one_liners = true # false/true
nl_class_leave_one_liners = true # false/true
nl_start_of_file = remove # ignore/add/remove/force
nl_end_of_file = force # ignore/add/remove/force
nl_end_of_file_min = 1 # unsigned number
nl_assign_brace = add # ignore/add/remove/force
nl_func_var_def_blk = 1 # unsigned number
nl_fcall_brace = add # ignore/add/remove/force
nl_enum_brace = force # ignore/add/remove/force
nl_struct_brace = force # ignore/add/remove/force
nl_union_brace = force # ignore/add/remove/force
nl_if_brace = add # ignore/add/remove/force
nl_brace_else = add # ignore/add/remove/force
nl_else_brace = add # ignore/add/remove/force
nl_getset_brace = force # ignore/add/remove/force
nl_for_brace = add # ignore/add/remove/force
nl_while_brace = add # ignore/add/remove/force
nl_do_brace = add # ignore/add/remove/force
nl_switch_brace = add # ignore/add/remove/force
nl_multi_line_define = true # false/true
nl_before_case = true # false/true
nl_after_case = true # false/true
nl_func_type_name = remove # ignore/add/remove/force
nl_func_proto_type_name = remove # ignore/add/remove/force
nl_func_paren = remove # ignore/add/remove/force
nl_func_def_paren = remove # ignore/add/remove/force
nl_func_decl_start = remove # ignore/add/remove/force
nl_func_def_start = remove # ignore/add/remove/force
nl_func_decl_args = add # ignore/add/remove/force
nl_func_def_args = add # ignore/add/remove/force
nl_func_decl_end = remove # ignore/add/remove/force
nl_func_def_end = remove # ignore/add/remove/force
nl_fdef_brace = add # ignore/add/remove/force
nl_after_semicolon = true # false/true
nl_after_brace_open = true # false/true
nl_after_brace_close = true # false/true
nl_squeeze_ifdef = true # false/true
nl_before_if = force # ignore/add/remove/force
nl_after_if = force # ignore/add/remove/force
nl_before_for = force # ignore/add/remove/force
nl_after_for = force # ignore/add/remove/force
nl_before_while = force # ignore/add/remove/force
nl_after_while = force # ignore/add/remove/force
nl_before_switch = force # ignore/add/remove/force
nl_after_switch = force # ignore/add/remove/force
nl_before_do = force # ignore/add/remove/force
nl_after_do = force # ignore/add/remove/force
nl_max = 4 # unsigned number
nl_after_func_proto_group = 1 # unsigned number
nl_after_func_body_class = 2 # unsigned number
nl_before_block_comment = 2 # unsigned number
eat_blanks_after_open_brace = true # false/true
eat_blanks_before_close_brace = true # false/true
nl_after_return = true # false/true
pos_bool = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
align_var_def_amp_style = 1 # unsigned number
align_var_def_thresh = 16 # unsigned number
align_assign_thresh = 12 # unsigned number
align_struct_init_span = 3 # unsigned number
align_typedef_gap = 3 # unsigned number
align_typedef_span = 5 # unsigned number
align_typedef_star_style = 1 # unsigned number
align_typedef_amp_style = 1 # unsigned number
align_right_cmt_span = 3 # unsigned number
align_nl_cont = true # false/true
align_pp_define_gap = 4 # unsigned number
align_pp_define_span = 3 # unsigned number
cmt_cpp_to_c = true # false/true
cmt_star_cont = true # false/true
mod_full_brace_do = add # ignore/add/remove/force
mod_full_brace_for = add # ignore/add/remove/force
mod_full_brace_if = add # ignore/add/remove/force
mod_full_brace_while = add # ignore/add/remove/force
mod_full_paren_if_bool = true # false/true
mod_remove_extra_semicolon = true # false/true
mod_add_long_ifdef_endif_comment = 10 # unsigned number
mod_add_long_ifdef_else_comment = 10 # unsigned number
mod_case_brace = remove # ignore/add/remove/force
mod_remove_empty_return = true # false/true
pp_indent = force # ignore/add/remove/force
pp_indent_at_level = true # false/true
pp_indent_count = 4 # unsigned number
pp_space = remove # ignore/add/remove/force
pp_if_indent_code = true # false/true
# option(s) with 'not default' value: 158

View File

@ -0,0 +1,160 @@
# Uncrustify-0.67
input_tab_size = 4 # unsigned number
output_tab_size = 4 # unsigned number
sp_arith = force # ignore/add/remove/force
sp_assign = force # ignore/add/remove/force
sp_assign_default = force # ignore/add/remove/force
sp_before_assign = force # ignore/add/remove/force
sp_after_assign = force # ignore/add/remove/force
sp_enum_assign = force # ignore/add/remove/force
sp_enum_before_assign = force # ignore/add/remove/force
sp_enum_after_assign = force # ignore/add/remove/force
sp_pp_stringify = add # ignore/add/remove/force
sp_bool = force # ignore/add/remove/force
sp_compare = force # ignore/add/remove/force
sp_inside_paren = force # ignore/add/remove/force
sp_paren_paren = force # ignore/add/remove/force
sp_paren_brace = force # ignore/add/remove/force
sp_before_ptr_star = force # ignore/add/remove/force
sp_before_unnamed_ptr_star = force # ignore/add/remove/force
sp_between_ptr_star = remove # ignore/add/remove/force
sp_after_ptr_star = force # ignore/add/remove/force
sp_before_byref = force # ignore/add/remove/force
sp_after_byref = remove # ignore/add/remove/force
sp_after_byref_func = remove # ignore/add/remove/force
sp_before_angle = remove # ignore/add/remove/force
sp_inside_angle = remove # ignore/add/remove/force
sp_after_angle = force # ignore/add/remove/force
sp_before_sparen = remove # ignore/add/remove/force
sp_inside_sparen = force # ignore/add/remove/force
sp_after_sparen = force # ignore/add/remove/force
sp_sparen_brace = force # ignore/add/remove/force
sp_before_semi_for = remove # ignore/add/remove/force
sp_before_semi_for_empty = add # ignore/add/remove/force
sp_after_semi_for_empty = force # ignore/add/remove/force
sp_before_square = remove # ignore/add/remove/force
sp_before_squares = remove # ignore/add/remove/force
sp_inside_square = force # ignore/add/remove/force
sp_after_comma = force # ignore/add/remove/force
sp_after_cast = force # ignore/add/remove/force
sp_inside_paren_cast = force # ignore/add/remove/force
sp_sizeof_paren = remove # ignore/add/remove/force
sp_inside_braces_enum = force # ignore/add/remove/force
sp_inside_braces_struct = force # ignore/add/remove/force
sp_inside_braces = force # ignore/add/remove/force
sp_inside_braces_empty = remove # ignore/add/remove/force
sp_type_func = force # ignore/add/remove/force
sp_func_proto_paren = remove # ignore/add/remove/force
sp_func_def_paren = remove # ignore/add/remove/force
sp_inside_fparens = remove # ignore/add/remove/force
sp_inside_fparen = force # ignore/add/remove/force
sp_fparen_brace = add # ignore/add/remove/force
sp_func_call_paren = remove # ignore/add/remove/force
sp_func_class_paren = remove # ignore/add/remove/force
sp_return_paren = remove # ignore/add/remove/force
sp_attribute_paren = remove # ignore/add/remove/force
sp_defined_paren = remove # ignore/add/remove/force
sp_macro = force # ignore/add/remove/force
sp_macro_func = force # ignore/add/remove/force
sp_brace_typedef = force # ignore/add/remove/force
sp_before_dc = remove # ignore/add/remove/force
sp_after_dc = remove # ignore/add/remove/force
sp_cond_colon = force # ignore/add/remove/force
sp_cond_question = force # ignore/add/remove/force
sp_case_label = force # ignore/add/remove/force
sp_endif_cmt = force # ignore/add/remove/force
sp_before_tr_emb_cmt = force # ignore/add/remove/force
sp_num_before_tr_emb_cmt = 1 # unsigned number
indent_columns = 4 # unsigned number
indent_with_tabs = 2 # unsigned number
indent_align_string = true # false/true
indent_class = true # false/true
indent_class_colon = true # false/true
indent_member = 3 # unsigned number
indent_switch_case = 4 # unsigned number
indent_case_brace = 3 # number
nl_assign_leave_one_liners = true # false/true
nl_class_leave_one_liners = true # false/true
nl_start_of_file = remove # ignore/add/remove/force
nl_end_of_file = force # ignore/add/remove/force
nl_end_of_file_min = 1 # unsigned number
nl_assign_brace = add # ignore/add/remove/force
nl_func_var_def_blk = 1 # unsigned number
nl_fcall_brace = add # ignore/add/remove/force
nl_enum_brace = force # ignore/add/remove/force
nl_struct_brace = force # ignore/add/remove/force
nl_union_brace = force # ignore/add/remove/force
nl_if_brace = add # ignore/add/remove/force
nl_brace_else = add # ignore/add/remove/force
nl_else_brace = add # ignore/add/remove/force
nl_getset_brace = force # ignore/add/remove/force
nl_for_brace = add # ignore/add/remove/force
nl_while_brace = add # ignore/add/remove/force
nl_do_brace = add # ignore/add/remove/force
nl_switch_brace = add # ignore/add/remove/force
nl_multi_line_define = true # false/true
nl_before_case = true # false/true
nl_after_case = true # false/true
nl_func_type_name = remove # ignore/add/remove/force
nl_func_proto_type_name = remove # ignore/add/remove/force
nl_func_paren = remove # ignore/add/remove/force
nl_func_def_paren = remove # ignore/add/remove/force
nl_func_decl_start = remove # ignore/add/remove/force
nl_func_def_start = remove # ignore/add/remove/force
nl_func_decl_args = add # ignore/add/remove/force
nl_func_def_args = add # ignore/add/remove/force
nl_func_decl_end = remove # ignore/add/remove/force
nl_func_def_end = remove # ignore/add/remove/force
nl_fdef_brace = add # ignore/add/remove/force
nl_after_semicolon = true # false/true
nl_after_brace_open = true # false/true
nl_after_brace_close = true # false/true
nl_squeeze_ifdef = true # false/true
nl_before_if = force # ignore/add/remove/force
nl_after_if = force # ignore/add/remove/force
nl_before_for = force # ignore/add/remove/force
nl_after_for = force # ignore/add/remove/force
nl_before_while = force # ignore/add/remove/force
nl_after_while = force # ignore/add/remove/force
nl_before_switch = force # ignore/add/remove/force
nl_after_switch = force # ignore/add/remove/force
nl_before_do = force # ignore/add/remove/force
nl_after_do = force # ignore/add/remove/force
nl_max = 4 # unsigned number
nl_after_func_proto_group = 1 # unsigned number
nl_after_func_body_class = 2 # unsigned number
nl_before_block_comment = 2 # unsigned number
eat_blanks_after_open_brace = true # false/true
eat_blanks_before_close_brace = true # false/true
nl_after_return = true # false/true
pos_bool = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
align_var_def_amp_style = 1 # unsigned number
align_var_def_thresh = 16 # unsigned number
align_assign_thresh = 12 # unsigned number
align_struct_init_span = 3 # unsigned number
align_typedef_gap = 3 # unsigned number
align_typedef_span = 5 # unsigned number
align_typedef_star_style = 1 # unsigned number
align_typedef_amp_style = 1 # unsigned number
align_right_cmt_span = 3 # unsigned number
align_nl_cont = true # false/true
align_pp_define_gap = 4 # unsigned number
align_pp_define_span = 3 # unsigned number
cmt_cpp_to_c = true # false/true
cmt_star_cont = true # false/true
mod_full_brace_do = add # ignore/add/remove/force
mod_full_brace_for = add # ignore/add/remove/force
mod_full_brace_if = add # ignore/add/remove/force
mod_full_brace_while = add # ignore/add/remove/force
mod_full_paren_if_bool = true # false/true
mod_remove_extra_semicolon = true # false/true
mod_add_long_ifdef_endif_comment = 10 # unsigned number
mod_add_long_ifdef_else_comment = 10 # unsigned number
mod_case_brace = remove # ignore/add/remove/force
mod_remove_empty_return = true # false/true
pp_indent = remove # ignore/add/remove/force
pp_indent_at_level = true # false/true
pp_indent_count = 4 # unsigned number
pp_space = remove # ignore/add/remove/force
pp_if_indent_code = false # false/true
# option(s) with 'not default' value: 158