1 /*
2 * Percepio Trace Recorder for Tracealyzer v4.6.6
3 * Copyright 2021 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * The implementation for errors.
9 */
10
11 #include <trcRecorder.h>
12
13 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
14
15 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
16
17 /* We skip the slot for TRC_ERROR_NONE so error code 1 is the first bit */
18 #define GET_ERROR_WARNING_FLAG(errorCode) (pxErrorInfo->uiErrorAndWarningFlags & (1 << ((errorCode) - 1)))
19 #define SET_ERROR_WARNING_FLAG(errorCode) (pxErrorInfo->uiErrorAndWarningFlags |= (1 << ((errorCode) - 1)))
20
21 traceResult prvTraceErrorPrint(uint32_t uiErrorCode);
22 traceResult prvTraceErrorGetDescription(uint32_t uiErrorCode, const char** pszDesc);
23
24 typedef struct TraceErrorInfo
25 {
26 uint32_t uiErrorAndWarningFlags;
27 uint32_t uiErrorCode;
28 TraceStringHandle_t xWarningChannel;
29 } TraceErrorInfo_t;
30
31 static TraceErrorInfo_t* pxErrorInfo;
32
xTraceErrorInitialize(TraceErrorBuffer_t * pxBuffer)33 traceResult xTraceErrorInitialize(TraceErrorBuffer_t* pxBuffer)
34 {
35 TRC_ASSERT_EQUAL_SIZE(TraceErrorBuffer_t, TraceErrorInfo_t);
36
37 /* This should never fail */
38 TRC_ASSERT(pxBuffer != 0);
39
40 pxErrorInfo = (TraceErrorInfo_t*)pxBuffer;
41
42 pxErrorInfo->uiErrorAndWarningFlags = 0;
43 pxErrorInfo->uiErrorCode = 0;
44 pxErrorInfo->xWarningChannel = 0;
45
46 xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ERROR);
47
48 return TRC_SUCCESS;
49 }
50
51 /* Called on warnings, when the recording can continue. */
xTraceWarning(uint32_t uiErrorCode)52 traceResult xTraceWarning(uint32_t uiErrorCode)
53 {
54 /* Probably good to verify this */
55 if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR))
56 {
57 /* If not initialized */
58 return TRC_FAIL;
59 }
60
61 if (GET_ERROR_WARNING_FLAG(uiErrorCode) == 0)
62 {
63 /* Will never reach this point more than once per warning type, since we verify if uiErrorAndWarningFlags[uiErrorCode] has already been set */
64 SET_ERROR_WARNING_FLAG(uiErrorCode);
65
66 prvTraceErrorPrint(uiErrorCode);
67 }
68
69 return TRC_SUCCESS;
70 }
71
72 /* Called on critical errors in the recorder. Stops the recorder! */
xTraceError(uint32_t uiErrorCode)73 traceResult xTraceError(uint32_t uiErrorCode)
74 {
75 /* Probably good to verify this */
76 if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR))
77 {
78 return TRC_FAIL;
79 }
80
81 if (pxErrorInfo->uiErrorCode == TRC_ERROR_NONE)
82 {
83 /* Will never reach this point more than once, since we verify if uiErrorCode has already been set */
84 SET_ERROR_WARNING_FLAG(uiErrorCode);
85 pxErrorInfo->uiErrorCode = uiErrorCode;
86
87 if (prvTraceErrorPrint(uiErrorCode) == TRC_FAIL)
88 {
89 xTraceDisable();
90
91 return TRC_FAIL;
92 }
93
94 xTracePrint(pxErrorInfo->xWarningChannel, "Recorder stopped in xTraceError(...)!");
95 xTraceDisable();
96 }
97
98 return TRC_SUCCESS;
99 }
100
101 /*******************************************************************************
102 * xTraceErrorGetLast
103 *
104 * Returns the last error or warning, as a string, or NULL if none.
105 *****************************************************************************/
xTraceErrorGetLast(const char ** pszError)106 traceResult xTraceErrorGetLast(const char **pszError)
107 {
108 /* Probably good to verify this */
109 if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR))
110 {
111 return TRC_FAIL;
112 }
113
114 /* This should never fail */
115 TRC_ASSERT(pszError != 0);
116
117 return prvTraceErrorGetDescription(pxErrorInfo->uiErrorCode, pszError);
118 }
119
120 /*******************************************************************************
121 * xTraceErrorClear
122 *
123 * Clears any errors.
124 *****************************************************************************/
xTraceErrorClear(void)125 traceResult xTraceErrorClear(void)
126 {
127 /* Probably good to verify this */
128 if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR))
129 {
130 /* If not initialized */
131 return TRC_FAIL;
132 }
133
134 pxErrorInfo->uiErrorCode = TRC_ERROR_NONE;
135
136 return TRC_SUCCESS;
137 }
138
139 /* Returns the error or warning, as a string, or NULL if none. */
prvTraceErrorPrint(uint32_t uiErrorCode)140 traceResult prvTraceErrorPrint(uint32_t uiErrorCode)
141 {
142 const char* szDesc;
143 /* Note: the error messages are short, in order to fit in a User Event.
144 Instead, the users can read more in the below comments.*/
145
146 if (pxErrorInfo->xWarningChannel == 0)
147 {
148 /* The #WFR channel means "Warnings from Recorder" and
149 * is used to store warnings and errors from the recorder.
150 * The abbreviation #WFR is used instead of the longer full name,
151 * to avoid truncation by small slots in the symbol table.
152 * This is translated in Tracealyzer and shown as the full name,
153 * "Warnings from Recorder".
154 */
155 if (xTraceStringRegister("#WFR", &pxErrorInfo->xWarningChannel) == TRC_FAIL)
156 {
157 return TRC_FAIL;
158 }
159 }
160
161 prvTraceErrorGetDescription(uiErrorCode, &szDesc);
162
163 switch (uiErrorCode)
164 {
165 case TRC_WARNING_ENTRY_TABLE_SLOTS:
166 case TRC_WARNING_ENTRY_SYMBOL_MAX_LENGTH:
167 case TRC_WARNING_EVENT_SIZE_TRUNCATED:
168 case TRC_WARNING_STREAM_PORT_READ:
169 case TRC_WARNING_STREAM_PORT_WRITE:
170 case TRC_WARNING_STREAM_PORT_INITIAL_BLOCKING:
171 case TRC_WARNING_STACKMON_NO_SLOTS:
172 case TRC_ERROR_STREAM_PORT_WRITE:
173 case TRC_ERROR_EVENT_CODE_TOO_LARGE:
174 case TRC_ERROR_ISR_NESTING_OVERFLOW:
175 case TRC_ERROR_DWT_NOT_SUPPORTED:
176 case TRC_ERROR_DWT_CYCCNT_NOT_SUPPORTED:
177 case TRC_ERROR_TZCTRLTASK_NOT_CREATED:
178 xTracePrint(pxErrorInfo->xWarningChannel, szDesc);
179 break;
180
181 case TRC_ERROR_ASSERT:
182 /* A TRC_ASSERT has triggered */
183 {
184 TraceUnsignedBaseType_t uxLineNumber;
185 TraceStringHandle_t xFileName;
186
187 if (xTraceAssertGet(&xFileName, &uxLineNumber) == TRC_FAIL)
188 {
189 return TRC_FAIL;
190 }
191
192 xTracePrintF(pxErrorInfo->xWarningChannel, szDesc, xFileName, (uint32_t)uxLineNumber);
193
194 return TRC_SUCCESS;
195 }
196
197 default:
198 /* No error, or an unknown error occurred */
199 xTracePrintF(pxErrorInfo->xWarningChannel, "Unknown error code: 0x%08X", uiErrorCode);
200
201 return TRC_FAIL;
202 }
203
204 return TRC_SUCCESS;
205 }
206
207 /* Returns the error or warning, as a string, or NULL if none. */
prvTraceErrorGetDescription(uint32_t uiErrorCode,const char ** pszDesc)208 traceResult prvTraceErrorGetDescription(uint32_t uiErrorCode, const char** pszDesc)
209 {
210 /* Note: the error messages are short, in order to fit in a User Event.
211 Instead, the users can read more in the below comments.*/
212
213 switch (uiErrorCode)
214 {
215 case TRC_ERROR_NONE:
216 return TRC_FAIL;
217
218 case TRC_WARNING_ENTRY_TABLE_SLOTS:
219 /* There was not enough symbol table slots for storing symbol names.
220 The number of missing slots is counted by NoRoomForSymbol. Inspect this
221 variable and increase TRC_CFG_ENTRY_TABLE_SLOTS by at least that value. */
222
223 *pszDesc = "Exceeded TRC_CFG_ENTRY_TABLE_SLOTS";
224 break;
225
226 case TRC_WARNING_ENTRY_SYMBOL_MAX_LENGTH:
227 /* A symbol name exceeded TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH in length.
228 Make sure the symbol names are at most TRC_CFG_SYMBOL_MAX_LENGTH,
229 or inspect uiLongestSymbolName in trcEntryTable and increase
230 TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH to at least this value. */
231
232 *pszDesc = "Exceeded TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH";
233 break;
234
235 case TRC_WARNING_EVENT_SIZE_TRUNCATED:
236 /* Some arguments was longer than the maximum payload size
237 and has been truncated by "uiMaxBytesTruncated" bytes.
238
239 This usually happens for the following functions:
240 - xTracePrint
241 - xTracePrintF
242 - xTraceStringRegister
243
244 A trace event may store a maximum of 56 bytes payload, including
245 data arguments and string characters. */
246
247 *pszDesc = "Event size exceeded";
248 break;
249
250 case TRC_WARNING_STREAM_PORT_READ:
251 /* TRC_STREAM_PORT_READ_DATA is expected to return 0 when completed successfully.
252 This means there is an error in the communication with host/Tracealyzer. */
253
254 *pszDesc = "TRC_STREAM_PORT_READ_DATA returned error";
255 break;
256
257 case TRC_WARNING_STREAM_PORT_WRITE:
258 /* TRC_STREAM_PORT_WRITE_DATA is expected to return 0 when completed successfully.
259 This means there is an error in the communication with host/Tracealyzer. */
260
261 *pszDesc = "TRC_STREAM_PORT_WRITE_DATA returned error";
262 break;
263
264 case TRC_WARNING_STREAM_PORT_INITIAL_BLOCKING:
265 /* Blocking occurred during xTraceEnable. This happens if the trace buffer is
266 smaller than the initial transmission (trace header, object table, and symbol table). */
267
268 *pszDesc = "Blocking in xTraceEnable";
269 break;
270
271 case TRC_WARNING_STACKMON_NO_SLOTS:
272 /* Some tasks did not fit in the stack monitor. Increase the slot count. */
273
274 *pszDesc = "No slots left in Stack Monitor";
275 break;
276
277 case TRC_ERROR_STREAM_PORT_WRITE:
278 /* TRC_STREAM_PORT_WRITE_DATA is expected to return 0 when completed successfully.
279 This means there is an error in the communication with host/Tracealyzer. */
280
281 *pszDesc = "TRC_STREAM_PORT_WRITE_DATA returned error";
282 break;
283
284 case TRC_ERROR_EVENT_CODE_TOO_LARGE:
285 /* The highest allowed event code is 4095, anything higher is an unexpected error.
286 Please contact support@percepio.com for assistance.*/
287
288 *pszDesc = "Invalid event code";
289 break;
290
291 case TRC_ERROR_ISR_NESTING_OVERFLOW:
292 /* Nesting of ISR trace calls exceeded the limit (TRC_CFG_MAX_ISR_NESTING).
293 If this is unlikely, make sure that you call vTraceStoreISRExit in the end
294 of all ISR handlers. Or increase TRC_CFG_MAX_ISR_NESTING. */
295
296 *pszDesc = "Exceeded ISR nesting";
297 break;
298
299 case TRC_ERROR_DWT_NOT_SUPPORTED:
300 /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip.
301 DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M
302 macro normally set by ARM's CMSIS library, since typically available. You can however select
303 SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/
304
305 *pszDesc = "DWT not supported";
306 break;
307
308 case TRC_ERROR_DWT_CYCCNT_NOT_SUPPORTED:
309 /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip.
310 DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M
311 macro normally set by ARM's CMSIS library, since typically available. You can however select
312 SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/
313
314 *pszDesc = "DWT_CYCCNT not supported";
315 break;
316
317 case TRC_ERROR_TZCTRLTASK_NOT_CREATED:
318 /* xTraceEnable failed creating the trace control task (TzCtrl) - incorrect parameters (priority?)
319 or insufficient heap size? */
320 *pszDesc = "Could not create TzCtrl";
321 break;
322
323 case TRC_ERROR_ASSERT:
324 /* A TRC_ASSERT has triggered */
325 *pszDesc = "ASSERT: %s (%d)";
326 break;
327
328 default:
329 /* An unknown error occurred */
330 *pszDesc = "Unknown error code: 0x%08X";
331 break;
332 }
333
334 return TRC_SUCCESS;
335 }
336
337 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
338
339 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
340