Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. //! \file triceRingBuffer.c
  2. //! \author Thomas.Hoehenleitner [at] seerose.net
  3. //! //////////////////////////////////////////////////////////////////////////
  4. #include "cobs.h"
  5. #include "tcobs.h"
  6. #include "trice.h"
  7. #if TRICE_BUFFER == TRICE_RING_BUFFER && TRICE_OFF == 0
  8. #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_SINGLE_PACK_MODE
  9. static void triceSingleDeferredOut(int *wordCount);
  10. #else
  11. static void triceMultiDeferredOut(int *triceCount, int *wordCount);
  12. #endif
  13. #if TRICE_RING_BUFFER_OVERFLOW_WATCH == 1
  14. #define TRICE_RING_BUFFER_LOWER_MARGIN 8 //!< 32-bit units just for debugging > 0
  15. #define TRICE_RING_BUFFER_UPPER_MARGIN 8 //!< 32-bit units just for debugging > 0
  16. #define TRICE_RING_BUFFER_MARGIN_FILL_VALUE 0xfee4deb
  17. #else
  18. #define TRICE_RING_BUFFER_LOWER_MARGIN 0 //!< 32-bit units just for debugging > 0
  19. #define TRICE_RING_BUFFER_UPPER_MARGIN 0 //!< 32-bit units just for debugging > 0
  20. #define TRICE_RING_BUFFER_FILL_VALUE 0
  21. #endif
  22. //! triceRingBuffer is a kind of heap for trice messages. It needs to be initialized with 0.
  23. //! Initial:
  24. //! |<-LM->|<---------------- triceRingBuffer ------------------------------------------------------->|<-UM->|
  25. //! |<-LM->|<--TRICE_DATA_OFFSET-->|<---------------- TRICE_RING_BUFFER_SIZE -------------------------->|<-UM->|
  26. //! |<-LM->|<--TRICE_DATA_OFFSET-->|<-- writable -->|<-- TRICE_RING_BUFFER_MIN_SPACE32 -->|<-UM->|
  27. //! | | ^--------- TriceRingBufferLimit
  28. //! | ^----------------------------------------------- TriceRingBufferProtectLimit
  29. //! ^------------------------------------------------------------------------------ TriceBufferWritePosition
  30. //! ^------------------------------------------------------------------------------ TriceRingBufferReadPosition
  31. //! ^------------------------------------------------------------------------------ TriceRingBufferStart
  32. //!
  33. //! After some writes:
  34. //! |<-LM->|<---------------- triceRingBuffer ------------------------------------------------------->|<-UM->|
  35. //! |<-LM->|<--TRICE_DATA_OFFSET-->|<---------------- TRICE_RING_BUFFER_SIZE -------------------------->|<-UM->|
  36. //! |<-LM->|<--TRICE_DATA_OFFSET-->|<-T->|<-T->|<-- writable -->|<-- TRICE_RING_BUFFER_MIN_SPACE32 -->|<-UM->|
  37. //! | | | ^--------- TriceRingBufferLimit
  38. //! | | ^----------------------------------------------- TriceRingBufferProtectLimit
  39. //! | ^------------------------------------------------------------------ TriceBufferWritePosition
  40. //! ^------------------------------------------------------------------------------ TriceRingBufferReadPosition
  41. //! ^------------------------------------------------------------------------------ TriceRingBufferStart
  42. //!
  43. //! After some reads:
  44. //! |<-LM->|<---------------- triceRingBuffer ------------------------------------------------------->|<-UM->|
  45. //! |<-LM->|<--TRICE_DATA_OFFSET-->|<---------------- TRICE_RING_BUFFER_SIZE -------------------------->|<-UM->|
  46. //! |<-LM->|<--TRICE_DATA_OFFSET-->|<writable->|<-- writable -->|<-- TRICE_RING_BUFFER_MIN_SPACE32 -->|<-UM->|
  47. //! | | | ^--------- TriceRingBufferLimit
  48. //! | | ^----------------------------------------------- TriceRingBufferProtectLimit
  49. //! | ^------------------------------------------------------------------ TriceBufferWritePosition
  50. //! | ^-------------------------------------------------------------------TriceRingBufferReadPosition
  51. //! ^------------------------------------------------------------------------------ TriceRingBufferStart
  52. //!
  53. //! After some time:
  54. //! |<-LM->|<---------------- triceRingBuffer ------------------------------------------------------->|<-UM->|
  55. //! |<-LM->|<--TRICE_DATA_OFFSET-->|<---------------- TRICE_RING_BUFFER_SIZE -------------------------->|<-UM->|
  56. //! |<-LM->|<--TRICE_DATA_OFFSET-->| |<-- TRICE_RING_BUFFER_MIN_SPACE32 -->|<-UM->|
  57. //! | | ^--------- TriceRingBufferLimit
  58. //! | ^----------------------------------------------- TriceRingBufferProtectLimit
  59. //! |<-- writable -->|<-T->|<-T->|<-T->|<-------- not writable --------->|<-UM->|
  60. //! | | ^------------------------------------------- TriceBufferWritePosition, no more TRICE_RING_BUFFER_MIN_SPACE32!
  61. //! | ^------------------------------------------------------------- TriceRingBufferReadPosition
  62. //! ^------------------------------------------------------------------------------ TriceRingBufferStart
  63. //! With next Trice, TriceBufferWritePosition has to wrap firstly:
  64. //! |<-LM->|<---------------- triceRingBuffer ------------------------------------------------------->|<-UM->|
  65. //! |<-LM->|<--TRICE_DATA_OFFSET-->|<---------------- TRICE_RING_BUFFER_SIZE -------------------------->|<-UM->|
  66. //! |<-LM->|<--TRICE_DATA_OFFSET-->| |<-- TRICE_RING_BUFFER_MIN_SPACE32 -->|<-UM->|
  67. //! | | ^--------- TriceRingBufferLimit
  68. //! | ^----------------------------------------------- TriceRingBufferProtectLimit
  69. //! |<-- writable -->|<-T->|<-T->|<-T->|<-------- not writable --------->|<-UM->| When depth32(==writable) < TRICE_RING_BUFFER_MIN_SPACE32, no write is possible.
  70. //! | ^------------------------------------------------------------- TriceRingBufferReadPosition
  71. //! ^------------------------------------------------------------------------------ TriceBufferWritePosition (wrapped)
  72. //! ^------------------------------------------------------------------------------ TriceRingBufferStart
  73. uint32_t triceRingBuffer[TRICE_RING_BUFFER_LOWER_MARGIN +(TRICE_DATA_OFFSET >> 2)+(TRICE_RING_BUFFER_SIZE >> 2)+ TRICE_RING_BUFFER_UPPER_MARGIN] = {0};
  74. //! TRICE_RING_BUFFER_MIN_SPACE32 is the needed space before a new Trice is allowed to be written.
  75. //! The TRICE_DATA_OFFSET guaranties, that in front of TriceRingBufferReadPosition is always a scratch pad.
  76. #define TRICE_RING_BUFFER_MIN_SPACE32 ((TRICE_SINGLE_MAX_SIZE + TRICE_DATA_OFFSET) >> 2)
  77. //! TRICE_RING_BUFFER_START is a helper definition to avoid warning "expression must have a constant value".
  78. #define TRICE_RING_BUFFER_START (triceRingBuffer + TRICE_RING_BUFFER_LOWER_MARGIN + (TRICE_DATA_OFFSET >> 2))
  79. //! TriceRingBufferStart is an immutable pointer to the begin of the triceRingBuffer area.
  80. uint32_t *const TriceRingBufferStart = TRICE_RING_BUFFER_START;
  81. //! triceBufferWriteLimit is the first address behind triceRingBuffer area and immutable.
  82. //! With encryption it can happen that 4 bytes following TriceRingBufferLimit are used as scratch pad.
  83. //! We use the value of TRICE_DEFERRED_XTEA_ENCRYPT (0 or 1) here to respect that
  84. //! See also comment inside triceSingleDeferredOut.
  85. uint32_t *const TriceRingBufferLimit = TRICE_RING_BUFFER_START + (TRICE_RING_BUFFER_SIZE >> 2);
  86. //! TricesCountRingBuffer holds the readable trices count inside triceRingBuffer.
  87. unsigned TricesCountRingBuffer = 0;
  88. //! TriceBufferWritePosition is used by the TRICE_PUT macros.
  89. uint32_t *TriceBufferWritePosition = TRICE_RING_BUFFER_START;
  90. //! TriceRingBufferProtectLimit is the first address not allowed to be written to in any circumstances.
  91. //! If TriceBufferWritePosition >= TriceRingBufferProtectLimit, TriceBufferWritePosition needs to wrap.
  92. uint32_t *const TriceRingBufferProtectLimit = TRICE_RING_BUFFER_START + (TRICE_RING_BUFFER_SIZE >> 2) - TRICE_RING_BUFFER_MIN_SPACE32;
  93. //! TriceRingBufferReadPosition points to a valid trice message when singleTricesRingCount > 0.
  94. //! This is first the TRICE_DATA_OFFSET byte space followed by the trice data.
  95. //! Initially this value is set to TriceRingBufferStart minus TRICE_DATA_OFFSET byte space
  96. //! to get a correct value for the very first call of triceNextRingBufferRead
  97. //! uint32_t* TriceRingBufferReadPosition = TriceRingBufferStart - (TRICE_DATA_OFFSET>>2); //lint !e428 Warning 428: negative subscript (-4) in operator 'ptr-int'
  98. uint32_t *TriceRingBufferReadPosition = TRICE_RING_BUFFER_START;
  99. #if TRICE_DIAGNOSTICS == 1
  100. //! TricesCountRingBufferMax holds the max count of trices occurred inside the ring buffer.
  101. //! This value is only informal, because the length of the trice messages is not known.
  102. //! unsigned TricesCountRingBufferMax = 0;
  103. //! TriceRingBufferDepthMax holds the max occurred ring buffer depth.
  104. int TriceRingBufferDepthMax = 0;
  105. #endif // #if TRICE_DIAGNOSTICS == 1
  106. #if TRICE_PROTECT == 1
  107. //! TriceEnoughSpace checks, if enough bytes available for the next trice.
  108. //! \retval 0, when not enough space
  109. //! \retval 1, when enough space
  110. int TriceEnoughSpace(void)
  111. {
  112. // depth32 is the used buffer space in 32-bit words. After reset TriceBufferWritePosition and TriceRingBufferReadPosition are equal and depth32 is 0.
  113. // After some trice data writing, TriceBufferWritePosition is > TriceRingBufferReadPosition and depth32 has a positive value.
  114. // When trice data read out takes place, the TriceRingBufferReadPosition is incremented. That makes the depth32 value smaller again and gives write space.
  115. // Before a new trice write operation, TriceBufferWritePosition is reset to TriceRingBufferStart if less than TRICE_SINGLE_MAX_SIZE bytes left to the TriceRingBufferLimit.
  116. // So, even there is a only 4 bytes Trice, it cannot be written, when no full TRICE_SINGLE_MAX_SIZE space is left, because we do not know its size in advance.
  117. // The TriceRingBufferReadPosition jumps in the same way as the TriceBufferWritePosition. It wraps according the same rules.
  118. int depth32 = TriceBufferWritePosition - TriceRingBufferReadPosition;
  119. if (depth32 == 0 && TricesCountRingBuffer > 0)
  120. {
  121. goto noSpace;
  122. }
  123. if (depth32 < 0) // After a TriceBufferWritePosition reset the difference is negative and needs correction to get the correct value.
  124. {
  125. depth32 += (TRICE_RING_BUFFER_SIZE >> 2);
  126. }
  127. // This fn is called before an intended trice data write ande therefore additional at least TRICE_SINGLE_MAX_SIZE>>2 32-bit words need to fit in the buffer.
  128. // There must be left TRICE_DATA_OFFSET space behind the last Trice to be usable as scratch pad in front of TriceRingBufferReadPosition.
  129. if (depth32 <= (TRICE_RING_BUFFER_SIZE >> 2) - TRICE_RING_BUFFER_MIN_SPACE32)
  130. {
  131. return 1;
  132. }
  133. else
  134. {
  135. noSpace:
  136. #if TRICE_DIAGNOSTICS == 1
  137. TriceDeferredOverflowCount++;
  138. #endif
  139. return 0;
  140. }
  141. }
  142. #endif // #if TRICE_PROTECT == 1
  143. // triceIncrementRingBufferReadPosition sets TriceRingBufferReadPosition forward by wordCount.
  144. //! \param lastWordCount is the u32 count of the last read trice including padding bytes.
  145. TRICE_INLINE void triceIncrementRingBufferReadPosition(int wordCount)
  146. {
  147. TriceRingBufferReadPosition += wordCount;
  148. if (TriceRingBufferReadPosition > TriceRingBufferProtectLimit)
  149. {
  150. TriceRingBufferReadPosition = TriceRingBufferStart;
  151. }
  152. }
  153. // triceRingBufferDiagnostics computes and tracks TriceRingBufferDepthMax
  154. TRICE_INLINE void triceRingBufferDiagnostics(void)
  155. {
  156. #if TRICE_DIAGNOSTICS == 1
  157. int depth = (TriceBufferWritePosition - TriceRingBufferReadPosition) << 2; // lint !e845 Info 845: The left argument to operator '<<' is certain to be 0
  158. if (depth < 0)
  159. {
  160. depth += TRICE_DEFERRED_BUFFER_SIZE;
  161. }
  162. TriceRingBufferDepthMax = (depth > TriceRingBufferDepthMax) ? depth : TriceRingBufferDepthMax;
  163. #endif // #if TRICE_DIAGNOSTICS == 1
  164. }
  165. #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_SINGLE_PACK_MODE
  166. //! triceTransferSingleFraming transfers a single Trice from the Ring Buffer.
  167. //! Implicit assumed is, that the pre-condition "TricesCountRingBuffer > 0" is fulfilled.
  168. void triceTransferSingleFraming(void)
  169. {
  170. triceRingBufferDiagnostics(); // We need to measure before the RingBufferReadPosition increment.
  171. static int lastWordCount = 0; // lastWordCount is needed to increment TriceRingBufferReadPosition accordingly after transfer is done.
  172. triceIncrementRingBufferReadPosition(lastWordCount);
  173. lastWordCount = 0;
  174. if (TricesCountRingBuffer == 0) // no data
  175. {
  176. return;
  177. }
  178. TRICE_ENTER_CRITICAL_SECTION
  179. TricesCountRingBuffer--; // We decrement, even the Trice is not out yet.
  180. TRICE_LEAVE_CRITICAL_SECTION
  181. // The trice data are starting at byte offset TRICE_DATA_OFFSET from TriceRingBufferReadPosition.
  182. triceSingleDeferredOut(&lastWordCount);
  183. }
  184. #endif // #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_SINGLE_PACK_MODE
  185. #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_MULTI_PACK_MODE
  186. //! triceTransferMultiFraming transfers several, but not necessarily all, Trices from the Ring Buffer.
  187. void triceTransferMultiFraming(void)
  188. {
  189. triceRingBufferDiagnostics(); // We need to measure before the RingBufferReadPosition increment.
  190. // The Ring Buffer can contain a fair amount of trices and we do not want them copy in a separate buffer for less RAM usage.
  191. // Therefore we pack all Trices until the Ring Buffer end (where it wraps) together.
  192. // We know here, that at least one Trice is inside the Ring Buffer.
  193. static int triceCount = 0; // triceCount it the count of Trices from the last call.
  194. TRICE_ENTER_CRITICAL_SECTION
  195. // It is known here, that the previous transmission is finished and we can advance.
  196. TricesCountRingBuffer -= triceCount;
  197. TRICE_LEAVE_CRITICAL_SECTION
  198. triceCount = 0;
  199. static int multiWordCount = 0; // wordCount is the Ring Buffer space which is now free after the last transfer is finished.
  200. triceIncrementRingBufferReadPosition(multiWordCount); // We can safely increment here, because we know, that the last transmission is done.
  201. multiWordCount = 0;
  202. triceMultiDeferredOut(&triceCount, &multiWordCount);
  203. return;
  204. }
  205. #endif // #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_MULTI_PACK_MODE
  206. //! TriceTransfer needs to be called cyclically to read out the Ring Buffer.
  207. void TriceTransfer(void)
  208. {
  209. #if TRICE_CGO == 0 // In automated tests we assume last transmission is finished, so we do not test depth to be able to test multiple Trices in deferred mode.
  210. if (TriceOutDepth() > 0) // Last transmission not finished. todo: Write TriceOutDepth() as dummy for TRICE_CGO.
  211. {
  212. return;
  213. }
  214. #endif
  215. #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_SINGLE_PACK_MODE
  216. triceTransferSingleFraming();
  217. #else
  218. triceTransferMultiFraming();
  219. #endif
  220. }
  221. //! TriceIDAndBuffer evaluates a trice message and returns the ID for routing.
  222. //! \param pData is where the trice message starts.
  223. //! \param pWordCount is filled with the word count the trice data occupy from pData.
  224. //! \param ppTriceNetStart is filled with the trice net data start. That is maybe a 2 bytes offset from pData.
  225. //! \param pTriceNetLength is filled with the net trice length (without padding bytes), 0 on error.
  226. //! \retval is the triceID, a positive value on success or error information.
  227. static int TriceIDAndBuffer(const uint32_t *const pData, int *pWordCount, uint8_t **ppTriceNetStart, size_t *pTriceNetLength)
  228. {
  229. uint16_t TID = TRICE_TTOHS(*(uint16_t *)pData); // type and id
  230. int triceID = 0x3FFF & TID;
  231. int triceType = TID >> 14; // 2 bits
  232. unsigned offset;
  233. size_t len;
  234. uint8_t *pStart = (uint8_t *)pData;
  235. switch (triceType)
  236. {
  237. case TRICE_TYPE_S0: // S0 = no stamp
  238. offset = 0;
  239. len = 4 + triceDataLen(pStart + 2); // tyId
  240. break;
  241. case TRICE_TYPE_S2: // S2 = 16-bit stamp
  242. len = 6 + triceDataLen(pStart + 6); // tyId ts16
  243. offset = 2;
  244. #if TRICE_DEFERRED_XTEA_ENCRYPT
  245. // move trice to start at a uint32_t alignment border
  246. memmove(pStart, pStart + 2, len); // https://stackoverflow.com/questions/1201319/what-is-the-difference-between-memmove-and-memcpy
  247. #else // #if TRICE_DEFERRED_XTEA_ENCRYPT
  248. // Like for UART transfer no uint32_t alignment is needed.
  249. pStart += 2; // see Id(n) macro definition
  250. #endif // #else // #if TRICE_DEFERRED_XTEA_ENCRYPT
  251. break;
  252. case TRICE_TYPE_S4: // S4 = 32-bit stamp
  253. offset = 0;
  254. len = 8 + triceDataLen(pStart + 6); // tyId ts32
  255. break;
  256. default: // impossible case (triceType has only 2 bits)
  257. // fall thru
  258. case TRICE_TYPE_X0:
  259. TriceErrorCount++;
  260. *ppTriceNetStart = pStart;
  261. *pTriceNetLength = 0;
  262. return -__LINE__; // extended trices not supported (yet)
  263. }
  264. // S16 case example: triceSize len t-0-3 t-o
  265. // 80id 80id 1616 00cc 8 6 3 6
  266. // 80id 80id 1616 01cc dd 12 7 7 10
  267. // 80id 80id 1616 02cc dd dd 12 8 7 10
  268. // 80id 80id 1616 03cc dd dd dd 12 9 7 10
  269. // 80id 80id 1616 04cc dd dd dd dd 12 10 7 10
  270. *pWordCount = (len + offset + 3) >> 2;
  271. *ppTriceNetStart = pStart;
  272. *pTriceNetLength = len;
  273. return triceID;
  274. }
  275. #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_SINGLE_PACK_MODE
  276. //! triceSingleDeferredOut expects a single trice at TriceRingBufferReadPosition and returns the wordCount of this trice which includes 1-3 padding bytes.
  277. //! The space from TriceRingBufferReadPosition-TRICE_DATA_OFFSET to TriceRingBufferReadPosition is assumed to be usable as scratch pad.
  278. //! This function is specific to the ring buffer, because the wordCount value needs to be reconstructed.
  279. //! \retval The returned value tells how many words where used by the transmitted trice and is usable for the memory management. See RingBuffer for example.
  280. //! The returned value is typically (TRICE_DATA_OFFSET/4) plus 1 (4 bytes) to 3 (9-12 bytes) but could go up to ((TRICE_DATA_OFFSET/4)+(TRICE_BUFFER_SIZE/4)).
  281. //! Return values <= 0 signal an error.
  282. //! TriceRingBufferReadPosition points to the begin of a single trice.
  283. //! The data at TriceRingBufferReadPosition are getting destroyed, because buffer is used as scratch pad.
  284. static void triceSingleDeferredOut(int *wordCount)
  285. {
  286. uint8_t *enc = ((uint8_t *)TriceRingBufferReadPosition) - TRICE_DATA_OFFSET; // TRICE_DATA_OFFSET bytes are usable in front of TriceRingBufferReadPosition.
  287. uint8_t *pTriceNetStart; // Trice starts here. That is maybe a 2 bytes offset from TriceRingBufferReadPosition.
  288. size_t triceNetLength; // Trice length without padding bytes.
  289. int triceID = TriceIDAndBuffer(TriceRingBufferReadPosition, wordCount, &pTriceNetStart, &triceNetLength);
  290. // We can let TRICE_DATA_OFFSET only in front of the ring buffer and pack the Trices without offset space.
  291. // And if we allow as max depth only ring buffer size minus TRICE_DATA_OFFSET, we can use space in front of each Trice.
  292. #if (TRICE_DEFERRED_XTEA_ENCRYPT == 1) && (TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_NONE)
  293. #if TRICE_CONFIG_WARNINGS == 1
  294. #warning configuration: The Trice tool does not support encryption without COBS (or TCOBS) framing.
  295. #endif
  296. size_t encLen = TriceEncode(TRICE_DEFERRED_XTEA_ENCRYPT, TRICE_DEFERRED_OUT_FRAMING, enc, pTriceNetStart, triceNetLength);
  297. #elif (TRICE_DEFERRED_XTEA_ENCRYPT == 1)
  298. // comment: The following 2 steps could be done in an incremental way within one singe loop.
  299. // Behind the trice brutto length (with padding bytes), 4 bytes needed as scratch pad when XTEA is active.
  300. // After TriceIDAndBuffer pTriceNetStart could have a 2 bytes offset.
  301. uint8_t *tmp = ((uint8_t *)TriceRingBufferReadPosition) - 4;
  302. memmove(tmp, pTriceNetStart, triceNetLength); // Make 4 bytes space for scratch pad beind Trice message.
  303. size_t len8 = (triceNetLength + 7) & ~7; // Only multiple of 8 are possible to encrypt, so we adjust len.
  304. memset(tmp + triceNetLength, 0, len8 - triceNetLength); // clear padding space
  305. XTEAEncrypt((uint32_t *)tmp, len8 >> 2);
  306. #if TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_TCOBS
  307. size_t encLen = (size_t)TCOBSEncode(enc, tmp, len8);
  308. #elif TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_COBS
  309. size_t encLen = COBSEncode(enc, tmp, len8);
  310. #else
  311. #error configuration
  312. #endif
  313. enc[encLen++] = 0; // Add zero as package delimiter.
  314. #elif (TRICE_DEFERRED_XTEA_ENCRYPT == 0) && (TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_TCOBS)
  315. size_t len = (size_t)TCOBSEncode(enc, pTriceNetStart, triceNetLength);
  316. enc[len++] = 0; // Add zero as package delimiter.
  317. size_t encLen = len;
  318. #elif (TRICE_DEFERRED_XTEA_ENCRYPT == 0) && (TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_COBS)
  319. size_t len = (size_t)COBSEncode(enc, pTriceNetStart, triceNetLength);
  320. enc[len++] = 0; // Add zero as package delimiter.
  321. size_t encLen = len;
  322. #elif (TRICE_DEFERRED_XTEA_ENCRYPT == 0) && (TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_NONE)
  323. enc = pTriceNetStart;
  324. size_t encLen = triceNetLength;
  325. #else
  326. #error configuration: TRICE_DEFERRED_TRANSFER_MODE == TRICE_MULTI_PACK_MODE for ring buffer not implemented yet
  327. #endif
  328. #if TRICE_DIAGNOSTICS == 1
  329. // enc addr pTriceNetStart nextData
  330. // ^-TRICE_DATA_OFFSET-^-0|2-^-triceNetLength+(0...3)-^
  331. // ^-encLen->firstNotModifiedAddress
  332. uint8_t *nextData = (uint8_t *)(((uintptr_t)(pTriceNetStart + triceNetLength + 3)) & ~3);
  333. uint8_t *firstNotModifiedAddress = enc + encLen;
  334. int distance = nextData - firstNotModifiedAddress;
  335. int triceDataOffsetDepth = TRICE_DATA_OFFSET - distance; // distance could get > TRICE_DATA_OFFSET, so TriceDataOffsetDepthMax stays unchanged then.
  336. TriceDataOffsetDepthMax = triceDataOffsetDepth < TriceDataOffsetDepthMax ? TriceDataOffsetDepthMax : triceDataOffsetDepth;
  337. #endif // #if TRICE_DIAGNOSTICS == 1
  338. TriceNonBlockingDeferredWrite8(triceID, enc, encLen);
  339. }
  340. #endif // #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_SINGLE_PACK_MODE
  341. #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_MULTI_PACK_MODE
  342. // triceMultiDeferredOut packs Trices until the Ring Buffer end and returns their count and total length in words.
  343. // These 2 values are used later, after the transmission is finished, for advancing.
  344. // The value TricesCountRingBuffer is evaluated internally but not modified.
  345. static void triceMultiDeferredOut(int *triceCount, int *multiWordCount)
  346. {
  347. *triceCount = 0;
  348. *multiWordCount = 0;
  349. if (TricesCountRingBuffer == 0)
  350. {
  351. return; // Nothing to do.
  352. }
  353. // At least one Trice message is ready for transfer.
  354. if (TriceRingBufferReadPosition > TriceRingBufferLimit - TRICE_RING_BUFFER_MIN_SPACE32)
  355. {
  356. for (;;)
  357. ; // unexpected
  358. }
  359. // We can start at TriceRingBufferReadPosition and go to the TriceRingBufferLimit OR go to the TriceBufferWritePosition using TricesCountRingBuffer.
  360. uint8_t *enc = ((uint8_t *)TriceRingBufferReadPosition) - TRICE_DATA_OFFSET; // TRICE_DATA_OFFSET bytes are usable in front of TriceRingBufferReadPosition.
  361. uint8_t *tmp = enc + TRICE_DATA_OFFSET / 2; // todo
  362. uint8_t *nextEnc = tmp;
  363. int multiLen = 0;
  364. uint32_t *nextTriceRingBufferReadPosition = TriceRingBufferReadPosition;
  365. do
  366. {
  367. int wordCount = 0;
  368. uint8_t *pTriceNetStart; // Trice starts here.
  369. size_t triceNetLength; // Trice length without padding bytes.
  370. TriceIDAndBuffer(nextTriceRingBufferReadPosition, &wordCount, &pTriceNetStart, &triceNetLength);
  371. memmove(nextEnc, pTriceNetStart, triceNetLength);
  372. nextEnc += triceNetLength;
  373. multiLen += triceNetLength;
  374. *multiWordCount += wordCount;
  375. (*triceCount)++;
  376. nextTriceRingBufferReadPosition += wordCount;
  377. } while (*triceCount < TricesCountRingBuffer && nextTriceRingBufferReadPosition <= TriceRingBufferLimit - TRICE_RING_BUFFER_MIN_SPACE32);
  378. #if (TRICE_DEFERRED_XTEA_ENCRYPT == 1) && (TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_NONE)
  379. #if TRICE_CONFIG_WARNINGS == 1
  380. #warning configuration: The Trice tool does not support encryption without COBS (or TCOBS) framing.
  381. #endif
  382. size_t encLen = TriceEncode(TRICE_DEFERRED_XTEA_ENCRYPT, TRICE_DEFERRED_OUT_FRAMING, enc, enc, multiLen);
  383. #elif (TRICE_DEFERRED_XTEA_ENCRYPT == 1)
  384. size_t len8 = (multiLen + 7) & ~7; // Only multiple of 8 are possible to encrypt, so we adjust len.
  385. memset(tmp + multiLen, 0, len8 - multiLen); // clear padding space
  386. XTEAEncrypt((uint32_t *)tmp, len8 >> 2);
  387. #if TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_TCOBS
  388. size_t encLen = (size_t)TCOBSEncode(enc, tmp, len8);
  389. enc[encLen++] = 0;
  390. #elif TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_COBS
  391. size_t encLen = (size_t)COBSEncode(enc, tmp, len8);
  392. enc[encLen++] = 0;
  393. #else
  394. #error configuration
  395. #endif
  396. #elif (TRICE_DEFERRED_XTEA_ENCRYPT == 0) && (TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_TCOBS)
  397. size_t len = (size_t)TCOBSEncode(enc, tmp, multiLen);
  398. enc[len++] = 0; // Add zero as package delimiter.
  399. size_t encLen = len;
  400. #elif (TRICE_DEFERRED_XTEA_ENCRYPT == 0) && (TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_COBS)
  401. size_t len = (size_t)COBSEncode(enc, tmp, multiLen);
  402. enc[len++] = 0; // Add zero as package delimiter.
  403. size_t encLen = len;
  404. #elif (TRICE_DEFERRED_XTEA_ENCRYPT == 0) && (TRICE_DEFERRED_OUT_FRAMING == TRICE_FRAMING_NONE)
  405. size_t encLen = multiLen;
  406. #else
  407. #error configuration: TRICE_DEFERRED_TRANSFER_MODE == TRICE_MULTI_PACK_MODE for ring buffer not implemented yet
  408. #endif
  409. #if TRICE_DIAGNOSTICS == 1
  410. // todo ...
  411. #endif // #if TRICE_DIAGNOSTICS == 1
  412. TriceNonBlockingDeferredWrite8(0, enc, encLen);
  413. }
  414. #endif // #if TRICE_DEFERRED_TRANSFER_MODE == TRICE_MULTI_PACK_MODE
  415. #if TRICE_RING_BUFFER_OVERFLOW_WATCH == 1
  416. void TriceInitRingBufferMargins(void)
  417. {
  418. for (int i = 0; i < TRICE_RING_BUFFER_LOWER_MARGIN; i++)
  419. {
  420. triceRingBuffer[i] = TRICE_RING_BUFFER_MARGIN_FILL_VALUE;
  421. }
  422. for (int i = 0; i < TRICE_RING_BUFFER_UPPER_MARGIN; i++)
  423. {
  424. *(TriceRingBufferLimit + i) = TRICE_RING_BUFFER_MARGIN_FILL_VALUE;
  425. }
  426. }
  427. void WatchRingBufferMargins(void)
  428. {
  429. for (int i = 0; i < TRICE_RING_BUFFER_LOWER_MARGIN; i++)
  430. {
  431. if (triceRingBuffer[i] != TRICE_RING_BUFFER_MARGIN_FILL_VALUE)
  432. {
  433. for (;;)
  434. ;
  435. }
  436. }
  437. for (int i = 0; i < TRICE_RING_BUFFER_UPPER_MARGIN; i++)
  438. {
  439. if (*(TriceRingBufferLimit + i) != TRICE_RING_BUFFER_MARGIN_FILL_VALUE)
  440. {
  441. for (;;)
  442. ;
  443. }
  444. }
  445. }
  446. #endif // #if TRICE_RING_BUFFER_OVERFLOW_WATCH == 1
  447. #endif // #if TRICE_BUFFER == TRICE_RING_BUFFER && TRICE_OFF == 0