Compare commits

..

1 Commits

Author SHA1 Message Date
Daniel Egger 40ffd3f189 Crude translation for embedded-hal 1.0.0-alpha.1 2 years ago
  1. 13
      CHANGELOG.md
  2. 16
      Cargo.toml
  3. 4
      examples/blinky.rs
  4. 6
      examples/blinky_adc.rs
  5. 4
      examples/blinky_delay.rs
  6. 10
      examples/blinky_multiple.rs
  7. 4
      examples/blinky_timer.rs
  8. 4
      examples/flash_systick.rs
  9. 4
      examples/flash_systick_fancier.rs
  10. 2
      examples/i2c_find_address.rs
  11. 8
      examples/led_hal_button_irq.rs
  12. 4
      examples/serial_echo.rs
  13. 8
      examples/serial_spi_bridge.rs
  14. 20
      examples/spi_hal_apa102c.rs
  15. 17
      examples/usb_serial.rs
  16. 16
      examples/watchdog.rs
  17. 17
      src/adc.rs
  18. 39
      src/delay.rs
  19. 84
      src/gpio.rs
  20. 6
      src/i2c.rs
  21. 8
      src/prelude.rs
  22. 19
      src/serial.rs
  23. 105
      src/spi.rs
  24. 20
      src/timers.rs
  25. 73
      src/tsc.rs
  26. 13
      src/usb.rs
  27. 14
      src/watchdog.rs

13
CHANGELOG.md

@ -7,16 +7,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## [v0.17.1] - 2020-08-30
### Changed
- Simplify USB PA11/12 remapping for STM32F042x via `usb_bus.usb_remap()` function.
### Added
- Complete the `TscPin` trait implementation for all touch pins in the f0 family
## [v0.17.0] - 2020-06-27
### Changed
@ -214,8 +204,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Updated stm32f0 dependency to v0.5.0.
- Interrupt handler to new #[interrupt] attribute
[Unreleased]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.17.1...HEAD
[v0.17.1]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.17.0...v0.17.1
[Unreleased]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.17.0...HEAD
[v0.17.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.16.0...v0.17.0
[v0.16.0]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.15.2...v0.16.0
[v0.15.2]: https://github.com/stm32-rs/stm32f0xx-hal/compare/v0.15.1...v0.15.2

16
Cargo.toml

@ -23,27 +23,27 @@ license = "0BSD"
name = "stm32f0xx-hal"
readme = "README.md"
repository = "https://github.com/stm32-rs/stm32f0xx-hal"
version = "0.17.1"
version = "0.17.0"
[package.metadata.docs.rs]
features = ["stm32f042", "rt", "stm32-usbd"]
targets = ["thumbv6m-none-eabi"]
[dependencies]
bare-metal = { version = "1.0.0" }
bare-metal = { version = "0.2" }
cast = { version = "0.2", default-features = false }
cortex-m = "0.6"
embedded-hal = { version = "0.2", features = ["unproven"] }
stm32f0 = "0.12.1"
nb = "1.0"
embedded-hal = { version = "1.0.0-alpha.1" }
stm32f0 = "0.11"
nb = "0.1"
void = { version = "1.0", default-features = false }
stm32-usbd = { version = "0.5.1", features = ["ram_access_2x16"], optional = true }
stm32-usbd = { version = "0.5.0", features = ["ram_access_2x16"], optional = true }
[dev-dependencies]
cortex-m-rt = "0.6"
panic-halt = "0.2"
usb-device = "0.2.7"
usbd-serial = "0.1.1"
usb-device = "0.2.3"
usbd-serial = "0.1.0"
[features]
device-selected = []

4
examples/blinky.rs

@ -22,11 +22,11 @@ fn main() -> ! {
loop {
// Turn PA1 on a million times in a row
for _ in 0..1_000_000 {
led.set_high().ok();
led.try_set_high().ok();
}
// Then turn PA1 off a million times in a row
for _ in 0..1_000_000 {
led.set_low().ok();
led.try_set_low().ok();
}
}
}

6
examples/blinky_adc.rs

@ -33,9 +33,9 @@ fn main() -> ! {
let mut adc = Adc::new(p.ADC, &mut rcc);
loop {
led.toggle().ok();
led.try_toggle().ok();
let time: u16 = if let Ok(val) = adc.read(&mut an_in) as Result<u16, _> {
let time: u16 = if let Ok(val) = adc.try_read(&mut an_in) as Result<u16, _> {
/* shift the value right by 3, same as divide by 8, reduces
the 0-4095 range into something approximating 1-512 */
(val >> 3) + 1
@ -43,7 +43,7 @@ fn main() -> ! {
1000
};
delay.delay_ms(time);
delay.try_delay_ms(time).ok();
}
}

4
examples/blinky_delay.rs

@ -24,8 +24,8 @@ fn main() -> ! {
let mut delay = Delay::new(cp.SYST, &rcc);
loop {
led.toggle().ok();
delay.delay_ms(1_000_u16);
led.try_toggle().ok();
delay.try_delay_ms(1_000_u16).ok();
}
}

10
examples/blinky_multiple.rs

@ -13,7 +13,7 @@ use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (pac::Peripherals::take(), Peripherals::take()) {
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut p.FLASH);
let mut rcc = p.RCC.configure().sysclk(8_u32.mhz()).freeze(&mut p.FLASH);
let gpioa = p.GPIOA.split(&mut rcc);
let gpiob = p.GPIOB.split(&mut rcc);
@ -34,14 +34,14 @@ fn main() -> ! {
let mut leds = [led1.downgrade(), led2.downgrade()];
loop {
for l in &mut leds {
l.set_high().ok();
l.try_set_high().ok();
}
delay.delay_ms(1_000_u16);
delay.try_delay_ms(1_000_u16).ok();
for l in &mut leds {
l.set_low().ok();
l.try_set_low().ok();
}
delay.delay_ms(1_000_u16);
delay.try_delay_ms(1_000_u16).ok();
}
}

4
examples/blinky_timer.rs

@ -23,10 +23,10 @@ fn main() -> ! {
let mut timer = Timer::tim1(p.TIM1, Hertz(1), &mut rcc);
loop {
led.toggle().ok();
led.try_toggle().ok();
// Wait for the timer to expire
nb::block!(timer.wait()).ok();
nb::block!(timer.try_wait()).ok();
}
}

4
examples/flash_systick.rs

@ -68,13 +68,13 @@ fn SysTick() {
// Check state variable, keep LED off most of the time and turn it on every 10th tick
if *STATE < 10 {
// Turn off the LED
led.set_low().ok();
led.try_set_low().ok();
// And now increment state variable
*STATE += 1;
} else {
// Turn on the LED
led.set_high().ok();
led.try_set_high().ok();
// And set new state variable back to 0
*STATE = 0;

4
examples/flash_systick_fancier.rs

@ -73,13 +73,13 @@ fn SysTick() {
// Check state variable, keep LED off most of the time and turn it on every 10th tick
if *STATE < 10 {
// Turn off the LED
led.set_low().ok();
led.try_set_low().ok();
// And now increment state variable
*STATE += 1;
} else {
// Turn on the LED
led.set_high().ok();
led.try_set_high().ok();
// And set new state variable back to 0
*STATE = 0;

2
examples/i2c_find_address.rs

@ -33,7 +33,7 @@ fn main() -> ! {
// The write method sends the specified address and checks for acknowledgement;
// if no ack is given by the slave device the result is Err(), otherwise Ok()
// Since we only care for an acknowledgement the data sent can be empty
if i2c.write(add, &[]).is_ok() {
if i2c.try_write(add, &[]).is_ok() {
_devices += 1;
}
}

8
examples/led_hal_button_irq.rs

@ -49,7 +49,7 @@ fn main() -> ! {
let mut led = gpioa.pa1.into_push_pull_output(cs);
// Turn off LED
led.set_low().ok();
led.try_set_low().ok();
// Initialise delay provider
let delay = Delay::new(cp.SYST, &rcc);
@ -96,13 +96,13 @@ fn EXTI0_1() {
INT.borrow(cs).borrow_mut().deref_mut(),
) {
// Turn on LED
led.set_high().ok();
led.try_set_high().ok();
// Wait a second
delay.delay_ms(1_000_u16);
delay.try_delay_ms(1_000_u16).ok();
// Turn off LED
led.set_low().ok();
led.try_set_low().ok();
// Clear event triggering the interrupt
exti.pr.write(|w| w.pif1().set_bit());

4
examples/serial_echo.rs

@ -28,10 +28,10 @@ fn main() -> ! {
loop {
// Wait for reception of a single byte
let received = nb::block!(serial.read()).unwrap();
let received = nb::block!(serial.try_read()).unwrap();
// Send back previously received byte and wait for completion
nb::block!(serial.write(received)).ok();
nb::block!(serial.try_write(received)).ok();
}
}

8
examples/serial_spi_bridge.rs

@ -57,10 +57,10 @@ fn main() -> ! {
let mut data = [0];
loop {
let serial_received = block!(rx.read()).unwrap();
spi.write(&[serial_received]).ok();
let spi_received = spi.transfer(&mut data).unwrap();
block!(tx.write(spi_received[0])).ok();
let serial_received = block!(rx.try_read()).unwrap();
spi.try_write(&[serial_received]).ok();
let spi_received = spi.try_transfer(&mut data).unwrap();
block!(tx.try_write(spi_received[0])).ok();
}
}

20
examples/spi_hal_apa102c.rs

@ -37,30 +37,30 @@ fn main() -> ! {
});
// Configure SPI with 100kHz rate
let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 100_000.hz(), &mut rcc);
let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 100_000_u32.hz(), &mut rcc);
// Cycle through colors on 16 chained APA102C LEDs
loop {
for r in 0..255 {
let _ = spi.write(&[0, 0, 0, 0]);
let _ = spi.try_write(&[0, 0, 0, 0]);
for _i in 0..16 {
let _ = spi.write(&[0b1110_0001, 0, 0, r]);
let _ = spi.try_write(&[0b1110_0001, 0, 0, r]);
}
let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]);
let _ = spi.try_write(&[0xFF, 0xFF, 0xFF, 0xFF]);
}
for b in 0..255 {
let _ = spi.write(&[0, 0, 0, 0]);
let _ = spi.try_write(&[0, 0, 0, 0]);
for _i in 0..16 {
let _ = spi.write(&[0b1110_0001, b, 0, 0]);
let _ = spi.try_write(&[0b1110_0001, b, 0, 0]);
}
let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]);
let _ = spi.try_write(&[0xFF, 0xFF, 0xFF, 0xFF]);
}
for g in 0..255 {
let _ = spi.write(&[0, 0, 0, 0]);
let _ = spi.try_write(&[0, 0, 0, 0]);
for _i in 0..16 {
let _ = spi.write(&[0b1110_0001, 0, g, 0]);
let _ = spi.try_write(&[0b1110_0001, 0, g, 0]);
}
let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]);
let _ = spi.try_write(&[0xFF, 0xFF, 0xFF, 0xFF]);
}
}
}

17
examples/usb_serial.rs

@ -15,6 +15,13 @@ use usbd_serial::{SerialPort, USB_CLASS_CDC};
fn main() -> ! {
let mut dp = pac::Peripherals::take().unwrap();
/* Uncomment the following lines if you have a chip in TSSOP20 (STM32F042F)
or UFQFPN28 (STM32F042G) package
This code enables clock for SYSCFG and remaps USB pins to PA9 and PA10.
*/
//dp.RCC.apb2enr.modify(|_, w| w.syscfgen().set_bit());
//dp.SYSCFG.cfgr1.modify(|_, w| w.pa11_pa12_rmp().remapped());
let mut rcc = dp
.RCC
.configure()
@ -36,20 +43,10 @@ fn main() -> ! {
pin_dm: gpioa.pa11,
pin_dp: gpioa.pa12,
};
let usb_bus = UsbBus::new(usb);
let mut serial = SerialPort::new(&usb_bus);
/*
* IMPORTANT: if you have a chip in TSSOP20 (STM32F042F) or UFQFPN28 (STM32F042G) package,
* and want to use USB, make sure you call `remap_pins(rcc, syscfg)`, otherwise the device will not enumerate.
*
* Uncomment the following function if the situation above applies to you.
*/
//usb_bus.remap_pins();
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")

16
examples/watchdog.rs

@ -37,17 +37,17 @@ fn main() -> ! {
serial.write_str("RESET \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);
watchdog.try_start(Hertz(1)).ok();
delay.try_delay_ms(500_u16).ok();
watchdog.try_feed().ok();
delay.try_delay_ms(500_u16).ok();
watchdog.try_feed().ok();
delay.try_delay_ms(500_u16).ok();
serial.write_str("This will get printed \r\n").ok();
watchdog.feed();
watchdog.try_feed().ok();
// Now a reset happens while delaying
delay.delay_ms(1500_u16);
delay.try_delay_ms(1500_u16).ok();
serial.write_str("This won't\r\n").ok();
}

17
src/adc.rs

@ -191,8 +191,7 @@ macro_rules! adc_pins {
$(
impl Channel<Adc> for $pin {
type ID = u8;
fn channel() -> u8 { $chan }
const CHANNEL : u8 = $chan;
}
)+
};
@ -295,7 +294,7 @@ impl VTemp {
vtemp.enable(adc);
if let Some(dref) = delay {
dref.delay_us(2_u16);
dref.try_delay_us(2_u16).ok();
} else {
// Double read of vdda to allow sufficient startup time for the temp sensor
VRef::read_vdda(adc);
@ -305,7 +304,7 @@ impl VTemp {
let prev_cfg = adc.default_cfg();
let vtemp_val = adc.read(&mut vtemp).unwrap();
let vtemp_val = adc.try_read(&mut vtemp).unwrap();
if !vtemp_preenable {
vtemp.disable(adc);
@ -346,11 +345,11 @@ impl VRef {
let prev_cfg = adc.default_cfg();
let vref_val: u32 = if vref.is_enabled(&adc) {
adc.read(&mut vref).unwrap()
adc.try_read(&mut vref).unwrap()
} else {
vref.enable(adc);
let ret = adc.read(&mut vref).unwrap();
let ret = adc.try_read(&mut vref).unwrap();
vref.disable(adc);
ret
@ -535,7 +534,7 @@ impl Adc {
/// 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 v: u32 = self.try_read(pin).unwrap();
let max_samp = u32::from(self.max_sample());
(v * vdda / max_samp) as u16
@ -612,9 +611,9 @@ where
{
type Error = ();
fn read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
fn try_read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
self.power_up();
let res = self.convert(PIN::channel());
let res = self.convert(PIN::CHANNEL);
self.power_down();
Ok(res.into())
}

39
src/delay.rs

@ -26,6 +26,7 @@
//! ```
use cast::{u16, u32};
use core::convert::Infallible;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
@ -60,35 +61,45 @@ impl Delay {
}
impl DelayMs<u32> for Delay {
type Error = Infallible;
// At 48 MHz (the maximum frequency), calling delay_us with ms * 1_000 directly overflows at 0x15D86 (just over the max u16 value)
// So we implement a separate, higher level, delay loop
fn delay_ms(&mut self, mut ms: u32) {
fn try_delay_ms(&mut self, mut ms: u32) -> Result<(), Self::Error> {
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);
self.try_delay_us(current_ms * 1_000)?;
ms -= current_ms;
}
Ok(())
}
}
impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
type Error = Infallible;
fn try_delay_ms(&mut self, ms: u16) -> Result<(), Self::Error> {
// Call delay_us directly, so we don't have to use the additional
// delay loop the u32 variant uses
self.delay_us(u32(ms) * 1_000);
self.try_delay_us(u32(ms) * 1_000)
}
}
impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u16(ms));
type Error = Infallible;
fn try_delay_ms(&mut self, ms: u8) -> Result<(), Self::Error> {
self.try_delay_ms(u16(ms))
}
}
// At 48MHz (the maximum frequency), this overflows at approx. 2^32 / 48 = 89 seconds
impl DelayUs<u32> for Delay {
fn delay_us(&mut self, us: u32) {
type Error = Infallible;
fn try_delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
// Here less than maximum is used so we have some play if there's a long running interrupt.
const MAX_TICKS: u32 = 0x007F_FFFF;
@ -109,17 +120,23 @@ impl DelayUs<u32> for Delay {
// from 0 to 0xFFFF
while (start_count.wrapping_sub(SYST::get_current()) % SYSTICK_RANGE) < current_ticks {}
}
Ok(())
}
}
impl DelayUs<u16> for Delay {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32(us))
type Error = Infallible;
fn try_delay_us(&mut self, us: u16) -> Result<(), Self::Error> {
self.try_delay_us(u32(us))
}
}
impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
type Error = Infallible;
fn try_delay_us(&mut self, us: u8) -> Result<(), Self::Error> {
self.try_delay_us(u32(us))
}
}

84
src/gpio.rs

@ -15,10 +15,10 @@ pub trait GpioExt {
}
trait GpioRegExt {
fn is_low(&self, pos: u8) -> bool;
fn is_set_low(&self, pos: u8) -> bool;
fn set_high(&self, pos: u8);
fn set_low(&self, pos: u8);
fn try_is_low(&self, pos: u8) -> bool;
fn try_is_set_low(&self, pos: u8) -> bool;
fn try_set_high(&self, pos: u8);
fn try_set_low(&self, pos: u8);
}
/// Alternate function 0
@ -71,7 +71,7 @@ pub struct Output<MODE> {
/// Push pull output (type state)
pub struct PushPull;
use embedded_hal::digital::v2::{toggleable, InputPin, OutputPin, StatefulOutputPin};
use embedded_hal::digital::{toggleable, InputPin, OutputPin, StatefulOutputPin};
/// Fully erased pin
pub struct Pin<MODE> {
@ -88,13 +88,13 @@ unsafe impl<MODE> Send for Pin<MODE> {}
impl<MODE> StatefulOutputPin for Pin<Output<MODE>> {
#[inline(always)]
fn is_set_high(&self) -> Result<bool, Self::Error> {
self.is_set_low().map(|v| !v)
fn try_is_set_high(&self) -> Result<bool, Self::Error> {
self.try_is_set_low().map(|v| !v)
}
#[inline(always)]
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*self.port).is_set_low(self.i) })
fn try_is_set_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*self.port).try_is_set_low(self.i) })
}
}
@ -102,14 +102,14 @@ impl<MODE> OutputPin for Pin<Output<MODE>> {
type Error = Infallible;
#[inline(always)]
fn set_high(&mut self) -> Result<(), Self::Error> {
unsafe { (*self.port).set_high(self.i) };
fn try_set_high(&mut self) -> Result<(), Self::Error> {
unsafe { (*self.port).try_set_high(self.i) };
Ok(())
}
#[inline(always)]
fn set_low(&mut self) -> Result<(), Self::Error> {
unsafe { (*self.port).set_low(self.i) }
fn try_set_low(&mut self) -> Result<(), Self::Error> {
unsafe { (*self.port).try_set_low(self.i) }
Ok(())
}
}
@ -120,13 +120,13 @@ impl InputPin for Pin<Output<OpenDrain>> {
type Error = Infallible;
#[inline(always)]
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
fn try_is_high(&self) -> Result<bool, Self::Error> {
self.try_is_low().map(|v| !v)
}
#[inline(always)]
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*self.port).is_low(self.i) })
fn try_is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*self.port).try_is_low(self.i) })
}
}
@ -134,35 +134,35 @@ impl<MODE> InputPin for Pin<Input<MODE>> {
type Error = Infallible;
#[inline(always)]
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
fn try_is_high(&self) -> Result<bool, Self::Error> {
self.try_is_low().map(|v| !v)
}
#[inline(always)]
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*self.port).is_low(self.i) })
fn try_is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*self.port).try_is_low(self.i) })
}
}
macro_rules! gpio_trait {
($gpiox:ident) => {
impl GpioRegExt for crate::pac::$gpiox::RegisterBlock {
fn is_low(&self, pos: u8) -> bool {
fn try_is_low(&self, pos: u8) -> bool {
// NOTE(unsafe) atomic read with no side effects
self.idr.read().bits() & (1 << pos) == 0
}
fn is_set_low(&self, pos: u8) -> bool {
fn try_is_set_low(&self, pos: u8) -> bool {
// NOTE(unsafe) atomic read with no side effects
self.odr.read().bits() & (1 << pos) == 0
}
fn set_high(&self, pos: u8) {
fn try_set_high(&self, pos: u8) {
// NOTE(unsafe) atomic write to a stateless register
unsafe { self.bsrr.write(|w| w.bits(1 << pos)) }
}
fn set_low(&self, pos: u8) {
fn try_set_low(&self, pos: u8) {
// NOTE(unsafe) atomic write to a stateless register
unsafe { self.bsrr.write(|w| w.bits(1 << (pos + 16))) }
}
@ -184,7 +184,7 @@ macro_rules! gpio {
use core::marker::PhantomData;
use core::convert::Infallible;
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable};
use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin, toggleable};
use crate::{
rcc::Rcc,
pac::$GPIOX
@ -504,24 +504,24 @@ macro_rules! gpio {
}
impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
self.is_set_low().map(|v| !v)
fn try_is_set_high(&self) -> Result<bool, Self::Error> {
self.try_is_set_low().map(|v| !v)
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).is_set_low($i) })
fn try_is_set_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).try_is_set_low($i) })
}
}
impl<MODE> OutputPin for $PXi<Output<MODE>> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).set_high($i) })
fn try_set_high(&mut self) -> Result<(), Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).try_set_high($i) })
}
fn set_low(&mut self) -> Result<(), Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).set_low($i) })
fn try_set_low(&mut self) -> Result<(), Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).try_set_low($i) })
}
}
@ -530,12 +530,12 @@ macro_rules! gpio {
impl InputPin for $PXi<Output<OpenDrain>> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
fn try_is_high(&self) -> Result<bool, Self::Error> {
self.try_is_low().map(|v| !v)
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).is_low($i) })
fn try_is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).try_is_low($i) })
}
}
@ -556,12 +556,12 @@ macro_rules! gpio {
impl<MODE> InputPin for $PXi<Input<MODE>> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
fn try_is_high(&self) -> Result<bool, Self::Error> {
self.try_is_low().map(|v| !v)
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).is_low($i) })
fn try_is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).try_is_low($i) })
}
}
)+

6
src/i2c.rs

@ -321,7 +321,7 @@ where
{
type Error = Error;
fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
fn try_write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
// Set up current slave address for writing and disable autoending
self.i2c.cr2.modify(|_, w| {
w.sadd()
@ -394,7 +394,7 @@ where
{
type Error = Error;
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
fn try_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
// Set up current address for reading
self.i2c.cr2.modify(|_, w| {
w.sadd()
@ -429,7 +429,7 @@ where
{
type Error = Error;
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
fn try_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
// Set up current slave address for writing and enable autoending
self.i2c.cr2.modify(|_, w| {
w.sadd()

8
src/prelude.rs

@ -6,10 +6,10 @@ pub use embedded_hal::watchdog::WatchdogEnable as _stm32f0xx_hal_embedded_hal_wa
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 embedded_hal::digital::InputPin as _embedded_hal_gpio_InputPin;
pub use embedded_hal::digital::OutputPin as _embedded_hal_gpio_OutputPin;
pub use embedded_hal::digital::StatefulOutputPin as _embedded_hal_gpio_StatefulOutputPin;
pub use embedded_hal::digital::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;

19
src/serial.rs

@ -64,8 +64,7 @@ use core::{
ops::Deref,
};
use embedded_hal::prelude::*;
use crate::prelude::*;
use crate::{gpio::*, rcc::Rcc, time::Bps};
use core::marker::PhantomData;
@ -430,7 +429,7 @@ where
type Error = Error;
/// Tries to read a byte from the uart
fn read(&mut self) -> nb::Result<u8, Error> {
fn try_read(&mut self) -> nb::Result<u8, Error> {
read(self.usart)
}
}
@ -443,7 +442,7 @@ where
type Error = Error;
/// Tries to read a byte from the uart
fn read(&mut self) -> nb::Result<u8, Error> {
fn try_read(&mut self) -> nb::Result<u8, Error> {
read(&*self.usart)
}
}
@ -455,13 +454,13 @@ where
type Error = Infallible;
/// Ensures that none of the previously written words are still buffered
fn flush(&mut self) -> nb::Result<(), Self::Error> {
fn try_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> {
fn try_write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
write(self.usart, byte)
}
}
@ -474,13 +473,13 @@ where
type Error = Infallible;
/// Ensures that none of the previously written words are still buffered
fn flush(&mut self) -> nb::Result<(), Self::Error> {
fn try_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> {
fn try_write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
write(&*self.usart, byte)
}
}
@ -520,7 +519,7 @@ where
fn write_str(&mut self, s: &str) -> Result {
s.as_bytes()
.iter()
.try_for_each(|c| nb::block!(self.write(*c)))
.try_for_each(|c| nb::block!(self.try_write(*c)))
.map_err(|_| core::fmt::Error)
}
}
@ -533,7 +532,7 @@ where
fn write_str(&mut self, s: &str) -> Result {
s.as_bytes()
.iter()
.try_for_each(|c| nb::block!(self.write(*c)))
.try_for_each(|c| nb::block!(self.try_write(*c)))
.map_err(|_| core::fmt::Error)
}
}

105
src/spi.rs

@ -365,27 +365,17 @@ where
fn check_read(&mut self) -> nb::Result<(), Error> {
let sr = self.spi.sr.read();
self.check_errors()?;
if !sr.rxne().bit_is_set() {
Err(nb::Error::WouldBlock)
} else {
Ok(())
}
}
fn check_errors(&mut self) -> Result<(), Error> {
let sr = self.spi.sr.read();
if sr.ovr().bit_is_set() {
Err(Error::Overrun)
Err(if sr.ovr().bit_is_set() {
nb::Error::Other(Error::Overrun)
} else if sr.modf().bit_is_set() {
Err(Error::ModeFault)
nb::Error::Other(Error::ModeFault)
} else if sr.crcerr().bit_is_set() {
Err(Error::Crc)
nb::Error::Other(Error::Crc)
} else if sr.rxne().bit_is_set() {
return Ok(());
} else {
Ok(())
}
nb::Error::WouldBlock
})
}
fn send_buffer_size(&mut self) -> u8 {
@ -404,13 +394,17 @@ where
fn check_send(&mut self) -> nb::Result<(), Error> {
let sr = self.spi.sr.read();
self.check_errors()?;
if !sr.txe().bit_is_set() {
Err(nb::Error::WouldBlock)
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() {
return Ok(());
} else {
Ok(())
}
nb::Error::WouldBlock
})
}
fn read_u8(&mut self) -> u8 {
@ -445,7 +439,7 @@ where
{
type Error = Error;
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
fn try_transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
// We want to transfer bidirectionally, make sure we're in the correct mode
self.set_bidi();
@ -460,29 +454,6 @@ where
}
}
impl<SPI, SCKPIN, MISOPIN, MOSIPIN> ::embedded_hal::spi::FullDuplex<u8>
for Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, EightBit>
where
SPI: Deref<Target = SpiRegisterBlock>,
{
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Error> {
self.check_read()?;
Ok(self.read_u8())
}
fn send(&mut self, byte: u8) -> nb::Result<(), Error> {
// We want to transfer bidirectionally, make sure we're in the correct mode
self.set_bidi();
self.check_send()?;
self.send_u8(byte);
self.check_errors().map_err(|e| nb::Error::Other(e))
}
}
impl<SPI, SCKPIN, MISOPIN, MOSIPIN> ::embedded_hal::blocking::spi::Write<u8>
for Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, EightBit>
where
@ -490,7 +461,7 @@ where
{
type Error = Error;
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
fn try_write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
let mut bufcap: u8 = 0;
// We only want to send, so we don't need to worry about the receive buffer overflowing
@ -511,33 +482,8 @@ where
}
// Do one last status register check before continuing
self.check_errors()
}
}
impl<SPI, SCKPIN, MISOPIN, MOSIPIN> ::embedded_hal::spi::FullDuplex<u16>
for Spi<SPI, SCKPIN, MISOPIN, MOSIPIN, SixteenBit>
where
SPI: Deref<Target = SpiRegisterBlock>,
{
type Error = Error;
fn read(&mut self) -> nb::Result<u16, Error> {
self.check_read()?;
Ok(self.read_u16())
}
fn send(&mut self, byte: u16) -> nb::Result<(), Error> {
// We want to transfer bidirectionally, make sure we're in the correct mode
self.set_bidi();
self.check_send()?;
self.send_u16(byte);
match self.check_errors() {
Ok(_) => Ok(()),
Err(e) => Err(nb::Error::Other(e)),
}
self.check_send().ok();
Ok(())
}
}
@ -548,7 +494,7 @@ where
{
type Error = Error;
fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
fn try_transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
// We want to transfer bidirectionally, make sure we're in the correct mode
self.set_bidi();
@ -570,7 +516,7 @@ where
{
type Error = Error;
fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
fn try_write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
// We only want to send, so we don't need to worry about the receive buffer overflowing
self.set_send_only();
@ -580,6 +526,7 @@ where
}
// Do one last status register check before continuing
self.check_errors()
self.check_send().ok();
Ok(())
}
}

20
src/timers.rs

@ -32,10 +32,10 @@ use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use crate::rcc::{Clocks, Rcc};
use core::convert::Infallible;
use crate::time::Hertz;
use embedded_hal::timer::{CountDown, Periodic};
use void::Void;
/// Hardware timers
pub struct Timer<TIM> {
@ -60,7 +60,7 @@ impl Timer<SYST> {
tim: syst,
clocks: rcc.clocks,
};
timer.start(timeout);
timer.try_start(timeout).ok();
timer
}
@ -84,9 +84,10 @@ impl Timer<SYST> {
/// Be aware that intervals less than 4 Hertz may not function properly
impl CountDown for Timer<SYST> {
type Time = Hertz;
type Error = Infallible;
/// Start the timer with a `timeout`
fn start<T>(&mut self, timeout: T)
fn try_start<T>(&mut self, timeout: T) -> Result<(), Self::Error>
where
T: Into<Hertz>,
{
@ -97,11 +98,13 @@ impl CountDown for Timer<SYST> {
self.tim.set_reload(rvr);
self.tim.clear_current();
self.tim.enable_counter();
Ok(())
}
/// Return `Ok` if the timer has wrapped
/// Automatically clears the flag and restarts the time
fn wait(&mut self) -> nb::Result<(), Void> {
fn try_wait(&mut self) -> nb::Result<(), Self::Error> {
if self.tim.has_wrapped() {
Ok(())
} else {
@ -134,7 +137,7 @@ macro_rules! timers {
clocks: rcc.clocks,
tim,
};
timer.start(timeout);
timer.try_start(timeout).ok();
timer
}
@ -172,9 +175,10 @@ macro_rules! timers {
impl CountDown for Timer<$TIM> {
type Time = Hertz;
type Error = Infallible;
/// Start the timer with a `timeout`
fn start<T>(&mut self, timeout: T)
fn try_start<T>(&mut self, timeout: T) -> Res