Table of Contents
Introduction
đź’» HACKER In the previous steps we simply edited files with pre-defined code, before running some commands in the terminal. This bare workflow may work to simply and blindly follow along, however there are some tools and methods that we can use to help us develop in Rust.

Here we attempt to outline some of these tools and methods. The goal here is to show how to add, test, and iterate our Rust code for this project.
WARNING
A software development workflow can be highly subjective and ever-evolving, where each developer may have his/her preferences, settings, and so on. Being relatively new to Rust embedded development, my advice is to first follow what is outlined here, then try to customize and set your own workflow however fits you.
Tools
Let’s add the following tools to your local development toolbelt on your computer. For each tool, we will briefly mention the tool, outline some notes, and define its importance and usage.
Remember, the goal here is give some foundemental and useful tools for simplicity for and accessibility for some inexperienced Rust developers.
rust-analyzer
This tool is the official Language Server Protocol (LSP)
server for the Rust programming language that provides code completion
and code navigation capabilities. Aside from the fundamental Rust tools like cargo
, rust-analyzer
is essential for any effective development.
rust-analyzer
typically runs in the background and in parallel with your IDE, constantly watching
your keystrokes and code changes. When appropriate, it provides auto-completion
hints, and options, while also enabling you and your IDE to effectively navigate your
code (i.e. jumping to variable definitions).
Official documentation for rust-analyzer
can be found here.
To install rust-analyzer
, follow these links:
After installation, rust-analyzer
is enabled and started by default when working on Rust code.
bacon
🥓
This tool is a background code checker/linter for Rust that provides real-time error detection and
warnings with minimal user interaction. bacon
usually is run continuously
in a separate terminal, providing immediate feedback as the code changes.
It is highly customizable and integrates
seamlessly with your development workflow. Official documentation for bacon
can be
found here.
To install bacon
, execute the following command within your terminal:
cargo install --locked bacon
After installation, bacon
is available system-wide. You can now run the following
command within your project root directory (Stop bacon
with pressing q
):
bacon --all-features --job clippy
TIP
probe-rs
offers a Visual Studio Code extension
that can use the probe-rs
CLI tool with VS Code to offer more advanced debugging and monitoring capabilities.
In this tutorial, we will not be focused on using this probe-rs
IDE extension, however I encourage
you to familiarise yourself with it and see if that is something you are interested in.
Logging Messages
While logging statements may not be the most powerful or most “sexy” debugging tool, they are effective, simple to understand and use, and tried and true!
The concept is simple. Any time you need to see some information at a specific point in your code, you add a logging statement which will show that information in the terminal output during the program’s run.
Specifically speaking, we will use defmt
with the following syntax to output logging.
Here is an example code snippet using various different defmt
logging statements.
// Import the following on top of the fileuse defmt::*; // Import all items from defmtuse defmt_rtt as _; // Import defmt_rtt - Real-Time Transfer (RTT) as transport for defmt loguse panic_probe as _; // Ensure that panic messages are sent through the debug probe
let my_variable = 3;
// Use the various logging functionsdebug!("A debug level logging message");info!("This is a simple info level log message");error!("This message has a variable: {}", my_variable);
For this specific example Rust code, the terminal output would look like this:
[DEBUG ] example.rs:9 : A debug level logging message[INFO ] example.rs:10 : This is a simple info level log message[ERROR ] example.rs:11 : This message has a variable: 3
The Workflow ♻️
Setup
-
Open the project’s root directory in your IDE.
-
Open one terminal for code warnings/error monitoring.
-
Run the following command in this first terminal:
Terminal window bacon --all-features --job clippy -
Open up a second terminal for building, flashing, and running your code.
Add Changes Continuously
-
Using your IDE, make some changes to the code or project configurations.
-
Monitor if those changes raised any Rust warnings or errors in the
bacon
monitoring terminal. -
In the second terminal that is used for flashing and running code, run the following to build, flash, and run the code:
Terminal window cargo run --release -
While it is running, watch log messages, the microcontroller, and all the things …
-
When ready or needed, stop the running code with pressing
Ctrl-c
in the second terminal. -
Repeat these steps until you are done with your code changes
Commit Changes (Saving Your Work)
-
Use
git
to add/stage all your changes.Terminal window git add . -
Commit the changes to the project’s git history with a useful message. Feel free to use conventional git commit messages.
Terminal window git commit -m "Completed some amazing work" -
Push the local changes to GitHub.com (assuming the default
main
git branch)Terminal window git push origin main
That’ll be our simple workflow. Next, we will talk about our embedded framework.