mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Update trace recorder code.
Add TCP Echo server to the FreeR_Plus_TCP_Minimal_Window_Simulator project.
This commit is contained in:
parent
f7fc215247
commit
d525d5092d
|
@ -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 */
|
||||
|
|
@ -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 */
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,15 +595,19 @@ static void prvInitialiseDHCP( void )
|
|||
xDHCPData.ulTransactionId++;
|
||||
}
|
||||
|
||||
xDHCPData.xUseBroadcast = 0;
|
||||
xDHCPData.ulOfferedIPAddress = 0UL;
|
||||
xDHCPData.ulDHCPServerAddress = 0UL;
|
||||
xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
|
||||
/* Check for random number generator API failure. */
|
||||
if( 0 != xDHCPData.ulTransactionId )
|
||||
{
|
||||
xDHCPData.xUseBroadcast = 0;
|
||||
xDHCPData.ulOfferedIPAddress = 0UL;
|
||||
xDHCPData.ulDHCPServerAddress = 0UL;
|
||||
xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
|
||||
|
||||
/* Create the DHCP socket if it has not already been created. */
|
||||
prvCreateDHCPSocket();
|
||||
FreeRTOS_debug_printf( ( "prvInitialiseDHCP: start after %lu ticks\n", dhcpINITIAL_TIMER_PERIOD ) );
|
||||
vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );
|
||||
/* Create the DHCP socket if it has not already been created. */
|
||||
prvCreateDHCPSocket();
|
||||
FreeRTOS_debug_printf( ( "prvInitialiseDHCP: start after %lu ticks\n", dhcpINITIAL_TIMER_PERIOD ) );
|
||||
vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -675,18 +677,17 @@ const uint32_t ulMandatoryOptions = 2ul; /* DHCP server address, and the correct
|
|||
state machine is expecting. */
|
||||
ulProcessed++;
|
||||
}
|
||||
else if( *pucByte == ( uint8_t ) dhcpMESSAGE_TYPE_NACK )
|
||||
{
|
||||
if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_ACK )
|
||||
{
|
||||
/* Start again. */
|
||||
xDHCPData.eDHCPState = eWaitingSendFirstDiscover;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *pucByte == ( uint8_t ) dhcpMESSAGE_TYPE_NACK )
|
||||
{
|
||||
if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_ACK )
|
||||
{
|
||||
/* Start again. */
|
||||
xDHCPData.eDHCPState = eWaitingSendFirstDiscover;
|
||||
}
|
||||
}
|
||||
/* Stop processing further options. */
|
||||
ucLength = 0;
|
||||
/* Don't process other message types. */
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -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 )++;
|
||||
}
|
||||
|
@ -788,12 +788,12 @@ const int32_t l500ms = 500;
|
|||
{
|
||||
ulSavedSequenceNumber = ulCurrentSequenceNumber;
|
||||
|
||||
/* Clean up all sequence received between ulSequenceNumber
|
||||
/* Clean up all sequence received between ulSequenceNumber
|
||||
and ulSequenceNumber + ulLength since they are duplicated.
|
||||
If the server is forced to retransmit packets several time
|
||||
in a row it might send a batch of concatenated packet for
|
||||
speed. So we cannot rely on the packets between
|
||||
ulSequenceNumber and ulSequenceNumber + ulLength to be
|
||||
If the server is forced to retransmit packets several time
|
||||
in a row it might send a batch of concatenated packet for
|
||||
speed. So we cannot rely on the packets between
|
||||
ulSequenceNumber and ulSequenceNumber + ulLength to be
|
||||
sequential and it is better to just clean them out. */
|
||||
do
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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*/
|
||||
|
|
|
@ -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;
|
||||
|
@ -84,7 +84,12 @@ typedef const void* traceHandle;
|
|||
#endif
|
||||
|
||||
#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,11 +213,14 @@ 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
|
||||
*
|
||||
* A faster version of vTracePrintF, that only allows for logging a string.
|
||||
|
@ -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)
|
||||
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) RecorderDataType bufname;
|
||||
#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
|
||||
#define TRC_ALLOC_CUSTOM_BUFFER(bufname)
|
||||
#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,82 +623,105 @@ 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() \
|
||||
prvTraceSetTaskInstanceFinished(TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()));
|
||||
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) \
|
||||
prvTraceStoreTaskReady(TRACE_GET_TASK_NUMBER(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
|
||||
#define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB)
|
||||
|
@ -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 ) \
|
||||
prvTraceStoreTaskswitch(TRACE_GET_TASK_NUMBER(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) \
|
||||
prvTraceStoreKernelCall(SERVICE, 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)); \
|
||||
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) \
|
||||
prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); \
|
||||
prvTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB));
|
||||
if (TRACE_GET_TASK_FILTER(pxTCB) & CurrentFilterMask) \
|
||||
{ \
|
||||
prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); \
|
||||
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) \
|
||||
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);
|
||||
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); \
|
||||
}
|
||||
|
||||
/* 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) \
|
||||
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));
|
||||
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 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.
|
||||
|
@ -979,8 +1070,8 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t objHandle; /* the handle of the closed object */
|
||||
uint16_t symbolIndex; /* the name of the closed object */
|
||||
uint8_t objHandle; /* the handle of the closed object */
|
||||
uint16_t symbolIndex; /* the name of the closed object */
|
||||
} ObjCloseNameEvent;
|
||||
|
||||
typedef struct
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -10,7 +10,7 @@
|
|||
* Read more at http://percepio.com/2016/10/05/rtos-tracing/
|
||||
*
|
||||
* Terms of Use
|
||||
* This file is part of the trace recorder library (RECORDER), which is the
|
||||
* 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
|
||||
|
@ -19,14 +19,14 @@
|
|||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
* 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.
|
||||
|
@ -41,10 +41,10 @@
|
|||
*
|
||||
* Tabs are used for indent in this file (1 tab = 4 spaces)
|
||||
*
|
||||
* Copyright Percepio AB, 2016.
|
||||
* Copyright Percepio AB, 2018.
|
||||
* www.percepio.com
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef TRC_CONFIG_H
|
||||
#define TRC_CONFIG_H
|
||||
|
||||
|
@ -56,8 +56,8 @@ extern "C" {
|
|||
|
||||
/******************************************************************************
|
||||
* Include of processor header file
|
||||
*
|
||||
* Here you may need to include the header file for your processor. This is
|
||||
*
|
||||
* Here you may need to include the header file for your processor. This is
|
||||
* required at least for the ARM Cortex-M port, that uses the ARM CMSIS API.
|
||||
* Try that in case of build problems. Otherwise, remove the #error line below.
|
||||
*****************************************************************************/
|
||||
|
@ -71,14 +71,14 @@ extern "C" {
|
|||
* All ARM Cortex-M MCUs are supported by "TRC_HARDWARE_PORT_ARM_Cortex_M".
|
||||
* This port uses the DWT cycle counter for Cortex-M3/M4/M7 devices, which is
|
||||
* available on most such devices. In case your device don't have DWT support,
|
||||
* you will get an error message opening the trace. In that case, you may
|
||||
* you will get an error message opening the trace. In that case, you may
|
||||
* force the recorder to use SysTick timestamping instead, using this define:
|
||||
*
|
||||
* #define TRC_CFG_ARM_CM_USE_SYSTICK
|
||||
*
|
||||
* For ARM Cortex-M0/M0+ devices, SysTick mode is used automatically.
|
||||
*
|
||||
* See trcHardwarePort.h for available ports and information on how to
|
||||
* See trcHardwarePort.h for available ports and information on how to
|
||||
* define your own port, if not already present.
|
||||
******************************************************************************/
|
||||
#define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_NOT_SET
|
||||
|
@ -88,7 +88,7 @@ extern "C" {
|
|||
*
|
||||
* Specify what recording mode to use. Snapshot means that the data is saved in
|
||||
* an internal RAM buffer, for later upload. Streaming means that the data is
|
||||
* transferred continuously to the host PC.
|
||||
* transferred continuously to the host PC.
|
||||
*
|
||||
* For more information, see http://percepio.com/2016/10/05/rtos-tracing/
|
||||
* and the Tracealyzer User Manual.
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -110,37 +265,24 @@ extern "C" {
|
|||
* TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC - Malloc in vTraceEnable
|
||||
* TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM - Use vTraceSetRecorderDataBuffer
|
||||
*
|
||||
* Static and dynamic mode does the allocation for you, either in compile time
|
||||
* (static) or in runtime (malloc).
|
||||
* The custom mode allows you to control how and where the allocation is made,
|
||||
* Static and dynamic mode does the allocation for you, either in compile time
|
||||
* (static) or in runtime (malloc).
|
||||
* The custom mode allows you to control how and where the allocation is made,
|
||||
* for details see TRC_ALLOC_CUSTOM_BUFFER and vTraceSetRecorderDataBuffer().
|
||||
******************************************************************************/
|
||||
#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
|
||||
*
|
||||
*
|
||||
* Defines how many levels of interrupt nesting the recorder can handle, in
|
||||
* case multiple ISRs are traced and ISR nesting is possible. If this
|
||||
* is exceeded, the particular ISR will not be traced and the recorder then
|
||||
* is exceeded, the particular ISR will not be traced and the recorder then
|
||||
* logs an error message. This setting is used to allocate an internal stack
|
||||
* for keeping track of the previous execution context (4 byte per entry).
|
||||
* for keeping track of the previous execution context (4 byte per entry).
|
||||
*
|
||||
* This value must be a non-zero positive constant, at least 1.
|
||||
*
|
||||
*
|
||||
* Default value: 8
|
||||
*****************************************************************************/
|
||||
#define TRC_CFG_MAX_ISR_NESTING 8
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/*******************************************************************************
|
||||
* Trace Recorder Library for Tracealyzer v3.1.2
|
||||
* Trace Recorder Library for Tracealyzer v4.1.1
|
||||
* Percepio AB, www.percepio.com
|
||||
*
|
||||
* trcSnapshotConfig.h
|
||||
*
|
||||
* Configuration parameters for trace recorder library in snapshot mode.
|
||||
* Configuration parameters for trace recorder library in snapshot mode.
|
||||
* Read more at http://percepio.com/2016/10/05/rtos-tracing/
|
||||
*
|
||||
* Terms of Use
|
||||
* This file is part of the trace recorder library (RECORDER), which is the
|
||||
* 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
|
||||
|
@ -17,14 +17,14 @@
|
|||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
* 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.
|
||||
|
@ -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,44 +57,28 @@
|
|||
* - TRC_SNAPSHOT_MODE_STOP_WHEN_FULL
|
||||
* Default is TRC_SNAPSHOT_MODE_RING_BUFFER.
|
||||
*
|
||||
* With TRC_CFG_SNAPSHOT_MODE set to TRC_SNAPSHOT_MODE_RING_BUFFER, the
|
||||
* events are stored in a ring buffer, i.e., where the oldest events are
|
||||
* With TRC_CFG_SNAPSHOT_MODE set to TRC_SNAPSHOT_MODE_RING_BUFFER, the
|
||||
* events are stored in a ring buffer, i.e., where the oldest events are
|
||||
* overwritten when the buffer becomes full. This allows you to get the last
|
||||
* events leading up to an interesting state, e.g., an error, without having
|
||||
* events leading up to an interesting state, e.g., an error, without having
|
||||
* to store the whole run since startup.
|
||||
*
|
||||
* When TRC_CFG_SNAPSHOT_MODE is TRC_SNAPSHOT_MODE_STOP_WHEN_FULL, the
|
||||
* When TRC_CFG_SNAPSHOT_MODE is TRC_SNAPSHOT_MODE_STOP_WHEN_FULL, the
|
||||
* recording is stopped when the buffer becomes full. This is useful for
|
||||
* recording events following a specific state, e.g., the startup sequence.
|
||||
*****************************************************************************/
|
||||
#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
|
||||
*
|
||||
* Macro which should be defined as an integer value.
|
||||
*
|
||||
* This defines the capacity of the event buffer, i.e., the number of records
|
||||
* it may store. Most events use one record (4 byte), although some events
|
||||
* it may store. Most events use one record (4 byte), although some events
|
||||
* require multiple 4-byte records. You should adjust this to the amount of RAM
|
||||
* available in the target system.
|
||||
*
|
||||
*
|
||||
* Default value is 1000, which means that 4000 bytes is allocated for the
|
||||
* event buffer.
|
||||
******************************************************************************/
|
||||
|
@ -106,111 +90,43 @@
|
|||
* A group of macros which should be defined as integer values, zero or larger.
|
||||
*
|
||||
* These define the capacity of the Object Property Table, i.e., the maximum
|
||||
* number of objects active at any given point, within each object class (e.g.,
|
||||
* number of objects active at any given point, within each object class (e.g.,
|
||||
* task, queue, semaphore, ...).
|
||||
*
|
||||
*
|
||||
* If tasks or other objects are deleted in your system, this
|
||||
* setting does not limit the total amount of objects created, only the number
|
||||
* of objects that have been successfully created but not yet deleted.
|
||||
*
|
||||
* Using too small values will cause vTraceError to be called, which stores an
|
||||
* Using too small values will cause vTraceError to be called, which stores an
|
||||
* error message in the trace that is shown when opening the trace file. The
|
||||
* error message can also be retrieved using xTraceGetLastError.
|
||||
*
|
||||
* It can be wise to start with large values for these constants,
|
||||
* It can be wise to start with large values for these constants,
|
||||
* unless you are very confident on these numbers. Then do a recording and
|
||||
* check the actual usage by selecting View menu -> Trace Details ->
|
||||
* Resource Usage -> Object Table.
|
||||
* 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
|
||||
*
|
||||
* Macro which should be defined as either zero (0) or one (1).
|
||||
* Macro which should be defined as either zero (0) or one (1).
|
||||
*
|
||||
* If this is zero (0), the support for logging floating point values in
|
||||
* If this is zero (0), the support for logging floating point values in
|
||||
* vTracePrintF is stripped out, in case floating point values are not used or
|
||||
* supported by the platform used.
|
||||
*
|
||||
* Floating point values are only used in vTracePrintF and its subroutines, to
|
||||
* allow for storing float (%f) or double (%lf) arguments.
|
||||
* Floating point values are only used in vTracePrintF and its subroutines, to
|
||||
* allow for storing float (%f) or double (%lf) arguments.
|
||||
*
|
||||
* vTracePrintF can be used with integer and string arguments in either case.
|
||||
*
|
||||
|
@ -218,29 +134,16 @@
|
|||
*****************************************************************************/
|
||||
#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
|
||||
*
|
||||
* Macro which should be defined as an integer value.
|
||||
*
|
||||
* This defines the capacity of the symbol table, in bytes. This symbol table
|
||||
* This defines the capacity of the symbol table, in bytes. This symbol table
|
||||
* stores User Events labels and names of deleted tasks, queues, or other kernel
|
||||
* objects. If you don't use User Events or delete any kernel
|
||||
* objects. If you don't use User Events or delete any kernel
|
||||
* objects you set this to a very low value. The minimum recommended value is 4.
|
||||
* A size of zero (0) is not allowed since a zero-sized array may result in a
|
||||
* A size of zero (0) is not allowed since a zero-sized array may result in a
|
||||
* 32-bit pointer, i.e., using 4 bytes rather than 0.
|
||||
*
|
||||
* Default value is 800.
|
||||
|
@ -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 ********************************************************
|
||||
|
@ -272,14 +177,14 @@
|
|||
* The remaining settings are not necessary to modify but allows for optimizing
|
||||
* the recorder setup for your specific needs, e.g., to exclude events that you
|
||||
* are not interested in, in order to get longer traces.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* TRC_CFG_HEAP_SIZE_BELOW_16M
|
||||
*
|
||||
* An integer constant that can be used to reduce the buffer usage of memory
|
||||
* allocation events (malloc/free). This value should be 1 if the heap size is
|
||||
* below 16 MB (2^24 byte), and you can live with reported addresses showing the
|
||||
* allocation events (malloc/free). This value should be 1 if the heap size is
|
||||
* below 16 MB (2^24 byte), and you can live with reported addresses showing the
|
||||
* lower 24 bits only. If 0, you get the full 32-bit addresses.
|
||||
*
|
||||
* Default value is 0.
|
||||
|
@ -289,16 +194,16 @@
|
|||
/******************************************************************************
|
||||
* TRC_CFG_USE_IMPLICIT_IFE_RULES
|
||||
*
|
||||
* Macro which should be defined as either zero (0) or one (1).
|
||||
* Macro which should be defined as either zero (0) or one (1).
|
||||
* Default is 1.
|
||||
*
|
||||
* Tracealyzer groups the events into "instances" based on Instance Finish
|
||||
* Events (IFEs), produced either by default rules or calls to the recorder
|
||||
* functions vTraceInstanceFinishedNow and vTraceInstanceFinishedNext.
|
||||
* functions vTraceInstanceFinishedNow and vTraceInstanceFinishedNext.
|
||||
*
|
||||
* If TRC_CFG_USE_IMPLICIT_IFE_RULES is one (1), the default IFE rules is
|
||||
* used, resulting in a "typical" grouping of events into instances.
|
||||
* If these rules don't give appropriate instances in your case, you can
|
||||
* If these rules don't give appropriate instances in your case, you can
|
||||
* override the default rules using vTraceInstanceFinishedNow/Next for one
|
||||
* or several tasks. The default IFE rules are then disabled for those tasks.
|
||||
*
|
||||
|
@ -306,15 +211,15 @@
|
|||
* disabled globally. You must then call vTraceInstanceFinishedNow or
|
||||
* vTraceInstanceFinishedNext to manually group the events into instances,
|
||||
* otherwise the tasks will appear a single long instance.
|
||||
*
|
||||
*
|
||||
* The default IFE rules count the following events as "instance finished":
|
||||
* - Task delay, delay until
|
||||
* - Task suspend
|
||||
* - Blocking on "input" operations, i.e., when the task is waiting for the
|
||||
* - Blocking on "input" operations, i.e., when the task is waiting for the
|
||||
* next a message/signal/event. But only if this event is blocking.
|
||||
*
|
||||
* For details, see trcSnapshotKernelPort.h and look for references to the
|
||||
* macro trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED.
|
||||
* For details, see trcSnapshotKernelPort.h and look for references to the
|
||||
* macro trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED.
|
||||
*****************************************************************************/
|
||||
#define TRC_CFG_USE_IMPLICIT_IFE_RULES 1
|
||||
|
||||
|
@ -322,21 +227,21 @@
|
|||
* TRC_CFG_USE_16BIT_OBJECT_HANDLES
|
||||
*
|
||||
* Macro which should be defined as either zero (0) or one (1).
|
||||
*
|
||||
* If set to 0 (zero), the recorder uses 8-bit handles to identify kernel
|
||||
*
|
||||
* If set to 0 (zero), the recorder uses 8-bit handles to identify kernel
|
||||
* objects such as tasks and queues. This limits the supported number of
|
||||
* concurrently active objects to 255 of each type (tasks, queues, mutexes,
|
||||
* etc.) Note: 255, not 256, since handle 0 is reserved.
|
||||
*
|
||||
* If set to 1 (one), the recorder uses 16-bit handles to identify kernel
|
||||
* If set to 1 (one), the recorder uses 16-bit handles to identify kernel
|
||||
* objects such as tasks and queues. This limits the supported number of
|
||||
* concurrent objects to 65535 of each type (object class). However, since the
|
||||
* object property table is limited to 64 KB, the practical limit is about
|
||||
* 3000 objects in total.
|
||||
*
|
||||
* 3000 objects in total.
|
||||
*
|
||||
* Default is 0 (8-bit handles)
|
||||
*
|
||||
* NOTE: An object with handle above 255 will use an extra 4-byte record in
|
||||
* NOTE: An object with handle above 255 will use an extra 4-byte record in
|
||||
* the event buffer whenever the object is referenced. Moreover, some internal
|
||||
* tables in the recorder gets slightly larger when using 16-bit handles.
|
||||
*****************************************************************************/
|
||||
|
@ -345,11 +250,11 @@
|
|||
/******************************************************************************
|
||||
* TRC_CFG_USE_TRACE_ASSERT
|
||||
*
|
||||
* Macro which should be defined as either zero (0) or one (1).
|
||||
* Macro which should be defined as either zero (0) or one (1).
|
||||
* Default is 1.
|
||||
*
|
||||
* If this is one (1), the TRACE_ASSERT macro (used at various locations in the
|
||||
* trace recorder) will verify that a relevant condition is true.
|
||||
* If this is one (1), the TRACE_ASSERT macro (used at various locations in the
|
||||
* trace recorder) will verify that a relevant condition is true.
|
||||
* If the condition is false, prvTraceError() will be called, which stops the
|
||||
* recording and stores an error message that is displayed when opening the
|
||||
* trace in Tracealyzer.
|
||||
|
@ -365,18 +270,18 @@
|
|||
*
|
||||
* Macro which should be defined as an integer value.
|
||||
*
|
||||
* Set TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER to 1 to enable the
|
||||
* Set TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER to 1 to enable the
|
||||
* separate user event buffer (UB).
|
||||
* In this mode, user events are stored separately from other events,
|
||||
* e.g., RTOS events. Thereby you can get a much longer history of
|
||||
* user events as they don't need to share the buffer space with more
|
||||
* frequent events.
|
||||
* In this mode, user events are stored separately from other events,
|
||||
* e.g., RTOS events. Thereby you can get a much longer history of
|
||||
* user events as they don't need to share the buffer space with more
|
||||
* frequent events.
|
||||
*
|
||||
* The UB is typically used with the snapshot ring-buffer mode, so the
|
||||
* recording can continue when the main buffer gets full. And since the
|
||||
* recording can continue when the main buffer gets full. And since the
|
||||
* main buffer then overwrites the earliest events, Tracealyzer displays
|
||||
* "Unknown Actor" instead of task scheduling for periods with UB data only.
|
||||
*
|
||||
*
|
||||
* In UB mode, user events are structured as UB channels, which contains
|
||||
* a channel name and a default format string. Register a UB channel using
|
||||
* xTraceRegisterUBChannel.
|
||||
|
@ -390,31 +295,31 @@
|
|||
* traceString chn1 = xTraceRegisterString("Channel 1");
|
||||
* traceString fmt1 = xTraceRegisterString("Event!");
|
||||
* traceUBChannel UBCh1 = xTraceRegisterUBChannel(chn1, fmt1);
|
||||
*
|
||||
*
|
||||
* traceString chn2 = xTraceRegisterString("Channel 2");
|
||||
* traceString fmt2 = xTraceRegisterString("X: %d, Y: %d");
|
||||
* traceUBChannel UBCh2 = xTraceRegisterUBChannel(chn2, fmt2);
|
||||
*
|
||||
*
|
||||
* // Result in "[Channel 1] Event!"
|
||||
* vTraceUBEvent(UBCh1);
|
||||
* vTraceUBEvent(UBCh1);
|
||||
*
|
||||
* // Result in "[Channel 2] X: 23, Y: 19"
|
||||
* vTraceUBData(UBCh2, 23, 19);
|
||||
*
|
||||
* You can also use the other user event functions, like vTracePrintF.
|
||||
* as they are then rerouted to the UB instead of the main event buffer.
|
||||
* vTracePrintF then looks up the correct UB channel based on the
|
||||
* vTracePrintF then looks up the correct UB channel based on the
|
||||
* provided channel name and format string, or creates a new UB channel
|
||||
* if no match is found. The format string should therefore not contain
|
||||
* if no match is found. The format string should therefore not contain
|
||||
* "random" messages but mainly format specifiers. Random strings should
|
||||
* be stored using %s and with the string as an argument.
|
||||
*
|
||||
* // Creates a new UB channel ("Channel 2", "%Z: %d")
|
||||
* vTracePrintF(chn2, "%Z: %d", value1);
|
||||
*
|
||||
*
|
||||
* // Finds the existing UB channel
|
||||
* vTracePrintF(chn2, "%Z: %d", value2);
|
||||
|
||||
|
||||
******************************************************************************/
|
||||
#define TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER 0
|
||||
|
||||
|
@ -449,22 +354,22 @@
|
|||
*
|
||||
* Macro which should be defined as an integer value.
|
||||
*
|
||||
* If tracing multiple ISRs, this setting allows for accurate display of the
|
||||
* If tracing multiple ISRs, this setting allows for accurate display of the
|
||||
* context-switching also in cases when the ISRs execute in direct sequence.
|
||||
*
|
||||
*
|
||||
* vTraceStoreISREnd normally assumes that the ISR returns to the previous
|
||||
* context, i.e., a task or a preempted ISR. But if another traced ISR
|
||||
* context, i.e., a task or a preempted ISR. But if another traced ISR
|
||||
* executes in direct sequence, Tracealyzer may incorrectly display a minimal
|
||||
* fragment of the previous context in between the ISRs.
|
||||
*
|
||||
* By using TRC_CFG_ISR_TAILCHAINING_THRESHOLD you can avoid this. This is
|
||||
* By using TRC_CFG_ISR_TAILCHAINING_THRESHOLD you can avoid this. This is
|
||||
* however a threshold value that must be measured for your specific setup.
|
||||
* See http://percepio.com/2014/03/21/isr_tailchaining_threshold/
|
||||
*
|
||||
* The default setting is 0, meaning "disabled" and that you may get an
|
||||
* The default setting is 0, meaning "disabled" and that you may get an
|
||||
* extra fragments of the previous context in between tail-chained ISRs.
|
||||
*
|
||||
* Note: This setting has separate definitions in trcSnapshotConfig.h and
|
||||
* Note: This setting has separate definitions in trcSnapshotConfig.h and
|
||||
* trcStreamingConfig.h, since it is affected by the recorder mode.
|
||||
******************************************************************************/
|
||||
#define TRC_CFG_ISR_TAILCHAINING_THRESHOLD 0
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)";
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -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)*/
|
|
@ -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 ****************************/
|
|
@ -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_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) writeToRTT(_ptrData, _size, _ptrBytesWritten)
|
||||
|
||||
#define TRC_STREAM_PORT_ON_TRACE_BEGIN() /* Do nothing */
|
||||
#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */
|
||||
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) readFromRTT(_ptrData, _size, _ptrBytesRead)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
|
||||
#include "trcRecorder.h"
|
||||
|
||||
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
|
||||
#if(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
@ -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;
|
||||
result=CDC_Transmit_FS(data, size);
|
||||
*noOfBytesSent = size;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
317
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/tracealyzer_readme.txt
Normal file
317
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/tracealyzer_readme.txt
Normal 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.
|
|
@ -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
|
||||
|
@ -7,7 +7,7 @@
|
|||
* The FreeRTOS-specific parts of the trace recorder
|
||||
*
|
||||
* Terms of Use
|
||||
* This file is part of the trace recorder library (RECORDER), which is the
|
||||
* 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
|
||||
|
@ -16,14 +16,14 @@
|
|||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
* 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.
|
||||
|
@ -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,40 +50,210 @@
|
|||
|
||||
#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:
|
||||
|
||||
The hardware port selected in trcConfig.h uses the operating system timer for the
|
||||
|
||||
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
|
||||
macro in your trcConfig.h file. But then the time scale may be incorrect during
|
||||
tickless idle periods.
|
||||
|
||||
|
||||
To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT
|
||||
in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros
|
||||
accordingly, using a free running counter or an independent periodic interrupt timer.
|
||||
See trcHardwarePort.h for details.
|
||||
|
||||
For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the
|
||||
DWT cycle counter for timestamping in these cases.
|
||||
|
||||
For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the
|
||||
DWT cycle counter for timestamping in these cases.
|
||||
*/
|
||||
|
||||
|
||||
#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_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
#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;
|
||||
#if (defined(configENABLE_BACKWARD_COMPATIBILITY) && configENABLE_BACKWARD_COMPATIBILITY == 0)
|
||||
/* We're explicitly not using compatibility mode */
|
||||
|
@ -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,14 +306,31 @@ 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");
|
||||
|
||||
TRC_STREAM_PORT_INIT();
|
||||
/* 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)
|
||||
{
|
||||
|
@ -147,9 +338,15 @@ void vTraceEnable(int startOption)
|
|||
do
|
||||
{
|
||||
bytes = 0;
|
||||
TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);
|
||||
|
||||
status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);
|
||||
}
|
||||
|
||||
if (bytes == sizeof(TracealyzerCommandType))
|
||||
if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))
|
||||
{
|
||||
if (prvIsValidCommand(&msg))
|
||||
{
|
||||
|
@ -158,7 +355,7 @@ void vTraceEnable(int startOption)
|
|||
/* On start, init and reset the timestamping */
|
||||
TRC_PORT_SPECIFIC_INIT();
|
||||
}
|
||||
|
||||
|
||||
prvProcessCommand(&msg);
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +366,7 @@ void vTraceEnable(int startOption)
|
|||
{
|
||||
/* We start streaming directly - this assumes that the interface is ready! */
|
||||
TRC_PORT_SPECIFIC_INIT();
|
||||
|
||||
|
||||
msg.cmdCode = CMD_SET_ACTIVE;
|
||||
msg.param1 = 1;
|
||||
prvProcessCommand(&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,9 +496,9 @@ 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,
|
||||
/* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
|
||||
INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in
|
||||
FreeRTOSConfig.h for this function to be available. */
|
||||
|
||||
|
@ -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,9 +818,9 @@ 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,
|
||||
/* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
|
||||
INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in
|
||||
FreeRTOSConfig.h for this function to be available. */
|
||||
|
||||
|
|
|
@ -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,8 +145,7 @@ 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;
|
||||
static uint32_t heapMemUsage = 0;
|
||||
#endif
|
||||
|
||||
#if (TRC_CFG_SCHEDULING_ONLY == 0)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -368,7 +376,10 @@ void vTraceStart(void)
|
|||
******************************************************************************/
|
||||
void vTraceStop(void)
|
||||
{
|
||||
RecorderDataPtr->recorderActive = 0;
|
||||
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++;
|
||||
static traceHandle handle = 0;
|
||||
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)
|
||||
{
|
||||
|
@ -1566,18 +1585,15 @@ 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);
|
||||
tr = (TREvent*)prvTraceNextFreeEventBufferSlot();
|
||||
if (tr != NULL)
|
||||
{
|
||||
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
|
||||
hnd8 = prvTraceGet8BitHandle(handle);
|
||||
tr = (TREvent*)prvTraceNextFreeEventBufferSlot();
|
||||
if (tr != NULL)
|
||||
{
|
||||
tr->type = DIV_TASK_READY;
|
||||
tr->dts = dts3;
|
||||
tr->objHandle = hnd8;
|
||||
prvTraceUpdateCounters();
|
||||
}
|
||||
tr->type = DIV_TASK_READY;
|
||||
tr->dts = dts3;
|
||||
tr->objHandle = hnd8;
|
||||
prvTraceUpdateCounters();
|
||||
}
|
||||
}
|
||||
trcCRITICAL_SECTION_END();
|
||||
|
@ -1667,44 +1683,40 @@ void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_si
|
|||
|
||||
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);
|
||||
ms = (MemEventSize *)prvTraceNextFreeEventBufferSlot();
|
||||
|
||||
if (ms != NULL)
|
||||
{
|
||||
dts1 = (uint8_t)prvTraceGetDTS(0xFF);
|
||||
size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);
|
||||
ms = (MemEventSize *)prvTraceNextFreeEventBufferSlot();
|
||||
ms->dts = dts1;
|
||||
ms->type = NULL_EVENT; /* Updated when all events are written */
|
||||
ms->size = size_low;
|
||||
prvTraceUpdateCounters();
|
||||
|
||||
if (ms != NULL)
|
||||
/* Storing a second record with address (signals "failed" if null) */
|
||||
#if (TRC_CFG_HEAP_SIZE_BELOW_16M)
|
||||
/* If the heap address range is within 16 MB, i.e., the upper 8 bits
|
||||
of addresses are constant, this optimization avoids storing an extra
|
||||
event record by ignoring the upper 8 bit of the address */
|
||||
addr_low = address & 0xFFFF;
|
||||
addr_high = (address >> 16) & 0xFF;
|
||||
#else
|
||||
/* The whole 32 bit address is stored using a second event record
|
||||
for the upper 16 bit */
|
||||
addr_low = (uint16_t)prvTraceGetParam(0xFFFF, address);
|
||||
addr_high = 0;
|
||||
#endif
|
||||
|
||||
ma = (MemEventAddr *) prvTraceNextFreeEventBufferSlot();
|
||||
if (ma != NULL)
|
||||
{
|
||||
ms->dts = dts1;
|
||||
ms->type = NULL_EVENT; /* Updated when all events are written */
|
||||
ms->size = size_low;
|
||||
prvTraceUpdateCounters();
|
||||
|
||||
/* Storing a second record with address (signals "failed" if null) */
|
||||
#if (TRC_CFG_HEAP_SIZE_BELOW_16M)
|
||||
/* If the heap address range is within 16 MB, i.e., the upper 8 bits
|
||||
of addresses are constant, this optimization avoids storing an extra
|
||||
event record by ignoring the upper 8 bit of the address */
|
||||
addr_low = address & 0xFFFF;
|
||||
addr_high = (address >> 16) & 0xFF;
|
||||
#else
|
||||
/* The whole 32 bit address is stored using a second event record
|
||||
for the upper 16 bit */
|
||||
addr_low = (uint16_t)prvTraceGetParam(0xFFFF, address);
|
||||
addr_high = 0;
|
||||
#endif
|
||||
|
||||
ma = (MemEventAddr *) prvTraceNextFreeEventBufferSlot();
|
||||
if (ma != NULL)
|
||||
{
|
||||
ma->addr_low = addr_low;
|
||||
ma->addr_high = addr_high;
|
||||
ma->type = (uint8_t) (ecode + 1); /* Note this! */
|
||||
ms->type = (uint8_t) ecode;
|
||||
prvTraceUpdateCounters();
|
||||
RecorderDataPtr->heapMemUsage = heapMemUsage;
|
||||
}
|
||||
ma->addr_low = addr_low;
|
||||
ma->addr_high = addr_high;
|
||||
ma->type = (uint8_t) (ecode + 1); /* Note this! */
|
||||
ms->type = (uint8_t) ecode;
|
||||
prvTraceUpdateCounters();
|
||||
RecorderDataPtr->heapMemUsage = heapMemUsage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1755,23 +1767,15 @@ 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)
|
||||
dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);
|
||||
hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);
|
||||
kse = (KernelCall*) prvTraceNextFreeEventBufferSlot();
|
||||
if (kse != NULL)
|
||||
{
|
||||
/* 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);
|
||||
kse = (KernelCall*) prvTraceNextFreeEventBufferSlot();
|
||||
if (kse != NULL)
|
||||
{
|
||||
kse->dts = dts1;
|
||||
kse->type = (uint8_t)ecode;
|
||||
kse->objHandle = hnd8;
|
||||
prvTraceUpdateCounters();
|
||||
}
|
||||
}
|
||||
kse->dts = dts1;
|
||||
kse->type = (uint8_t)ecode;
|
||||
kse->objHandle = hnd8;
|
||||
prvTraceUpdateCounters();
|
||||
}
|
||||
}
|
||||
trcCRITICAL_SECTION_END();
|
||||
|
@ -1818,24 +1822,19 @@ void prvTraceStoreKernelCallWithParam(uint32_t evtcode,
|
|||
}
|
||||
|
||||
trcCRITICAL_SECTION_BEGIN();
|
||||
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && (! inExcludedTask || nISRactive))
|
||||
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
|
||||
{
|
||||
/* Check if the referenced object or the event code is excluded */
|
||||
if (!uiTraceIsObjectExcluded(objectClass, (traceHandle)objectNumber) &&
|
||||
!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
|
||||
dts2 = (uint8_t)prvTraceGetDTS(0xFF);
|
||||
p8 = (uint8_t) prvTraceGetParam(0xFF, param);
|
||||
hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);
|
||||
kse = (KernelCallWithParamAndHandle*) prvTraceNextFreeEventBufferSlot();
|
||||
if (kse != NULL)
|
||||
{
|
||||
dts2 = (uint8_t)prvTraceGetDTS(0xFF);
|
||||
p8 = (uint8_t) prvTraceGetParam(0xFF, param);
|
||||
hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);
|
||||
kse = (KernelCallWithParamAndHandle*) prvTraceNextFreeEventBufferSlot();
|
||||
if (kse != NULL)
|
||||
{
|
||||
kse->dts = dts2;
|
||||
kse->type = (uint8_t)evtcode;
|
||||
kse->objHandle = hnd8;
|
||||
kse->param = p8;
|
||||
prvTraceUpdateCounters();
|
||||
}
|
||||
kse->dts = dts2;
|
||||
kse->type = (uint8_t)evtcode;
|
||||
kse->objHandle = hnd8;
|
||||
kse->param = p8;
|
||||
prvTraceUpdateCounters();
|
||||
}
|
||||
}
|
||||
trcCRITICAL_SECTION_END();
|
||||
|
@ -1913,22 +1912,17 @@ void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t para
|
|||
}
|
||||
|
||||
trcCRITICAL_SECTION_BEGIN();
|
||||
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task
|
||||
&& (! inExcludedTask || nISRactive))
|
||||
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
|
||||
{
|
||||
/* Check if the event code is excluded */
|
||||
if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
|
||||
dts6 = (uint8_t)prvTraceGetDTS(0xFF);
|
||||
restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);
|
||||
kse = (KernelCallWithParam16*) prvTraceNextFreeEventBufferSlot();
|
||||
if (kse != NULL)
|
||||
{
|
||||
dts6 = (uint8_t)prvTraceGetDTS(0xFF);
|
||||
restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);
|
||||
kse = (KernelCallWithParam16*) prvTraceNextFreeEventBufferSlot();
|
||||
if (kse != NULL)
|
||||
{
|
||||
kse->dts = dts6;
|
||||
kse->type = (uint8_t)evtcode;
|
||||
kse->param = restParam;
|
||||
prvTraceUpdateCounters();
|
||||
}
|
||||
kse->dts = dts6;
|
||||
kse->type = (uint8_t)evtcode;
|
||||
kse->param = restParam;
|
||||
prvTraceUpdateCounters();
|
||||
}
|
||||
}
|
||||
trcCRITICAL_SECTION_END();
|
||||
|
@ -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,8 +2508,11 @@ void vTraceSetFrequency(uint32_t frequency)
|
|||
void prvTraceError(const char* msg)
|
||||
{
|
||||
/* Stop the recorder */
|
||||
vTraceStop();
|
||||
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
const char* str);
|
||||
|
||||
/* 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
|
||||
|
@ -578,6 +587,8 @@ void vTraceStoreISREnd(int isTaskSwitchRequired)
|
|||
TRACE_ALLOC_CRITICAL_SECTION();
|
||||
|
||||
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,8 +814,12 @@ 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;
|
||||
prvTraceStoreHeader();
|
||||
|
@ -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)
|
||||
const char* errStr = xTraceGetLastError();
|
||||
|
||||
if (errStr != NULL)
|
||||
{
|
||||
vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_TABLE_SLOTS too small. Add %d slots.", NoRoomForSymbol);
|
||||
}
|
||||
|
||||
if (LongestSymbolName > 0)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
vTracePrint(trcWarningChannel, errStr);
|
||||
}
|
||||
}
|
||||
TRACE_EXIT_CRITICAL_SECTION();
|
||||
}
|
||||
|
||||
/* Store an event with zero parameters (event ID only) */
|
||||
|
@ -1035,20 +1096,24 @@ 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);
|
||||
}
|
||||
|
||||
/* Internal common function for storing string events */
|
||||
static void prvTraceStoreStringEventHelper( int nArgs,
|
||||
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;
|
||||
|
@ -1056,8 +1121,6 @@ static void prvTraceStoreStringEventHelper( int nArgs,
|
|||
TRACE_ALLOC_CRITICAL_SECTION();
|
||||
|
||||
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,8 +1203,8 @@ static void prvTraceStoreStringEventHelper( int nArgs,
|
|||
}
|
||||
|
||||
/* Internal common function for storing string events without additional arguments */
|
||||
static void prvTraceStoreSimpleStringEventHelper( traceString userEvtChannel,
|
||||
const char* str)
|
||||
void prvTraceStoreSimpleStringEventHelper(traceString userEvtChannel,
|
||||
const char* str)
|
||||
{
|
||||
int len;
|
||||
int nWords;
|
||||
|
@ -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.
|
||||
|
||||
*******************************************************************************/
|
||||
int32_t prvPagedEventBufferTransfer(int32_t (*writeFunc)(void* data, uint32_t size, int32_t* ptrBytesWritten), int32_t* nofBytes)
|
||||
* 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().
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t prvPagedEventBufferTransfer(void)
|
||||
{
|
||||
int8_t pageToTransfer = -1;
|
||||
int32_t transferred = 0;
|
||||
int32_t size = 0;
|
||||
|
||||
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
|
||||
int32_t bytesTransferredTotal = 0;
|
||||
int32_t bytesTransferredNow = 0;
|
||||
int32_t bytesToTransfer;
|
||||
|
||||
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)*/
|
||||
|
|
|
@ -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.
|
||||
|
Loading…
Reference in a new issue