diff --git a/CHANGELOG.md b/CHANGELOG.md index 8be387f..aef32c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/Cargo.toml b/Cargo.toml index 7d279dd..7629909 100644 --- a/Cargo.toml +++ b/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" diff --git a/examples/led_hal_button_irq.rs b/examples/led_hal_button_irq.rs index 6e9029f..255729d 100644 --- a/examples/led_hal_button_irq.rs +++ b/examples/led_hal_button_irq.rs @@ -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 diff --git a/src/adc.rs b/src/adc.rs index 78f7176..b51e5a4 100644 --- a/src/adc.rs +++ b/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) diff --git a/src/rcc.rs b/src/rcc.rs index 3b797e9..52f8468 100644 --- a/src/rcc.rs +++ b/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 + } + }; + + 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, + }; -enum SysClkSource { - HSI, - HSE(u32), - HSI48, + // 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, pclk: Option, sysclk: Option, 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(mut self, freq: F) -> Self where F: Into, @@ -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 { diff --git a/src/spi.rs b/src/spi.rs index 1c4bdf0..7ed5c1b 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -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()