va108xx-rs/docs/expanded_stm32f0xx.rs
2021-11-05 11:08:51 +01:00

3895 lines
134 KiB
Rust

#![feature(prelude_import)]
#![no_std]
#![allow(non_camel_case_types)]
#![allow(clippy::uninit_assumed_init)]
#[prelude_import]
use core::prelude::rust_2018::*;
#[macro_use]
extern crate core;
#[macro_use]
extern crate compiler_builtins;
pub use stm32f0;
#[cfg(any(feature = "stm32f030", feature = "stm32f070"))]
pub use stm32f0::stm32f0x0 as pac;
#[cfg(feature = "device-selected")]
pub mod adc {
//! # API for the Analog to Digital converter
//!
//! Currently implements oneshot conversion with variable sampling times.
//! Also references for the internal temperature sense, voltage
//! reference and battery sense are provided.
//!
//! ## Example
//! ``` no_run
//! use stm32f0xx_hal as hal;
//!
//! use crate::hal::pac;
//! use crate::hal::prelude::*;
//! use crate::hal::adc::Adc;
//!
//! cortex_m::interrupt::free(|cs| {
//! let mut p = pac::Peripherals::take().unwrap();
//! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH);
//!
//! let gpioa = p.GPIOA.split(&mut rcc);
//!
//! let mut led = gpioa.pa1.into_push_pull_pull_output(cs);
//! let mut an_in = gpioa.pa0.into_analog(cs);
//!
//! let mut delay = Delay::new(cp.SYST, &rcc);
//!
//! let mut adc = Adc::new(p.ADC, &mut rcc);
//!
//! loop {
//! let val: u16 = adc.read(&mut an_in).unwrap();
//! if val < ((1 << 8) - 1) {
//! led.set_low();
//! } else {
//! led.set_high();
//! }
//! delay.delay_ms(50_u16);
//! }
//! });
//! ```
const VREFCAL: *const u16 = 0x1FFF_F7BA as *const u16;
const VTEMPCAL30: *const u16 = 0x1FFF_F7B8 as *const u16;
const VTEMPCAL110: *const u16 = 0x1FFF_F7C2 as *const u16;
const VDD_CALIB: u16 = 3300;
use core::ptr;
use embedded_hal::{
adc::{Channel, OneShot},
blocking::delay::DelayUs,
};
use crate::{
delay::Delay,
gpio::*,
pac::{
adc::{
cfgr1::{ALIGN_A, RES_A},
smpr::SMP_A,
},
ADC,
},
rcc::Rcc,
};
/// Analog to Digital converter interface
pub struct Adc {
rb: ADC,
sample_time: AdcSampleTime,
align: AdcAlign,
precision: AdcPrecision,
}
/// ADC Sampling time
///
/// Options for the sampling time, each is T + 0.5 ADC clock cycles.
pub enum AdcSampleTime {
/// 1.5 cycles sampling time
T_1,
/// 7.5 cycles sampling time
T_7,
/// 13.5 cycles sampling time
T_13,
/// 28.5 cycles sampling time
T_28,
/// 41.5 cycles sampling time
T_41,
/// 55.5 cycles sampling time
T_55,
/// 71.5 cycles sampling time
T_71,
/// 239.5 cycles sampling time
T_239,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for AdcSampleTime {
#[inline]
fn clone(&self) -> AdcSampleTime {
{
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for AdcSampleTime {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for AdcSampleTime {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match (&*self,) {
(&AdcSampleTime::T_1,) => ::core::fmt::Formatter::write_str(f, "T_1"),
(&AdcSampleTime::T_7,) => ::core::fmt::Formatter::write_str(f, "T_7"),
(&AdcSampleTime::T_13,) => ::core::fmt::Formatter::write_str(f, "T_13"),
(&AdcSampleTime::T_28,) => ::core::fmt::Formatter::write_str(f, "T_28"),
(&AdcSampleTime::T_41,) => ::core::fmt::Formatter::write_str(f, "T_41"),
(&AdcSampleTime::T_55,) => ::core::fmt::Formatter::write_str(f, "T_55"),
(&AdcSampleTime::T_71,) => ::core::fmt::Formatter::write_str(f, "T_71"),
(&AdcSampleTime::T_239,) => ::core::fmt::Formatter::write_str(f, "T_239"),
}
}
}
impl ::core::marker::StructuralPartialEq for AdcSampleTime {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for AdcSampleTime {
#[inline]
fn eq(&self, other: &AdcSampleTime) -> bool {
{
let __self_vi = ::core::intrinsics::discriminant_value(&*self);
let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other);
if true && __self_vi == __arg_1_vi {
match (&*self, &*other) {
_ => true,
}
} else {
false
}
}
}
}
impl AdcSampleTime {
/// Get the default sample time (currently 239.5 cycles)
pub fn default() -> Self {
AdcSampleTime::T_239
}
}
impl From<AdcSampleTime> for SMP_A {
fn from(val: AdcSampleTime) -> Self {
match val {
AdcSampleTime::T_1 => SMP_A::CYCLES1_5,
AdcSampleTime::T_7 => SMP_A::CYCLES7_5,
AdcSampleTime::T_13 => SMP_A::CYCLES13_5,
AdcSampleTime::T_28 => SMP_A::CYCLES28_5,
AdcSampleTime::T_41 => SMP_A::CYCLES41_5,
AdcSampleTime::T_55 => SMP_A::CYCLES55_5,
AdcSampleTime::T_71 => SMP_A::CYCLES71_5,
AdcSampleTime::T_239 => SMP_A::CYCLES239_5,
}
}
}
/// ADC Result Alignment
pub enum AdcAlign {
/// Left aligned results (most significant bits)
///
/// Results in all precisions returning a value in the range 0-65535.
/// Depending on the precision the result will step by larger or smaller
/// amounts.
Left,
/// Right aligned results (least significant bits)
///
/// Results in all precisions returning values from 0-(2^bits-1) in
/// steps of 1.
Right,
/// Left aligned results without correction of 6bit values.
///
/// Returns left aligned results exactly as shown in RM0091 Fig.37.
/// Where the values are left aligned within the u16, with the exception
/// of 6 bit mode where the value is left aligned within the first byte of
/// the u16.
LeftAsRM,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for AdcAlign {
#[inline]
fn clone(&self) -> AdcAlign {
{
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for AdcAlign {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for AdcAlign {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match (&*self,) {
(&AdcAlign::Left,) => ::core::fmt::Formatter::write_str(f, "Left"),
(&AdcAlign::Right,) => ::core::fmt::Formatter::write_str(f, "Right"),
(&AdcAlign::LeftAsRM,) => ::core::fmt::Formatter::write_str(f, "LeftAsRM"),
}
}
}
impl ::core::marker::StructuralPartialEq for AdcAlign {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for AdcAlign {
#[inline]
fn eq(&self, other: &AdcAlign) -> bool {
{
let __self_vi = ::core::intrinsics::discriminant_value(&*self);
let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other);
if true && __self_vi == __arg_1_vi {
match (&*self, &*other) {
_ => true,
}
} else {
false
}
}
}
}
impl AdcAlign {
/// Get the default alignment (currently right aligned)
pub fn default() -> Self {
AdcAlign::Right
}
}
impl From<AdcAlign> for ALIGN_A {
fn from(val: AdcAlign) -> Self {
match val {
AdcAlign::Left => ALIGN_A::LEFT,
AdcAlign::Right => ALIGN_A::RIGHT,
AdcAlign::LeftAsRM => ALIGN_A::LEFT,
}
}
}
/// ADC Sampling Precision
pub enum AdcPrecision {
/// 12 bit precision
B_12,
/// 10 bit precision
B_10,
/// 8 bit precision
B_8,
/// 6 bit precision
B_6,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for AdcPrecision {
#[inline]
fn clone(&self) -> AdcPrecision {
{
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for AdcPrecision {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for AdcPrecision {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match (&*self,) {
(&AdcPrecision::B_12,) => ::core::fmt::Formatter::write_str(f, "B_12"),
(&AdcPrecision::B_10,) => ::core::fmt::Formatter::write_str(f, "B_10"),
(&AdcPrecision::B_8,) => ::core::fmt::Formatter::write_str(f, "B_8"),
(&AdcPrecision::B_6,) => ::core::fmt::Formatter::write_str(f, "B_6"),
}
}
}
impl ::core::marker::StructuralPartialEq for AdcPrecision {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for AdcPrecision {
#[inline]
fn eq(&self, other: &AdcPrecision) -> bool {
{
let __self_vi = ::core::intrinsics::discriminant_value(&*self);
let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other);
if true && __self_vi == __arg_1_vi {
match (&*self, &*other) {
_ => true,
}
} else {
false
}
}
}
}
impl AdcPrecision {
/// Get the default precision (currently 12 bit precision)
pub fn default() -> Self {
AdcPrecision::B_12
}
}
impl From<AdcPrecision> for RES_A {
fn from(val: AdcPrecision) -> Self {
match val {
AdcPrecision::B_12 => RES_A::TWELVEBIT,
AdcPrecision::B_10 => RES_A::TENBIT,
AdcPrecision::B_8 => RES_A::EIGHTBIT,
AdcPrecision::B_6 => RES_A::SIXBIT,
}
}
}
impl Channel<Adc> for gpioa::PA0<Analog> {
type ID = u8;
fn channel() -> u8 {
0_u8
}
}
impl Channel<Adc> for gpioa::PA1<Analog> {
type ID = u8;
fn channel() -> u8 {
1_u8
}
}
impl Channel<Adc> for gpioa::PA2<Analog> {
type ID = u8;
fn channel() -> u8 {
2_u8
}
}
impl Channel<Adc> for gpioa::PA3<Analog> {
type ID = u8;
fn channel() -> u8 {
3_u8
}
}
impl Channel<Adc> for gpioa::PA4<Analog> {
type ID = u8;
fn channel() -> u8 {
4_u8
}
}
impl Channel<Adc> for gpioa::PA5<Analog> {
type ID = u8;
fn channel() -> u8 {
5_u8
}
}
impl Channel<Adc> for gpioa::PA6<Analog> {
type ID = u8;
fn channel() -> u8 {
6_u8
}
}
impl Channel<Adc> for gpioa::PA7<Analog> {
type ID = u8;
fn channel() -> u8 {
7_u8
}
}
impl Channel<Adc> for gpiob::PB0<Analog> {
type ID = u8;
fn channel() -> u8 {
8_u8
}
}
impl Channel<Adc> for gpiob::PB1<Analog> {
type ID = u8;
fn channel() -> u8 {
9_u8
}
}
impl Channel<Adc> for gpioc::PC0<Analog> {
type ID = u8;
fn channel() -> u8 {
10_u8
}
}
impl Channel<Adc> for gpioc::PC1<Analog> {
type ID = u8;
fn channel() -> u8 {
11_u8
}
}
impl Channel<Adc> for gpioc::PC2<Analog> {
type ID = u8;
fn channel() -> u8 {
12_u8
}
}
impl Channel<Adc> for gpioc::PC3<Analog> {
type ID = u8;
fn channel() -> u8 {
13_u8
}
}
impl Channel<Adc> for gpioc::PC4<Analog> {
type ID = u8;
fn channel() -> u8 {
14_u8
}
}
impl Channel<Adc> for gpioc::PC5<Analog> {
type ID = u8;
fn channel() -> u8 {
15_u8
}
}
/// Internal temperature sensor (ADC Channel 16)
pub struct VTemp;
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for VTemp {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
VTemp => ::core::fmt::Formatter::write_str(f, "VTemp"),
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::default::Default for VTemp {
#[inline]
fn default() -> VTemp {
VTemp {}
}
}
/// Internal voltage reference (ADC Channel 17)
pub struct VRef;
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for VRef {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
VRef => ::core::fmt::Formatter::write_str(f, "VRef"),
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::default::Default for VRef {
#[inline]
fn default() -> VRef {
VRef {}
}
}
impl Channel<Adc> for VTemp {
type ID = u8;
fn channel() -> u8 {
16_u8
}
}
impl Channel<Adc> for VRef {
type ID = u8;
fn channel() -> u8 {
17_u8
}
}
impl VTemp {
/// Init a new VTemp
pub fn new() -> Self {
VTemp::default()
}
/// Enable the internal temperature sense, this has a wake up time
/// t<sub>START</sub> which can be found in your micro's datasheet, you
/// must wait at least that long after enabling before taking a reading.
/// Remember to disable when not in use.
pub fn enable(&mut self, adc: &mut Adc) {
adc.rb.ccr.modify(|_, w| w.tsen().set_bit());
}
/// Disable the internal temperature sense.
pub fn disable(&mut self, adc: &mut Adc) {
adc.rb.ccr.modify(|_, w| w.tsen().clear_bit());
}
/// Checks if the temperature sensor is enabled, does not account for the
/// t<sub>START</sub> time however.
pub fn is_enabled(&self, adc: &Adc) -> bool {
adc.rb.ccr.read().tsen().bit_is_set()
}
fn convert_temp(vtemp: u16, vdda: u16) -> i16 {
let vtemp30_cal = i32::from(unsafe { ptr::read(VTEMPCAL30) }) * 100;
let vtemp110_cal = i32::from(unsafe { ptr::read(VTEMPCAL110) }) * 100;
let mut temperature = i32::from(vtemp) * 100;
temperature = (temperature * (i32::from(vdda) / i32::from(VDD_CALIB))) - vtemp30_cal;
temperature *= (110 - 30) * 100;
temperature /= vtemp110_cal - vtemp30_cal;
temperature += 3000;
temperature as i16
}
/// Read the value of the internal temperature sensor and return the
/// result in 100ths of a degree centigrade.
///
/// Given a delay reference it will attempt to restrict to the
/// minimum delay needed to ensure a 10 us t<sub>START</sub> value.
/// Otherwise it will approximate the required delay using ADC reads.
pub fn read(adc: &mut Adc, delay: Option<&mut Delay>) -> i16 {
let mut vtemp = Self::new();
let vtemp_preenable = vtemp.is_enabled(adc);
if !vtemp_preenable {
vtemp.enable(adc);
if let Some(dref) = delay {
dref.delay_us(2_u16);
} else {
VRef::read_vdda(adc);
}
}
let vdda = VRef::read_vdda(adc);
let prev_cfg = adc.default_cfg();
let vtemp_val = adc.read(&mut vtemp).unwrap();
if !vtemp_preenable {
vtemp.disable(adc);
}
adc.restore_cfg(prev_cfg);
Self::convert_temp(vtemp_val, vdda)
}
}
impl VRef {
/// Init a new VRef
pub fn new() -> Self {
VRef::default()
}
/// Enable the internal voltage reference, remember to disable when not in use.
pub fn enable(&mut self, adc: &mut Adc) {
adc.rb.ccr.modify(|_, w| w.vrefen().set_bit());
}
/// Disable the internal reference voltage.
pub fn disable(&mut self, adc: &mut Adc) {
adc.rb.ccr.modify(|_, w| w.vrefen().clear_bit());
}
/// Returns if the internal voltage reference is enabled.
pub fn is_enabled(&self, adc: &Adc) -> bool {
adc.rb.ccr.read().vrefen().bit_is_set()
}
/// Reads the value of VDDA in milli-volts
pub fn read_vdda(adc: &mut Adc) -> u16 {
let vrefint_cal = u32::from(unsafe { ptr::read(VREFCAL) });
let mut vref = Self::new();
let prev_cfg = adc.default_cfg();
let vref_val: u32 = if vref.is_enabled(adc) {
adc.read(&mut vref).unwrap()
} else {
vref.enable(adc);
let ret = adc.read(&mut vref).unwrap();
vref.disable(adc);
ret
};
adc.restore_cfg(prev_cfg);
(u32::from(VDD_CALIB) * vrefint_cal / vref_val) as u16
}
}
/// A stored ADC config, can be restored by using the `Adc::restore_cfg` method
pub struct StoredConfig(AdcSampleTime, AdcAlign, AdcPrecision);
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for StoredConfig {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for StoredConfig {
#[inline]
fn clone(&self) -> StoredConfig {
{
let _: ::core::clone::AssertParamIsClone<AdcSampleTime>;
let _: ::core::clone::AssertParamIsClone<AdcAlign>;
let _: ::core::clone::AssertParamIsClone<AdcPrecision>;
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for StoredConfig {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
StoredConfig(ref __self_0_0, ref __self_0_1, ref __self_0_2) => {
let debug_trait_builder =
&mut ::core::fmt::Formatter::debug_tuple(f, "StoredConfig");
let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_0_0));
let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_0_1));
let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_0_2));
::core::fmt::DebugTuple::finish(debug_trait_builder)
}
}
}
}
impl ::core::marker::StructuralPartialEq for StoredConfig {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for StoredConfig {
#[inline]
fn eq(&self, other: &StoredConfig) -> bool {
match *other {
StoredConfig(ref __self_1_0, ref __self_1_1, ref __self_1_2) => match *self {
StoredConfig(ref __self_0_0, ref __self_0_1, ref __self_0_2) => {
(*__self_0_0) == (*__self_1_0)
&& (*__self_0_1) == (*__self_1_1)
&& (*__self_0_2) == (*__self_1_2)
}
},
}
}
#[inline]
fn ne(&self, other: &StoredConfig) -> bool {
match *other {
StoredConfig(ref __self_1_0, ref __self_1_1, ref __self_1_2) => match *self {
StoredConfig(ref __self_0_0, ref __self_0_1, ref __self_0_2) => {
(*__self_0_0) != (*__self_1_0)
|| (*__self_0_1) != (*__self_1_1)
|| (*__self_0_2) != (*__self_1_2)
}
},
}
}
}
impl Adc {
/// Init a new Adc
///
/// Sets all configurable parameters to defaults, enables the HSI14 clock
/// for the ADC if it is not already enabled and performs a boot time
/// calibration. As such this method may take an appreciable time to run.
pub fn new(adc: ADC, rcc: &mut Rcc) -> Self {
let mut s = Self {
rb: adc,
sample_time: AdcSampleTime::default(),
align: AdcAlign::default(),
precision: AdcPrecision::default(),
};
s.select_clock(rcc);
s.calibrate();
s
}
/// Saves a copy of the current ADC config
pub fn save_cfg(&mut self) -> StoredConfig {
StoredConfig(self.sample_time, self.align, self.precision)
}
/// Restores a stored config
pub fn restore_cfg(&mut self, cfg: StoredConfig) {
self.sample_time = cfg.0;
self.align = cfg.1;
self.precision = cfg.2;
}
/// Resets the ADC config to default, returning the existing config as
/// a stored config.
pub fn default_cfg(&mut self) -> StoredConfig {
let cfg = self.save_cfg();
self.sample_time = AdcSampleTime::default();
self.align = AdcAlign::default();
self.precision = AdcPrecision::default();
cfg
}
/// Set the Adc sampling time
///
/// Options can be found in [AdcSampleTime](crate::adc::AdcSampleTime).
pub fn set_sample_time(&mut self, t_samp: AdcSampleTime) {
self.sample_time = t_samp;
}
/// Set the Adc result alignment
///
/// Options can be found in [AdcAlign](crate::adc::AdcAlign).
pub fn set_align(&mut self, align: AdcAlign) {
self.align = align;
}
/// Set the Adc precision
///
/// Options can be found in [AdcPrecision](crate::adc::AdcPrecision).
pub fn set_precision(&mut self, precision: AdcPrecision) {
self.precision = precision;
}
/// Returns the largest possible sample value for the current settings
pub fn max_sample(&self) -> u16 {
match self.align {
AdcAlign::Left => u16::max_value(),
AdcAlign::LeftAsRM => match self.precision {
AdcPrecision::B_6 => u16::from(u8::max_value()),
_ => u16::max_value(),
},
AdcAlign::Right => match self.precision {
AdcPrecision::B_12 => (1 << 12) - 1,
AdcPrecision::B_10 => (1 << 10) - 1,
AdcPrecision::B_8 => (1 << 8) - 1,
AdcPrecision::B_6 => (1 << 6) - 1,
},
}
}
/// Read the value of a channel and converts the result to milli-volts
pub fn read_abs_mv<PIN: Channel<Adc, ID = u8>>(&mut self, pin: &mut PIN) -> u16 {
let vdda = u32::from(VRef::read_vdda(self));
let v: u32 = self.read(pin).unwrap();
let max_samp = u32::from(self.max_sample());
(v * vdda / max_samp) as u16
}
fn calibrate(&mut self) {
if self.rb.cr.read().aden().is_enabled() {
self.rb.cr.modify(|_, w| w.addis().disable());
}
while self.rb.cr.read().aden().is_enabled() {}
self.rb.cfgr1.modify(|_, w| w.dmaen().disabled());
self.rb.cr.modify(|_, w| w.adcal().start_calibration());
while self.rb.cr.read().adcal().is_calibrating() {}
}
fn select_clock(&mut self, rcc: &mut Rcc) {
rcc.regs.apb2enr.modify(|_, w| w.adcen().enabled());
rcc.regs.cr2.modify(|_, w| w.hsi14on().on());
while rcc.regs.cr2.read().hsi14rdy().is_not_ready() {}
}
fn power_up(&mut self) {
if self.rb.isr.read().adrdy().is_ready() {
self.rb.isr.modify(|_, w| w.adrdy().clear());
}
self.rb.cr.modify(|_, w| w.aden().enabled());
while self.rb.isr.read().adrdy().is_not_ready() {}
}
fn power_down(&mut self) {
self.rb.cr.modify(|_, w| w.adstp().stop_conversion());
while self.rb.cr.read().adstp().is_stopping() {}
self.rb.cr.modify(|_, w| w.addis().disable());
while self.rb.cr.read().aden().is_enabled() {}
}
fn convert(&mut self, chan: u8) -> u16 {
self.rb.chselr.write(|w| unsafe { w.bits(1_u32 << chan) });
self.rb
.smpr
.write(|w| w.smp().variant(self.sample_time.into()));
self.rb.cfgr1.modify(|_, w| {
w.res()
.variant(self.precision.into())
.align()
.variant(self.align.into())
});
self.rb.cr.modify(|_, w| w.adstart().start_conversion());
while self.rb.isr.read().eoc().is_not_complete() {}
let res = self.rb.dr.read().bits() as u16;
if self.align == AdcAlign::Left && self.precision == AdcPrecision::B_6 {
res << 8
} else {
res
}
}
}
impl<WORD, PIN> OneShot<Adc, WORD, PIN> for Adc
where
WORD: From<u16>,
PIN: Channel<Adc, ID = u8>,
{
type Error = ();
fn read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
self.power_up();
let res = self.convert(PIN::channel());
self.power_down();
Ok(res.into())
}
}
}
#[cfg(feature = "device-selected")]
pub mod delay {
//! API for delays with the systick timer
//!
//! Please be aware of potential overflows when using `delay_us`.
//! E.g. at 48MHz the maximum delay is 89 seconds.
//!
//! Consider using the timers api as a more flexible interface
//!
//! # Example
//!
//! ``` no_run
//! use stm32f0xx_hal as hal;
//!
//! use crate::hal::pac;
//! use crate::hal::prelude::*;
//! use crate::hal::delay::Delay;
//! use cortex_m::peripheral::Peripherals;
//!
//! let mut p = pac::Peripherals::take().unwrap();
//! let mut cp = cortex_m::Peripherals::take().unwrap();
//!
//! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH);
//! let mut delay = Delay::new(cp.SYST, &rcc);
//! loop {
//! delay.delay_ms(1_000_u16);
//! }
//! ```
use cast::{u16, u32};
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use crate::rcc::Rcc;
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
/// System timer (SysTick) as a delay provider
pub struct Delay {
scale: u32,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for Delay {
#[inline]
fn clone(&self) -> Delay {
match *self {
Delay {
scale: ref __self_0_0,
} => Delay {
scale: ::core::clone::Clone::clone(&(*__self_0_0)),
},
}
}
}
const SYSTICK_RANGE: u32 = 0x0100_0000;
impl Delay {
/// Configures the system timer (SysTick) as a delay provider
pub fn new(mut syst: SYST, rcc: &Rcc) -> Delay {
syst.set_clock_source(SystClkSource::Core);
syst.set_reload(SYSTICK_RANGE - 1);
syst.clear_current();
syst.enable_counter();
if !(rcc.clocks.hclk().0 >= 1_000_000) {
::core::panicking::panic("assertion failed: rcc.clocks.hclk().0 >= 1_000_000")
};
let scale = rcc.clocks.hclk().0 / 1_000_000;
Delay { scale }
}
}
impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, mut ms: u32) {
const MAX_MS: u32 = 0x0000_FFFF;
while ms != 0 {
let current_ms = if ms <= MAX_MS { ms } else { MAX_MS };
self.delay_us(current_ms * 1_000);
ms -= current_ms;
}
}
}
impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
self.delay_us(u32(ms) * 1_000);
}
}
impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u16(ms));
}
}
impl DelayUs<u32> for Delay {
fn delay_us(&mut self, us: u32) {
const MAX_TICKS: u32 = 0x007F_FFFF;
let mut total_ticks = us * self.scale;
while total_ticks != 0 {
let current_ticks = if total_ticks <= MAX_TICKS {
total_ticks
} else {
MAX_TICKS
};
let start_count = SYST::get_current();
total_ticks -= current_ticks;
while (start_count.wrapping_sub(SYST::get_current()) % SYSTICK_RANGE)
< current_ticks
{}
}
}
}
impl DelayUs<u16> for Delay {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32(us))
}
}
impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
}
}
}
#[cfg(feature = "device-selected")]
pub mod i2c {
use core::ops::Deref;
use embedded_hal::blocking::i2c::{Read, Write, WriteRead};
use crate::{
gpio::*,
rcc::Rcc,
time::{KiloHertz, U32Ext},
};
/// I2C abstraction
pub struct I2c<I2C, SCLPIN, SDAPIN> {
i2c: I2C,
pins: (SCLPIN, SDAPIN),
}
pub trait SclPin<I2C> {}
pub trait SdaPin<I2C> {}
impl SclPin<crate::pac::I2C1> for gpiob::PB6<Alternate<AF1>> {}
impl SclPin<crate::pac::I2C1> for gpiob::PB8<Alternate<AF1>> {}
impl SdaPin<crate::pac::I2C1> for gpiob::PB7<Alternate<AF1>> {}
impl SdaPin<crate::pac::I2C1> for gpiob::PB9<Alternate<AF1>> {}
pub enum Error {
OVERRUN,
NACK,
BUS,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for Error {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match (&*self,) {
(&Error::OVERRUN,) => ::core::fmt::Formatter::write_str(f, "OVERRUN"),
(&Error::NACK,) => ::core::fmt::Formatter::write_str(f, "NACK"),
(&Error::BUS,) => ::core::fmt::Formatter::write_str(f, "BUS"),
}
}
}
use crate::pac::I2C1;
impl<SCLPIN, SDAPIN> I2c<I2C1, SCLPIN, SDAPIN> {
pub fn i2c1(i2c: I2C1, pins: (SCLPIN, SDAPIN), speed: KiloHertz, rcc: &mut Rcc) -> Self
where
SCLPIN: SclPin<I2C1>,
SDAPIN: SdaPin<I2C1>,
{
rcc.regs.apb1enr.modify(|_, w| w.i2c1en().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.i2c1rst().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit());
I2c { i2c, pins }.i2c_init(speed)
}
}
#[allow(dead_code)]
type I2cRegisterBlock = crate::pac::i2c1::RegisterBlock;
impl<I2C, SCLPIN, SDAPIN> I2c<I2C, SCLPIN, SDAPIN>
where
I2C: Deref<Target = I2cRegisterBlock>,
{
fn i2c_init(self, speed: KiloHertz) -> Self {
use core::cmp;
self.i2c.cr1.modify(|_, w| w.pe().clear_bit());
let presc;
let scldel;
let sdadel;
let sclh;
let scll;
const FREQ: u32 = 8_000_000;
if speed <= 100_u32.khz() {
presc = 1;
scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8;
sclh = scll - 4;
sdadel = 2;
scldel = 4;
} else {
presc = 0;
scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8;
sclh = scll - 6;
sdadel = 1;
scldel = 3;
}
self.i2c.timingr.write(|w| {
w.presc()
.bits(presc)
.scldel()
.bits(scldel)
.sdadel()
.bits(sdadel)
.sclh()
.bits(sclh)
.scll()
.bits(scll)
});
self.i2c.cr1.modify(|_, w| w.pe().set_bit());
self
}
pub fn release(self) -> (I2C, (SCLPIN, SDAPIN)) {
(self.i2c, self.pins)
}
fn check_and_clear_error_flags(
&self,
isr: &crate::stm32::i2c1::isr::R,
) -> Result<(), Error> {
if isr.ovr().bit_is_set() {
self.i2c.icr.write(|w| w.ovrcf().set_bit());
return Err(Error::OVERRUN);
}
if isr.arlo().bit_is_set() | isr.berr().bit_is_set() {
self.i2c
.icr
.write(|w| w.arlocf().set_bit().berrcf().set_bit());
return Err(Error::BUS);
}
if isr.nackf().bit_is_set() {
self.i2c
.icr
.write(|w| w.stopcf().set_bit().nackcf().set_bit());
return Err(Error::NACK);
}
Ok(())
}
fn send_byte(&self, byte: u8) -> Result<(), Error> {
loop {
let isr = self.i2c.isr.read();
self.check_and_clear_error_flags(&isr)?;
if isr.txis().bit_is_set() {
break;
}
}
self.i2c.txdr.write(|w| unsafe { w.bits(u32::from(byte)) });
self.check_and_clear_error_flags(&self.i2c.isr.read())?;
Ok(())
}
fn recv_byte(&self) -> Result<u8, Error> {
loop {
let isr = self.i2c.isr.read();
self.check_and_clear_error_flags(&isr)?;
if isr.rxne().bit_is_set() {
break;
}
}
let value = self.i2c.rxdr.read().bits() as u8;
Ok(value)
}
}
impl<I2C, SCLPIN, SDAPIN> WriteRead for I2c<I2C, SCLPIN, SDAPIN>
where
I2C: Deref<Target = I2cRegisterBlock>,
{
type Error = Error;
fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
self.i2c.cr2.modify(|_, w| {
w.sadd()
.bits(u16::from(addr) << 1)
.nbytes()
.bits(bytes.len() as u8)
.rd_wrn()
.clear_bit()
.autoend()
.clear_bit()
});
self.i2c.cr2.modify(|_, w| w.start().set_bit());
loop {
let isr = self.i2c.isr.read();
self.check_and_clear_error_flags(&isr)?;
if isr.txis().bit_is_set() || isr.tc().bit_is_set() {
break;
}
}
for c in bytes {
self.send_byte(*c)?;
}
loop {
let isr = self.i2c.isr.read();
self.check_and_clear_error_flags(&isr)?;
if isr.tc().bit_is_set() {
break;
}
}
self.i2c.cr2.modify(|_, w| {
w.sadd()
.bits(u16::from(addr) << 1)
.nbytes()
.bits(buffer.len() as u8)
.rd_wrn()
.set_bit()
});
self.i2c.cr2.modify(|_, w| w.start().set_bit());
self.i2c.cr2.modify(|_, w| w.autoend().set_bit());
for c in buffer.iter_mut() {
*c = self.recv_byte()?;
}
self.check_and_clear_error_flags(&self.i2c.isr.read())?;
Ok(())
}
}
impl<I2C, SCLPIN, SDAPIN> Read for I2c<I2C, SCLPIN, SDAPIN>
where
I2C: Deref<Target = I2cRegisterBlock>,
{
type Error = Error;
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
self.i2c.cr2.modify(|_, w| {
w.sadd()
.bits(u16::from(addr) << 1)
.nbytes()
.bits(buffer.len() as u8)
.rd_wrn()
.set_bit()
});
self.i2c.cr2.modify(|_, w| w.start().set_bit());
self.i2c.cr2.modify(|_, w| w.autoend().set_bit());
for c in buffer.iter_mut() {
*c = self.recv_byte()?;
}
self.check_and_clear_error_flags(&self.i2c.isr.read())?;
Ok(())
}
}
impl<I2C, SCLPIN, SDAPIN> Write for I2c<I2C, SCLPIN, SDAPIN>
where
I2C: Deref<Target = I2cRegisterBlock>,
{
type Error = Error;
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
self.i2c.cr2.modify(|_, w| {
w.sadd()
.bits(u16::from(addr) << 1)
.nbytes()
.bits(bytes.len() as u8)
.rd_wrn()
.clear_bit()
.autoend()
.set_bit()
});
self.i2c.cr2.modify(|_, w| w.start().set_bit());
for c in bytes {
self.send_byte(*c)?;
}
self.check_and_clear_error_flags(&self.i2c.isr.read())?;
Ok(())
}
}
}
#[cfg(feature = "device-selected")]
pub mod prelude {
pub use embedded_hal::prelude::*;
pub use embedded_hal::watchdog::Watchdog as _stm32f0xx_hal_embedded_hal_watchdog_Watchdog;
pub use embedded_hal::watchdog::WatchdogEnable as _stm32f0xx_hal_embedded_hal_watchdog_WatchdogEnable;
pub use embedded_hal::adc::OneShot as _embedded_hal_adc_OneShot;
pub use embedded_hal::digital::v2::InputPin as _embedded_hal_gpio_InputPin;
pub use embedded_hal::digital::v2::OutputPin as _embedded_hal_gpio_OutputPin;
pub use embedded_hal::digital::v2::StatefulOutputPin as _embedded_hal_gpio_StatefulOutputPin;
pub use embedded_hal::digital::v2::ToggleableOutputPin as _embedded_hal_gpio_ToggleableOutputPin;
pub use crate::gpio::GpioExt as _stm32f0xx_hal_gpio_GpioExt;
pub use crate::rcc::RccExt as _stm32f0xx_hal_rcc_RccExt;
pub use crate::time::U32Ext as _stm32f0xx_hal_time_U32Ext;
}
#[cfg(feature = "device-selected")]
pub mod pwm {
use cast::{u16, u32};
use core::{marker::PhantomData, mem::MaybeUninit};
use crate::rcc::Rcc;
use crate::time::Hertz;
use embedded_hal as hal;
pub trait Pins<TIM, P> {
const C1: bool = false;
const C2: bool = false;
const C3: bool = false;
const C4: bool = false;
type Channels;
}
use crate::timers::PinC1;
use crate::timers::PinC2;
use crate::timers::PinC3;
use crate::timers::PinC4;
pub struct C1;
pub struct C2;
pub struct C3;
pub struct C4;
pub struct PwmChannels<TIM, CHANNELS> {
_channel: PhantomData<CHANNELS>,
_tim: PhantomData<TIM>,
}
#[allow(unused_parens)]
impl<TIM, P1, P2, P3, P4> Pins<TIM, (C1, C2, C3, C4)> for (P1, P2, P3, P4)
where
P1: PinC1<TIM>,
P2: PinC2<TIM>,
P3: PinC3<TIM>,
P4: PinC4<TIM>,
{
const C1: bool = true;
const C2: bool = true;
const C3: bool = true;
const C4: bool = true;
type Channels = (
PwmChannels<TIM, C1>,
PwmChannels<TIM, C2>,
PwmChannels<TIM, C3>,
PwmChannels<TIM, C4>,
);
}
#[allow(unused_parens)]
impl<TIM, P2, P3, P4> Pins<TIM, (C2, C3, C4)> for (P2, P3, P4)
where
P2: PinC2<TIM>,
P3: PinC3<TIM>,
P4: PinC4<TIM>,
{
const C2: bool = true;
const C3: bool = true;
const C4: bool = true;
type Channels = (
PwmChannels<TIM, C2>,
PwmChannels<TIM, C3>,
PwmChannels<TIM, C4>,
);
}
#[allow(unused_parens)]
impl<TIM, P1, P3, P4> Pins<TIM, (C1, C3, C4)> for (P1, P3, P4)
where
P1: PinC1<TIM>,
P3: PinC3<TIM>,
P4: PinC4<TIM>,
{
const C1: bool = true;
const C3: bool = true;
const C4: bool = true;
type Channels = (
PwmChannels<TIM, C1>,
PwmChannels<TIM, C3>,
PwmChannels<TIM, C4>,
);
}
#[allow(unused_parens)]
impl<TIM, P1, P2, P4> Pins<TIM, (C1, C2, C4)> for (P1, P2, P4)
where
P1: PinC1<TIM>,
P2: PinC2<TIM>,
P4: PinC4<TIM>,
{
const C1: bool = true;
const C2: bool = true;
const C4: bool = true;
type Channels = (
PwmChannels<TIM, C1>,
PwmChannels<TIM, C2>,
PwmChannels<TIM, C4>,
);
}
#[allow(unused_parens)]
impl<TIM, P1, P2, P3> Pins<TIM, (C1, C2, C3)> for (P1, P2, P3)
where
P1: PinC1<TIM>,
P2: PinC2<TIM>,
P3: PinC3<TIM>,
{
const C1: bool = true;
const C2: bool = true;
const C3: bool = true;
type Channels = (
PwmChannels<TIM, C1>,
PwmChannels<TIM, C2>,
PwmChannels<TIM, C3>,
);
}
#[allow(unused_parens)]
impl<TIM, P3, P4> Pins<TIM, (C3, C4)> for (P3, P4)
where
P3: PinC3<TIM>,
P4: PinC4<TIM>,
{
const C3: bool = true;
const C4: bool = true;
type Channels = (PwmChannels<TIM, C3>, PwmChannels<TIM, C4>);
}
#[allow(unused_parens)]
impl<TIM, P2, P4> Pins<TIM, (C2, C4)> for (P2, P4)
where
P2: PinC2<TIM>,
P4: PinC4<TIM>,
{
const C2: bool = true;
const C4: bool = true;
type Channels = (PwmChannels<TIM, C2>, PwmChannels<TIM, C4>);
}
#[allow(unused_parens)]
impl<TIM, P2, P3> Pins<TIM, (C2, C3)> for (P2, P3)
where
P2: PinC2<TIM>,
P3: PinC3<TIM>,
{
const C2: bool = true;
const C3: bool = true;
type Channels = (PwmChannels<TIM, C2>, PwmChannels<TIM, C3>);
}
#[allow(unused_parens)]
impl<TIM, P1, P4> Pins<TIM, (C1, C4)> for (P1, P4)
where
P1: PinC1<TIM>,
P4: PinC4<TIM>,
{
const C1: bool = true;
const C4: bool = true;
type Channels = (PwmChannels<TIM, C1>, PwmChannels<TIM, C4>);
}
#[allow(unused_parens)]
impl<TIM, P1, P3> Pins<TIM, (C1, C3)> for (P1, P3)
where
P1: PinC1<TIM>,
P3: PinC3<TIM>,
{
const C1: bool = true;
const C3: bool = true;
type Channels = (PwmChannels<TIM, C1>, PwmChannels<TIM, C3>);
}
#[allow(unused_parens)]
impl<TIM, P1, P2> Pins<TIM, (C1, C2)> for (P1, P2)
where
P1: PinC1<TIM>,
P2: PinC2<TIM>,
{
const C1: bool = true;
const C2: bool = true;
type Channels = (PwmChannels<TIM, C1>, PwmChannels<TIM, C2>);
}
#[allow(unused_parens)]
impl<TIM, P1> Pins<TIM, (C1)> for (P1)
where
P1: PinC1<TIM>,
{
const C1: bool = true;
type Channels = (PwmChannels<TIM, C1>);
}
#[allow(unused_parens)]
impl<TIM, P2> Pins<TIM, (C2)> for (P2)
where
P2: PinC2<TIM>,
{
const C2: bool = true;
type Channels = (PwmChannels<TIM, C2>);
}
#[allow(unused_parens)]
impl<TIM, P3> Pins<TIM, (C3)> for (P3)
where
P3: PinC3<TIM>,
{
const C3: bool = true;
type Channels = (PwmChannels<TIM, C3>);
}
#[allow(unused_parens)]
impl<TIM, P4> Pins<TIM, (C4)> for (P4)
where
P4: PinC4<TIM>,
{
const C4: bool = true;
type Channels = (PwmChannels<TIM, C4>);
}
impl<TIM, P1: PinC1<TIM>, P2: PinC1<TIM>> PinC1<TIM> for (P1, P2) {}
impl<TIM, P1: PinC2<TIM>, P2: PinC2<TIM>> PinC2<TIM> for (P1, P2) {}
impl<TIM, P1: PinC3<TIM>, P2: PinC3<TIM>> PinC3<TIM> for (P1, P2) {}
impl<TIM, P1: PinC4<TIM>, P2: PinC4<TIM>> PinC4<TIM> for (P1, P2) {}
impl<TIM, P1: PinC1<TIM>, P2: PinC1<TIM>, P3: PinC1<TIM>> PinC1<TIM> for (P1, P2, P3) {}
impl<TIM, P1: PinC2<TIM>, P2: PinC2<TIM>, P3: PinC2<TIM>> PinC2<TIM> for (P1, P2, P3) {}
impl<TIM, P1: PinC3<TIM>, P2: PinC3<TIM>, P3: PinC3<TIM>> PinC3<TIM> for (P1, P2, P3) {}
impl<TIM, P1: PinC4<TIM>, P2: PinC4<TIM>, P3: PinC4<TIM>> PinC4<TIM> for (P1, P2, P3) {}
impl<TIM, P1: PinC1<TIM>, P2: PinC1<TIM>, P3: PinC1<TIM>, P4: PinC1<TIM>> PinC1<TIM>
for (P1, P2, P3, P4)
{
}
impl<TIM, P1: PinC2<TIM>, P2: PinC2<TIM>, P3: PinC2<TIM>, P4: PinC2<TIM>> PinC2<TIM>
for (P1, P2, P3, P4)
{
}
impl<TIM, P1: PinC3<TIM>, P2: PinC3<TIM>, P3: PinC3<TIM>, P4: PinC3<TIM>> PinC3<TIM>
for (P1, P2, P3, P4)
{
}
impl<TIM, P1: PinC4<TIM>, P2: PinC4<TIM>, P3: PinC4<TIM>, P4: PinC4<TIM>> PinC4<TIM>
for (P1, P2, P3, P4)
{
}
use crate::pac::*;
pub fn tim1<P, PINS, T>(tim: TIM1, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels
where
PINS: Pins<TIM1, P>,
T: Into<Hertz>,
{
rcc.regs.apb2enr.modify(|_, w| w.tim1en().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim1rst().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim1rst().clear_bit());
if PINS::C1 {
tim.ccmr1_output()
.modify(|_, w| w.oc1pe().set_bit().oc1m().pwm_mode1());
}
if PINS::C2 {
tim.ccmr1_output()
.modify(|_, w| w.oc2pe().set_bit().oc2m().pwm_mode1());
}
if PINS::C3 {
tim.ccmr2_output()
.modify(|_, w| w.oc3pe().set_bit().oc3m().pwm_mode1());
}
if PINS::C4 {
tim.ccmr2_output()
.modify(|_, w| w.oc4pe().set_bit().oc4m().pwm_mode1());
}
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
rcc.clocks.pclk().0
} else {
rcc.clocks.pclk().0 * 2
};
let ticks = tclk / freq.into().0;
let psc = u16((ticks - 1) / (1 << 16)).unwrap();
tim.psc.write(|w| w.psc().bits(psc));
let arr = u16(ticks / u32(psc + 1)).unwrap();
tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
tim.cr1.modify(|_, w| w.arpe().set_bit());
tim.cr1.modify(|_, w| w.urs().set_bit());
tim.egr.write(|w| w.ug().set_bit());
tim.cr1.modify(|_, w| w.urs().clear_bit());
tim.bdtr.modify(|_, w| w.aoe().set_bit());
tim.cr1.write(|w| {
w.cms()
.bits(0b00)
.dir()
.clear_bit()
.opm()
.clear_bit()
.cen()
.set_bit()
});
unsafe { MaybeUninit::uninit().assume_init() }
}
impl hal::PwmPin for PwmChannels<TIM1, C1> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM1::ptr()).ccr1.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM1::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM1::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
}
}
impl hal::PwmPin for PwmChannels<TIM1, C2> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc2e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc2e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM1::ptr()).ccr2.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM1::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM1::ptr()).ccr2.write(|w| w.ccr().bits(duty.into())) }
}
}
impl hal::PwmPin for PwmChannels<TIM1, C3> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc3e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc3e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM1::ptr()).ccr3.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM1::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM1::ptr()).ccr3.write(|w| w.ccr().bits(duty.into())) }
}
}
impl hal::PwmPin for PwmChannels<TIM1, C4> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc4e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc4e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM1::ptr()).ccr4.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM1::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM1::ptr()).ccr4.write(|w| w.ccr().bits(duty.into())) }
}
}
pub fn tim3<P, PINS, T>(tim: TIM3, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels
where
PINS: Pins<TIM3, P>,
T: Into<Hertz>,
{
rcc.regs.apb1enr.modify(|_, w| w.tim3en().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.tim3rst().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.tim3rst().clear_bit());
if PINS::C1 {
tim.ccmr1_output()
.modify(|_, w| w.oc1pe().set_bit().oc1m().pwm_mode1());
}
if PINS::C2 {
tim.ccmr1_output()
.modify(|_, w| w.oc2pe().set_bit().oc2m().pwm_mode1());
}
if PINS::C3 {
tim.ccmr2_output()
.modify(|_, w| w.oc3pe().set_bit().oc3m().pwm_mode1());
}
if PINS::C4 {
tim.ccmr2_output()
.modify(|_, w| w.oc4pe().set_bit().oc4m().pwm_mode1());
}
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
rcc.clocks.pclk().0
} else {
rcc.clocks.pclk().0 * 2
};
let ticks = tclk / freq.into().0;
let psc = u16((ticks - 1) / (1 << 16)).unwrap();
tim.psc.write(|w| w.psc().bits(psc));
let arr = u16(ticks / u32(psc + 1)).unwrap();
tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
tim.cr1.modify(|_, w| w.arpe().set_bit());
tim.cr1.modify(|_, w| w.urs().set_bit());
tim.egr.write(|w| w.ug().set_bit());
tim.cr1.modify(|_, w| w.urs().clear_bit());
tim.cr1.write(|w| {
w.cms()
.bits(0b00)
.dir()
.clear_bit()
.opm()
.clear_bit()
.cen()
.set_bit()
});
unsafe { MaybeUninit::uninit().assume_init() }
}
impl hal::PwmPin for PwmChannels<TIM3, C1> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM3::ptr()).ccr1.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM3::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM3::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
}
}
impl hal::PwmPin for PwmChannels<TIM3, C2> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc2e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc2e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM3::ptr()).ccr2.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM3::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM3::ptr()).ccr2.write(|w| w.ccr().bits(duty.into())) }
}
}
impl hal::PwmPin for PwmChannels<TIM3, C3> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc3e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc3e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM3::ptr()).ccr3.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM3::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM3::ptr()).ccr3.write(|w| w.ccr().bits(duty.into())) }
}
}
impl hal::PwmPin for PwmChannels<TIM3, C4> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc4e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc4e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM3::ptr()).ccr4.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM3::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM3::ptr()).ccr4.write(|w| w.ccr().bits(duty.into())) }
}
}
pub fn tim14<P, PINS, T>(tim: TIM14, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels
where
PINS: Pins<TIM14, P>,
T: Into<Hertz>,
{
rcc.regs.apb1enr.modify(|_, w| w.tim14en().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.tim14rst().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.tim14rst().clear_bit());
if PINS::C1 {
tim.ccmr1_output()
.modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6));
}
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
rcc.clocks.pclk().0
} else {
rcc.clocks.pclk().0 * 2
};
let ticks = tclk / freq.into().0;
let psc = u16((ticks - 1) / (1 << 16)).unwrap();
tim.psc.write(|w| w.psc().bits(psc));
let arr = u16(ticks / u32(psc + 1)).unwrap();
tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
tim.cr1.modify(|_, w| w.arpe().set_bit());
tim.cr1.modify(|_, w| w.urs().set_bit());
tim.egr.write(|w| w.ug().set_bit());
tim.cr1.modify(|_, w| w.urs().clear_bit());
tim.cr1.write(|w| w.cen().set_bit());
unsafe { MaybeUninit::uninit().assume_init() }
}
impl hal::PwmPin for PwmChannels<TIM14, C1> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM14::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM14::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM14::ptr()).ccr1.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM14::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM14::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
}
}
pub fn tim16<P, PINS, T>(tim: TIM16, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels
where
PINS: Pins<TIM16, P>,
T: Into<Hertz>,
{
rcc.regs.apb2enr.modify(|_, w| w.tim16en().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim16rst().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim16rst().clear_bit());
if PINS::C1 {
tim.ccmr1_output()
.modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6));
}
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
rcc.clocks.pclk().0
} else {
rcc.clocks.pclk().0 * 2
};
let ticks = tclk / freq.into().0;
let psc = u16((ticks - 1) / (1 << 16)).unwrap();
tim.psc.write(|w| w.psc().bits(psc));
let arr = u16(ticks / u32(psc + 1)).unwrap();
tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
tim.cr1.modify(|_, w| w.arpe().set_bit());
tim.cr1.modify(|_, w| w.urs().set_bit());
tim.egr.write(|w| w.ug().set_bit());
tim.cr1.modify(|_, w| w.urs().clear_bit());
tim.bdtr.modify(|_, w| w.aoe().set_bit());
tim.cr1.write(|w| w.opm().clear_bit().cen().set_bit());
unsafe { MaybeUninit::uninit().assume_init() }
}
impl hal::PwmPin for PwmChannels<TIM16, C1> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM16::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM16::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM16::ptr()).ccr1.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM16::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM16::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
}
}
pub fn tim17<P, PINS, T>(tim: TIM17, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels
where
PINS: Pins<TIM17, P>,
T: Into<Hertz>,
{
rcc.regs.apb2enr.modify(|_, w| w.tim17en().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim17rst().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim17rst().clear_bit());
if PINS::C1 {
tim.ccmr1_output()
.modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6));
}
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
rcc.clocks.pclk().0
} else {
rcc.clocks.pclk().0 * 2
};
let ticks = tclk / freq.into().0;
let psc = u16((ticks - 1) / (1 << 16)).unwrap();
tim.psc.write(|w| w.psc().bits(psc));
let arr = u16(ticks / u32(psc + 1)).unwrap();
tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
tim.cr1.modify(|_, w| w.arpe().set_bit());
tim.cr1.modify(|_, w| w.urs().set_bit());
tim.egr.write(|w| w.ug().set_bit());
tim.cr1.modify(|_, w| w.urs().clear_bit());
tim.bdtr.modify(|_, w| w.aoe().set_bit());
tim.cr1.write(|w| w.opm().clear_bit().cen().set_bit());
unsafe { MaybeUninit::uninit().assume_init() }
}
impl hal::PwmPin for PwmChannels<TIM17, C1> {
type Duty = u16;
fn disable(&mut self) {
unsafe { (*(TIM17::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) };
}
fn enable(&mut self) {
unsafe { (*(TIM17::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) };
}
fn get_duty(&self) -> u16 {
unsafe { (*TIM17::ptr()).ccr1.read().ccr().bits() as u16 }
}
fn get_max_duty(&self) -> u16 {
unsafe { (*TIM17::ptr()).arr.read().arr().bits() as u16 }
}
fn set_duty(&mut self, duty: u16) {
unsafe { (*TIM17::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
}
}
}
#[cfg(feature = "device-selected")]
pub mod rcc {
use crate::pac::RCC;
use crate::time::Hertz;
/// Extension trait that sets up the `RCC` peripheral
pub trait RccExt {
/// Configure the clocks of the RCC peripheral
fn configure(self) -> CFGR;
}
impl RccExt for RCC {
fn configure(self) -> CFGR {
CFGR {
hclk: None,
pclk: None,
sysclk: None,
clock_src: SysClkSource::HSI,
#[cfg(feature = "stm32f070")]
usb_src: USBClockSource::Disabled,
rcc: self,
}
}
}
/// Constrained RCC peripheral
pub struct Rcc {
pub clocks: Clocks,
pub(crate) regs: RCC,
}
pub enum HSEBypassMode {
/// Not bypassed: for crystals
NotBypassed,
/// Bypassed: for external clock sources
Bypassed,
}
#[cfg(any(
feature = "stm32f042",
feature = "stm32f048",
feature = "stm32f070",
feature = "stm32f072",
feature = "stm32f078",
))]
pub enum USBClockSource {
#[cfg(feature = "stm32f070")]
/// USB peripheral's tranceiver is disabled
Disabled,
/// PLL output is used as USB peripheral tranceiver clock
PLL,
}
/// RCC for F0x0 devices
#[cfg(any(feature = "stm32f030", feature = "stm32f070",))]
mod inner {
use crate::pac::{rcc::cfgr::SW_A, RCC};
pub(super) const HSI: u32 = 8_000_000;
#[cfg(any(
feature = "stm32f030x4",
feature = "stm32f030x6",
feature = "stm32f030x8",
feature = "stm32f070",
feature = "stm32f030xc"
))]
pub(super) const RCC_PLLSRC_PREDIV1_SUPPORT: bool = false;
pub(super) enum SysClkSource {
HSI,
/// High-speed external clock(freq,bypassed)
HSE(u32, super::HSEBypassMode),
}
pub(super) fn get_freq(c_src: &SysClkSource) -> u32 {
match c_src {
SysClkSource::HSE(freq, _) => *freq,
_ => HSI,
}
}
pub(super) fn enable_clock(rcc: &mut RCC, c_src: &SysClkSource) {
match c_src {
SysClkSource::HSE(_, bypassed) => {
match bypassed {
super::HSEBypassMode::NotBypassed => {
rcc.cr
.modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed());
}
super::HSEBypassMode::Bypassed => {
rcc.cr
.modify(|_, w| w.csson().on().hseon().on().hsebyp().bypassed());
}
}
while !rcc.cr.read().hserdy().bit_is_set() {}
}
SysClkSource::HSI => {
rcc.cr.write(|w| w.hsion().set_bit());
while rcc.cr.read().hsirdy().bit_is_clear() {}
}
}
}
pub(super) fn enable_pll(
rcc: &mut RCC,
c_src: &SysClkSource,
pllmul_bits: u8,
ppre_bits: u8,
hpre_bits: u8,
) {
let pllsrc_bit: bool = match c_src {
SysClkSource::HSI => false,
SysClkSource::HSE(_, _) => true,
};
rcc.cfgr
.modify(|_, w| w.pllsrc().bit(pllsrc_bit).pllmul().bits(pllmul_bits));
rcc.cr.modify(|_, w| w.pllon().set_bit());
while rcc.cr.read().pllrdy().bit_is_clear() {}
rcc.cfgr.modify(|_, w| unsafe {
w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll()
});
}
pub(super) fn get_sww(c_src: &SysClkSource) -> SW_A {
match c_src {
SysClkSource::HSI => SW_A::HSI,
SysClkSource::HSE(_, _) => SW_A::HSE,
}
}
}
use self::inner::SysClkSource;
pub struct CFGR {
hclk: Option<u32>,
pclk: Option<u32>,
sysclk: Option<u32>,
clock_src: SysClkSource,
#[cfg(any(
feature = "stm32f042",
feature = "stm32f048",
feature = "stm32f070",
feature = "stm32f072",
feature = "stm32f078",
))]
usb_src: USBClockSource,
rcc: RCC,
}
impl CFGR {
pub fn hse<F>(mut self, freq: F, bypass: HSEBypassMode) -> Self
where
F: Into<Hertz>,
{
self.clock_src = SysClkSource::HSE(freq.into().0, bypass);
self
}
pub fn hclk<F>(mut self, freq: F) -> Self
where
F: Into<Hertz>,
{
self.hclk = Some(freq.into().0);
self
}
pub fn pclk<F>(mut self, freq: F) -> Self
where
F: Into<Hertz>,
{
self.pclk = Some(freq.into().0);
self
}
pub fn sysclk<F>(mut self, freq: F) -> Self
where
F: Into<Hertz>,
{
self.sysclk = Some(freq.into().0);
self
}
#[cfg(any(
feature = "stm32f042",
feature = "stm32f048",
feature = "stm32f070",
feature = "stm32f072",
feature = "stm32f078",
))]
/// Set the USB clock source (only valid for STM32F0xx with USB)
pub fn usbsrc(mut self, src: USBClockSource) -> Self {
self.usb_src = src;
self
}
pub fn freeze(mut self, flash: &mut crate::pac::FLASH) -> Rcc {
let sysclk = self.sysclk.unwrap_or(self::inner::HSI);
let r_sysclk;
let pllmul_bits;
let src_clk_freq = self::inner::get_freq(&self.clock_src);
if sysclk == src_clk_freq {
pllmul_bits = None;
r_sysclk = src_clk_freq;
} else {
let pllprediv = match (&self.clock_src, self::inner::RCC_PLLSRC_PREDIV1_SUPPORT) {
(self::inner::SysClkSource::HSI, false) => 2,
(_, _) => 1,
};
let pllmul = (2 * pllprediv * self.sysclk.unwrap_or(src_clk_freq) + src_clk_freq)
/ src_clk_freq
/ 2;
let pllmul = core::cmp::min(core::cmp::max(pllmul, 2), 16);
r_sysclk = pllmul * src_clk_freq / pllprediv;
pllmul_bits = Some(pllmul as u8 - 2)
}
let hpre_bits = self
.hclk
.map(|hclk| match r_sysclk / hclk {
0 => ::core::panicking::panic("internal error: entered unreachable code"),
1 => 0b0111,
2 => 0b1000,
3..=5 => 0b1001,
6..=11 => 0b1010,
12..=39 => 0b1011,
40..=95 => 0b1100,
96..=191 => 0b1101,
192..=383 => 0b1110,
_ => 0b1111,
})
.unwrap_or(0b0111);
let hclk = r_sysclk / (1 << (hpre_bits - 0b0111));
let ppre_bits = self
.pclk
.map(|pclk| match hclk / pclk {
0 => ::core::panicking::panic("internal error: entered unreachable code"),
1 => 0b011,
2 => 0b100,
3..=5 => 0b101,
6..=11 => 0b110,
_ => 0b111,
})
.unwrap_or(0b011);
let ppre: u8 = 1 << (ppre_bits - 0b011);
let pclk = hclk / cast::u32(ppre);
unsafe {
flash.acr.write(|w| {
w.latency().bits(if r_sysclk <= 24_000_000 {
0b000
} else if r_sysclk <= 48_000_000 {
0b001
} else {
0b010
})
})
}
self::inner::enable_clock(&mut self.rcc, &self.clock_src);
#[cfg(feature = "stm32f070")]
{
match self.usb_src {
USBClockSource::Disabled => self.rcc.cfgr3.modify(|_, w| w.usbsw().clear_bit()),
USBClockSource::PLL => self.rcc.cfgr3.modify(|_, w| w.usbsw().set_bit()),
}
}
if let Some(pllmul_bits) = pllmul_bits {
self::inner::enable_pll(
&mut self.rcc,
&self.clock_src,
pllmul_bits,
ppre_bits,
hpre_bits,
);
} else {
let sw_var = self::inner::get_sww(&self.clock_src);
self.rcc.cfgr.modify(|_, w| unsafe {
w.ppre()
.bits(ppre_bits)
.hpre()
.bits(hpre_bits)
.sw()
.variant(sw_var)
});
}
Rcc {
clocks: Clocks {
hclk: Hertz(hclk),
pclk: Hertz(pclk),
sysclk: Hertz(sysclk),
},
regs: self.rcc,
}
}
}
/// Frozen clock frequencies
///
/// The existence of this value indicates that the clock configuration can no longer be changed
pub struct Clocks {
hclk: Hertz,
pclk: Hertz,
sysclk: Hertz,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for Clocks {
#[inline]
fn clone(&self) -> Clocks {
{
let _: ::core::clone::AssertParamIsClone<Hertz>;
let _: ::core::clone::AssertParamIsClone<Hertz>;
let _: ::core::clone::AssertParamIsClone<Hertz>;
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for Clocks {}
impl Clocks {
/// Returns the frequency of the AHB
pub fn hclk(&self) -> Hertz {
self.hclk
}
/// Returns the frequency of the APB
pub fn pclk(&self) -> Hertz {
self.pclk
}
/// Returns the system (core) frequency
pub fn sysclk(&self) -> Hertz {
self.sysclk
}
}
}
#[cfg(feature = "device-selected")]
pub mod serial {
//! API for the integrated USART ports
//!
//! This only implements the usual asynchronous bidirectional 8-bit transfers.
//!
//! It's possible to use a read-only/write-only serial implementation with
//! `usartXrx`/`usartXtx`.
//!
//! # Examples
//! Echo
//! ``` no_run
//! use stm32f0xx_hal as hal;
//!
//! use crate::hal::prelude::*;
//! use crate::hal::serial::Serial;
//! use crate::hal::pac;
//!
//! use nb::block;
//!
//! cortex_m::interrupt::free(|cs| {
//! let rcc = p.RCC.configure().sysclk(48.mhz()).freeze();
//!
//! let gpioa = p.GPIOA.split(&mut rcc);
//!
//! let tx = gpioa.pa9.into_alternate_af1(cs);
//! let rx = gpioa.pa10.into_alternate_af1(cs);
//!
//! let mut serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc);
//!
//! loop {
//! let received = block!(serial.read()).unwrap();
//! block!(serial.write(received)).ok();
//! }
//! });
//! ```
//!
//! Hello World
//! ``` no_run
//! use stm32f0xx_hal as hal;
//!
//! use crate::hal::prelude::*;
//! use crate::hal::serial::Serial;
//! use crate::hal::pac;
//!
//! use nb::block;
//!
//! cortex_m::interrupt::free(|cs| {
//! let rcc = p.RCC.configure().sysclk(48.mhz()).freeze();
//!
//! let gpioa = p.GPIOA.split(&mut rcc);
//!
//! let tx = gpioa.pa9.into_alternate_af1(cs);
//!
//! let mut serial = Serial::usart1tx(p.USART1, tx, 115_200.bps(), &mut rcc);
//!
//! loop {
//! serial.write_str("Hello World!\r\n");
//! }
//! });
//! ```
use core::{
convert::Infallible,
fmt::{Result, Write},
ops::Deref,
};
use embedded_hal::prelude::*;
use crate::{gpio::*, rcc::Rcc, time::Bps};
use core::marker::PhantomData;
/// Serial error
#[non_exhaustive]
pub enum Error {
/// Framing error
Framing,
/// Noise error
Noise,
/// RX buffer overrun
Overrun,
/// Parity check error
Parity,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for Error {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match (&*self,) {
(&Error::Framing,) => ::core::fmt::Formatter::write_str(f, "Framing"),
(&Error::Noise,) => ::core::fmt::Formatter::write_str(f, "Noise"),
(&Error::Overrun,) => ::core::fmt::Formatter::write_str(f, "Overrun"),
(&Error::Parity,) => ::core::fmt::Formatter::write_str(f, "Parity"),
}
}
}
/// Interrupt event
pub enum Event {
/// New data has been received
Rxne,
/// New data can be sent
Txe,
/// Idle line state detected
Idle,
}
pub trait TxPin<USART> {}
pub trait RxPin<USART> {}
impl TxPin<crate::pac::USART1> for gpioa::PA9<Alternate<AF1>> {}
impl TxPin<crate::pac::USART1> for gpiob::PB6<Alternate<AF0>> {}
impl RxPin<crate::pac::USART1> for gpioa::PA10<Alternate<AF1>> {}
impl RxPin<crate::pac::USART1> for gpiob::PB7<Alternate<AF0>> {}
impl TxPin<crate::pac::USART2> for gpioa::PA2<Alternate<AF1>> {}
impl TxPin<crate::pac::USART2> for gpioa::PA14<Alternate<AF1>> {}
impl RxPin<crate::pac::USART2> for gpioa::PA3<Alternate<AF1>> {}
impl RxPin<crate::pac::USART2> for gpioa::PA15<Alternate<AF1>> {}
/// Serial abstraction
pub struct Serial<USART, TXPIN, RXPIN> {
usart: USART,
pins: (TXPIN, RXPIN),
}
type SerialRegisterBlock = crate::pac::usart1::RegisterBlock;
/// Serial receiver
pub struct Rx<USART> {
usart: *const SerialRegisterBlock,
_instance: PhantomData<USART>,
}
unsafe impl<USART> Send for Rx<USART> {}
/// Serial transmitter
pub struct Tx<USART> {
usart: *const SerialRegisterBlock,
_instance: PhantomData<USART>,
}
unsafe impl<USART> Send for Tx<USART> {}
use crate::pac::USART1;
impl<TXPIN, RXPIN> Serial<USART1, TXPIN, RXPIN>
where
TXPIN: TxPin<USART1>,
RXPIN: RxPin<USART1>,
{
/// Creates a new serial instance
pub fn usart1(usart: USART1, pins: (TXPIN, RXPIN), baud_rate: Bps, rcc: &mut Rcc) -> Self {
let mut serial = Serial { usart, pins };
serial.configure(baud_rate, rcc);
serial
.usart
.cr1
.modify(|_, w| w.te().set_bit().re().set_bit().ue().set_bit());
serial
}
}
impl<TXPIN> Serial<USART1, TXPIN, ()>
where
TXPIN: TxPin<USART1>,
{
/// Creates a new tx-only serial instance
pub fn usart1tx(usart: USART1, txpin: TXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self {
let rxpin = ();
let mut serial = Serial {
usart,
pins: (txpin, rxpin),
};
serial.configure(baud_rate, rcc);
serial
.usart
.cr1
.modify(|_, w| w.te().set_bit().ue().set_bit());
serial
}
}
impl<RXPIN> Serial<USART1, (), RXPIN>
where
RXPIN: RxPin<USART1>,
{
/// Creates a new rx-only serial instance
pub fn usart1rx(usart: USART1, rxpin: RXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self {
let txpin = ();
let mut serial = Serial {
usart,
pins: (txpin, rxpin),
};
serial.configure(baud_rate, rcc);
serial
.usart
.cr1
.modify(|_, w| w.re().set_bit().ue().set_bit());
serial
}
}
impl<TXPIN, RXPIN> Serial<USART1, TXPIN, RXPIN> {
fn configure(&mut self, baud_rate: Bps, rcc: &mut Rcc) {
rcc.regs.apb2enr.modify(|_, w| w.usart1en().set_bit());
let brr = rcc.clocks.pclk().0 / baud_rate.0;
self.usart.brr.write(|w| unsafe { w.bits(brr) });
self.usart.cr2.reset();
self.usart.cr3.reset();
}
/// Starts listening for an interrupt event
pub fn listen(&mut self, event: Event) {
match event {
Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().set_bit()),
Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().set_bit()),
Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().set_bit()),
}
}
/// Stop listening for an interrupt event
pub fn unlisten(&mut self, event: Event) {
match event {
Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().clear_bit()),
Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().clear_bit()),
Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().clear_bit()),
}
}
}
use crate::pac::USART2;
impl<TXPIN, RXPIN> Serial<USART2, TXPIN, RXPIN>
where
TXPIN: TxPin<USART2>,
RXPIN: RxPin<USART2>,
{
/// Creates a new serial instance
pub fn usart2(usart: USART2, pins: (TXPIN, RXPIN), baud_rate: Bps, rcc: &mut Rcc) -> Self {
let mut serial = Serial { usart, pins };
serial.configure(baud_rate, rcc);
serial
.usart
.cr1
.modify(|_, w| w.te().set_bit().re().set_bit().ue().set_bit());
serial
}
}
impl<TXPIN> Serial<USART2, TXPIN, ()>
where
TXPIN: TxPin<USART2>,
{
/// Creates a new tx-only serial instance
pub fn usart2tx(usart: USART2, txpin: TXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self {
let rxpin = ();
let mut serial = Serial {
usart,
pins: (txpin, rxpin),
};
serial.configure(baud_rate, rcc);
serial
.usart
.cr1
.modify(|_, w| w.te().set_bit().ue().set_bit());
serial
}
}
impl<RXPIN> Serial<USART2, (), RXPIN>
where
RXPIN: RxPin<USART2>,
{
/// Creates a new rx-only serial instance
pub fn usart2rx(usart: USART2, rxpin: RXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self {
let txpin = ();
let mut serial = Serial {
usart,
pins: (txpin, rxpin),
};
serial.configure(baud_rate, rcc);
serial
.usart
.cr1
.modify(|_, w| w.re().set_bit().ue().set_bit());
serial
}
}
impl<TXPIN, RXPIN> Serial<USART2, TXPIN, RXPIN> {
fn configure(&mut self, baud_rate: Bps, rcc: &mut Rcc) {
rcc.regs.apb1enr.modify(|_, w| w.usart2en().set_bit());
let brr = rcc.clocks.pclk().0 / baud_rate.0;
self.usart.brr.write(|w| unsafe { w.bits(brr) });
self.usart.cr2.reset();
self.usart.cr3.reset();
}
/// Starts listening for an interrupt event
pub fn listen(&mut self, event: Event) {
match event {
Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().set_bit()),
Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().set_bit()),
Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().set_bit()),
}
}
/// Stop listening for an interrupt event
pub fn unlisten(&mut self, event: Event) {
match event {
Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().clear_bit()),
Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().clear_bit()),
Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().clear_bit()),
}
}
}
impl<USART> embedded_hal::serial::Read<u8> for Rx<USART>
where
USART: Deref<Target = SerialRegisterBlock>,
{
type Error = Error;
/// Tries to read a byte from the uart
fn read(&mut self) -> nb::Result<u8, Error> {
read(self.usart)
}
}
impl<USART, TXPIN, RXPIN> embedded_hal::serial::Read<u8> for Serial<USART, TXPIN, RXPIN>
where
USART: Deref<Target = SerialRegisterBlock>,
RXPIN: RxPin<USART>,
{
type Error = Error;
/// Tries to read a byte from the uart
fn read(&mut self) -> nb::Result<u8, Error> {
read(&*self.usart)
}
}
impl<USART> embedded_hal::serial::Write<u8> for Tx<USART>
where
USART: Deref<Target = SerialRegisterBlock>,
{
type Error = Infallible;
/// Ensures that none of the previously written words are still buffered
fn flush(&mut self) -> nb::Result<(), Self::Error> {
flush(self.usart)
}
/// Tries to write a byte to the uart
/// Fails if the transmit buffer is full
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
write(self.usart, byte)
}
}
impl<USART, TXPIN, RXPIN> embedded_hal::serial::Write<u8> for Serial<USART, TXPIN, RXPIN>
where
USART: Deref<Target = SerialRegisterBlock>,
TXPIN: TxPin<USART>,
{
type Error = Infallible;
/// Ensures that none of the previously written words are still buffered
fn flush(&mut self) -> nb::Result<(), Self::Error> {
flush(&*self.usart)
}
/// Tries to write a byte to the uart
/// Fails if the transmit buffer is full
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
write(&*self.usart, byte)
}
}
impl<USART, TXPIN, RXPIN> Serial<USART, TXPIN, RXPIN>
where
USART: Deref<Target = SerialRegisterBlock>,
{
/// Splits the UART Peripheral in a Tx and an Rx part
/// This is required for sending/receiving
pub fn split(self) -> (Tx<USART>, Rx<USART>)
where
TXPIN: TxPin<USART>,
RXPIN: RxPin<USART>,
{
(
Tx {
usart: &*self.usart,
_instance: PhantomData,
},
Rx {
usart: &*self.usart,
_instance: PhantomData,
},
)
}
pub fn release(self) -> (USART, (TXPIN, RXPIN)) {
(self.usart, self.pins)
}
}
impl<USART> Write for Tx<USART>
where
Tx<USART>: embedded_hal::serial::Write<u8>,
{
fn write_str(&mut self, s: &str) -> Result {
s.as_bytes()
.iter()
.try_for_each(|c| loop {
#[allow(unreachable_patterns)]
match self.write(*c) {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
})
.map_err(|_| core::fmt::Error)
}
}
impl<USART, TXPIN, RXPIN> Write for Serial<USART, TXPIN, RXPIN>
where
USART: Deref<Target = SerialRegisterBlock>,
TXPIN: TxPin<USART>,
{
fn write_str(&mut self, s: &str) -> Result {
s.as_bytes()
.iter()
.try_for_each(|c| loop {
#[allow(unreachable_patterns)]
match self.write(*c) {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
})
.map_err(|_| core::fmt::Error)
}
}
/// Ensures that none of the previously written words are still buffered
fn flush(usart: *const SerialRegisterBlock) -> nb::Result<(), Infallible> {
let isr = unsafe { (*usart).isr.read() };
if isr.tc().bit_is_set() {
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
/// Tries to write a byte to the UART
/// Returns `Err(WouldBlock)` if the transmit buffer is full
fn write(usart: *const SerialRegisterBlock, byte: u8) -> nb::Result<(), Infallible> {
let isr = unsafe { (*usart).isr.read() };
if isr.txe().bit_is_set() {
unsafe { (*usart).tdr.write(|w| w.tdr().bits(byte as u16)) }
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
/// Tries to read a byte from the UART
fn read(usart: *const SerialRegisterBlock) -> nb::Result<u8, Error> {
let isr = unsafe { (*usart).isr.read() };
let icr = unsafe { &(*usart).icr };
if isr.pe().bit_is_set() {
icr.write(|w| w.pecf().set_bit());
Err(nb::Error::Other(Error::Parity))
} else if isr.fe().bit_is_set() {
icr.write(|w| w.fecf().set_bit());
Err(nb::Error::Other(Error::Framing))
} else if isr.nf().bit_is_set() {
icr.write(|w| w.ncf().set_bit());
Err(nb::Error::Other(Error::Noise))
} else if isr.ore().bit_is_set() {
icr.write(|w| w.orecf().set_bit());
Err(nb::Error::Other(Error::Overrun))
} else if isr.rxne().bit_is_set() {
Ok(unsafe { (*usart).rdr.read().rdr().bits() as u8 })
} else {
Err(nb::Error::WouldBlock)
}
}
}
#[cfg(feature = "device-selected")]
pub mod spi {
//! API for the integrate SPI peripherals
//!
//! The spi bus acts as the master (generating the clock) and you need to handle the CS separately.
//!
//! The most significant bit is transmitted first & only 8-bit transfers are supported
//!
//! # Example
//! Echo incoming data in the next transfer
//! ``` no_run
//! use stm32f0xx_hal as hal;
//!
//! use crate::hal::pac;
//! use crate::hal::prelude::*;
//! use crate::hal::spi::{Spi, Mode, Phase, Polarity};
//!
//! cortex_m::interrupt::free(|cs| {
//! let mut p = pac::Peripherals::take().unwrap();
//! let mut rcc = p.RCC.constrain().freeze(&mut p.FLASH);
//!
//! let gpioa = p.GPIOA.split(&mut rcc);
//!
//! // Configure pins for SPI
//! let sck = gpioa.pa5.into_alternate_af0(cs);
//! let miso = gpioa.pa6.into_alternate_af0(cs);
//! let mosi = gpioa.pa7.into_alternate_af0(cs);
//!
//! // Configure SPI with 1MHz rate
//! let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), Mode {
//! polarity: Polarity::IdleHigh,
//! phase: Phase::CaptureOnSecondTransition,
//! }, 1.mhz(), &mut rcc);
//!
//! let mut data = [0];
//! loop {
//! spi.transfer(&mut data).unwrap();
//! }
//! });
//! ```
use core::marker::PhantomData;
use core::{ops::Deref, ptr};
pub use embedded_hal::spi::{Mode, Phase, Polarity};
use crate::pac::SPI1;
use crate::gpio::*;
use crate::rcc::{Clocks, Rcc};
use crate::time::Hertz;
/// Typestate for 8-bit transfer size
pub struct EightBit;
/// Typestate for 16-bit transfer size
pub struct SixteenBit;
/// SPI error
#[non_exhaustive]
pub enum Error {
/// Overrun occurred
Overrun,
/// Mode fault occurred
ModeFault,
/// CRC error
Crc,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for Error {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match (&*self,) {
(&Error::Overrun,) => ::core::fmt::Formatter::write_str(f, "Overrun"),
(&Error::ModeFault,) => ::core::fmt::Formatter::write_str(f, "ModeFault"),
(&Error::Crc,) => ::core::fmt::Formatter::write_str(f, "Crc"),
}
}
}
/// SPI abstraction
pub struct Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, WIDTH> {
spi: SPI,
pins: (SCKPIN, MISOPIN, MOSIPIN),
_width: PhantomData<WIDTH>,
}
pub trait SckPin<SPI> {}
pub trait MisoPin<SPI> {}
pub trait MosiPin<SPI> {}
impl SckPin<crate::pac::SPI1> for gpioa::PA5<Alternate<AF0>> {}
impl SckPin<crate::pac::SPI1> for gpiob::PB3<Alternate<AF0>> {}
impl MisoPin<crate::pac::SPI1> for gpioa::PA6<Alternate<AF0>> {}
impl MisoPin<crate::pac::SPI1> for gpiob::PB4<Alternate<AF0>> {}
impl MosiPin<crate::pac::SPI1> for gpioa::PA7<Alternate<AF0>> {}
impl MosiPin<crate::pac::SPI1> for gpiob::PB5<Alternate<AF0>> {}
impl<SCKPIN, MISOPIN, MOSIPIN> Spi<SPI1, SCKPIN, MISOPIN, MOSIPIN, EightBit> {
/// Creates a new spi instance
pub fn spi1<F>(
spi: SPI1,
pins: (SCKPIN, MISOPIN, MOSIPIN),
mode: Mode,
speed: F,
rcc: &mut Rcc,
) -> Self
where
SCKPIN: SckPin<SPI1>,
MISOPIN: MisoPin<SPI1>,
MOSIPIN: MosiPin<SPI1>,
F: Into<Hertz>,
{
rcc.regs.apb2enr.modify(|_, w| w.spi1en().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.spi1rst().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.spi1rst().clear_bit());
Spi::<SPI1, SCKPIN, MISOPIN, MOSIPIN, EightBit> {
spi,
pins,
_width: PhantomData,
}
.spi_init(mode, speed, rcc.clocks)
.into_8bit_width()
}
}
#[allow(dead_code)]
type SpiRegisterBlock = crate::pac::spi1::RegisterBlock;
impl<SPI, SCKPIN, MISOPIN, MOSIPIN, WIDTH> Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, WIDTH>
where
SPI: Deref<Target = SpiRegisterBlock>,
{
fn spi_init<F>(self, mode: Mode, speed: F, clocks: Clocks) -> Self
where
F: Into<Hertz>,
{
self.spi.cr1.modify(|_, w| w.spe().clear_bit());
let br = match clocks.pclk().0 / speed.into().0 {
0 => ::core::panicking::panic("internal error: entered unreachable code"),
1..=2 => 0b000,
3..=5 => 0b001,
6..=11 => 0b010,
12..=23 => 0b011,
24..=47 => 0b100,
48..=95 => 0b101,
96..=191 => 0b110,
_ => 0b111,
};
self.spi.cr1.write(|w| {
w.cpha()
.bit(mode.phase == Phase::CaptureOnSecondTransition)
.cpol()
.bit(mode.polarity == Polarity::IdleHigh)
.mstr()
.set_bit()
.br()
.bits(br)
.lsbfirst()
.clear_bit()
.ssm()
.set_bit()
.ssi()
.set_bit()
.rxonly()
.clear_bit()
.bidimode()
.clear_bit()
.spe()
.set_bit()
});
self
}
pub fn into_8bit_width(self) -> Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, EightBit> {
self.spi
.cr2
.write(|w| w.frxth().set_bit().ds().eight_bit().ssoe().clear_bit());
Spi {
spi: self.spi,
pins: self.pins,
_width: PhantomData,
}
}
pub fn into_16bit_width(self) -> Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, SixteenBit> {
self.spi
.cr2
.write(|w| w.frxth().set_bit().ds().sixteen_bit().ssoe().clear_bit());
Spi {
spi: self.spi,
pins: self.pins,
_width: PhantomData,
}
}
fn set_send_only(&mut self) {
self.spi
.cr1
.modify(|_, w| w.bidimode().set_bit().bidioe().set_bit());
}
fn set_bidi(&mut self) {
self.spi
.cr1
.modify(|_, w| w.bidimode().clear_bit().bidioe().clear_bit());
}
fn check_read(&mut self) -> nb::Result<(), Error> {
let sr = self.spi.sr.read();
Err(if sr.ovr().bit_is_set() {
nb::Error::Other(Error::Overrun)
} else if sr.modf().bit_is_set() {
nb::Error::Other(Error::ModeFault)
} else if sr.crcerr().bit_is_set() {
nb::Error::Other(Error::Crc)
} else if sr.rxne().bit_is_set() {
return Ok(());
} else {
nb::Error::WouldBlock
})
}
fn send_buffer_size(&mut self) -> u8 {
match self.spi.sr.read().ftlvl().bits() {
0 => 4,
1 => 3,
2 => 2,
_ => 0,
}
}
fn check_send(&mut self) -> nb::Result<(), Error> {
let sr = self.spi.sr.read();
Err(if sr.ovr().bit_is_set() {
nb::Error::Other(Error::Overrun)
} else if sr.modf().bit_is_set() {
nb::Error::Other(Error::ModeFault)
} else if sr.crcerr().bit_is_set() {
nb::Error::Other(Error::Crc)
} else if sr.txe().bit_is_set() && sr.bsy().bit_is_clear() {
return Ok(());
} else {
nb::Error::WouldBlock
})
}
fn read_u8(&mut self) -> u8 {
unsafe { ptr::read_volatile(&self.spi.dr as *const _ as *const u8) }
}
fn send_u8(&mut self, byte: u8) {
unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) }
}
fn read_u16(&mut self) -> u16 {
unsafe { ptr::read_volatile(&self.spi.dr as *const _ as *const u16) }
}
fn send_u16(&mut self, byte: u16) {
unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u16, byte) }
}
pub fn release(self) -> (SPI, (SCKPIN, MISOPIN, MOSIPIN)) {
(self.spi, self.pins)
}
}
impl<SPI, SCKPIN, MISOPIN, MOSIPIN> ::embedded_hal::blocking::spi::Transfer<u8>
for Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, EightBit>
where
SPI: Deref<Target = SpiRegisterBlock>,
{
type Error = Error;
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
self.set_bidi();
for word in words.iter_mut() {
loop {
#[allow(unreachable_patterns)]
match self.check_send() {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
}?;
self.send_u8(*word);
loop {
#[allow(unreachable_patterns)]
match self.check_read() {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
}?;
*word = self.read_u8();
}
Ok(words)
}
}
impl<SPI, SCKPIN, MISOPIN, MOSIPIN> ::embedded_hal::blocking::spi::Write<u8>
for Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, EightBit>
where
SPI: Deref<Target = SpiRegisterBlock>,
{
type Error = Error;
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
let mut bufcap: u8 = 0;
self.set_send_only();
loop {
#[allow(unreachable_patterns)]
match self.check_send() {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
}?;
for word in words {
while bufcap == 0 {
bufcap = self.send_buffer_size();
}
self.send_u8(*word);
bufcap -= 1;
}
loop {
#[allow(unreachable_patterns)]
match self.check_send() {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
}
.ok();
Ok(())
}
}
impl<SPI, SCKPIN, MISOPIN, MOSIPIN> ::embedded_hal::blocking::spi::Transfer<u16>
for Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, SixteenBit>
where
SPI: Deref<Target = SpiRegisterBlock>,
{
type Error = Error;
fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
self.set_bidi();
for word in words.iter_mut() {
loop {
#[allow(unreachable_patterns)]
match self.check_send() {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
}?;
self.send_u16(*word);
loop {
#[allow(unreachable_patterns)]
match self.check_read() {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
}?;
*word = self.read_u16();
}
Ok(words)
}
}
impl<SPI, SCKPIN, MISOPIN, MOSIPIN> ::embedded_hal::blocking::spi::Write<u16>
for Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, SixteenBit>
where
SPI: Deref<Target = SpiRegisterBlock>,
{
type Error = Error;
fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
self.set_send_only();
for word in words {
loop {
#[allow(unreachable_patterns)]
match self.check_send() {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
}?;
self.send_u16(*word);
}
loop {
#[allow(unreachable_patterns)]
match self.check_send() {
Err(::nb::Error::Other(e)) =>
{
#[allow(unreachable_code)]
break Err(e)
}
Err(::nb::Error::WouldBlock) => {}
Ok(x) => break Ok(x),
}
}
.ok();
Ok(())
}
}
}
#[cfg(feature = "device-selected")]
pub mod time {
/// Bits per second
pub struct Bps(pub u32);
impl ::core::marker::StructuralPartialEq for Bps {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for Bps {
#[inline]
fn eq(&self, other: &Bps) -> bool {
match *other {
Bps(ref __self_1_0) => match *self {
Bps(ref __self_0_0) => (*__self_0_0) == (*__self_1_0),
},
}
}
#[inline]
fn ne(&self, other: &Bps) -> bool {
match *other {
Bps(ref __self_1_0) => match *self {
Bps(ref __self_0_0) => (*__self_0_0) != (*__self_1_0),
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialOrd for Bps {
#[inline]
fn partial_cmp(&self, other: &Bps) -> ::core::option::Option<::core::cmp::Ordering> {
match *other {
Bps(ref __self_1_0) => match *self {
Bps(ref __self_0_0) => {
match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0)) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) => {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
}
cmp => cmp,
}
}
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for Bps {
#[inline]
fn clone(&self) -> Bps {
{
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for Bps {}
pub struct Hertz(pub u32);
impl ::core::marker::StructuralPartialEq for Hertz {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for Hertz {
#[inline]
fn eq(&self, other: &Hertz) -> bool {
match *other {
Hertz(ref __self_1_0) => match *self {
Hertz(ref __self_0_0) => (*__self_0_0) == (*__self_1_0),
},
}
}
#[inline]
fn ne(&self, other: &Hertz) -> bool {
match *other {
Hertz(ref __self_1_0) => match *self {
Hertz(ref __self_0_0) => (*__self_0_0) != (*__self_1_0),
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialOrd for Hertz {
#[inline]
fn partial_cmp(&self, other: &Hertz) -> ::core::option::Option<::core::cmp::Ordering> {
match *other {
Hertz(ref __self_1_0) => match *self {
Hertz(ref __self_0_0) => {
match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0)) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) => {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
}
cmp => cmp,
}
}
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for Hertz {
#[inline]
fn clone(&self) -> Hertz {
{
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for Hertz {}
pub struct KiloHertz(pub u32);
impl ::core::marker::StructuralPartialEq for KiloHertz {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for KiloHertz {
#[inline]
fn eq(&self, other: &KiloHertz) -> bool {
match *other {
KiloHertz(ref __self_1_0) => match *self {
KiloHertz(ref __self_0_0) => (*__self_0_0) == (*__self_1_0),
},
}
}
#[inline]
fn ne(&self, other: &KiloHertz) -> bool {
match *other {
KiloHertz(ref __self_1_0) => match *self {
KiloHertz(ref __self_0_0) => (*__self_0_0) != (*__self_1_0),
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialOrd for KiloHertz {
#[inline]
fn partial_cmp(&self, other: &KiloHertz) -> ::core::option::Option<::core::cmp::Ordering> {
match *other {
KiloHertz(ref __self_1_0) => match *self {
KiloHertz(ref __self_0_0) => {
match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0)) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) => {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
}
cmp => cmp,
}
}
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for KiloHertz {
#[inline]
fn clone(&self) -> KiloHertz {
{
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for KiloHertz {}
pub struct MegaHertz(pub u32);
impl ::core::marker::StructuralPartialEq for MegaHertz {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for MegaHertz {
#[inline]
fn eq(&self, other: &MegaHertz) -> bool {
match *other {
MegaHertz(ref __self_1_0) => match *self {
MegaHertz(ref __self_0_0) => (*__self_0_0) == (*__self_1_0),
},
}
}
#[inline]
fn ne(&self, other: &MegaHertz) -> bool {
match *other {
MegaHertz(ref __self_1_0) => match *self {
MegaHertz(ref __self_0_0) => (*__self_0_0) != (*__self_1_0),
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialOrd for MegaHertz {
#[inline]
fn partial_cmp(&self, other: &MegaHertz) -> ::core::option::Option<::core::cmp::Ordering> {
match *other {
MegaHertz(ref __self_1_0) => match *self {
MegaHertz(ref __self_0_0) => {
match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0)) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) => {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
}
cmp => cmp,
}
}
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for MegaHertz {
#[inline]
fn clone(&self) -> MegaHertz {
{
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for MegaHertz {}
/// Extension trait that adds convenience methods to the `u32` type
pub trait U32Ext {
/// Wrap in `Bps`
fn bps(self) -> Bps;
/// Wrap in `Hertz`
fn hz(self) -> Hertz;
/// Wrap in `KiloHertz`
fn khz(self) -> KiloHertz;
/// Wrap in `MegaHertz`
fn mhz(self) -> MegaHertz;
}
impl U32Ext for u32 {
fn bps(self) -> Bps {
Bps(self)
}
fn hz(self) -> Hertz {
Hertz(self)
}
fn khz(self) -> KiloHertz {
KiloHertz(self)
}
fn mhz(self) -> MegaHertz {
MegaHertz(self)
}
}
impl Into<Hertz> for KiloHertz {
fn into(self) -> Hertz {
Hertz(self.0 * 1_000)
}
}
impl Into<Hertz> for MegaHertz {
fn into(self) -> Hertz {
Hertz(self.0 * 1_000_000)
}
}
impl Into<KiloHertz> for MegaHertz {
fn into(self) -> KiloHertz {
KiloHertz(self.0 * 1_000)
}
}
}
#[cfg(feature = "device-selected")]
pub mod timers {
//! API for the integrated timers
//!
//! This only implements basic functions, a lot of things are missing
//!
//! # Example
//! Blink the led with 1Hz
//! ``` no_run
//! use stm32f0xx_hal as hal;
//!
//! use crate::hal::pac;
//! use crate::hal::prelude::*;
//! use crate::hal::time::*;
//! use crate::hal::timers::*;
//! use nb::block;
//!
//! cortex_m::interrupt::free(|cs| {
//! let mut p = pac::Peripherals::take().unwrap();
//! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH);
//!
//! let gpioa = p.GPIOA.split(&mut rcc);
//!
//! let mut led = gpioa.pa1.into_push_pull_pull_output(cs);
//!
//! let mut timer = Timer::tim1(p.TIM1, Hertz(1), &mut rcc);
//! loop {
//! led.toggle();
//! block!(timer.wait()).ok();
//! }
//! });
//! ```
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use crate::rcc::{Clocks, Rcc};
use crate::time::Hertz;
use embedded_hal::timer::{CountDown, Periodic};
use void::Void;
/// Hardware timers
pub struct Timer<TIM> {
clocks: Clocks,
tim: TIM,
}
/// Interrupt events
pub enum Event {
/// Timer timed out / count down ended
TimeOut,
}
impl Timer<SYST> {
/// Configures the SYST clock as a periodic count down timer
pub fn syst<T>(mut syst: SYST, timeout: T, rcc: &Rcc) -> Self
where
T: Into<Hertz>,
{
syst.set_clock_source(SystClkSource::Core);
let mut timer = Timer {
tim: syst,
clocks: rcc.clocks,
};
timer.start(timeout);
timer
}
/// Starts listening for an `event`
pub fn listen(&mut self, event: &Event) {
match event {
Event::TimeOut => self.tim.enable_interrupt(),
}
}
/// Stops listening for an `event`
pub fn unlisten(&mut self, event: &Event) {
match event {
Event::TimeOut => self.tim.disable_interrupt(),
}
}
}
/// Use the systick as a timer
///
/// Be aware that intervals less than 4 Hertz may not function properly
impl CountDown for Timer<SYST> {
type Time = Hertz;
/// Start the timer with a `timeout`
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
let rvr = self.clocks.sysclk().0 / timeout.into().0 - 1;
if !(rvr < (1 << 24)) {
::core::panicking::panic("assertion failed: rvr < (1 << 24)")
};
self.tim.set_reload(rvr);
self.tim.clear_current();
self.tim.enable_counter();
}
/// Return `Ok` if the timer has wrapped
/// Automatically clears the flag and restarts the time
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.has_wrapped() {
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
impl Periodic for Timer<SYST> {}
use crate::pac::TIM1;
impl Timer<TIM1> {
/// Configures a TIM peripheral as a periodic count down timer
pub fn tim1<T>(tim: TIM1, timeout: T, rcc: &mut Rcc) -> Self
where
T: Into<Hertz>,
{
rcc.regs.apb2enr.modify(|_, w| w.tim1en().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim1rst().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim1rst().clear_bit());
let mut timer = Timer {
clocks: rcc.clocks,
tim,
};
timer.start(timeout);
timer
}
/// Starts listening for an `event`
pub fn listen(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().set_bit());
}
}
}
/// Stops listening for an `event`
pub fn unlisten(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().clear_bit());
}
}
}
/// Releases the TIM peripheral
pub fn release(self) -> TIM1 {
let rcc = unsafe { &(*crate::pac::RCC::ptr()) };
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
rcc.apb2enr.modify(|_, w| w.tim1en().clear_bit());
self.tim
}
}
impl CountDown for Timer<TIM1> {
type Time = Hertz;
/// Start the timer with a `timeout`
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
self.tim.cnt.reset();
let frequency = timeout.into().0;
let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 {
self.clocks.pclk().0
} else {
self.clocks.pclk().0 * 2
};
let ticks = tclk / frequency;
let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap();
self.tim.psc.write(|w| w.psc().bits(psc));
let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap();
self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) });
self.tim.cr1.modify(|_, w| w.cen().set_bit());
}
/// Return `Ok` if the timer has wrapped
/// Automatically clears the flag and restarts the time
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.sr.read().uif().bit_is_clear() {
Err(nb::Error::WouldBlock)
} else {
self.tim.sr.modify(|_, w| w.uif().clear_bit());
Ok(())
}
}
}
impl Periodic for Timer<TIM1> {}
use crate::pac::TIM3;
impl Timer<TIM3> {
/// Configures a TIM peripheral as a periodic count down timer
pub fn tim3<T>(tim: TIM3, timeout: T, rcc: &mut Rcc) -> Self
where
T: Into<Hertz>,
{
rcc.regs.apb1enr.modify(|_, w| w.tim3en().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.tim3rst().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.tim3rst().clear_bit());
let mut timer = Timer {
clocks: rcc.clocks,
tim,
};
timer.start(timeout);
timer
}
/// Starts listening for an `event`
pub fn listen(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().set_bit());
}
}
}
/// Stops listening for an `event`
pub fn unlisten(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().clear_bit());
}
}
}
/// Releases the TIM peripheral
pub fn release(self) -> TIM3 {
let rcc = unsafe { &(*crate::pac::RCC::ptr()) };
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
rcc.apb1enr.modify(|_, w| w.tim3en().clear_bit());
self.tim
}
}
impl CountDown for Timer<TIM3> {
type Time = Hertz;
/// Start the timer with a `timeout`
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
self.tim.cnt.reset();
let frequency = timeout.into().0;
let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 {
self.clocks.pclk().0
} else {
self.clocks.pclk().0 * 2
};
let ticks = tclk / frequency;
let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap();
self.tim.psc.write(|w| w.psc().bits(psc));
let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap();
self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) });
self.tim.cr1.modify(|_, w| w.cen().set_bit());
}
/// Return `Ok` if the timer has wrapped
/// Automatically clears the flag and restarts the time
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.sr.read().uif().bit_is_clear() {
Err(nb::Error::WouldBlock)
} else {
self.tim.sr.modify(|_, w| w.uif().clear_bit());
Ok(())
}
}
}
impl Periodic for Timer<TIM3> {}
use crate::pac::TIM14;
impl Timer<TIM14> {
/// Configures a TIM peripheral as a periodic count down timer
pub fn tim14<T>(tim: TIM14, timeout: T, rcc: &mut Rcc) -> Self
where
T: Into<Hertz>,
{
rcc.regs.apb1enr.modify(|_, w| w.tim14en().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.tim14rst().set_bit());
rcc.regs.apb1rstr.modify(|_, w| w.tim14rst().clear_bit());
let mut timer = Timer {
clocks: rcc.clocks,
tim,
};
timer.start(timeout);
timer
}
/// Starts listening for an `event`
pub fn listen(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().set_bit());
}
}
}
/// Stops listening for an `event`
pub fn unlisten(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().clear_bit());
}
}
}
/// Releases the TIM peripheral
pub fn release(self) -> TIM14 {
let rcc = unsafe { &(*crate::pac::RCC::ptr()) };
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
rcc.apb1enr.modify(|_, w| w.tim14en().clear_bit());
self.tim
}
}
impl CountDown for Timer<TIM14> {
type Time = Hertz;
/// Start the timer with a `timeout`
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
self.tim.cnt.reset();
let frequency = timeout.into().0;
let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 {
self.clocks.pclk().0
} else {
self.clocks.pclk().0 * 2
};
let ticks = tclk / frequency;
let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap();
self.tim.psc.write(|w| w.psc().bits(psc));
let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap();
self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) });
self.tim.cr1.modify(|_, w| w.cen().set_bit());
}
/// Return `Ok` if the timer has wrapped
/// Automatically clears the flag and restarts the time
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.sr.read().uif().bit_is_clear() {
Err(nb::Error::WouldBlock)
} else {
self.tim.sr.modify(|_, w| w.uif().clear_bit());
Ok(())
}
}
}
impl Periodic for Timer<TIM14> {}
use crate::pac::TIM16;
impl Timer<TIM16> {
/// Configures a TIM peripheral as a periodic count down timer
pub fn tim16<T>(tim: TIM16, timeout: T, rcc: &mut Rcc) -> Self
where
T: Into<Hertz>,
{
rcc.regs.apb2enr.modify(|_, w| w.tim16en().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim16rst().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim16rst().clear_bit());
let mut timer = Timer {
clocks: rcc.clocks,
tim,
};
timer.start(timeout);
timer
}
/// Starts listening for an `event`
pub fn listen(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().set_bit());
}
}
}
/// Stops listening for an `event`
pub fn unlisten(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().clear_bit());
}
}
}
/// Releases the TIM peripheral
pub fn release(self) -> TIM16 {
let rcc = unsafe { &(*crate::pac::RCC::ptr()) };
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
rcc.apb2enr.modify(|_, w| w.tim16en().clear_bit());
self.tim
}
}
impl CountDown for Timer<TIM16> {
type Time = Hertz;
/// Start the timer with a `timeout`
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
self.tim.cnt.reset();
let frequency = timeout.into().0;
let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 {
self.clocks.pclk().0
} else {
self.clocks.pclk().0 * 2
};
let ticks = tclk / frequency;
let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap();
self.tim.psc.write(|w| w.psc().bits(psc));
let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap();
self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) });
self.tim.cr1.modify(|_, w| w.cen().set_bit());
}
/// Return `Ok` if the timer has wrapped
/// Automatically clears the flag and restarts the time
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.sr.read().uif().bit_is_clear() {
Err(nb::Error::WouldBlock)
} else {
self.tim.sr.modify(|_, w| w.uif().clear_bit());
Ok(())
}
}
}
impl Periodic for Timer<TIM16> {}
use crate::pac::TIM17;
impl Timer<TIM17> {
/// Configures a TIM peripheral as a periodic count down timer
pub fn tim17<T>(tim: TIM17, timeout: T, rcc: &mut Rcc) -> Self
where
T: Into<Hertz>,
{
rcc.regs.apb2enr.modify(|_, w| w.tim17en().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim17rst().set_bit());
rcc.regs.apb2rstr.modify(|_, w| w.tim17rst().clear_bit());
let mut timer = Timer {
clocks: rcc.clocks,
tim,
};
timer.start(timeout);
timer
}
/// Starts listening for an `event`
pub fn listen(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().set_bit());
}
}
}
/// Stops listening for an `event`
pub fn unlisten(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().clear_bit());
}
}
}
/// Releases the TIM peripheral
pub fn release(self) -> TIM17 {
let rcc = unsafe { &(*crate::pac::RCC::ptr()) };
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
rcc.apb2enr.modify(|_, w| w.tim17en().clear_bit());
self.tim
}
}
impl CountDown for Timer<TIM17> {
type Time = Hertz;
/// Start the timer with a `timeout`
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
self.tim.cnt.reset();
let frequency = timeout.into().0;
let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 {
self.clocks.pclk().0
} else {
self.clocks.pclk().0 * 2
};
let ticks = tclk / frequency;
let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap();
self.tim.psc.write(|w| w.psc().bits(psc));
let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap();
self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) });
self.tim.cr1.modify(|_, w| w.cen().set_bit());
}
/// Return `Ok` if the timer has wrapped
/// Automatically clears the flag and restarts the time
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.sr.read().uif().bit_is_clear() {
Err(nb::Error::WouldBlock)
} else {
self.tim.sr.modify(|_, w| w.uif().clear_bit());
Ok(())
}
}
}
impl Periodic for Timer<TIM17> {}
use crate::gpio::{AF0, AF1, AF2, AF4, AF5};
use crate::gpio::{gpioa::*, gpiob::*, Alternate};
pub trait PinC1<TIM> {}
pub trait PinC2<TIM> {}
pub trait PinC3<TIM> {}
pub trait PinC4<TIM> {}
impl PinC1<TIM1> for PA8<Alternate<AF2>> {}
impl PinC2<TIM1> for PA9<Alternate<AF2>> {}
impl PinC3<TIM1> for PA10<Alternate<AF2>> {}
impl PinC4<TIM1> for PA11<Alternate<AF2>> {}
impl PinC1<TIM3> for PA6<Alternate<AF1>> {}
impl PinC2<TIM3> for PA7<Alternate<AF1>> {}
impl PinC1<TIM3> for PB4<Alternate<AF1>> {}
impl PinC2<TIM3> for PB5<Alternate<AF1>> {}
impl PinC3<TIM3> for PB0<Alternate<AF1>> {}
impl PinC4<TIM3> for PB1<Alternate<AF1>> {}
impl PinC1<TIM14> for PA4<Alternate<AF4>> {}
impl PinC1<TIM14> for PA7<Alternate<AF4>> {}
impl PinC1<TIM14> for PB1<Alternate<AF0>> {}
impl PinC1<TIM16> for PA6<Alternate<AF5>> {}
impl PinC1<TIM16> for PB8<Alternate<AF2>> {}
impl PinC1<TIM17> for PA7<Alternate<AF5>> {}
impl PinC1<TIM17> for PB9<Alternate<AF2>> {}
#[cfg(any(
feature = "stm32f030",
feature = "stm32f051",
feature = "stm32f058",
feature = "stm32f070",
feature = "stm32f071",
feature = "stm32f072",
feature = "stm32f078",
feature = "stm32f091",
feature = "stm32f098"
))]
use crate::gpio::gpioc::*;
impl PinC1<TIM3> for PC6<Alternate<AF0>> {}
impl PinC2<TIM3> for PC7<Alternate<AF0>> {}
impl PinC3<TIM3> for PC8<Alternate<AF0>> {}
impl PinC4<TIM3> for PC9<Alternate<AF0>> {}
}
#[cfg(feature = "device-selected")]
pub mod watchdog {
//! API for the IWDG
//!
//! You can activate the watchdog by calling `start` or the setting appropriate
//! device option bit when programming.
//!
//! After activating the watchdog, you'll have to regularly `feed` the watchdog.
//! If more time than `timeout` has gone by since the last `feed`, your
//! microcontroller will be reset.
//!
//! This is useful if you fear that your program may get stuck. In that case it
//! won't feed the watchdog anymore, the watchdog will reset the microcontroller
//! and thus your program will function again.
//!
//! **Attention**:
//!
//! The IWDG runs on a separate 40kHz low-accuracy clock (30kHz-60kHz). You may
//! want to some buffer in your interval.
//!
//! Per default the iwdg continues to run even when you stopped execution of code via a debugger.
//! You may want to disable the watchdog when the cpu is stopped
//!
//! ``` ignore
//! let dbgmcu = p.DBGMCU;
//! dbgmcu.apb1_fz.modify(|_, w| w.dbg_iwdg_stop().set_bit());
//! ```
//!
//! # Example
//! ``` no_run
//! use stm32f0xx_hal as hal;
//!
//! use crate::hal::pac;
//! use crate::hal::prelude::*;
//! use crate::hal:watchdog::Watchdog;
//! use crate::hal:time::Hertz;
//!
//! let mut p = pac::Peripherals::take().unwrap();
//!
//! let mut iwdg = Watchdog::new(p.iwdg);
//! iwdg.start(Hertz(100));
//! loop {}
//! // Whoops, got stuck, the watchdog issues a reset after 10 ms
//! iwdg.feed();
//! ```
use embedded_hal::watchdog;
use crate::pac::IWDG;
use crate::time::Hertz;
/// Watchdog instance
pub struct Watchdog {
iwdg: IWDG,
}
impl watchdog::Watchdog for Watchdog {
/// Feed the watchdog, so that at least one `period` goes by before the next
/// reset
fn feed(&mut self) {
self.iwdg.kr.write(|w| w.key().reset());
}
}
/// Timeout configuration for the IWDG
pub struct IwdgTimeout {
psc: u8,
reload: u16,
}
impl ::core::marker::StructuralPartialEq for IwdgTimeout {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for IwdgTimeout {
#[inline]
fn eq(&self, other: &IwdgTimeout) -> bool {
match *other {
IwdgTimeout {
psc: ref __self_1_0,
reload: ref __self_1_1,
} => match *self {
IwdgTimeout {
psc: ref __self_0_0,
reload: ref __self_0_1,
} => (*__self_0_0) == (*__self_1_0) && (*__self_0_1) == (*__self_1_1),
},
}
}
#[inline]
fn ne(&self, other: &IwdgTimeout) -> bool {
match *other {
IwdgTimeout {
psc: ref __self_1_0,
reload: ref __self_1_1,
} => match *self {
IwdgTimeout {
psc: ref __self_0_0,
reload: ref __self_0_1,
} => (*__self_0_0) != (*__self_1_0) || (*__self_0_1) != (*__self_1_1),
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialOrd for IwdgTimeout {
#[inline]
fn partial_cmp(
&self,
other: &IwdgTimeout,
) -> ::core::option::Option<::core::cmp::Ordering> {
match *other {
IwdgTimeout {
psc: ref __self_1_0,
reload: ref __self_1_1,
} => match *self {
IwdgTimeout {
psc: ref __self_0_0,
reload: ref __self_0_1,
} => match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0))
{
::core::option::Option::Some(::core::cmp::Ordering::Equal) => {
match ::core::cmp::PartialOrd::partial_cmp(
&(*__self_0_1),
&(*__self_1_1),
) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) => {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
}
cmp => cmp,
}
}
cmp => cmp,
},
},
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for IwdgTimeout {
#[inline]
fn clone(&self) -> IwdgTimeout {
{
let _: ::core::clone::AssertParamIsClone<u8>;
let _: ::core::clone::AssertParamIsClone<u16>;
*self
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for IwdgTimeout {}
impl Into<IwdgTimeout> for Hertz {
/// This converts the value so it's usable by the IWDG
/// Due to conversion losses, the specified frequency is a maximum
///
/// It can also only represent values < 10000 Hertz
fn into(self) -> IwdgTimeout {
let mut time = 40_000 / 4 / self.0;
let mut psc = 0;
let mut reload = 0;
while psc < 7 {
reload = time;
if reload < 0x1000 {
break;
}
psc += 1;
time /= 2;
}
let reload = reload as u16;
IwdgTimeout { psc, reload }
}
}
impl Watchdog {
pub fn new(iwdg: IWDG) -> Self {
Self { iwdg }
}
}
impl watchdog::WatchdogEnable for Watchdog {
type Time = IwdgTimeout;
fn start<T>(&mut self, period: T)
where
T: Into<IwdgTimeout>,
{
let time: IwdgTimeout = period.into();
self.iwdg.kr.write(|w| w.key().reset());
self.iwdg.kr.write(|w| w.key().start());
self.iwdg.kr.write(|w| w.key().enable());
while self.iwdg.sr.read().pvu().bit() {}
self.iwdg.pr.write(|w| w.pr().bits(time.psc));
while self.iwdg.sr.read().rvu().bit() {}
self.iwdg.rlr.write(|w| w.rl().bits(time.reload));
while self.iwdg.sr.read().bits() != 0 {}
self.iwdg.kr.write(|w| w.key().reset());
}
}
}
#[cfg(feature = "device-selected")]
#[deprecated(since = "0.17.0", note = "please use `pac` instead")]
pub use pac as stm32;