How to Integrate Modality Into RTIC Systems

# Summary

In this guide we will walk through the following steps to enable Modality's functionality in your RTIC (opens new window) system.

Integration Steps

Currently, Modality's RTIC integration is realized as a set of in-tree patches for rtic-syntax (opens new window) and cortex-m-rtic (opens new window). These will eventually be replaced by an out-of-tree integration solution.

A new custom attribute is provided (#[modality_probe(...)]). When applied to a task, this attribute will synthesize a Modality probe instance in the task's local resources.

# RTIC Only

This guide provides integration steps specific to RTIC. The full list of integration guides includes integration instructions for any C project, as well as other platform-specific Modality integrations, such as for FreeRTOS and Zephyr.

# Integrate With Your Build

  1. Install Modality. You can use the Linux package (Debian) or the tarball.

  2. Update your Cargo.toml dependencies to point to Modality's cortex-m-rtic fork (opens new window).

cortex-m-rtic = { git = "" }
  1. Add modality-probe-sys crate dependency to your Cargo.toml
# If using the Modality debian package
path = "/usr/share/modality/modality-probe-sys"
features = ["static"]
default-features = false
# If using the Modality tarball package
# For example, if Modality is extracted to /usr/local/modality:
# export PATH=$PATH:/usr/local/modality/bin
# export MODALITY_PROBE_VERSION=$(cat /usr/local/modality/VERSION)
# export MODALITY_PROBE_LIBRARY_DIR=/usr/local/modality/lib/<target-triple>
path = "/usr/local/modality/rust/modality-probe-sys"
features = ["static"]
default-features = false

# Using Probes

Probes are the machinery that enables Modality's instrumentation. Using the RTIC integration makes working with probes easier.

Simply decorate tasks with the modality_probe attribute to initialize a probe for each task.

  • modality_probe arguments:

    • name - Ident - Probe name used when generating a manifest entry for the probe
    • size - u32 - Probe storage buffer size in bytes
    • local_name - Ident - Optional local variable name, defaults to 'probe'
  • modality_probe Args not mentioned in original readme:

    • description - Option<LitSt> - Optional description
    • storage_name - Ident - Name of the probe-backing storage buffer
    • storage_resource - Local - Probe-backing storage resource
    • probe resource - LocalResource - Probe resource
// name: Probe name used when generating a manifest entry for the probe
// size: Probe storage buffer size
// local_name: Optional local variable name, defaults to 'probe'
#[modality_probe(name = PROBE_FOO, size = 1024)]
fn foo(ctx: foo::Context) {
    record!(ctx.local.probe, EVENT_FOO, "Event FOO happened", tags!("foo", "RTIC"));

#[modality_probe(name = PROBE_BAR, size = 1024, local_name = p)]
fn bar(ctx: bar::Context) {
    record_w_u32!(ctx.local.p, EVENT_BAR, 1_u32, "Event BAR happened", tags!("bar", "RTIC"));

# Example

  1. Install QEMU (opens new window)
sudo apt install qemu-system-arm
  1. Install thumbv7m-none-eabi target
rustup target add thumbv7m-none-eabi
  1. Build the example
cd example/
cargo build
  1. Run it
cargo run