trcPrint.c 12 KB

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