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 print.
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 #if (TRC_CFG_INCLUDE_USER_EVENTS == 1)
18
19 #include <stdarg.h>
20
21 static traceResult prvTraceVPrintF(const TraceStringHandle_t xChannel, const char* szFormat, uint32_t uiLength, uint32_t uiArgs, va_list* pxVariableList);
22
23 static TracePrintData_t *pxPrintData TRC_CFG_RECORDER_DATA_ATTRIBUTE;
24
xTracePrintInitialize(TracePrintData_t * pxBuffer)25 traceResult xTracePrintInitialize(TracePrintData_t *pxBuffer)
26 {
27 /* This should never fail */
28 TRC_ASSERT(pxBuffer != (void*)0);
29
30 pxPrintData = pxBuffer;
31
32 pxPrintData->defaultChannel = 0;
33 pxPrintData->consoleChannel = 0;
34
35 xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_PRINT);
36
37 return TRC_SUCCESS;
38 }
39
40 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTracePrint(TraceStringHandle_t xChannel,const char * szString)41 traceResult xTracePrint(TraceStringHandle_t xChannel, const char* szString)
42 {
43 uint32_t uiLength;
44 uint32_t i;
45
46 /* We need to check this */
47 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
48 {
49 return TRC_FAIL;
50 }
51
52 if (szString == (void*)0)
53 {
54 szString = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
55 }
56
57 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*/
58
59 uiLength = i + 1u; /* Null termination */
60
61 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*/
62 }
63
64 /*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,...)65 traceResult xTraceConsoleChannelPrintF(const char* szFormat, ...)
66 {
67 traceResult xResult;
68 va_list xVariableList; /*cstat !MISRAC2012-Rule-17.1 Suppress stdarg usage check*/
69
70 /* We need to check this */
71 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
72 {
73 return TRC_FAIL;
74 }
75
76 if (pxPrintData->consoleChannel == 0)
77 {
78 if (xTraceStringRegister("Debug Console", &pxPrintData->consoleChannel) == TRC_FAIL)
79 {
80 return TRC_FAIL;
81 }
82 }
83
84 va_start(xVariableList, szFormat);
85 xResult = xTraceVPrintF(pxPrintData->consoleChannel, szFormat, &xVariableList);
86 va_end(xVariableList);
87
88 return xResult;
89 }
90
91 /*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,...)92 traceResult xTracePrintCompactF(const char* szChannel, const char* szFormat, ...)
93 {
94 uint32_t i;
95 uint32_t uiArgs = 0u;
96 traceResult xResult;
97 va_list xVariableList; /*cstat !MISRAC2012-Rule-17.1 Suppress stdarg usage check*/
98 TraceUnsignedBaseType_t uxArg1, uxArg2, uxArg3, uxArg4;
99
100 /* We need to check this */
101 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
102 {
103 return TRC_FAIL;
104 }
105
106 if (szFormat == (void*)0)
107 {
108 szFormat = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
109 }
110
111 /* Count the number of arguments in the format string (e.g., %d) */
112 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*/
113 {
114 if (szFormat[i] == '%') /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
115 {
116 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*/
117 {
118 /* Found end of string, let for loop detect it */
119 continue; /*cstat !MISRAC2004-14.5 Suppress continue usage check*/
120 }
121
122 if (szFormat[i + 1u] != '%') /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
123 {
124 uiArgs++; /* Found an argument */
125 }
126
127 /* Move past format specifier or non-argument '%' */
128 i++; /*cstat !MISRAC2004-13.6 Suppress i increment inside for loop check*/
129 }
130 }
131
132 va_start(xVariableList, szFormat);
133 switch(uiArgs)
134 {
135 case 0:
136 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*/
137 break;
138 case 1:
139 uxArg1 = va_arg(xVariableList, TraceUnsignedBaseType_t);
140 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*/
141 break;
142 case 2:
143 uxArg1 = va_arg(xVariableList, TraceUnsignedBaseType_t);
144 uxArg2 = va_arg(xVariableList, TraceUnsignedBaseType_t);
145 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*/
146 break;
147 case 3:
148 uxArg1 = va_arg(xVariableList, TraceUnsignedBaseType_t);
149 uxArg2 = va_arg(xVariableList, TraceUnsignedBaseType_t);
150 uxArg3 = va_arg(xVariableList, TraceUnsignedBaseType_t);
151 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*/
152 break;
153 case 4:
154 uxArg1 = va_arg(xVariableList, TraceUnsignedBaseType_t);
155 uxArg2 = va_arg(xVariableList, TraceUnsignedBaseType_t);
156 uxArg3 = va_arg(xVariableList, TraceUnsignedBaseType_t);
157 uxArg4 = va_arg(xVariableList, TraceUnsignedBaseType_t);
158 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*/
159 break;
160 default:
161 xResult = TRC_FAIL;
162 break;
163 }
164 va_end(xVariableList);
165
166 return xResult;
167 }
168
169 /*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,...)170 traceResult xTracePrintF(TraceStringHandle_t xChannel, const char* szFormat, ...)
171 {
172 traceResult xResult;
173 va_list xVariableList; /*cstat !MISRAC2012-Rule-17.1 Suppress stdarg usage check*/
174
175 /* We need to check this */
176 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
177 {
178 return TRC_FAIL;
179 }
180
181 va_start(xVariableList, szFormat);
182 xResult = xTraceVPrintF(xChannel, szFormat, &xVariableList);
183 va_end(xVariableList);
184
185 return xResult;
186 }
187
188 /*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)189 traceResult xTraceVPrintF(TraceStringHandle_t xChannel, const char* szFormat, va_list* pxVariableList)
190 {
191 uint32_t i;
192 uint32_t uiArgs = 0u;
193 uint32_t uiLength;
194
195 /* We need to check this */
196 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT) == 0U)
197 {
198 return TRC_FAIL;
199 }
200
201 if (szFormat == (void*)0)
202 {
203 szFormat = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
204 }
205
206 /* Count the number of arguments in the format string (e.g., %d) */
207 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*/
208 {
209 if (szFormat[i] == '%') /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
210 {
211 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*/
212 {
213 /* Found end of string, let for loop detect it */
214 continue; /*cstat !MISRAC2004-14.5 Suppress continue usage check*/
215 }
216
217 if (szFormat[i + 1u] != '%') /*cstat !MISRAC2004-17.4_b We need to access a specific character in the string*/
218 {
219 uiArgs++; /* Found an argument */
220 }
221
222 /* Move past format specifier or non-argument '%' */
223 i++; /*cstat !MISRAC2004-13.6 Suppress i increment inside for loop check*/
224 }
225 }
226
227 uiLength = i + 1u; /* Null termination */
228
229 return prvTraceVPrintF(xChannel, szFormat, uiLength, uiArgs, pxVariableList);
230 }
231
232 /*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)233 static traceResult prvTraceVPrintF(TraceStringHandle_t xChannel, const char* szFormat, uint32_t uiLength, uint32_t uiArgs, va_list* pxVariableList)
234 {
235 TraceEventHandle_t xEventHandle = 0;
236 uint32_t i, uiRemaining = 0u;
237 uint32_t uiValue = 0u;
238 const uint32_t uiEventCode = PSF_EVENT_USER_EVENT + 1u + uiArgs; /* Add channel (1) */
239 const uint32_t uiSize = sizeof(void*) + (uiArgs * sizeof(TraceUnsignedBaseType_t)) + uiLength; /* Add channel (sizeof(void*)) */
240
241 if (xChannel == 0)
242 {
243 if (pxPrintData->defaultChannel == 0)
244 {
245 /* Channel is not present */
246 if (xTraceStringRegister("Default", &pxPrintData->defaultChannel) == TRC_FAIL)
247 {
248 return TRC_FAIL;
249 }
250 }
251
252 xChannel = pxPrintData->defaultChannel; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
253 }
254
255 /* Added channel to uiEventCode and uiSize */
256 if (xTraceEventBegin(uiEventCode, uiSize , &xEventHandle) == TRC_FAIL)
257 {
258 return TRC_FAIL;
259 }
260
261 /* Add xChannel */
262 (void)xTraceEventAddPointer(xEventHandle, (void*)xChannel);
263
264 /* Add all arguments */
265 for (i = 0u; i < uiArgs; i++)
266 {
267 (void)xTraceEventAddUnsignedBaseType(xEventHandle, va_arg(*pxVariableList, TraceUnsignedBaseType_t));
268 }
269
270 (void)xTraceEventPayloadRemaining(xEventHandle, &uiRemaining);
271 if (uiRemaining < uiLength)
272 {
273 uiLength = uiRemaining - 1u; /* Make room for null termination */ /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
274 }
275
276 /* Add format string */
277 (void)xTraceEventAddString(xEventHandle, szFormat, uiLength);
278
279 /* Check if we can truncate */
280 (void)xTraceEventPayloadRemaining(xEventHandle, &uiValue);
281 if (uiValue > 0u)
282 {
283 (void)xTraceEventAdd8(xEventHandle, 0u);
284 }
285
286 (void)xTraceEventEnd(xEventHandle); /*cstat !MISRAC2012-Rule-17.7 Suppress ignored return value check (inside macro)*/
287
288 return TRC_SUCCESS;
289 }
290
291 #endif
292
293 #endif
294
295 #endif
296