
Kick off your embedded Rust journey with a quick Rust fundamentals intro, covering variables, statics, arrays, references and ownership, match statements, strings, enums, options, and result types.
Install and configure the Rust host toolchain with rustup, including rustc, cargo, and clippy, then set up a hello world project in VSCode and manage toolchains with rustup commands.
Install and explore the Rust toolchain on Windows, including the compiler, cargo, std, and Clippy, and understand the target triple and tier one targets for ARM microcontrollers.
Learn to create a hello world Rust project with cargo, set up VS Code with Rust extensions, and build and run binary crate using cargo build and cargo run.
Master rustfmt, cargo fix, and Clippy to format Rust code, enforce idiomatic patterns, and apply automated fixes. Enable Clippy in VSCode for real-time hints.
Learn how Rust ensures memory safety unlike C/C++, using ownership, the borrow checker, and the option type to prevent null pointers and use-after-free.
Learn how to create local and global static variables in Rust using let, type inference, and explicit casting with as, while exploring primitive data types and mutability.
Learn how Rust uses static for immutable and mutable globals, why mutating statics requires unsafe blocks, and that immutable statics live in ROM while mutable ones in RAM.
Learn how Rust constants use const to define compile-time values. Contrast them with static variables that are inlined and do not occupy memory, like peripheral base addresses and gpio pins.
Explore how Rust prevents buffer overflows and ensures memory safety through runtime bounds checks, panic handling, and automatic memory management with ownership, drop, and smart pointers.
Explore Rust references, including ampersand forms like ref and ref mut, and how the borrow checker enforces one mutable or multiple immutable references, with lifetimes in safe Rust.
Explore the borrow operation in Rust, distinguishing immutable borrows from mutable borrows, using ampersand and ampersand mut, and why only one mutable borrow is allowed at a time.
Explore Rust's decision making with if else and match, including if let and pattern matching; learn expressions, statements, and how blocks return values.
Explore the Rust match statement, its pattern matching, exhaustiveness, and catch-all patterns, with practical examples using integers, tuples, and arrays.
Master the if let statement as a shorthand for a single-pattern match, with an optional else block, and use the at operator, underscores, and chained else if let in Rust.
Rust guarantees memory safety by preventing data races and dangling references with the borrow checker. It enforces explicit casts and initialization, unlike C/C++ which risks type confusion.
Explore Rust's comparison operators, including ==, !=, >, <, >=, <=, and learn how PartialEq and PartialOrd enable custom type comparisons, plus how !, &&, and || operate on booleans.
Explore bitwise operators in Rust, including not, and, or, and left and right shifts. Understand unsigned versus signed shifts and how traits enable bitwise operations on custom types.
Explore how Rust stores strings as utf eight encoded data by default, enabling Unicode text and emoji, while ASCII characters use one byte and non-ascii characters may take multiple bytes.
Define rust functions with the fn keyword, a snake_case name, and an explicit parameter list. Call with parentheses and return values via a final expression or return statement.
Learn how to print a Rust struct using println and the debug trait, derive a debug implementation with #[derive(Debug)], and understand when to implement display for custom types and mutability.
Pass a struct by reference using a mutable borrow and access its fields with the dot operator, no dereferencing needed, while updating a person's age and hinting at structure methods.
Define associated functions in Rust and show how they differ from methods using self, then illustrate constructors like new and default via impl blocks with rectangle and point examples.
Explore Rust enums and their variants, including associated data, to model states like car status or game state. Learn to create enum instances and extract data with match patterns.
Implement an area method for the shape enum with circle, rectangle, and square variants, each carrying associated data, and compute areas using the provided formulas.
learn rust error handling using the result and option enums, unwrap and expect, panic macros for unrecoverable errors, and the question mark operator for error propagation in recoverable error management.
Master the question mark operator in Rust, propagating errors and enabling early returns by unwrapping result or option values, with main returning a result or unit and reduced match boilerplate.
Learn generics in Rust to write reusable, type-safe code across functions, structs, enums, traits, closures, and methods; use generic type parameters with trait bounds and understand monomorphism.
Explore the hardware for this course: the fast bit Stm32 nano board with stm32 f3 cortex-m4 and mpu6050 accelerometer/gyroscope, plus an lcd shield with touch, usable on any stm32 board.
Learn native versus cross compilation in embedded rust, configure a host toolchain for a target like armv7-m cortex-m, and build bare-metal no-std projects with cargo --target and target add.
Learn to build a bare-metal rust program by adding a panic handler, using no_std with no_main and no_mangle, and generating an ARM elf executable.
Explore the ELF executable format and inspect its headers, program headers, and sections using cargo-binutils, including text, data, symbol tables, and linker scripts for bare metal embedded projects.
Learn to write startup code for a microcontroller in Rust, defining the vector table, reset handler, and exception handlers, copying data to RAM, zeroing BSS, and calling main.
Explore how to create and connect a linker script for an embedded rust project, configure cargo to use a linker and pass flags, and place memory sections with memory.ld.
Write a linker script from scratch to define memory regions and map sections to outputs using memory and sections commands for flash, ram, core coupled memory, and battery backed ram.
Explain read-only data, initialized data, uninitialized data, and stack and heap in Rust, mapped to flash memory and RAM, with startup code handling dot data and BSS.
Use the location counter to define and align linker symbols for data and bss in ram, initialize the stack pointer, and set the entry to the reset handler.
Learn how to build a vector table in Rust for STM32 microcontrollers, placing stack pointer, exception and interrupt handlers at flash start, and using a default handler for unused IRQs.
Learn to fix Rust startup code by declaring external C functions, using extern "C" for the vector table's interrupt handlers, and aligning with the C ABI and ARM EABI.
Copy the data section from flash to SRAM and zero-initialize the BSS in RAM within the reset handler, using linker-script symbols referenced via an extern block in Rust.
Explore raw pointers in Rust, including mutable and immutable C-like pointers, and learn why unsafe blocks govern their manipulation in safe versus unsafe Rust.
Implement a reset handler that copies the data section from flash to RAM and zeroes the BSS, using address_of and address_of_mut, raw pointers, and unsafe blocks, then calls main.
Flash the ELF to the target hardware and debug your Rust code using stlink or jlink with stm32cube clt and cortex-debug in vscode.
Learn to flash and debug embedded Rust projects on STM32 microcontrollers using VS Code, cortex-debug, GDB servers, and ST-LINK, with setup of toolchains, SVD files, and launch configurations.
Flash the elf file onto target hardware using probeRS, including installation, chip selection, and cargo flash options. Configure cargo run with a probeRS runner in .cargo/config.toml.
Toggle the development board LEDs with a button interrupt in bare metal Rust using raw pointer access to peripheral registers and a template cargo project with no external dependencies.
Learn how to resolve function scope by using module paths and use statements, organize embedded rust code with board and mcu modules, and declare public constants for GPIO pins.
Configure the GPIO output mode by calculating the bit position from the pin, applying a mode mask, and updating the register using clear_bits and set_bits helpers.
Refactor the LED module by moving GPIO code to a dedicated GPIO module and reg manipulation to reg, implement GPIO pin state with high, low, and toggle.
Explore inner documentation comments for modules and crates, explain outer documentation at the top of a module or crate, and show how cargo doc renders the crate front page.
Implement the button module with a public button_init that configures the port and pin in either input or interrupt mode, using Mode and Trigger enums.
Explore how gpio interrupts are delivered to the stm32 processor via the exti controller. Configure edge triggers with rising and falling registers and organize exti gpio modules for masking.
Demonstrates implementing enable_interrupt and disable_interrupt in Rust by using configure_interrupt, modifying IMR1/IMR2 via EXTI line numbers, and configuring SYSCFG EXTICR registers for correct GPIO-to-EXTI mapping.
Learn how to enable and route external interrupts on STM32 with EXTI and NVIC, map EXTI lines to IRQ numbers, and implement enable_irq and disable_irq in a processor module.
Explore external crates in embedded Rust via cargo and crates.io, and learn library vs binary crates, main.rs, and how a package may contain crates with at most one library crate.
Explore essential Rust crates for embedded systems, from cortex-m and cortex-m-runtime to cortex-m-rtic and embedded-hal, hardware abstraction layers, and peripherals like mpu6050, with FFI basics, RTIC, embassy, and defmt logging.
Explore how to set up the embedded runtime with the cortex-m-rt crate for ARM cortex microcontrollers, including entry, exception, and pre_init attributes, linker script considerations, and stack setup.
Understand Rust semantic versioning for crates, including major, minor, and patch changes, and learn cargo version specifiers such as =, ^, ~, and range expressions to manage dependencies.
Explore panic handling crates for embedded Rust, including panic-halt and panic-itm, and configure a global panic handler. Learn to integrate cortex-m-rt and cortex-m for SysTick handling and ITM logging.
Learn to generate 500 ms SysTick interrupts on STM32 using the cortex-m crate, leveraging the singleton Peripherals pattern, take(), and reload value calculation for reliable timing.
Learn how to test a SysTick-based 500 ms time base on STM32 by using the cortex_m_rt linker script, memory.x, and cargo debugging to verify led toggling.
Explore instrumentation trace macrocell (itm) for sending log messages over swo via tpiu and itm stimulus ports on cortex-m processors; configure acpr baud rate and enable swo protocol.
Initialize ITM for SWO output by configuring the TPIU_ACPR prescaler, enabling trace, enabling stimulus port 0, and logging with iprintln in main and systick.
Learn how Rust interoperates with C through the foreign function interface, using extern \"C\", unsafe blocks, and precise type mapping to call and be called by C code.
Explains handling C void and void pointers in Rust via FFI, including mut pointers, casting to i32, null checks, and memory management with a free function.
Rust passes strings to C by converting them to std::ffi::CString, ensuring UTF-8 validity, null termination, and no interior nulls, then uses as_ptr to hand a const char pointer.
Learn to pass a Rust struct to C by reference or by value, using raw pointers, repr(C), and layout matching, with heap-field handling via C strings and a print_item example.
==> Looking to add another embedded programming language to your arsenal? Give Rust a shot — you won’t be disappointed!! <==
This course is your starting point for using Rust on ARM Cortex Mx based microcontrollers such as STM32, even if you are new to embedded systems.
This is a fully hands on course that takes you from scratch into real world embedded Rust development on STM32. Each video builds on the previous, helping you progress step-by-step, from writing bare metal code to advanced topics like FFI, crates, driver development, and traits. Ideal for those new to Rust and embedded systems.
Why Rust for embedded?
Rust prevents many common memory issues (like null pointer dereferencing, buffer overflows, and use-after-free errors) through:
Ownership model: Rust’s strict rules around ownership, borrowing, and lifetimes prevent most accidental memory misuse.
Type safety: Rust’s type system ensures that you access data correctly and helps prevent certain types of invalid memory access by enforcing strict variable usage patterns.
Thanks to Cargo, Rust’s official package manager, you can easily add features by simply including external libraries, or "crates," which are like plug-and-play components.
What will you learn?
Here’s what you will master in this course:
A beginner-friendly introduction to Rust, tailored for embedded systems
Complete toolchain setup for cross-compiling, flashing, and debugging
Debugging and logging with defmt and probe-rs for real-time tracing
High-level peripheral programming with STM32 HAL crate
Step-by-step, build a real-world Flappy Bird game application using Rust
Interface with real sensors (MPU6050) to control game mechanics
Clean, modular coding practices and hardware abstraction
Build hardware-agnostic drivers using the embedded-hal traits
Writing and understanding your own linker scripts and startup code
Building generic embedded code using Rust generics and traits
Safe and seamless Rust + C integration through FFI
Confidence to write robust, reusable, and production-grade embedded firmware in Rust
Hardware Requirements
Note: If you already have a microcontroller development board, we recommend continuing with it. This course is designed with such thoroughness that the concepts and steps can be applied to most development boards though some minor adjustments may be needed. But, if you prefer to use the exact same board as the instructor for a smoother experience, you can check out the recommended hardware
1) Microcontroller development board
Option-1. STM32F303-Based Board
The course primarily utilizes Fastbit STM32 Nano board which is based on the STM32F303 microcontroller and onboard MPU6050 sensor.
Option 2. Any STM32 Microcontroller Board
You can use any development board featuring an STM32 microcontroller. The course content is designed to be adaptable, allowing you to follow along with the specific STM32 board you have available.
2) SWD-Based Debugger
An SWD (Serial Wire Debug) based debugger is required for programming and debugging your STM32 microcontroller. This tool is essential for loading your programs onto the microcontroller and for debugging your projects in real-time.
3) LCD shield
In one of the projects, you will need a TFT LCD module for experimentation. This course uses the Fastbit 1.28" TFT LCD with an 8-bit parallel interface, based on the GC9A01 LCD driver. However, you are free to use the same or a similar compatible module
4) MPU6050 sensor
Software requirements
VS Code
STM32CubeIDE