mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-20 03:37:46 -04:00
* * Percepio Trace Recorder v4.6.0 * Add space between inclusion of header and comment * Fix broken posix build - part 1 * Add percepio timer implementation * Remove delted trace recorder header file * Fix Networking demo build * Fix CLI demo * Fix visual studio version number * Fix core header check * Fix more core checks * Fix last of core checks Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Alfred Gedeon <alfred2g@hotmail.com>
161 lines
5.8 KiB
C
161 lines
5.8 KiB
C
/*
|
|
* Trace Recorder for Tracealyzer v4.6.0
|
|
* Copyright 2021 Percepio AB
|
|
* www.percepio.com
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* 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.
|
|
*
|
|
* This stream port is for ITM streaming on Arm Cortex-M devices.
|
|
*
|
|
* To setup Keil uVision for ITM tracing with a Keil ULINKpro (or ULINKplus),
|
|
* see Percepio Application Note PA-021, available at
|
|
* https://percepio.com/2018/05/04/keil-itm-support/
|
|
*
|
|
* To setup IAR Embedded Workbench for ITM tracing with an IAR I-Jet,
|
|
* see Percepio Application Note PA-023, https://percepio.com/iar
|
|
*
|
|
* NOTE: This stream port may block the application in case the ITM port
|
|
* is not ready for more data (the TPIU FIFO has become full). This is
|
|
* necessary to avoid data loss, as the TPIU FIFO is often quite small.
|
|
*
|
|
* --- Direct vs. Indirect ITM streaming ---
|
|
* Direct streaming: By default, this stream port writes directly to the ITM
|
|
* register mode without any RAM buffer. This assumes you have a fast debug
|
|
* probe, like aKeil ULINKpro or IAR I-Jet, to avoid excessive blocking.
|
|
* In case the ITM blocking appears to disturb your application, make sure your
|
|
* debugger is configured for maximum performance, as described in the above
|
|
* Application Nodes.
|
|
*
|
|
* Indirect streaming: If direct streaming gives too much overhead, you may
|
|
* instead try indirect ITM streaming. This is done by enabling the internal
|
|
* RAM buffer, like below. This reconfigures the recorder to store the events
|
|
* in the internal RAM buffer instead of writing them directly to the ITM port.
|
|
*
|
|
* Set TRC_STREAM_PORT_USE_INTERNAL_BUFFER to 1 to use the indirect mode.
|
|
*
|
|
* This increases RAM usage but eliminates peaks in the trace data rate.
|
|
* Moreover, the ITM writes are then performed in a separate task (TzCtrl).
|
|
* You find relevant settings (buffer size etc.) in trcStreamingConfig.h.
|
|
*
|
|
* See also https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming
|
|
*
|
|
* --- One-way vs. Two-way Communication ---
|
|
* The ITM port only provides one-way communication, from target to host.
|
|
* This is sufficient if you start the tracing from the target application,
|
|
* using vTraceEnable(TRC_START). Just make sure to start the Tracealyzer
|
|
* recording before you start the target system.
|
|
*
|
|
* In case you prefer to interactively start and stop the tracing from the host
|
|
* computer, you need two-way communication to send commands to the recorder.
|
|
* This is possible by writing such "start" and "stop" commands to a special
|
|
* buffer, monitored by the recorder library, using the debugger IDE.
|
|
* See trcStreamingPort.c and also the example macro for Keil uVision
|
|
* (Keil-uVision-Tracealyzer-ITM-Exporter.ini).
|
|
*/
|
|
|
|
#include <trcRecorder.h>
|
|
|
|
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
|
|
|
|
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
|
|
|
typedef struct TraceStreamPortFile
|
|
{
|
|
uint8_t buffer[sizeof(TraceUnsignedBaseType_t)];
|
|
} TraceStreamPortFile_t;
|
|
|
|
static TraceStreamPortFile_t* pxStreamPortFile;
|
|
|
|
/* This will be set by the debugger when there is data to be read */
|
|
volatile int32_t tz_host_command_bytes_to_read = 0;
|
|
|
|
/* This will be filled with data from the debugger */
|
|
volatile char tz_host_command_data[32];
|
|
|
|
/* These variables are used for reading commands from the host, using read_from_host().
|
|
* This is not required if using vTraceEnable(TRC_START).
|
|
* A debugger IDE may write to these functions using a macro.
|
|
* An example for Keil is included (Keil-uVision-Tracealyzer-ITM-Exporter.ini). */
|
|
|
|
#define itm_write_32(__data) \
|
|
{\
|
|
if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) && /* Trace enabled? */ \
|
|
(ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled? */ \
|
|
(ITM->TER & (1UL << (TRC_CFG_STREAM_PORT_ITM_PORT)))) /* ITM port enabled? */ \
|
|
{ \
|
|
while (ITM->PORT[TRC_CFG_STREAM_PORT_ITM_PORT].u32 == 0) { /* Do nothing */ } /* Block until room in ITM FIFO - This stream port is always in "blocking mode", since intended for high-speed ITM! */ \
|
|
ITM->PORT[TRC_CFG_STREAM_PORT_ITM_PORT].u32 = __data; /* Write the data */ \
|
|
} \
|
|
}
|
|
|
|
/* This is assumed to execute from within the recorder, with interrupts disabled */
|
|
traceResult prvTraceItmWrite(void* ptrData, uint32_t size, int32_t* ptrBytesWritten)
|
|
{
|
|
uint32_t* ptr32 = (uint32_t*)ptrData;
|
|
|
|
TRC_ASSERT(size % 4 == 0);
|
|
TRC_ASSERT(ptrBytesWritten != 0);
|
|
|
|
*ptrBytesWritten = 0;
|
|
|
|
while (*ptrBytesWritten < (int32_t)size)
|
|
{
|
|
itm_write_32(*ptr32);
|
|
ptr32++;
|
|
*ptrBytesWritten += 4;
|
|
}
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
/* This reads "command" data from a RAM buffer, written by a host macro in the debugger */
|
|
traceResult prvTraceItmRead(void* ptrData, uint32_t uiSize, int32_t* piBytesRead)
|
|
{
|
|
int32_t i;
|
|
uint8_t* bytesBuffer = (uint8_t*)ptrData;
|
|
|
|
TRC_ASSERT(piBytesRead != 0);
|
|
|
|
/* Check if the debugger has updated tz_host_command_bytes_to_read */
|
|
if (tz_host_command_bytes_to_read > 0)
|
|
{
|
|
if (tz_host_command_bytes_to_read != (int32_t)uiSize)
|
|
{
|
|
/* Sanity check. */
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
*piBytesRead = (int32_t)tz_host_command_bytes_to_read;
|
|
|
|
/* Read the bytes */
|
|
for (i = 0; i < tz_host_command_bytes_to_read; i++)
|
|
{
|
|
bytesBuffer[i] = tz_host_command_data[i];
|
|
}
|
|
|
|
/* Reset */
|
|
tz_host_command_bytes_to_read = 0;
|
|
}
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer)
|
|
{
|
|
TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortFile_t);
|
|
|
|
TRC_ASSERT(pxBuffer != 0);
|
|
|
|
pxStreamPortFile = (TraceStreamPortFile_t*)pxBuffer;
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|