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 print.
9 */
10
11 #include <trcRecorder.h>
12
13 #if (TRC_USE_TRACEALYZER_RECORDER == 1) && (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
14
15 #include <stdarg.h>
16
17 static traceResult prvTraceVPrintF(const TraceStringHandle_t xChannel, const char* szFormat, uint32_t uiLength, uint32_t uiArgs, va_list* pxVariableList);
18
19 static TracePrintData_t *pxPrintData TRC_CFG_RECORDER_DATA_ATTRIBUTE;
20
xTracePrintInitialize(TracePrintData_t * pxBuffer)21 traceResult xTracePrintInitialize(TracePrintData_t *pxBuffer)
22 {
23 /* This should never fail */
24 TRC_ASSERT(pxBuffer != (void*)0);
25
26 pxPrintData = pxBuffer;
27
28 pxPrintData->defaultChannel = 0;
29 pxPrintData->consoleChannel = 0;
30
31 xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_PRINT);
32
33 return TRC_SUCCESS;
34 }
35
36 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTracePrint(TraceStringHandle_t xChannel,const char * szString)37 traceResult xTracePrint(TraceStringHandle_t xChannel, const char* szString)
38 {
39 uint32_t uiLength;
40 uint32_t i;
41
42 /* We need to check this */
43 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
44 {
45 return TRC_FAIL;
46 }
47
48 if (szString == (void*)0)
49 {
50 szString = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
51 }
52
53 for (i = 0u; (szString[i] != (char)0) && (i < 128u); i++) {} /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress char base type usage checks*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
54
55 uiLength = i + 1u; /* Null termination */
56
57 return prvTraceVPrintF(xChannel, szString, uiLength, 0u, (va_list*)0); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 Suppress conversion of pointer to integer check*/ /*cstat !MISRAC2012-Rule-11.9 Suppress NULL recommendation*/
58 }
59
60 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-16.1 Suppress variable parameter count check*/
xTraceConsoleChannelPrintF(const char * szFormat,...)61 traceResult xTraceConsoleChannelPrintF(const char* szFormat, ...)
62 {
63 traceResult xResult;
64 va_list xVariableList; /*cstat !MISRAC2012-Rule-17.1 Suppress stdarg usage check*/
65
66 /* We need to check this */
67 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
68 {
69 return TRC_FAIL;
70 }
71
72 if (pxPrintData->consoleChannel == 0)
73 {
74 if (xTraceStringRegister("Debug Console", &pxPrintData->consoleChannel) == TRC_FAIL)
75 {
76 return TRC_FAIL;
77 }
78 }
79
80 va_start(xVariableList, szFormat);
81 xResult = xTraceVPrintF(pxPrintData->consoleChannel, szFormat, &xVariableList);
82 va_end(xVariableList);
83
84 return xResult;
85 }
86
87 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-16.1 Suppress variable parameter count check*/
xTracePrintCompactF(const char * szChannel,const char * szFormat,...)88 traceResult xTracePrintCompactF(const char* szChannel, const char* szFormat, ...)
89 {
90 uint32_t i;
91 uint32_t uiArgs = 0u;
92 traceResult xResult;
93 va_list xVariableList; /*cstat !MISRAC2012-Rule-17.1 Suppress stdarg usage check*/
94 TraceUnsignedBaseType_t uxArg1, uxArg2, uxArg3, uxArg4;
95
96 /* We need to check this */
97 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
98 {
99 return TRC_FAIL;
100 }
101
102 if (szFormat == (void*)0)
103 {
104 szFormat = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
105 }
106
107 /* Count the number of arguments in the format string (e.g., %d) */
108 for (i = 0u; (szFormat[i] != (char)0) && (i < 128u); i++) /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress char base type usage checks*/ /*cstat !MISRAC2012-Rule-14.2 Suppress malformed for loop due to i being incremented inside*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
109 {
110 if (szFormat[i] == '%') /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
111 {
112 if (szFormat[i + 1u] == (char)0) /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
113 {
114 /* Found end of string, let for loop detect it */
115 continue; /*cstat !MISRAC2004-14.5 Suppress continue usage check*/
116 }
117
118 if (szFormat[i + 1u] != '%') /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
119 {
120 uiArgs++; /* Found an argument */
121 }
122
123 /* Move past format specifier or non-argument '%' */
124 i++; /*cstat !MISRAC2004-13.6 Suppress i increment inside for loop check*/
125 }
126 }
127
128 va_start(xVariableList, szFormat);
129 switch(uiArgs)
130 {
131 case 0:
132 xResult = xTraceEventCreate2(PSF_EVENT_USER_EVENT_FIXED, (TraceUnsignedBaseType_t)szChannel, (TraceUnsignedBaseType_t)szFormat); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 We need the addresses*/
133 break;
134 case 1:
135 uxArg1 = va_arg(xVariableList, TraceUnsignedBaseType_t);
136 xResult = xTraceEventCreate3(PSF_EVENT_USER_EVENT_FIXED + 1UL, (TraceUnsignedBaseType_t)szChannel, (TraceUnsignedBaseType_t)szFormat, uxArg1); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 We need the addresses*/
137 break;
138 case 2:
139 uxArg1 = va_arg(xVariableList, TraceUnsignedBaseType_t);
140 uxArg2 = va_arg(xVariableList, TraceUnsignedBaseType_t);
141 xResult = xTraceEventCreate4(PSF_EVENT_USER_EVENT_FIXED + 2UL, (TraceUnsignedBaseType_t)szChannel, (TraceUnsignedBaseType_t)szFormat, uxArg1, uxArg2); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 We need the addresses*/
142 break;
143 case 3:
144 uxArg1 = va_arg(xVariableList, TraceUnsignedBaseType_t);
145 uxArg2 = va_arg(xVariableList, TraceUnsignedBaseType_t);
146 uxArg3 = va_arg(xVariableList, TraceUnsignedBaseType_t);
147 xResult = xTraceEventCreate5(PSF_EVENT_USER_EVENT_FIXED + 3UL, (TraceUnsignedBaseType_t)szChannel, (TraceUnsignedBaseType_t)szFormat, uxArg1, uxArg2, uxArg3); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 We need the addresses*/
148 break;
149 case 4:
150 uxArg1 = va_arg(xVariableList, TraceUnsignedBaseType_t);
151 uxArg2 = va_arg(xVariableList, TraceUnsignedBaseType_t);
152 uxArg3 = va_arg(xVariableList, TraceUnsignedBaseType_t);
153 uxArg4 = va_arg(xVariableList, TraceUnsignedBaseType_t);
154 xResult = xTraceEventCreate6(PSF_EVENT_USER_EVENT_FIXED + 4UL, (TraceUnsignedBaseType_t)szChannel, (TraceUnsignedBaseType_t)szFormat, uxArg1, uxArg2, uxArg3, uxArg4); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 We need the addresses*/
155 break;
156 default:
157 xResult = TRC_FAIL;
158 break;
159 }
160 va_end(xVariableList);
161
162 return xResult;
163 }
164
165 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-16.1 Suppress variable parameter count check*/
xTracePrintF(TraceStringHandle_t xChannel,const char * szFormat,...)166 traceResult xTracePrintF(TraceStringHandle_t xChannel, const char* szFormat, ...)
167 {
168 traceResult xResult;
169 va_list xVariableList; /*cstat !MISRAC2012-Rule-17.1 Suppress stdarg usage check*/
170
171 /* We need to check this */
172 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
173 {
174 return TRC_FAIL;
175 }
176
177 va_start(xVariableList, szFormat);
178 xResult = xTraceVPrintF(xChannel, szFormat, &xVariableList);
179 va_end(xVariableList);
180
181 return xResult;
182 }
183
184 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2012-Rule-17.1 Suppress stdarg usage check*/
xTraceVPrintF(TraceStringHandle_t xChannel,const char * szFormat,va_list * pxVariableList)185 traceResult xTraceVPrintF(TraceStringHandle_t xChannel, const char* szFormat, va_list* pxVariableList)
186 {
187 uint32_t i;
188 uint32_t uiArgs = 0u;
189 uint32_t uiLength;
190
191 /* We need to check this */
192 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
193 {
194 return TRC_FAIL;
195 }
196
197 if (szFormat == (void*)0)
198 {
199 szFormat = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
200 }
201
202 /* Count the number of arguments in the format string (e.g., %d) */
203 for (i = 0u; (szFormat[i] != (char)0) && (i < 128u); i++) /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress char base type usage checks*/ /*cstat !MISRAC2012-Rule-14.2 Suppress malformed for loop due to i being incremented inside*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
204 {
205 if (szFormat[i] == '%') /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
206 {
207 if (szFormat[i + 1u] == (char)0) /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
208 {
209 /* Found end of string, let for loop detect it */
210 continue; /*cstat !MISRAC2004-14.5 Suppress continue usage check*/
211 }
212
213 if (szFormat[i + 1u] != '%') /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
214 {
215 uiArgs++; /* Found an argument */
216 }
217
218 /* Move past format specifier or non-argument '%' */
219 i++; /*cstat !MISRAC2004-13.6 Suppress i increment inside for loop check*/
220 }
221 }
222
223 uiLength = i + 1u; /* Null termination */
224
225 return prvTraceVPrintF(xChannel, szFormat, uiLength, uiArgs, pxVariableList);
226 }
227
228 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2012-Rule-17.1 Suppress stdarg usage check*/
prvTraceVPrintF(TraceStringHandle_t xChannel,const char * szFormat,uint32_t uiLength,uint32_t uiArgs,va_list * pxVariableList)229 static traceResult prvTraceVPrintF(TraceStringHandle_t xChannel, const char* szFormat, uint32_t uiLength, uint32_t uiArgs, va_list* pxVariableList)
230 {
231 const uint32_t uiEventCode = PSF_EVENT_USER_EVENT + 1u + uiArgs; /* Add channel (1) */
232 traceResult xResult;
233 TraceUnsignedBaseType_t uxParam1;
234 TraceUnsignedBaseType_t uxParam2;
235 TraceUnsignedBaseType_t uxParam3;
236 TraceUnsignedBaseType_t uxParam4;
237 TraceUnsignedBaseType_t uxParam5;
238
239 if (xChannel == 0)
240 {
241 if (pxPrintData->defaultChannel == 0)
242 {
243 /* Channel is not present */
244 if (xTraceStringRegister("Default", &pxPrintData->defaultChannel) == TRC_FAIL)
245 {
246 return TRC_FAIL;
247 }
248 }
249
250 xChannel = pxPrintData->defaultChannel; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
251 }
252
253 switch (uiArgs)
254 {
255 case 0:
256 xResult = xTraceEventCreateData1(uiEventCode, (TraceUnsignedBaseType_t)xChannel, (TraceUnsignedBaseType_t*)szFormat, uiLength);
257 break;
258 case 1:
259 uxParam1 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
260 xResult = xTraceEventCreateData2(
261 uiEventCode,
262 (TraceUnsignedBaseType_t)xChannel,
263 uxParam1,
264 (TraceUnsignedBaseType_t*)szFormat,
265 uiLength
266 );
267 break;
268 case 2:
269 uxParam1 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
270 uxParam2 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
271 xResult = xTraceEventCreateData3(
272 uiEventCode,
273 (TraceUnsignedBaseType_t)xChannel,
274 uxParam1,
275 uxParam2,
276 (TraceUnsignedBaseType_t*)szFormat,
277 uiLength
278 );
279 break;
280 case 3:
281 uxParam1 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
282 uxParam2 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
283 uxParam3 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
284 xResult = xTraceEventCreateData4(
285 uiEventCode,
286 (TraceUnsignedBaseType_t)xChannel,
287 uxParam1,
288 uxParam2,
289 uxParam3,
290 (TraceUnsignedBaseType_t*)szFormat,
291 uiLength
292 );
293 break;
294 case 4:
295 uxParam1 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
296 uxParam2 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
297 uxParam3 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
298 uxParam4 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
299 xResult = xTraceEventCreateData5(
300 uiEventCode,
301 (TraceUnsignedBaseType_t)xChannel,
302 uxParam1,
303 uxParam2,
304 uxParam3,
305 uxParam4,
306 (TraceUnsignedBaseType_t*)szFormat,
307 uiLength
308 );
309 break;
310 case 5:
311 uxParam1 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
312 uxParam2 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
313 uxParam3 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
314 uxParam4 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
315 uxParam5 = va_arg(*pxVariableList, TraceUnsignedBaseType_t);
316 xResult = xTraceEventCreateData6(
317 uiEventCode,
318 (TraceUnsignedBaseType_t)xChannel,
319 uxParam1,
320 uxParam2,
321 uxParam3,
322 uxParam4,
323 uxParam5,
324 (TraceUnsignedBaseType_t*)szFormat,
325 uiLength
326 );
327 break;
328 default:
329 xResult = TRC_FAIL;
330 break;
331 }
332
333 return xResult;
334 }
335
336 #endif
337