You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
8.9 KiB
C
268 lines
8.9 KiB
C
/*******************************************************************************
|
|
* 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
|