Compare commits

..

1 Commits

Author SHA1 Message Date
Daniel Egger 70eceec773 Alternate implementation of PWM 4 years ago
  1. 8
      .github/bors.toml
  2. 33
      .github/workflows/ci.yml
  3. 21
      .github/workflows/clippy.yml
  4. 23
      .github/workflows/rustfmt.yml
  5. 21
      .travis.yml
  6. 172
      CHANGELOG.md
  7. 81
      Cargo.toml
  8. 101
      README.md
  9. 89
      examples/adc_values.rs
  10. 24
      examples/blinky.rs
  11. 55
      examples/blinky_adc.rs
  12. 27
      examples/blinky_delay.rs
  13. 42
      examples/blinky_multiple.rs
  14. 31
      examples/blinky_timer.rs
  15. 98
      examples/blinky_timer_irq.rs
  16. 61
      examples/dac.rs
  17. 85
      examples/flash_systick.rs
  18. 96
      examples/flash_systick_fancier.rs
  19. 48
      examples/i2c_find_address.rs
  20. 92
      examples/led_hal_button_irq.rs
  21. 35
      examples/serial_echo.rs
  22. 70
      examples/serial_spi_bridge.rs
  23. 121
      examples/serial_stopwatch.rs
  24. 34
      examples/spi_hal_apa102c.rs
  25. 93
      examples/usb_serial.rs
  26. 38
      examples/watchdog.rs
  27. 438
      src/adc.rs
  28. 175
      src/dac.rs
  29. 76
      src/delay.rs
  30. 1004
      src/gpio.rs
  31. 296
      src/i2c.rs
  32. 76
      src/lib.rs
  33. 6
      src/prelude.rs
  34. 233
      src/pwm.rs
  35. 558
      src/rcc.rs
  36. 522
      src/serial.rs
  37. 486
      src/spi.rs
  38. 110
      src/timers.rs
  39. 430
      src/tsc.rs
  40. 58
      src/usb.rs
  41. 12
      src/watchdog.rs
  42. 24
      tools/capture_example_bloat.sh
  43. 31
      tools/capture_nightly_example_bloat.sh
  44. 47
      tools/check.py

8
.github/bors.toml

@ -1,8 +0,0 @@
required_approvals = 1
block_labels = ["wip"]
delete_merged_branches = true
status = [
"Rustfmt",
"ci (stable)",
"ci (1.39.0, stable)",
]

33
.github/workflows/ci.yml

@ -1,33 +0,0 @@
on:
push:
branches: [ staging, trying, master ]
pull_request:
name: Continuous integration
jobs:
ci:
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- 1.39.0 # MSRV
include:
- rust: nightly
experimental: true
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
target: thumbv6m-none-eabi
override: true
- name: Regular build
run: python tools/check.py
- name: Size check
run: python tools/check.py size_check

21
.github/workflows/clippy.yml

@ -1,21 +0,0 @@
on:
push:
branches: [ staging, trying, master ]
pull_request:
name: Clippy check
jobs:
clippy_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: rustup component add clippy
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: thumbv6m-none-eabi
override: true
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --features=stm32f072 --target thumbv6m-none-eabi

23
.github/workflows/rustfmt.yml

@ -1,23 +0,0 @@
on:
push:
branches: [ staging, trying, master ]
pull_request:
name: Code formatting check
jobs:
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- run: rustup component add rustfmt
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check

21
.travis.yml

@ -0,0 +1,21 @@
language: rust
rust:
- stable
- nightly
cache: cargo
env:
- MCU=stm32f042
- MCU=stm32f030
- MCU=stm32f030x6
- MCU=stm32f030x8
- MCU=stm32f030xc
- MCU=stm32f070
- MCU=stm32f070x6
- MCU=stm32f070xb
matrix:
allow_failures:
- rust: nightly
fast_finish: true
script:
- rustup target add thumbv6m-none-eabi
- cargo build --features=$MCU --examples --release

172
CHANGELOG.md

@ -7,162 +7,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## [v0.17.1] - 2020-08-30
### Changed
- Simplify USB PA11/12 remapping for STM32F042x via `usb_bus.usb_remap()` function.
### Added
- Complete the `TscPin` trait implementation for all touch pins in the f0 family
## [v0.17.0] - 2020-06-27
### Changed
- Remove duplicate error bits clearing in serial `read()` implementation
- Optimize SPI implementation
- Use `pac` instead of `stm32` for PAC access and soft-deprecate the former
- Updated stm32f0 dependency to v0.11 (breaking change)
### Added
- Add 16bit SPI transfers
- Another example resembling a stop watch controlled via serial interface
### Fixed
- Incorrect PLLSRC bits when using HSE
## [v0.16.0] - 2020-02-02
### Added
- Another blinky example using a timer interrupt
### Changed
- Added "bypass" parameter to Rcc HSE configuration (breaking change)
- Add "usbsrc" function to Rcc configuration, used for selecting USB clock source
- For STM32F030, require use more specific feature flag, e.g. "stm32f030xc"
- Add `embedded-hal` `blocking::i2c::Read` implementation for I2C
- Added USB driver
### Fixed
- Timer: Fix use of wrong frequency when HCLK != PCLK
- RCC: Correct code to enable PLL
- RCC: Correct calculation of PLL multiplier
## [v0.15.2] - 2019-11-04
### Changed
- Re-enabled LTO
- Changed digital pin functionality to implement v2 versions
- Fixed a few deprecation warning and lints
- Enabled commented out and now available GPIOE support for 07x and 09x families
- Extract register block address only once
- Add DAC driver
## [v0.15.1] - 2019-08-11
### Fixed
- Clear UART errors in hardware after handling them
## [v0.15.0] - 2019-08-09
### Changed
- Updated stm32f0 dependency to v0.8.0 (breaking change)
- Made blinky example more universal by reducing CS
### Added
- Added fancier example moving a resource into an exception handler
## [v0.14.1] - 2019-06-06
### Added
- Support for CRS for devices with USB and HSI48
### Changed
- Clear error flags in serial read() before returning
- Revised feature flags for HSI48 clock support
## [v0.14.0] - 2019-04-25
### Changed
- Updated stm32f0 dependency to v0.7.0 (breaking change) - @jessebraham
- Bumped cortex-m dependency to ">=0.5.8,<0.7.0" to let user decide version
- Bumped cortex-m-rt dependency to v0.6.8
## [v0.13.0] - 2019-02-06
### Added
- Support for stm32f0x8 line - @jessebraham
- Support for capacitive touch sensing (TSC)
### Changed
- Updated to stm32-rs v0.6.0 - @HarkonenBade
- Updated the ADC code to use variants added in stm32-rs v0.6.0 - @HarkonenBade
- Improved serial `write_str` implementation
### Fixed
- Fixed ADC use trampling over the HSI48 clock settings
## [v0.12.0] - 2019-01-13
### Added
- Support for stm32f0x1 line - @jessebraham
- Support for HSE as a system clocksource (#25 - breaking change) - @zklapow
- Add ability to use a Tx/Rx only serial instance - @david-sawatzke
### Changed
- Optimize delay implemenation (#42) - @david-sawatzke
- Enforced more rigorous safety guarentees (#41 - Very breaking change) - @HarkonenBade
### Fixed
- Fixed panic in delay overflow handling for debug builds - @david-sawatzke
## [v0.11.1] - 2019-01-05
### Added
- Added peripheral definitions for the stm32f072xx line - @Yatekii
### Changed
- Fixed broken PC GPIO definitions with feature = "stm32f030" and feature = "stm32f070"
- More robust error handling for I2C
## [v0.11.0] - 2019-01-04
### Added
- Added ADC helper functions to read more intuitive values (#22) - @HarkonenBade
- Added interrupt enabling/disabling support to USART ports
- Added the option to have multiple Delay instances by cloning it - @david-sawatzke
### Changed
- Fixed a few clippy lints
### Removed
- Removed the free() method on the Delay provider (breaking change)
## [v0.10.1] - 2018-12-25
### Added
@ -181,7 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Reworked GPIOs and added fully erased pins
- Timer support
- Support for STM32F070 - @jessebraham
- Support for STM32F070
- Additional peripheral support for STM32F030
- Watchdog support
@ -214,19 +58,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Updated stm32f0 dependency to v0.5.0.
- Interrupt handler to new #[interrupt] attribute
[Unreleased]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.17.1...HEAD
[v0.17.1]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.17.0...v0.17.1
[v0.17.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.16.0...v0.17.0
[v0.16.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.15.2...v0.16.0
[v0.15.2]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.15.1...v0.15.2
[v0.15.1]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.15.0...v0.15.1
[v0.15.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.14.1...v0.15.0
[v0.14.1]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.14.0...v0.14.1
[v0.14.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.13.0...v0.14.0
[v0.13.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.12.0...v0.13.0
[v0.12.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.11.1...v0.12.0
[v0.11.1]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.11.0...v0.11.1
[v0.11.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.10.1...v0.11.0
[Unreleased]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.10.1...HEAD
[v0.10.1]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.10.0...v0.10.1
[v0.10.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.9.0...v0.10.0
[v0.9.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.8.0...v0.9.0

81
Cargo.toml

@ -1,10 +1,6 @@
[package]
edition = "2018"
authors = [
"Daniel Egger <daniel@eggers-club.de>",
"Thomas Bytheway <github@harkonen.net>",
"Jesse Braham <jesse@beta7.io>",
]
authors = ["Daniel Egger <daniel@eggers-club.de>"]
categories = [
"embedded",
"hardware-support",
@ -23,76 +19,51 @@ license = "0BSD"
name = "stm32f0xx-hal"
readme = "README.md"
repository = "https://github.com/stm32-rs/stm32f0xx-hal"
version = "0.17.1"
version = "0.10.1"
[package.metadata.docs.rs]
features = ["stm32f042", "rt", "stm32-usbd"]
targets = ["thumbv6m-none-eabi"]
features = ["stm32f042", "rt"]
[dependencies]
bare-metal = { version = "1.0.0" }
cast = { version = "0.2", default-features = false }
cortex-m = "0.6"
embedded-hal = { version = "0.2", features = ["unproven"] }
stm32f0 = "0.12.1"
nb = "1.0"
void = { version = "1.0", default-features = false }
stm32-usbd = { version = "0.5.1", features = ["ram_access_2x16"], optional = true }
bare-metal = { version = "0.2.4", features = ["const-fn"] }
cortex-m = "0.5.8"
cortex-m-rt = "0.6.7"
nb = "0.1.1"
void = { version = "1.0.2", default-features = false }
stm32f0 = "0.5.0"
[dependencies.cast]
default-features = false
version = "0.2.2"
[dependencies.embedded-hal]
features = ["unproven"]
version = "0.2.2"
[dev-dependencies]
cortex-m-rt = "0.6"
panic-halt = "0.2"
usb-device = "0.2.7"
usbd-serial = "0.1.1"
panic-halt = "0.2.0"
[features]
device-selected = []
rt = ["stm32f0/rt"]
stm32f030 = ["stm32f0/stm32f0x0", "device-selected"]
stm32f030x4 = ["stm32f030"]
stm32f030x6 = ["stm32f030"]
stm32f030x8 = ["stm32f030"]
stm32f030xc = ["stm32f030"]
stm32f031 = ["stm32f0/stm32f0x1", "device-selected"]
stm32f038 = ["stm32f0/stm32f0x8", "device-selected"]
stm32f042 = ["stm32f0/stm32f0x2", "device-selected"]
stm32f048 = ["stm32f0/stm32f0x8", "device-selected"]
stm32f051 = ["stm32f0/stm32f0x1", "device-selected"]
stm32f058 = ["stm32f0/stm32f0x8", "device-selected"]
stm32f030 = ["stm32f0/stm32f0x0", "device-selected"]
stm32f030x4 = ["stm32f030x6", "device-selected"]
stm32f030x6 = ["stm32f030", "device-selected"]
stm32f030x8 = ["stm32f030", "device-selected"]
stm32f030xc = ["stm32f030", "device-selected"]
stm32f070 = ["stm32f0/stm32f0x0", "device-selected"]
stm32f070x6 = ["stm32f070"]
stm32f070xb = ["stm32f070"]
stm32f071 = ["stm32f0/stm32f0x1", "device-selected"]
stm32f072 = ["stm32f0/stm32f0x2", "device-selected"]
stm32f078 = ["stm32f0/stm32f0x8", "device-selected"]
stm32f091 = ["stm32f0/stm32f0x1", "device-selected"]
stm32f098 = ["stm32f0/stm32f0x8", "device-selected"]
stm32f070x6 = ["stm32f070", "device-selected"]
stm32f070xb = ["stm32f070", "device-selected"]
[profile.dev]
debug = true
lto = true
[profile.release]
lto = true
debug = true
lto = true
opt-level = "s"
[[example]]
name = "blinky_timer_irq"
required-features = ["stm32f072", "rt"]
[[example]]
name = "serial_stopwatch"
required-features = ["stm32f072", "rt"]
[[example]]
name = "dac"
required-features = ["stm32f072"]
[[example]]
name = "led_hal_button_irq"
required-features = ["stm32f042", "rt"]
[[example]]
name = "usb_serial"
required-features = ["rt", "stm32f042", "stm32-usbd"]

101
README.md

@ -1,74 +1,41 @@
stm32f0xx-hal
=============
[![Continuous integration](https://github.com/stm32-rs/stm32f0xx-hal/workflows/Continuous%20integration/badge.svg)](https://github.com/stm32-rs/stm32f0xx-hal)
[![Crates.io](https://img.shields.io/crates/v/stm32f0xx-hal.svg)](https://crates.io/crates/stm32f0xx-hal)
[![docs.rs](https://docs.rs/stm32f0xx-hal/badge.svg)](https://docs.rs/stm32f0xx-hal/)
[_stm32f0xx-hal_](https://github.com/stm32-rs/stm32f0xx-hal) contains a hardware abstraction on top of the peripheral access API for the STMicro STM32F0xx family of microcontrollers.
This crate replaces the [stm32f042-hal](https://github.com/therealprof/stm32f042-hal) by a more ubiquitous version suitable for additional families. The idea behind this crate is to gloss over the slight differences in the various peripherals available on those MCUs so a HAL can be written for all chips in that same family without having to cut and paste crates for every single model.
This crate relies on Adam Greig's fantastic [stm32f0](https://crates.io/crates/stm32f0) crate to provide appropriate register definitions, and implements a partial set of the [embedded-hal](https://github.com/rust-embedded/embedded-hal) traits. Some of the implementation was shamelessly adapted from the [stm32f103xx-hal](https://github.com/japaric/stm32f103xx-hal) crate by Jorge Aparicio.
Collaboration on this crate is highly welcome, as are pull requests!
Supported Configurations
------------------------
* __stm32f030__ (stm32f030x4, stm32f030x6, stm32f030x8, stm32f030xc)
* __stm32f031__
* __stm32f038__
* __stm32f042__
* __stm32f048__
* __stm32f051__
* __stm32f058__
* __stm32f070__ (stm32f070x6, stm32f070xb)
* __stm32f071__
* __stm32f072__
* __stm32f078__
* __stm32f091__
* __stm32f098__
Getting Started
---------------
The `examples` folder contains several example programs. To compile them, one must specify the target device as cargo feature:
```
$ cargo build --features=stm32f030
```
To use stm32f0xx-hal as a dependency in a standalone project the target device feature must be specified in the `Cargo.toml` file:
```
[dependencies]
cortex-m = "0.6.0"
cortex-m-rt = "0.6.8"
stm32f0xx-hal = {version = "0.16", features = ["stm32f030"]}
```
If you are unfamiliar with embedded development using Rust, there are a number of fantastic resources available to help.
- [Embedded Rust Documentation](https://docs.rust-embedded.org/)
- [The Embedded Rust Book](https://docs.rust-embedded.org/book/)
- [Rust Embedded FAQ](https://docs.rust-embedded.org/faq.html)
- [rust-embedded/awesome-embedded-rust](https://github.com/rust-embedded/awesome-embedded-rust)
Minimum supported Rust version
------------------------------
The minimum supported Rust version at the moment is **1.39.0**. Older versions
**may** compile, especially when some features are not used in your
application.
Changelog
---------
See [CHANGELOG.md](CHANGELOG.md).
_stm32f0xx-hal_ contains a hardware abstraction on top of the peripheral access
API for the STMicro STM32F0xx family of microcontrollers. It replaces the
[stm32f042-hal][] by a more ubiqitous version suitable for additional families.
Currently supported configuration are:
* stm32f030
* stm32f030x4
* stm32f030x6
* stm32f030x8
* stm32f030xc
* stm32f042
* stm32f070
* stm32f070x6
* stm32f070xb
The idea behind this crate is to gloss over the slight differences in the
various peripherals available on those MCUs so a HAL can be written for all
chips in that same family without having to cut and paste crates for every
single model.
Collaboration on this crate is highly welcome as are pull requests!
This crate relies on Adam Greigs fantastic [stm32f0][] crate to provide
appropriate register definitions and implements a partial set of the
[embedded-hal][] traits.
Some of the implementation was shamelessly adapted from the [stm32f103xx-hal][]
crate by Jorge Aparicio.
[stm32f0]: https://crates.io/crates/stm32f0
[stm32f042-hal]: https://github.com/therealprof/stm32f042-hal
[stm32f103xx-hal]: https://github.com/japaric/stm32f103xx-hal
[embedded-hal]: https://github.com/japaric/embedded-hal.git
License
-------
0-Clause BSD License, see [LICENSE-0BSD.txt](LICENSE-0BSD.txt) for more details.
[0-clause BSD license](LICENSE-0BSD.txt).

89
examples/adc_values.rs

@ -1,89 +0,0 @@
#![no_main]
#![no_std]
use panic_halt as _;
use stm32f0xx_hal as hal;
use crate::hal::{pac, prelude::*};
use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource::Core};
use cortex_m_rt::{entry, exception};
use core::{cell::RefCell, fmt::Write};
struct Shared {
adc: hal::adc::Adc,
tx: hal::serial::Tx<pac::USART1>,
}
static SHARED: Mutex<RefCell<Option<Shared>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
if let (Some(p), Some(cp)) = (
hal::pac::Peripherals::take(),
cortex_m::peripheral::Peripherals::take(),
) {
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash);
let gpioa = p.GPIOA.split(&mut rcc);
let mut syst = cp.SYST;
// Set source for SysTick counter, here full operating frequency (== 8MHz)
syst.set_clock_source(Core);
// Set reload value, i.e. timer delay 8 MHz/counts
syst.set_reload(8_000_000 - 1);
// Start SysTick counter
syst.enable_counter();
// Start SysTick interrupt generation
syst.enable_interrupt();
// USART1 at PA9 (TX) and PA10(RX)
let tx = gpioa.pa9.into_alternate_af1(cs);
let rx = gpioa.pa10.into_alternate_af1(cs);
// Initialiase UART
let (mut tx, _) =
hal::serial::Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc).split();
// Initialise ADC
let adc = hal::adc::Adc::new(p.ADC, &mut rcc);
// Output a friendly greeting
tx.write_str("\n\rThis ADC example will read various values using the ADC and print them out to the serial terminal\r\n").ok();
// Move all components under Mutex supervision
*SHARED.borrow(cs).borrow_mut() = Some(Shared { adc, tx });
});
}
loop {
continue;
}
}
#[exception]
fn SysTick() {
use core::ops::DerefMut;
// Enter critical section
cortex_m::interrupt::free(|cs| {
// Get access to the Mutex protected shared data
if let Some(ref mut shared) = SHARED.borrow(cs).borrow_mut().deref_mut() {
// Read temperature data from internal sensor using ADC
let t = hal::adc::VTemp::read(&mut shared.adc, None);
writeln!(shared.tx, "Temperature {}.{}C\r", t / 100, t % 100).ok();
// Read volatage reference data from internal sensor using ADC
let t = hal::adc::VRef::read_vdda(&mut shared.adc);
writeln!(shared.tx, "Vdda {}mV\r", t).ok();
}
});
}

24
examples/blinky.rs

@ -1,32 +1,32 @@
#![no_main]
#![no_std]
use panic_halt as _;
#[allow(unused)]
use panic_halt;
use stm32f0xx_hal as hal;
use crate::hal::{pac, prelude::*};
use crate::hal::prelude::*;
use crate::hal::stm32;
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let Some(mut p) = pac::Peripherals::take() {
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut p.FLASH);
if let Some(p) = stm32::Peripherals::take() {
let gpioa = p.GPIOA.split();
let gpioa = p.GPIOA.split(&mut rcc);
// (Re-)configure PA1 as output
let mut led = cortex_m::interrupt::free(|cs| gpioa.pa1.into_push_pull_output(cs));
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output();
loop {
// Turn PA1 on a million times in a row
/* Turn PA1 on a million times in a row */
for _ in 0..1_000_000 {
led.set_high().ok();
led.set_high();
}
// Then turn PA1 off a million times in a row
/* Then turn PA1 off a million times in a row */
for _ in 0..1_000_000 {
led.set_low().ok();
led.set_low();
}
}
}

55
examples/blinky_adc.rs

@ -1,47 +1,50 @@
#![no_main]
#![no_std]
use panic_halt as _;
#[allow(unused_imports)]
use panic_halt;
use stm32f0xx_hal as hal;
use crate::hal::{adc::Adc, delay::Delay, pac, prelude::*};
use crate::hal::delay::Delay;
use crate::hal::prelude::*;
use crate::hal::stm32;
use crate::hal::adc::Adc;
use cortex_m::peripheral::Peripherals;
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (pac::Peripherals::take(), Peripherals::take()) {
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut p.FLASH);
if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) {
let gpioa = p.GPIOA.split();
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output();
/* (Re-)configure PA0 as analog in */
let mut an_in = gpioa.pa0.into_analog();
let gpioa = p.GPIOA.split(&mut rcc);
/* Constrain clocking registers */
let rcc = p.RCC.constrain();
let (mut led, mut an_in) = cortex_m::interrupt::free(move |cs| {
(
// (Re-)configure PA1 as output
gpioa.pa1.into_push_pull_output(cs),
// (Re-)configure PA0 as analog input
gpioa.pa0.into_analog(cs),
)
});
/* Configure clock to 8 MHz (i.e. the default) and freeze it */
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
// Get delay provider
let mut delay = Delay::new(cp.SYST, &rcc);
/* Get delay provider */
let mut delay = Delay::new(cp.SYST, clocks);
// Get access to the ADC
let mut adc = Adc::new(p.ADC, &mut rcc);
let mut adc = Adc::new(p.ADC);
loop {
led.toggle().ok();
let time: u16 = if let Ok(val) = adc.read(&mut an_in) as Result<u16, _> {
/* shift the value right by 3, same as divide by 8, reduces
the 0-4095 range into something approximating 1-512 */
(val >> 3) + 1
} else {
1000
};
led.toggle();
let val: u16 = adc.read(&mut an_in).unwrap();
/* shift the value right by 3, same as divide by 8, reduces
the 0-4095 range into something approximating 1-512 */
let time: u16 = (val >> 3) + 1;
delay.delay_ms(time);
}

27
examples/blinky_delay.rs

@ -1,30 +1,37 @@
#![no_main]
#![no_std]
use panic_halt as _;
#[allow(unused)]
use panic_halt;
use stm32f0xx_hal as hal;
use crate::hal::{delay::Delay, pac, prelude::*};
use crate::hal::delay::Delay;
use crate::hal::prelude::*;
use crate::hal::stm32;
use cortex_m::peripheral::Peripherals;
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (pac::Peripherals::take(), Peripherals::take()) {
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut p.FLASH);
if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) {
let gpioa = p.GPIOA.split();
let gpioa = p.GPIOA.split(&mut rcc);
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output();
// (Re-)configure PA1 as output
let mut led = cortex_m::interrupt::free(move |cs| gpioa.pa1.into_push_pull_output(cs));
/* Constrain clocking registers */
let rcc = p.RCC.constrain();
// Get delay provider
let mut delay = Delay::new(cp.SYST, &rcc);
/* Configure clock to 8 MHz (i.e. the default) and freeze it */
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
/* Get delay provider */
let mut delay = Delay::new(cp.SYST, clocks);
loop {
led.toggle().ok();
led.toggle();
delay.delay_ms(1_000_u16);
}
}

42
examples/blinky_multiple.rs

@ -1,45 +1,49 @@
#![no_main]
#![no_std]
use panic_halt as _;
#[allow(unused)]
use panic_halt;
use stm32f0xx_hal as hal;
use crate::hal::{delay::Delay, pac, prelude::*};
use crate::hal::delay::Delay;
use crate::hal::prelude::*;
use crate::hal::stm32;
use cortex_m::peripheral::Peripherals;
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (pac::Peripherals::take(), Peripherals::take()) {
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut p.FLASH);
if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) {
let gpioa = p.GPIOA.split();
let gpiob = p.GPIOB.split();
let gpioa = p.GPIOA.split(&mut rcc);
let gpiob = p.GPIOB.split(&mut rcc);
/* (Re-)configure PA1 as output */
let led1 = gpioa.pa1.into_push_pull_output();
let (led1, led2) = cortex_m::interrupt::free(move |cs| {
(
// (Re-)configure PA1 as output
gpioa.pa1.into_push_pull_output(cs),
// (Re-)configure PB1 as output
gpiob.pb1.into_push_pull_output(cs),
)
});
/* (Re-)configure PB1 as output */
let led2 = gpiob.pb1.into_push_pull_output();
// Get delay provider
let mut delay = Delay::new(cp.SYST, &rcc);
/* Constrain clocking registers */
let rcc = p.RCC.constrain();
// Store them together after erasing the type
/* Configure clock to 8 MHz (i.e. the default) and freeze it */
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
/* Get delay provider */
let mut delay = Delay::new(cp.SYST, clocks);
/* Store them together */
let mut leds = [led1.downgrade(), led2.downgrade()];
loop {
for l in &mut leds {
l.set_high().ok();
l.set_high();
}
delay.delay_ms(1_000_u16);
for l in &mut leds {
l.set_low().ok();
l.set_low();
}
delay.delay_ms(1_000_u16);
}

31
examples/blinky_timer.rs

@ -1,32 +1,37 @@
#![no_main]
#![no_std]
use panic_halt as _;
#[allow(unused)]
use panic_halt;
use stm32f0xx_hal as hal;
use crate::hal::{pac, prelude::*, time::Hertz, timers::*};
use crate::hal::prelude::*;
use crate::hal::stm32;
use crate::hal::time::*;
use crate::hal::timers::*;
use cortex_m_rt::entry;
use nb::block;
#[entry]
fn main() -> ! {
if let Some(mut p) = pac::Peripherals::take() {
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut p.FLASH);
if let Some(p) = stm32::Peripherals::take() {
let gpioa = p.GPIOA.split();
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output();
let gpioa = p.GPIOA.split(&mut rcc);
/* Constrain clocking registers */
let rcc = p.RCC.constrain();
// (Re-)configure PA1 as output
let mut led = cortex_m::interrupt::free(move |cs| gpioa.pa1.into_push_pull_output(cs));
/* Configure clock to 8 MHz (i.e. the default) and freeze it */
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
// Set up a timer expiring after 1s
let mut timer = Timer::tim1(p.TIM1, Hertz(1), &mut rcc);
let mut timer = Timer::tim1(p.TIM1, Hertz(1), clocks);
loop {
led.toggle().ok();
// Wait for the timer to expire
nb::block!(timer.wait()).ok();
led.toggle();
block!(timer.wait()).ok();
}
}

98
examples/blinky_timer_irq.rs

@ -1,98 +0,0 @@
#![no_main]
#![no_std]
use panic_halt as _;
use stm32f0xx_hal as hal;
use crate::hal::{
gpio::*,
pac::{interrupt, Interrupt, Peripherals, TIM7},
prelude::*,
time::Hertz,
timers::*,
};
use cortex_m_rt::entry;
use core::cell::RefCell;
use cortex_m::{interrupt::Mutex, peripheral::Peripherals as c_m_Peripherals};
// A type definition for the GPIO pin to be used for our LED
type LEDPIN = gpioa::PA5<Output<PushPull>>;
// Make LED pin globally available
static GLED: Mutex<RefCell<Option<LEDPIN>>> = Mutex::new(RefCell::new(None));
// Make timer interrupt registers globally available
static GINT: Mutex<RefCell<Option<Timer<TIM7>>>> = Mutex::new(RefCell::new(None));
// Define an interupt handler, i.e. function to call when interrupt occurs. Here if our external
// interrupt trips when the timer timed out
#[interrupt]
fn TIM7() {
static mut LED: Option<LEDPIN> = None;
static mut INT: Option<Timer<TIM7>> = None;
let led = LED.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {
// Move LED pin here, leaving a None in its place
GLED.borrow(cs).replace(None).unwrap()
})
});
let int = INT.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {
// Move LED pin here, leaving a None in its place
GINT.borrow(cs).replace(None).unwrap()
})
});
led.toggle().ok();
int.wait().ok();
}
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
cortex_m::interrupt::free(move |cs| {
let mut rcc = p
.RCC
.configure()
.hsi48()
.enable_crs(p.CRS)
.sysclk(48.mhz())
.pclk(24.mhz())
.freeze(&mut p.FLASH);
let gpioa = p.GPIOA.split(&mut rcc);
// (Re-)configure PA5 as output
let led = gpioa.pa5.into_push_pull_output(cs);
// Move the pin into our global storage
*GLED.borrow(cs).borrow_mut() = Some(led);
// Set up a timer expiring after 1s
let mut timer = Timer::tim7(p.TIM7, Hertz(1), &mut rcc);
// Generate an interrupt when the timer expires
timer.listen(Event::TimeOut);
// Move the timer into our global storage
*GINT.borrow(cs).borrow_mut() = Some(timer);
// Enable TIM7 IRQ, set prio 1 and clear any pending IRQs
let mut nvic = cp.NVIC;
unsafe {
nvic.set_priority(Interrupt::TIM7, 1);
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM7);
}
cortex_m::peripheral::NVIC::unpend(Interrupt::TIM7);
});
}
loop {
continue;
}
}

61
examples/dac.rs

@ -1,61 +0,0 @@
#![deny(unused_imports)]
#![no_main]
#![no_std]
use cortex_m;
use cortex_m_rt as rt;
use panic_halt as _;
use stm32f0xx_hal as hal;
use crate::hal::dac::*;
use crate::hal::pac;
use crate::hal::prelude::*;
use rt::entry;
enum Direction {
Upcounting,
Downcounting,
}
#[entry]
fn main() -> ! {
if let (Some(mut dp), Some(_cp)) = (pac::Peripherals::take(), cortex_m::Peripherals::take()) {
let mut rcc = dp.RCC.configure().sysclk(8.mhz()).freeze(&mut dp.FLASH);
let gpioa = dp.GPIOA.split(&mut rcc);
let pa4 = cortex_m::interrupt::free(move |cs| gpioa.pa4.into_analog(cs));
let mut dac = dac(dp.DAC, pa4, &mut rcc);
dac.enable();
let mut dir = Direction::Upcounting;
let mut val = 0;
dac.set_value(2058);
cortex_m::asm::bkpt();
dac.set_value(4095);
cortex_m::asm::bkpt();
loop {
dac.set_value(val);
match val {
0 => dir = Direction::Upcounting,
4095 => dir = Direction::Downcounting,
_ => (),
};
match dir {
Direction::Upcounting => val += 1,
Direction::Downcounting => val -= 1,
}
}
}
loop {
continue;
}
}

85
examples/flash_systick.rs

@ -1,52 +1,54 @@
#![no_main]
#![no_std]
use panic_halt as _;
#[allow(unused)]
use panic_halt;
use stm32f0xx_hal as hal;
use crate::hal::{gpio::*, pac, prelude::*};
use crate::hal::gpio::*;
use crate::hal::prelude::*;
use crate::hal::stm32;
use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource::Core, Peripherals};
use cortex_m::interrupt::Mutex;
use cortex_m::peripheral::syst::SystClkSource::Core;
use cortex_m::peripheral::Peripherals;
use cortex_m_rt::{entry, exception};
use core::cell::RefCell;
use core::ops::DerefMut;
// Mutex protected structure for our shared GPIO pin
static GPIO: Mutex<RefCell<Option<gpioa::PA1<Output<PushPull>>>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (pac::Peripherals::take(), Peripherals::take()) {
cortex_m::interrupt::free(move |cs| {
let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut p.FLASH);
let gpioa = p.GPIOA.split(&mut rcc);
if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) {
let gpioa = p.GPIOA.split();
let rcc = p.RCC.constrain();
let _ = rcc.cfgr.sysclk(48.mhz()).freeze();
let mut syst = cp.SYST;
// (Re-)configure PA1 as output
let led = gpioa.pa1.into_push_pull_output(cs);
/* (Re-)configure PA1 as output */
let led = gpioa.pa1.into_push_pull_output();
// Transfer GPIO into a shared structure
cortex_m::interrupt::free(move |cs| {
*GPIO.borrow(cs).borrow_mut() = Some(led);
});
let mut syst = cp.SYST;
// Initialise SysTick counter with a defined value
unsafe { syst.cvr.write(1) };
/* Initialise SysTick counter with a defined value */
unsafe { syst.cvr.write(1) };
// Set source for SysTick counter, here full operating frequency (== 48MHz)
syst.set_clock_source(Core);
/* Set source for SysTick counter, here full operating frequency (== 8MHz) */
syst.set_clock_source(Core);
// Set reload value, i.e. timer delay 48 MHz/4 Mcounts == 12Hz or 83ms
syst.set_reload(4_000_000 - 1);
/* Set reload value, i.e. timer delay 48 MHz/4 Mcounts == 12Hz or 83ms */
syst.set_reload(4_000_000 - 1);
// Start counting
syst.enable_counter();
/* Start counter */
syst.enable_counter();
// Enable interrupt generation
syst.enable_interrupt();
});
/* Start interrupt generation */
syst.enable_interrupt();
}
loop {
@ -54,30 +56,29 @@ fn main() -> ! {
}
}
// Define an exception handler, i.e. function to call when exception occurs. Here, if our SysTick
// timer generates an exception the following handler will be called
/* Define an exception, i.e. function to call when exception occurs. Here if our SysTick timer
* trips the flash function will be called and the specified stated passed in via argument */
//, flash, state: u8 = 1);
#[exception]
fn SysTick() {
// Exception handler state variable
static mut STATE: u8 = 1;
fn SysTick() -> ! {
static mut state: u8 = 1;
// Enter critical section
/* Enter critical section */
cortex_m::interrupt::free(|cs| {
// Borrow access to our GPIO pin from the shared structure
if let Some(ref mut led) = *GPIO.borrow(cs).borrow_mut().deref_mut() {
// Check state variable, keep LED off most of the time and turn it on every 10th tick
if *STATE < 10 {
// Turn off the LED
led.set_low().ok();
/* Check state variable, keep LED off most of the time and turn it on every 10th tick */
if *state < 10 {
/* If set turn off the LED */
led.set_low();
// And now increment state variable
*STATE += 1;
/* And now increment state variable */
*state += 1;
} else {
// Turn on the LED
led.set_high().ok();
/* If not set, turn on the LED */
led.set_high();
// And set new state variable back to 0
*STATE = 0;
/* And set new state variable back to 0 */
*state = 0;
}
}
});

96
examples/flash_systick_fancier.rs

@ -1,96 +0,0 @@
#![no_main]
#![no_std]
use panic_halt as _;
use stm32f0xx_hal as hal;
use crate::hal::{gpio::*, pac, prelude::*};
use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource::Core, Peripherals};
use cortex_m_rt::{entry, exception};
use core::cell::RefCell;
use core::mem::swap;
// A type definition for the GPIO pin to be used for our LED
type LEDPIN = gpiob::PB3<Output<PushPull>>;
// Mutex protected structure for our shared GPIO pin
static GPIO: Mutex<RefCell<Option<LEDPIN>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (pac::Peripherals::take(), Peripherals::take()) {
cortex_m::interrupt::free(move |cs| {
let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut p.FLASH);
// Get access to individual pins in the GPIO port
let gpioa = p.GPIOB.split(&mut rcc);
// (Re-)configure the pin connected to our LED as output
let led = gpioa.pb3.into_push_pull_output(cs);
// Transfer GPIO into a shared structure
swap(&mut Some(led), &mut GPIO.borrow(cs).borrow_mut());
let mut syst = cp.SYST;
// Initialise SysTick counter with a defined value
unsafe { syst.cvr.write(1) };
// Set source for SysTick counter, here full operating frequency (== 48MHz)
syst.set_clock_source(Core);
// Set reload value, i.e. timer delay 48 MHz/4 Mcounts == 12Hz or 83ms
syst.set_reload(4_000_000 - 1);
// Start counting
syst.enable_counter();
// Enable interrupt generation
syst.enable_interrupt();
});
}
loop {
continue;
}
}
// Define an exception handler, i.e. function to call when exception occurs. Here, if our SysTick
// timer generates an exception the following handler will be called
#[exception]
fn SysTick() {
// Our moved LED pin
static mut LED: Option<LEDPIN> = None;
// Exception handler state variable
static mut STATE: u8 = 1;
// If LED pin was moved into the exception handler, just use it
if let Some(led) = LED {
// Check state variable, keep LED off most of the time and turn it on every 10th tick
if *STATE < 10 {
// Turn off the LED
led.set_low().ok();
// And now increment state variable
*STATE += 1;
} else {
// Turn on the LED
led.set_high().ok();
// And set new state variable back to 0
*STATE = 0;
}
}
// Otherwise move it out of the Mutex protected shared region into our exception handler
else {
// Enter critical section
cortex_m::interrupt::free(|cs| {
// Swap globally stored data with SysTick private data
swap(LED, &mut GPIO.borrow(cs).borrow_mut());
});
}
}

48
examples/i2c_find_address.rs

@ -1,48 +0,0 @@
#![no_main]
#![no_std]
use panic_halt as _;
use stm32f0xx_hal as hal;
use crate::hal::{i2c::I2c, pac, prelude::*};
use cortex_m_rt::entry;
/* Example meant for stm32f030xc MCUs with i2c devices connected on PB7 and PB8 */
#[entry]
fn main() -> ! {
if let Some(p) = pac::Peripherals::take() {
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().freeze(&mut flash);
let gpiob = p.GPIOB.split(&mut rcc);
// Configure pins for I2C
let sda = gpiob.pb7.into_alternate_af1(cs);
let scl = gpiob.pb8.into_alternate_af1(cs);
// Configure I2C with 100kHz rate
let mut i2c = I2c::i2c1(p.I2C1, (scl, sda), 100.khz(), &mut rcc);
let mut _devices = 0;
// I2C addresses are 7-bit wide, covering the 0-127 range