Skip to main content

Crate stm32f1_hal

Crate stm32f1_hal 

Source
Expand description

§stm32f1-hal

CI Crates.io Docs.rs License Downloads

stm32f1-hal is a Rust Hardware Abstraction Layer (HAL) for STM32F1 microcontrollers (All F1 series devices). It provides a clear, idiomatic interface for embedded development on STM32F1.

  • It implements selected embedded-hal traits.
  • It uses the os-trait crate, which makes it easy to integrate with different RTOSes.
  • It works with stable Rust.

§🎯 Motivation

Existing crates didn’t fully meet my needs:

  • stm32f1xx-hal’s design didn’t align with my workflow.
  • stm32-hal lacks support for the STM32F1 series.
  • Embassy and RTIC are async frameworks, but I need a blocking one.

To address this gap, I created stm32f1-hal. While parts of the implementation are adapted from stm32f1xx-hal, the focus here is on clarity, readability, and usability.

§📖 Design Philosophy

  • Readability is the most important. We only write code a few times, but we read it countless times. Clear understanding is essential for long-term maintenance.

    • Prefer sync-code over complex macros In complex modules, combining macros with generics and calling a lot of low level interfaces often makes the code harder to follow and maintain. Instead, I use sync-code to synchronizes code blocks across peripherals, keeping peripheral code easy to read and maintain.

    • A script is used to generate code for GPIO alternate function remapping.

  • Concise is not equal to simple. Fewer lines of code do not necessarily mean easier to read or understand.

    • The initialization code is not hidden. This makes the main function more verbose, but everything that’s happening is clearly visible.
    • Static variables are kept to a minimum in the library.

§📦 Usage

cargo add stm32f1-hal
ⓘ
use stm32f1_hal::{self as hal, pac, cortex_m_rt::entry, prelude::*};

#[entry]
fn main() -> ! {
    let dp = pac::Peripherals::take().unwrap();
    let mut flash = dp.FLASH.init();

    let cfg = rcc::Config::default();
    let mut rcc = dp.RCC.init().freeze(cfg, &mut flash.acr);
    let mut gpioa = dp.GPIOA.split(&mut rcc);

    let mut led = gpioa.pa5.into_push_pull_output(&mut gpioa.crl);

    loop {
        led.set_high();
        // delay...
        led.set_low();
        // delay...
    }
}

§Examples

For a more complete example, see example. And stm32f1-FreeRTOS-example shows how to use this crate with FreeRTOS together.

§🗺 Roadmap

This project is still in its early stages, with only a few features implemented so far. Contributions and feedback are welcome to help expand support for more peripherals and features.

  • GPIO (tested)
  • EXTI (tested)
  • UART + poll mode (tested)
  • UART + interrupt (stress tested)
  • UART + DMA (stress tested)
  • I2C + interrupt (tested)
  • SPI + interrupt (tested)
  • DMA
  • PWM output
  • DAC
  • ADC
  • More features

§🛠 Contributing

  • Submit PRs with documents, improvements or new peripheral support.
  • Open issues for bugs or feature requests.

§🔖 Keywords

stm32 · stm32f1 · rust · embedded-hal · hal · microcontroller · embedded development

Re-exports§

pub use mcu::Mcu;
pub use common::ringbuf;
pub use cortex_m;
pub use cortex_m_rt;
pub use critical_section;
pub use fugit;
pub use os_trait;
pub use embedded_hal;
pub use embedded_io;
pub use nb;

Modules§

afio
Alternate Function I/Os
backup_domain
Registers that are not reset as long as Vbat or Vdd has power.
bb
Bit banding
common
dma
Direct Memory Access
flash
Flash memory
gpio
General Purpose I/Os
i2c
interrupt
mcu
nvic_scb
pac
Peripheral access API for STM32F103 microcontrollers (generated using svd2rust v0.36.1 (4052ce6 2025-04-04))
prelude
raw_os
rcc
Reset & Control Clock
spi
time
Time units
timer
uart

Macros§

interrupt_handler

Traits§

Steal