Skip to the content.

Project Background and Resources

Contents

1. Download and install Trice

Choose a release or a source checkout, then use its matching target sources, host tools, and documentation. An older release binary may not contain features documented by a newer checkout. See firmware and host-tool compatibility.

For the first hardware-free experiment, follow the User Manual. Its PC examples additionally require a native C compiler. Shell examples use Bash; Windows users can run them in Git Bash with a Windows host compiler. For target integration, choose a firmware quickstart.

Trice combines printf-like source calls, ID-based host decoding, and configurable binary transport. Other projects emphasize different languages, runtime environments, tracing models, or integrations. These links are starting points for comparison, not a claim that all projects provide the same features or interchangeable formats.

2.1. Logging and deferred formatting

2.2. Tracing and visualization

2.3. Other techniques and background reading

3. Community and contributions

Use GitHub Discussions for questions, ideas, and integration experience. Search open and closed issues for known problems and previous resolutions. For a reproducible bug, include the tool version, relevant configuration, command, expected result, and actual output.

Examples, documentation improvements, platform recipes, fixes, and reproducible performance measurements are welcome. CONTRIBUTING describes the development workflow, CHANGELOG records release changes, and the MIT License governs the project. AUTHORS lists contributors.

4. Support and sponsoring

If Trice helps your work, you can support it by sharing an example, improving the documentation, reporting a reproducible problem, contributing a fix, or starring the repository. Financial support for continued maintenance is also welcome:

These are the support routes configured by the project in FUNDING.yml. Sponsoring is optional; using Trice does not require a donation.

5. Project history

For the cumulative release changes, see Progress from 1.0 to 2.0.

Developing firmware means to deal also with interrupts and often with timing. How do you check, if an interrupt occurred? OK, increment a counter and display it in a background loop with some printf-like function. What about time measurement? Set a digital output to 1 and 0 and connect a measurement device. Once, developing software for a real-time image processing device, I had no clue where in detail the processing time exploded when the image quality got bad. A spare analog output with a video interrupt synced oscilloscope gave me the needed information, after I changed the analog output on several points in my algorithm. But, hey guys, I want to deal with my programming tasks and do not like all this hassle connecting wires and steer into instruments.

A printf is so cool on a PC, developing software there. But an embedded device often cannot use it for performance reasons. My very first attempt was writing the format string .const offset together with its values in a FIFO during a log statement and to do the printf it in the background. But that is compiler specific. OK the full string address is better but needs buffer space. Zephyr for example does something like that calling it “deferred logging”.

Then, one day I had the idea to compute short checksums for the format strings in a pre-compile step and to use them as ID in a list together with the format strings. That was a step forward but needed to write a supporting PC program. I did that in C++ in the assumption to get it better done that way. Finally, it worked, but I hated my PC code, as I dislike C++ now because of all its nuts and bolts to handle, accompanied by missing libraries on the next PC. The tool usability was also unhandy and therefore error prone and the need became clear for a full automated solution. Also, what is, if 2 different format strings accidentally generate the same short checksum? There was a way around, but an ID based message filtering will never be possible that way.

The need became clear for controllable IDs and management options. And there was Go now, an as-fast-as-C language, easy to learn, promising high programming efficiency and portability. It would be interesting to try it out on a real PC project.

Trying to add tags in form of partial Trice macro names was blowing up the header code amount and was a too rigid design. Which are the right tags? One lucky day I came to the conclusion to handle tags just as format string parts like "debug:Here we are!\n" and getting rid of them in the target code this way also giving the user freedom to invent any tags.

Another point in the design was the question how to re-sync after data stream interruption, because that happens often during firmware development. Several encodings were tried out and a proprietary escape sequence format and an alternative flexible data format with more ID bits were working reliably but with COBS things got satisfactory. A side result of that trials is the Trice tool option to add different decoders if needed. Now the default Trice message framing is TCOBSv1 which includes short message compression and this way allows very low transmit bandwidths and/or saves storage, when binary Trice data are stored in Flash memory.

There was a learning not to reduce the transmit byte count to an absolute minimum, but to focus more on Trice macro speed and universality. That led to a double buffer on the target side as an alternative to the ring buffer solution. The actual binary encoding, allowing alongside user protocols, is the result of the optional target timestamps and location info some users asked for, keeping the target code as light as possible. Float and double number support was implementable for free because this work is done mainly on the host side.

Trice grew, and as it got usable I decided to make it Open Source to say “Thank You” to the community this way.

Learning that Trice is also a baby girl name, our daughter Ida designed the little girl with the pen symbolizing the Trice macro for recording and the eyeglasses standing for the PC tool Trice visualizing the logs.

./ref/TriceGirlS.png

5.1. Progress from 1.0 to 2.0

ID-based binary logging, Insert/Clean, target buffers, COBS/TCOBS, XTEA and RTT were already available in 1.0. The table separates later improvements from the features introduced with 2.0; use the Changelog for individual release notes.

Release period Progress for users Current reference
1.1.x Macro aliases and user tags, UDP input, additional stamp/version information and more host packages. Existing logging macros, CLI
1.2.x More stamp-delta and portability support, shared decoder registration, format-string removal and printf-length corrections. Standalone tlog arrived in 1.2.3; installation packages expanded. Stamps, Printf comparison, Build and release
1.2.4 to 1.3.0 Counted typeX0 payloads, ABC reception and broadcast commands with multi-node examples. ABC was already part of 1.3.0. typeX0, ABC
2.0 Bind supplies IDs through generated headers so source calls remain ID-free. Insert/Clean stays available; compiler and wrapper limits are documented. Bind
2.0 Named structured fields with text/JSON/key-value output; Context Enrichment adds selected context values with explicit limits for direct and wrapper/rebase sites. Structured logging, Context Enrichment
2.0 Weighted tags, filtering, configurable colors, consistent macro-alias identity and updated CLI/custom-tag spellings. Tags, Alias identity
2.0 Host-side printf, unwrap and delta expressions for stamps, plus numeric visualization through files or UDP. Stamp expressions, Visualization
2.0 Local deferred text logging on the target, source-selected C metadata, readable dictionaries and Bind reports. Target implementation, Generation
2.0 Deterministic ID assignment for identical calls, improved reload/replay and filter behavior, a guided User Manual, a split reference and two release PDFs. IDs, User Manual, Reference

Before rebuilding a 1.x project, follow the migration guide and preserve the matching firmware, tool and dictionaries. The unchanged record layout alone does not make old format strings compatible with the new field syntax.

6. Ideas for future development

These are ideas and historical proposals, not release commitments.

The Future Design Ideas appendix preserves the dictionary-schema, dashboard-adapter and C-host-decoder proposals recovered from the former archive.

6.1. Further Context Enrichment Variants

Context Enrichment supports direct Bind log sites and reversible source extensions with insert/clean. Bind rejects selected CE sites in wrapper macros or counter-rebase regions. Use an ordinary function, put direct calls on separate source lines, or use insert/clean as described under bind-limits.

6.2. Improving the Trice Tool Internal Parser (not planned right now)

6.2.1. Trice Internal Log Code Short Description

Trice v1.0 Code

Hint: To follow this explanation with the debugger, open the trice folder in VSCode, click the Run & Debug button or press CTRL-SHIFT-D, select trice l -p DUMP and set a breakpoint at func main() in ./cmd/trice/main.go or directly in translator.Translate in ./internal/translator/translator.go.

Disadvantages of Trice v1.0 Implementation
Aims for a better implementation

6.3. Using Trice on Servers

A server can ingest and analyze Trice streams from devices. Using Trice as the server application’s own logger is a separate use case and needs evidence of a practical benefit. Claims about speed, energy use, storage, and additional compression require measurements with equivalent retained information.