Reference Patterns

This chapter is a quick-reference you will come back to again and again. It collects the target triples, feature flags, pin mappings, and debugging checklists that save you from searching through documentation at 2am.

Target Triples

Every ARM Cortex-M core has a specific Rust compilation target. Using the wrong one means your binary will not run — or worse, will run with subtle bugs.

Target TripleCoreFPUUsed By
thumbv6m-none-eabiCortex-M0, M0+NoF0, G0, L0
thumbv7m-none-eabiCortex-M3NoF1, F2, L1
thumbv7em-none-eabiCortex-M4 (no FPU)NoL4 (some), G4 (if FPU unused)
thumbv7em-none-eabihfCortex-M4, M7YesF3, F4, F7, H7, G4, L4+
thumbv8m.main-none-eabihfCortex-M33YesH5, U5, L5

The hf suffix means "hardware float." If your chip has an FPU (most F4, F7, H7, G4 do), always use the hf target. Using the non-hf target on an FPU-equipped chip works but wastes the hardware floating point unit — all float math gets done in software, roughly 10-50x slower.

Think About It: The target triple encodes the instruction set, not the chip model. An STM32F407 and an STM32F411 use the same target (thumbv7em-none-eabihf) because they both have Cortex-M4F cores. An STM32G071 uses a different target (thumbv6m-none-eabi) because it has a Cortex-M0+ core.

Embassy Chip Feature Flags

Embassy uses Cargo feature flags to select the exact chip model. The feature name matches the chip part number in lowercase. Here are the most common ones:

Board / ChipEmbassy FeatureTargetNotes
Blue Pill (F103C8)stm32f103c8thumbv7m-none-eabiClassic learning board
Black Pill (F411CE)stm32f411cethumbv7em-none-eabihfGreat value, USB OTG
STM32F407 Discoverystm32f407vgthumbv7em-none-eabihf4 LEDs, audio codec
Nucleo-G071RBstm32g071rbthumbv6m-none-eabiBudget, lots of peripherals
Nucleo-H743ZIstm32h743vithumbv7em-none-eabihf480MHz, complex memory
Nucleo-U575ZIstm32u575zithumbv8m.main-none-eabihfUltra-low-power
Nucleo-H563ZIstm32h563zithumbv8m.main-none-eabihfH5 mainstream
WeAct STM32G431stm32g431cbthumbv7em-none-eabihfMotor control, USB-C
# In Cargo.toml — change only this feature to switch chips
[dependencies.embassy-stm32]
version = "0.2"
features = ["stm32f411ce", "time-driver-any", "memory-x"]

Common LED Pins by Board

When you are trying to blink an LED and nothing happens, the first question is: which pin is the LED on?

BoardLED PinActiveColor
Blue Pill (F103)PC13LowGreen
Black Pill (F411)PC13LowBlue
STM32F407 DiscoveryPD12, PD13, PD14, PD15HighGreen, Orange, Red, Blue
Nucleo-64 (most)PA5HighGreen
Nucleo-144 (most)PB0, PB7, PB14HighGreen, Blue, Red
WeAct H743PE3LowBlue

Fun Fact: The "active low" LED convention (PC13 on Blue/Black Pill) means you set the pin LOW to turn the LED ON. This is because the LED is wired between VCC and the GPIO pin. When the pin is low, current flows through the LED. When the pin is high, both sides are at the same voltage and no current flows.

Debug Checklist

When something does not work, walk through this checklist in order. Each item is listed roughly by how often it causes problems:

Power and Hardware

  • Power connected? Check 3.3V rail with a multimeter. Should be 3.2V–3.4V.
  • Debugger connected? ST-Link or J-Link wired to SWDIO, SWCLK, GND. Is the debugger LED solid?
  • Correct chip selected? The Embassy feature flag must match your physical chip exactly.
  • Reset pin? Some boards need NRST connected or have a reset button you need to press.

Basic Firmware

  • LED blinks? Before debugging any peripheral, confirm the chip is running code at all.
  • defmt logs appearing? If not, check that defmt-rtt is in your dependencies and probe-rs is configured correctly.
  • Clock configuration correct? Wrong PLL settings can make the chip run at the wrong speed or not run at all. Start with the default clock (HSI) to confirm basic operation.

GPIO and Pins

  • Correct pin for this function? Check the datasheet's alternate function mapping.
  • Correct alternate function number? PA9 might be USART1_TX on AF7 but SPI1_SCK on AF5. Getting the AF wrong means the peripheral is not connected to the pin.
  • Pin mode correct? Push-pull vs open-drain, pull-up vs pull-down.

Communication Peripherals

  • SPI: CS pin toggling? Scope it. If CS is stuck high, the slave ignores everything.
  • SPI: Clock polarity and phase? CPOL and CPHA must match the slave device's requirements.
  • I2C: Pull-up resistors present? I2C requires external 4.7k pull-ups to 3.3V on SDA and SCL. Without them, the bus stays low.
  • I2C: Correct address? Some datasheets give 8-bit addresses, Rust expects 7-bit. Divide by 2 if needed.
  • UART: TX and RX swapped? The most common UART mistake. Your TX connects to their RX and vice versa.
  • UART: Baud rate match? Both sides must agree on the baud rate exactly.

STM32H7 Specific

  • DMA buffer in correct memory region? Must be in SRAM1/2/3, NOT in DTCM or AXI SRAM.
  • Cache coherency? If using AXI SRAM with DMA, cache invalidation or clean operations are required.
  • Power supply configuration? H7 has SMPS and LDO options. Wrong power configuration prevents boot.

System Level

  • Watchdog timeout too short? If the watchdog fires during initialization, the chip resets in a loop.
  • Stack overflow? Large local arrays can overflow the stack. Use static for big buffers. Enable the paint feature in cortex-m-rt to detect stack overflows.
  • Flash full? cargo size shows your binary size. If it exceeds your chip's Flash, linking fails with an obscure error.

Common Error Messages and Fixes

Error MessageLikely CauseFix
Error: connecting to the chip was unsuccessfulDebugger wiring, chip not powered, wrong chip in probe-rs configCheck wiring, power, and probe-rs chip setting
SP is not 8-byte alignedCorrupt vector table or wrong memory.xVerify FLASH and RAM origins in memory.x
292 or HardFaultNull pointer, stack overflow, or invalid memory accessEnable defmt panic handler, check stack size, review unsafe blocks
292 292 292 292 292 292 (defmt gibberish)defmt version mismatch between crate and probe-rsRun cargo update and update probe-rs
292 292 then silencePanic during initializationSimplify init code, add defmt::info at each step to find where it stops
error[E0292]: stm32f411ce not foundWrong feature flag or embassy versionCheck embassy-stm32 version supports your chip
292292 292292 292292 292292 (repeating)Watchdog reset loopIncrease watchdog timeout or pet it earlier in init
292292292292...292292292 (continuous)Boot loop from brownoutCheck power supply voltage and decoupling capacitors

Think About It: Most embedded debugging follows a pattern: confirm the obvious first (power, wiring, chip selection), then narrow down to the specific subsystem. Resist the urge to change code before confirming the hardware is correct.

Quick Pin Reference Template

When starting a new project, fill in this table for your specific board:

Project: ____________________
Board:   ____________________
Chip:    ____________________

| Function      | Pin  | AF# | Notes           |
|---------------|------|-----|-----------------|
| SPI1_SCK      |      |     |                 |
| SPI1_MOSI     |      |     |                 |
| SPI1_MISO     |      |     |                 |
| SPI1_CS       |      |     | Manual GPIO     |
| I2C1_SCL      |      |     | 4.7k pull-up    |
| I2C1_SDA      |      |     | 4.7k pull-up    |
| USART1_TX     |      |     |                 |
| USART1_RX     |      |     |                 |
| ADC1_CH0      |      |     |                 |
| LED           |      |     | Active High/Low |
| SWD_IO        |      |     |                 |
| SWD_CLK       |      |     |                 |

Debugging with probe-rs

Quick command reference for the tools you will use most often:

# Flash and run with defmt output
cargo run --release

# Just flash without running
probe-rs download target/thumbv7em-none-eabihf/release/my-project --chip STM32F411CE

# Reset the chip
probe-rs reset --chip STM32F411CE

# List connected probes
probe-rs list

# Check what chip is connected
probe-rs info

Summary

Keep this chapter bookmarked. The target triples table, the debug checklist, and the error message reference will save you hours over the course of any embedded Rust project. When something breaks — and it will — start at the top of the checklist and work down methodically.