Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /*!
  2. * \file trice.h
  3. \author thomas.hoehenleitner [at] seerose.net
  4. * *****************************************************************************
  5. */
  6. #ifndef TRICE_H_
  7. #define TRICE_H_
  8. #ifdef __cplusplus
  9. extern "C"
  10. {
  11. #endif
  12. #undef ID //!< avoid name clashes in case ID was used by an other library
  13. #undef Id //!< avoid name clashes in case Id was used by an other library
  14. #undef id //!< avoid name clashes in case id was used by an other library
  15. #undef iD //!< avoid name clashes in case iD was used by an other library
  16. #define TRICE_UNUSED(x) (void)(x); //!< https://stackoverflow.com/questions/3599160/how-can-i-suppress-unused-parameter-warnings-in-c
  17. // lint -e529 Warning 529: Symbol '_SEGGER_RTT__LockState' not subsequently referenced
  18. // lint -e629 Warning 629: static class for function '' is non standard
  19. // lint -emacro( 701, TRICE* ) Info 701: Shift left of signed quantity (int)
  20. // lint -emacro( 123, TRICE* )
  21. // lint -emacro( 571, TRICE* )
  22. // lint -emacro( 572, TRICE* )
  23. // lint -emacro( 578, TRICE* )
  24. // lint -emacro( 648, TRICE* )
  25. // lint -emacro( 665, TRICE* )
  26. // lint -emacro( 666, TRICE* )
  27. // lint -emacro( 670, TRICE* )
  28. // lint -emacro( 694, TRICE* )
  29. // lint -emacro( 717, TRICE* )
  30. // lint -emacro( 718, TRICE* )
  31. // lint -emacro( 732, TRICE* )
  32. // lint -emacro( 734, TRICE* )
  33. // lint -emacro( 736, TRICE* )
  34. // lint -emacro( 740, TRICE* )
  35. // lint -emacro( 746, TRICE* )
  36. // lint -emacro( 747, TRICE* )
  37. // lint -emacro( 774, TRICE* )
  38. // lint -emacro( 778, TRICE* )
  39. // lint -emacro( 826, TRICE* )
  40. // lint -emacro( 830, TRICE* )
  41. // lint -emacro( 831, TRICE* )
  42. // lint -emacro( 835, TRICE* )
  43. // lint -emacro( 545, SCOPY, DCOPY )
  44. // lint -ecall( 666, aFloat, aDouble )
  45. // lint -efunc( 666, aFloat, aDouble )
  46. // lint -esym( 666, aFloat, aDouble )
  47. // lint -emacro( 732, SCOPY )
  48. // lint -emacro( 717, DCOPY, SCOPY )
  49. // lint -emacro( 732, DCOPY )
  50. // helper macros (the numbers are 32-bit random values)
  51. //! TRICE_SINGLE_PACK_MODE is the recommended TRICE_DEFERRED_TRANSFER_MODE. It packs each trice in a separate TCOBS package with a following 0-delimiter byte.
  52. //! Single trices need a bit more transfer data. In case of a data disruption, only a single trice messages can get lost.
  53. #define TRICE_SINGLE_PACK_MODE 787345706U
  54. //! TRICE_MULTI_PACK_MODE packs all trices of a buffer in a single TCOBS package and a following 0-delimiter byte.
  55. //! Grouped trices need a bit less transfer data. In case of a data disruption, multiple trice messages can get lost.
  56. //! Olny relevant when TRICE_DOUBLE_BUFFER is selected
  57. #define TRICE_MULTI_PACK_MODE 3987862482U
  58. //! With TRICE_BUFFER == TRICE_STACK_BUFFER the internal macro TRICE_PUT writes to the stack.
  59. //! This is direct logging. This reduces memory needs if only one stack is used.
  60. #define TRICE_STACK_BUFFER 2645382063U
  61. //! With TRICE_BUFFER == TRICE_STATIC_BUFFER the internal macro TRICE_PUT writes to a static buffer.
  62. //! This reduces memory needs if many stacks are used.
  63. #define TRICE_STATIC_BUFFER 1763551404U
  64. //! With TRICE_BUFFER == TRICE_DOUBLE_BUFFER the internal macro TRICE_PUT writes to a double buffer half.
  65. //! This is deferred logging using more space but the TRICE macros are executed faster.
  66. #define TRICE_DOUBLE_BUFFER 1950870368U
  67. //! With TRICE_BUFFER == TRICE_RING_BUFFER the internal macro TRICE_PUT writes to a ring buffer segment.
  68. //! This is deferred logging using less space but the TRICE macros are executed a bit slower.
  69. #define TRICE_RING_BUFFER 2237719049U
  70. //! TRICE_FRAMING_TCOBS is recommended for trice transfer over UART.
  71. #define TRICE_FRAMING_TCOBS 3745917584U
  72. //! TRICE_FRAMING_COBS is recommended for encrypted trices.
  73. #define TRICE_FRAMING_COBS 2953804234U
  74. //! TRICE_FRAMING_NONE is recommended for RTT in direct mode. One trice costs about 100 clocks and is completely done.
  75. #define TRICE_FRAMING_NONE 1431860787U
  76. #include <stdint.h>
  77. #include <string.h>
  78. #include "triceConfig.h" // Project specific settings are overwriting the default settings.
  79. #include "triceDefaultConfig.h" // default settings
  80. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  81. // These converter functions need to be visible in the TRICE_OFF == 1 case to avoid compiler warnings then.
  82. //
  83. // pre C99
  84. // // aFloat returns passed float value x as bit pattern in a uint32_t type.
  85. // TRICE_INLINE uint32_t aFloat( float x ){
  86. // union {
  87. // float f;
  88. // uint32_t u;
  89. // } t;
  90. // t.f = x;
  91. // return t.u;
  92. // }
  93. // aFloat returns passed float value x as bit pattern in a uint32_t type.
  94. TRICE_INLINE uint32_t aFloat(float f)
  95. {
  96. union
  97. {
  98. float from;
  99. uint32_t to;
  100. } pun = {.from = f};
  101. return pun.to;
  102. }
  103. // aDouble returns passed double value x as bit pattern in a uint64_t type.
  104. TRICE_INLINE uint64_t aDouble(double x)
  105. {
  106. union
  107. {
  108. double d;
  109. uint64_t u;
  110. } t;
  111. t.d = x;
  112. return t.u;
  113. }
  114. // Just in case you are receiving Trice messages containing uint32_t values to be interpreted as float:
  115. //
  116. // // asFloat returns passed uint32_t value x bit pattern as float type.
  117. // TRICE_INLINE float asFloat(uint32_t x) {
  118. // union {
  119. // uint32_t from;
  120. // float to;
  121. // } pun = {.from = x};
  122. // return pun.to;
  123. // }
  124. //
  125. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  126. // Do not generate trice code
  127. // - when defining TRICE_CLEAN to 1 inside "triceConfig.h" or
  128. // - when defining TRICE_OFF to 1 before including "trice.h".
  129. // It is possible to `#define TRICE_OFF 1` inside the project settings to disable all Trice code.
  130. #if ((defined(TRICE_OFF) && TRICE_OFF == 1)) || ((defined(TRICE_CLEAN) && TRICE_CLEAN == 1))
  131. // When the user defines TRICE_CLEAN to 0 or 1 inside triceConfig.h, this value is set to 0 with "trice insert" and to 1 with "trice clean".
  132. // This gives the option to silence editor warnings in the "trice clean" state.
  133. // To avoid a re-build on files including trice.h, the Trice cache will be helpful. See issue #488.
  134. #include "triceOff.h"
  135. #else // #if ((defined(TRICE_OFF) && TRICE_OFF == 1)) || ((defined(TRICE_CLEAN) && TRICE_CLEAN == 1))
  136. /***************************************************************************************************/
  137. /**/
  138. /**/
  139. #include "triceOn.h"
  140. #if (TRICE_DIRECT_SEGGER_RTT_8BIT_WRITE == 1) || (TRICE_DIRECT_SEGGER_RTT_32BIT_WRITE == 1) || (TRICE_DEFERRED_SEGGER_RTT_8BIT_WRITE == 1)
  141. #define SEGGER_RTT
  142. #endif
  143. #if defined(SEGGER_RTT) || (USE_SEGGER_RTT_LOCK_UNLOCK_MACROS == 1)
  144. #include "SEGGER_RTT.h"
  145. #endif
  146. // global defines
  147. #define TRICE_TYPE_X0 0 //!< TRICE_TYPE_X0 is an unspecified trice (reserved)
  148. #define TRICE_TYPE_S0 1 //!< TRICE_TYPE_S0 is a trice without stamp.
  149. #define TRICE_TYPE_S2 2 //!< TRICE_TYPE_S2 is a trice with 16-bit stamp.
  150. #define TRICE_TYPE_S4 3 //!< TRICE_TYPE_S4 is a trice with 32-bit stamp.
  151. // global variables:
  152. extern uint32_t *const triceSingleBufferStartWritePosition;
  153. extern unsigned TricesCountRingBuffer;
  154. extern char triceCommandBuffer[];
  155. extern int triceCommandFlag;
  156. extern uint8_t TriceCycle;
  157. extern unsigned RTT0_writeDepthMax;
  158. extern unsigned TriceErrorCount;
  159. #if (TRICE_BUFFER == TRICE_RING_BUFFER)
  160. extern uint32_t *const TriceRingBufferStart;
  161. extern uint32_t *const TriceRingBufferLimit;
  162. extern uint32_t *const TriceRingBufferProtectLimit;
  163. #if (TRICE_DIAGNOSTICS == 1)
  164. extern int TriceRingBufferDepthMax;
  165. #endif
  166. #if TRICE_RING_BUFFER_OVERFLOW_WATCH == 1
  167. void TriceInitRingBufferMargins(void);
  168. void WatchRingBufferMargins(void);
  169. #endif
  170. #endif // #if (TRICE_BUFFER == TRICE_RING_BUFFER)
  171. #if (TRICE_DIAGNOSTICS == 1)
  172. extern int TriceDataOffsetDepthMax;
  173. extern unsigned TriceSingleMaxWordCount;
  174. extern unsigned TriceDynStringBufTruncateCount;
  175. extern unsigned TriceHalfBufferDepthMax;
  176. #if TRICE_PROTECT == 1
  177. extern unsigned TriceDirectOverflowCount;
  178. extern unsigned TriceDeferredOverflowCount;
  179. #endif // #if TRICE_PROTECT == 1
  180. #define TRICE_DYN_STRG_BUF_TRUNCATE_COUNT_INCREMENT() \
  181. do { \
  182. TriceDynStringBufTruncateCount++; \
  183. } while (0)
  184. #else // #if (TRICE_DIAGNOSTICS == 1)
  185. #define TRICE_DYN_STRG_BUF_TRUNCATE_COUNT_INCREMENT()
  186. #endif // #else // #if (TRICE_DIAGNOSTICS == 1)
  187. #if (TRICE_BUFFER == TRICE_RING_BUFFER) || (TRICE_BUFFER == TRICE_DOUBLE_BUFFER)
  188. extern uint32_t *TriceBufferWritePosition;
  189. #endif
  190. //! TRICE_BUFFER_SIZE is
  191. //! \li the additional needed stack space when TRICE_BUFFER == TRICE_STACK_BUFFER
  192. //! \li the statically allocated buffer size when TRICE_BUFFER == TRICE_STATIC_BUFFER
  193. //! \li the value before Ringbuffer wraps, when TRICE_BUFFER == TRICE_RING_BUFFER
  194. //!
  195. //! The trice buffer needs 4 additional scratch bytes, when the longest possible
  196. //! trice gets formally the padding space cleared.
  197. #define TRICE_BUFFER_SIZE (TRICE_DATA_OFFSET + TRICE_SINGLE_MAX_SIZE + 4)
  198. #if TRICE_CYCLE_COUNTER == 1
  199. #define TRICE_CYCLE TriceCycle++ //!< TRICE_CYCLE is the trice cycle counter as 8 bit count 0-255.
  200. #else // #if TRICE_CYCLE_COUNTER == 1
  201. #define TRICE_CYCLE 0xC0 //!< TRICE_CYCLE is no trice cycle counter, just a static value.
  202. #endif // #else // #if TRICE_CYCLE_COUNTER == 1
  203. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. // "Declare" endian dependent macros, needed in trice8.h, trice16.h, trice32.h, trice64.h:
  205. //
  206. #define TRICE_HTOTS(x) TRICE_HTOTS(x)
  207. #define TRICE_HTOTL(x) TRICE_HTOTL(x)
  208. #define TRICE_TTOHS(x) TRICE_TTOHS(x)
  209. #define TRICE_PUT16_1616(x, ts) TRICE_PUT16_1616(x, ts)
  210. #define TRICE_PUT64(x) TRICE_PUT64(x)
  211. #define TRICE_SWAPINT16(x) TRICE_SWAPINT16(x)
  212. #define TRICE_SWAPINT32(x) TRICE_SWAPINT32(x)
  213. #define idLH idLH
  214. #define IdLH IdLH
  215. #define IDLH IDLH
  216. #define tsL tsL
  217. #define tsH tsH
  218. #define tsHH tsHH
  219. #define tsHL tsHL
  220. #define tsLH tsLH
  221. #define tsLL tsLL
  222. //
  223. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  224. //! TRICE_PUT16 copies 16-bit value x into the Trice buffer.
  225. #define TRICE_PUT16(x) \
  226. do { \
  227. uint16_t* p = (uint16_t*)TriceBufferWritePosition; \
  228. *p++ = TRICE_HTOTS(x); \
  229. TriceBufferWritePosition = (uint32_t*)p; \
  230. } while (0)
  231. #include "trice8.h"
  232. #include "trice16.h"
  233. #include "trice32.h"
  234. #include "trice64.h"
  235. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  236. // Endian dependent macros and code:
  237. //
  238. #undef TRICE_HTOTS
  239. #undef TRICE_HTOTL
  240. #undef TRICE_TTOHS
  241. #undef TRICE_PUT16_1616
  242. #undef TRICE_PUT64
  243. #undef TRICE_SWAPINT16
  244. #undef TRICE_SWAPINT32
  245. #undef idLH
  246. #undef IdLH
  247. #undef IDLH
  248. #undef tsL
  249. #undef tsH
  250. #undef tsHH
  251. #undef tsHL
  252. #undef tsLH
  253. #undef tsLL
  254. #if (__STDC_VERSION__ >= 202000) //! C23 standard specification for endianess detection (Note N3022)
  255. // https://github.com/rokath/trice/pull/505
  256. #if __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_LITTLE__
  257. #define TRICE_MCU_IS_BIG_ENDIAN 0
  258. #else
  259. #define TRICE_MCU_IS_BIG_ENDIAN 1
  260. #endif // __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_LITTLE__
  261. #else
  262. //! Try detect endianess by using compilers macros
  263. #if (defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \
  264. (defined(__BYTE_ORDER) && defined(__ORDER_LITTLE_ENDIAN) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \
  265. (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
  266. #define TRICE_MCU_IS_BIG_ENDIAN 0
  267. #elif (defined(BYTE_ORDER) && defined(ORDER_BIG_ENDIAN) && BYTE_ORDER == ORDER_BIG_ENDIAN) || \
  268. (defined(__BYTE_ORDER) && defined(__ORDER_BIG_ENDIAN) && __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \
  269. (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
  270. #define TRICE_MCU_IS_BIG_ENDIAN 1
  271. #else
  272. #ifndef TRICE_MCU_IS_BIG_ENDIAN
  273. #error Bytes order not supported or not detected, set TRICE_MCU_IS_BIG_ENDIAN to 0 or 1 in your triceConfig.h file.
  274. #endif // #ifndef TRICE_MCU_IS_BIG_ENDIAN
  275. #endif // __BYTE_ORDER__
  276. #endif // __STDC_VERSION__
  277. #if TRICE_TRANSFER_ORDER_IS_BIG_ENDIAN == TRICE_MCU_IS_BIG_ENDIAN
  278. // TRICE_REVERSE == 0 uses no byte swapping inside the Trice macros resulting in less code and faster execution.
  279. #include "triceMcuOrder.h"
  280. #include "trice8McuOrder.h"
  281. #include "trice16McuOrder.h"
  282. #include "trice32McuOrder.h"
  283. #include "trice64McuOrder.h"
  284. #else // #if TRICE_TRANSFER_ORDER_IS_BIG_ENDIAN == TRICE_MCU_IS_BIG_ENDIAN
  285. // TRICE_REVERSE == 1 causes byte swapping inside the Trice macros resulting in more code and slower execution.
  286. #include "triceMcuReverse.h"
  287. #include "trice8McuReverse.h"
  288. #include "trice16McuReverse.h"
  289. #include "trice32McuReverse.h"
  290. #include "trice64McuReverse.h"
  291. #endif // #else // #if TRICE_TRANSFER_ORDER_IS_BIG_ENDIAN == TRICE_MCU_IS_BIG_ENDIAN
  292. //
  293. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  294. #if TRICE_DIAGNOSTICS == 1
  295. #define TRICE_DIAGNOSTICS_SINGLE_BUFFER_KEEP_START \
  296. uint32_t* const triceSingleBufferStartWritePosition = TriceBufferWritePosition;
  297. #define TRICE_DIAGNOSTICS_SINGLE_BUFFER \
  298. do { \
  299. unsigned wordCount = TriceBufferWritePosition - triceSingleBufferStartWritePosition; \
  300. TriceSingleMaxWordCount = (wordCount < TriceSingleMaxWordCount) ? TriceSingleMaxWordCount : wordCount; \
  301. } while (0);
  302. #define TRICE_DIAGNOSTICS_SINGLE_BUFFER_USING_WORD_COUNT \
  303. do { \
  304. TriceSingleMaxWordCount = (wordCount < TriceSingleMaxWordCount) ? TriceSingleMaxWordCount : wordCount; \
  305. } while (0);
  306. #else // #if TRICE_DIAGNOSTICS == 1
  307. #define TRICE_DIAGNOSTICS_SINGLE_BUFFER_KEEP_START
  308. #define TRICE_DIAGNOSTICS_SINGLE_BUFFER
  309. #define TRICE_DIAGNOSTICS_SINGLE_BUFFER_USING_WORD_COUNT
  310. #endif // #else // #if TRICE_DIAGNOSTICS == 1
  311. // clang-format off
  312. #ifndef TRICE_ENTER
  313. #if TRICE_BUFFER == TRICE_STACK_BUFFER
  314. //! TRICE_ENTER is the start of TRICE macro.
  315. #define TRICE_ENTER \
  316. TRICE_ENTER_CRITICAL_SECTION { \
  317. { \
  318. uint32_t triceSingleBuffer[TRICE_BUFFER_SIZE >> 2]; /* no = {0} here for speed */ \
  319. uint32_t* const triceSingleBufferStartWritePosition = &triceSingleBuffer[TRICE_DATA_OFFSET >> 2]; \
  320. uint32_t* TriceBufferWritePosition = triceSingleBufferStartWritePosition;
  321. #endif // #if TRICE_BUFFER == TRICE_STACK_BUFFER
  322. #if TRICE_BUFFER == TRICE_STATIC_BUFFER
  323. //! TRICE_ENTER is the start of TRICE macro.
  324. #define TRICE_ENTER \
  325. TRICE_ENTER_CRITICAL_SECTION { \
  326. { \
  327. uint32_t* TriceBufferWritePosition = triceSingleBufferStartWritePosition;
  328. #endif // #if TRICE_BUFFER == TRICE_STATIC_BUFFER
  329. #if (TRICE_BUFFER == TRICE_DOUBLE_BUFFER) && (TRICE_DIRECT_OUTPUT == 1)
  330. #if TRICE_PROTECT == 1
  331. //! TRICE_ENTER is the start of TRICE macro.
  332. #define TRICE_ENTER \
  333. TRICE_ENTER_CRITICAL_SECTION { \
  334. if (TriceEnoughSpace()) { \
  335. uint32_t* const triceSingleBufferStartWritePosition = TriceBufferWritePosition;
  336. #else // #if TRICE_PROTECT == 1
  337. //! TRICE_ENTER is the start of TRICE macro.
  338. #define TRICE_ENTER \
  339. TRICE_ENTER_CRITICAL_SECTION { \
  340. { \
  341. uint32_t* const triceSingleBufferStartWritePosition = TriceBufferWritePosition;
  342. #endif // #else // #if TRICE_PROTECT == 1
  343. #endif // #if (TRICE_BUFFER == TRICE_DOUBLE_BUFFER) && (TRICE_DIRECT_OUTPUT == 1)
  344. #if (TRICE_BUFFER == TRICE_DOUBLE_BUFFER) && (TRICE_DIRECT_OUTPUT == 0)
  345. #if TRICE_PROTECT == 1
  346. //! TRICE_ENTER is the start of TRICE macro.
  347. #define TRICE_ENTER \
  348. TRICE_ENTER_CRITICAL_SECTION { \
  349. if (TriceEnoughSpace()) { \
  350. TRICE_DIAGNOSTICS_SINGLE_BUFFER_KEEP_START
  351. #else // #if TRICE_PROTECT == 1
  352. //! TRICE_ENTER is the start of TRICE macro.
  353. #define TRICE_ENTER \
  354. TRICE_ENTER_CRITICAL_SECTION { \
  355. { \
  356. TRICE_DIAGNOSTICS_SINGLE_BUFFER_KEEP_START
  357. #endif // #else // #if TRICE_PROTECT == 1
  358. #endif // #if (TRICE_BUFFER == TRICE_DOUBLE_BUFFER) && (TRICE_DIRECT_OUTPUT == 0)
  359. #if (TRICE_BUFFER == TRICE_RING_BUFFER) && (TRICE_DIRECT_OUTPUT == 1)
  360. #if TRICE_PROTECT == 1
  361. //! TRICE_ENTER is the start of TRICE macro.
  362. #define TRICE_ENTER \
  363. TRICE_ENTER_CRITICAL_SECTION { \
  364. /* The TriceBufferWritePosition stays unchanged, when there is enough space for the next trice at the current write position.*/ \
  365. /* Because the the size of the next trice message is unknown here, the biggest value is assumed, that is TRICE_SINGLE_MAX_SIZE bytes. */ \
  366. /* If this space is not given anymore, the `TriceBufferWritePosition` is reset to the start address of the ring buffer. */ \
  367. TriceBufferWritePosition = TriceBufferWritePosition <= TriceRingBufferProtectLimit ? TriceBufferWritePosition : TriceRingBufferStart; \
  368. if (TriceEnoughSpace()) { \
  369. uint32_t* const triceSingleBufferStartWritePosition = TriceBufferWritePosition; \
  370. TricesCountRingBuffer++; // Because TRICE macros are an atomic instruction normally, this can be done here.
  371. #else // #if TRICE_PROTECT == 1
  372. //! TRICE_ENTER is the start of TRICE macro.
  373. #define TRICE_ENTER \
  374. TRICE_ENTER_CRITICAL_SECTION { \
  375. { \
  376. /* The TriceBufferWritePosition stays unchanged, when there is enough space for the next trice at the current write position.*/ \
  377. /* Because the the size of the next trice message is unknown here, the biggest value is assumed, that is TRICE_BUFFER_SIZE bytes. */ \
  378. /* If this space is not given anymore, the `TriceBufferWritePosition` is reset to the start address of the ring buffer. */ \
  379. /* This implementation is a bit different than a ring buffer is usually implemented. */ \
  380. TriceBufferWritePosition = TriceBufferWritePosition <= TriceRingBufferProtectLimit ? TriceBufferWritePosition : TriceRingBufferStart; \
  381. uint32_t* const triceSingleBufferStartWritePosition = TriceBufferWritePosition; \
  382. TricesCountRingBuffer++; // Because TRICE macros are an atomic instruction normally, this can be done here.
  383. #endif // #else // #if TRICE_PROTECT == 1
  384. #endif // #if TRICE_BUFFER == TRICE_RING_BUFFER && (TRICE_DIRECT_OUTPUT == 1)
  385. #if (TRICE_BUFFER == TRICE_RING_BUFFER) && (TRICE_DIRECT_OUTPUT == 0)
  386. #if TRICE_PROTECT == 1
  387. //! TRICE_ENTER is the start of TRICE macro.
  388. #define TRICE_ENTER \
  389. TRICE_ENTER_CRITICAL_SECTION { \
  390. TriceBufferWritePosition = TriceBufferWritePosition <= TriceRingBufferProtectLimit ? TriceBufferWritePosition : TriceRingBufferStart; \
  391. if (TriceEnoughSpace()) { \
  392. TRICE_DIAGNOSTICS_SINGLE_BUFFER_KEEP_START \
  393. TricesCountRingBuffer++; // Because TRICE macros are an atomic instruction normally, this can be done here.
  394. #else // #if TRICE_PROTECT == 1
  395. //! TRICE_ENTER is the start of TRICE macro.
  396. #define TRICE_ENTER \
  397. TRICE_ENTER_CRITICAL_SECTION { \
  398. { \
  399. TriceBufferWritePosition = TriceBufferWritePosition <= TriceRingBufferProtectLimit ? TriceBufferWritePosition : TriceRingBufferStart; \
  400. TRICE_DIAGNOSTICS_SINGLE_BUFFER_KEEP_START \
  401. TricesCountRingBuffer++; // Because TRICE macros are an atomic instruction normally, this can be done here.
  402. #endif // #else // #if TRICE_PROTECT == 1
  403. #endif // #if TRICE_BUFFER == TRICE_RING_BUFFER && (TRICE_DIRECT_OUTPUT == 0)
  404. #endif // #ifndef TRICE_ENTER
  405. #ifndef TRICE_LEAVE
  406. #if TRICE_DIRECT_OUTPUT == 1
  407. //! TRICE_LEAVE is the end of TRICE macro. It is the same for all buffer variants.
  408. #define TRICE_LEAVE \
  409. /* wordCount is the amount of steps, the TriceBufferWritePosition went forward for the actual trice. */ \
  410. /* The last written uint32_t trice value can contain 1 to 3 padding bytes. */ \
  411. unsigned wordCount = TriceBufferWritePosition - triceSingleBufferStartWritePosition; \
  412. TRICE_DIAGNOSTICS_SINGLE_BUFFER_USING_WORD_COUNT \
  413. TriceNonBlockingDirectWrite(triceSingleBufferStartWritePosition, wordCount); \
  414. } \
  415. } \
  416. TRICE_LEAVE_CRITICAL_SECTION
  417. #else // #if TRICE_DIRECT_OUTPUT == 1
  418. //! TRICE_LEAVE is the end of TRICE macro. It is the same for all buffer variants.
  419. #define TRICE_LEAVE \
  420. TRICE_DIAGNOSTICS_SINGLE_BUFFER \
  421. } \
  422. } \
  423. TRICE_LEAVE_CRITICAL_SECTION
  424. #endif // #else //#if TRICE_DIRECT_OUTPUT == 1
  425. #endif // #ifndef TRICE_LEAVE
  426. #ifndef TRICE_PUT
  427. //! TRICE_PUT writes x as 32-bit value into the Trice buffer without changing the endianness.
  428. //! This macro does not use internally TRICE_HTOTL and therefore it is usable without speed loss, when TRICE_REVERSE == 1.
  429. //! In that case the byte order needs to be provided by the written code.
  430. #define TRICE_PUT(x) \
  431. do { \
  432. *TriceBufferWritePosition++ = x; \
  433. } while (0);
  434. #endif
  435. #ifndef TRICE_PUT_BUFFER
  436. //! TRICE_PUT_BUFFER copies a buffer into the TRICE buffer.
  437. #define TRICE_PUT_BUFFER(buf, len) \
  438. do { \
  439. memcpy(TriceBufferWritePosition, buf, len); \
  440. unsigned len4 = ((unsigned)len + 3) & ~3; \
  441. memset((uint8_t*)TriceBufferWritePosition + len, 0, len4 - len); /*clear padding space*/ \
  442. TriceBufferWritePosition += len4 >> 2; \
  443. } while (0)
  444. #endif
  445. // clang-format on
  446. ///////////////////////////////////////////////////////////////////////////////
  447. // TRICE macros
  448. //
  449. #define TRICE_0 TRICE0 //!< Only the format string without parameter values.
  450. #define TRice_0 TRice0 //!< Only the format string without parameter values.
  451. #define Trice_0 Trice0 //!< Only the format string without parameter values.
  452. #define trice_0 trice0 //!< Only the format string without parameter values.
  453. #ifndef TRICE_N
  454. //! TRICE_N writes id and buffer of size len.
  455. //! \param tid trice identifier
  456. //! \param pFmt formatstring for trice (ignored here but used by the trice tool), could contain any add on information. The trice tool "sees" the "TRICE_N" and can handle that.
  457. //! \param dynString 0-terminated runtime generated string
  458. //! After the 4 byte trice message header are following 4 bytes coding n (only 2 used) and the buffer
  459. //! transfer format:
  460. //! idH idL len cycle <- trice header
  461. //! n0 n1 n2 n3 <- payload count without paddings bytes (transmittable len)
  462. //! c0 c1 c2 c3 <- buffer
  463. //! ... <- buffer
  464. //! cLen-3 cLen-2 cLen-1 cLen <- buffer ending with maybe 1-3 undetermined padding bytes
  465. //!
  466. //! todo: for some reason this macro is not working well wit name len instead of len_, probably when injected len as value.
  467. //!
  468. #define TRICE_N(tid, pFmt, buf, n) \
  469. do { \
  470. TRICE_UNUSED(pFmt); \
  471. uint32_t limit = TRICE_SINGLE_MAX_SIZE - 12; /* 12 = head(2) + max timestamp size(4) + count(2) + max 3 zeroes, we take 4 */ \
  472. uint32_t len_ = n; /* n could be a constant */ \
  473. if (len_ > limit) { \
  474. TRICE_DYN_STRG_BUF_TRUNCATE_COUNT_INCREMENT(); \
  475. len_ = limit; \
  476. } \
  477. TRICE_ENTER tid; \
  478. if (len_ <= 127) { \
  479. TRICE_CNTC(len_); \
  480. } else { \
  481. TRICE_LCNT(len_); \
  482. } \
  483. TRICE_PUT_BUFFER(buf, len_); \
  484. TRICE_LEAVE \
  485. } while (0)
  486. void triceN(int tid, char* fmt, void* buf, uint32_t n);
  487. void TriceN(int tid, char* fmt, void* buf, uint32_t n);
  488. void TRiceN(int tid, char* fmt, void* buf, uint32_t n);
  489. void trice8B(int tid, char* fmt, void* buf, uint32_t n);
  490. void Trice8B(int tid, char* fmt, void* buf, uint32_t n);
  491. void TRice8B(int tid, char* fmt, void* buf, uint32_t n);
  492. void trice16B(int tid, char* fmt, void* buf, uint32_t n);
  493. void Trice16B(int tid, char* fmt, void* buf, uint32_t n);
  494. void TRice16B(int tid, char* fmt, void* buf, uint32_t n);
  495. void trice32B(int tid, char* fmt, void* buf, uint32_t n);
  496. void Trice32B(int tid, char* fmt, void* buf, uint32_t n);
  497. void TRice32B(int tid, char* fmt, void* buf, uint32_t n);
  498. void trice64B(int tid, char* fmt, void* buf, uint32_t n);
  499. void Trice64B(int tid, char* fmt, void* buf, uint32_t n);
  500. void TRice64B(int tid, char* fmt, void* buf, uint32_t n);
  501. void trice8F(int tid, char* fmt, void* buf, uint32_t n);
  502. void Trice8F(int tid, char* fmt, void* buf, uint32_t n);
  503. void TRice8F(int tid, char* fmt, void* buf, uint32_t n);
  504. void trice16F(int tid, char* fmt, void* buf, uint32_t n);
  505. void Trice16F(int tid, char* fmt, void* buf, uint32_t n);
  506. void TRice16F(int tid, char* fmt, void* buf, uint32_t n);
  507. void trice32F(int tid, char* fmt, void* buf, uint32_t n);
  508. void Trice32F(int tid, char* fmt, void* buf, uint32_t n);
  509. void TRice32F(int tid, char* fmt, void* buf, uint32_t n);
  510. void trice64F(int tid, char* fmt, void* buf, uint32_t n);
  511. void Trice64F(int tid, char* fmt, void* buf, uint32_t n);
  512. void TRice64F(int tid, char* fmt, void* buf, uint32_t n);
  513. #endif // #ifndef TRICE_N
  514. #ifndef TRICE_S
  515. //! TRICE_S writes id and runtimeGeneratedString.
  516. //! \param tid trice identifier
  517. //! \param pFmt format string for trice (ignored here but used by the trice tool)
  518. //! \param runtimeGeneratedString 0-terminated runtime generated string
  519. #define TRICE_S(tid, pFmt, runtimeGeneratedString) \
  520. do { \
  521. uint32_t ssiz = strlen(runtimeGeneratedString); \
  522. TRICE_N(tid, pFmt, runtimeGeneratedString, ssiz); \
  523. } while (0)
  524. void triceS(int tid, char* fmt, char* runtimeGeneratedString);
  525. void TriceS(int tid, char* fmt, char* runtimeGeneratedString);
  526. void TRiceS(int tid, char* fmt, char* runtimeGeneratedString);
  527. #endif // #ifndef TRICE_S
  528. //! ID writes 14-bit id with 11 as 2 most significant bits, followed by a 32-bit stamp.
  529. //! 11iiiiiiI TT | TT (NC) | ...
  530. //! C000 = 1100 0000 0000 0000
  531. #define ID(n) \
  532. do { \
  533. uint32_t ts = TriceStamp32; \
  534. TRICE_PUT16_1616((0xC000 | (n)), ts); \
  535. } while (0)
  536. //! Id writes 14-bit id with 10 as 2 most significant bits two times, followed by a 16-bit stamp.
  537. //! 10iiiiiiI 10iiiiiiI | TT (NC) | ...
  538. //! 8000 = 1000 0000 0000 0000
  539. #define Id(n) \
  540. do { \
  541. uint16_t ts = TriceStamp16; \
  542. TRICE_PUT(TRICE_HTOTL(0x80008000 | ((n) << 16) | (n))); \
  543. TRICE_PUT16(ts); \
  544. } while (0)
  545. //! id writes 14-bit id with 01 as 2 most significant bits, followed by no stamp.
  546. //! 01iiiiiiI (NC) | ...
  547. //! 4000 = 0100 0000 0000 0000
  548. #define id(n) TRICE_PUT16(0x4000 | (n));
  549. //! iD is just a code parsing helper.
  550. #define iD(n) (n)
  551. //! TRICE_CNTC writes 7-bit byte count and 8-bit cycle counter.
  552. #define TRICE_CNTC(count) \
  553. do { \
  554. uint16_t v = ((count) << 8) | TRICE_CYCLE; \
  555. TRICE_PUT16(v); \
  556. } while (0)
  557. #if TRICE_CYCLE_COUNTER == 1
  558. //! TRICE_LCNT writes 1 as most significant bit and 15-bit byte count. It does not write the cycle counter but increments the cycle counter.
  559. #define TRICE_LCNT(count) \
  560. TRICE_PUT16((0x8000 | (count))); \
  561. TRICE_CYCLE // increment TRICE_CYCLE but do not transmit it
  562. #else
  563. //! TRICE_LCNT writes 1 as most significant bit and 15-bit byte count. It does not write the cycle counter but increments the cycle counter.
  564. #define TRICE_LCNT(count) TRICE_PUT16((0x8000 | (count))); // no TRICE_CYCLE
  565. #endif
  566. //! TRICE0 writes trice data as fast as possible in a buffer.
  567. //! \param tid is a 16 bit Trice id in upper 2 bytes of a 32 bit value
  568. #define TRICE0(tid, pFmt) \
  569. TRICE_ENTER tid; \
  570. TRICE_CNTC(0); \
  571. TRICE_LEAVE
  572. TRICE_INLINE void trice0(uint16_t tid, const char* pFmt)
  573. {
  574. trice32m_0(tid);
  575. TRICE_UNUSED(pFmt)
  576. }
  577. TRICE_INLINE void Trice0(uint16_t tid, const char *pFmt)
  578. {
  579. Trice32m_0(tid);
  580. TRICE_UNUSED(pFmt)
  581. }
  582. TRICE_INLINE void TRice0(uint16_t tid, const char *pFmt)
  583. {
  584. TRice32m_0(tid);
  585. TRICE_UNUSED(pFmt)
  586. }
  587. void triceAssertTrue(int idN, char *msg, int flag);
  588. void TriceAssertTrue(int idN, char *msg, int flag);
  589. void TRiceAssertTrue(int idN, char *msg, int flag);
  590. void triceAssertFalse(int idN, char *msg, int flag);
  591. void TriceAssertFalse(int idN, char *msg, int flag);
  592. void TRiceAssertFalse(int idN, char *msg, int flag);
  593. typedef void (*Write8AuxiliaryFn_t)(const uint8_t *enc, size_t encLen);
  594. extern Write8AuxiliaryFn_t UserNonBlockingDirectWrite8AuxiliaryFn;
  595. extern Write8AuxiliaryFn_t UserNonBlockingDeferredWrite8AuxiliaryFn;
  596. typedef void (*Write32AuxiliaryFn_t)(const uint32_t *enc, unsigned count);
  597. extern Write32AuxiliaryFn_t UserNonBlockingDirectWrite32AuxiliaryFn;
  598. extern Write32AuxiliaryFn_t UserNonBlockingDeferredWrite32AuxiliaryFn;
  599. /**/
  600. /**/
  601. /***************************************************************************************************/
  602. #endif // #else // #if ((defined(TRICE_OFF) && TRICE_OFF == 1)) || ((defined(TRICE_CLEAN) && TRICE_CLEAN == 1))
  603. #ifdef __cplusplus
  604. }
  605. #endif
  606. #endif // TRICE_H_