Update to stm32f0 - 0.6.0 (#52)
* Updated stm32f0 to 0.6.0 and neatened other deps * Adjusted names and removed unneeded unsafe blocks * Overhauled RCC to gate HSI48 correctly and add a selector function for it to CFGR
This commit is contained in:
parent
cc5dbe03e5
commit
1524cb1967
|
@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
- Support for stm32f0x8 line - @jessebraham
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to stm32-rs v0.6.0 - @HarkonenBade
|
||||
|
||||
## [v0.12.0] - 2019-01-13
|
||||
|
||||
### Added
|
||||
|
|
12
Cargo.toml
12
Cargo.toml
|
@ -30,19 +30,13 @@ features = ["stm32f042", "rt"]
|
|||
|
||||
[dependencies]
|
||||
bare-metal = { version = "0.2.4", features = ["const-fn"] }
|
||||
cast = { version = "0.2.2", default-features = false }
|
||||
cortex-m = "0.5.8"
|
||||
cortex-m-rt = "0.6.7"
|
||||
embedded-hal = { version = "0.2.2", features = ["unproven"] }
|
||||
stm32f0 = "0.6.0"
|
||||
nb = "0.1.1"
|
||||
void = { version = "1.0.2", default-features = false }
|
||||
stm32f0 = "0.5.0"
|
||||
|
||||
[dependencies.cast]
|
||||
default-features = false
|
||||
version = "0.2.2"
|
||||
|
||||
[dependencies.embedded-hal]
|
||||
features = ["unproven"]
|
||||
version = "0.2.2"
|
||||
|
||||
[dev-dependencies]
|
||||
panic-halt = "0.2.0"
|
||||
|
|
|
@ -40,7 +40,7 @@ fn main() -> ! {
|
|||
|
||||
let gpioa = p.GPIOA.split(&mut rcc);
|
||||
let gpiob = p.GPIOB.split(&mut rcc);
|
||||
let syscfg = p.SYSCFG_COMP;
|
||||
let syscfg = p.SYSCFG;
|
||||
let exti = p.EXTI;
|
||||
|
||||
// Configure PB1 as input (button)
|
||||
|
@ -57,7 +57,7 @@ fn main() -> ! {
|
|||
|
||||
// Enable external interrupt for PB1
|
||||
syscfg
|
||||
.syscfg_exticr1
|
||||
.exticr1
|
||||
.modify(|_, w| unsafe { w.exti1().bits(1) });
|
||||
|
||||
// Set interrupt request mask for line 1
|
||||
|
|
44
src/adc.rs
44
src/adc.rs
|
@ -84,20 +84,18 @@ pub enum AdcSampleTime {
|
|||
|
||||
impl AdcSampleTime {
|
||||
fn write_bits(self, adc: &mut stm32::ADC) {
|
||||
unsafe {
|
||||
adc.smpr.write(|w| {
|
||||
w.smpr().bits(match self {
|
||||
AdcSampleTime::T_1 => 0b000_u8,
|
||||
AdcSampleTime::T_7 => 0b001_u8,
|
||||
AdcSampleTime::T_13 => 0b010_u8,
|
||||
AdcSampleTime::T_28 => 0b011_u8,
|
||||
AdcSampleTime::T_41 => 0b100_u8,
|
||||
AdcSampleTime::T_55 => 0b101_u8,
|
||||
AdcSampleTime::T_71 => 0b110_u8,
|
||||
AdcSampleTime::T_239 => 0b111_u8,
|
||||
})
|
||||
});
|
||||
}
|
||||
adc.smpr.write(|w| {
|
||||
w.smp().bits(match self {
|
||||
AdcSampleTime::T_1 => 0b000_u8,
|
||||
AdcSampleTime::T_7 => 0b001_u8,
|
||||
AdcSampleTime::T_13 => 0b010_u8,
|
||||
AdcSampleTime::T_28 => 0b011_u8,
|
||||
AdcSampleTime::T_41 => 0b100_u8,
|
||||
AdcSampleTime::T_55 => 0b101_u8,
|
||||
AdcSampleTime::T_71 => 0b110_u8,
|
||||
AdcSampleTime::T_239 => 0b111_u8,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/// Get the default sample time (currently 239.5 cycles)
|
||||
|
@ -161,16 +159,14 @@ pub enum AdcPrecision {
|
|||
|
||||
impl AdcPrecision {
|
||||
fn write_bits(self, adc: &mut stm32::ADC) {
|
||||
unsafe {
|
||||
adc.cfgr1.write(|w| {
|
||||
w.res().bits(match self {
|
||||
AdcPrecision::B_12 => 0b00_u8,
|
||||
AdcPrecision::B_10 => 0b01_u8,
|
||||
AdcPrecision::B_8 => 0b10_u8,
|
||||
AdcPrecision::B_6 => 0b11_u8,
|
||||
})
|
||||
});
|
||||
}
|
||||
adc.cfgr1.write(|w| {
|
||||
w.res().bits(match self {
|
||||
AdcPrecision::B_12 => 0b00_u8,
|
||||
AdcPrecision::B_10 => 0b01_u8,
|
||||
AdcPrecision::B_8 => 0b10_u8,
|
||||
AdcPrecision::B_6 => 0b11_u8,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/// Get the default precision (currently 12 bit precision)
|
||||
|
|
234
src/rcc.rs
234
src/rcc.rs
|
@ -1,4 +1,4 @@
|
|||
use crate::stm32::rcc::cfgr::SWW;
|
||||
use crate::stm32::RCC;
|
||||
use crate::time::Hertz;
|
||||
|
||||
/// Extension trait that sets up the `RCC` peripheral
|
||||
|
@ -7,7 +7,7 @@ pub trait RccExt {
|
|||
fn configure(self) -> CFGR;
|
||||
}
|
||||
|
||||
impl RccExt for crate::stm32::RCC {
|
||||
impl RccExt for RCC {
|
||||
fn configure(self) -> CFGR {
|
||||
CFGR {
|
||||
hclk: None,
|
||||
|
@ -22,24 +22,169 @@ impl RccExt for crate::stm32::RCC {
|
|||
/// Constrained RCC peripheral
|
||||
pub struct Rcc {
|
||||
pub clocks: Clocks,
|
||||
pub(crate) regs: crate::stm32::RCC,
|
||||
pub(crate) regs: RCC,
|
||||
}
|
||||
|
||||
const HSI: u32 = 8_000_000; // Hz
|
||||
const HSI48: u32 = 48_000_000; // Hz - (available on STM32F04x, STM32F07x and STM32F09x devices only)
|
||||
#[cfg(any(feature = "stm32f030",
|
||||
feature = "stm32f070",
|
||||
))]
|
||||
mod inner {
|
||||
use crate::stm32::{
|
||||
RCC,
|
||||
rcc::{
|
||||
cfgr::SWW
|
||||
}
|
||||
};
|
||||
|
||||
enum SysClkSource {
|
||||
HSI,
|
||||
HSE(u32),
|
||||
HSI48,
|
||||
pub(super) const HSI: u32 = 8_000_000; // Hz
|
||||
|
||||
pub(super) enum SysClkSource {
|
||||
HSI,
|
||||
HSE(u32),
|
||||
}
|
||||
|
||||
pub(super) fn get_freq(c_src: &SysClkSource) -> u32 {
|
||||
// Select clock source based on user input and capability
|
||||
// Highest selected frequency source available takes precedent.
|
||||
match c_src {
|
||||
SysClkSource::HSE(freq) => *freq,
|
||||
_ => HSI,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn enable_clock(rcc: &mut RCC, c_src: &SysClkSource) {
|
||||
// Enable the requested clock
|
||||
match c_src {
|
||||
SysClkSource::HSE(_) => {
|
||||
rcc.cr.modify(|_, w| w.csson().on().hseon().on().hsebyp().not_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,
|
||||
};
|
||||
|
||||
// Set PLL source and multiplier
|
||||
rcc.cfgr.modify(|_, w| unsafe { w.pllsrc().bit(pllsrc_bit).pllmul().bits(pllmul_bits) });
|
||||
|
||||
rcc.cr.write(|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) -> SWW {
|
||||
match c_src {
|
||||
SysClkSource::HSI => SWW::HSI,
|
||||
SysClkSource::HSE(_) => SWW::HSE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "stm32f031", // TODO: May be an SVD bug
|
||||
feature = "stm32f038",
|
||||
feature = "stm32f042",
|
||||
feature = "stm32f048",
|
||||
feature = "stm32f051",
|
||||
feature = "stm32f058",
|
||||
feature = "stm32f071",
|
||||
feature = "stm32f072",
|
||||
feature = "stm32f078",
|
||||
feature = "stm32f091",
|
||||
feature = "stm32f098",
|
||||
))]
|
||||
mod inner {
|
||||
use crate::stm32::{
|
||||
RCC,
|
||||
rcc::{
|
||||
cfgr::SWW
|
||||
}
|
||||
};
|
||||
|
||||
pub(super) const HSI: u32 = 8_000_000; // Hz
|
||||
pub(super) const HSI48: u32 = 48_000_000; // Hz
|
||||
|
||||
pub(super) enum SysClkSource {
|
||||
HSI,
|
||||
HSE(u32),
|
||||
HSI48,
|
||||
}
|
||||
|
||||
pub(super) fn get_freq(c_src: &SysClkSource) -> u32 {
|
||||
// Select clock source based on user input and capability
|
||||
// Highest selected frequency source available takes precedent.
|
||||
match c_src {
|
||||
SysClkSource::HSE(freq) => *freq,
|
||||
SysClkSource::HSI48 => HSI48,
|
||||
_ => HSI,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn enable_clock(rcc: &mut RCC, c_src: &SysClkSource) {
|
||||
// Enable the requested clock
|
||||
match c_src {
|
||||
SysClkSource::HSE(_) => {
|
||||
rcc.cr.modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed());
|
||||
|
||||
while !rcc.cr.read().hserdy().bit_is_set() {}
|
||||
}
|
||||
SysClkSource::HSI48 => {
|
||||
rcc.cr2.modify(|_, w| w.hsi48on().set_bit());
|
||||
while rcc.cr2.read().hsi48rdy().bit_is_clear() {}
|
||||
}
|
||||
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: u8 = match c_src {
|
||||
SysClkSource::HSI => 0b00,
|
||||
SysClkSource::HSI48 => 0b11,
|
||||
SysClkSource::HSE(_) => 0b01,
|
||||
};
|
||||
|
||||
// Set PLL source and multiplier
|
||||
rcc.cfgr.modify(|_, w| unsafe { w.pllsrc().bits(pllsrc_bit).pllmul().bits(pllmul_bits) });
|
||||
|
||||
rcc.cr.write(|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) -> SWW {
|
||||
match c_src {
|
||||
SysClkSource::HSI => SWW::HSI,
|
||||
SysClkSource::HSI48 => SWW::HSI48,
|
||||
SysClkSource::HSE(_) => SWW::HSE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use self::inner::SysClkSource;
|
||||
|
||||
pub struct CFGR {
|
||||
hclk: Option<u32>,
|
||||
pclk: Option<u32>,
|
||||
sysclk: Option<u32>,
|
||||
clock_src: SysClkSource,
|
||||
rcc: crate::stm32::RCC,
|
||||
rcc: RCC,
|
||||
}
|
||||
|
||||
impl CFGR {
|
||||
|
@ -51,6 +196,23 @@ impl CFGR {
|
|||
self
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "stm32f031", // TODO: May be an SVD bug
|
||||
feature = "stm32f038",
|
||||
feature = "stm32f042",
|
||||
feature = "stm32f048",
|
||||
feature = "stm32f051",
|
||||
feature = "stm32f058",
|
||||
feature = "stm32f071",
|
||||
feature = "stm32f072",
|
||||
feature = "stm32f078",
|
||||
feature = "stm32f091",
|
||||
feature = "stm32f098",
|
||||
))]
|
||||
pub fn hsi48(mut self) -> Self {
|
||||
self.clock_src = SysClkSource::HSI48;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn hclk<F>(mut self, freq: F) -> Self
|
||||
where
|
||||
F: Into<Hertz>,
|
||||
|
@ -75,9 +237,9 @@ impl CFGR {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn freeze(self, flash: &mut crate::stm32::FLASH) -> Rcc {
|
||||
pub fn freeze(mut self, flash: &mut crate::stm32::FLASH) -> Rcc {
|
||||
// Default to lowest frequency clock on all systems.
|
||||
let sysclk = self.sysclk.unwrap_or(HSI);
|
||||
let sysclk = self.sysclk.unwrap_or(self::inner::HSI);
|
||||
|
||||
let r_sysclk; // The "real" sysclock value, calculated below
|
||||
let pllmul_bits;
|
||||
|
@ -85,11 +247,7 @@ impl CFGR {
|
|||
// Select clock source based on user input and capability
|
||||
// Highest selected frequency source available takes precedent.
|
||||
// For F04x, F07x, F09x parts, use HSI48 if requested.
|
||||
let src_clk_freq = match self.clock_src {
|
||||
SysClkSource::HSE(freq) => freq,
|
||||
SysClkSource::HSI48 => HSI48,
|
||||
_ => HSI,
|
||||
};
|
||||
let src_clk_freq = self::inner::get_freq(&self.clock_src);
|
||||
|
||||
// Pll check
|
||||
if sysclk == src_clk_freq {
|
||||
|
@ -158,51 +316,15 @@ impl CFGR {
|
|||
}
|
||||
|
||||
// Enable the requested clock
|
||||
match self.clock_src {
|
||||
SysClkSource::HSE(_) => {
|
||||
self.rcc
|
||||
.cr
|
||||
.modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed());
|
||||
|
||||
while !self.rcc.cr.read().hserdy().bit_is_set() {}
|
||||
}
|
||||
SysClkSource::HSI48 => {
|
||||
self.rcc.cr2.modify(|_, w| w.hsi48on().set_bit());
|
||||
while self.rcc.cr2.read().hsi48rdy().bit_is_clear() {}
|
||||
}
|
||||
SysClkSource::HSI => {
|
||||
self.rcc.cr.write(|w| w.hsion().set_bit());
|
||||
while self.rcc.cr.read().hsirdy().bit_is_clear() {}
|
||||
}
|
||||
};
|
||||
self::inner::enable_clock(&mut self.rcc, &self.clock_src);
|
||||
|
||||
// Set up rcc based on above calculated configuration.
|
||||
|
||||
// Enable PLL
|
||||
if let Some(pllmul_bits) = pllmul_bits {
|
||||
let pllsrc_bit: u8 = match self.clock_src {
|
||||
SysClkSource::HSI => 0b00,
|
||||
SysClkSource::HSI48 => 0b11,
|
||||
SysClkSource::HSE(_) => 0b01,
|
||||
};
|
||||
|
||||
// Set PLL source and multiplier
|
||||
self.rcc
|
||||
.cfgr
|
||||
.write(|w| unsafe { w.pllsrc().bits(pllsrc_bit).pllmul().bits(pllmul_bits) });
|
||||
|
||||
self.rcc.cr.write(|w| w.pllon().set_bit());
|
||||
while self.rcc.cr.read().pllrdy().bit_is_clear() {}
|
||||
|
||||
self.rcc.cfgr.modify(|_, w| unsafe {
|
||||
w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll()
|
||||
});
|
||||
self::inner::enable_pll(&mut self.rcc, &self.clock_src, pllmul_bits, ppre_bits, hpre_bits);
|
||||
} else {
|
||||
let sw_var = match self.clock_src {
|
||||
SysClkSource::HSI => SWW::HSI,
|
||||
SysClkSource::HSI48 => SWW::HSI48,
|
||||
SysClkSource::HSE(_) => SWW::HSE,
|
||||
};
|
||||
let sw_var = self::inner::get_sww(&self.clock_src);
|
||||
|
||||
// use HSI as source
|
||||
self.rcc.cfgr.write(|w| unsafe {
|
||||
|
|
|
@ -298,7 +298,7 @@ where
|
|||
// dff: 8 bit frames
|
||||
// bidimode: 2-line unidirectional
|
||||
// spe: enable the SPI bus
|
||||
self.spi.cr1.write(|w| unsafe {
|
||||
self.spi.cr1.write(|w| {
|
||||
w.cpha()
|
||||
.bit(mode.phase == Phase::CaptureOnSecondTransition)
|
||||
.cpol()
|
||||
|
|
Loading…
Reference in New Issue