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