Skip to the content.

Binary Format, Framing and Encryption

Contents

1. Overview

CountAndCycle.svg

Most trice messages are with small payloads (<128) and take advantage of a cycle counter which allows to detect transmission issues with a high probability. Some Trice messages may contain more payload bytes. Then the cycle counter is incremented too but not transmitted and the cycle byte serves as additional count bits.

CountAndCycle.svg

The 2 selector bits control the Trice header layout in the following way:

TriceTypesBuffer.svg

For speed and alighnemt reasons the target internal representation is:

TriceTypesBuffer.svg

The leading doubled 2 bytes are removed before framing. But there are cases, these doubled 2 bytes are transmitted too. That is when using direct mode is used over RTT, a for developers important setting. To tell that tlog the CLI switch -d16 is needed.

2. Symbols

Symbol Meaning
i ID bit
I iiiiiiii = ID byte
n number bit
z count selector bit
s stamp selector bit
N znnnnnnnn = count selector bit plus 7-bit number byte
c cycle counter bit
C z==0 ? cccccccc : nnnnnnnn = cycle counter byte or number byte extension
t (time)stamp bit
T tttttttt = (time)stamp byte
d data bit
D dddddddd = data byte
... 0 to 32767 data bytes
"..." format string
W bit width 8, 16, 32 or 64 (uW stands for u8, u16, or u64)
x unspecified bit
X =xxxxxxxx unspecified byte

The long count field can represent up to 32767 payload bytes. This is the binary format limit, not the amount that the current target buffer macros can write. TRICE_N, TRICE_S, and the buffer macros built on TRICE_N cap the payload at TRICE_SINGLE_MAX_SIZE - 12 bytes. TRICE_SINGLE_MAX_SIZE is the reserved size of one aligned target-side record and cannot exceed 32764 bytes; therefore the largest payload through these macros is 32752 bytes. The limit for a runtime string counts its characters, excluding the terminating zero byte.

The 12-byte allowance covers up to 8 bytes for the ID, a 32-bit timestamp, and the count field, plus one 4-byte word for alignment and output scratch space. The target rounds the stored payload up to a 32-bit boundary; some output paths also need space after the record, for example when padding for XTEA encryption. At the macro’s maximum payload size, the aligned record uses at most TRICE_SINGLE_MAX_SIZE - 4 bytes, leaving that word inside the reserved size. Package framing can add further bytes on the transport.

3. Package Format

Example for Trices without timestamps

value byte offset type comment
IdLo 0 byte The first byte is always the Trice ID lower 8 bits.
IdHi 1 byte The second byte 2 most significant bits are 01 and the 6 least significant bits are the Trice ID upper 6 bits.
NC 2 u16 The most significant bit is the count selector bit z and usually 0, telling, that the following 7 bits are the payload byte count and that the 8 least significant bits are the cycle counter. If z is 1, the current Trice contains no cycle counter and has a 15-bit payload count instead (for payloads > 127).
payload 4 u8|u16|u32|u64 The payload contains a number of equal size values.

3.1. typeX0 Records

The user can insert any data with a well-defined structure into the Trice data stream. When interpreting the Trice binary data, the Trice tool handles selector-0/typeX0 records according to the CLI switch -typeX0.

One possible use case is to have user printi statements parallel to Trices (see Legacy User Code Option Print Buffer Wrapping and Framing). For the counted typeX0 variant, the user prepends a generated printi buffer with its payload size as a 16-bit count smaller than 16384. See ./_test/userprint_dblB_de_tcobs_ua/TargetActivity.c for an implementation option. See chapter 20. typeX0 User Packets for further details.

3.2. Framing - NONE or with COBS or TCOBS encoding

Summary Information for Trice Data Parsing

Details

Framing NONE Overview Table:

mode packed -pf= encr wr use pad stream remark
di single none32 NONE 32 32 0-3 aligned done
de single none8 NONE 8 8 0 compact done
de single none32 NONE 8 32 0 aligned plan
de multi none8 NONE 8 8 0 compact done
de multi none32 NONE 8 32 0 unknown forbid
de multi none NONE 8 32 0 unknown forbid
di single none64 XTEA 32 32 0-7 aligned done
de single none64 XTEA 8 8 0-7 aligned done
de single none64 XTEA 8 32 0-7 aligned plan
de multi none XTEA 8 8 0-7 unknown forbid
de multi none XTEA 8 32 0-7 unknown forbid

4. Framing and encoder dependencies

Encoder dependencies follow the active outputs. Select direct framing with TRICE_DIRECT_OUT_FRAMING and deferred framing with TRICE_DEFERRED_OUT_FRAMING. An inactive output’s framing setting adds no dependency. For example, a direct-only COBS application does not need TCOBS despite the deferred framing default.

Active output framing Required encoder source Encoder sources that can be omitted
TCOBS only src/tcobsv1Encode.c src/cobsEncode.c
COBS only src/cobsEncode.c src/tcobsv1Encode.c
NONE only None Both encoder sources
Direct COBS and deferred TCOBS, or the reverse Both encoder sources Neither

These selective builds work without LTO, optimization or linker removal of unused sections. Encryption-disabled builds need no src/xtea.c; builds without RTT need no src/SEGGER_RTT.c or project RTT configuration. With the Trice backend disabled (TRICE_OFF or TRICE_CLEAN, without counted typeX0 transmission), retained UART settings do not require triceUart.h or UART hardware hooks. The minimal demos still compile src/*.c for simplicity; removing unreferenced code from such a complete-library build remains a separate image-size optimization.

TriceEncode(encrypt, framing, dst, buf, len) keeps its runtime framing argument. By default, TRICE_COBS_ENCODE_SUPPORT and TRICE_TCOBS_ENCODE_SUPPORT include exactly the encoders needed by active outputs. If your own code calls this API with additional framing methods, enable the corresponding support in triceConfig.h and link its encoder source. For example, add runtime COBS to an otherwise TCOBS-only application with:

#define TRICE_COBS_ENCODE_SUPPORT 1

Use TRICE_TCOBS_ENCODE_SUPPORT 1 to add runtime TCOBS instead. Both switches accept only 0 or 1; disabling an encoder required by an active output is a compile-time error. A request for a framing method not included in the build returns 0, leaves the source and destination untouched, and produces no fallback frame. Unknown framing values also return 0. NONE remains available without either encoder; its return value is the copied byte count, without a delimiter. Check the return value before sending the destination buffer.

The encoder dependency tests link isolated native projects at -O0, decode their real output, and check disabled outputs and runtime opt-ins. They also inspect ARM GCC objects when that toolchain is installed; no test relies on LTO or unused-section removal.

5. Endianness

6. Optional XTEA encryption

Trice supports optional XTEA encryption. Configure it in the application’s triceConfig.h, using the settings documented in triceDefaultConfig.h:

Setting Use
XTEA_ENCRYPT_KEY Target encryption key.
TRICE_DIRECT_XTEA_ENCRYPT 1 Encrypt direct output; adds work in the call’s critical path.
TRICE_DEFERRED_XTEA_ENCRYPT 1 Encrypt deferred output during transfer.

Run trice log -port ... -password MySecret -showKey once to obtain the matching key definition, then use the same password when decoding. The example password is not a project secret.

Encryption pads data to an 8-byte boundary before framing; decryption follows frame decoding. COBS is the usual choice. Select -pf cobs on the host and TRICE_FRAMING_COBS for the encrypted target output. TCOBS offers little compression on encrypted data.

This format provides no message-authentication mechanism. Do not interpret successful decryption as proof of the sender’s identity or of unmodified data.

7. Minimal Transfer Bytes Amount

A Trice message is 4 bytes long (2 ID bytes and 2 count bytes) plus optional time stamps and/or values. In conjunction with the compressing TCOBS framing the Trice data stream is as small as possible. Use the -debug switch to see the compressed and framed packages alongside the decompressed ones together with the decoded messages.

To see the encoding for each single message #define TRICE_DEFERRED_TRANSFER_MODE TRICE_SINGLE_PACK_MODE inside the project specific triceConfig.h.

Without -debug CLI switch:

ms@MacBook-Pro G0B1_inst % trice log -p /dev/tty.usbmodem0007722641261 -prefix off -li off -hs off -ts off
...
This is a message without values and without stamp.
...

With -debug CLI switch:

ms@MacBook-Pro G0B1_inst % trice log -p /dev/tty.usbmodem0007722641261 -prefix off -li off -hs off -ts off -debug
...
TCOBSv1: c1 74 e2 23 00
->TRICE: c1 74 e2 00
This is a message without values and without stamp.
...

The TCOBS encoding cannot compress in the example above, because the data are too small, but here is a significant compression result shown:

ms@MacBook-Pro G0B1_inst % trice log -p /dev/tty.usbmodem0007722641261 -prefix off -hs off -debug
...
TCOBSv1: b8 76 7b 18 84 fe e1 fd e1 fc e1 fb e1 fa e1 00
->TRICE: b8 76 7b 18 ff ff ff ff fe ff ff ff fd ff ff ff fc ff ff ff fb ff ff ff fa ff ff ff
_test/testdata/triceCheck.c   805              value=-1, -2, -3, -4, -5, -6
...

When encryption is active, a compression makes no sense, but the TRICE_MULTI_PACK_MODE can help to reduce the total amount of padding bytes, because each encrypted package must have a multiple of 8 as length.

ms@MacBook-Pro G0B1_inst % trice log -p /dev/tty.usbmodem0007722641261 -prefix off -hs off -pw MySecret -pf cobs -debug
...
cobs: 21 84 b7 60 8b 21 89 1e e3 07 6d dc d9 2d 6f 59 04 8e 50 8f 24 1c a2 63 2e 3d 4a 57 ef 39 63 01 cb 00
->TRICE: 84 b7 60 8b 21 89 1e e3 07 6d dc d9 2d 6f 59 04 8e 50 8f 24 1c a2 63 2e 3d 4a 57 ef 39 63 01 cb
-> DEC:  cc b6 63 01 71 02 ff fe cd 76 72 03 ff fe fd ce f6 64 81 00 00 73 04 ff fe fd fc 00 00 00 00 00
_test/testdata/triceCheck.c   827        0_355 value=-1, -2
_test/testdata/triceCheck.c   828              value=-1, -2, -3
_test/testdata/triceCheck.c   829    0,033_124 value=-1, -2, -3, -4
cobs: 19 50 70 79 d7 75 6f d7 99 dc d8 ec 06 e1 66 e7 a7 c1 0d 96 85 df 19 25 55 00
->TRICE: 50 70 79 d7 75 6f d7 99 dc d8 ec 06 e1 66 e7 a7 c1 0d 96 85 df 19 25 55
-> DEC:  cf b6 64 01 74 05 ff fe fd fc fb d0 76 75 06 ff fe fd fc fb fa 00 00 00
_test/testdata/triceCheck.c   830        0_356 value=-1, -2, -3, -4, -5
_test/testdata/triceCheck.c   831              value=-1, -2, -3, -4, -5, -6
...