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