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