defmt Setup

We have created a Cargo project template to make the setup easier. Here are the setup steps.

  1. Install version v0.1.4 (or newer) of probe-run, a custom Cargo runner that lets you run embedded apps if they were native apps.
$ cargo install probe-run
  1. Either initialize the project template with cargo-generate or fetch a copy and initialize the Cargo.toml manually.
$ cargo generate \
    --git https://github.com/knurling-rs/app-template \
    --branch main \
    --name my-app

If you are not using cargo-generate you'll need to manually enter the author and name fields in Cargo.toml.

 # Cargo.toml
 [package]
-# authors = ["{{authors}}"]
-# name = "{{project-name}}"
+name = "my-app"

After that there are a few TODOs in the template. You can ripgrep for the word TODO (rg TODO .cargo .) to find them but we'll walk you through all of them in this blog post.

  1. Pick a chip from probe-run --list-chips and enter it into .cargo/config.toml.

If, for example, you have a nRF52840 Development Kit from one of our workshops then replace {{chip}} with nRF52840_xxAA.

 # .cargo/config.toml
 [target.'cfg(all(target_arch = "arm", target_os = "none"))']
-runner = "probe-run --chip {{chip}} --defmt"
+runner = "probe-run --chip nRF52840_xxAA --defmt"
  1. Adjust the compilation target in .cargo/config.toml.

For the nRF52840 chip you'll want to use the thumbv7em-none-eabihf target.

 # .cargo/config.toml
 [build]
-target = "thumbv6m-none-eabi"    # Cortex-M0 and Cortex-M0+
-# target = "thumbv7m-none-eabi"    # Cortex-M3
-# target = "thumbv7em-none-eabi"   # Cortex-M4 and Cortex-M7 (no FPU)
-# target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
+target = "thumbv7em-none-eabihf" # Cortex-M4F (with FPU)

If you haven't done so already, install the rust-std component for the target above:

$ rustup target add thumbv7em-none-eabihf
  1. Add a HAL as a dependency.

For the nRF52840 you'll want to use the nrf52840-hal.

 # Cargo.toml
 [dependencies]
-# some-hal = "1.2.3"
+nrf52840-hal = "0.11.0"
  1. Now that you have selected a HAL fix the HAL import in src/lib.rs
 // my-app/src/lib.rs
-// use some_hal as _; // memory layout
+use nrf52840_hal as _; // memory layout

Hello defmt

You are now all set to cargo-run your first defmt-powered application! There are some examples in the src/bin directory.

// my-app/src/bin/hello.rs

#![no_main]
#![no_std]

use my_app as _; // global logger + panicking-behavior + memory layout

#[cortex_m_rt::entry]
fn main() -> ! {
    defmt::info!("Hello, world!");

    my_app::exit()
}

cargo run-ning this program produces the classic "Hello, world!" output.

$ # `rb` is an alias for `run --bin`
$ cargo rb hello
    Finished dev [optimized + debuginfo] target(s) in 0.03s
flashing program ..
DONE
resetting device
0.000000 INFO Hello, world!
(..)

$ echo $?
0

Or if you are using VS code + Rust-Analyzer, instead, you can open the src/bin/hello.rs file and click the "Run" button as we demonstrated in a previous blog post.

For more details check out the defmt book.