blob: e3a9c46aa798ef450a6f2a5236d726f294910435 [file] [log] [blame]
/*******************************************************************************
* Trace Recorder Library for Tracealyzer v3.0.2
* Percepio AB, www.percepio.com
*
* trcKernelPort.c
*
* The kernel-specific code for integration with FreeRTOS.
*
* Terms of Use
* This software (the "Tracealyzer Recorder Library") is the intellectual
* property of Percepio AB and may not be sold or in other ways commercially
* redistributed without explicit written permission by Percepio AB.
*
* Separate conditions applies for the SEGGER branded source code included.
*
* The recorder library is free for use together with Percepio products.
* You may distribute the recorder library in its original form, but public
* distribution of modified versions require approval by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB 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 AB, 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 AB 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, 2015.
* www.percepio.com
******************************************************************************/
#include "trcKernelPort.h"
#if (USE_TRACEALYZER_RECORDER == 1)
#include <stdint.h>
#include "trcRecorder.h"
#include "trcStreamPort.h"
#include "task.h"
/* TzCtrl task TCB */
static xTaskHandle HandleTzCtrl;
/* Called by TzCtrl task periodically (every 100 ms) */
static void CheckRecorderStatus(void);
/* The TzCtrl task - receives commands from Tracealyzer (start/stop) */
static portTASK_FUNCTION( TzCtrl, pvParameters );
/* Monitored by TzCtrl task, that give warnings as User Events */
extern volatile uint32_t NoRoomForSymbol;
extern volatile uint32_t NoRoomForObjectData;
extern volatile uint32_t LongestSymbolName;
extern volatile uint32_t MaxBytesTruncated;
#define TRC_PORT_MALLOC(size) pvPortMalloc(size)
#if ((TRC_STREAM_PORT_BLOCKING_TRANSFER == 1) && (TRC_MEASURE_BLOCKING_TIME == 1))
/*** Used in blocking transfer mode, if enabled TRC_MEASURE_BLOCKING_TIME **************/
/* The highest number of cycles used by SEGGER_RTT_Write. */
static volatile int32_t blockingCyclesMax;
/* The number of times SEGGER_RTT_Write has blocked due to a full buffer. */
static volatile uint32_t blockingCount;
/* User Event Channel for giving warnings regarding blocking */
static char* trcDiagnosticsChannel;
#endif /*((TRC_STREAM_PORT_BLOCKING_TRANSFER==1) && (TRC_MEASURE_BLOCKING_TIME))*/
TRC_STREAM_PORT_ALLOCATE_FIELDS()
/* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */
char* trcWarningChannel;
/* Keeps track of previous values, to only react on changes. */
static uint32_t NoRoomForSymbol_last = 0;
static uint32_t NoRoomForObjectData_last = 0;
static uint32_t LongestSymbolName_last = 0;
static uint32_t MaxBytesTruncated_last = 0;
/*******************************************************************************
* prvTraceGetCurrentTaskHandle
*
* Function that returns the handle to the currently executing task.
*
******************************************************************************/
void* prvTraceGetCurrentTaskHandle(void)
{
return xTaskGetCurrentTaskHandle();
}
/*******************************************************************************
* prvIsNewTCB
*
* Function that returns the handle to the currently executing task.
*
******************************************************************************/
static void* pCurrentTCB = NULL;
uint32_t prvIsNewTCB(void* pNewTCB)
{
if (pCurrentTCB != pNewTCB)
{
pCurrentTCB = pNewTCB;
return 1;
}
return 0;
}
/*******************************************************************************
* CheckRecorderStatus
*
* Called by TzCtrl task periodically (every 100 ms - seems reasonable).
* Checks a number of diagnostic variables and give warnings as user events,
* in most cases including a suggested solution.
******************************************************************************/
static void CheckRecorderStatus(void)
{
if (NoRoomForSymbol > NoRoomForSymbol_last)
{
vTracePrintF(trcWarningChannel, "TRC_SYMBOL_TABLE_SLOTS too small. Add %d slots.",
NoRoomForSymbol);
NoRoomForSymbol_last = NoRoomForSymbol;
}
if (NoRoomForObjectData > NoRoomForObjectData_last)
{
vTracePrintF(trcWarningChannel, "TRC_OBJECT_DATA_SLOTS too small. Add %d slots.",
NoRoomForObjectData);
NoRoomForObjectData_last = NoRoomForObjectData;
}
if (LongestSymbolName > LongestSymbolName_last)
{
if (LongestSymbolName > TRC_SYMBOL_MAX_LENGTH)
{
vTracePrintF(trcWarningChannel, "TRC_SYMBOL_MAX_LENGTH too small. Add %d chars.",
LongestSymbolName);
}
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);
MaxBytesTruncated_last = MaxBytesTruncated;
}
#if ((TRC_STREAM_PORT_BLOCKING_TRANSFER==1) && (TRC_MEASURE_BLOCKING_TIME))
if (blockingCount > 0)
{
/* At least one case of blocking since the last check and this is
the longest case. */
vTracePrintF(trcDiagnosticsChannel, "Longest since last: %d us",
(uint32_t)blockingCyclesMax/(TRACE_CPU_CLOCK_HZ/1000000));
blockingCyclesMax = 0;
}
#endif
}
/*******************************************************************************
* vTraceOnTraceBegin
*
* Called on trace begin.
******************************************************************************/
void vTraceOnTraceBegin(void)
{
TRC_STREAM_PORT_ON_TRACE_BEGIN();
}
/*******************************************************************************
* vTraceOnTraceEnd
*
* Called on trace end.
******************************************************************************/
void vTraceOnTraceEnd(void)
{
TRC_STREAM_PORT_ON_TRACE_END();
}
/*******************************************************************************
* TzCtrl
*
* Task for receiving commands from Tracealyzer and for recorder diagnostics.
*
******************************************************************************/
static portTASK_FUNCTION( TzCtrl, pvParameters )
{
TracealyzerCommandType msg;
int bytes = 0;
while (1)
{
bytes = 0;
TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);
if (bytes != 0)
{
if (bytes == sizeof(TracealyzerCommandType))
{
if (isValidCommand(&msg))
{
processCommand(&msg); /* Start or Stop currently... */
}
}
}
do
{
bytes = 0;
TRC_STREAM_PORT_PERIODIC_SEND_DATA(&bytes);
}
while (bytes != 0);
CheckRecorderStatus();
vTaskDelay(TRC_CTRL_TASK_DELAY); /* 10ms */
}
}
/*******************************************************************************
* Trace_Init
*
* The main initialization routine for the trace recorder. Configures the stream
* and activates the TzCtrl task.
* Also sets up the diagnostic User Event channels used by TzCtrl task.
*
******************************************************************************/
void Trace_Init(void)
{
TRC_STREAM_PORT_INIT();
trcWarningChannel = vTraceStoreUserEventChannelName("Warnings from Recorder");
#if ((TRC_STREAM_PORT_BLOCKING_TRANSFER==1) && (TRC_MEASURE_BLOCKING_TIME))
trcDiagnosticsChannel = vTraceStoreUserEventChannelName("Blocking on trace buffer");
#endif
/* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
xTaskCreate( TzCtrl, "TzCtrl", configMINIMAL_STACK_SIZE, NULL, TRC_CTRL_TASK_PRIORITY, &HandleTzCtrl );
}
#endif