1 /*******************************************************************************
\r
2 * Trace Recorder Library for Tracealyzer v3.0.2
\r
3 * Percepio AB, www.percepio.com
\r
7 * The kernel-specific code for integration with FreeRTOS.
\r
10 * This software (the "Tracealyzer Recorder Library") is the intellectual
\r
11 * property of Percepio AB and may not be sold or in other ways commercially
\r
12 * redistributed without explicit written permission by Percepio AB.
\r
14 * Separate conditions applies for the SEGGER branded source code included.
\r
16 * The recorder library is free for use together with Percepio products.
\r
17 * You may distribute the recorder library in its original form, but public
\r
18 * distribution of modified versions require approval by Percepio AB.
\r
21 * The trace tool and recorder library is being delivered to you AS IS and
\r
22 * Percepio AB makes no warranty as to its use or performance. Percepio AB does
\r
23 * not and cannot warrant the performance or results you may obtain by using the
\r
24 * software or documentation. Percepio AB make no warranties, express or
\r
25 * implied, as to noninfringement of third party rights, merchantability, or
\r
26 * fitness for any particular purpose. In no event will Percepio AB, its
\r
27 * technology partners, or distributors be liable to you for any consequential,
\r
28 * incidental or special damages, including any lost profits or lost savings,
\r
29 * even if a representative of Percepio AB has been advised of the possibility
\r
30 * of such damages, or for any claim by any third party. Some jurisdictions do
\r
31 * not allow the exclusion or limitation of incidental, consequential or special
\r
32 * damages, or the exclusion of implied warranties or limitations on how long an
\r
33 * implied warranty may last, so the above limitations may not apply to you.
\r
35 * Tabs are used for indent in this file (1 tab = 4 spaces)
\r
37 * Copyright Percepio AB, 2015.
\r
39 ******************************************************************************/
\r
41 #include "trcKernelPort.h"
\r
43 #if (USE_TRACEALYZER_RECORDER == 1)
\r
46 #include "trcRecorder.h"
\r
47 #include "trcStreamPort.h"
\r
50 /* TzCtrl task TCB */
\r
51 static xTaskHandle HandleTzCtrl;
\r
53 /* Called by TzCtrl task periodically (every 100 ms) */
\r
54 static void CheckRecorderStatus(void);
\r
56 /* The TzCtrl task - receives commands from Tracealyzer (start/stop) */
\r
57 static portTASK_FUNCTION( TzCtrl, pvParameters );
\r
59 /* Monitored by TzCtrl task, that give warnings as User Events */
\r
60 extern volatile uint32_t NoRoomForSymbol;
\r
61 extern volatile uint32_t NoRoomForObjectData;
\r
62 extern volatile uint32_t LongestSymbolName;
\r
63 extern volatile uint32_t MaxBytesTruncated;
\r
65 #define TRC_PORT_MALLOC(size) pvPortMalloc(size)
\r
66 #if ((TRC_STREAM_PORT_BLOCKING_TRANSFER == 1) && (TRC_MEASURE_BLOCKING_TIME == 1))
\r
68 /*** Used in blocking transfer mode, if enabled TRC_MEASURE_BLOCKING_TIME **************/
\r
70 /* The highest number of cycles used by SEGGER_RTT_Write. */
\r
71 static volatile int32_t blockingCyclesMax;
\r
73 /* The number of times SEGGER_RTT_Write has blocked due to a full buffer. */
\r
74 static volatile uint32_t blockingCount;
\r
76 /* User Event Channel for giving warnings regarding blocking */
\r
77 static char* trcDiagnosticsChannel;
\r
79 #endif /*((TRC_STREAM_PORT_BLOCKING_TRANSFER==1) && (TRC_MEASURE_BLOCKING_TIME))*/
\r
81 TRC_STREAM_PORT_ALLOCATE_FIELDS()
\r
83 /* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */
\r
84 char* trcWarningChannel;
\r
86 /* Keeps track of previous values, to only react on changes. */
\r
87 static uint32_t NoRoomForSymbol_last = 0;
\r
88 static uint32_t NoRoomForObjectData_last = 0;
\r
89 static uint32_t LongestSymbolName_last = 0;
\r
90 static uint32_t MaxBytesTruncated_last = 0;
\r
92 /*******************************************************************************
\r
93 * prvTraceGetCurrentTaskHandle
\r
95 * Function that returns the handle to the currently executing task.
\r
97 ******************************************************************************/
\r
98 void* prvTraceGetCurrentTaskHandle(void)
\r
100 return xTaskGetCurrentTaskHandle();
\r
103 /*******************************************************************************
\r
106 * Function that returns the handle to the currently executing task.
\r
108 ******************************************************************************/
\r
109 static void* pCurrentTCB = NULL;
\r
110 uint32_t prvIsNewTCB(void* pNewTCB)
\r
112 if (pCurrentTCB != pNewTCB)
\r
114 pCurrentTCB = pNewTCB;
\r
119 /*******************************************************************************
\r
120 * CheckRecorderStatus
\r
122 * Called by TzCtrl task periodically (every 100 ms - seems reasonable).
\r
123 * Checks a number of diagnostic variables and give warnings as user events,
\r
124 * in most cases including a suggested solution.
\r
125 ******************************************************************************/
\r
126 static void CheckRecorderStatus(void)
\r
128 if (NoRoomForSymbol > NoRoomForSymbol_last)
\r
130 vTracePrintF(trcWarningChannel, "TRC_SYMBOL_TABLE_SLOTS too small. Add %d slots.",
\r
133 NoRoomForSymbol_last = NoRoomForSymbol;
\r
136 if (NoRoomForObjectData > NoRoomForObjectData_last)
\r
138 vTracePrintF(trcWarningChannel, "TRC_OBJECT_DATA_SLOTS too small. Add %d slots.",
\r
139 NoRoomForObjectData);
\r
141 NoRoomForObjectData_last = NoRoomForObjectData;
\r
144 if (LongestSymbolName > LongestSymbolName_last)
\r
146 if (LongestSymbolName > TRC_SYMBOL_MAX_LENGTH)
\r
148 vTracePrintF(trcWarningChannel, "TRC_SYMBOL_MAX_LENGTH too small. Add %d chars.",
\r
149 LongestSymbolName);
\r
151 LongestSymbolName_last = LongestSymbolName;
\r
154 if (MaxBytesTruncated > MaxBytesTruncated_last)
\r
156 /* Some string event generated a too long string that was truncated.
\r
157 This may happen for the following functions:
\r
160 - vTraceStoreKernelObjectName
\r
161 - vTraceStoreUserEventChannelName
\r
162 - vTraceSetISRProperties
\r
164 A PSF event may store maximum 60 bytes payload, including data arguments
\r
165 and string characters. For User Events, also the User Event Channel ptr
\r
166 must be squeezed in, if a channel is specified. */
\r
168 vTracePrintF(trcWarningChannel, "String event too long, up to %d bytes truncated.",
\r
169 MaxBytesTruncated);
\r
171 MaxBytesTruncated_last = MaxBytesTruncated;
\r
174 #if ((TRC_STREAM_PORT_BLOCKING_TRANSFER==1) && (TRC_MEASURE_BLOCKING_TIME))
\r
175 if (blockingCount > 0)
\r
177 /* At least one case of blocking since the last check and this is
\r
178 the longest case. */
\r
179 vTracePrintF(trcDiagnosticsChannel, "Longest since last: %d us",
\r
180 (uint32_t)blockingCyclesMax/(TRACE_CPU_CLOCK_HZ/1000000));
\r
182 blockingCyclesMax = 0;
\r
187 /*******************************************************************************
\r
188 * vTraceOnTraceBegin
\r
190 * Called on trace begin.
\r
191 ******************************************************************************/
\r
192 void vTraceOnTraceBegin(void)
\r
194 TRC_STREAM_PORT_ON_TRACE_BEGIN();
\r
197 /*******************************************************************************
\r
200 * Called on trace end.
\r
201 ******************************************************************************/
\r
202 void vTraceOnTraceEnd(void)
\r
204 TRC_STREAM_PORT_ON_TRACE_END();
\r
207 /*******************************************************************************
\r
210 * Task for receiving commands from Tracealyzer and for recorder diagnostics.
\r
212 ******************************************************************************/
\r
213 static portTASK_FUNCTION( TzCtrl, pvParameters )
\r
215 TracealyzerCommandType msg;
\r
221 TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);
\r
224 if (bytes == sizeof(TracealyzerCommandType))
\r
226 if (isValidCommand(&msg))
\r
228 processCommand(&msg); /* Start or Stop currently... */
\r
236 TRC_STREAM_PORT_PERIODIC_SEND_DATA(&bytes);
\r
238 while (bytes != 0);
\r
240 CheckRecorderStatus();
\r
241 vTaskDelay(TRC_CTRL_TASK_DELAY); /* 10ms */
\r
245 /*******************************************************************************
\r
248 * The main initialization routine for the trace recorder. Configures the stream
\r
249 * and activates the TzCtrl task.
\r
250 * Also sets up the diagnostic User Event channels used by TzCtrl task.
\r
252 ******************************************************************************/
\r
253 void Trace_Init(void)
\r
255 TRC_STREAM_PORT_INIT();
\r
257 trcWarningChannel = vTraceStoreUserEventChannelName("Warnings from Recorder");
\r
259 #if ((TRC_STREAM_PORT_BLOCKING_TRANSFER==1) && (TRC_MEASURE_BLOCKING_TIME))
\r
260 trcDiagnosticsChannel = vTraceStoreUserEventChannelName("Blocking on trace buffer");
\r
263 /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
\r
264 xTaskCreate( TzCtrl, "TzCtrl", configMINIMAL_STACK_SIZE, NULL, TRC_CTRL_TASK_PRIORITY, &HandleTzCtrl );
\r