diff --git a/CHANGELOG.md b/CHANGELOG.md index a4fb790..29d626e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Optimize delay implemenation (#42) - @david-sawatzke +- Enforced more rigorous safety guarentees (#41 - Very breaking change) - @HarkonenBade ### Fixed diff --git a/examples/adc_values.rs b/examples/adc_values.rs index fbe839d..a7adcd6 100644 --- a/examples/adc_values.rs +++ b/examples/adc_values.rs @@ -29,40 +29,41 @@ fn main() -> ! { hal::stm32::Peripherals::take(), cortex_m::peripheral::Peripherals::take(), ) { - let gpioa = p.GPIOA.split(); - let rcc = p.RCC.constrain(); - let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(); + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash); - let mut syst = cp.SYST; + let gpioa = p.GPIOA.split(&mut rcc); - // Set source for SysTick counter, here full operating frequency (== 8MHz) - syst.set_clock_source(Core); + let mut syst = cp.SYST; - // Set reload value, i.e. timer delay 8 MHz/counts - syst.set_reload(8_000_000 - 1); + // Set source for SysTick counter, here full operating frequency (== 8MHz) + syst.set_clock_source(Core); - // Start SysTick counter - syst.enable_counter(); + // Set reload value, i.e. timer delay 8 MHz/counts + syst.set_reload(8_000_000 - 1); - // Start SysTick interrupt generation - syst.enable_interrupt(); + // Start SysTick counter + syst.enable_counter(); - // USART1 at PA9 (TX) and PA10(RX) - let tx = gpioa.pa9.into_alternate_af1(); - let rx = gpioa.pa10.into_alternate_af1(); + // Start SysTick interrupt generation + syst.enable_interrupt(); - // Initialiase UART - let (mut tx, _) = - hal::serial::Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), clocks).split(); + // USART1 at PA9 (TX) and PA10(RX) + let tx = gpioa.pa9.into_alternate_af1(cs); + let rx = gpioa.pa10.into_alternate_af1(cs); - // Initialise ADC - let adc = hal::adc::Adc::new(p.ADC); + // Initialiase UART + let (mut tx, _) = + hal::serial::Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc).split(); - // Output a friendly greeting - tx.write_str("\n\rThis ADC example will read various values using the ADC and print them out to the serial terminal\r\n").ok(); + // Initialise ADC + let adc = hal::adc::Adc::new(p.ADC, &mut rcc); - // Move all components under Mutex supervision - cortex_m::interrupt::free(move |cs| { + // Output a friendly greeting + tx.write_str("\n\rThis ADC example will read various values using the ADC and print them out to the serial terminal\r\n").ok(); + + // Move all components under Mutex supervision *SHARED.borrow(cs).borrow_mut() = Some(Shared { adc, tx }); }); } diff --git a/examples/blinky.rs b/examples/blinky.rs index 1bcc2a7..826bac3 100644 --- a/examples/blinky.rs +++ b/examples/blinky.rs @@ -14,21 +14,26 @@ use cortex_m_rt::entry; #[entry] fn main() -> ! { if let Some(p) = stm32::Peripherals::take() { - let gpioa = p.GPIOA.split(); - - /* (Re-)configure PA1 as output */ - let mut led = gpioa.pa1.into_push_pull_output(); - - loop { - /* Turn PA1 on a million times in a row */ - for _ in 0..1_000_000 { - led.set_high(); - } - /* Then turn PA1 off a million times in a row */ - for _ in 0..1_000_000 { - led.set_low(); + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash); + + let gpioa = p.GPIOA.split(&mut rcc); + + /* (Re-)configure PA1 as output */ + let mut led = gpioa.pa1.into_push_pull_output(cs); + + loop { + /* Turn PA1 on a million times in a row */ + for _ in 0..1_000_000 { + led.set_high(); + } + /* Then turn PA1 off a million times in a row */ + for _ in 0..1_000_000 { + led.set_low(); + } } - } + }); } loop { diff --git a/examples/blinky_adc.rs b/examples/blinky_adc.rs index 30c3ce3..74a698c 100644 --- a/examples/blinky_adc.rs +++ b/examples/blinky_adc.rs @@ -18,36 +18,35 @@ use cortex_m_rt::entry; #[entry] fn main() -> ! { if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) { - let gpioa = p.GPIOA.split(); + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash); - /* (Re-)configure PA1 as output */ - let mut led = gpioa.pa1.into_push_pull_output(); + let gpioa = p.GPIOA.split(&mut rcc); - /* (Re-)configure PA0 as analog in */ - let mut an_in = gpioa.pa0.into_analog(); + /* (Re-)configure PA1 as output */ + let mut led = gpioa.pa1.into_push_pull_output(cs); - /* Constrain clocking registers */ - let rcc = p.RCC.constrain(); + /* (Re-)configure PA0 as analog in */ + let mut an_in = gpioa.pa0.into_analog(cs); - /* Configure clock to 8 MHz (i.e. the default) and freeze it */ - let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(); + /* Get delay provider */ + let mut delay = Delay::new(cp.SYST, &rcc); - /* Get delay provider */ - let mut delay = Delay::new(cp.SYST, clocks); + let mut adc = Adc::new(p.ADC, &mut rcc); - let mut adc = Adc::new(p.ADC); + loop { + led.toggle(); - loop { - led.toggle(); + let val: u16 = adc.read(&mut an_in).unwrap(); - let val: u16 = adc.read(&mut an_in).unwrap(); + /* shift the value right by 3, same as divide by 8, reduces + the 0-4095 range into something approximating 1-512 */ + let time: u16 = (val >> 3) + 1; - /* shift the value right by 3, same as divide by 8, reduces - the 0-4095 range into something approximating 1-512 */ - let time: u16 = (val >> 3) + 1; - - delay.delay_ms(time); - } + delay.delay_ms(time); + } + }); } loop { diff --git a/examples/blinky_delay.rs b/examples/blinky_delay.rs index 4f3b42b..c8fba45 100644 --- a/examples/blinky_delay.rs +++ b/examples/blinky_delay.rs @@ -16,24 +16,23 @@ use cortex_m_rt::entry; #[entry] fn main() -> ! { if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) { - let gpioa = p.GPIOA.split(); + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash); - /* (Re-)configure PA1 as output */ - let mut led = gpioa.pa1.into_push_pull_output(); + let gpioa = p.GPIOA.split(&mut rcc); - /* Constrain clocking registers */ - let rcc = p.RCC.constrain(); + /* (Re-)configure PA1 as output */ + let mut led = gpioa.pa1.into_push_pull_output(cs); - /* Configure clock to 8 MHz (i.e. the default) and freeze it */ - let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(); + /* Get delay provider */ + let mut delay = Delay::new(cp.SYST, &rcc); - /* Get delay provider */ - let mut delay = Delay::new(cp.SYST, clocks); - - loop { - led.toggle(); - delay.delay_ms(1_000_u16); - } + loop { + led.toggle(); + delay.delay_ms(1_000_u16); + } + }); } loop { diff --git a/examples/blinky_multiple.rs b/examples/blinky_multiple.rs index 35a4894..9cb5dd4 100644 --- a/examples/blinky_multiple.rs +++ b/examples/blinky_multiple.rs @@ -16,37 +16,36 @@ use cortex_m_rt::entry; #[entry] fn main() -> ! { if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) { - let gpioa = p.GPIOA.split(); - let gpiob = p.GPIOB.split(); - - /* (Re-)configure PA1 as output */ - let led1 = gpioa.pa1.into_push_pull_output(); - - /* (Re-)configure PB1 as output */ - let led2 = gpiob.pb1.into_push_pull_output(); - - /* Constrain clocking registers */ - let rcc = p.RCC.constrain(); - - /* Configure clock to 8 MHz (i.e. the default) and freeze it */ - let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(); - - /* Get delay provider */ - let mut delay = Delay::new(cp.SYST, clocks); - - /* Store them together */ - let mut leds = [led1.downgrade(), led2.downgrade()]; - loop { - for l in &mut leds { - l.set_high(); - } - delay.delay_ms(1_000_u16); - - for l in &mut leds { - l.set_low(); + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash); + + let gpioa = p.GPIOA.split(&mut rcc); + let gpiob = p.GPIOB.split(&mut rcc); + + /* (Re-)configure PA1 as output */ + let led1 = gpioa.pa1.into_push_pull_output(cs); + + /* (Re-)configure PB1 as output */ + let led2 = gpiob.pb1.into_push_pull_output(cs); + + /* Get delay provider */ + let mut delay = Delay::new(cp.SYST, &rcc); + + /* Store them together */ + let mut leds = [led1.downgrade(), led2.downgrade()]; + loop { + for l in &mut leds { + l.set_high(); + } + delay.delay_ms(1_000_u16); + + for l in &mut leds { + l.set_low(); + } + delay.delay_ms(1_000_u16); } - delay.delay_ms(1_000_u16); - } + }); } loop { diff --git a/examples/blinky_timer.rs b/examples/blinky_timer.rs index 2078c1b..58a66c2 100644 --- a/examples/blinky_timer.rs +++ b/examples/blinky_timer.rs @@ -17,22 +17,21 @@ use nb::block; #[entry] fn main() -> ! { if let Some(p) = stm32::Peripherals::take() { - let gpioa = p.GPIOA.split(); - /* (Re-)configure PA1 as output */ - let mut led = gpioa.pa1.into_push_pull_output(); + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash); - /* Constrain clocking registers */ - let rcc = p.RCC.constrain(); + let gpioa = p.GPIOA.split(&mut rcc); + /* (Re-)configure PA1 as output */ + let mut led = gpioa.pa1.into_push_pull_output(cs); - /* Configure clock to 8 MHz (i.e. the default) and freeze it */ - let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(); + let mut timer = Timer::tim1(p.TIM1, Hertz(1), &mut rcc); - let mut timer = Timer::tim1(p.TIM1, Hertz(1), clocks); - - loop { - led.toggle(); - block!(timer.wait()).ok(); - } + loop { + led.toggle(); + block!(timer.wait()).ok(); + } + }); } loop { diff --git a/examples/flash_systick.rs b/examples/flash_systick.rs index b1b9e72..8bd5623 100644 --- a/examples/flash_systick.rs +++ b/examples/flash_systick.rs @@ -23,32 +23,34 @@ static GPIO: Mutex>>>> = Mutex::new(R #[entry] fn main() -> ! { if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) { - let gpioa = p.GPIOA.split(); - let rcc = p.RCC.constrain(); - let _ = rcc.cfgr.sysclk(48.mhz()).freeze(); - let mut syst = cp.SYST; + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut flash); - /* (Re-)configure PA1 as output */ - let led = gpioa.pa1.into_push_pull_output(); + let gpioa = p.GPIOA.split(&mut rcc); + + let mut syst = cp.SYST; + + /* (Re-)configure PA1 as output */ + let led = gpioa.pa1.into_push_pull_output(cs); - cortex_m::interrupt::free(move |cs| { *GPIO.borrow(cs).borrow_mut() = Some(led); - }); - /* Initialise SysTick counter with a defined value */ - unsafe { syst.cvr.write(1) }; + /* Initialise SysTick counter with a defined value */ + unsafe { syst.cvr.write(1) }; - /* Set source for SysTick counter, here full operating frequency (== 8MHz) */ - syst.set_clock_source(Core); + /* Set source for SysTick counter, here full operating frequency (== 8MHz) */ + syst.set_clock_source(Core); - /* Set reload value, i.e. timer delay 48 MHz/4 Mcounts == 12Hz or 83ms */ - syst.set_reload(4_000_000 - 1); + /* Set reload value, i.e. timer delay 48 MHz/4 Mcounts == 12Hz or 83ms */ + syst.set_reload(4_000_000 - 1); - /* Start counter */ - syst.enable_counter(); + /* Start counter */ + syst.enable_counter(); - /* Start interrupt generation */ - syst.enable_interrupt(); + /* Start interrupt generation */ + syst.enable_interrupt(); + }); } loop { diff --git a/examples/led_hal_button_irq.rs b/examples/led_hal_button_irq.rs index 2594ee2..60f7669 100644 --- a/examples/led_hal_button_irq.rs +++ b/examples/led_hal_button_irq.rs @@ -31,53 +31,53 @@ static INT: Mutex>> = Mutex::new(RefCell::new(None)); #[entry] fn main() -> ! { if let (Some(p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) { - let gpioa = p.GPIOA.split(); - let gpiob = p.GPIOB.split(); - let syscfg = p.SYSCFG_COMP; - let exti = p.EXTI; + cortex_m::interrupt::free(move |cs| { + // Enable clock for SYSCFG + let rcc = p.RCC; + rcc.apb2enr.modify(|_, w| w.syscfgen().set_bit()); - // Enable clock for SYSCFG - let rcc = p.RCC; - rcc.apb2enr.modify(|_, w| w.syscfgen().set_bit()); + let mut flash = p.FLASH; + let mut rcc = rcc.configure().sysclk(8.mhz()).freeze(&mut flash); - // Configure PB1 as input (button) - let _ = gpiob.pb1.into_pull_down_input(); + let gpioa = p.GPIOA.split(&mut rcc); + let gpiob = p.GPIOB.split(&mut rcc); + let syscfg = p.SYSCFG_COMP; + let exti = p.EXTI; - // Configure PA1 as output (LED) - let mut led = gpioa.pa1.into_push_pull_output(); + // Configure PB1 as input (button) + let _ = gpiob.pb1.into_pull_down_input(cs); - // Turn off LED - led.set_low(); + // Configure PA1 as output (LED) + let mut led = gpioa.pa1.into_push_pull_output(cs); - // Configure clock to 8 MHz (i.e. the default) and freeze it - let clocks = rcc.constrain().cfgr.sysclk(8.mhz()).freeze(); + // Turn off LED + led.set_low(); - // Initialise delay provider - let delay = Delay::new(cp.SYST, clocks); + // Initialise delay provider + let delay = Delay::new(cp.SYST, &rcc); - // Enable external interrupt for PB1 - syscfg - .syscfg_exticr1 - .modify(|_, w| unsafe { w.exti1().bits(1) }); + // Enable external interrupt for PB1 + syscfg + .syscfg_exticr1 + .modify(|_, w| unsafe { w.exti1().bits(1) }); - // Set interrupt request mask for line 1 - exti.imr.modify(|_, w| w.mr1().set_bit()); + // Set interrupt request mask for line 1 + exti.imr.modify(|_, w| w.mr1().set_bit()); - // Set interrupt rising trigger for line 1 - exti.rtsr.modify(|_, w| w.tr1().set_bit()); + // Set interrupt rising trigger for line 1 + exti.rtsr.modify(|_, w| w.tr1().set_bit()); - // Move control over LED and DELAY and EXTI into global mutexes - cortex_m::interrupt::free(move |cs| { + // Move control over LED and DELAY and EXTI into global mutexes *LED.borrow(cs).borrow_mut() = Some(led); *DELAY.borrow(cs).borrow_mut() = Some(delay); *INT.borrow(cs).borrow_mut() = Some(exti); - }); - // Enable EXTI IRQ, set prio 1 and clear any pending IRQs - let mut nvic = cp.NVIC; - nvic.enable(Interrupt::EXTI0_1); - unsafe { nvic.set_priority(Interrupt::EXTI0_1, 1) }; - cortex_m::peripheral::NVIC::unpend(Interrupt::EXTI0_1); + // Enable EXTI IRQ, set prio 1 and clear any pending IRQs + let mut nvic = cp.NVIC; + nvic.enable(Interrupt::EXTI0_1); + unsafe { nvic.set_priority(Interrupt::EXTI0_1, 1) }; + cortex_m::peripheral::NVIC::unpend(Interrupt::EXTI0_1); + }); } loop { diff --git a/examples/serial_echo.rs b/examples/serial_echo.rs index 5a414f4..ec8163c 100644 --- a/examples/serial_echo.rs +++ b/examples/serial_echo.rs @@ -17,21 +17,24 @@ use cortex_m_rt::entry; #[entry] fn main() -> ! { if let Some(p) = stm32::Peripherals::take() { - let gpioa = p.GPIOA.split(); - let rcc = p.RCC.constrain(); - let clocks = rcc.cfgr.sysclk(48.mhz()).freeze(); + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut flash); - let tx = gpioa.pa9.into_alternate_af1(); - let rx = gpioa.pa10.into_alternate_af1(); + let gpioa = p.GPIOA.split(&mut rcc); - let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), clocks); + let tx = gpioa.pa9.into_alternate_af1(cs); + let rx = gpioa.pa10.into_alternate_af1(cs); - let (mut tx, mut rx) = serial.split(); + let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc); - loop { - let received = block!(rx.read()).unwrap(); - block!(tx.write(received)).ok(); - } + let (mut tx, mut rx) = serial.split(); + + loop { + let received = block!(rx.read()).unwrap(); + block!(tx.write(received)).ok(); + } + }); } loop { diff --git a/examples/serial_spi_bridge.rs b/examples/serial_spi_bridge.rs index 6abae26..74050a7 100644 --- a/examples/serial_spi_bridge.rs +++ b/examples/serial_spi_bridge.rs @@ -30,34 +30,37 @@ fn main() -> ! { }; if let Some(p) = stm32::Peripherals::take() { - let rcc = p.RCC.constrain(); - let clocks = rcc.cfgr.freeze(); - let gpioa = p.GPIOA.split(); + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().freeze(&mut flash); - // Configure pins for SPI - let sck = gpioa.pa5.into_alternate_af0(); - let miso = gpioa.pa6.into_alternate_af0(); - let mosi = gpioa.pa7.into_alternate_af0(); + let gpioa = p.GPIOA.split(&mut rcc); - // Configure SPI with 1MHz rate - let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 1.mhz(), clocks); + // 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); - let tx = gpioa.pa9.into_alternate_af1(); - let rx = gpioa.pa10.into_alternate_af1(); + // Configure SPI with 1MHz rate + let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 1.mhz(), &mut rcc); - let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), clocks); + let tx = gpioa.pa9.into_alternate_af1(cs); + let rx = gpioa.pa10.into_alternate_af1(cs); - let (mut tx, mut rx) = serial.split(); + let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc); - loop { - let serial_received = block!(rx.read()).unwrap(); + let (mut tx, mut rx) = serial.split(); - block!(spi.send(serial_received)).ok(); + loop { + let serial_received = block!(rx.read()).unwrap(); - let spi_received = block!(spi.read()).unwrap(); + block!(spi.send(serial_received)).ok(); - block!(tx.write(spi_received)).ok(); - } + let spi_received = block!(spi.read()).unwrap(); + + block!(tx.write(spi_received)).ok(); + } + }); } loop { diff --git a/examples/spi_hal_apa102c.rs b/examples/spi_hal_apa102c.rs index 985bf38..422e6da 100644 --- a/examples/spi_hal_apa102c.rs +++ b/examples/spi_hal_apa102c.rs @@ -21,42 +21,45 @@ fn main() -> ! { }; if let Some(p) = stm32::Peripherals::take() { - let rcc = p.RCC.constrain(); - let clocks = rcc.cfgr.freeze(); - let gpioa = p.GPIOA.split(); + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().freeze(&mut flash); - // Configure pins for SPI - let sck = gpioa.pa5.into_alternate_af0(); - let miso = gpioa.pa6.into_alternate_af0(); - let mosi = gpioa.pa7.into_alternate_af0(); + let gpioa = p.GPIOA.split(&mut rcc); - // Configure SPI with 100kHz rate - let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 100_000.hz(), clocks); + // 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); - // Cycle through colors on 16 chained APA102C LEDs - loop { - for r in 0..255 { - let _ = spi.write(&[0, 0, 0, 0]); - for _i in 0..16 { - let _ = spi.write(&[0b1110_0001, 0, 0, r]); + // Configure SPI with 100kHz rate + let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 100_000.hz(), &mut rcc); + + // Cycle through colors on 16 chained APA102C LEDs + loop { + for r in 0..255 { + let _ = spi.write(&[0, 0, 0, 0]); + for _i in 0..16 { + let _ = spi.write(&[0b1110_0001, 0, 0, r]); + } + let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]); } - let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]); - } - for b in 0..255 { - let _ = spi.write(&[0, 0, 0, 0]); - for _i in 0..16 { - let _ = spi.write(&[0b1110_0001, b, 0, 0]); + for b in 0..255 { + let _ = spi.write(&[0, 0, 0, 0]); + for _i in 0..16 { + let _ = spi.write(&[0b1110_0001, b, 0, 0]); + } + let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]); } - let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]); - } - for g in 0..255 { - let _ = spi.write(&[0, 0, 0, 0]); - for _i in 0..16 { - let _ = spi.write(&[0b1110_0001, 0, g, 0]); + for g in 0..255 { + let _ = spi.write(&[0, 0, 0, 0]); + for _i in 0..16 { + let _ = spi.write(&[0b1110_0001, 0, g, 0]); + } + let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]); } - let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]); } - } + }); } loop { diff --git a/examples/watchdog.rs b/examples/watchdog.rs index 66752f3..f639dcf 100644 --- a/examples/watchdog.rs +++ b/examples/watchdog.rs @@ -20,39 +20,42 @@ use cortex_m_rt::entry; #[entry] fn main() -> ! { if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) { - let gpioa = p.GPIOA.split(); - let rcc = p.RCC.constrain(); - let dbgmcu = p.DBGMCU; + cortex_m::interrupt::free(move |cs| { + let mut flash = p.FLASH; + let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash); - // Disable the watchdog when the cpu is stopped under debug - dbgmcu.apb1_fz.modify(|_, w| w.dbg_iwdg_stop().set_bit()); + let gpioa = p.GPIOA.split(&mut rcc); + let dbgmcu = p.DBGMCU; - let mut watchdog = Watchdog::new(p.IWDG); - let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(); + // Disable the watchdog when the cpu is stopped under debug + dbgmcu.apb1_fz.modify(|_, w| w.dbg_iwdg_stop().set_bit()); - // Get delay provider - let mut delay = Delay::new(cp.SYST, clocks); + let mut watchdog = Watchdog::new(p.IWDG); - let tx = gpioa.pa9.into_alternate_af1(); - let rx = gpioa.pa10.into_alternate_af1(); + // Get delay provider + let mut delay = Delay::new(cp.SYST, &rcc); - let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), clocks); + let tx = gpioa.pa9.into_alternate_af1(cs); + let rx = gpioa.pa10.into_alternate_af1(cs); - let (mut tx, _rx) = serial.split(); - tx.write_str("RESET \r\n").ok(); + let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc); - watchdog.start(Hertz(1)); - delay.delay_ms(500_u16); - watchdog.feed(); - delay.delay_ms(500_u16); - watchdog.feed(); - delay.delay_ms(500_u16); - tx.write_str("This will get printed \r\n").ok(); - watchdog.feed(); + let (mut tx, _rx) = serial.split(); + tx.write_str("RESET \r\n").ok(); - // Now a reset happens while delaying - delay.delay_ms(1500_u16); - tx.write_str("This won't\r\n").ok(); + watchdog.start(Hertz(1)); + delay.delay_ms(500_u16); + watchdog.feed(); + delay.delay_ms(500_u16); + watchdog.feed(); + delay.delay_ms(500_u16); + tx.write_str("This will get printed \r\n").ok(); + watchdog.feed(); + + // Now a reset happens while delaying + delay.delay_ms(1500_u16); + tx.write_str("This won't\r\n").ok(); + }); } loop { diff --git a/src/adc.rs b/src/adc.rs index fb39277..cdc7aa5 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -12,52 +12,45 @@ //! use crate::hal::prelude::*; //! use crate::hal::adc::Adc; //! -//! let mut p = stm32::Peripherals::take().unwrap(); +//! cortex_m::interrupt::free(|cs| { +//! let mut p = stm32::Peripherals::take().unwrap(); +//! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH); //! -//! let mut led = gpioa.pa1.into_push_pull_pull_output(); -//! let mut an_in = gpioa.pa0.into_analog(); +//! let gpioa = p.GPIOA.split(&mut rcc); //! -//! let rcc = p.RCC.constrain().cfgr.freeze(); -//! let mut delay = Delay::new(cp.SYST, clocks); +//! let mut led = gpioa.pa1.into_push_pull_pull_output(cs); +//! let mut an_in = gpioa.pa0.into_analog(cs); //! -//! let mut adc = Adc::new(p.ADC); +//! let mut delay = Delay::new(cp.SYST, &rcc); //! -//! loop { -//! let val: u16 = adc.read(&mut an_in).unwrap(); -//! if val < ((1 << 8) - 1) { -//! led.set_low(); -//! } else { -//! led.set_high(); +//! 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); //! } -//! delay.delay_ms(50_u16); -//! } +//! }); //! ``` -#[cfg(feature = "device-selected")] const VREFCAL: *const u16 = 0x1FFF_F7BA as *const u16; - -#[cfg(feature = "device-selected")] const VTEMPCAL30: *const u16 = 0x1FFF_F7B8 as *const u16; - -#[cfg(feature = "device-selected")] const VTEMPCAL110: *const u16 = 0x1FFF_F7C2 as *const u16; - -#[cfg(feature = "device-selected")] const VDD_CALIB: u16 = 3300; -#[cfg(feature = "device-selected")] use core::ptr; -#[cfg(feature = "device-selected")] use embedded_hal::{ adc::{Channel, OneShot}, blocking::delay::DelayUs, }; -#[cfg(feature = "device-selected")] -use crate::{delay::Delay, gpio::*, stm32}; +use crate::{delay::Delay, gpio::*, rcc::Rcc, stm32}; -#[cfg(feature = "device-selected")] /// Analog to Digital converter interface pub struct Adc { rb: stm32::ADC, @@ -89,7 +82,6 @@ pub enum AdcSampleTime { T_239, } -#[cfg(feature = "device-selected")] impl AdcSampleTime { fn write_bits(self, adc: &mut stm32::ADC) { unsafe { @@ -137,7 +129,6 @@ pub enum AdcAlign { LeftAsRM, } -#[cfg(feature = "device-selected")] impl AdcAlign { fn write_bits(self, adc: &mut stm32::ADC) { adc.cfgr1.write(|w| { @@ -168,7 +159,6 @@ pub enum AdcPrecision { B_6, } -#[cfg(feature = "device-selected")] impl AdcPrecision { fn write_bits(self, adc: &mut stm32::ADC) { unsafe { @@ -189,7 +179,6 @@ impl AdcPrecision { } } -#[cfg(feature = "device-selected")] macro_rules! adc_pins { ($($pin:ty => $chan:expr),+ $(,)*) => { $( @@ -202,7 +191,6 @@ macro_rules! adc_pins { }; } -#[cfg(feature = "device-selected")] adc_pins!( gpioa::PA0 => 0_u8, gpioa::PA1 => 1_u8, @@ -239,13 +227,11 @@ pub struct VTemp; /// Internal voltage reference (ADC Channel 17) pub struct VRef; -#[cfg(feature = "device-selected")] adc_pins!( VTemp => 16_u8, VRef => 17_u8, ); -#[cfg(feature = "device-selected")] impl VTemp { /// Init a new VTemp pub fn new() -> Self { @@ -319,7 +305,6 @@ impl VTemp { } } -#[cfg(feature = "device-selected")] impl VRef { /// Init a new VRef pub fn new() -> Self { @@ -421,21 +406,20 @@ impl VBat { #[derive(Copy, Clone, Debug, PartialEq)] pub struct StoredConfig(AdcSampleTime, AdcAlign, AdcPrecision); -#[cfg(feature = "device-selected")] 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: stm32::ADC) -> Self { + pub fn new(adc: stm32::ADC, rcc: &mut Rcc) -> Self { let mut s = Self { rb: adc, sample_time: AdcSampleTime::default(), align: AdcAlign::default(), precision: AdcPrecision::default(), }; - s.select_clock(); + s.select_clock(rcc); s.calibrate(); s } @@ -527,12 +511,10 @@ impl Adc { while self.rb.cr.read().adcal().bit_is_set() {} } - fn select_clock(&mut self) { - let rcc = unsafe { &*stm32::RCC::ptr() }; - - rcc.apb2enr.modify(|_, w| w.adcen().set_bit()); - rcc.cr2.write(|w| w.hsi14on().set_bit()); - while rcc.cr2.read().hsi14rdy().bit_is_clear() {} + fn select_clock(&mut self, rcc: &mut Rcc) { + rcc.regs.apb2enr.modify(|_, w| w.adcen().set_bit()); + rcc.regs.cr2.write(|w| w.hsi14on().set_bit()); + while rcc.regs.cr2.read().hsi14rdy().bit_is_clear() {} } fn power_up(&mut self) { @@ -569,7 +551,6 @@ impl Adc { } } -#[cfg(feature = "device-selected")] impl OneShot for Adc where WORD: From, diff --git a/src/delay.rs b/src/delay.rs index 019b49a..5d6125c 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -18,8 +18,8 @@ //! let mut p = stm32::Peripherals::take().unwrap(); //! let mut cp = cortex_m::Peripherals::take().unwrap(); //! -//! let clocks = p.RCC.constrain().cfgr.freeze(); -//! let mut delay = Delay::new(cp.SYST, clocks); +//! 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); //! } @@ -29,7 +29,8 @@ use cast::{u16, u32}; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; -use crate::rcc::Clocks; +use crate::rcc::Rcc; + use embedded_hal::blocking::delay::{DelayMs, DelayUs}; /// System timer (SysTick) as a delay provider @@ -42,14 +43,15 @@ const SYSTICK_RANGE: u32 = 0x0100_0000; impl Delay { /// Configures the system timer (SysTick) as a delay provider - pub fn new(mut syst: SYST, clocks: Clocks) -> Delay { + 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(); - assert!(clocks.hclk().0 >= 1_000_000); - let scale = clocks.hclk().0 / 1_000_000; + + assert!(rcc.clocks.hclk().0 >= 1_000_000); + let scale = rcc.clocks.hclk().0 / 1_000_000; Delay { scale } // As access to the count register is possible without a reference to the systick, we can diff --git a/src/gpio.rs b/src/gpio.rs index 315a972..f8c40a6 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -2,13 +2,15 @@ use core::marker::PhantomData; +use crate::rcc::Rcc; + /// Extension trait to split a GPIO peripheral in independent pins and registers pub trait GpioExt { /// The parts to split the GPIO into type Parts; /// Splits the GPIO block into independent pins and registers - fn split(self) -> Self::Parts; + fn split(self, rcc: &mut Rcc) -> Self::Parts; } trait GpioRegExt { @@ -116,7 +118,6 @@ impl InputPin for Pin> { } } -#[allow(unused)] macro_rules! gpio_trait { ($gpiox:ident) => { impl GpioRegExt for crate::stm32::$gpiox::RegisterBlock { @@ -143,13 +144,9 @@ macro_rules! gpio_trait { }; } -#[cfg(feature = "device-selected")] gpio_trait!(gpioa); - -#[cfg(feature = "device-selected")] gpio_trait!(gpiof); -#[allow(unused)] macro_rules! gpio { ($GPIOX:ident, $gpiox:ident, $iopxenr:ident, $PXx:ident, [ $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+ @@ -159,9 +156,13 @@ macro_rules! gpio { use core::marker::PhantomData; use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin, toggleable}; - use crate::stm32::$GPIOX; + use crate::{ + rcc::Rcc, + stm32::$GPIOX + }; + + use cortex_m::interrupt::CriticalSection; - use crate::stm32::RCC; use super::{ Alternate, Analog, Floating, GpioExt, Input, OpenDrain, Output, PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, @@ -179,10 +180,8 @@ macro_rules! gpio { impl GpioExt for $GPIOX { type Parts = Parts; - fn split(self) -> Parts { - // NOTE(unsafe) This executes only during initialisation - let rcc = unsafe { &(*RCC::ptr()) }; - rcc.ahbenr.modify(|_, w| w.$iopxenr().set_bit()); + fn split(self, rcc: &mut Rcc) -> Parts { + rcc.regs.ahbenr.modify(|_, w| w.$iopxenr().set_bit()); Parts { $( @@ -201,8 +200,7 @@ macro_rules! gpio { &(*$GPIOX::ptr()).afrl.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); - } else - { + } else { let offset2 = offset2 - 32; &(*$GPIOX::ptr()).afrh.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) @@ -223,7 +221,7 @@ macro_rules! gpio { impl $PXi { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0( - self, + self, _cs: &CriticalSection ) -> $PXi> { _set_alternate_mode($i, 0); $PXi { _mode: PhantomData } @@ -231,7 +229,7 @@ macro_rules! gpio { /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1( - self, + self, _cs: &CriticalSection ) -> $PXi> { _set_alternate_mode($i, 1); $PXi { _mode: PhantomData } @@ -239,7 +237,7 @@ macro_rules! gpio { /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2( - self, + self, _cs: &CriticalSection ) -> $PXi> { _set_alternate_mode($i, 2); $PXi { _mode: PhantomData } @@ -247,7 +245,7 @@ macro_rules! gpio { /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3( - self, + self, _cs: &CriticalSection ) -> $PXi> { _set_alternate_mode($i, 3); $PXi { _mode: PhantomData } @@ -255,7 +253,7 @@ macro_rules! gpio { /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4( - self, + self, _cs: &CriticalSection ) -> $PXi> { _set_alternate_mode($i, 4); $PXi { _mode: PhantomData } @@ -263,7 +261,7 @@ macro_rules! gpio { /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5( - self, + self, _cs: &CriticalSection ) -> $PXi> { _set_alternate_mode($i, 5); $PXi { _mode: PhantomData } @@ -271,7 +269,7 @@ macro_rules! gpio { /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6( - self, + self, _cs: &CriticalSection ) -> $PXi> { _set_alternate_mode($i, 6); $PXi { _mode: PhantomData } @@ -279,7 +277,7 @@ macro_rules! gpio { /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7( - self, + self, _cs: &CriticalSection ) -> $PXi> { _set_alternate_mode($i, 7); $PXi { _mode: PhantomData } @@ -287,7 +285,7 @@ macro_rules! gpio { /// Configures the pin to operate as a floating input pin pub fn into_floating_input( - self, + self, _cs: &CriticalSection ) -> $PXi> { let offset = 2 * $i; unsafe { @@ -303,7 +301,7 @@ macro_rules! gpio { /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input( - self, + self, _cs: &CriticalSection ) -> $PXi> { let offset = 2 * $i; unsafe { @@ -319,7 +317,7 @@ macro_rules! gpio { /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input( - self, + self, _cs: &CriticalSection ) -> $PXi> { let offset = 2 * $i; unsafe { @@ -335,7 +333,7 @@ macro_rules! gpio { /// Configures the pin to operate as an analog pin pub fn into_analog( - self, + self, _cs: &CriticalSection ) -> $PXi { let offset = 2 * $i; unsafe { @@ -351,7 +349,7 @@ macro_rules! gpio { /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output( - self, + self, _cs: &CriticalSection ) -> $PXi> { let offset = 2 * $i; unsafe { @@ -370,10 +368,9 @@ macro_rules! gpio { /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output( - self, + self, _cs: &CriticalSection ) -> $PXi> { let offset = 2 * $i; - unsafe { &(*$GPIOX::ptr()).pupdr.modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset)) @@ -391,10 +388,9 @@ macro_rules! gpio { /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs( - self, + self, _cs: &CriticalSection ) -> $PXi> { let offset = 2 * $i; - unsafe { &(*$GPIOX::ptr()).pupdr.modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset)) @@ -409,46 +405,46 @@ macro_rules! gpio { w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset)) }); } - $PXi { _mode: PhantomData } } } impl $PXi> { /// Enables / disables the internal pull up - pub fn internal_pull_up(&mut self, on: bool) { + pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * $i; let value = if on { 0b01 } else { 0b00 }; unsafe { &(*$GPIOX::ptr()).pupdr.modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (value << offset)) - })}; + }); + } } } impl $PXi> { /// Enables / disables the internal pull up - pub fn internal_pull_up(self, on: bool) -> Self { + pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * $i; let value = if on { 0b01 } else { 0b00 }; unsafe { &(*$GPIOX::ptr()).pupdr.modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (value << offset)) - })}; - + }); + } self } } impl $PXi> { /// Turns pin alternate configuration pin into open drain - pub fn set_open_drain(self) -> Self { + pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = $i; unsafe { &(*$GPIOX::ptr()).otyper.modify(|r, w| { w.bits(r.bits() | (1 << offset)) - })}; - + }); + } self } } @@ -527,7 +523,6 @@ macro_rules! gpio { } } -#[cfg(feature = "device-selected")] gpio!(GPIOA, gpioa, iopaen, PA, [ PA0: (pa0, 0, Input), PA1: (pa1, 1, Input), @@ -547,7 +542,6 @@ gpio!(GPIOA, gpioa, iopaen, PA, [ PA15: (pa15, 15, Input), ]); -#[cfg(feature = "device-selected")] gpio!(GPIOB, gpiob, iopben, PB, [ PB0: (pb0, 0, Input), PB1: (pb1, 1, Input), diff --git a/src/i2c.rs b/src/i2c.rs index 4b77700..bba521e 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -1,17 +1,14 @@ -#[allow(unused)] use core::ops::Deref; -#[allow(unused)] use embedded_hal::blocking::i2c::{Write, WriteRead}; -#[allow(unused)] use crate::{ gpio::*, + rcc::Rcc, time::{KiloHertz, U32Ext}, }; /// I2C abstraction -#[allow(unused)] pub struct I2c { i2c: I2C, pins: (SCLPIN, SDAPIN), @@ -20,7 +17,6 @@ pub struct I2c { pub trait SclPin {} pub trait SdaPin {} -#[allow(unused)] macro_rules! i2c_pins { ($($I2C:ident => { scl => [$($scl:ty),+ $(,)*], @@ -125,26 +121,22 @@ pub enum Error { NACK, } -#[allow(unused)] macro_rules! i2c { ($($I2C:ident: ($i2c:ident, $i2cXen:ident, $i2cXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => { $( use crate::stm32::$I2C; impl I2c<$I2C, SCLPIN, SDAPIN> { - pub fn $i2c(i2c: $I2C, pins: (SCLPIN, SDAPIN), speed: KiloHertz) -> Self + pub fn $i2c(i2c: $I2C, pins: (SCLPIN, SDAPIN), speed: KiloHertz, rcc: &mut Rcc) -> Self where SCLPIN: SclPin<$I2C>, SDAPIN: SdaPin<$I2C>, { - // NOTE(unsafe) This executes only during initialisation - let rcc = unsafe { &(*crate::stm32::RCC::ptr()) }; - // Enable clock for I2C - rcc.$apbenr.modify(|_, w| w.$i2cXen().set_bit()); + rcc.regs.$apbenr.modify(|_, w| w.$i2cXen().set_bit()); // Reset I2C - rcc.$apbrstr.modify(|_, w| w.$i2cXrst().set_bit()); - rcc.$apbrstr.modify(|_, w| w.$i2cXrst().clear_bit()); + rcc.regs.$apbrstr.modify(|_, w| w.$i2cXrst().set_bit()); + rcc.regs.$apbrstr.modify(|_, w| w.$i2cXrst().clear_bit()); I2c { i2c, pins }.i2c_init(speed) } } @@ -152,7 +144,6 @@ macro_rules! i2c { } } -#[cfg(feature = "device-selected")] i2c! { I2C1: (i2c1, i2c1en, i2c1rst, apb1enr, apb1rstr), } @@ -169,12 +160,10 @@ i2c! { I2C2: (i2c2, i2c2en, i2c2rst, apb1enr, apb1rstr), } -#[cfg(feature = "device-selected")] // It's s needed for the impls, but rustc doesn't recognize that #[allow(dead_code)] type I2cRegisterBlock = crate::stm32::i2c1::RegisterBlock; -#[cfg(feature = "device-selected")] impl I2c where I2C: Deref, @@ -273,7 +262,6 @@ where } } -#[cfg(feature = "device-selected")] impl WriteRead for I2c where I2C: Deref, @@ -343,7 +331,6 @@ where } } -#[cfg(feature = "device-selected")] impl Write for I2c where I2C: Deref, diff --git a/src/lib.rs b/src/lib.rs index 9df724b..abc82b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,14 +12,25 @@ pub use stm32f0::stm32f0x1 as stm32; #[cfg(any(feature = "stm32f042", feature = "stm32f072"))] pub use stm32f0::stm32f0x2 as stm32; +#[cfg(feature = "device-selected")] pub mod adc; +#[cfg(feature = "device-selected")] pub mod delay; +#[cfg(feature = "device-selected")] pub mod gpio; +#[cfg(feature = "device-selected")] pub mod i2c; +#[cfg(feature = "device-selected")] pub mod prelude; +#[cfg(feature = "device-selected")] pub mod rcc; +#[cfg(feature = "device-selected")] pub mod serial; +#[cfg(feature = "device-selected")] pub mod spi; +#[cfg(feature = "device-selected")] pub mod time; +#[cfg(feature = "device-selected")] pub mod timers; +#[cfg(feature = "device-selected")] pub mod watchdog; diff --git a/src/rcc.rs b/src/rcc.rs index cb1ebf4..3b797e9 100644 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -1,53 +1,47 @@ -#[cfg(feature="device-selected")] use crate::stm32::rcc::cfgr::SWW; use crate::time::Hertz; -/// Extension trait that constrains the `RCC` peripheral +/// Extension trait that sets up the `RCC` peripheral pub trait RccExt { - /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions - fn constrain(self) -> Rcc; + /// Configure the clocks of the RCC peripheral + fn configure(self) -> CFGR; } -#[cfg(feature = "device-selected")] impl RccExt for crate::stm32::RCC { - fn constrain(self) -> Rcc { - Rcc { - cfgr: CFGR { - hclk: None, - pclk: None, - sysclk: None, - clock_src: SysClkSource::HSI, - }, + fn configure(self) -> CFGR { + CFGR { + hclk: None, + pclk: None, + sysclk: None, + clock_src: SysClkSource::HSI, + rcc: self, } } } /// Constrained RCC peripheral pub struct Rcc { - pub cfgr: CFGR, + pub clocks: Clocks, + pub(crate) regs: crate::stm32::RCC, } -#[allow(unused)] const HSI: u32 = 8_000_000; // Hz -#[allow(unused)] const HSI48: u32 = 48_000_000; // Hz - (available on STM32F04x, STM32F07x and STM32F09x devices only) -#[allow(unused)] enum SysClkSource { HSI, HSE(u32), HSI48, } -#[allow(unused)] pub struct CFGR { hclk: Option, pclk: Option, sysclk: Option, clock_src: SysClkSource, + rcc: crate::stm32::RCC, } -#[cfg(feature = "device-selected")] impl CFGR { pub fn hse(mut self, freq: F) -> Self where @@ -81,7 +75,7 @@ impl CFGR { self } - pub fn freeze(self) -> Clocks { + pub fn freeze(self, flash: &mut crate::stm32::FLASH) -> Rcc { // Default to lowest frequency clock on all systems. let sysclk = self.sysclk.unwrap_or(HSI); @@ -150,11 +144,8 @@ impl CFGR { let ppre: u8 = 1 << (ppre_bits - 0b011); let pclk = hclk / cast::u32(ppre); - let rcc = unsafe { &*crate::stm32::RCC::ptr() }; - // adjust flash wait states unsafe { - let flash = &*crate::stm32::FLASH::ptr(); flash.acr.write(|w| { w.latency().bits(if sysclk <= 24_000_000 { 0b000 @@ -169,23 +160,22 @@ impl CFGR { // Enable the requested clock match self.clock_src { SysClkSource::HSE(_) => { - rcc.cr + self.rcc + .cr .modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed()); - while !rcc.cr.read().hserdy().bit_is_set() {} + while !self.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() {} + self.rcc.cr2.modify(|_, w| w.hsi48on().set_bit()); + while self.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() {} + self.rcc.cr.write(|w| w.hsion().set_bit()); + while self.rcc.cr.read().hsirdy().bit_is_clear() {} } }; - let rcc = unsafe { &*crate::stm32::RCC::ptr() }; - // Set up rcc based on above calculated configuration. // Enable PLL @@ -197,13 +187,14 @@ impl CFGR { }; // Set PLL source and multiplier - rcc.cfgr + self.rcc + .cfgr .write(|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() {} + self.rcc.cr.write(|w| w.pllon().set_bit()); + while self.rcc.cr.read().pllrdy().bit_is_clear() {} - rcc.cfgr.modify(|_, w| unsafe { + self.rcc.cfgr.modify(|_, w| unsafe { w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll() }); } else { @@ -214,7 +205,7 @@ impl CFGR { }; // use HSI as source - rcc.cfgr.write(|w| unsafe { + self.rcc.cfgr.write(|w| unsafe { w.ppre() .bits(ppre_bits) .hpre() @@ -223,11 +214,13 @@ impl CFGR { .variant(sw_var) }); } - - Clocks { - hclk: Hertz(hclk), - pclk: Hertz(pclk), - sysclk: Hertz(sysclk), + Rcc { + clocks: Clocks { + hclk: Hertz(hclk), + pclk: Hertz(pclk), + sysclk: Hertz(sysclk), + }, + regs: self.rcc, } } } diff --git a/src/serial.rs b/src/serial.rs index d8d668f..1e8fbb1 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -2,39 +2,44 @@ //! //! This only implements the usual asynchronous bidirectional 8-bit transfers, everything else is missing //! -//! # Example -//! Serial Echo +//! # Examples //! ``` no_run //! use stm32f0xx_hal as hal; //! -//! use crate::hal::stm32; //! use crate::hal::prelude::*; //! use crate::hal::serial::Serial; +//! use crate::hal::stm32; +//! //! use nb::block; //! -//! let mut p = stm32::Peripherals::take().unwrap(); +//! cortex_m::interrupt::free(|cs| { +//! let rcc = p.RCC.configure().sysclk(48.mhz()).freeze(); +//! +//! let gpioa = p.GPIOA.split(&mut rcc); //! -//! let mut led = gpioa.pa1.into_push_pull_pull_output(); -//! let rcc = p.RCC.constrain().cfgr.freeze(); -//! let mut timer = Timer::tim1(p.TIM1, Hertz(1), clocks); -//! loop { -//! led.toggle(); -//! block!(timer.wait()).ok(); -//! } +//! let tx = gpioa.pa9.into_alternate_af1(cs); +//! let rx = gpioa.pa10.into_alternate_af1(cs); +//! +//! let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc); +//! +//! let (mut tx, mut rx) = serial.split(); +//! +//! loop { +//! let received = block!(rx.read()).unwrap(); +//! block!(tx.write(received)).ok(); +//! } +//! }); //! ``` -#[allow(unused)] use core::{ fmt::{Result, Write}, ops::Deref, ptr, }; -#[allow(unused)] use embedded_hal::prelude::*; -#[allow(unused)] -use crate::{gpio::*, rcc::Clocks, time::Bps}; +use crate::{gpio::*, rcc::Rcc, time::Bps}; /// Serial error #[derive(Debug)] @@ -64,7 +69,6 @@ pub enum Event { pub trait TxPin {} pub trait RxPin {} -#[cfg(feature = "device-selected")] macro_rules! usart_pins { ($($USART:ident => { tx => [$($tx:ty),+ $(,)*], @@ -182,14 +186,12 @@ usart_pins! { } /// Serial abstraction -#[allow(unused)] pub struct Serial { usart: USART, pins: (TXPIN, RXPIN), } /// Serial receiver -#[allow(unused)] pub struct Rx { // This is ok, because the USART types only contains PhantomData usart: *const USART, @@ -199,7 +201,6 @@ pub struct Rx { unsafe impl Send for Rx {} /// Serial transmitter -#[allow(unused)] pub struct Tx { // This is ok, because the USART types only contains PhantomData usart: *const USART, @@ -208,26 +209,22 @@ pub struct Tx { // NOTE(unsafe) Required to allow protected shared access in handlers unsafe impl Send for Tx {} -#[cfg(feature = "device-selected")] macro_rules! usart { ($($USART:ident: ($usart:ident, $usartXen:ident, $apbenr:ident),)+) => { $( use crate::stm32::$USART; impl Serial<$USART, TXPIN, RXPIN> { /// Creates a new serial instance - pub fn $usart(usart: $USART, pins: (TXPIN, RXPIN), baud_rate: Bps, clocks: Clocks) -> Self + pub fn $usart(usart: $USART, pins: (TXPIN, RXPIN), baud_rate: Bps, rcc: &mut Rcc) -> Self where TXPIN: TxPin<$USART>, RXPIN: RxPin<$USART>, { - // NOTE(unsafe) This executes only during initialisation - let rcc = unsafe { &(*crate::stm32::RCC::ptr()) }; - // Enable clock for USART - rcc.$apbenr.modify(|_, w| w.$usartXen().set_bit()); + rcc.regs.$apbenr.modify(|_, w| w.$usartXen().set_bit()); // Calculate correct baudrate divisor on the fly - let brr = clocks.pclk().0 / baud_rate.0; + let brr = rcc.clocks.pclk().0 / baud_rate.0; usart.brr.write(|w| unsafe { w.bits(brr) }); // Reset other registers to disable advanced USART features @@ -274,7 +271,6 @@ macro_rules! usart { } } -#[cfg(feature = "device-selected")] usart! { USART1: (usart1, usart1en, apb2enr), } @@ -307,10 +303,8 @@ usart! { // It's s needed for the impls, but rustc doesn't recognize that #[allow(dead_code)] -#[cfg(feature = "device-selected")] type SerialRegisterBlock = crate::stm32::usart1::RegisterBlock; -#[cfg(feature = "device-selected")] impl embedded_hal::serial::Read for Rx where USART: Deref, @@ -339,7 +333,6 @@ where } } -#[cfg(feature = "device-selected")] impl embedded_hal::serial::Write for Tx where USART: Deref, @@ -375,7 +368,6 @@ where } } -#[cfg(feature = "device-selected")] impl Serial where USART: Deref, @@ -397,7 +389,6 @@ where } } -#[cfg(feature = "device-selected")] impl Write for Tx where Tx: embedded_hal::serial::Write, diff --git a/src/spi.rs b/src/spi.rs index d7364b5..947a43f 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -13,56 +13,51 @@ //! use crate::hal::prelude::*; //! use crate::hal::spi::{Spi, Mode, Phase, Polarity}; //! -//! let p = stm32::Peripherals::take().unwrap(); -//! let clcks = p.RCC.constrain().cfgr.freeze(); +//! cortex_m::interrupt::free(|cs| { +//! let mut p = stm32::Peripherals::take().unwrap(); +//! let mut rcc = p.RCC.constrain().freeze(&mut p.FLASH); //! -//! let gpioa = p.GPIOA.split(); +//! let gpioa = p.GPIOA.split(&mut rcc); //! -//! // Configure pins for SPI -//! let sck = gpioa.pa5.into_alternate_af0(); -//! let miso = gpioa.pa6.into_alternate_af0(); -//! let mosi = gpioa.pa7.into_alternate_af0(); +//! // 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(), clocks); +//! // 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(); -//! } +//! let mut data = [ 0 ]; +//! loop { +//! spi.transfer(&mut data).unwrap(); +//! } +//! }); //! ``` -#[allow(unused)] use core::{ops::Deref, ptr}; -#[allow(unused)] use nb; pub use embedded_hal::spi::{Mode, Phase, Polarity}; // TODO Put this inside the macro // Currently that causes a compiler panic -#[cfg(feature = "device-selected")] use crate::stm32::SPI1; #[cfg(any( feature = "stm32f030x8", feature = "stm32f030xc", feature = "stm32f070xb", - feature = "stm32f072", feature = "stm32f091", ))] use crate::stm32::SPI2; -#[allow(unused)] use crate::gpio::*; -#[allow(unused)] -use crate::rcc::Clocks; +use crate::rcc::{Clocks, Rcc}; -#[allow(unused)] use crate::time::Hertz; /// SPI error @@ -79,7 +74,6 @@ pub enum Error { } /// SPI abstraction -#[allow(unused)] pub struct Spi { spi: SPI, pins: (SCKPIN, MISOPIN, MOSIPIN), @@ -89,7 +83,6 @@ pub trait SckPin {} pub trait MisoPin {} pub trait MosiPin {} -#[cfg(feature = "device-selected")] macro_rules! spi_pins { ($($SPI:ident => { sck => [$($sck:ty),+ $(,)*], @@ -110,7 +103,6 @@ macro_rules! spi_pins { } } -#[cfg(feature = "device-selected")] spi_pins! { SPI1 => { sck => [gpioa::PA5>, gpiob::PB3>], @@ -174,7 +166,6 @@ spi_pins! { } } -#[allow(unused)] macro_rules! spi { ($($SPI:ident: ($spi:ident, $spiXen:ident, $spiXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => { $( @@ -185,7 +176,7 @@ macro_rules! spi { pins: (SCKPIN, MISOPIN, MOSIPIN), mode: Mode, speed: F, - clocks: Clocks, + rcc: &mut Rcc, ) -> Self where SCKPIN: SckPin<$SPI>, @@ -193,23 +184,20 @@ macro_rules! spi { MOSIPIN: MosiPin<$SPI>, F: Into, { - // NOTE(unsafe) This executes only during initialisation - let rcc = unsafe { &(*crate::stm32::RCC::ptr()) }; - /* Enable clock for SPI */ - rcc.$apbenr.modify(|_, w| w.$spiXen().set_bit()); + rcc.regs.$apbenr.modify(|_, w| w.$spiXen().set_bit()); /* Reset SPI */ - rcc.$apbrstr.modify(|_, w| w.$spiXrst().set_bit()); - rcc.$apbrstr.modify(|_, w| w.$spiXrst().clear_bit()); - Spi { spi, pins }.spi_init(mode, speed, clocks) + rcc.regs.$apbrstr.modify(|_, w| w.$spiXrst().set_bit()); + rcc.regs.$apbrstr.modify(|_, w| w.$spiXrst().clear_bit()); + + Spi { spi, pins }.spi_init(mode, speed, rcc.clocks) } } )+ } } -#[cfg(feature = "device-selected")] spi! { SPI1: (spi1, spi1en, spi1rst, apb2enr, apb2rstr), } @@ -225,10 +213,8 @@ spi! { // It's s needed for the impls, but rustc doesn't recognize that #[allow(dead_code)] -#[cfg(feature = "device-selected")] type SpiRegisterBlock = crate::stm32::spi1::RegisterBlock; -#[cfg(feature = "device-selected")] impl Spi where SPI: Deref, @@ -299,7 +285,6 @@ where } } -#[cfg(feature = "device-selected")] impl ::embedded_hal::spi::FullDuplex for Spi where @@ -344,7 +329,6 @@ where } } -#[cfg(feature = "device-selected")] impl ::embedded_hal::blocking::spi::transfer::Default for Spi where @@ -352,7 +336,6 @@ where { } -#[cfg(feature = "device-selected")] impl ::embedded_hal::blocking::spi::write::Default for Spi where diff --git a/src/timers.rs b/src/timers.rs index f29637f..42c9c6e 100644 --- a/src/timers.rs +++ b/src/timers.rs @@ -13,27 +13,31 @@ //! use crate::hal::timers::*; //! use nb::block; //! -//! let mut p = stm32::Peripherals::take().unwrap(); +//! cortex_m::interrupt::free(|cs| { +//! let mut p = stm32::Peripherals::take().unwrap(); +//! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH); //! -//! let mut led = gpioa.pa1.into_push_pull_pull_output(); -//! let rcc = p.RCC.constrain().cfgr.freeze(); -//! let mut timer = Timer::tim1(p.TIM1, Hertz(1), clocks); -//! loop { -//! led.toggle(); -//! block!(timer.wait()).ok(); -//! } +//! 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; +use crate::rcc::{Clocks, Rcc}; + +use crate::time::Hertz; use embedded_hal::timer::{CountDown, Periodic}; use nb; use void::Void; -use crate::time::Hertz; - /// Hardware timers pub struct Timer { clocks: Clocks, @@ -48,12 +52,15 @@ pub enum Event { impl Timer { /// Configures the SYST clock as a periodic count down timer - pub fn syst(mut syst: SYST, timeout: T, clocks: Clocks) -> Self + pub fn syst(mut syst: SYST, timeout: T, rcc: &Rcc) -> Self where T: Into, { syst.set_clock_source(SystClkSource::Core); - let mut timer = Timer { tim: syst, clocks }; + let mut timer = Timer { + tim: syst, + clocks: rcc.clocks, + }; timer.start(timeout); timer } @@ -106,7 +113,6 @@ impl CountDown for Timer { impl Periodic for Timer {} -#[allow(unused)] macro_rules! timers { ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => { $( @@ -116,20 +122,17 @@ macro_rules! timers { // even if the `$TIM` are non overlapping (compare to the `free` function below // which just works) /// Configures a TIM peripheral as a periodic count down timer - pub fn $tim(tim: $TIM, timeout: T, clocks: Clocks) -> Self + pub fn $tim(tim: $TIM, timeout: T, rcc: &mut Rcc) -> Self where T: Into, { - // NOTE(unsafe) This executes only during initialisation - let rcc = unsafe { &(*crate::stm32::RCC::ptr()) }; - // enable and reset peripheral to a clean slate state - rcc.$apbenr.modify(|_, w| w.$timXen().set_bit()); - rcc.$apbrstr.modify(|_, w| w.$timXrst().set_bit()); - rcc.$apbrstr.modify(|_, w| w.$timXrst().clear_bit()); + rcc.regs.$apbenr.modify(|_, w| w.$timXen().set_bit()); + rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().set_bit()); + rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().clear_bit()); let mut timer = Timer { - clocks, + clocks: rcc.clocks, tim, }; timer.start(timeout); @@ -211,7 +214,6 @@ macro_rules! timers { } } -#[cfg(feature = "device-selected")] timers! { TIM1: (tim1, tim1en, tim1rst, apb2enr, apb2rstr), TIM3: (tim3, tim3en, tim3rst, apb1enr, apb1rstr), diff --git a/src/watchdog.rs b/src/watchdog.rs index a3fb569..8e4dec3 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -41,20 +41,16 @@ //! // Whoops, got stuck, the watchdog issues a reset after 10 ms //! iwdg.feed(); //! ``` -#[allow(unused)] use embedded_hal::watchdog; -#[cfg(feature = "device-selected")] use crate::stm32::IWDG; use crate::time::Hertz; -#[cfg(feature = "device-selected")] /// Watchdog instance pub struct Watchdog { iwdg: IWDG, } -#[cfg(feature = "device-selected")] impl watchdog::Watchdog for Watchdog { /// Feed the watchdog, so that at least one `period` goes by before the next /// reset @@ -93,14 +89,12 @@ impl Into for Hertz { } } -#[cfg(feature = "device-selected")] impl Watchdog { pub fn new(iwdg: IWDG) -> Self { Self { iwdg } } } -#[cfg(feature = "device-selected")] impl watchdog::WatchdogEnable for Watchdog { type Time = IwdgTimeout; fn start(&mut self, period: T)