Update trace recorder code.

Add TCP Echo server to the FreeR_Plus_TCP_Minimal_Window_Simulator project.
This commit is contained in:
Richard Barry 2018-07-02 22:29:02 +00:00
parent f7fc215247
commit d525d5092d
35 changed files with 4431 additions and 2436 deletions

View file

@ -0,0 +1,288 @@
/*
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
/*
* FreeRTOS tasks are used with FreeRTOS+TCP to create a TCP echo server on the
* standard echo port number (7).
*
* See the following web page for essential demo usage and configuration
* details:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Echo_Server.html
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
/* Remove the whole file if FreeRTOSIPConfig.h is set to exclude TCP. */
#if( ipconfigUSE_TCP == 1 )
/* The maximum time to wait for a closing socket to close. */
#define tcpechoSHUTDOWN_DELAY ( pdMS_TO_TICKS( 5000 ) )
/* The standard echo port number. */
#define tcpechoPORT_NUMBER 7
/* If ipconfigUSE_TCP_WIN is 1 then the Tx sockets will use a buffer size set by
ipconfigTCP_TX_BUFFER_LENGTH, and the Tx window size will be
configECHO_SERVER_TX_WINDOW_SIZE times the buffer size. Note
ipconfigTCP_TX_BUFFER_LENGTH is set in FreeRTOSIPConfig.h as it is a standard TCP/IP
stack constant, whereas configECHO_SERVER_TX_WINDOW_SIZE is set in
FreeRTOSConfig.h as it is a demo application constant. */
#ifndef configECHO_SERVER_TX_WINDOW_SIZE
#define configECHO_SERVER_TX_WINDOW_SIZE 2
#endif
/* If ipconfigUSE_TCP_WIN is 1 then the Rx sockets will use a buffer size set by
ipconfigTCP_RX_BUFFER_LENGTH, and the Rx window size will be
configECHO_SERVER_RX_WINDOW_SIZE times the buffer size. Note
ipconfigTCP_RX_BUFFER_LENGTH is set in FreeRTOSIPConfig.h as it is a standard TCP/IP
stack constant, whereas configECHO_SERVER_RX_WINDOW_SIZE is set in
FreeRTOSConfig.h as it is a demo application constant. */
#ifndef configECHO_SERVER_RX_WINDOW_SIZE
#define configECHO_SERVER_RX_WINDOW_SIZE 2
#endif
/*-----------------------------------------------------------*/
/*
* Uses FreeRTOS+TCP to listen for incoming echo connections, creating a task
* to handle each connection.
*/
static void prvConnectionListeningTask( void *pvParameters );
/*
* Created by the connection listening task to handle a single connection.
*/
static void prvServerConnectionInstance( void *pvParameters );
/*-----------------------------------------------------------*/
/* Stores the stack size passed into vStartSimpleTCPServerTasks() so it can be
reused when the server listening task creates tasks to handle connections. */
static uint16_t usUsedStackSize = 0;
/*-----------------------------------------------------------*/
void vStartSimpleTCPServerTasks( uint16_t usStackSize, UBaseType_t uxPriority )
{
/* Create the TCP echo server. */
xTaskCreate( prvConnectionListeningTask, "ServerListener", usStackSize, NULL, uxPriority + 1, NULL );
/* Remember the requested stack size so it can be re-used by the server
listening task when it creates tasks to handle connections. */
usUsedStackSize = usStackSize;
}
/*-----------------------------------------------------------*/
static void prvConnectionListeningTask( void *pvParameters )
{
struct freertos_sockaddr xClient, xBindAddress;
Socket_t xListeningSocket, xConnectedSocket;
socklen_t xSize = sizeof( xClient );
static const TickType_t xReceiveTimeOut = portMAX_DELAY;
const BaseType_t xBacklog = 20;
#if( ipconfigUSE_TCP_WIN == 1 )
WinProperties_t xWinProps;
/* Fill in the buffer and window sizes that will be used by the socket. */
xWinProps.lTxBufSize = ipconfigTCP_TX_BUFFER_LENGTH;
xWinProps.lTxWinSize = configECHO_SERVER_TX_WINDOW_SIZE;
xWinProps.lRxBufSize = ipconfigTCP_RX_BUFFER_LENGTH;
xWinProps.lRxWinSize = configECHO_SERVER_RX_WINDOW_SIZE;
#endif /* ipconfigUSE_TCP_WIN */
/* Just to prevent compiler warnings. */
( void ) pvParameters;
/* Attempt to open the socket. */
xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
/* Set a time out so accept() will just wait for a connection. */
FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
/* Set the window and buffer sizes. */
#if( ipconfigUSE_TCP_WIN == 1 )
{
FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
}
#endif /* ipconfigUSE_TCP_WIN */
/* Bind the socket to the port that the client task will send to, then
listen for incoming connections. */
xBindAddress.sin_port = tcpechoPORT_NUMBER;
xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
FreeRTOS_listen( xListeningSocket, xBacklog );
for( ;; )
{
/* Wait for a client to connect. */
xConnectedSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize );
configASSERT( xConnectedSocket != FREERTOS_INVALID_SOCKET );
/* Spawn a task to handle the connection. */
xTaskCreate( prvServerConnectionInstance, "EchoServer", usUsedStackSize, ( void * ) xConnectedSocket, tskIDLE_PRIORITY, NULL );
}
}
/*-----------------------------------------------------------*/
static void prvServerConnectionInstance( void *pvParameters )
{
int32_t lBytes, lSent, lTotalSent;
Socket_t xConnectedSocket;
static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );
static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 5000 );
TickType_t xTimeOnShutdown;
uint8_t *pucRxBuffer;
xConnectedSocket = ( Socket_t ) pvParameters;
/* Attempt to create the buffer used to receive the string to be echoed
back. This could be avoided using a zero copy interface that just returned
the same buffer. */
pucRxBuffer = ( uint8_t * ) pvPortMalloc( ipconfigTCP_MSS );
if( pucRxBuffer != NULL )
{
FreeRTOS_setsockopt( xConnectedSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
FreeRTOS_setsockopt( xConnectedSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xReceiveTimeOut ) );
for( ;; )
{
/* Zero out the receive array so there is NULL at the end of the string
when it is printed out. */
memset( pucRxBuffer, 0x00, ipconfigTCP_MSS );
/* Receive data on the socket. */
lBytes = FreeRTOS_recv( xConnectedSocket, pucRxBuffer, ipconfigTCP_MSS, 0 );
/* If data was received, echo it back. */
if( lBytes >= 0 )
{
lSent = 0;
lTotalSent = 0;
/* Call send() until all the data has been sent. */
while( ( lSent >= 0 ) && ( lTotalSent < lBytes ) )
{
lSent = FreeRTOS_send( xConnectedSocket, pucRxBuffer, lBytes - lTotalSent, 0 );
lTotalSent += lSent;
}
if( lSent < 0 )
{
/* Socket closed? */
break;
}
}
else
{
/* Socket closed? */
break;
}
}
}
/* Initiate a shutdown in case it has not already been initiated. */
FreeRTOS_shutdown( xConnectedSocket, FREERTOS_SHUT_RDWR );
/* Wait for the shutdown to take effect, indicated by FreeRTOS_recv()
returning an error. */
xTimeOnShutdown = xTaskGetTickCount();
do
{
if( FreeRTOS_recv( xConnectedSocket, pucRxBuffer, ipconfigTCP_MSS, 0 ) < 0 )
{
break;
}
} while( ( xTaskGetTickCount() - xTimeOnShutdown ) < tcpechoSHUTDOWN_DELAY );
/* Finished with the socket, buffer, the task. */
vPortFree( pucRxBuffer );
FreeRTOS_closesocket( xConnectedSocket );
vTaskDelete( NULL );
}
/*-----------------------------------------------------------*/
/* The whole file is excluded if TCP is not compiled in. */
#endif /* ipconfigUSE_TCP */

View file

@ -0,0 +1,76 @@
/*
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
#ifndef SIMPLE_TCP_ECHO_SERVER_H
#define SIMPLE_TCP_ECHO_SERVER_H
void vStartSimpleTCPServerTasks( uint16_t usStackSize, BaseType_t uxPriority );
BaseType_t xAreTCPEchoServersStillRunning( void );
#endif /* SIMPLE_TCP_ECHO_SERVER_H */

View file

@ -174,16 +174,16 @@ configure the real network connection to use. */
/* Default IP address configuration. Used in ipconfigUSE_DNS is set to 0, or
ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */
#define configIP_ADDR0 172
#define configIP_ADDR1 25
#define configIP_ADDR2 218
#define configIP_ADDR0 10
#define configIP_ADDR1 10
#define configIP_ADDR2 10
#define configIP_ADDR3 200
/* Default gateway IP address configuration. Used in ipconfigUSE_DNS is set to
0, or ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */
#define configGATEWAY_ADDR0 172
#define configGATEWAY_ADDR1 25
#define configGATEWAY_ADDR2 218
#define configGATEWAY_ADDR0 10
#define configGATEWAY_ADDR1 10
#define configGATEWAY_ADDR2 10
#define configGATEWAY_ADDR3 1
/* Default DNS server configuration. OpenDNS addresses are 208.67.222.222 and
@ -197,7 +197,7 @@ to 1 but a DNS server cannot be contacted.*/
/* Default netmask configuration. Used in ipconfigUSE_DNS is set to 0, or
ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */
#define configNET_MASK0 255
#define configNET_MASK1 255
#define configNET_MASK1 0
#define configNET_MASK2 0
#define configNET_MASK3 0

View file

@ -154,6 +154,7 @@
<ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_UDP_IP.c" />
<ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\portable\BufferManagement\BufferAllocation_2.c" />
<ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\portable\NetworkInterface\WinPCap\NetworkInterface.c" />
<ClCompile Include="DemoTasks\SimpleTCPEchoServer.c" />
<ClCompile Include="DemoTasks\TCPEchoClient_SingleTasks.c" />
<ClCompile Include="DemoTasks\SimpleUDPClientAndServer.c" />
<ClCompile Include="demo_logging.c" />

View file

@ -97,6 +97,9 @@
<Filter>FreeRTOS+\FreeRTOS+TCP</Filter>
</ClCompile>
<ClCompile Include="demo_logging.c" />
<ClCompile Include="DemoTasks\SimpleTCPEchoServer.c">
<Filter>DemoTasks</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\NetworkInterface.h">

View file

@ -44,6 +44,7 @@
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "SimpleUDPClientAndServer.h"
#include "SimpleTCPEchoServer.h"
#include "TCPEchoClient_SingleTasks.h"
#include "demo_logging.h"
@ -55,6 +56,10 @@
#define mainECHO_CLIENT_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) /* Not used in the Windows port. */
#define mainECHO_CLIENT_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* Echo server task parameters. */
#define mainECHO_SERVER_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) /* Not used in the Windows port. */
#define mainECHO_SERVER_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* Define a name that will be used for LLMNR and NBNS searches. */
#define mainHOST_NAME "RTOSDemo"
#define mainDEVICE_NICK_NAME "windows_demo"
@ -77,10 +82,14 @@ verify the echo reply, from within the same task (Tx and Rx are performed in the
same RTOS task). The IP address of the echo server must be configured using the
configECHO_SERVER_ADDR0 to configECHO_SERVER_ADDR3 constants in
FreeRTOSConfig.h.
mainCREATE_TCP_ECHO_SERVER_TASK: When set to 1 a task is created that accepts
connections on the standard echo port (port 7), then echos back any data
received on that connection.
*/
#define mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS 1
#define mainCREATE_TCP_ECHO_TASKS_SINGLE 1
#define mainCREATE_TCP_ECHO_SERVER_TASK 0
/*-----------------------------------------------------------*/
/*
@ -231,6 +240,12 @@ static BaseType_t xTasksAlreadyCreated = pdFALSE;
}
#endif /* mainCREATE_TCP_ECHO_TASKS_SINGLE */
#if( mainCREATE_TCP_ECHO_SERVER_TASK == 1 )
{
vStartSimpleTCPServerTasks( mainECHO_SERVER_TASK_STACK_SIZE, mainECHO_SERVER_TASK_PRIORITY );
}
#endif
xTasksAlreadyCreated = pdTRUE;
}

View file

@ -1,5 +1,5 @@
/*
* FreeRTOS+TCP V2.0.1
* 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
@ -19,10 +19,8 @@
* 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
*/
/* Standard includes. */
@ -597,6 +595,9 @@ static void prvInitialiseDHCP( void )
xDHCPData.ulTransactionId++;
}
/* Check for random number generator API failure. */
if( 0 != xDHCPData.ulTransactionId )
{
xDHCPData.xUseBroadcast = 0;
xDHCPData.ulOfferedIPAddress = 0UL;
xDHCPData.ulDHCPServerAddress = 0UL;
@ -607,6 +608,7 @@ static void prvInitialiseDHCP( void )
FreeRTOS_debug_printf( ( "prvInitialiseDHCP: start after %lu ticks\n", dhcpINITIAL_TIMER_PERIOD ) );
vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );
}
}
/*-----------------------------------------------------------*/
static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
@ -675,9 +677,7 @@ const uint32_t ulMandatoryOptions = 2ul; /* DHCP server address, and the correct
state machine is expecting. */
ulProcessed++;
}
else
{
if( *pucByte == ( uint8_t ) dhcpMESSAGE_TYPE_NACK )
else if( *pucByte == ( uint8_t ) dhcpMESSAGE_TYPE_NACK )
{
if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_ACK )
{
@ -685,8 +685,9 @@ const uint32_t ulMandatoryOptions = 2ul; /* DHCP server address, and the correct
xDHCPData.eDHCPState = eWaitingSendFirstDiscover;
}
}
/* Stop processing further options. */
ucLength = 0;
else
{
/* Don't process other message types. */
}
break;

View file

@ -292,7 +292,7 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
pxWhere->pxPrevious = pxNewListItem;
/* Remember which list the item is in. */
pxNewListItem->pvContainer = ( void * ) pxList;
pxNewListItem->pxContainer = pxList;
( pxList->uxNumberOfItems )++;
}

View file

@ -510,7 +510,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif
#ifndef ipconfigTCP_KEEP_ALIVE
#define ipconfigTCP_KEEP_ALIVE 0
#define ipconfigTCP_KEEP_ALIVE 1
#endif
#ifndef ipconfigDNS_USE_CALLBACKS
@ -526,7 +526,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif
#ifndef ipconfigTCP_HANG_PROTECTION
#define ipconfigTCP_HANG_PROTECTION 0
#define ipconfigTCP_HANG_PROTECTION 1
#endif
#ifndef ipconfigTCP_IP_SANITY

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcHardwarePort.h
@ -38,7 +38,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -344,7 +344,22 @@
#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
#define TRC_IRQ_PRIORITY_ORDER 0
#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Altera_NiosII)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#include "system.h"
#include "sys/alt_timestamp.h"
#define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
#define TRC_HWTC_COUNT (uint32_t)alt_timestamp()
#define TRC_HWTC_PERIOD 0xFFFFFFFF
#define TRC_HWTC_FREQ_HZ TIMESTAMP_TIMER_FREQ
#define TRC_HWTC_DIVISOR 1
#define TRC_IRQ_PRIORITY_ORDER 0
#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9)
/* INPUT YOUR PERIPHERAL BASE ADDRESS HERE */
#define TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS 0xSOMETHING

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcPortDefines.h
@ -38,7 +38,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -70,6 +70,23 @@
#define TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC (0x01)
#define TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM (0x02)
/* Filter Groups */
#define FilterGroup0 (uint16_t)0x0001
#define FilterGroup1 (uint16_t)0x0002
#define FilterGroup2 (uint16_t)0x0004
#define FilterGroup3 (uint16_t)0x0008
#define FilterGroup4 (uint16_t)0x0010
#define FilterGroup5 (uint16_t)0x0020
#define FilterGroup6 (uint16_t)0x0040
#define FilterGroup7 (uint16_t)0x0080
#define FilterGroup8 (uint16_t)0x0100
#define FilterGroup9 (uint16_t)0x0200
#define FilterGroup10 (uint16_t)0x0400
#define FilterGroup11 (uint16_t)0x0800
#define FilterGroup12 (uint16_t)0x1000
#define FilterGroup13 (uint16_t)0x2000
#define FilterGroup14 (uint16_t)0x4000
#define FilterGroup15 (uint16_t)0x8000
/******************************************************************************
* Supported ports
@ -116,5 +133,5 @@
#define TRC_HARDWARE_PORT_NXP_LPC210X 14 /* No Any */
#define TRC_HARDWARE_PORT_ARM_CORTEX_A9 15 /* Yes Any */
#define TRC_HARDWARE_PORT_POWERPC_Z4 16 /* No FreeRTOS */
#define TRC_HARDWARE_PORT_Altera_NiosII 17 /* No Any */
#endif /*TRC_PORTDEFINES_H*/

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcRecorder.h
@ -38,7 +38,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -51,11 +51,11 @@ extern "C" {
#include <stdarg.h>
#include <stdint.h>
#include <stddef.h>
#include "trcConfig.h"
#include "trcPortDefines.h"
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
typedef uint16_t traceString;
typedef uint8_t traceUBChannel;
@ -85,6 +85,11 @@ typedef const void* traceHandle;
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
#define TRACE_GET_LOW16(value) ((uint16_t)((value) & 0x0000FFFF))
#define TRACE_GET_HIGH16(value) ((uint16_t)(((value) >> 16) & 0x0000FFFF))
#define TRACE_SET_LOW16(current, value) (((current) & 0xFFFF0000) | (value))
#define TRACE_SET_HIGH16(current, value) (((current) & 0x0000FFFF) | (((uint32_t)(value)) << 16))
/******************************************************************************/
/*** Common API - both Snapshot and Streaming mode ****************************/
/******************************************************************************/
@ -208,9 +213,12 @@ void vTraceEnable(int startOption);
* In snapshot mode you are limited to maximum 15 arguments, that must not exceed
* 32 bytes in total (not counting the format string). If exceeded, the recorder
* logs an internal error (displayed when opening the trace) and stops recording.
*
******************************************************************************/
#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
void vTracePrintF(traceString chn, const char* fmt, ...);
#else
#define vTracePrintF(chn, ...) (void)chn
#endif
/******************************************************************************
* vTracePrint
@ -222,9 +230,12 @@ void vTracePrintF(traceString chn, const char* fmt, ...);
* traceString chn = xTraceRegisterString("MyChannel");
* ...
* vTracePrint(chn, "Hello World!");
*
******************************************************************************/
#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
void vTracePrint(traceString chn, const char* str);
#else
#define vTracePrint(chn, ...) (void)chn
#endif
/*******************************************************************************
* xTraceRegisterString
@ -235,9 +246,12 @@ void vTracePrint(traceString chn, const char* str);
* myEventHandle = xTraceRegisterString("MyUserEvent");
* ...
* vTracePrintF(myEventHandle, "My value is: %d", myValue);
*
******************************************************************************/
#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
traceString xTraceRegisterString(const char* name);
#else
#define xTraceRegisterString(x) (x)
#endif
/*******************************************************************************
* vTraceSet...Name(void* object, const char* name)
@ -247,18 +261,8 @@ traceString xTraceRegisterString(const char* name);
*
* Kernel-specific functions for setting names of kernel objects, for display in
* Tracealyzer.
*
* See trcKernelPort.h for details (since kernel-specific)
******************************************************************************/
/*******************************************************************************
* vTraceExclude...
*
* Kernel-specific macros for excluding specified events from the trace. Allows
* for capturing longer traces in snapshot mode by selective tracing.
*
* See trcKernelPort.h for details (kernel-specific)
******************************************************************************/
/* See trcKernelPort.h for details (kernel-specific) */
/*******************************************************************************
* xTraceSetISRProperties
@ -277,7 +281,6 @@ traceString xTraceRegisterString(const char* name);
* ...
* vTraceStoreISREnd(0);
* }
*
******************************************************************************/
traceHandle xTraceSetISRProperties(const char* name, uint8_t priority);
@ -298,7 +301,6 @@ traceHandle xTraceSetISRProperties(const char* name, uint8_t priority);
* ...
* vTraceStoreISREnd(0);
* }
*
******************************************************************************/
void vTraceStoreISRBegin(traceHandle handle);
@ -323,7 +325,6 @@ void vTraceStoreISRBegin(traceHandle handle);
* ...
* vTraceStoreISREnd(0);
* }
*
******************************************************************************/
void vTraceStoreISREnd(int isTaskSwitchRequired);
@ -352,7 +353,7 @@ void vTraceInstanceFinishedNext(void);
/*******************************************************************************
* xTraceGetLastError
*
* Returns the last error, if any.
* Returns the last error or warning as a string, or NULL if none.
*****************************************************************************/
const char* xTraceGetLastError(void);
@ -420,8 +421,11 @@ void vTraceSetRecorderDataBuffer(void* pRecorderData);
*
* This translates to a single static allocation, on which you can apply linker
* directives to place it in a particular memory region.
*
* - Snapshot mode: "RecorderDataType <name>"
* - Streaming mode: "char <name> [<size>]", with <size> from trcStreamingPort.h.
*
* - Streaming mode: "char <name> [<size>]",
* where <size> is defined in trcStreamingConfig.h.
*
* Example:
*
@ -434,17 +438,96 @@ void vTraceSetRecorderDataBuffer(void* pRecorderData);
* vTraceSetRecorderDataBuffer(&myTraceBuffer); // Note the "&"
* ...
* vTraceEnable(TRC_INIT); // Initialize the data structure
*
******************************************************************************/
#ifndef TRC_ALLOC_CUSTOM_BUFFER
/* Definition for snapshot mode only. Also defined in trcStreamingPort.h */
#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM)
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) RecorderDataType bufname;
#elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
#ifdef TRC_CFG_RTT_BUFFER_SIZE_UP /* J-Link RTT */
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) char bufname [TRC_CFG_RTT_BUFFER_SIZE_UP]; /* Not static in this case, since declared in user code */
#else
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) char bufname [(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
#endif
#endif
#else
#define TRC_ALLOC_CUSTOM_BUFFER(bufname)
#endif
#endif
/******************************************************************************
* xTraceIsRecordingEnabled
*
* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0.
******************************************************************************/
int xTraceIsRecordingEnabled(void);
/*******************************************************************************
* vTraceSetFilterGroup
*
* Sets the "filter group" to assign when creating RTOS objects, such as tasks,
* queues, semaphores and mutexes. This together with vTraceSetFilterMask
* allows you to control what events that are recorded, based on the
* objects they refer to.
*
* There are 16 filter groups named FilterGroup0 .. FilterGroup15.
*
* Note: We don't recommend filtering out the Idle task, so make sure to call
* vTraceSetFilterGroup just before initializing the RTOS, in order to assign
* such "default" objects to the right Filter Group (typically group 0).
*
* Example:
*
* // Assign tasks T1 to FilterGroup0 (default)
* <Create Task T1>
*
* // Assign Q1 and Q2 to FilterGroup1
* vTraceSetFilterGroup(FilterGroup1);
* <Create Queue Q1>
* <Create Queue Q2>
*
* // Assigns Q3 to FilterGroup2
* vTraceSetFilterGroup(FilterGroup2);
* <Create Queue Q3>
*
* // Only include FilterGroup0 and FilterGroup2, exclude FilterGroup1 (Q1 and Q2) from the trace
* vTraceSetFilterMask( FilterGroup0 | FilterGroup2 );
*
* // Assign the default RTOS objects (e.g. Idle task) to FilterGroup0
* vTraceSetFilterGroup(FilterGroup0);
* <Start the RTOS scheduler>
*
* Note that you may define your own names for the filter groups using
* preprocessor definitions, to make the code easier to understand.
*
* Example:
*
* #define BASE FilterGroup0
* #define USB_EVENTS FilterGroup1
* #define CAN_EVENTS FilterGroup2
*
* Note that filtering per event type (regardless of object) is also available
* in trcConfig.h.
******************************************************************************/
void vTraceSetFilterGroup(uint16_t filterGroup);
/******************************************************************************
* vTraceSetFilterMask
*
* Sets the "filter mask" that is used to filter the events by object. This can
* be used to reduce the trace data rate, i.e., if your streaming interface is
* a bottleneck or if you want longer snapshot traces without increasing the
* buffer size.
*
* Note: There are two kinds of filters in the recorder. The other filter type
* excludes all events of certain kinds (e.g., OS ticks). See trcConfig.h.
*
* The filtering is based on bitwise AND with the Filter Group ID, assigned
* to RTOS objects such as tasks, queues, semaphores and mutexes.
* This together with vTraceSetFilterGroup allows you to control what
* events that are recorded, based on the objects they refer to.
*
* See example for vTraceSetFilterGroup.
******************************************************************************/
void vTraceSetFilterMask(uint16_t filterMask);
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
@ -494,7 +577,6 @@ void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction);
* error. In that case, check xTraceGetLastError to get the error message.
* Any error message is also presented when opening a trace file.
*
*
* Snapshot mode only!
******************************************************************************/
uint32_t uiTraceStart(void);
@ -527,11 +609,7 @@ void vTraceClear(void);
/*** INTERNAL SNAPSHOT FUNCTIONS *********************************************/
/*****************************************************************************/
#undef INCLUDE_xTaskGetSchedulerState
#define INCLUDE_xTaskGetSchedulerState 1
#undef INCLUDE_xTaskGetCurrentTaskHandle
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define TRC_UNUSED
#ifndef TRC_CFG_INCLUDE_OBJECT_DELETE
#define TRC_CFG_INCLUDE_OBJECT_DELETE 0
@ -545,81 +623,104 @@ void vTraceClear(void);
#define TRC_CFG_INCLUDE_OSTICK_EVENTS 0
#endif
#define TRC_UNUSED
#if (TRC_CFG_INCLUDE_OBJECT_DELETE == 1)
/* This macro will remove the task and store it in the event buffer */
#undef trcKERNEL_HOOKS_TASK_DELETE
#define trcKERNEL_HOOKS_TASK_DELETE(SERVICE, pxTCB) \
prvTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, SUCCESS, CLASS, pxTCB), TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
prvTraceStoreObjectNameOnCloseEvent(TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
prvTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
prvTraceSetObjectState(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TASK_STATE_INSTANCE_NOT_ACTIVE); \
prvTraceFreeObjectHandle(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
#else /*(TRC_CFG_INCLUDE_OBJECT_DELETE == 1)*/
#undef trcKERNEL_HOOKS_TASK_DELETE
#define trcKERNEL_HOOKS_TASK_DELETE(SERVICE, pxTCB)
#endif /*(TRC_CFG_INCLUDE_OBJECT_DELETE == 1)*/
#if (TRC_CFG_INCLUDE_OBJECT_DELETE == 1)
/* This macro will remove the object and store it in the event buffer */
#undef trcKERNEL_HOOKS_OBJECT_DELETE
#define trcKERNEL_HOOKS_OBJECT_DELETE(SERVICE, CLASS, pxObject) \
prvTraceStoreKernelCall(TRACE_GET_OBJECT_EVENT_CODE(SERVICE, SUCCESS, CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
prvTraceStoreObjectNameOnCloseEvent(TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
prvTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
prvTraceFreeObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
#else /*TRC_CFG_INCLUDE_OBJECT_DELETE*/
#undef trcKERNEL_HOOKS_OBJECT_DELETE
#define trcKERNEL_HOOKS_OBJECT_DELETE(SERVICE, CLASS, pxObject)
#endif /*TRC_CFG_INCLUDE_OBJECT_DELETE*/
/* This macro will create a task in the object table */
#undef trcKERNEL_HOOKS_TASK_CREATE
#define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, CLASS, pxTCB) \
TRACE_SET_TASK_NUMBER(pxTCB) \
TRACE_SET_TASK_NUMBER(pxTCB); \
TRACE_SET_TASK_FILTER(pxTCB, CurrentFilterGroup); \
prvTraceSetObjectName(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_NAME(pxTCB)); \
prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
prvTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, SUCCESS, CLASS, pxTCB), TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
/* This macro will remove the task and store it in the event buffer */
#undef trcKERNEL_HOOKS_TASK_DELETE
#define trcKERNEL_HOOKS_TASK_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, pxTCB) \
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
prvTraceSetObjectState(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TASK_STATE_INSTANCE_NOT_ACTIVE); \
prvTraceFreeObjectHandle(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
/* This macro will create a failed create call to create a task */
#undef trcKERNEL_HOOKS_TASK_CREATE_FAILED
#define trcKERNEL_HOOKS_TASK_CREATE_FAILED(SERVICE, CLASS) \
prvTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, FAILED, CLASS, 0), TRACE_CLASS_TASK, 0);
/* This macro will setup a task in the object table */
#undef trcKERNEL_HOOKS_OBJECT_CREATE
#define trcKERNEL_HOOKS_OBJECT_CREATE(SERVICE, CLASS, pxObject)\
TRACE_SET_OBJECT_NUMBER(CLASS, pxObject);\
TRACE_SET_OBJECT_FILTER(CLASS, pxObject, CurrentFilterGroup); \
prvMarkObjectAsUsed(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));\
prvTraceStoreKernelCall(TRACE_GET_OBJECT_EVENT_CODE(SERVICE, SUCCESS, CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), 0);
/* This macro will create a failed create call to create an object */
#undef trcKERNEL_HOOKS_OBJECT_CREATE_FAILED
#define trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(SERVICE, CLASS, kernelClass) \
prvTraceStoreKernelCall(TRACE_GET_CLASS_EVENT_CODE(SERVICE, FAILED, CLASS, kernelClass), TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass), 0);
/* This macro will remove the object and store it in the event buffer */
#undef trcKERNEL_HOOKS_OBJECT_DELETE
#define trcKERNEL_HOOKS_OBJECT_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, CLASS, pxObject) \
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
prvTraceFreeObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
#undef trcKERNEL_HOOKS_KERNEL_SERVICE
#define trcKERNEL_HOOKS_KERNEL_SERVICE(SERVICE, RESULT, CLASS, pxObject) \
prvTraceStoreKernelCall(TRACE_GET_OBJECT_EVENT_CODE(SERVICE, RESULT, CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
#define trcKERNEL_HOOKS_KERNEL_SERVICE(SERVICE, CLASS, pxObject) \
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
#undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM
#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(SERVICE, CLASS, pxObject, param) \
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param);
/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
#undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY
#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(SERVICE, param) \
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param);
/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
#undef trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR
#define trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(SERVICE, CLASS, pxObject) \
if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
#undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR
#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(SERVICE, CLASS, pxObject, param) \
if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param);
/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
#undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR
#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR(SERVICE, param) \
prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param);
/* This macro will set the state for an object */
#undef trcKERNEL_HOOKS_SET_OBJECT_STATE
#define trcKERNEL_HOOKS_SET_OBJECT_STATE(CLASS, pxObject, STATE) \
prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), STATE);
prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint8_t)STATE);
/* This macro will flag a certain task as a finished instance */
#undef trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED
#define trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED() \
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
prvTraceSetTaskInstanceFinished(TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()));
#if (TRC_CFG_INCLUDE_READY_EVENTS == 1)
/* This macro will create an event to indicate that a task became Ready */
#undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE
#define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB) \
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
prvTraceStoreTaskReady(TRACE_GET_TASK_NUMBER(pxTCB));
#else /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/
#undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE
@ -629,7 +730,11 @@ void vTraceClear(void);
/* This macro will update the internal tick counter and call prvTracePortGetTimeStamp(0) to update the internal counters */
#undef trcKERNEL_HOOKS_INCREMENT_TICK
#define trcKERNEL_HOOKS_INCREMENT_TICK() \
{ extern uint32_t uiTraceTickCount; uiTraceTickCount++; prvTracePortGetTimeStamp(0); }
{ \
extern uint32_t uiTraceTickCount; \
uiTraceTickCount++; \
prvTracePortGetTimeStamp(0); \
}
#if (TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)
/* This macro will create an event indicating that the OS tick count has increased */
@ -644,48 +749,46 @@ void vTraceClear(void);
/* This macro will create a task switch event to the currently executing task */
#undef trcKERNEL_HOOKS_TASK_SWITCH
#define trcKERNEL_HOOKS_TASK_SWITCH( pxTCB ) \
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
prvTraceStoreTaskswitch(TRACE_GET_TASK_NUMBER(pxTCB));
/* This macro will create an event to indicate that the task has been suspended */
#undef trcKERNEL_HOOKS_TASK_SUSPEND
#define trcKERNEL_HOOKS_TASK_SUSPEND(SERVICE, pxTCB) \
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
prvTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB));
/* This macro will create an event to indicate that a task has called a wait/delay function */
#undef trcKERNEL_HOOKS_TASK_DELAY
#define trcKERNEL_HOOKS_TASK_DELAY(SERVICE, pxTCB, xValue) \
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
{ \
prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); \
prvTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB));
prvTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB)); \
}
/* This macro will create an event to indicate that a task has gotten its priority changed */
#undef trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE
#define trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(SERVICE, pxTCB, uxNewPriority) \
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
{ \
prvTraceStoreKernelCallWithParam(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), prvTraceGetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)));\
prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), (uint8_t)uxNewPriority);
prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), (uint8_t)uxNewPriority); \
}
/* This macro will create an event to indicate that the task has been resumed */
#undef trcKERNEL_HOOKS_TASK_RESUME
#define trcKERNEL_HOOKS_TASK_RESUME(SERVICE, pxTCB) \
if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
#undef trcKERNEL_HOOKS_TIMER_EVENT
#define trcKERNEL_HOOKS_TIMER_EVENT(SERVICE, pxTimer) \
prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));
/* This macro will create a timer in the object table and assign the timer a trace handle (timer number).*/
#undef trcKERNEL_HOOKS_TIMER_CREATE
#define trcKERNEL_HOOKS_TIMER_CREATE(SERVICE, pxTimer) \
TRACE_SET_TIMER_NUMBER(pxTimer); \
prvTraceSetObjectName(TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_GET_TIMER_NAME(pxTimer)); \
prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));
#undef trcKERNEL_HOOKS_TIMER_DELETE
#define trcKERNEL_HOOKS_TIMER_DELETE(SERVICE, pxTimer) \
prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer)); \
prvTraceStoreObjectNameOnCloseEvent(TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_CLASS_TIMER); \
prvTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_CLASS_TIMER); \
prvTraceFreeObjectHandle(TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));
#undef trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR
#define trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR(SERVICE, pxTCB) \
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
#if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1
void prvTraceSetReadyEventsEnabled(int status);
@ -725,15 +828,11 @@ void prvTraceSetObjectState(uint8_t objectclass, traceHandle id, uint8_t value);
void prvMarkObjectAsUsed(traceObjectClass objectclass, traceHandle handle);
#if (TRC_CFG_INCLUDE_OBJECT_DELETE == 1)
void prvTraceStoreObjectNameOnCloseEvent(traceHandle handle,
void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle,
traceObjectClass objectclass);
void prvTraceStoreObjectPropertiesOnCloseEvent(traceHandle handle,
void prvTraceStoreObjectPropertiesOnCloseEvent(uint8_t evtcode, traceHandle handle,
traceObjectClass objectclass);
#endif
/* Internal constants for task state */
#define TASK_STATE_INSTANCE_NOT_ACTIVE 0
@ -742,9 +841,6 @@ void prvTraceStoreObjectPropertiesOnCloseEvent(traceHandle handle,
#if (TRC_CFG_INCLUDE_ISR_TRACING == 0)
//void prvTraceIncreaseISRActive(void);
//void prvTraceDecreaseISRActive(void);
#undef vTraceSetISRProperties
#define vTraceSetISRProperties(handle, name, priority)
@ -824,12 +920,6 @@ void vTraceUBEvent(traceUBChannel channel);
#define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--;
#endif
/* Structure to handle the exclude flags for all objects and tasks. We add some extra objects since index 0 is not used for each object class. */
extern uint8_t trcExcludedObjects[(TRACE_KERNEL_OBJECT_COUNT + TRACE_NCLASSES) / 8 + 1];
/* Structure to handle the exclude flags for all event codes */
extern uint8_t trcExcludedEventCodes[NEventCodes / 8 + 1];
/******************************************************************************
* ObjectHandleStack
* This data-structure is used to provide a mechanism for 1-byte trace object
@ -838,6 +928,7 @@ extern uint8_t trcExcludedEventCodes[NEventCodes / 8 + 1];
* each object class active at any given moment. There can be more "historic"
* objects, that have been deleted - that number is only limited by the size of
* the symbol table.
*
* Note that handle zero (0) is not used, it is a code for an invalid handle.
*
* This data structure keeps track of the FREE handles, not the handles in use.
@ -851,7 +942,6 @@ extern uint8_t trcExcludedEventCodes[NEventCodes / 8 + 1];
* is not a valid handle, that is a signal of additional handles needed.
* If a zero is received when popping a new handle, it is replaced by the
* index of the popped handle instead.
*
*****************************************************************************/
typedef struct
{
@ -884,6 +974,7 @@ extern objectHandleStackType objectHandleStacks;
* represent the current state. If a property is changed during runtime, the OLD
* value should be stored in the trace buffer, not the new value (since the new
* value is found in the Object Property Table).
*
* For close events this mechanism is the old names are stored in the symbol
* table), for "priority set" (the old priority is stored in the event data)
* and for "isActive", where the value decides if the task switch event type
@ -927,7 +1018,7 @@ typedef struct
uint32_t nextFreeSymbolIndex;
/* Size rounded up to closest multiple of 4, to avoid alignment issues*/
uint8_t symbytes[4*((TRC_CFG_SYMBOL_TABLE_SIZE+3)/4)];
uint8_t symbytes[4*(((TRC_CFG_SYMBOL_TABLE_SIZE)+3)/4)];
/* Used for lookups - Up to 64 linked lists within the symbol table
connecting all entries with the same 6 bit checksum.
@ -1060,9 +1151,9 @@ typedef struct
uint8_t padding1;
uint8_t padding2;
uint8_t padding3;
ChannelFormatPair channels[TRC_CFG_UB_CHANNELS+1];
uint8_t channelBuffer[(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE + 3) & 0xFFFFFFFC]; /* 1 byte per slot, with padding for 4 byte alignment */
uint8_t dataBuffer[TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE * 4]; /* 4 bytes per slot */
ChannelFormatPair channels[(TRC_CFG_UB_CHANNELS)+1];
uint8_t channelBuffer[((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) + 3) & 0xFFFFFFFC]; /* 1 byte per slot, with padding for 4 byte alignment */
uint8_t dataBuffer[(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) * 4]; /* 4 bytes per slot */
} UserEventBuffer;
#endif
@ -1182,7 +1273,7 @@ typedef struct
int32_t debugMarker3;
/* The event data, in 4-byte records */
uint8_t eventData[ TRC_CFG_EVENT_BUFFER_SIZE * 4 ];
uint8_t eventData[ (TRC_CFG_EVENT_BUFFER_SIZE) * 4 ];
#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
UserEventBuffer userEventBuffer;
@ -1249,14 +1340,6 @@ RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclas
RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1]
#define TRACE_SET_FLAG_ISEXCLUDED(flags, bitIndex) flags[(bitIndex) >> 3] |= (1 << ((bitIndex) & 7))
#define TRACE_CLEAR_FLAG_ISEXCLUDED(flags, bitIndex) flags[(bitIndex) >> 3] &= (uint8_t)(~(1 << ((bitIndex) & 7)))
#define TRACE_GET_FLAG_ISEXCLUDED(flags, bitIndex) (flags[(bitIndex) >> 3] & (1 << ((bitIndex) & 7)))
#define TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_SET_FLAG_ISEXCLUDED(trcExcludedEventCodes, eventCode)
#define TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_CLEAR_FLAG_ISEXCLUDED(trcExcludedEventCodes, eventCode)
#define TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_GET_FLAG_ISEXCLUDED(trcExcludedEventCodes, eventCode)
/* DEBUG ASSERTS */
#if defined TRC_CFG_USE_TRACE_ASSERT && TRC_CFG_USE_TRACE_ASSERT != 0
#define TRACE_ASSERT(eval, msg, defRetVal) \
@ -1273,6 +1356,279 @@ if (!(eval)) \
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
/******************************************************************************
* Default values for STREAM PORT macros
*
* As a normal user, this is nothing you don't need to bother about. This is
* only important if you want to define your own custom streaming interface.
*
* You may override these in your own trcStreamingPort.h to create a custom
* stream port, and thereby stream the trace on any host-target interface.
* These default values are suitable for most cases, except the J-Link port.
******************************************************************************/
/******************************************************************************
* TRC_STREAM_PORT_USE_INTERNAL_BUFFER
*
* There are two kinds of stream ports, those that store the event to the
* internal buffer (with periodic flushing by the TzCtrl task) and those that
* write directly to the streaming interface. Most stream ports use the
* recorder's internal buffer, except for the SEGGER J-Link port (also uses a
* RAM buffer, but one defined in the SEGGER code).
*
* If the stream port (trcStreamingPort.h) defines this as zero (0), it is
* expected to transmit the data directly using TRC_STREAM_PORT_COMMIT_EVENT.
* Otherwise it is expected that the trace data is stored in the internal buffer
* and the TzCtrl task will then send the buffer pages when they become full.
******************************************************************************/
#ifndef TRC_STREAM_PORT_USE_INTERNAL_BUFFER
#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 1
#endif
/******************************************************************************
* TRC_STREAM_PORT_ON_TRACE_BEGIN
*
* Defining any actions needed in the stream port when the recording is activated.
*******************************************************************************/
#ifndef TRC_STREAM_PORT_ON_TRACE_BEGIN
#define TRC_STREAM_PORT_ON_TRACE_BEGIN() /* Do nothing */
#endif
/******************************************************************************
* TRC_STREAM_PORT_ON_TRACE_BEGIN
*
* Defining any actions needed in the stream port when the tracing stops.
* Empty by default.
*******************************************************************************/
#ifndef TRC_STREAM_PORT_ON_TRACE_END
#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */
#endif
/******************************************************************************
* TRC_STREAM_PORT_ALLOCATE_EVENT
*
* This macro is used to allocate memory for each event record, just before
* assigning the record fields.
* Depending on "TRC_STREAM_PORT_USE_INTERNAL_BUFFER", this either allocates
* space in the paged event buffer, or on the local stack. In the latter case,
* the COMMIT event is used to write the data to the streaming interface.
******************************************************************************/
#ifndef TRC_STREAM_PORT_ALLOCATE_EVENT
#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
#define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type* _ptrData; _ptrData = (_type*)prvPagedEventBufferGetWritePointer(_size);
#else
#define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type _tmpArray[_size / sizeof(_type)]; _type* _ptrData = _tmpArray;
#endif
#endif
/******************************************************************************
* TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT
*
* This macro is used to allocate memory for each event record, just before
* assigning the record fields.
* This has the same purpose as TRC_STREAM_PORT_ALLOCATE_EVENT and by default
* it has the same definition as TRC_STREAM_PORT_ALLOCATE_EVENT. This is used
* for events carrying variable-sized payload, such as strings.
* In the SEGGER RTT port, we need this in order to make a worst-case
* allocation on the stack.
******************************************************************************/
#ifndef TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT
#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
#define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) /* We do the same thing as for non-dynamic event sizes */
#else
#define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) _type _tmpArray[sizeof(largestEventType) / sizeof(_type)]; _type* _ptrData = _tmpArray;
#endif
#endif
/******************************************************************************
* TRC_STREAM_PORT_COMMIT_EVENT
*
* The COMMIT macro is used to write a single event record directly to the
* streaming inteface, without first storing the event in the internal buffer.
* This is currently only used in the SEGGER J-Link RTT port.
*
* This relies on the TRC_STREAM_PORT_WRITE_DATA macro, defined in by the
* stream port in trcStreamingPort.h. The COMMIT macro calls
* prvTraceWarning(TRC_STREAM_PORT_WRITE_DATA) if a non-zero value is returned
* from TRC_STREAM_PORT_WRITE_DATA. If zero (0) is returned, it is assumed
* that all data was successfully written.
*
* In ports using the internal buffer, this macro has no purpose as the events
* are written to the internal buffer instead. They are then flushed to the
* streaming interface in the TzCtrl task using TRC_STREAM_PORT_WRITE_DATA.
******************************************************************************/
#ifndef TRC_STREAM_PORT_COMMIT_EVENT
#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
#define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) /* Not used */
#else
#define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) \
{ \
if (TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, 0) != 0)\
prvTraceWarning(PSF_WARNING_STREAM_PORT_WRITE); \
}
#endif
#endif
/******************************************************************************
* TRC_STREAM_PORT_READ_DATA (defined in trcStreamingPort.h)
*
* Defining how to read data from host (commands from Tracealyzer).
*
* If there is no direct interface to host (e.g., if streaming to a file
* system) this should be defined as 0. Instead use vTraceEnable(TRC_START) and
* vTraceStop() to control the recording from target.
*
* Parameters:
*
* - _ptrData: a pointer to a data buffer, where the received data shall be
* stored (TracealyzerCommandType*).
*
* - _size: the number of bytes to read (int).
*
* - _ptrBytesRead: a pointer to an integer (int), that should be assigned
* with the number of bytes that was received.
*
* Example:
*
* int32_t myRead(void* ptrData, uint32_t size, int32_t* ptrBytesRead);
*
* #define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) \
* myRead(_ptrData, _size, _ptrBytesRead)
*
* Your "myRead" function should return 0 if successful, i.e. if at least some
* bytes were received. A non-zero value should be returned if the streaming
* interface returned an error (e.g. a closed socket), which results in the
* recorder calling prvTraceWarning with the error code
* PSF_WARNING_STREAM_PORT_WRITE.
*
* If developing your own custom stream port and using the default internal
* buffer, it is important that the _ptrBytesRead parameter is assigned
* correctly by "myRead", i.e. with the number of bytes actually written.
* Otherwise the data stream may get out of sync in case the streaming interface
* can't swallow all data at once.
******************************************************************************/
#ifndef TRC_STREAM_PORT_READ_DATA
#error "No definition for TRC_STREAM_PORT_READ_DATA (should be in trcStreamingPort.h)"
#endif
/******************************************************************************
* TRC_STREAM_PORT_WRITE_DATA (defined in trcStreamingPort.h)
*
* Defining how to write trace data to the streaming interface.
*
* Parameters:
*
* - _ptrData: a pointer (void*) to the data to write.
*
* - _size: the number of bytes to write (uint32_t).
*
* - _ptrBytesWritten: a pointer to an integer (int32_t), that should be
* assigned with the number of bytes actually written.
*
* Example:
*
* int32_t myWrite(void* ptrData, uint32_t size, int32_t* ptrBytesWritten);
*
* #define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) \
* myWrite(_ptrData, _size, _ptrBytesWritten)
*
* Your "myWrite" function should return 0 if successful, i.e. if at least some
* bytes were sent. A non-zero value should be returned if the streaming interface
* returned an error (e.g. a closed socket), which results in the recorder calling
* prvTraceWarning with the error code PSF_WARNING_STREAM_PORT_WRITE.
*
* If developing your own custom stream port and using the default internal
* buffer, it is important that the _ptrBytesWritten parameter is assigned
* correctly by "myWrite", i.e. with the number of bytes actually written.
* Otherwise the data stream may get out of sync in case the streaming interface
* can't swallow all data at once.
*
* Assuming TRC_STREAM_PORT_USE_INTERNAL_BUFFER is 1 (default), the TzCtrl task
* will use this macro to send one buffer page at a time. In case all data can't
* be written at once (if _ptrBytesWritten is less than _size), the TzCtrl task
* is smart enough to make repeated calls (with updated parameters) in order to
* send the remaining data.
*
* However, if TRC_STREAM_PORT_USE_INTERNAL_BUFFER is 0, this is used from the
* COMMIT macro, directly in the "event functions". In that case, the
* _ptrBytesWritten parameter will be NULL and should be ignored by the write
* function. In this case, it is assumed that all data can be sent in a single
* call, otherwise the write function should return a non-zero error code.
******************************************************************************/
#ifndef TRC_STREAM_PORT_WRITE_DATA
#error "No definition for TRC_STREAM_PORT_WRITE_DATA (should be in trcStreamingPort.h)"
#endif
/******************************************************************************
* Data structure declaration, depending on TRC_CFG_RECORDER_BUFFER_ALLOCATION
*******************************************************************************/
#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC)
/* Static allocation. */
/* If not defined in trcStreamingPort.h */
#ifndef TRC_STREAM_PORT_ALLOCATE_FIELDS
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() \
char _TzTraceData[(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
extern char _TzTraceData[(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
#endif
/* If not defined in trcStreamingPort.h */
#ifndef TRC_STREAM_PORT_MALLOC
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
#endif
#else
/* For Dynamic or Custom Allocation mode */
/* If not defined in trcStreamingPort.h */
#ifndef TRC_STREAM_PORT_ALLOCATE_FIELDS
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() char* _TzTraceData = NULL;
extern char* _TzTraceData;
#endif
/* If not defined in trcStreamingPort.h */
#ifndef TRC_STREAM_PORT_MALLOC
#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC)
#define TRC_STREAM_PORT_MALLOC() \
_TzTraceData = TRC_PORT_MALLOC((TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE));
extern char* _TzTraceData;
#else
#define TRC_STREAM_PORT_MALLOC() /* Custom allocation. Not used. */
#endif
#endif
#endif
#ifndef TRC_STREAM_PORT_INIT
#define TRC_STREAM_PORT_INIT() \
TRC_STREAM_PORT_MALLOC(); /* Empty if static allocation mode */ \
prvPagedEventBufferInit(_TzTraceData);
#endif
/* Signal an error. */
void prvTraceError(int errCode);
/* Signal an warning (does not stop the recorder). */
void prvTraceWarning(int errCode);
/******************************************************************************/
/*** ERROR AND WARNING CODES (check using xTraceGetLastError) *****************/
/******************************************************************************/
#define PSF_ERROR_NONE 0
#define PSF_ERROR_EVENT_CODE_TOO_LARGE 1
#define PSF_ERROR_ISR_NESTING_OVERFLOW 2
#define PSF_ERROR_DWT_NOT_SUPPORTED 3
#define PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED 4
#define PSF_ERROR_TZCTRLTASK_NOT_CREATED 5
#define PSF_WARNING_SYMBOL_TABLE_SLOTS 101
#define PSF_WARNING_SYMBOL_MAX_LENGTH 102
#define PSF_WARNING_OBJECT_DATA_SLOTS 103
#define PSF_WARNING_STRING_TOO_LONG 104
#define PSF_WARNING_STREAM_PORT_READ 105
#define PSF_WARNING_STREAM_PORT_WRITE 106
/******************************************************************************/
/*** INTERNAL STREAMING FUNCTIONS *********************************************/
/******************************************************************************/
@ -1320,10 +1676,7 @@ void prvPagedEventBufferInit(char* buffer);
void* prvPagedEventBufferGetWritePointer(int sizeOfEvent);
/* Transfer a full buffer page */
int32_t prvPagedEventBufferTransfer(int32_t(*writeFunc)(void* data, uint32_t size, int32_t* ptrBytesWritten), int32_t* nofBytes);
/* Resets the paged event buffer */
void prvPagedEventBufferReset(void);
uint32_t prvPagedEventBufferTransfer(void);
/* The data structure for commands (a bit overkill) */
typedef struct
@ -1344,6 +1697,7 @@ int prvIsValidCommand(TracealyzerCommandType* cmd);
/* Executed the received command (Start or Stop) */
void prvProcessCommand(TracealyzerCommandType* cmd);
#define vTraceSetStopHook(x)
#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
@ -1363,6 +1717,9 @@ void prvProcessCommand(TracealyzerCommandType* cmd);
#define vTraceChannelPrint(label)
#define vTraceUBData(label, ...)
#define vTraceSetFilterGroup(x)
#define vTraceSetFilterMask(x)
#define prvTraceSetReadyEventsEnabled(status)
#define vTraceExcludeTask(handle)
@ -1379,6 +1736,10 @@ void prvProcessCommand(TracealyzerCommandType* cmd);
#define TRC_ALLOC_CUSTOM_BUFFER(bufname)
#endif
#define xTraceIsRecordingEnabled() (0)
#define vTraceSetStopHook(x)
#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
#ifdef __cplusplus

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcConfig.h
@ -41,7 +41,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2016.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -99,6 +99,161 @@ extern "C" {
******************************************************************************/
#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_SNAPSHOT
/******************************************************************************
* TRC_CFG_FREERTOS_VERSION
*
* Specify what version of FreeRTOS that is used (don't change unless using the
* trace recorder library with an older version of FreeRTOS).
*
* TRC_FREERTOS_VERSION_7_3 If using FreeRTOS v7.3.x
* TRC_FREERTOS_VERSION_7_4 If using FreeRTOS v7.4.x
* TRC_FREERTOS_VERSION_7_5_OR_7_6 If using FreeRTOS v7.5.0 - v7.6.0
* TRC_FREERTOS_VERSION_8_X If using FreeRTOS v8.X.X
* TRC_FREERTOS_VERSION_9_0_0 If using FreeRTOS v9.0.0
* TRC_FREERTOS_VERSION_9_0_1 If using FreeRTOS v9.0.1
* TRC_FREERTOS_VERSION_9_0_2 If using FreeRTOS v9.0.2
* TRC_FREERTOS_VERSION_10_0_0 If using FreeRTOS v10.0.0 or later
*****************************************************************************/
#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_10_0_0
/*******************************************************************************
* TRC_CFG_SCHEDULING_ONLY
*
* Macro which should be defined as an integer value.
*
* If this setting is enabled (= 1), only scheduling events are recorded.
* If disabled (= 0), all events are recorded (unless filtered in other ways).
*
* Default value is 0 (= include additional events).
******************************************************************************/
#define TRC_CFG_SCHEDULING_ONLY 0
/******************************************************************************
* TRC_CFG_INCLUDE_MEMMANG_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* This controls if malloc and free calls should be traced. Set this to zero (0)
* to exclude malloc/free calls, or one (1) to include such events in the trace.
*
* Default value is 1.
*****************************************************************************/
#define TRC_CFG_INCLUDE_MEMMANG_EVENTS 1
/******************************************************************************
* TRC_CFG_INCLUDE_USER_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0), all code related to User Events is excluded in order
* to reduce code size. Any attempts of storing User Events are then silently
* ignored.
*
* User Events are application-generated events, like "printf" but for the
* trace log, generated using vTracePrint and vTracePrintF.
* The formatting is done on host-side, by Tracealyzer. User Events are
* therefore much faster than a console printf and can often be used
* in timing critical code without problems.
*
* Note: In streaming mode, User Events are used to provide error messages
* and warnings from the recorder (in case of incorrect configuration) for
* display in Tracealyzer. Disabling user events will also disable these
* warnings. You can however still catch them by calling xTraceGetLastError
* or by putting breakpoints in prvTraceError and prvTraceWarning.
*
* Default value is 1.
*****************************************************************************/
#define TRC_CFG_INCLUDE_USER_EVENTS 1
/*****************************************************************************
* TRC_CFG_INCLUDE_ISR_TRACING
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0), the code for recording Interrupt Service Routines is
* excluded, in order to reduce code size.
*
* Default value is 1.
*
* Note: tracing ISRs requires that you insert calls to vTraceStoreISRBegin
* and vTraceStoreISREnd in your interrupt handlers.
*****************************************************************************/
#define TRC_CFG_INCLUDE_ISR_TRACING 1
/*****************************************************************************
* TRC_CFG_INCLUDE_READY_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If one (1), events are recorded when tasks enter scheduling state "ready".
* This allows Tracealyzer to show the initial pending time before tasks enter
* the execution state, and present accurate response times.
* If zero (0), "ready events" are not created, which allows for recording
* longer traces in the same amount of RAM.
*
* Default value is 1.
*****************************************************************************/
#define TRC_CFG_INCLUDE_READY_EVENTS 1
/*****************************************************************************
* TRC_CFG_INCLUDE_OSTICK_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is one (1), events will be generated whenever the OS clock is
* increased. If zero (0), OS tick events are not generated, which allows for
* recording longer traces in the same amount of RAM.
*
* Default value is 1.
*****************************************************************************/
#define TRC_CFG_INCLUDE_OSTICK_EVENTS 1
/*****************************************************************************
* TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0), the trace will exclude any "event group" events.
*
* Default value is 0 (excluded) since dependent on event_groups.c
*****************************************************************************/
#define TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS 0
/*****************************************************************************
* TRC_CFG_INCLUDE_TIMER_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0), the trace will exclude any Timer events.
*
* Default value is 0 since dependent on timers.c
*****************************************************************************/
#define TRC_CFG_INCLUDE_TIMER_EVENTS 0
/*****************************************************************************
* TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0), the trace will exclude any "pending function call"
* events, such as xTimerPendFunctionCall().
*
* Default value is 0 since dependent on timers.c
*****************************************************************************/
#define TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS 0
/*******************************************************************************
* Configuration Macro: TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0), the trace will exclude any stream buffer or message
* buffer events.
*
* Default value is 0 since dependent on stream_buffer.c (new in FreeRTOS v10)
******************************************************************************/
#define TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS 0
/*******************************************************************************
* Configuration Macro: TRC_CFG_RECORDER_BUFFER_ALLOCATION
*
@ -117,19 +272,6 @@ extern "C" {
******************************************************************************/
#define TRC_CFG_RECORDER_BUFFER_ALLOCATION TRC_RECORDER_BUFFER_ALLOCATION_STATIC
/******************************************************************************
* TRC_CFG_FREERTOS_VERSION
*
* Specify what version of FreeRTOS that is used (don't change unless using the
* trace recorder library with an older version of FreeRTOS).
*
* TRC_FREERTOS_VERSION_7_3_OR_7_4 If using FreeRTOS v7.3.0 - v7.4.2
* TRC_FREERTOS_VERSION_7_5_OR_7_6 If using FreeRTOS v7.5.0 - v7.6.0
* TRC_FREERTOS_VERSION_8_X If using FreeRTOS v8.X.X
* TRC_FREERTOS_VERSION_9_X If using FreeRTOS v9.X.X
*****************************************************************************/
#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_9_X
/******************************************************************************
* TRC_CFG_MAX_ISR_NESTING
*

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcSnapshotConfig.h
@ -39,7 +39,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -69,22 +69,6 @@
*****************************************************************************/
#define TRC_CFG_SNAPSHOT_MODE TRC_SNAPSHOT_MODE_RING_BUFFER
/*******************************************************************************
* TRC_CFG_SCHEDULING_ONLY
*
* Macro which should be defined as an integer value.
*
* If this setting is enabled (= 1), only scheduling events are recorded.
* If disabled (= 0), all events are recorded.
*
* For users of Tracealyzer Free Edition, that only displays scheduling events, this
* option can be used to avoid storing other events.
*
* Default value is 0 (store all enabled events).
*
******************************************************************************/
#define TRC_CFG_SCHEDULING_ONLY 0
/*******************************************************************************
* TRC_CFG_EVENT_BUFFER_SIZE
*
@ -122,83 +106,15 @@
* check the actual usage by selecting View menu -> Trace Details ->
* Resource Usage -> Object Table.
******************************************************************************/
#define TRC_CFG_NTASK 10
#define TRC_CFG_NTASK 15
#define TRC_CFG_NISR 5
#define TRC_CFG_NQUEUE 10
#define TRC_CFG_NSEMAPHORE 10
#define TRC_CFG_NMUTEX 10
#define TRC_CFG_NTIMER 5
#define TRC_CFG_NEVENTGROUP 5
/******************************************************************************
* TRC_CFG_INCLUDE_MEMMANG_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* This controls if malloc and free calls should be traced. Set this to zero (0)
* to exclude malloc/free calls, or one (1) to include such events in the trace.
*
* Default value is 1.
*****************************************************************************/
#define TRC_CFG_INCLUDE_MEMMANG_EVENTS 1
/******************************************************************************
* TRC_CFG_INCLUDE_USER_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0) the code for creating User Events is excluded to
* reduce code size. User Events are application-generated events, like
* "printf" but for the trace log and the formatting is done offline, by the
* Tracealyzer visualization tool. User Events are much faster than a printf
* and can therefore be used in timing critical code.
*
* Default value is 1.
*****************************************************************************/
#define TRC_CFG_INCLUDE_USER_EVENTS 1
/*****************************************************************************
* TRC_CFG_INCLUDE_ISR_TRACING
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0), the code for recording Interrupt Service Routines is
* excluded, in order to reduce code size.
*
* Default value is 1.
*
* Note: tracing ISRs requires that you insert calls to vTraceStoreISRBegin
* and vTraceStoreISREnd in your interrupt handlers.
*****************************************************************************/
#define TRC_CFG_INCLUDE_ISR_TRACING 1
/*****************************************************************************
* TRC_CFG_INCLUDE_READY_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If one (1), events are recorded when tasks enter scheduling state "ready".
* This allows Tracealyzer to show the initial pending time before tasks enter
* the execution state, and present accurate response times.
* If zero (0), "ready events" are not created, which allows for recording
* longer traces in the same amount of RAM.
*
* Default value is 1.
*****************************************************************************/
#define TRC_CFG_INCLUDE_READY_EVENTS 1
/*****************************************************************************
* TRC_CFG_INCLUDE_OSTICK_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is one (1), events will be generated whenever the OS clock is
* increased. If zero (0), OS tick events are not generated, which allows for
* recording longer traces in the same amount of RAM.
*
* Default value is 0.
*****************************************************************************/
#define TRC_CFG_INCLUDE_OSTICK_EVENTS 0
#define TRC_CFG_NSTREAMBUFFER 5
#define TRC_CFG_NMESSAGEBUFFER 5
/******************************************************************************
* TRC_CFG_INCLUDE_FLOAT_SUPPORT
@ -218,19 +134,6 @@
*****************************************************************************/
#define TRC_CFG_INCLUDE_FLOAT_SUPPORT 0
/******************************************************************************
* TRC_CFG_INCLUDE_OBJECT_DELETE
*
* Macro which should be defined as either zero (0) or one (1).
*
* This must be enabled (1) if tasks, queues or other
* traced kernel objects are deleted at runtime. If no deletes are made, this
* can be set to 0 in order to exclude the delete-handling code.
*
* Default value is 1.
*****************************************************************************/
#define TRC_CFG_INCLUDE_OBJECT_DELETE 1
/*******************************************************************************
* TRC_CFG_SYMBOL_TABLE_SIZE
*
@ -265,6 +168,8 @@
#define TRC_CFG_NAME_LEN_MUTEX 15
#define TRC_CFG_NAME_LEN_TIMER 15
#define TRC_CFG_NAME_LEN_EVENTGROUP 15
#define TRC_CFG_NAME_LEN_STREAMBUFFER 15
#define TRC_CFG_NAME_LEN_MESSAGEBUFFER 15
/******************************************************************************
*** ADVANCED SETTINGS ********************************************************

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcStreamingConfig.h
@ -39,7 +39,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -57,7 +57,7 @@ extern "C" {
* - Task names
* - Named ISRs (vTraceSetISRProperties)
* - Named kernel objects (vTraceStoreKernelObjectName)
* - User event channels (vTraceStoreUserEventChannelName)
* - User event channels (xTraceRegisterString)
*
* If this value is too small, not all symbol names will be stored and the
* trace display will be affected. In that case, there will be warnings
@ -72,7 +72,7 @@ extern "C" {
* - Task names
* - Named ISRs (vTraceSetISRProperties)
* - Named kernel objects (vTraceStoreKernelObjectName)
* - User event channel names (vTraceStoreUserEventChannelName)
* - User event channel names (xTraceRegisterString)
*
* If longer symbol names are used, they will be truncated by the recorder,
* which will affect the trace display. In that case, there will be warnings
@ -123,7 +123,7 @@ extern "C" {
* Specifies the number of pages used by the paged event buffer.
* This may need to be increased if there are a lot of missed events.
*
* Note: not used by the J-Link RTT stream port (see SEGGER_RTT_Conf.h instead)
* Note: not used by the J-Link RTT stream port (see trcStreamingPort.h instead)
******************************************************************************/
#define TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT 2
@ -134,7 +134,7 @@ extern "C" {
* to match any internal low-level buffers used by the streaming interface, like
* the Ethernet MTU (Maximum Transmission Unit).
*
* Note: not used by the J-Link RTT stream port (see SEGGER_RTT_Conf.h instead)
* Note: not used by the J-Link RTT stream port (see trcStreamingPort.h instead)
******************************************************************************/
#define TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE 2500

View file

@ -0,0 +1,52 @@
/************************************************************
* Percepio Tracealyzer - ITM Trace Exporter for Keil uVision
* Copyright (c) 2018, Percepio AB.
* https://percepio.com
************************************************************/
FUNC void tzSetEnable(int enable)
{
if (enable == 1)
{
printf("Starting Tracealyzer recorder\n");
// Forward the ITM data to file
exec("ITMLOG 1 > .\\tracealyzer.psf");
// Send start command to Tracealyzer (not required if using vTraceEnable(TRC_START))
exec("E CHAR tz_host_command_data = 1, 1, 0, 0, 0, 0, 0xFD, 0xFF");
exec("tz_host_command_bytes_to_read = 8");
}
else if (enable == 0)
{
printf("Stopping Tracealyzer recorder...\n");
// Send stop command to Tracealyzer, to stop writing ITM data.
exec("E CHAR tz_host_command_data = 1, 0, 0, 0, 0, 0, 0xFE, 0xFF");
exec("tz_host_command_bytes_to_read = 8");
_sleep_(2000); // Wait a while to let all data be written the host file.
// Stop forwarding the ITM data to file and close the file.
exec("ITMLOG 1 OFF");
printf("Tracealyzer recorder stopped.\n");
}
else printf("Usage: tzSetEnable(0 or 1), where 0 is disable (stops recorder) and 1 enable (starts recording)");
}
// The Tracealyzer ITM stream port for Keil µVision can be used in two ways.
//
// 1. Start tracing directly from startup.
// Make sure tzSetEnable(1) is called below and vTraceEnable(TRC_START) in your target startup.
//
// 2. Start the trace manually, using the "Start Recording" button in Keil µVision.
// In this case, comment out the below call to tzSetEnable and make sure you call vTraceEnable(TRC_INIT) in your target startup (not TRC_START).
tzSetEnable(1);
DEFINE BUTTON "Start Recording", "tzSetEnable(1)";
DEFINE BUTTON "Stop Recording", "tzSetEnable(0)";

View file

@ -0,0 +1,28 @@
Tracealyzer Stream Port for ARM Cortex-M ITM
--------------------------------------------
2018-05-04
This directory contains a "stream port" for the Tracealyzer recorder library,
i.e., the specific code needed to use a particular interface for streaming a
Tracealyzer RTOS trace. The stream port is defined by a set of macros in
trcStreamingPort.h, found in the "include" directory.
This particular stream port targets ARM's ITM interface, which together with
a fast debug probe such as a Keil ULINKpro or ULINKplus provides excellent
performance. This stream port does not use any RAM buffer for the trace, but
writes the data directly to the ITM registers. This is very fast.
To setup Keil uVision for ITM tracing with a Keil ULINKpro (or ULINKplus),
see Percepio Application Note PA-021 https://percepio.com/2018/05/04/keil-itm-support/
Learning more:
- Tracealyzer User Manual (Help -> User Manual)
- https://percepio.com/gettingstarted
- Percepio Application Note PA-021 https://percepio.com/2018/05/04/keil-itm-support/
- About ITM trace, https://percepio.com/2016/06/09/arm-itm/
- About the recorder and custom streaming, http://percepio.com/2016/10/05/rtos-tracing
For questions, please contact support@percepio.com
Percepio AB
www.percepio.com

View file

@ -0,0 +1,91 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcStreamingPort.h
*
* The interface definitions for trace streaming ("stream ports").
* This "stream port" sets up the recorder to use ARM ITM as streaming channel.
*
* Terms of Use
* This file is part of the trace recorder library (RECORDER), which is the
* intellectual property of Percepio AB (PERCEPIO) and provided under a
* license as follows.
* The RECORDER may be used free of charge for the purpose of recording data
* intended for analysis in PERCEPIO products. It may not be used or modified
* for other purposes without explicit permission from PERCEPIO.
* You may distribute the RECORDER in its original source code form, assuming
* this text (terms of use, disclaimer, copyright notice) is unchanged. You are
* allowed to distribute the RECORDER with minor modifications intended for
* configuration or porting of the RECORDER, e.g., to allow using it on a
* specific processor, processor family or with a specific communication
* interface. Any such modifications should be documented directly below
* this comment block.
*
* Disclaimer
* The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
* as to its use or performance. PERCEPIO does not and cannot warrant the
* performance or results you may obtain by using the RECORDER or documentation.
* PERCEPIO make no warranties, express or implied, as to noninfringement of
* third party rights, merchantability, or fitness for any particular purpose.
* In no event will PERCEPIO, its technology partners, or distributors be liable
* to you for any consequential, incidental or special damages, including any
* lost profits or lost savings, even if a representative of PERCEPIO has been
* advised of the possibility of such damages, or for any claim by any third
* party. Some jurisdictions do not allow the exclusion or limitation of
* incidental, consequential or special damages, or the exclusion of implied
* warranties or limitations on how long an implied warranty may last, so the
* above limitations may not apply to you.
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
#ifndef TRC_STREAMING_PORT_H
#define TRC_STREAMING_PORT_H
#ifdef __cplusplus
extern "C" {
#endif
int32_t itm_write(void* ptrData, uint32_t size, int32_t* ptrBytesWritten);
int32_t read_from_host(void* ptrData, uint32_t size, int32_t* ptrBytesRead);
/*******************************************************************************
* TRC_CFG_ITM_PORT
*
* Possible values: 0 - 31
*
* What ITM port to use for the ITM software events. Make sure the IDE is
* configured for the same channel.
*
* Default: 1 (0 is typically terminal output and 31 is used by Keil)
*
******************************************************************************/
#define TRC_CFG_ITM_PORT 1
#if (TRC_CFG_ITM_PORT < 0) || (TRC_CFG_ITM_PORT > 31)
#error "Bad ITM port selected."
#endif
// Not used for ITM - no RAM buffer...
#define TRC_STREAM_PORT_ALLOCATE_FIELDS()
// Not used for ITM - assume the IDE configures the ITM setup
#define TRC_STREAM_PORT_INIT()
/* Important for the ITM port - no RAM buffer, direct writes. In most other ports this can be skipped (default is 1) */
#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 0
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) itm_write(_ptrData, _size, _ptrBytesWritten)
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) read_from_host(_ptrData, _size, _ptrBytesRead)
#ifdef __cplusplus
}
#endif
#endif /* TRC_STREAMING_PORT_H */

View file

@ -0,0 +1,71 @@
#include "trcRecorder.h"
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
static void itm_write_32(uint32_t data);
volatile int32_t tz_host_command_bytes_to_read = 0; // This is set by the Tracealyzer host application (to the number of bytes written), after having written to tz_host_commands. Set to zero by the read function after the message in tz_host_commands has been read.
volatile char tz_host_command_data[32];
/* This reads "command" data from a RAM buffer, written by a host macro in the debugger */
int32_t read_from_host(void* ptrData, uint32_t size, int32_t* ptrBytesRead)
{
if ( tz_host_command_bytes_to_read > 0)
{
int i;
uint8_t * bytesBuffer = (uint8_t*) ptrData;
if (ptrBytesRead != NULL)
*ptrBytesRead = (int32_t)tz_host_command_bytes_to_read;
if (tz_host_command_bytes_to_read != size)
{
return -1;
}
for (i=0; i < tz_host_command_bytes_to_read; i++)
{
bytesBuffer[i] = tz_host_command_data[i];
}
tz_host_command_bytes_to_read = 0;
}
return 0;
}
static void itm_write_32(uint32_t data)
{
if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) && // Trace enabled
(ITM->TCR & ITM_TCR_ITMENA_Msk) && // ITM enabled
(ITM->TER & (1UL << 0))) // ITM Port #0 enabled
{
while (ITM->PORT[TRC_CFG_ITM_PORT].u32 == 0); // Block until room in ITM FIFO - This stream port is always in "blocking mode", since intended for high-speed ITM!
ITM->PORT[TRC_CFG_ITM_PORT].u32 = data; // Write the data
}
}
/* This is assumed to execute from within the recorder, with interrupts disabled */
int32_t itm_write(void* ptrData, uint32_t size, int32_t* ptrBytesWritten)
{
uint32_t bytesWritten = 0;
uint32_t* ptr32 = (uint32_t*)ptrData;
if (size % 4 != 0) return -2;
while(bytesWritten < size)
{
itm_write_32(*ptr32);
ptr32++;
bytesWritten += 4;
}
*ptrBytesWritten = bytesWritten;
return 0;
}
#endif
#endif

View file

@ -0,0 +1,19 @@
Tracealyzer Stream Port for Files
-------------------------------------------------
This directory contains a "stream port" for the Tracealyzer recorder library,
i.e., the specific code needed to use a particular interface for streaming a
Tracealyzer RTOS trace. The stream port is defined by a set of macros in
trcStreamingPort.h, found in the "include" directory.
This particular stream port is for streaming to a file via stdio.h (fwrite).
To use this stream port, make sure that include/trcStreamingPort.h is found
by the compiler (i.e., add this folder to your project's include paths) and
add all included source files to your build. Make sure no other versions of
trcStreamingPort.h are included by mistake!
See also http://percepio.com/2016/10/05/rtos-tracing.
Percepio AB
www.percepio.com

View file

@ -0,0 +1,87 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcStreamingPort.h
*
* The interface definitions for trace streaming ("stream ports").
* This "stream port" sets up the recorder to stream the trace to file.
*
* Terms of Use
* This file is part of the trace recorder library (RECORDER), which is the
* intellectual property of Percepio AB (PERCEPIO) and provided under a
* license as follows.
* The RECORDER may be used free of charge for the purpose of recording data
* intended for analysis in PERCEPIO products. It may not be used or modified
* for other purposes without explicit permission from PERCEPIO.
* You may distribute the RECORDER in its original source code form, assuming
* this text (terms of use, disclaimer, copyright notice) is unchanged. You are
* allowed to distribute the RECORDER with minor modifications intended for
* configuration or porting of the RECORDER, e.g., to allow using it on a
* specific processor, processor family or with a specific communication
* interface. Any such modifications should be documented directly below
* this comment block.
*
* Disclaimer
* The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
* as to its use or performance. PERCEPIO does not and cannot warrant the
* performance or results you may obtain by using the RECORDER or documentation.
* PERCEPIO make no warranties, express or implied, as to noninfringement of
* third party rights, merchantability, or fitness for any particular purpose.
* In no event will PERCEPIO, its technology partners, or distributors be liable
* to you for any consequential, incidental or special damages, including any
* lost profits or lost savings, even if a representative of PERCEPIO has been
* advised of the possibility of such damages, or for any claim by any third
* party. Some jurisdictions do not allow the exclusion or limitation of
* incidental, consequential or special damages, or the exclusion of implied
* warranties or limitations on how long an implied warranty may last, so the
* above limitations may not apply to you.
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
#ifndef TRC_STREAMING_PORT_H
#define TRC_STREAMING_PORT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
int32_t writeToFile(void* data, uint32_t size, int32_t *ptrBytesWritten);
void closeFile(void);
void openFile(char* fileName);
/* This define will determine whether to use the internal PagedEventBuffer or not.
If file writing creates additional trace events (i.e. it uses semaphores or mutexes),
then the paged event buffer must be enabled to avoid infinite recursion. */
#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 1
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) 0 /* Does not read commands from Tz (yet) */
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) writeToFile(_ptrData, _size, _ptrBytesSent)
#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC)
#define TRC_STREAM_PORT_MALLOC() \
_TzTraceData = TRC_PORT_MALLOC((TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE));
extern char* _TzTraceData;
#else
#define TRC_STREAM_PORT_MALLOC() /* Custom or static allocation. Not used. */
#endif
#define TRC_STREAM_PORT_INIT() \
TRC_STREAM_PORT_MALLOC(); \
openFile("trace.psf")
#define TRC_STREAM_PORT_ON_TRACE_END() closeFile()
#ifdef __cplusplus
}
#endif
#endif /* TRC_STREAMING_PORT_H */

View file

@ -0,0 +1,103 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcStreamingPort.c
*
* Supporting functions for trace streaming, used by the "stream ports"
* for reading and writing data to the interface.
* Existing ports can easily be modified to fit another setup, e.g., a
* different TCP/IP stack, or to define your own stream port.
*
* Terms of Use
* This file is part of the trace recorder library (RECORDER), which is the
* intellectual property of Percepio AB (PERCEPIO) and provided under a
* license as follows.
* The RECORDER may be used free of charge for the purpose of recording data
* intended for analysis in PERCEPIO products. It may not be used or modified
* for other purposes without explicit permission from PERCEPIO.
* You may distribute the RECORDER in its original source code form, assuming
* this text (terms of use, disclaimer, copyright notice) is unchanged. You are
* allowed to distribute the RECORDER with minor modifications intended for
* configuration or porting of the RECORDER, e.g., to allow using it on a
* specific processor, processor family or with a specific communication
* interface. Any such modifications should be documented directly below
* this comment block.
*
* Disclaimer
* The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
* as to its use or performance. PERCEPIO does not and cannot warrant the
* performance or results you may obtain by using the RECORDER or documentation.
* PERCEPIO make no warranties, express or implied, as to noninfringement of
* third party rights, merchantability, or fitness for any particular purpose.
* In no event will PERCEPIO, its technology partners, or distributors be liable
* to you for any consequential, incidental or special damages, including any
* lost profits or lost savings, even if a representative of PERCEPIO has been
* advised of the possibility of such damages, or for any claim by any third
* party. Some jurisdictions do not allow the exclusion or limitation of
* incidental, consequential or special damages, or the exclusion of implied
* warranties or limitations on how long an implied warranty may last, so the
* above limitations may not apply to you.
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
#include "trcRecorder.h"
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
FILE* traceFile = NULL;
void openFile(char* fileName)
{
if (traceFile == NULL)
{
errno_t err = fopen_s(&traceFile, fileName, "wb");
if (err != 0)
{
printf("Could not open trace file, error code %d.\n", err);
exit(-1);
}
else {
printf("Trace file created.\n");
}
}
}
int32_t writeToFile(void* data, uint32_t size, int32_t *ptrBytesWritten)
{
int32_t written = 0;
if (traceFile != NULL)
{
written = fwrite(data, 1, size, traceFile);
}
else
{
written = 0;
}
if (ptrBytesWritten != 0)
*ptrBytesWritten = written;
if ((int32_t)size == written)
return 0;
else
return -1;
}
void closeFile(void)
{
if (traceFile != NULL)
{
fclose(traceFile);
traceFile = NULL;
printf("Trace file closed.\n");
}
}
#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/

View file

@ -1,505 +0,0 @@
/*********************************************************************
* SEGGER MICROCONTROLLER GmbH & Co. KG *
* Solutions for real time microcontroller applications *
**********************************************************************
* *
* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
* *
* SEGGER RTT * Real Time Transfer for embedded targets *
* *
**********************************************************************
* *
* All rights reserved. *
* *
* * This software may in its unmodified form be freely redistributed *
* in source, linkable, or executable form. *
* * The source code may be modified, provided the source code *
* retains the above copyright notice, this list of conditions and *
* the following disclaimer. *
* * Modified versions of this software in source, executable, or *
* linkable form may not be distributed without prior consent of *
* SEGGER. *
* * This software may only be used for communication with SEGGER *
* J-Link debug probes. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
* DAMAGE. *
* *
**********************************************************************
* *
* RTT version: 6.00e *
* *
**********************************************************************
---------------------------END-OF-HEADER------------------------------
File : SEGGER_RTT_printf.c
Purpose : Replacement for printf to write formatted data via RTT
Revision: $Rev: 3667 $
----------------------------------------------------------------------
*/
#include "SEGGER_RTT.h"
#include "SEGGER_RTT_Conf.h"
/*********************************************************************
*
* Defines, configurable
*
**********************************************************************
*/
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
#endif
#include <stdlib.h>
#include <stdarg.h>
#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0)
#define FORMAT_FLAG_PAD_ZERO (1u << 1)
#define FORMAT_FLAG_PRINT_SIGN (1u << 2)
#define FORMAT_FLAG_ALTERNATE (1u << 3)
/*********************************************************************
*
* Types
*
**********************************************************************
*/
typedef struct {
char* pBuffer;
unsigned BufferSize;
unsigned Cnt;
int ReturnValue;
unsigned RTTBufferIndex;
} SEGGER_RTT_PRINTF_DESC;
/*********************************************************************
*
* Function prototypes
*
**********************************************************************
*/
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
/*********************************************************************
*
* _StoreChar
*/
static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) {
unsigned Cnt;
Cnt = p->Cnt;
if ((Cnt + 1u) <= p->BufferSize) {
*(p->pBuffer + Cnt) = c;
p->Cnt = Cnt + 1u;
p->ReturnValue++;
}
//
// Write part of string, when the buffer is full
//
if (p->Cnt == p->BufferSize) {
if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
p->ReturnValue = -1;
} else {
p->Cnt = 0u;
}
}
}
/*********************************************************************
*
* _PrintUnsigned
*/
static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
unsigned Div;
unsigned Digit;
unsigned Number;
unsigned Width;
char c;
Number = v;
Digit = 1u;
//
// Get actual field width
//
Width = 1u;
while (Number >= Base) {
Number = (Number / Base);
Width++;
}
if (NumDigits > Width) {
Width = NumDigits;
}
//
// Print leading chars if necessary
//
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
if (FieldWidth != 0u) {
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
c = '0';
} else {
c = ' ';
}
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
FieldWidth--;
_StoreChar(pBufferDesc, c);
if (pBufferDesc->ReturnValue < 0) {
break;
}
}
}
}
if (pBufferDesc->ReturnValue >= 0) {
//
// Compute Digit.
// Loop until Digit has the value of the highest digit required.
// Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
//
while (1) {
if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
NumDigits--;
} else {
Div = v / Digit;
if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done
break;
}
}
Digit *= Base;
}
//
// Output digits
//
do {
Div = v / Digit;
v -= Div * Digit;
_StoreChar(pBufferDesc, _aV2C[Div]);
if (pBufferDesc->ReturnValue < 0) {
break;
}
Digit /= Base;
} while (Digit);
//
// Print trailing spaces if necessary
//
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
if (FieldWidth != 0u) {
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
FieldWidth--;
_StoreChar(pBufferDesc, ' ');
if (pBufferDesc->ReturnValue < 0) {
break;
}
}
}
}
}
}
/*********************************************************************
*
* _PrintInt
*/
static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
unsigned Width;
int Number;
Number = (v < 0) ? -v : v;
//
// Get actual field width
//
Width = 1u;
while (Number >= (int)Base) {
Number = (Number / (int)Base);
Width++;
}
if (NumDigits > Width) {
Width = NumDigits;
}
if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
FieldWidth--;
}
//
// Print leading spaces if necessary
//
if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
if (FieldWidth != 0u) {
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
FieldWidth--;
_StoreChar(pBufferDesc, ' ');
if (pBufferDesc->ReturnValue < 0) {
break;
}
}
}
}
//
// Print sign if necessary
//
if (pBufferDesc->ReturnValue >= 0) {
if (v < 0) {
v = -v;
_StoreChar(pBufferDesc, '-');
} else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
_StoreChar(pBufferDesc, '+');
} else {
}
if (pBufferDesc->ReturnValue >= 0) {
//
// Print leading zeros if necessary
//
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
if (FieldWidth != 0u) {
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
FieldWidth--;
_StoreChar(pBufferDesc, '0');
if (pBufferDesc->ReturnValue < 0) {
break;
}
}
}
}
if (pBufferDesc->ReturnValue >= 0) {
//
// Print number without sign
//
_PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
}
}
}
}
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* SEGGER_RTT_vprintf
*
* Function description
* Stores a formatted string in SEGGER RTT control block.
* This data is read by the host.
*
* Parameters
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
* sFormat Pointer to format string
* pParamList Pointer to the list of arguments for the format string
*
* Return values
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
* < 0: Error
*/
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
char c;
SEGGER_RTT_PRINTF_DESC BufferDesc;
int v;
unsigned NumDigits;
unsigned FormatFlags;
unsigned FieldWidth;
char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
BufferDesc.pBuffer = acBuffer;
BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE;
BufferDesc.Cnt = 0u;
BufferDesc.RTTBufferIndex = BufferIndex;
BufferDesc.ReturnValue = 0;
do {
c = *sFormat;
sFormat++;
if (c == 0u) {
break;
}
if (c == '%') {
//
// Filter out flags
//
FormatFlags = 0u;
v = 1;
do {
c = *sFormat;
switch (c) {
case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break;
case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break;
case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break;
default: v = 0; break;
}
} while (v);
//
// filter out field with
//
FieldWidth = 0u;
do {
c = *sFormat;
if ((c < '0') || (c > '9')) {
break;
}
sFormat++;
FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
} while (1);
//
// Filter out precision (number of digits to display)
//
NumDigits = 0u;
c = *sFormat;
if (c == '.') {
sFormat++;
do {
c = *sFormat;
if ((c < '0') || (c > '9')) {
break;
}
sFormat++;
NumDigits = NumDigits * 10u + ((unsigned)c - '0');
} while (1);
}
//
// Filter out length modifier
//
c = *sFormat;
do {
if ((c == 'l') || (c == 'h')) {
sFormat++;
c = *sFormat;
} else {
break;
}
} while (1);
//
// Handle specifiers
//
switch (c) {
case 'c': {
char c0;
v = va_arg(*pParamList, int);
c0 = (char)v;
_StoreChar(&BufferDesc, c0);
break;
}
case 'd':
v = va_arg(*pParamList, int);
_PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
break;
case 'u':
v = va_arg(*pParamList, int);
_PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
break;
case 'x':
case 'X':
v = va_arg(*pParamList, int);
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
break;
case 's':
{
const char * s = va_arg(*pParamList, const char *);
do {
c = *s;
s++;
if (c == '\0') {
break;
}
_StoreChar(&BufferDesc, c);
} while (BufferDesc.ReturnValue >= 0);
}
break;
case 'p':
v = va_arg(*pParamList, int);
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
break;
case '%':
_StoreChar(&BufferDesc, '%');
break;
default:
break;
}
sFormat++;
} else {
_StoreChar(&BufferDesc, c);
}
} while (BufferDesc.ReturnValue >= 0);
if (BufferDesc.ReturnValue > 0) {
//
// Write remaining data, if any
//
if (BufferDesc.Cnt != 0u) {
SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
}
BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
}
return BufferDesc.ReturnValue;
}
/*********************************************************************
*
* SEGGER_RTT_printf
*
* Function description
* Stores a formatted string in SEGGER RTT control block.
* This data is read by the host.
*
* Parameters
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
* sFormat Pointer to format string, followed by the arguments for conversion
*
* Return values
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
* < 0: Error
*
* Notes
* (1) Conversion specifications have following syntax:
* %[flags][FieldWidth][.Precision]ConversionSpecifier
* (2) Supported flags:
* -: Left justify within the field width
* +: Always print sign extension for signed conversions
* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
* Supported conversion specifiers:
* c: Print the argument as one char
* d: Print the argument as a signed integer
* u: Print the argument as an unsigned integer
* x: Print the argument as an hexadecimal integer
* s: Print the string pointed to by the argument
* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)
*/
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) {
int r;
va_list ParamList;
va_start(ParamList, sFormat);
r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
va_end(ParamList);
return r;
}
/*************************** End of file ****************************/

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcStreamingPort.h
@ -7,6 +7,11 @@
* The interface definitions for trace streaming ("stream ports").
* This "stream port" sets up the recorder to use SEGGER RTT as streaming channel.
*
* Note that this stream port is more complex than the typical case, since
* the J-Link interface uses a separate RAM buffer in SEGGER_RTT.c, instead
* of the default buffer included in the recorder core. The other stream ports
* offer more typical examples of how to define a custom streaming interface.
*
* Terms of Use
* This file is part of the trace recorder library (RECORDER), which is the
* intellectual property of Percepio AB (PERCEPIO) and provided under a
@ -39,7 +44,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -113,17 +118,18 @@ extern "C" {
* internal RAM buffer read by the J-Link probes during execution.
*
* Possible values:
* - SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (default)
* - SEGGER_RTT_MODE_NO_BLOCK_SKIP
* - SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
* - SEGGER_RTT_MODE_NO_BLOCK_SKIP (default)
*
* We recommend using SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL, to ensure you get a
* Using SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL ensure that you get a
* complete and valid trace. This may however cause blocking if your streaming
* interface isn't fast enough, which may disturb the real-time behavior.
* We therefore recommend to try SEGGER_RTT_MODE_NO_BLOCK_SKIP as well.
* In this mode, Tracealyzer will report lost events if the transfer is not
*
* We therefore recommend SEGGER_RTT_MODE_NO_BLOCK_SKIP. In this mode,
* Tracealyzer will report lost events if the transfer is not
* fast enough. In that case, try increasing the size of the "up buffer".
******************************************************************************/
#define TRC_CFG_RTT_MODE SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
#define TRC_CFG_RTT_MODE SEGGER_RTT_MODE_NO_BLOCK_SKIP
#include "SEGGER_RTT_Conf.h"
#include "SEGGER_RTT.h"
@ -140,22 +146,18 @@ extern "C" {
#if TRC_CFG_RTT_UP_BUFFER_INDEX == 0
#define TRC_RTT_ALLOC_UP() static char* _TzTraceData = NULL; /* Not actually used. Ignore allocation method. */
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) /* Only for custom allocation */
#else
#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC
#define TRC_RTT_ALLOC_UP() char _TzTraceData[TRC_CFG_RTT_BUFFER_SIZE_UP]; /* Static allocation */
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) /* Only for custom allocation */
#endif
#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC
#define TRC_RTT_ALLOC_UP() char* _TzTraceData = NULL; /* Dynamic allocation */
#define TRC_STREAM_PORT_MALLOC() _TzTraceData = TRC_PORT_MALLOC(TRC_CFG_RTT_BUFFER_SIZE_UP);
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) /* Only for custom allocation */
#endif
#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM
#define TRC_RTT_ALLOC_UP() char* _TzTraceData = NULL; /* Custom allocation, user needs to call vTraceSetRecorderDataBuffer before vTraceEnable, to assign this */
#define TRC_STREAM_PORT_MALLOC() /* Not used in custom mode */
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) char bufname [TRC_CFG_RTT_BUFFER_SIZE_UP]; /* Not static in this case, since declared in user code */
#endif
#endif
@ -170,20 +172,22 @@ extern "C" {
TRC_RTT_ALLOC_UP() /* Macro that will result in proper UP buffer allocation */ \
TRC_RTT_ALLOC_DOWN() /* Macro that will result in proper DOWN buffer allocation */
int32_t readFromRTT(void* ptrData, uint32_t size, int32_t* ptrBytesRead);
int32_t writeToRTT(void* ptrData, uint32_t size, int32_t* ptrBytesWritten);
#define TRC_STREAM_PORT_INIT() \
TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */ \
SEGGER_RTT_ConfigUpBuffer(TRC_CFG_RTT_UP_BUFFER_INDEX, "TzData", _TzTraceData, TRC_CFG_RTT_BUFFER_SIZE_UP, TRC_CFG_RTT_MODE ); \
SEGGER_RTT_ConfigDownBuffer(TRC_CFG_RTT_DOWN_BUFFER_INDEX, "TzCtrl", _TzCtrlData, TRC_CFG_RTT_BUFFER_SIZE_DOWN, TRC_CFG_RTT_MODE);
#define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type _tmpArray[_size / sizeof(_type)]; _type* _ptrData = _tmpArray;
#define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) _type _tmpArray[sizeof(largestEventType) / sizeof(_type)]; _type* _ptrData = _tmpArray;
#define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) SEGGER_RTT_Write(TRC_CFG_RTT_UP_BUFFER_INDEX, (const char*)_ptrData, _size);
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) if (SEGGER_RTT_HASDATA(TRC_CFG_RTT_DOWN_BUFFER_INDEX)) *_ptrBytesRead = (int)SEGGER_RTT_Read(TRC_CFG_RTT_DOWN_BUFFER_INDEX, (char*)_ptrData, _size);
#define TRC_STREAM_PORT_PERIODIC_SEND_DATA(_ptrBytesSent)
/* Important for the J-Link port, in most other ports this can be skipped (default is 1) */
#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 0
#define TRC_STREAM_PORT_ON_TRACE_BEGIN() /* Do nothing */
#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) writeToRTT(_ptrData, _size, _ptrBytesWritten)
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) readFromRTT(_ptrData, _size, _ptrBytesRead)
#ifdef __cplusplus
}

View file

@ -0,0 +1,44 @@
#include "trcRecorder.h"
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
int32_t readFromRTT(void* ptrData, uint32_t size, int32_t* ptrBytesRead)
{
uint32_t bytesRead = 0;
if (SEGGER_RTT_HASDATA(TRC_CFG_RTT_DOWN_BUFFER_INDEX))
{
bytesRead = SEGGER_RTT_Read((TRC_CFG_RTT_DOWN_BUFFER_INDEX), (char*)ptrData, size);
if (ptrBytesRead != NULL)
*ptrBytesRead = (int32_t)bytesRead;
if (bytesRead != size)
{
return -1;
}
}
return 0;
}
int32_t writeToRTT(void* ptrData, uint32_t size, int32_t* ptrBytesWritten)
{
uint32_t bytesWritten = SEGGER_RTT_Write((TRC_CFG_RTT_UP_BUFFER_INDEX), (const char*)ptrData, size);
if (ptrBytesWritten != NULL)
*ptrBytesWritten = (int32_t)bytesWritten;
if (bytesWritten != size)
{
return -1;
}
return 0;
}
#endif
#endif

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcStreamingPort.h
@ -40,7 +40,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -51,37 +51,13 @@
extern "C" {
#endif
/*******************************************************************************
* TRC_RECORDER_TRANSFER_METHOD_TCPIP
*
* This stream port for TCP/IP uses a temporary buffer consisting of multiple
* pages, that are transmitted periodically by the TzCtrl task. You can modify
* the supporting functions to match your system. See trcStreamingPort.c
******************************************************************************/
int32_t trcTcpWrite(void* data, uint32_t size, int32_t *ptrBytesWritten);
int32_t trcTcpRead(void* data, uint32_t size, int32_t *ptrBytesRead);
#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char _TzTraceData[TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE]; /* Static allocation. */
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
#else
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char* _TzTraceData = NULL; /* Dynamic allocation. */
#define TRC_STREAM_PORT_MALLOC() _TzTraceData = TRC_PORT_MALLOC(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
#endif
int32_t trcTcpWrite(void* data, uint32_t size, int32_t *ptrBytesWritten);
#define TRC_STREAM_PORT_INIT() \
TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */ \
prvPagedEventBufferInit(_TzTraceData);
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcTcpRead(_ptrData, _size, _ptrBytesRead)
#define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type* _ptrData; _ptrData = (_type*)prvPagedEventBufferGetWritePointer(_size);
#define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) /* We do the same thing as for non-dynamic event sizes */
#define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) /* Not needed since we write immediately into the buffer received above by TRC_STREAM_PORT_ALLOCATE_EVENT, and the TRC_STREAM_PORT_PERIODIC_SEND_DATA defined below will take care of the actual trace transfer. */
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcTcpRead(_ptrData, _size, _ptrBytesRead);
#define TRC_STREAM_PORT_PERIODIC_SEND_DATA(_ptrBytesSent) prvPagedEventBufferTransfer(trcTcpWrite, _ptrBytesSent);
#define TRC_STREAM_PORT_ON_TRACE_BEGIN() prvPagedEventBufferInit(_TzTraceData);
#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) trcTcpWrite(_ptrData, _size, _ptrBytesSent)
#ifdef __cplusplus
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcStreamingPort.c
@ -41,7 +41,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -50,7 +50,7 @@
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
/* TCP/IP includes */
/* TCP/IP includes - for lwIP in this case */
#include "lwip/tcpip.h"
#include "lwip/sockets.h"
@ -68,11 +68,14 @@ int32_t trcSocketSend( void* data, int32_t size, int32_t* bytesWritten )
if (new_sd < 0)
return -1;
if (bytesWritten == NULL)
return -1;
*bytesWritten = send( new_sd, data, size, 0 );
if (*bytesWritten < 0)
{
/* EWOULDBLOCK may be expected when buffers are full */
if (errno != EWOULDBLOCK)
if (errno != 0 && errno != EWOULDBLOCK)
{
closesocket(new_sd);
new_sd = -1;
@ -94,7 +97,7 @@ int32_t trcSocketReceive( void* data, int32_t size, int32_t* bytesRead )
if ( *bytesRead < 0 )
{
/* EWOULDBLOCK may be expected when there is no data to receive */
if (errno != EWOULDBLOCK)
if (errno != 0 && errno != EWOULDBLOCK)
{
closesocket(new_sd);
new_sd = -1;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcStreamingPort.h
@ -40,7 +40,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -51,16 +51,6 @@
extern "C" {
#endif
/*******************************************************************************
* Implement the below macros to define your own stream port. If your transfer
* method uses RTOS functions, you should not send the data directly but use
* the recorder's internal buffer to store the trace data, for later transfer by
* the TzCtrl task. Check the predefined stream ports for examples on how to use
* the internal buffer (e.g., TCP/IP, UART or USB CDC).
*
* Read more at http://percepio.com/2016/10/05/rtos-tracing/
******************************************************************************/
/* Include files as needed, in this case it is files from STM32Cube FW_F7 V1.4.1 */
#include "usb_device.h"
#include "usbd_cdc.h"
@ -70,32 +60,21 @@ extern "C" {
/* Tested on STM32 devices using Keil/CMSIS USB stack */
extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS;
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes);
int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent );
#if TRC_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char _TzTraceData[TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE]; /* Static allocation. */
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
#else
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char* _TzTraceData = NULL; /* Dynamic allocation. */
#define TRC_STREAM_PORT_MALLOC() _TzTraceData = TRC_PORT_MALLOC(TRC_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_PAGED_EVENT_BUFFER_PAGE_SIZE);
#endif
int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent );
#define TRC_STREAM_PORT_INIT() \
MX_USB_DEVICE_Init(); \
TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */
#define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type* _ptrData; _ptrData = (_type*)prvPagedEventBufferGetWritePointer(_size);
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcCDCReceive(_ptrData, _size, _ptrBytesRead)
#define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) /* We do the same thing as for non-dynamic event sizes */
#define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) /* Not needed since we write immediately into the buffer received above by TRC_STREAM_PORT_ALLOCATE_EVENT, and the TRC_STREAM_PORT_PERIODIC_SEND_DATA defined below will take care of the actual trace transfer. */
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcCDCReceive(_ptrData, _size, _ptrBytesRead);
#define TRC_STREAM_PORT_PERIODIC_SEND_DATA(_ptrBytesSent) prvPagedEventBufferTransfer(trcCDCTransmit, _ptrBytesSent);
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) trcCDCTransmit(_ptrData, _size, _ptrBytesSent)
#define TRC_STREAM_PORT_ON_TRACE_BEGIN() { prvPagedEventBufferInit(_TzTraceData); }
#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */
#ifdef __cplusplus
}

View file

@ -1,3 +1,4 @@
#include "trcRecorder.h"
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
@ -29,8 +30,8 @@ uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
extern USBD_HandleTypeDef hUsbDeviceFS;
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
recBuf commandBuffer;
@ -186,6 +187,7 @@ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
return result;
}
/* The READ function, used in trcStreamingPort.h */
int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes)
{
uint32_t i,diff;
@ -217,13 +219,18 @@ int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes)
return 0;
}
/* The WRITE function, used in trcStreamingPort.h */
int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent )
{
int32_t result;
result=CDC_Transmit_FS(data, size);
*noOfBytesSent = size;
return result;
/* Return value should be 0 on success (not sure what the value of USBD_OK is) */
if (result == USBD_OK)
return 0;
else
return -1;
}
/**

View file

@ -0,0 +1,317 @@
-------------------------------------------------------------------------------
Tracealyzer Recorder Library v4.1.0 for FreeRTOS
-------------------------------------------------------------------------------
Tracealyzer is a sophisticated tool for tracing and visualization
of FreeRTOS-based software systems.
Tracealyzer gives an unprecedented insight into the runtime behavior, which
speeds up debugging, validation and optimization.
This, the Trace Recorder Library, is the target-side part of Tracealyzer, that
performs the actual tracing. The resulting data can then be viewed in the
Tracealyzer PC application, found at https://percepio.com/tracealyzer
To learn more, see these links.
- Getting Started (videos etc): https://percepio.com/gettingstarted
- FAQ: https://percepio.com/category/faq
In case you have any questions, don't hesitate to contact support@percepio.com
Tracealyzer supports FreeRTOS v7.3 and newer, including Amazon FreeRTOS.
-------------------------------------------------------------------------------
Changes, v4.0.3 -> v4.1.0
- Improved performance of User Events
- Fixed handling of format strings ending with '%'
- Improved handling of creative user configuration macros
-------------------------------------------------------------------------------
Changes, v4.0.2 -> v4.0.3
- Minor fix for TCP/IP stream port.
- Corrected default RTT mode setting.
-------------------------------------------------------------------------------
Changes, v4.0.1 -> v4.0.2
- Memory allocation trace events now ignore filters.
-------------------------------------------------------------------------------
Changes, v4.0.0 -> v4.0.1
- Minor fixes to default values.
-------------------------------------------------------------------------------
Changes, v3.3.0 -> v4.0.0
- Fixed some issues with filters.
-------------------------------------------------------------------------------
Changes, v3.2.0 -> v3.3.0
- Added support for FreeRTOS v10, including the new object types Message Buffer
and Stream Buffer.
- Improved the object-level filtering to also support Timer, Event Group,
Message Buffer and Stream Buffer objects.
- Fixed a few remaining build problems with older FreeRTOS versions (v7.x).
- vTraceStoreISRBegin now reports an error on invalid handles, i.e., if the
initialization of the handle (xTraceSetISRProperties) had not been made.
-------------------------------------------------------------------------------
Changes, v3.1.2 -> v3.2.0
- Added new filtering system - that works in both snapshot and streaming mode.
Filtering was previously not supported in streaming mode, but can be very
useful for slower streaming interfaces. By exluding irrelevant events, the
amount of data produced can be reduced a lot.
* New functions vTraceSetFilterGroup and vTraceSetFilterMask allows for
excluding all events from specific objects (like a semaphore or queue).
* Added new "generic" filters (preprocessor level) to trcConfig.h, that
exclude all events of a particular types.
- TRC_CFG_INCLUDE_NOTIFY_EVENTS
- TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS
- TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS
- TRC_CFG_INCLUDE_TIMER_EVENTS
* Upgraded some previous filters from "Snapshot only" to the Common API
and thereby moved them from trcSnapshotConfig.h to trcConfig.h.
- TRC_CFG_SCHEDULING_ONLY
- TRC_CFG_INCLUDE_MEMMANG_EVENTS
- TRC_CFG_INCLUDE_USER_EVENTS
- TRC_CFG_INCLUDE_ISR_TRACING
- TRC_CFG_INCLUDE_READY_EVENTS
- TRC_CFG_INCLUDE_OSTICK_EVENTS
* Removed the old filter system from trcSnapshotRecorder.c.
- Improved streaming interface - Now only two (2) macros are needed to be
defined in most cases, read and write. This makes it a lot easier to make
custom stream ports.
* Many definitions that were identical in most stream ports, have been
replaced by default definitions in the recorder core. If needed, they
can be overriden by custom definitions in trcStreamingPort.h.
* Stream ports are now assumed to use recorder's internal event buffer.
Other stream ports that writes directly to the streaming interface
(like J-Link) should define TRC_STREAM_PORT_USE_INTERNAL_BUFFER
as zero (0) to make it work correctly.
* Macro TRC_STREAM_PORT_PERIODIC_SEND_DATA has been replaced by
TRC_STREAM_PORT_WRITE_DATA. Together with TRC_STREAM_PORT_READ_DATA,
this is all that is necessary for a typical stream port.
* Return values from the stream port macros READ_DATA and WRITE_DATA are
now checked. Expects 0 on success, anything else produces a warning
that can be retrived using xTraceGetLastError() and also seen in
Tracealyzer if a trace was produced.
* Stream ports should no longer call prvPagedEventBufferInit explicitly
(e.g. in TRC_STREAM_PORT_ON_TRACE_BEGIN). This is now called
automatically if TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1.
* Macros TRC_STREAM_PORT_ON_TRACE_BEGIN and TRC_STREAM_PORT_ON_TRACE_END
are now unused by default and don't need to be defined.
You can however use them to hook in some own function at these events.
- Added two new stream ports
* TCPIP-Win32: allows for testing the streaming on Windows ports of your
RTOS, using Winsock.
* File: example of streaming to a local file system (tested on Windows,
but easy to modify).
- Added support for FreeRTOS v9.0.1
* Replaced FreeRTOS version code TRC_FREERTOS_VERSION_9_X with
- TRC_FREERTOS_VERSION_9_0_0
- TRC_FREERTOS_VERSION_9_0_1
* Using TRC_FREERTOS_VERSION_9_X is no longer allowed.
- Added additional events for xQueuePeek, for blocking and timeouts events.
- Added event for traceTIMER_EXPIRED, showing when the timer callback
function is called.
- Improved diagnostics in streaming mode, in case of errors in the recorder.
* Added prvTraceWarning() - registers a "warning" error code, without
stopping the recorder. Called if READ_DATA or WRITE_DATA returns a
non-zero value, and in several other cases where the recorder
configuration is incorrect (e.g., too small symbol table).
* Added several new warning codes (PSF_WARNING_XYZ), corresponding to the
issues detected by prvCheckRecorderStatus.
* Fixed duplicate definitions of warning messages, so the warnings reported
to Tracealyzer are the same as those provided in xTraceGetLastError().
* Added better explainations of warning/error messages in the body of
xTraceGetLastError (in streaming mode).
- Added xTraceIsRecordingEnabled() to Common API.
- Added "unofficial" hardware port for Altera Nios-II.
This is a user contribition, not yet verified by Percerpio.
- Fixed bug in vTraceEnable - option TRC_START_AWAIT_HOST was ignored if already initialized.
- Fixed a few remaining compiler warnings.
- Changed order of some settings in trcConfig.h - moved advanced stuff to the
bottom.
- Removed SEGGER_RTT_Printf.c from the J-Link stream port since not required
for Tracealyzer.
-------------------------------------------------------------------------------
Changes, v3.1.1 -> v3.1.2
- Fixed two bugs related to User Events, one in vTracePrintF and other in vTracePrint.
- Fixed a build problem related to a single reference of the old FreeRTOS type "xTaskHandle", in trcKernelPort.c.
Changed to "TaskHandle_t", unless if using an older FreeRTOS kernel or the "compatibility mode".
- Removed traceCREATE_MUTEX hook for FreeRTOS v9 or later (no longer required)
- Updated the User Manual regarding snapshot trace via IAR Embedded Workbench.
- Renamed vTraceGetTraceBuffer to xTraceGetTraceBuffer, since returning a pointer.
-------------------------------------------------------------------------------
Changes, v3.1.0 -> v3.1.1
After the major changes in the v3.1.0 trace recorder library, this update
corrects a number of minor issues. Only minor functional improvements.
- You can now use TRC_ALLOC_CUSTOM_BUFFER to declare a trace buffer on a custom
location (using linker directives).
The related function vTraceSetRecorderDataBuffer has been promoted to the
Common API (previously only supported in snapshot mode, but custom allocation
is now generally supported also in streaming mode).
- Removed TRC_CFG_USE_LINKER_PRAGMA. No longer necessary thanks to the custom
allocation mode.
- Added support for timestamping from custom periodic timers, required for
accurate timestamping on Cortex-M0/M0+ devices when using tickless idle.
Only for streaming mode so far. See TRC_CUSTOM_TIMER_INCR / DECR.
- ARM Cortex-M port: Made sure the DWT unit is initialized properly, in case
the debugger doesn't handle this.
- ARM Cortex-M port: Added possibility to use Systick timestamping also on
Cortex-M3/M4/M7 devices (that otherwise use DWT timestamping by default).
To use this option, define the macro TRC_CFG_ARM_CM_USE_SYSTICK.
- J-Link streaming: The default RTT buffer has been changed from 0 to 1.
- J-Link streaming: The RTT buffer settings for buffer 1 and higher, are now
found in trcStreamingPort.h. Note: These settings don't apply to buffer 0.
- vTracePrint has been optimized for better performance in string logging.
- Minor performance improvement related to symbol table transfer in streaming mode.
- Timer names now registered also in streaming mode.
- Timer start and stop event are now traced.
- Implemented support for queue registry (traceQUEUE_REGISTRY_ADD) also for streaming.
- Fixed a bug related to repeated calls of vTraceEnable.
- Fixed a bug where task-switches seemed to occur even though the scheduler was disabled.
- Renamed HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48, added prefix TRC.
- Fixed several language issues in the comments and documentation.
- Fixed several minor issues and warnings from different compilers
(including PowerPC/gcc) and configurations.
-------------------------------------------------------------------------------
Changes, v3.0.9 -> v3.1.0
- Merge of previously separated snapshot and streaming recorders into a single
recorder supporting both streaming and snapshot as different modes.
- New common API for supporting both streaming and snapshot modes.
- New integration guide, see the User Manual.
- Major improvement of API documentation in source files and User Manual.
- New concept of "stream ports", giving a better structure defining streaming
interfaces, and restructured the J-Link and TCP/IP streaming as stream ports.
- Added a stream port for USB CDC connections, with STM32 as example.
Since Tracealyzer now can receive serial data on Windows COM ports, this is
really easy to use.
- Added a warning (#error) for cases where FreeRTOS tickless idle mode is used
together with timestamping using SysTick or other periodic interrupt timers,
Tracing with tickless idle requires an independent time source to correctly
capture the length of the idle periods.
- Major changes in the recorder API. Important examples are:
* Some configuration macros have changed names, e.g. for "hardware port".
Make sure to remove any old "trcConfig.h" files if upgrading from an
earlier version!
* Recorder configuration in trcConfig.h has been minimized and now only
includes the important settings that are independent of recorder mode.
Advanced settings for each mode are found in trcSnapshotConfig.h and
trcStreamingConfig.h.
* vTraceEnable replaces Trace_Init and vTraceInitTraceData, as well as
vTraceStart and uiTraceStart.
* vTraceStop now part of the common API and thereby available also in
streaming. And since vTraceEnable can start the streaming directly
you have the option control the tracing from target, e.g., for
streaming to a device file system.
* vTraceStoreKernelObjectName from old streaming recorder has been replaced
by vTraceSetQueueName, vTraceSetSemaphoreName, etc.
* vTraceSetISRProperties now returns a "traceHandle" that should be passed as
parameter to vTraceStoreISRBegin and vTraceStoreISREnd.
* xTraceRegisterString has replaced the old functions xTraceOpenLabel and
vTraceStoreUserEventChannelName. This now returns a "traceString" for use
as "channel" parameter in vTracePrintF, and in other places where strings
are stored.
* Removed vTraceStoreISREndManual and vTraceStoreISREndAuto, use
vTraceStoreISREnd instead.
* Renamed the functions for saving User Events in a separate buffer:
- xTraceRegisterChannelFormat -> xTraceRegisterUBChannel
- vTraceChannelPrintF -> vTraceUBData
- vTraceChannelUserEvent -> vTraceUBEvent
-------------------------------------------------------------------------------
Copyright Percepio AB, 2018.

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcKernelPort.c
@ -38,7 +38,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -50,6 +50,26 @@
#if (defined(TRC_USE_TRACEALYZER_RECORDER) && TRC_USE_TRACEALYZER_RECORDER == 1)
#ifndef TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS
/* TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS is missing in trcConfig.h. */
#error "TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS must be defined in trcConfig.h."
#endif
#ifndef TRC_CFG_INCLUDE_TIMER_EVENTS
/* TRC_CFG_INCLUDE_TIMER_EVENTS is missing in trcConfig.h. */
#error "TRC_CFG_INCLUDE_TIMER_EVENTS must be defined in trcConfig.h."
#endif
#ifndef TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS
/* TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS is missing in trcConfig.h. */
#error "TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS must be defined in trcConfig.h."
#endif
#ifndef TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS
/* TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS is missing in trcConfig.h. Define this as 1 if using FreeRTOS v10 or later and like to trace stream buffer or message buffer events, otherwise 0. */
#error "TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be defined in trcConfig.h."
#endif
#if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))
/*
The below error message is to alert you on the following issue:
@ -57,8 +77,8 @@
The hardware port selected in trcConfig.h uses the operating system timer for the
timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt.
When using tickless idle, the recorder needs an independent time source in order to
correctly record the durations of the idle times. Otherwise, the trace may appear
When using "tickless idle" mode, the recorder needs an independent time source in
order to correctly record the durations of the idle times. Otherwise, the trace may appear
to have a different length than in reality, and the reported CPU load is also affected.
You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
@ -77,11 +97,161 @@
#ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
#error Trace Recorder: This timestamping mode is not recommended with Tickless Idle.
#endif
#endif
#endif /* (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)) */
#include "task.h"
#include "queue.h"
#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
/* If the project does not include the FreeRTOS timers, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
#include "timers.h"
#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
/* If the project does not include the FreeRTOS event groups, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
#include "event_groups.h"
#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
/* If the project does not include the FreeRTOS stream buffers, TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be set to 0 */
#include "stream_buffer.h"
#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
uint32_t prvTraceGetQueueNumber(void* handle);
#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X)
extern unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue );
extern void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber );
extern unsigned char ucQueueGetQueueType( xQueueHandle pxQueue );
uint32_t prvTraceGetQueueNumber(void* handle)
{
return (uint32_t)ucQueueGetQueueNumber(handle);
}
#else
uint32_t prvTraceGetQueueNumber(void* handle)
{
return (uint32_t)uxQueueGetQueueNumber(handle);
}
#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X) */
uint8_t prvTraceGetQueueType(void* handle)
{
// This is either declared in header file in FreeRTOS 8 and later, or as extern above
return ucQueueGetQueueType(handle);
}
/* Tasks */
uint16_t prvTraceGetTaskNumberLow16(void* handle)
{
return TRACE_GET_LOW16(uxTaskGetTaskNumber(handle));
}
uint16_t prvTraceGetTaskNumberHigh16(void* handle)
{
return TRACE_GET_HIGH16(uxTaskGetTaskNumber(handle));
}
void prvTraceSetTaskNumberLow16(void* handle, uint16_t value)
{
vTaskSetTaskNumber(handle, TRACE_SET_LOW16(uxTaskGetTaskNumber(handle), value));
}
void prvTraceSetTaskNumberHigh16(void* handle, uint16_t value)
{
vTaskSetTaskNumber(handle, TRACE_SET_HIGH16(uxTaskGetTaskNumber(handle), value));
}
uint16_t prvTraceGetQueueNumberLow16(void* handle)
{
return TRACE_GET_LOW16(prvTraceGetQueueNumber(handle));
}
uint16_t prvTraceGetQueueNumberHigh16(void* handle)
{
return TRACE_GET_HIGH16(prvTraceGetQueueNumber(handle));
}
void prvTraceSetQueueNumberLow16(void* handle, uint16_t value)
{
vQueueSetQueueNumber(handle, TRACE_SET_LOW16(prvTraceGetQueueNumber(handle), value));
}
void prvTraceSetQueueNumberHigh16(void* handle, uint16_t value)
{
vQueueSetQueueNumber(handle, TRACE_SET_HIGH16(prvTraceGetQueueNumber(handle), value));
}
#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
uint16_t prvTraceGetTimerNumberLow16(void* handle)
{
return TRACE_GET_LOW16(uxTimerGetTimerNumber(handle));
}
uint16_t prvTraceGetTimerNumberHigh16(void* handle)
{
return TRACE_GET_HIGH16(uxTimerGetTimerNumber(handle));
}
void prvTraceSetTimerNumberLow16(void* handle, uint16_t value)
{
vTimerSetTimerNumber(handle, TRACE_SET_LOW16(uxTimerGetTimerNumber(handle), value));
}
void prvTraceSetTimerNumberHigh16(void* handle, uint16_t value)
{
vTimerSetTimerNumber(handle, TRACE_SET_HIGH16(uxTimerGetTimerNumber(handle), value));
}
#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
uint16_t prvTraceGetEventGroupNumberLow16(void* handle)
{
return TRACE_GET_LOW16(uxEventGroupGetNumber(handle));
}
uint16_t prvTraceGetEventGroupNumberHigh16(void* handle)
{
return TRACE_GET_HIGH16(uxEventGroupGetNumber(handle));
}
void prvTraceSetEventGroupNumberLow16(void* handle, uint16_t value)
{
vEventGroupSetNumber(handle, TRACE_SET_LOW16(uxEventGroupGetNumber(handle), value));
}
void prvTraceSetEventGroupNumberHigh16(void* handle, uint16_t value)
{
vEventGroupSetNumber(handle, TRACE_SET_HIGH16(uxEventGroupGetNumber(handle), value));
}
#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
uint16_t prvTraceGetStreamBufferNumberLow16(void* handle)
{
return TRACE_GET_LOW16(uxStreamBufferGetStreamBufferNumber(handle));
}
uint16_t prvTraceGetStreamBufferNumberHigh16(void* handle)
{
return TRACE_GET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle));
}
void prvTraceSetStreamBufferNumberLow16(void* handle, uint16_t value)
{
vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_LOW16(uxStreamBufferGetStreamBufferNumber(handle), value));
}
void prvTraceSetStreamBufferNumberHigh16(void* handle, uint16_t value)
{
vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle), value));
}
#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
static void* pCurrentTCB = NULL;
@ -93,10 +263,12 @@ static TaskHandle_t HandleTzCtrl = NULL; /* TzCtrl task TCB */
static xTaskHandle HandleTzCtrl = NULL; /* TzCtrl task TCB */
#endif
#if defined(configSUPPORT_STATIC_ALLOCATION)
#if (configSUPPORT_STATIC_ALLOCATION == 1)
static StackType_t stackTzCtrl[TRC_CFG_CTRL_TASK_STACK_SIZE];
static StaticTask_t tcbTzCtrl;
#endif
#endif
/* Monitored by TzCtrl task, that give warnings as User Events */
extern volatile uint32_t NoRoomForSymbol;
@ -120,6 +292,8 @@ TRC_STREAM_PORT_ALLOCATE_FIELDS()
/* Called by TzCtrl task periodically (Normally every 100 ms) */
static void prvCheckRecorderStatus(void);
extern void prvTraceWarning(int errCode);
/* The TzCtrl task - receives commands from Tracealyzer (start/stop) */
static portTASK_FUNCTION( TzCtrl, pvParameters );
@ -132,24 +306,47 @@ static portTASK_FUNCTION( TzCtrl, pvParameters );
******************************************************************************/
void vTraceEnable(int startOption)
{
int bytes = 0;
int32_t bytes = 0;
int32_t status;
extern uint32_t RecorderEnabled;
TracealyzerCommandType msg;
if (HandleTzCtrl != NULL)
return; /* Seems we already initiated */
/* Only do this first time...*/
if (HandleTzCtrl == NULL)
{
TRC_STREAM_PORT_INIT();
/* Note: Requires that TRC_CFG_INCLUDE_USER_EVENTS is 1. */
trcWarningChannel = xTraceRegisterString("Warnings from Recorder");
/* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
HandleTzCtrl = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
#else
xTaskCreate( TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );
#endif
if (HandleTzCtrl == NULL)
{
prvTraceError(PSF_ERROR_TZCTRLTASK_NOT_CREATED);
}
}
if (startOption == TRC_START_AWAIT_HOST)
{
/* We keep trying to read commands until the recorder has been started */
do
{
bytes = 0;
TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);
if (bytes == sizeof(TracealyzerCommandType))
status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);
if (status != 0)
{
prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);
}
if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))
{
if (prvIsValidCommand(&msg))
{
@ -179,38 +376,9 @@ void vTraceEnable(int startOption)
/* On TRC_INIT */
TRC_PORT_SPECIFIC_INIT();
}
trcWarningChannel = xTraceRegisterString("Warnings from Recorder");
/* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
#if (configSUPPORT_STATIC_ALLOCATION == 1)
HandleTzCtrl = xTaskCreateStatic(TzCtrl, "TzCtrl", TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
(void)HandleTzCtrl;
#else
xTaskCreate( TzCtrl, "TzCtrl", TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );
#endif
}
/*******************************************************************************
* prvTraceOnBegin
*
* Called on trace begin.
******************************************************************************/
void prvTraceOnBegin()
{
TRC_STREAM_PORT_ON_TRACE_BEGIN();
}
/*******************************************************************************
* prvTraceOnEnd
*
* Called on trace end.
******************************************************************************/
void prvTraceOnEnd()
{
TRC_STREAM_PORT_ON_TRACE_END();
}
#if (TRC_CFG_SCHEDULING_ONLY == 0)
/*******************************************************************************
* vTraceSetQueueName(void* object, const char* name)
*
@ -243,13 +411,58 @@ void vTraceSetSemaphoreName(void* object, const char* name)
* Parameter object: pointer to the Mutex that shall be named
* Parameter name: the name to set (const string literal)
*
* Sets a name for Semaphore objects for display in Tracealyzer.
* Sets a name for Mutex objects for display in Tracealyzer.
******************************************************************************/
void vTraceSetMutexName(void* object, const char* name)
{
vTraceStoreKernelObjectName(object, name);
}
#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
/*******************************************************************************
* vTraceSetEventGroupName(void* object, const char* name)
*
* Parameter object: pointer to the vTraceSetEventGroupName that shall be named
* Parameter name: the name to set (const string literal)
*
* Sets a name for EventGroup objects for display in Tracealyzer.
******************************************************************************/
void vTraceSetEventGroupName(void* object, const char* name)
{
vTraceStoreKernelObjectName(object, name);
}
#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
/*******************************************************************************
* vTraceSetStreamBufferName(void* object, const char* name)
*
* Parameter object: pointer to the StreamBuffer that shall be named
* Parameter name: the name to set (const string literal)
*
* Sets a name for StreamBuffer objects for display in Tracealyzer.
******************************************************************************/
void vTraceSetStreamBufferName(void* object, const char* name)
{
vTraceStoreKernelObjectName(object, name);
}
/*******************************************************************************
* vTraceSetMessageBufferName(void* object, const char* name)
*
* Parameter object: pointer to the MessageBuffer that shall be named
* Parameter name: the name to set (const string literal)
*
* Sets a name for MessageBuffer objects for display in Tracealyzer.
******************************************************************************/
void vTraceSetMessageBufferName(void* object, const char* name)
{
vTraceStoreKernelObjectName(object, name);
}
#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */
/*******************************************************************************
* prvGetCurrentTaskHandle
*
@ -283,7 +496,7 @@ uint32_t prvIsNewTCB(void* pNewTCB)
* Returns true if the RTOS scheduler currently is disabled, thus preventing any
* task-switches from occurring. Only called from vTraceStoreISREnd.
******************************************************************************/
unsigned char prvTraceIsSchedulerSuspended()
unsigned char prvTraceIsSchedulerSuspended(void)
{
/* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in
@ -304,47 +517,37 @@ static void prvCheckRecorderStatus(void)
{
if (NoRoomForSymbol > NoRoomForSymbol_last)
{
vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_TABLE_SLOTS too small. Add %d slots.",
NoRoomForSymbol);
if (NoRoomForSymbol > 0)
{
prvTraceWarning(PSF_WARNING_SYMBOL_TABLE_SLOTS);
}
NoRoomForSymbol_last = NoRoomForSymbol;
}
if (NoRoomForObjectData > NoRoomForObjectData_last)
{
vTracePrintF(trcWarningChannel, "TRC_CFG_OBJECT_DATA_SLOTS too small. Add %d slots.",
NoRoomForObjectData);
if (NoRoomForObjectData > 0)
{
prvTraceWarning(PSF_WARNING_OBJECT_DATA_SLOTS);
}
NoRoomForObjectData_last = NoRoomForObjectData;
}
if (LongestSymbolName > LongestSymbolName_last)
{
if (LongestSymbolName > TRC_CFG_SYMBOL_MAX_LENGTH)
if (LongestSymbolName > (TRC_CFG_SYMBOL_MAX_LENGTH))
{
vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_MAX_LENGTH too small. Add %d chars.",
LongestSymbolName);
prvTraceWarning(PSF_WARNING_SYMBOL_MAX_LENGTH);
}
LongestSymbolName_last = LongestSymbolName;
}
if (MaxBytesTruncated > MaxBytesTruncated_last)
{
/* Some string event generated a too long string that was truncated.
This may happen for the following functions:
- vTracePrintF
- vTracePrintF
- vTraceStoreKernelObjectName
- vTraceStoreUserEventChannelName
- vTraceSetISRProperties
A PSF event may store maximum 60 bytes payload, including data arguments
and string characters. For User Events, also the User Event Channel ptr
must be squeezed in, if a channel is specified. */
vTracePrintF(trcWarningChannel, "String event too long, up to %d bytes truncated.",
MaxBytesTruncated);
if (MaxBytesTruncated > 0)
{
prvTraceWarning(PSF_WARNING_STRING_TOO_LONG);
}
MaxBytesTruncated_last = MaxBytesTruncated;
}
}
@ -352,14 +555,15 @@ static void prvCheckRecorderStatus(void)
/*******************************************************************************
* TzCtrl
*
* Task for receiving commands from Tracealyzer and for recorder diagnostics.
*
* Task for sending the trace data from the internal buffer to the stream
* interface (assuming TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) and for
* receiving commands from Tracealyzer. Also does some diagnostics.
******************************************************************************/
static portTASK_FUNCTION( TzCtrl, pvParameters )
{
TracealyzerCommandType msg;
int bytes = 0;
int32_t bytes = 0;
int32_t status = 0;
(void)pvParameters;
while (1)
@ -368,8 +572,14 @@ static portTASK_FUNCTION( TzCtrl, pvParameters )
{
/* Listen for new commands */
bytes = 0;
TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);
if (bytes == sizeof(TracealyzerCommandType))
status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);
if (status != 0)
{
prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);
}
if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))
{
if (prvIsValidCommand(&msg))
{
@ -377,15 +587,21 @@ static portTASK_FUNCTION( TzCtrl, pvParameters )
}
}
/* Send periodic data */
bytes = 0;
TRC_STREAM_PORT_PERIODIC_SEND_DATA(&bytes);
/* If there was data sent (bytes != 0), immediately loop around and do all this again. Otherwise, step out of this loop and sleep for a while. */
}
while (bytes != 0);
/* If the internal buffer is disabled, the COMMIT macro instead sends the data directly
from the "event functions" (using TRC_STREAM_PORT_WRITE_DATA). */
#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
/* If there is a buffer page, this sends it to the streaming interface using TRC_STREAM_PORT_WRITE_DATA. */
bytes = prvPagedEventBufferTransfer();
#endif
/* If there was data sent or received (bytes != 0), loop around and repeat, if there is more data to send or receive.
Otherwise, step out of this loop and sleep for a while. */
} while (bytes != 0);
prvCheckRecorderStatus();
vTaskDelay(TRC_CFG_CTRL_TASK_DELAY); /* 10ms */
vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);
}
}
@ -398,11 +614,11 @@ static portTASK_FUNCTION( TzCtrl, pvParameters )
int uiInEventGroupSetBitsFromISR = 0;
/******************************************************************************
* TraceObjectClassTable
* TraceQueueClassTable
* Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).
* Has one entry for each QueueType, gives TRACE_CLASS ID.
******************************************************************************/
traceObjectClass TraceObjectClassTable[5] = {
traceObjectClass TraceQueueClassTable[5] = {
TRACE_CLASS_QUEUE,
TRACE_CLASS_MUTEX,
TRACE_CLASS_SEMAPHORE,
@ -410,6 +626,7 @@ traceObjectClass TraceObjectClassTable[5] = {
TRACE_CLASS_MUTEX
};
#if (TRC_CFG_SCHEDULING_ONLY == 0)
/*******************************************************************************
* vTraceSetQueueName(void* object, const char* name)
*
@ -420,7 +637,7 @@ traceObjectClass TraceObjectClassTable[5] = {
******************************************************************************/
void vTraceSetQueueName(void* object, const char* name)
{
prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);
prvTraceSetObjectName(TRACE_CLASS_QUEUE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
}
/*******************************************************************************
@ -433,7 +650,7 @@ void vTraceSetQueueName(void* object, const char* name)
******************************************************************************/
void vTraceSetSemaphoreName(void* object, const char* name)
{
prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);
prvTraceSetObjectName(TRACE_CLASS_SEMAPHORE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
}
/*******************************************************************************
@ -446,36 +663,59 @@ void vTraceSetSemaphoreName(void* object, const char* name)
******************************************************************************/
void vTraceSetMutexName(void* object, const char* name)
{
prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);
prvTraceSetObjectName(TRACE_CLASS_MUTEX, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
}
#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
/*******************************************************************************
* vTraceSetEventGroupName(void* object, const char* name)
*
* Parameter object: pointer to the EventGroup that shall be named
* Parameter name: the name to set (const string literal)
*
* Sets a name for EventGroup objects for display in Tracealyzer.
******************************************************************************/
void vTraceSetEventGroupName(void* object, const char* name)
{
prvTraceSetObjectName(TRACE_CLASS_EVENTGROUP, TRACE_GET_OBJECT_NUMBER(EVENTGROUP, object), name);
}
#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
/*******************************************************************************
* vTraceSetStreamBufferName(void* object, const char* name)
*
* Parameter object: pointer to the StreamBuffer that shall be named
* Parameter name: the name to set (const string literal)
*
* Sets a name for StreamBuffer objects for display in Tracealyzer.
******************************************************************************/
void vTraceSetStreamBufferName(void* object, const char* name)
{
prvTraceSetObjectName(TRACE_CLASS_STREAMBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name);
}
/*******************************************************************************
* vTraceSetMessageBufferName(void* object, const char* name)
*
* Parameter object: pointer to the MessageBuffer that shall be named
* Parameter name: the name to set (const string literal)
*
* Sets a name for MessageBuffer objects for display in Tracealyzer.
******************************************************************************/
void vTraceSetMessageBufferName(void* object, const char* name)
{
prvTraceSetObjectName(TRACE_CLASS_MESSAGEBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name);
}
#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */
void* prvTraceGetCurrentTaskHandle()
{
return xTaskGetCurrentTaskHandle();
}
#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X)
traceHandle prvTraceGetObjectNumber(void* handle)
{
return (traceHandle) ucQueueGetQueueNumber(handle);
}
#else /* For FreeRTOS v8 and later */
traceHandle prvTraceGetObjectNumber(void* handle)
{
return (traceHandle) uxQueueGetQueueNumber(handle);
}
#endif
uint8_t prvTraceGetObjectType(void* handle)
{
return ucQueueGetQueueType(handle);
}
traceHandle prvTraceGetTaskNumber(void* handle)
{
return (traceHandle)uxTaskGetTaskNumber(handle);
}
/* Initialization of the object property table */
void vTraceInitObjectPropertyTable()
{
@ -487,6 +727,8 @@ void vTraceInitObjectPropertyTable()
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = TRC_CFG_NISR;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = TRC_CFG_NTIMER;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = TRC_CFG_NEVENTGROUP;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[7] = TRC_CFG_NSTREAMBUFFER;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[8] = TRC_CFG_NMESSAGEBUFFER;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = TRC_CFG_NAME_LEN_QUEUE;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = TRC_CFG_NAME_LEN_SEMAPHORE;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = TRC_CFG_NAME_LEN_MUTEX;
@ -494,6 +736,8 @@ void vTraceInitObjectPropertyTable()
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = TRC_CFG_NAME_LEN_ISR;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = TRC_CFG_NAME_LEN_TIMER;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = TRC_CFG_NAME_LEN_EVENTGROUP;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[7] = TRC_CFG_NAME_LEN_STREAMBUFFER;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[8] = TRC_CFG_NAME_LEN_MESSAGEBUFFER;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;
@ -501,6 +745,8 @@ void vTraceInitObjectPropertyTable()
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[7] = PropertyTableSizeStreamBuffer;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[8] = PropertyTableSizeMessageBuffer;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;
@ -508,6 +754,8 @@ void vTraceInitObjectPropertyTable()
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[5] = StartIndexTimer;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[7] = StartIndexStreamBuffer;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[8] = StartIndexMessageBuffer;
RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;
}
@ -515,20 +763,24 @@ void vTraceInitObjectPropertyTable()
void vTraceInitObjectHandleStack()
{
objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;
objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = TRC_CFG_NQUEUE;
objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE;
objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX;
objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK;
objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR;
objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR + TRC_CFG_NTIMER;
objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = (TRC_CFG_NQUEUE);
objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE);
objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX);
objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK);
objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR);
objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER);
objectHandleStacks.indexOfNextAvailableHandle[7] = objectHandleStacks.lowestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP);
objectHandleStacks.indexOfNextAvailableHandle[8] = objectHandleStacks.lowestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER);
objectHandleStacks.highestIndexOfClass[0] = TRC_CFG_NQUEUE - 1;
objectHandleStacks.highestIndexOfClass[1] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE - 1;
objectHandleStacks.highestIndexOfClass[2] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX - 1;
objectHandleStacks.highestIndexOfClass[3] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK - 1;
objectHandleStacks.highestIndexOfClass[4] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR - 1;
objectHandleStacks.highestIndexOfClass[5] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR + TRC_CFG_NTIMER - 1;
objectHandleStacks.highestIndexOfClass[6] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR + TRC_CFG_NTIMER + TRC_CFG_NEVENTGROUP - 1;
objectHandleStacks.highestIndexOfClass[0] = (TRC_CFG_NQUEUE) - 1;
objectHandleStacks.highestIndexOfClass[1] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) - 1;
objectHandleStacks.highestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) - 1;
objectHandleStacks.highestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) - 1;
objectHandleStacks.highestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) - 1;
objectHandleStacks.highestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) - 1;
objectHandleStacks.highestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) - 1;
objectHandleStacks.highestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) - 1;
objectHandleStacks.highestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) + (TRC_CFG_NMESSAGEBUFFER) - 1;
}
/* Returns the "Not enough handles" error message for this object class */
@ -550,39 +802,15 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)
return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h";
case TRACE_CLASS_EVENTGROUP:
return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h";
case TRACE_CLASS_STREAMBUFFER:
return "Not enough STREAMBUFFER handles - increase TRC_CFG_NSTREAMBUFFER in trcSnapshotConfig.h";
case TRACE_CLASS_MESSAGEBUFFER:
return "Not enough MESSAGEBUFFER handles - increase TRC_CFG_NMESSAGEBUFFER in trcSnapshotConfig.h";
default:
return "pszTraceGetErrorHandles: Invalid objectclass!";
}
}
/* Returns the exclude state of the object */
uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, traceHandle handle)
{
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "prvIsObjectExcluded: objectclass >= TRACE_NCLASSES", 1);
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "prvIsObjectExcluded: Invalid value for handle", 1);
switch(objectclass)
{
case TRACE_CLASS_TASK:
return (uint8_t) TRACE_GET_TASK_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_SEMAPHORE:
return (uint8_t) TRACE_GET_SEMAPHORE_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_MUTEX:
return (uint8_t) TRACE_GET_MUTEX_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_QUEUE:
return (uint8_t) TRACE_GET_QUEUE_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_TIMER:
return (uint8_t) TRACE_GET_TIMER_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_EVENTGROUP:
return (uint8_t) TRACE_GET_EVENTGROUP_FLAG_ISEXCLUDED(handle);
}
prvTraceError("Invalid object class ID in prvIsObjectExcluded!");
/* Must never reach */
return 1;
}
/*******************************************************************************
* prvTraceIsSchedulerSuspended
*
@ -590,7 +818,7 @@ uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, traceHandle handle
* task-switches from occurring. Only called from vTraceStoreISREnd.
******************************************************************************/
#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
unsigned char prvTraceIsSchedulerSuspended()
unsigned char prvTraceIsSchedulerSuspended(void)
{
/* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcSnapshotRecorder.c
@ -38,7 +38,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -66,6 +66,7 @@ int32_t isPendingContextSwitch = 0;
#if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1
static int readyEventsEnabled = 1;
#endif /*!defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1*/
/*******************************************************************************
* uiTraceTickCount
*
@ -77,7 +78,9 @@ static int readyEventsEnabled = 1;
uint32_t uiTraceTickCount = 0;
uint32_t trace_disable_timestamp = 0;
static uint32_t last_timestamp = 0;
/* Flag that shows if inside a critical section of the recorder */
volatile int recorder_busy = 0;
@ -87,18 +90,21 @@ uint32_t timestampFrequency = 0;
/* The last error message of the recorder. NULL if no error message. */
const char* traceErrorMessage = NULL;
int8_t nISRactive = 0;
traceHandle handle_of_last_logged_task = 0;
uint8_t inExcludedTask = 0;
extern uint8_t inExcludedTask;
extern int8_t nISRactive;
extern traceHandle handle_of_last_logged_task;
traceHandle handle_of_last_logged_task = 0;
/* Called when the recorder is stopped, set by vTraceSetStopHook. */
TRACE_STOP_HOOK vTraceStopHookPtr = (TRACE_STOP_HOOK)0;
uint16_t CurrentFilterMask = 0xFFFF;
uint16_t CurrentFilterGroup = FilterGroup0;
extern int8_t nISRactive;
extern traceHandle handle_of_last_logged_task;
/*************** Private Functions *******************************************/
static void prvStrncpy(char* dst, const char* src, uint32_t maxLength);
static uint8_t prvTraceGetObjectState(uint8_t objectclass, traceHandle id);
@ -108,6 +114,8 @@ static uint16_t prvTraceGetDTS(uint16_t param_maxDTS);
static traceString prvTraceOpenSymbol(const char* name, traceString userEventChannel);
static void prvTraceUpdateCounters(void);
void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_size);
#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
static void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nEntries);
#endif
@ -137,7 +145,6 @@ static uint8_t prvTraceGet8BitHandle(traceHandle handle);
#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)
/* Current heap usage. Always updated. */
static uint32_t heapMemUsage = 0;
#endif
@ -261,7 +268,8 @@ void vTraceSetRecorderDataBuffer(void* pRecorderData)
* vTraceSetStopHook
*
* Sets a function to be called when the recorder is stopped. This can be used
* to save the trace to a file system, if available.
* to save the trace to a file system, if available. This is only implemented
* for snapshot mode.
******************************************************************************/
void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction)
{
@ -314,7 +322,7 @@ uint32_t uiTraceStart(void)
if (RecorderDataPtr == NULL)
{
prvTraceError("RecorderDataPtr is NULL. Call vTraceInitTraceData() before starting trace.");
TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized. Use vTraceEnable() instead!", 0);
return 0;
}
@ -367,8 +375,11 @@ void vTraceStart(void)
* This does not reset the recorder. Use vTraceClear if that is desired.
******************************************************************************/
void vTraceStop(void)
{
if (RecorderDataPtr != NULL)
{
RecorderDataPtr->recorderActive = 0;
}
if (vTraceStopHookPtr != (TRACE_STOP_HOOK)0)
{
@ -376,6 +387,22 @@ void vTraceStop(void)
}
}
/*******************************************************************************
* xTraceIsRecordingEnabled
* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0.
******************************************************************************/
int xTraceIsRecordingEnabled(void)
{
if (RecorderDataPtr != NULL)
{
return (int)RecorderDataPtr->recorderActive;
}
else
{
return 0;
}
}
/*******************************************************************************
* xTraceGetLastError
*
@ -433,7 +460,6 @@ uint32_t uiTraceGetTraceBufferSize(void)
* prvTraceTaskInstanceFinish
*
* Private common function for the vTraceTaskInstanceFinishXXX functions.
*
*****************************************************************************/
static void prvTraceTaskInstanceFinish(int8_t direct)
{
@ -443,7 +469,7 @@ static void prvTraceTaskInstanceFinish(int8_t direct)
TRACE_ALLOC_CRITICAL_SECTION();
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
{
dts45 = (uint8_t)prvTraceGetDTS(0xFF);
tis = (TaskInstanceStatusEvent*) prvTraceNextFreeEventBufferSlot();
@ -482,9 +508,6 @@ static void prvTraceTaskInstanceFinish(int8_t direct)
* processCommand(command);
* vTraceInstanceFinishedNext();
* }
*
* Note: This is only supported in Tracealyzer tools v2.7 or later
*
*****************************************************************************/
void vTraceInstanceFinishedNext(void)
{
@ -514,9 +537,6 @@ void vTraceInstanceFinishedNext(void)
* DoSometingElse();
* vTraceInstanceFinishedNext();
* }
*
* Note: This is only supported in Tracealyzer tools v2.7 or later
*
*****************************************************************************/
void vTraceInstanceFinishedNow(void)
{
@ -546,15 +566,16 @@ void vTraceInstanceFinishedNow(void)
* ...
* vTraceStoreISREnd(0);
* }
*
******************************************************************************/
traceHandle xTraceSetISRProperties(const char* name, uint8_t priority)
{
static traceHandle handle = 0;
handle++;
TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0);
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "xTraceSetISRProperties: Invalid value for handle", 0);
TRACE_ASSERT(name != NULL, "xTraceSetISRProperties: name == NULL", 0);
handle++;
prvTraceSetObjectName(TRACE_CLASS_ISR, handle, name);
prvTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority);
@ -578,7 +599,6 @@ void vTraceInstanceFinishedNow(void)
* ...
* vTraceStoreISREnd(0);
* }
*
******************************************************************************/
void vTraceStoreISRBegin(traceHandle handle)
{
@ -605,7 +625,8 @@ void vTraceStoreISRBegin(traceHandle handle)
{
uint16_t dts4;
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid value for handle", TRC_UNUSED);
TRACE_ASSERT(handle != 0, "vTraceStoreISRBegin: Invalid ISR handle (NULL)", TRC_UNUSED);
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid ISR handle (> NISR)", TRC_UNUSED);
dts4 = (uint16_t)prvTraceGetDTS(0xFFFF);
@ -657,7 +678,6 @@ void vTraceStoreISRBegin(traceHandle handle)
* ...
* vTraceStoreISREnd(0);
* }
*
******************************************************************************/
void vTraceStoreISREnd(int pendingISR)
{
@ -742,6 +762,7 @@ void prvTraceDecreaseISRActive(void)
}
#endif /* (TRC_CFG_INCLUDE_ISR_TRACING == 1)*/
/********************************************************************************/
/* User Event functions */
/********************************************************************************/
@ -1036,13 +1057,13 @@ static void prvTraceClearChannelBuffer(uint32_t count)
{
uint32_t slots;
TRACE_ASSERT(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE >= count,
TRACE_ASSERT((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) >= count,
"prvTraceClearChannelBuffer: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);
/* Check if we're close to the end of the buffer */
if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE)
if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE))
{
slots = TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */
slots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */
(void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite], 0, slots);
(void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[0], 0, (count - slots));
}
@ -1063,12 +1084,12 @@ static void prvTraceCopyToDataBuffer(uint32_t* data, uint32_t count)
TRACE_ASSERT(data != NULL,
"prvTraceCopyToDataBuffer: data == NULL.", TRC_UNUSED);
TRACE_ASSERT(count <= TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE,
TRACE_ASSERT(count <= (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE),
"prvTraceCopyToDataBuffer: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);
/* Check if we're close to the end of the buffer */
if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE)
if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE))
{
slots = TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */
slots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */
(void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite * 4], data, slots * 4);
(void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[0], data + slots, (count - slots) * 4);
}
@ -1119,7 +1140,7 @@ static void prvTraceUBHelper2(traceUBChannel channel, uint32_t* data, uint32_t n
TRACE_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE >= noOfSlots, "prvTraceUBHelper2: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);
TRACE_ASSERT((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) >= noOfSlots, "prvTraceUBHelper2: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);
trcCRITICAL_SECTION_BEGIN();
/* Store the timestamp */
@ -1138,7 +1159,7 @@ static void prvTraceUBHelper2(traceUBChannel channel, uint32_t* data, uint32_t n
prvTraceCopyToDataBuffer(data, noOfSlots); /* Will wrap around the data if necessary */
old_nextSlotToWrite = RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Save the index that we want to write the channel data at when we're done */
RecorderDataPtr->userEventBuffer.nextSlotToWrite = (RecorderDataPtr->userEventBuffer.nextSlotToWrite + noOfSlots) % TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE; /* Make sure we never end up outside the buffer */
RecorderDataPtr->userEventBuffer.nextSlotToWrite = (RecorderDataPtr->userEventBuffer.nextSlotToWrite + noOfSlots) % (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE); /* Make sure we never end up outside the buffer */
/* Write to the channel buffer to indicate that this user event is ready to be used */
if (channel != 0)
@ -1174,7 +1195,7 @@ traceUBChannel xTraceRegisterUBChannel(traceString channel, traceString formatSt
TRACE_ASSERT(formatStr != 0, "xTraceRegisterChannelFormat: formatStr == 0", (traceUBChannel)0);
trcCRITICAL_SECTION_BEGIN();
for (i = 1; i <= TRC_CFG_UB_CHANNELS; i++) /* Size of the channels buffer is TRC_CFG_UB_CHANNELS + 1. Index 0 is unused. */
for (i = 1; i <= (TRC_CFG_UB_CHANNELS); i++) /* Size of the channels buffer is TRC_CFG_UB_CHANNELS + 1. Index 0 is unused. */
{
if(RecorderDataPtr->userEventBuffer.channels[i].name == 0 && RecorderDataPtr->userEventBuffer.channels[i].defaultFormat == 0)
{
@ -1203,9 +1224,8 @@ traceUBChannel xTraceRegisterUBChannel(traceString channel, traceString formatSt
*
* Slightly faster version of vTracePrintF() due to no lookups.
*
* Note: This is only available if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is enabled in
* trcConfig.h
*
* Note: This is only available if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is
* enabled in trcSnapshotConfig.h
******************************************************************************/
#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))
void vTraceUBData(traceUBChannel channelPair, ...)
@ -1228,7 +1248,7 @@ void vTraceUBData_Helper(traceUBChannel channelPair, va_list vl)
traceString formatStr;
TRACE_ASSERT(channelPair != 0, "vTraceUBData_Helper: channelPair == 0", TRC_UNUSED);
TRACE_ASSERT(channelPair <= TRC_CFG_UB_CHANNELS, "vTraceUBData_Helper: ", TRC_UNUSED);
TRACE_ASSERT(channelPair <= (TRC_CFG_UB_CHANNELS), "vTraceUBData_Helper: ", TRC_UNUSED);
channel = RecorderDataPtr->userEventBuffer.channels[channelPair].name;
formatStr = RecorderDataPtr->userEventBuffer.channels[channelPair].defaultFormat;
@ -1248,7 +1268,7 @@ void vTraceUBEvent(traceUBChannel channelPair)
uint32_t data[(3 + MAX_ARG_SIZE) / 4];
TRACE_ASSERT(channelPair != 0, "vTraceUBEvent: channelPair == 0", TRC_UNUSED);
TRACE_ASSERT(channelPair <= TRC_CFG_UB_CHANNELS, "vTraceUBEvent: ", TRC_UNUSED);
TRACE_ASSERT(channelPair <= (TRC_CFG_UB_CHANNELS), "vTraceUBEvent: ", TRC_UNUSED);
prvTraceUBHelper2(channelPair, data, 1); /* Only need one slot for timestamp */
}
@ -1331,7 +1351,7 @@ void vTracePrintF_Helper(traceString eventLabel, const char* formatStr, va_list
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
{
/* First, write the "primary" user event entry in the local buffer, but
let the event type be "EVENT_BEING_WRITTEN" for now...*/
@ -1396,7 +1416,7 @@ void vTracePrintF_Helper(traceString eventLabel, const char* formatStr, va_list
RecorderDataPtr->nextFreeIndex += noOfSlots;
RecorderDataPtr->numEvents += noOfSlots;
if (RecorderDataPtr->nextFreeIndex >= TRC_CFG_EVENT_BUFFER_SIZE)
if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE))
{
#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
/* We have reached the end, but this is a ring buffer. Start from the beginning again. */
@ -1423,7 +1443,7 @@ void vTracePrintF_Helper(traceString eventLabel, const char* formatStr, va_list
traceString formatLabel;
traceUBChannel channel;
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
{
formatLabel = xTraceRegisterString(formatStr);
@ -1452,7 +1472,7 @@ void vTracePrint(traceString chn, const char* str)
TRACE_ALLOC_CRITICAL_SECTION();
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
{
dts1 = (uint8_t)prvTraceGetDTS(0xFF);
ue = (UserEvent*) prvTraceNextFreeEventBufferSlot();
@ -1470,7 +1490,7 @@ void vTracePrint(traceString chn, const char* str)
traceUBChannel channel;
uint32_t noOfSlots = 1;
uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
{
traceString trcStr = prvTraceOpenSymbol(str, chn);
channel = xTraceRegisterUBChannel(chn, trcStr);
@ -1498,13 +1518,12 @@ void vTracePrint(traceString chn, const char* str)
* myEventHandle = xTraceRegisterString("MyUserEvent");
* ...
* vTracePrintF(myEventHandle, "My value is: %d", myValue);
*
******************************************************************************/
#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
traceString xTraceRegisterString(const char* label)
{
TRACE_ASSERT(label != NULL, "xTraceRegisterString: label == NULL", (traceString)0);
TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0);
return prvTraceOpenSymbol(label, 0);
}
#endif
@ -1545,7 +1564,7 @@ void prvTraceStoreTaskReady(traceHandle handle)
return;
}
TRACE_ASSERT(handle <= TRC_CFG_NTASK, "prvTraceStoreTaskReady: Invalid value for handle", TRC_UNUSED);
TRACE_ASSERT(handle <= (TRC_CFG_NTASK), "prvTraceStoreTaskReady: Invalid value for handle", TRC_UNUSED);
if (recorder_busy)
{
@ -1565,8 +1584,6 @@ void prvTraceStoreTaskReady(traceHandle handle)
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
if (!TRACE_GET_TASK_FLAG_ISEXCLUDED(handle))
{
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
hnd8 = prvTraceGet8BitHandle(handle);
@ -1579,7 +1596,6 @@ void prvTraceStoreTaskReady(traceHandle handle)
prvTraceUpdateCounters();
}
}
}
trcCRITICAL_SECTION_END();
}
#endif
@ -1666,9 +1682,6 @@ void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_si
heapMemUsage = heapMemUsage + (uint32_t)signed_size;
if (RecorderDataPtr->recorderActive)
{
/* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
if (nISRactive || !inExcludedTask)
{
dts1 = (uint8_t)prvTraceGetDTS(0xFF);
size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);
@ -1707,7 +1720,6 @@ void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_si
}
}
}
}
trcCRITICAL_SECTION_END();
}
#endif /* TRC_CFG_SCHEDULING_ONLY */
@ -1754,12 +1766,6 @@ void prvTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint3
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive)
{
/* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
if (nISRactive || !inExcludedTask)
{
/* Check if the referenced object or the event code is excluded */
if (!uiTraceIsObjectExcluded(objectClass, (traceHandle)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))
{
dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);
hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);
@ -1772,8 +1778,6 @@ void prvTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint3
prvTraceUpdateCounters();
}
}
}
}
trcCRITICAL_SECTION_END();
}
#endif /* TRC_CFG_SCHEDULING_ONLY */
@ -1818,11 +1822,7 @@ void prvTraceStoreKernelCallWithParam(uint32_t evtcode,
}
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && (! inExcludedTask || nISRactive))
{
/* Check if the referenced object or the event code is excluded */
if (!uiTraceIsObjectExcluded(objectClass, (traceHandle)objectNumber) &&
!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
{
dts2 = (uint8_t)prvTraceGetDTS(0xFF);
p8 = (uint8_t) prvTraceGetParam(0xFF, param);
@ -1837,7 +1837,6 @@ void prvTraceStoreKernelCallWithParam(uint32_t evtcode,
prvTraceUpdateCounters();
}
}
}
trcCRITICAL_SECTION_END();
}
#endif /* TRC_CFG_SCHEDULING_ONLY */
@ -1913,11 +1912,7 @@ void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t para
}
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task
&& (! inExcludedTask || nISRactive))
{
/* Check if the event code is excluded */
if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
{
dts6 = (uint8_t)prvTraceGetDTS(0xFF);
restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);
@ -1930,7 +1925,6 @@ void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t para
prvTraceUpdateCounters();
}
}
}
trcCRITICAL_SECTION_END();
}
#endif /* TRC_CFG_SCHEDULING_ONLY */
@ -1944,44 +1938,18 @@ void prvTraceStoreTaskswitch(traceHandle task_handle)
{
uint16_t dts3;
TSEvent* ts;
int8_t skipEvent;
uint8_t hnd8;
#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
extern int32_t isPendingContextSwitch;
#endif
trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY();
skipEvent = 0;
TRACE_ASSERT(task_handle <= TRC_CFG_NTASK,
TRACE_ASSERT(task_handle <= (TRC_CFG_NTASK),
"prvTraceStoreTaskswitch: Invalid value for task_handle", TRC_UNUSED);
/* Skip the event if the task has been excluded, using vTraceExcludeTask */
if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))
{
skipEvent = 1;
inExcludedTask = 1;
}
else
{
inExcludedTask = 0;
}
trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY();
/* Skip the event if the same task is scheduled */
if (task_handle == handle_of_last_logged_task)
{
skipEvent = 1;
}
if (!RecorderDataPtr->recorderActive)
{
skipEvent = 1;
}
/* If this event should be logged, log it! */
if (skipEvent == 0)
if ((task_handle != handle_of_last_logged_task) && (RecorderDataPtr->recorderActive))
{
#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
isPendingContextSwitch = 0;
@ -2026,8 +1994,7 @@ void prvTraceStoreTaskswitch(traceHandle task_handle)
* and name (a symbol table handle). The stored name-handle mapping is thus the
* "old" one, valid up until this point.
******************************************************************************/
#if (TRC_CFG_INCLUDE_OBJECT_DELETE == 1)
void prvTraceStoreObjectNameOnCloseEvent(traceHandle handle,
void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle,
traceObjectClass objectclass)
{
ObjCloseNameEvent * ce;
@ -2049,7 +2016,7 @@ void prvTraceStoreObjectNameOnCloseEvent(traceHandle handle,
ce = (ObjCloseNameEvent*) prvTraceNextFreeEventBufferSlot();
if (ce != NULL)
{
ce->type = (uint8_t) (EVENTGROUP_OBJCLOSE_NAME + objectclass);
ce->type = (uint8_t) evtcode;
ce->objHandle = hnd8;
ce->symbolIndex = idx;
prvTraceUpdateCounters();
@ -2057,7 +2024,7 @@ void prvTraceStoreObjectNameOnCloseEvent(traceHandle handle,
}
}
void prvTraceStoreObjectPropertiesOnCloseEvent(traceHandle handle,
void prvTraceStoreObjectPropertiesOnCloseEvent(uint8_t evtcode, traceHandle handle,
traceObjectClass objectclass)
{
ObjClosePropEvent * pe;
@ -2081,12 +2048,11 @@ void prvTraceStoreObjectPropertiesOnCloseEvent(traceHandle handle,
{
pe->arg1 = TRACE_PROPERTY_OBJECT_STATE(objectclass, handle);
}
pe->type = (uint8_t) (EVENTGROUP_OBJCLOSE_PROP + objectclass);
pe->type = evtcode;
prvTraceUpdateCounters();
}
}
}
#endif
void prvTraceSetPriorityProperty(uint8_t objectclass, traceHandle id, uint8_t value)
{
@ -2142,16 +2108,6 @@ void prvTraceSetTaskInstanceFinished(traceHandle handle)
* Static data initializations
******************************************************************************/
/* Tasks and kernel objects can be explicitly excluded from the trace to reduce
buffer usage. This structure handles the exclude flags for all objects and tasks.
Note that slot 0 is not used, since not a valid handle. */
uint8_t trcExcludedObjects[(TRACE_KERNEL_OBJECT_COUNT + TRACE_NCLASSES) / 8 + 1] = { 0 };
/* Specific events can also be excluded, i.e., by the event code. This can be
used to exclude kernel calls that don't refer to a kernel object, like a delay.
This structure handle the exclude flags for all event codes */
uint8_t trcExcludedEventCodes[NEventCodes / 8 + 1] = { 0 };
/* A set of stacks that keeps track of available object handles for each class.
The stacks are empty initially, meaning that allocation of new handles will be
based on a counter (for each object class). Any delete operation will
@ -2222,7 +2178,7 @@ void prvTraceInitTraceData()
RecorderDataPtr->minor_version = TRACE_MINOR_VERSION;
RecorderDataPtr->irq_priority_order = TRC_IRQ_PRIORITY_ORDER;
RecorderDataPtr->filesize = sizeof(RecorderDataType);
RecorderDataPtr->maxEvents = TRC_CFG_EVENT_BUFFER_SIZE;
RecorderDataPtr->maxEvents = (TRC_CFG_EVENT_BUFFER_SIZE);
RecorderDataPtr->debugMarker0 = (int32_t) 0xF0F0F0F0;
RecorderDataPtr->isUsing16bitHandles = TRC_CFG_USE_16BIT_OBJECT_HANDLES;
RecorderDataPtr->isrTailchainingThreshold = TRC_CFG_ISR_TAILCHAINING_THRESHOLD;
@ -2231,7 +2187,7 @@ void prvTraceInitTraceData()
vTraceInitObjectPropertyTable();
RecorderDataPtr->debugMarker1 = (int32_t)0xF1F1F1F1;
RecorderDataPtr->SymbolTable.symTableSize = TRC_CFG_SYMBOL_TABLE_SIZE;
RecorderDataPtr->SymbolTable.symTableSize = (TRC_CFG_SYMBOL_TABLE_SIZE);
RecorderDataPtr->SymbolTable.nextFreeSymbolIndex = 1;
#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT == 1)
RecorderDataPtr->exampleFloatEncoding = 1.0f; /* otherwise already zero */
@ -2255,8 +2211,8 @@ void prvTraceInitTraceData()
#if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER
RecorderDataPtr->userEventBuffer.bufferID = 1;
RecorderDataPtr->userEventBuffer.version = 0;
RecorderDataPtr->userEventBuffer.numberOfSlots = TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE;
RecorderDataPtr->userEventBuffer.numberOfChannels = TRC_CFG_UB_CHANNELS + 1;
RecorderDataPtr->userEventBuffer.numberOfSlots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE);
RecorderDataPtr->userEventBuffer.numberOfChannels = (TRC_CFG_UB_CHANNELS) + 1;
#endif
/* Kernel specific initialization of the objectHandleStacks variable */
@ -2289,6 +2245,15 @@ void prvTraceInitTraceData()
RecorderDataPtr->startmarker1 = 0x02;
RecorderDataPtr->startmarker0 = 0x01;
if (traceErrorMessage != NULL)
{
// An error was detected before vTraceEnable was called, make sure this is stored in the trace data.
prvStrncpy(RecorderDataPtr->systemInfo, traceErrorMessage, 80);
RecorderDataPtr->internalErrorOccured = 1;
vTraceStop();
}
#ifdef TRC_PORT_SPECIFIC_INIT
TRC_PORT_SPECIFIC_INIT();
@ -2305,7 +2270,7 @@ void* prvTraceNextFreeEventBufferSlot(void)
return NULL;
}
if (RecorderDataPtr->nextFreeIndex >= TRC_CFG_EVENT_BUFFER_SIZE)
if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE))
{
prvTraceError("Attempt to index outside event buffer!");
return NULL;
@ -2336,9 +2301,14 @@ traceHandle prvTraceGetObjectHandle(traceObjectClass objectclass)
traceHandle handle;
static int indexOfHandle;
TRACE_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0);
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
"prvTraceGetObjectHandle: Invalid value for objectclass", (traceHandle)0);
trcCRITICAL_SECTION_BEGIN();
indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass];
if (objectHandleStacks.objectHandles[indexOfHandle] == 0)
{
@ -2372,8 +2342,9 @@ traceHandle prvTraceGetObjectHandle(traceObjectClass objectclass)
objectHandleStacks.handleCountWaterMarksOfClass[objectclass] =
(traceHandle)hndCount;
}
TRACE_CLEAR_OBJECT_FLAG_ISEXCLUDED(objectclass, handle);
}
trcCRITICAL_SECTION_END();
return handle;
}
@ -2537,7 +2508,10 @@ void vTraceSetFrequency(uint32_t frequency)
void prvTraceError(const char* msg)
{
/* Stop the recorder */
if (RecorderDataPtr != NULL)
{
vTraceStop();
}
/* If first error only... */
if (traceErrorMessage == NULL)
@ -2551,6 +2525,16 @@ void prvTraceError(const char* msg)
}
}
void vTraceSetFilterMask(uint16_t filterMask)
{
CurrentFilterMask = filterMask;
}
void vTraceSetFilterGroup(uint16_t filterGroup)
{
CurrentFilterGroup = filterGroup;
}
/******************************************************************************
* prvCheckDataToBeOverwrittenForMultiEntryEvents
*
@ -2623,7 +2607,7 @@ void prvTraceUpdateCounters(void)
RecorderDataPtr->nextFreeIndex++;
if (RecorderDataPtr->nextFreeIndex >= TRC_CFG_EVENT_BUFFER_SIZE)
if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE))
{
#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
RecorderDataPtr->bufferIsFull = 1;
@ -2663,16 +2647,16 @@ uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
if (timestampFrequency != 0)
{
/* If to override default TRC_HWTC_FREQ_HZ value with value set by vTraceSetFrequency */
RecorderDataPtr->frequency = timestampFrequency / TRC_HWTC_DIVISOR;
RecorderDataPtr->frequency = timestampFrequency / (TRC_HWTC_DIVISOR);
}
else if (init_hwtc_count != TRC_HWTC_COUNT)
else if (init_hwtc_count != (TRC_HWTC_COUNT))
{
/* If using default value and timer has been started.
Note: If the default frequency value set here would be incorrect, e.g.,
if the timer has actually not been configured yet, override this
with vTraceSetFrequency.
*/
RecorderDataPtr->frequency = TRC_HWTC_FREQ_HZ / TRC_HWTC_DIVISOR;
RecorderDataPtr->frequency = (TRC_HWTC_FREQ_HZ) / (TRC_HWTC_DIVISOR);
}
/* If no override (vTraceSetFrequency) and timer inactive -> no action */
}
@ -2819,7 +2803,7 @@ uint16_t prvTraceCreateSymbolTableEntry(const char* name,
TRACE_ASSERT(name != NULL, "prvTraceCreateSymbolTableEntry: name == NULL", 0);
TRACE_ASSERT(len != 0, "prvTraceCreateSymbolTableEntry: len == 0", 0);
if (RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + len + 4 >= TRC_CFG_SYMBOL_TABLE_SIZE)
if (RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + len + 4 >= (TRC_CFG_SYMBOL_TABLE_SIZE))
{
prvTraceError("Symbol table full. Increase TRC_CFG_SYMBOL_TABLE_SIZE in trcConfig.h");
ret = 0;
@ -3033,10 +3017,10 @@ void prvTracePortGetTimeStamp(uint32_t *pTimestamp)
/* Retrieve TRC_HWTC_COUNT only once since the same value should be used all throughout this function. */
#if (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_INCR)
/* Get the increasing tick count */
hwtc_count = TRC_HWTC_COUNT;
hwtc_count = (TRC_HWTC_COUNT);
#elif (TRC_HWTC_TYPE == TRC_OS_TIMER_DECR || TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_DECR)
/* Convert decreasing tick count into increasing tick count */
hwtc_count = TRC_HWTC_PERIOD - TRC_HWTC_COUNT;
hwtc_count = (TRC_HWTC_PERIOD) - (TRC_HWTC_COUNT);
#else
#error "TRC_HWTC_TYPE has unexpected value"
#endif
@ -3081,9 +3065,9 @@ void prvTracePortGetTimeStamp(uint32_t *pTimestamp)
if (pTimestamp)
{
/* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */
last_timestamp = traceTickCount * (TRC_HWTC_PERIOD / TRC_HWTC_DIVISOR);
last_timestamp = traceTickCount * ((TRC_HWTC_PERIOD) / (TRC_HWTC_DIVISOR));
/* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / TRC_HWTC_DIVISOR. */
last_timestamp += (hwtc_count + traceTickCount * (TRC_HWTC_PERIOD % TRC_HWTC_DIVISOR)) / TRC_HWTC_DIVISOR;
last_timestamp += (hwtc_count + traceTickCount * ((TRC_HWTC_PERIOD) % (TRC_HWTC_DIVISOR))) / (TRC_HWTC_DIVISOR);
}
/* Store the previous value */
last_traceTickCount = traceTickCount;
@ -3099,10 +3083,10 @@ void prvTracePortGetTimeStamp(uint32_t *pTimestamp)
diff = (hwtc_count - last_hwtc_count) + last_hwtc_rest;
/* Scale down the diff */
diff_scaled = diff / TRC_HWTC_DIVISOR;
diff_scaled = diff / (TRC_HWTC_DIVISOR);
/* Find out how many ticks were lost when scaling down, so we can add them the next time */
last_hwtc_rest = diff % TRC_HWTC_DIVISOR;
last_hwtc_rest = diff % (TRC_HWTC_DIVISOR);
/* We increase the scaled timestamp by the scaled amount */
last_timestamp += diff_scaled;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.1.2
* Trace Recorder Library for Tracealyzer v4.1.1
* Percepio AB, www.percepio.com
*
* trcStreamingRecorder.c
@ -38,7 +38,7 @@
*
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2017.
* Copyright Percepio AB, 2018.
* www.percepio.com
******************************************************************************/
@ -121,7 +121,7 @@ typedef struct{
} ObjectDataTable;
typedef struct{
uint8_t Status;
uint16_t Status; /* 16 bit to avoid implicit padding (warnings) */
uint16_t BytesRemaining;
char* WritePointer;
} PageType;
@ -135,13 +135,6 @@ typedef struct{
#define PSF_ASSERT(_assert, _err) if (! (_assert)){ prvTraceError(_err); return; }
#define PSF_ERROR_NONE 0
#define PSF_ERROR_EVENT_CODE_TOO_LARGE 1
#define PSF_ERROR_ISR_NESTING_OVERFLOW 2
#define PSF_ERROR_DWT_NOT_SUPPORTED 3
#define PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED 4
#define PSF_ERROR_AUTO_ISR_END 5
/* Part of the PSF format - encodes the number of 32-bit params in an event */
#define PARAM_COUNT(n) ((n & 0xF) << 12)
@ -190,9 +183,9 @@ int32_t isPendingContextSwitch = 0;
uint32_t uiTraceTickCount = 0;
uint32_t timestampFrequency = 0;
uint32_t DroppedEventCounter = 0; // Total number of dropped events (failed allocations)
uint32_t TotalBytesRemaining_LowWaterMark = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;
uint32_t TotalBytesRemaining = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;
uint32_t DroppedEventCounter = 0;
uint32_t TotalBytesRemaining_LowWaterMark = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
uint32_t TotalBytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
PageType PageInfo[TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT];
@ -228,9 +221,9 @@ volatile uint32_t NoRoomForObjectData = 0;
/*******************************************************************************
* LongestSymbolName
*
* Updated in prvTraceSaveSymbol. Should not exceed SYMBOL_MAX_LENGTH, otherwise
* symbol names will be truncated. In that case, set SYMBOL_MAX_LENGTH to (at
* least) this value.
* Updated in prvTraceSaveSymbol. Should not exceed TRC_CFG_SYMBOL_MAX_LENGTH,
* otherwise symbol names will be truncated. In that case, set
* TRC_CFG_SYMBOL_MAX_LENGTH to (at least) this value.
******************************************************************************/
volatile uint32_t LongestSymbolName = 0;
@ -245,15 +238,23 @@ volatile uint32_t LongestSymbolName = 0;
******************************************************************************/
volatile uint32_t MaxBytesTruncated = 0;
uint16_t CurrentFilterMask = 0xFFFF;
uint16_t CurrentFilterGroup = FilterGroup0;
/* Internal common function for storing string events */
static void prvTraceStoreStringEventHelper( int nArgs,
uint16_t eventID,
traceString userEvtChannel,
int len,
const char* str,
va_list* vl);
static void prvTraceStoreSimpleStringEventHelper( traceString userEvtChannel,
/* Not static to avoid warnings from SysGCC/PPC */
void prvTraceStoreSimpleStringEventHelper(traceString userEvtChannel,
const char* str);
/* Stores the header information on Start */
static void prvTraceStoreHeader(void);
@ -278,7 +279,8 @@ static void prvPageReadComplete(int pageIndex);
/* Retrieve a buffer page to write to. */
static int prvAllocateBufferPage(int prevPage);
/* Get the current buffer page index and remaining number of bytes. */
/* Get the current buffer page index (return value) and the number
of valid bytes in the buffer page (bytesUsed). */
static int prvGetBufferPage(int32_t* bytesUsed);
/* Performs timestamping using definitions in trcHardwarePort.h */
@ -287,6 +289,9 @@ static uint32_t prvGetTimestamp32(void);
/* Signal an error. */
void prvTraceError(int errCode);
/* Signal an warning (does not stop the recorder). */
void prvTraceWarning(int errCode);
/******************************************************************************
* vTraceInstanceFinishedNow
*
@ -315,21 +320,6 @@ void vTraceInstanceFinishedNext(void)
prvTraceStoreEvent0(PSF_EVENT_IFE_NEXT);
}
/*******************************************************************************
* xTraceRegisterString
*
* Stores a name for a user event channel, returns the handle.
******************************************************************************/
traceString xTraceRegisterString(const char* name)
{
prvTraceSaveSymbol((const void*)name, name);
/* Always save in symbol table, if the recording has not yet started */
prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, (const char*)name, (uint32_t)name);
return (traceString)name;
}
/*******************************************************************************
* vTraceStoreKernelObjectName
*
@ -362,6 +352,23 @@ void vTraceSetFrequency(uint32_t frequency)
timestampFrequency = frequency;
}
#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
/*******************************************************************************
* xTraceRegisterString
*
* Stores a name for a user event channel, returns the handle.
******************************************************************************/
traceString xTraceRegisterString(const char* name)
{
prvTraceSaveSymbol((const void*)name, name);
/* Always save in symbol table, if the recording has not yet started */
prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, (const char*)name, (uint32_t)name);
return (traceString)name;
}
/******************************************************************************
* vTracePrint
*
@ -450,7 +457,7 @@ void vTracePrintF(traceString chn, const char* fmt, ...)
{
if (fmt[i] == '%')
{
if (fmt[i + 1] != '%')
if (fmt[i + 1] != 0 && fmt[i + 1] != '%')
{
nArgs++; /* Found an argument */
}
@ -463,15 +470,15 @@ void vTracePrintF(traceString chn, const char* fmt, ...)
if (chn != NULL)
{
prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs + 1), chn, fmt, &vl);
prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs + 1), chn, i, fmt, &vl);
}
else
{
prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs), chn, fmt, &vl);
prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs), chn, i, fmt, &vl);
}
va_end(vl);
}
#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) */
/*******************************************************************************
* xTraceSetISRProperties
@ -536,11 +543,13 @@ void vTraceStoreISRBegin(traceHandle handle)
if (ISR_stack_index == -1)
isPendingContextSwitch = 0;
if (ISR_stack_index < TRC_CFG_MAX_ISR_NESTING - 1)
if (ISR_stack_index < (TRC_CFG_MAX_ISR_NESTING) - 1)
{
ISR_stack_index++;
ISR_stack[ISR_stack_index] = (uint32_t)handle;
#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
prvTraceStoreEvent1(PSF_EVENT_ISR_BEGIN, (uint32_t)handle);
#endif
TRACE_EXIT_CRITICAL_SECTION();
}
else
@ -579,6 +588,8 @@ void vTraceStoreISREnd(int isTaskSwitchRequired)
TRACE_ENTER_CRITICAL_SECTION();
(void)ISR_stack;
/* Is there a pending task-switch? (perhaps from an earlier ISR) */
isPendingContextSwitch |= isTaskSwitchRequired;
@ -586,8 +597,10 @@ void vTraceStoreISREnd(int isTaskSwitchRequired)
{
ISR_stack_index--;
#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
/* Store return to interrupted ISR (if nested ISRs)*/
prvTraceStoreEvent1(PSF_EVENT_ISR_RESUME, (uint32_t)ISR_stack[ISR_stack_index]);
#endif
}
else
{
@ -596,7 +609,9 @@ void vTraceStoreISREnd(int isTaskSwitchRequired)
/* Store return to interrupted task, if no context switch will occur in between. */
if ((isPendingContextSwitch == 0) || (prvTraceIsSchedulerSuspended()))
{
#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
prvTraceStoreEvent1(PSF_EVENT_TS_RESUME, (uint32_t)TRACE_GET_CURRENT_TASK());
#endif
}
}
@ -607,43 +622,106 @@ void vTraceStoreISREnd(int isTaskSwitchRequired)
/*******************************************************************************
* xTraceGetLastError
*
* Returns the last error, if any.
* Returns the last error or warning, as a string, or NULL if none.
*****************************************************************************/
const char* xTraceGetLastError(void)
{
if (NoRoomForSymbol > 0)
{
return "TRC_CFG_SYMBOL_TABLE_SLOTS too small.";
}
if (LongestSymbolName > (TRC_CFG_SYMBOL_MAX_LENGTH))
{
return "TRC_CFG_SYMBOL_MAX_LENGTH too small.";
}
if (NoRoomForObjectData > 0)
{
return "TRC_CFG_OBJECT_DATA_SLOTS too small.";
}
if (MaxBytesTruncated > 0)
{
return "String or User Event too long.";
}
/* Note: the error messages are short, in order to fit in a User Event.
Instead, the users can read more in the below comments.*/
switch (errorCode)
{
case PSF_WARNING_SYMBOL_TABLE_SLOTS:
/* There was not enough symbol table slots for storing symbol names.
The number of missing slots is counted by NoRoomForSymbol. Inspect this
variable and increase TRC_CFG_SYMBOL_TABLE_SLOTS by at least that value. */
return "Exceeded SYMBOL_TABLE_SLOTS (see xTraceGetLastError)";
case PSF_WARNING_SYMBOL_MAX_LENGTH:
/* A symbol name exceeded TRC_CFG_SYMBOL_MAX_LENGTH in length.
Make sure the symbol names are at most TRC_CFG_SYMBOL_MAX_LENGTH,
or inspect LongestSymbolName and increase TRC_CFG_SYMBOL_MAX_LENGTH
to at least this value. */
return "Exceeded SYMBOL_MAX_LENGTH (see xTraceGetLastError)";
case PSF_WARNING_OBJECT_DATA_SLOTS:
/* There was not enough symbol object table slots for storing object
properties, such as task priorites. The number of missing slots is
counted by NoRoomForObjectData. Inspect this variable and increase
TRC_CFG_OBJECT_DATA_SLOTS by at least that value. */
return "Exceeded OBJECT_DATA_SLOTS (see xTraceGetLastError)";
case PSF_WARNING_STRING_TOO_LONG:
/* Some string argument was longer than the maximum payload size
and has been truncated by "MaxBytesTruncated" bytes.
This may happen for the following functions:
- vTracePrint
- vTracePrintF
- vTraceStoreKernelObjectName
- xTraceRegisterString
- vTraceSetISRProperties
A PSF event may store maximum 60 bytes payload, including data
arguments and string characters. For User Events, also the User
Event Channel (4 bytes) must be squeezed in, if a channel is
specified (can be NULL). */
return "String too long (see xTraceGetLastError)";
case PSF_WARNING_STREAM_PORT_READ:
/* TRC_STREAM_PORT_READ_DATA is expected to return 0 when completed successfully.
This means there is an error in the communication with host/Tracealyzer. */
return "TRC_STREAM_PORT_READ_DATA returned error (!= 0).";
case PSF_WARNING_STREAM_PORT_WRITE:
/* TRC_STREAM_PORT_WRITE_DATA is expected to return 0 when completed successfully.
This means there is an error in the communication with host/Tracealyzer. */
return "TRC_STREAM_PORT_WRITE_DATA returned error (!= 0).";
case PSF_ERROR_EVENT_CODE_TOO_LARGE:
return "An invalid event code was used.";
/* The highest allowed event code is 4095, anything higher is an unexpected error.
Please contact support@percepio.com for assistance.*/
return "Invalid event code (see xTraceGetLastError)";
case PSF_ERROR_ISR_NESTING_OVERFLOW:
return "Too much ISR nesting.";
/* Nesting of ISR trace calls exceeded the limit (TRC_CFG_MAX_ISR_NESTING).
If this is unlikely, make sure that you call vTraceStoreISRExit in the end
of all ISR handlers. Or increase TRC_CFG_MAX_ISR_NESTING. */
return "Exceeded ISR nesting (see xTraceGetLastError)";
case PSF_ERROR_DWT_NOT_SUPPORTED:
return "DWT not supported by this chip.";
/* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip.
DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M
macro normally set by ARM's CMSIS library, since typically available. You can however select
SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/
return "DWT not supported (see xTraceGetLastError)";
case PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED:
return "DWT_CYCCNT not supported by this chip.";
/* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip.
DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M
macro normally set by ARM's CMSIS library, since typically available. You can however select
SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/
return "DWT_CYCCNT not supported (see xTraceGetLastError)";
case PSF_ERROR_TZCTRLTASK_NOT_CREATED:
/* vTraceEnable failed creating the trace control task (TzCtrl) - incorrect parameters (priority?)
or insufficient heap size? */
return "Could not create TzCtrl (see xTraceGetLastError)";
}
return "";
return NULL;
}
/*******************************************************************************
@ -686,6 +764,27 @@ void vTraceSetRecorderDataBuffer(void* pRecorderData)
}
#endif
/*******************************************************************************
* xTraceIsRecordingEnabled
* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0.
******************************************************************************/
int xTraceIsRecordingEnabled(void)
{
return (int)RecorderEnabled;
}
void vTraceSetFilterMask(uint16_t filterMask)
{
CurrentFilterMask = filterMask;
}
void vTraceSetFilterGroup(uint16_t filterGroup)
{
CurrentFilterGroup = filterGroup;
}
/******************************************************************************/
/*** INTERNAL FUNCTIONS *******************************************************/
/******************************************************************************/
@ -697,6 +796,11 @@ static void prvSetRecorderEnabled(uint32_t isEnabled)
TRACE_ALLOC_CRITICAL_SECTION();
if (RecorderEnabled == isEnabled)
{
return;
}
currentTask = TRACE_GET_CURRENT_TASK();
TRACE_ENTER_CRITICAL_SECTION();
@ -710,7 +814,11 @@ static void prvSetRecorderEnabled(uint32_t isEnabled)
if (RecorderEnabled)
{
prvTraceOnBegin();
TRC_STREAM_PORT_ON_TRACE_BEGIN();
#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
prvPagedEventBufferInit(_TzTraceData);
#endif
eventCounter = 0;
ISR_stack_index = -1;
@ -726,14 +834,14 @@ static void prvSetRecorderEnabled(uint32_t isEnabled)
}
else
{
prvTraceOnEnd();
TRC_STREAM_PORT_ON_TRACE_END();
}
TRACE_EXIT_CRITICAL_SECTION();
}
/* Stores the symbol table on Start */
static void prvTraceStoreSymbolTable()
static void prvTraceStoreSymbolTable(void)
{
uint32_t i = 0;
uint32_t j = 0;
@ -760,7 +868,7 @@ static void prvTraceStoreSymbolTable()
}
/* Stores the object table on Start */
static void prvTraceStoreObjectDataTable()
static void prvTraceStoreObjectDataTable(void)
{
uint32_t i = 0;
uint32_t j = 0;
@ -787,7 +895,7 @@ static void prvTraceStoreObjectDataTable()
}
/* Stores the header information on Start */
static void prvTraceStoreHeader()
static void prvTraceStoreHeader(void)
{
TRACE_ALLOC_CRITICAL_SECTION();
@ -807,7 +915,7 @@ static void prvTraceStoreHeader()
header->symbolSize = SYMBOL_TABLE_SLOT_SIZE;
header->symbolCount = (TRC_CFG_SYMBOL_TABLE_SLOTS);
header->objectDataSize = 8;
header->objectDataCount = TRC_CFG_OBJECT_DATA_SLOTS;
header->objectDataCount = (TRC_CFG_OBJECT_DATA_SLOTS);
TRC_STREAM_PORT_COMMIT_EVENT(header, sizeof(PSFHeaderInfo));
}
}
@ -815,64 +923,17 @@ static void prvTraceStoreHeader()
}
/* Store the current warnings */
static void prvTraceStoreWarnings()
static void prvTraceStoreWarnings(void)
{
TRACE_ALLOC_CRITICAL_SECTION();
TRACE_ENTER_CRITICAL_SECTION();
if (RecorderEnabled)
{
if (NoRoomForSymbol > 0)
{
vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_TABLE_SLOTS too small. Add %d slots.", NoRoomForSymbol);
}
const char* errStr = xTraceGetLastError();
if (LongestSymbolName > 0)
if (errStr != NULL)
{
if (LongestSymbolName > (TRC_CFG_SYMBOL_MAX_LENGTH))
{
vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_MAX_LENGTH too small. Add %d chars.", LongestSymbolName - (TRC_CFG_SYMBOL_MAX_LENGTH));
vTracePrint(trcWarningChannel, errStr);
}
}
if (NoRoomForObjectData > 0)
{
/* We don't know how many objects we actually need to make room for since NoRoomForObjectData can be increased multiple times for the same object! */
vTracePrintF(trcWarningChannel, "TRC_CFG_OBJECT_DATA_SLOTS too small. Add more slots.");
}
if (MaxBytesTruncated > 0)
{
/* Some string event generated a too long string that was truncated.
This may happen for the following functions:
- vTracePrintF
- vTraceStoreKernelObjectName
- vTraceStoreUserEventChannelName
- vTraceSetISRProperties
A PSF event may store maximum 60 bytes payload, including data arguments
and string characters. For User Events, also the User Event Channel ptr
must be squeezed in, if a channel is specified. */
vTracePrintF(trcWarningChannel, "String event too long, up to %d bytes truncated.", MaxBytesTruncated);
}
switch (errorCode)
{
case PSF_ERROR_EVENT_CODE_TOO_LARGE:
break;
case PSF_ERROR_ISR_NESTING_OVERFLOW:
break;
case PSF_ERROR_DWT_NOT_SUPPORTED:
vTracePrintF(trcWarningChannel, "DWT not supported, see prvTraceInitCortexM.");
break;
case PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED:
vTracePrintF(trcWarningChannel, "DWT_CYCCNT not supported, see prvTraceInitCortexM.");
break;
}
}
TRACE_EXIT_CRITICAL_SECTION();
}
/* Store an event with zero parameters (event ID only) */
@ -1035,10 +1096,13 @@ void prvTraceStoreEvent(int nParam, uint16_t eventID, ...)
/* Stories an event with a string and <nParam> 32-bit integer parameters */
void prvTraceStoreStringEvent(int nArgs, uint16_t eventID, const char* str, ...)
{
int len;
va_list vl;
for (len = 0; (str[len] != 0) && (len < 52); len++); /* empty loop */
va_start(vl, str);
prvTraceStoreStringEventHelper(nArgs, eventID, NULL, str, &vl);
prvTraceStoreStringEventHelper(nArgs, eventID, NULL, len, str, &vl);
va_end(vl);
}
@ -1046,9 +1110,10 @@ void prvTraceStoreStringEvent(int nArgs, uint16_t eventID, const char* str, ...)
static void prvTraceStoreStringEventHelper(int nArgs,
uint16_t eventID,
traceString userEvtChannel,
const char* str, va_list* vl)
int len,
const char* str,
va_list* vl)
{
int len;
int nWords;
int nStrWords;
int i;
@ -1057,8 +1122,6 @@ static void prvTraceStoreStringEventHelper( int nArgs,
PSF_ASSERT(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE);
for (len = 0; (str[len] != 0) && (len < 52); len++); /* empty loop */
/* The string length in multiples of 32 bit words (+1 for null character) */
nStrWords = (len+1+3)/4;
@ -1140,7 +1203,7 @@ static void prvTraceStoreStringEventHelper( int nArgs,
}
/* Internal common function for storing string events without additional arguments */
static void prvTraceStoreSimpleStringEventHelper( traceString userEvtChannel,
void prvTraceStoreSimpleStringEventHelper(traceString userEvtChannel,
const char* str)
{
int len;
@ -1465,6 +1528,16 @@ void prvProcessCommand(TracealyzerCommandType* cmd)
}
}
/* Called on warnings, when the recording can continue. */
void prvTraceWarning(int errCode)
{
if (!errorCode)
{
errorCode = errCode;
prvTraceStoreWarnings();
}
}
/* Called on critical errors in the recorder. Stops the recorder! */
void prvTraceError(int errCode)
{
@ -1472,7 +1545,7 @@ void prvTraceError(int errCode)
{
errorCode = errCode;
prvTraceStoreWarnings();
vTracePrintF(trcWarningChannel, "Error detected. Stopped recorder.");
vTracePrintF(trcWarningChannel, "Recorder stopped in prvTraceError()");
prvSetRecorderEnabled(0);
}
@ -1550,7 +1623,7 @@ static uint32_t prvGetTimestamp32(void)
#if ((TRC_HWTC_TYPE == TRC_OS_TIMER_INCR) || (TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))
uint32_t ticks = TRACE_GET_OS_TICKS();
return (TRC_HWTC_COUNT & 0x00FFFFFFU) + ((ticks & 0x000000FFU) << 24);
return ((TRC_HWTC_COUNT) & 0x00FFFFFFU) + ((ticks & 0x000000FFU) << 24);
#endif
}
@ -1563,25 +1636,25 @@ static void prvTraceStoreTSConfig(void)
timestampFrequency = TRC_HWTC_FREQ_HZ;
}
if (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR || TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR)
{
#if (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR || TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR)
prvTraceStoreEvent(5,
PSF_EVENT_TS_CONFIG,
(uint32_t)timestampFrequency,
(uint32_t)TRACE_TICK_RATE_HZ,
(uint32_t)TRC_HWTC_TYPE,
(uint32_t)TRC_CFG_ISR_TAILCHAINING_THRESHOLD,
(uint32_t)TRC_HWTC_PERIOD);
}
else
{
(uint32_t)(TRACE_TICK_RATE_HZ),
(uint32_t)(TRC_HWTC_TYPE),
(uint32_t)(TRC_CFG_ISR_TAILCHAINING_THRESHOLD),
(uint32_t)(TRC_HWTC_PERIOD));
#else
prvTraceStoreEvent(4,
PSF_EVENT_TS_CONFIG,
(uint32_t)timestampFrequency,
(uint32_t)TRACE_TICK_RATE_HZ,
(uint32_t)TRC_HWTC_TYPE,
(uint32_t)TRC_CFG_ISR_TAILCHAINING_THRESHOLD);
}
(uint32_t)(TRACE_TICK_RATE_HZ),
(uint32_t)(TRC_HWTC_TYPE),
(uint32_t)(TRC_CFG_ISR_TAILCHAINING_THRESHOLD));
#endif
}
/* Retrieve a buffer page to write to. */
@ -1590,11 +1663,11 @@ static int prvAllocateBufferPage(int prevPage)
int index;
int count = 0;
index = (prevPage + 1) % TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT;
index = (prevPage + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);
while((PageInfo[index].Status != PAGE_STATUS_FREE) && (count ++ < TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT))
while((PageInfo[index].Status != PAGE_STATUS_FREE) && (count ++ < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT)))
{
index = (index + 1) % TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT;
index = (index + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);
}
if (PageInfo[index].Status == PAGE_STATUS_FREE)
@ -1611,11 +1684,11 @@ static void prvPageReadComplete(int pageIndex)
TRACE_ALLOC_CRITICAL_SECTION();
TRACE_ENTER_CRITICAL_SECTION();
PageInfo[pageIndex].BytesRemaining = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;
PageInfo[pageIndex].WritePointer = &EventBuffer[pageIndex * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE];
PageInfo[pageIndex].BytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
PageInfo[pageIndex].WritePointer = &EventBuffer[pageIndex * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
PageInfo[pageIndex].Status = PAGE_STATUS_FREE;
TotalBytesRemaining += TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;
TotalBytesRemaining += (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
TRACE_EXIT_CRITICAL_SECTION();
}
@ -1625,16 +1698,16 @@ static int prvGetBufferPage(int32_t* bytesUsed)
{
static int8_t lastPage = -1;
int count = 0;
int8_t index = (int8_t) ((lastPage + 1) % TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);
int8_t index = (int8_t) ((lastPage + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT));
while((PageInfo[index].Status != PAGE_STATUS_READ) && (count++ < TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT))
while((PageInfo[index].Status != PAGE_STATUS_READ) && (count++ < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT)))
{
index = (int8_t)((index + 1) % TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);
index = (int8_t)((index + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT));
}
if (PageInfo[index].Status == PAGE_STATUS_READ)
{
*bytesUsed = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE - PageInfo[index].BytesRemaining;
*bytesUsed = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE) - PageInfo[index].BytesRemaining;
lastPage = index;
return index;
}
@ -1645,63 +1718,58 @@ static int prvGetBufferPage(int32_t* bytesUsed)
}
/*******************************************************************************
int32_t prvPagedEventBufferTransfer(int32_t (*writeFunc)(void* data,
uint32_t size),
int32_t* nofBytes)
Transfers one block of trace data, if available for reading. Returns the number
of bytes transfered, or a negative error code. If data was transferred (return
value > 0), it can be good to call this function again until all data available
has been transfered.
This function is intended to be called by a periodic task with a suitable
delay (e.g. 10-100 ms).
Return value: as returned from writeFunc (0 == OK)
Parameters:
- writeFunc
Function pointer (example: int32_t write(void* data, uint32_t size))
The function passed as writeFunc should write "size" bytes from "data" to the
socket/file/channel, and return a status code where 0 means OK,
and any other non-zero value means an error.
- int32_t* nofBytes
Pointer to an integer assigned the number of bytes that was transfered.
* uint32_t prvPagedEventBufferTransfer(void)
*
* Transfers one buffer page of trace data, if a full page is available, using
* the macro TRC_STREAM_PORT_WRITE_DATA as defined in trcStreamingPort.h.
*
* This function is intended to be called the periodic TzCtrl task with a suitable
* delay (e.g. 10-100 ms).
*
* Returns the number of bytes sent. If non-zero, it is good to call this
* again, in order to send any additional data waiting in the buffer.
* If zero, wait a while before calling again.
*
* In case of errors from the streaming interface, it registers a warning
* (PSF_WARNING_STREAM_PORT_WRITE) provided by xTraceGetLastError().
*
*******************************************************************************/
int32_t prvPagedEventBufferTransfer(int32_t (*writeFunc)(void* data, uint32_t size, int32_t* ptrBytesWritten), int32_t* nofBytes)
uint32_t prvPagedEventBufferTransfer(void)
{
int8_t pageToTransfer = -1;
int32_t transferred = 0;
int32_t size = 0;
int32_t bytesTransferredTotal = 0;
int32_t bytesTransferredNow = 0;
int32_t bytesToTransfer;
pageToTransfer = (int8_t)prvGetBufferPage(nofBytes);
size = *nofBytes; // The number of bytes we want to transfer
transferred = 0; // The number of bytes we have transferred so far
pageToTransfer = (int8_t)prvGetBufferPage(&bytesToTransfer);
/* bytesToTransfer now contains the number of "valid" bytes in the buffer page, that should be transmitted.
There might be some unused junk bytes in the end, that must be ignored. */
if (pageToTransfer > -1)
{
while (1) // Keep going until we have transferred all that we intended to
while (1) /* Keep going until we have transferred all that we intended to */
{
if (writeFunc(&EventBuffer[pageToTransfer * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE + transferred], (uint32_t)(size - transferred), nofBytes) == 0)
if (TRC_STREAM_PORT_WRITE_DATA(
&EventBuffer[pageToTransfer * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE) + bytesTransferredTotal],
(uint32_t)(bytesToTransfer - bytesTransferredTotal),
&bytesTransferredNow) == 0)
{
// Write was successful. Update the number of transferred bytes.
transferred += *nofBytes;
if (size == transferred)
/* Write was successful. Update the number of transferred bytes. */
bytesTransferredTotal += bytesTransferredNow;
if (bytesTransferredTotal == bytesToTransfer)
{
// All bytes have been transferred. Mark as Complete and return.
*nofBytes = transferred;
/* All bytes have been transferred. Mark the buffer page as "Read Complete" (so it can be written to) and return OK. */
prvPageReadComplete(pageToTransfer);
return 0;
return (uint32_t)bytesTransferredTotal;
}
}
else
{
*nofBytes = 0;
return 1;
/* Some error from the streaming interface... */
prvTraceWarning(PSF_WARNING_STREAM_PORT_WRITE);
return 0;
}
}
}
@ -1709,19 +1777,16 @@ int32_t prvPagedEventBufferTransfer(int32_t (*writeFunc)(void* data, uint32_t si
}
/*******************************************************************************
void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)
Returns a pointer to an available location in the buffer able to store the
requested size.
Return value: The pointer.
Parameters:
- sizeOfEvent
The size of the event that is to be placed in the buffer.
* void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)
*
* Returns a pointer to an available location in the buffer able to store the
* requested size.
*
* Return value: The pointer.
*
* Parameters:
* - sizeOfEvent: The size of the event that is to be placed in the buffer.
*
*******************************************************************************/
void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)
{
@ -1767,19 +1832,15 @@ void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)
}
/*******************************************************************************
void prvPagedEventBufferInit(char* buffer)
Assigns the buffer to use and initializes the PageInfo structure.
Return value: void
Parameters:
- buffer
Pointer to the buffer location that is dynamically or statically allocated by
the caller.
* void prvPagedEventBufferInit(char* buffer)
*
* Assigns the buffer to use and initializes the PageInfo structure.
*
* Return value: void
*
* Parameters:
* - char* buffer: pointer to the trace data buffer, allocated by the caller.
*
*******************************************************************************/
void prvPagedEventBufferInit(char* buffer)
{
@ -1789,13 +1850,14 @@ void prvPagedEventBufferInit(char* buffer)
EventBuffer = buffer;
TRACE_ENTER_CRITICAL_SECTION();
for (i = 0; i < TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT; i++)
for (i = 0; i < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT); i++)
{
PageInfo[i].BytesRemaining = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;
PageInfo[i].WritePointer = &EventBuffer[i * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE];
PageInfo[i].BytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
PageInfo[i].WritePointer = &EventBuffer[i * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
PageInfo[i].Status = PAGE_STATUS_FREE;
}
TRACE_EXIT_CRITICAL_SECTION();
}
#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/

View file

@ -1,7 +0,0 @@
Directories:
+ The FreeRTOS-Plus/Source contains the source code of each FreeRTOS+ product.
+ See http://www.FreeRTOS.org for FreeRTOS documentation. See
http://www.freertos.org/plus for FreeRTOS+ documentation.