Display “Hello Rust!” on an SSD1306 OLED using the STM32F446RE Nucleo board — entirely in Rust!
This project demonstrates a clean and minimal Embedded Rust application for the STM32F446RE, using an SSD1306 OLED display to render text over I²C. It serves as a beginner-friendly foundation for learning low-level Rust on ARM microcontrollers, focusing on safe abstractions, memory control, and real-time embedded behavior. While it currently outputs basic text, the project is designed to grow—making it easy to integrate additional hardware such as BME280 environmental sensors, IMUs, GPS modules, or external flash storage, allowing sensor readings or system data to be displayed directly on the OLED. This modular approach encourages improving and expanding the code into dashboards, weather stations, or fully interactive embedded systems.
| Component | Description |
|---|---|
| STM32F446RE | Nucleo-64 Development Board |
| SSD1306 OLED (128×64) | I2C interface |
| Jumper Wires | 4× Female-to-Male |
| Micro USB Cable | Must support data/programming |
Using the I2C1 peripheral of the STM32:
| OLED Pin | STM32 Pin | Nucleo Header | Description |
|---|---|---|---|
| VCC | 3V3 | 3V3 | Power (3.3V) |
| GND | GND | GND | Ground |
| SCL | PB8 | D15 | I2C Clock |
| SDA | PB9 | D14 | I2C Data |
⚠️ Note: Most SSD1306 modules support 3.3V. If yours needs 5V, check the module’s back label.
3.3V is the safe choice for STM32.
┌──────────────────────────────────────────┐
│ SSD1306 OLED (128x64, I²C) │
│ │
│ GND ────────────────┐ │
│ VCC ────────────────┤───► 3.3V │
│ SCL ────────────────┤───► PB8 (D15) │
│ SDA ────────────────┘───► PB9 (D14) │
│ │
│ *(Pull-ups usually built in)* │
└──────────────────────────────────────────┘
I²C Bus (3.3V Logic)
▲
│
┌────────────────────────────────────────────┐
│ NUCLEO-F446RE (STM32F446) │
│ │
│ PB8 ── SCL (Open-Drain, I²C1) ◄─────────┘
│ PB9 ── SDA (Open-Drain, I²C1) ◄─────────
│ │
│ 3.3V ───────────────► OLED VCC │
│ GND ───────────────► OLED GND │
└────────────────────────────────────────────┘
Ensure Rust is installed:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add thumbv7em-none-eabihf
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh
1️⃣ memory.x (Flash & RAM layout)
Create a file called memory.x in your project root:
MEMORY
{
/* STM32F446RET6: 512KB Flash, 128KB RAM */
FLASH : ORIGIN = 0x08000000, LENGTH = 512K
RAM : ORIGIN = 0x20000000, LENGTH = 128K
}
2️⃣ .cargo/config.toml (Runner + Linker)
Create a folder named .cargo and inside it, a file config.toml:
[target.thumbv7em-none-eabihf]
runner = "probe-rs run --chip STM32F446RETx"
rustflags = [
"-C", "link-arg=-Tlink.x",
]
[build]
target = "thumbv7em-none-eabihf"Connect the Nucleo via USB, then:
cargo run❌ No loadable segments were found in the ELF file
Fix: Ensure .cargo/config.toml contains:
rustflags = ["-C", "link-arg=-Tlink.x"]Then run
cargo clean
cargo run