Skip to content

Commit

Permalink
Merge #443
Browse files Browse the repository at this point in the history
443: e-hal alpha.7 r=burrbull a=burrbull

Same as #388, but uses alpha.7

Co-authored-by: Andrey Zgarbul <zgarbul.andrey@gmail.com>
  • Loading branch information
bors[bot] and burrbull committed Feb 12, 2022
2 parents 22f1e8f + c9f823e commit aa934ca
Show file tree
Hide file tree
Showing 19 changed files with 1,111 additions and 88 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added

- Missing `DelayMs<u8>` / `DelayUs<u8>` impls for fugit::Delay
- Support of embedded-hal 1.0.0-alpha.7 [#443]
- Aliases for peripheral wrappers [#434]
- `WithPwm` trait implemented for timers with channels (internals) [#425]
- `Pwm` struct with `split` method and implementation of embedded-hal::Pwm (similar to f1xx-hal) [#425]
Expand All @@ -50,6 +51,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
[#438]: https://github.com/stm32-rs/stm32f4xx-hal/pull/438
[#439]: https://github.com/stm32-rs/stm32f4xx-hal/pull/439
[#440]: https://github.com/stm32-rs/stm32f4xx-hal/pull/440
[#443]: https://github.com/stm32-rs/stm32f4xx-hal/pull/443

### Changed

Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ embedded-dma = "0.2.0"
bare-metal = { version = "1" }
cast = { default-features = false, version = "0.3.0" }
void = { default-features = false, version = "1.0.2" }
embedded-hal = { features = ["unproven"], version = "0.2.6" }
embedded-hal = { features = ["unproven"], version = "0.2.7" }
display-interface = { version = "0.4.1", optional = true }
fugit = "0.3.3"
fugit-timer = "0.1.3"
Expand All @@ -51,6 +51,10 @@ embedded-storage = "0.2"
version = "0.3"
default-features = false

[dependencies.embedded-hal-one]
version = "1.0.0-alpha.7"
package = "embedded-hal"

[dependencies.stm32_i2s_v12x]
version = "0.2.0"
optional = true
Expand Down
16 changes: 16 additions & 0 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ macro_rules! adc_pins {
type ID = u8;
fn channel() -> u8 { $chan }
}

impl embedded_hal_one::adc::nb::Channel<pac::$adc> for $pin {
type ID = u8;
fn channel(&self) -> u8 { $chan }
}
)+
};
}
Expand Down Expand Up @@ -1070,6 +1075,17 @@ macro_rules! adc {
}
}

impl<PIN> embedded_hal_one::adc::nb::OneShot<pac::$adc_type, u16, PIN> for Adc<pac::$adc_type>
where
PIN: embedded_hal::adc::Channel<pac::$adc_type, ID=u8> + embedded_hal_one::adc::nb::Channel<pac::$adc_type, ID=u8>,
{
type Error = ();

fn read(&mut self, pin: &mut PIN) -> nb::Result<u16, Self::Error> {
self.read::<PIN>(pin)
}
}

unsafe impl PeriAddress for Adc<pac::$adc_type> {
#[inline(always)]
fn address(&self) -> u32 {
Expand Down
96 changes: 96 additions & 0 deletions src/delay/hal_1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//! Delay implementation based on general-purpose 32 bit timers and System timer (SysTick).
//!
//! TIM2 and TIM5 are a general purpose 32-bit auto-reload up/downcounter with
//! a 16-bit prescaler.

use cast::u16;
use core::convert::Infallible;
use cortex_m::peripheral::SYST;
use embedded_hal_one::delay::blocking::DelayUs;

use super::{Delay, Wait};

impl DelayUs for Delay<SYST> {
type Error = Infallible;

fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
const MAX_RVR: u32 = 0x00FF_FFFF;

let mut total_rvr = us * (self.clk.0 / 8_000_000);

while total_rvr != 0 {
let current_rvr = if total_rvr <= MAX_RVR {
total_rvr
} else {
MAX_RVR
};

self.tim.set_reload(current_rvr);
self.tim.clear_current();
self.tim.enable_counter();

// Update the tracking variable while we are waiting...
total_rvr -= current_rvr;

while !self.tim.has_wrapped() {}

self.tim.disable_counter();
}

Ok(())
}

fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> {
self.delay_us(ms * 1_000)
}
}

impl<TIM> DelayUs for Delay<TIM>
where
Self: Wait,
{
type Error = Infallible;

/// Sleep for up to 2^32-1 microseconds (~71 minutes).
fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
// Set up prescaler so that a tick takes exactly 1 µs.
//
// For example, if the clock is set to 48 MHz, with a prescaler of 48
// we'll get ticks that are 1 µs long. This means that we can write the
// delay value directly to the auto-reload register (ARR).
let psc = u16(self.clk.0 / 1_000_000).expect("Prescaler does not fit in u16");
let arr = us;
self.wait(psc, arr);

Ok(())
}

/// Sleep for up to (2^32)/2-1 milliseconds (~24 days).
/// If the `ms` value is larger than 2147483647, the code will panic.
fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> {
// See next section for explanation why the usable range is reduced.
assert!(ms <= 2_147_483_647); // (2^32)/2-1

// Set up prescaler so that a tick takes exactly 0.5 ms.
//
// For example, if the clock is set to 48 MHz, with a prescaler of 24'000
// we'll get ticks that are 0.5 ms long. This means that we can write the
// delay value multipled by two to the auto-reload register (ARR).
//
// Note that we cannot simply use a prescaler value where the tick corresponds
// to 1 ms, because then a clock of 100 MHz would correspond to a prescaler
// value of 100'000, which doesn't fit in the 16-bit PSC register.
//
// Unfortunately this means that only one half of the full 32-bit range
// can be used, but 24 days should be plenty of usable delay time.
let psc = u16(self.clk.0 / 1000 / 2).expect("Prescaler does not fit in u16");

// Since PSC = 0.5 ms, double the value for the ARR
let arr = ms << 1;

self.wait(psc, arr);

Ok(())
}
}
1 change: 1 addition & 0 deletions src/delay/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Delays

mod hal_02;
mod hal_1;

use crate::{
pac,
Expand Down
20 changes: 20 additions & 0 deletions src/dwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,26 @@ impl<T: Into<u64>> embedded_hal::blocking::delay::DelayMs<T> for Delay {
}
}

impl embedded_hal_one::delay::blocking::DelayUs for Delay {
type Error = core::convert::Infallible;

fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
// Convert us to ticks
let start = DWT::cycle_count();
let ticks = (us as u64 * self.clock.0 as u64) / 1_000_000;
Delay::delay_ticks(start, ticks);
Ok(())
}

fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> {
// Convert ms to ticks
let start = DWT::cycle_count();
let ticks = (ms as u64 * self.clock.0 as u64) / 1_000;
Delay::delay_ticks(start, ticks);
Ok(())
}
}

/// Very simple stopwatch which reads from DWT Cycle Counter to record timing.
///
/// Since DWT Cycle Counter is a 32-bit counter that wraps around to 0 on overflow,
Expand Down
58 changes: 28 additions & 30 deletions src/fmpi2c.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use core::ops::Deref;

use crate::gpio::{Const, OpenDrain, PinA, SetAlternate};
use crate::i2c::{Error, Scl, Sda};
use crate::i2c::{Error, NoAcknowledgeSource, Pins};
use crate::pac::{fmpi2c1, FMPI2C1, RCC};
use crate::rcc::{Enable, Reset};
use crate::time::{Hertz, U32Ext};

mod hal_02;
mod hal_1;

/// I2C FastMode+ abstraction
pub struct FMPI2c<I2C, PINS> {
Expand Down Expand Up @@ -67,12 +67,11 @@ where
}
}

impl<SCL, SDA, const SCLA: u8, const SDAA: u8> FMPI2c<FMPI2C1, (SCL, SDA)>
impl<PINS> FMPI2c<FMPI2C1, PINS>
where
SCL: PinA<Scl, FMPI2C1, A = Const<SCLA>> + SetAlternate<OpenDrain, SCLA>,
SDA: PinA<Sda, FMPI2C1, A = Const<SDAA>> + SetAlternate<OpenDrain, SDAA>,
PINS: Pins<FMPI2C1>,
{
pub fn new<M: Into<FmpMode>>(i2c: FMPI2C1, mut pins: (SCL, SDA), mode: M) -> Self {
pub fn new<M: Into<FmpMode>>(i2c: FMPI2C1, mut pins: PINS, mode: M) -> Self {
unsafe {
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
let rcc = &(*RCC::ptr());
Expand All @@ -84,17 +83,15 @@ where
rcc.dckcfgr2.modify(|_, w| w.fmpi2c1sel().hsi());
}

pins.0.set_alt_mode();
pins.1.set_alt_mode();
pins.set_alt_mode();

let i2c = FMPI2c { i2c, pins };
i2c.i2c_init(mode);
i2c
}

pub fn release(mut self) -> (FMPI2C1, (SCL, SDA)) {
self.pins.0.restore_mode();
self.pins.1.restore_mode();
pub fn release(mut self) -> (FMPI2C1, PINS) {
self.pins.restore_mode();

(self.i2c, self.pins)
}
Expand Down Expand Up @@ -171,31 +168,39 @@ where
self.i2c
.icr
.write(|w| w.stopcf().set_bit().nackcf().set_bit());
return Err(Error::NACK);
return Err(Error::NoAcknowledge(NoAcknowledgeSource::Unknown));
}

Ok(())
}

fn end_transaction(&self) -> Result<(), Error> {
// Check and clear flags if they somehow ended up set
self.check_and_clear_error_flags(&self.i2c.isr.read())
.map_err(Error::nack_data)?;
Ok(())
}

fn send_byte(&self, byte: u8) -> Result<(), Error> {
// Wait until we're ready for sending
while {
let isr = self.i2c.isr.read();
self.check_and_clear_error_flags(&isr)?;
self.check_and_clear_error_flags(&isr)
.map_err(Error::nack_addr)?;
isr.txis().bit_is_clear()
} {}

// Push out a byte of data
self.i2c.txdr.write(|w| unsafe { w.bits(u32::from(byte)) });

self.check_and_clear_error_flags(&self.i2c.isr.read())?;
Ok(())
self.end_transaction()
}

fn recv_byte(&self) -> Result<u8, Error> {
while {
let isr = self.i2c.isr.read();
self.check_and_clear_error_flags(&isr)?;
self.check_and_clear_error_flags(&isr)
.map_err(Error::nack_data)?;
isr.rxne().bit_is_clear()
} {}

Expand Down Expand Up @@ -225,10 +230,7 @@ where
*c = self.recv_byte()?;
}

// Check and clear flags if they somehow ended up set
self.check_and_clear_error_flags(&self.i2c.isr.read())?;

Ok(())
self.end_transaction()
}

pub fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
Expand All @@ -252,10 +254,7 @@ where
self.send_byte(*c)?;
}

// Check and clear flags if they somehow ended up set
self.check_and_clear_error_flags(&self.i2c.isr.read())?;

Ok(())
self.end_transaction()
}

pub fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
Expand All @@ -277,7 +276,8 @@ where
// Wait until the transmit buffer is empty and there hasn't been any error condition
while {
let isr = self.i2c.isr.read();
self.check_and_clear_error_flags(&isr)?;
self.check_and_clear_error_flags(&isr)
.map_err(Error::nack_addr)?;
isr.txis().bit_is_clear() && isr.tc().bit_is_clear()
} {}

Expand All @@ -289,7 +289,8 @@ where
// Wait until data was sent
while {
let isr = self.i2c.isr.read();
self.check_and_clear_error_flags(&isr)?;
self.check_and_clear_error_flags(&isr)
.map_err(Error::nack_data)?;
isr.tc().bit_is_clear()
} {}

Expand All @@ -314,9 +315,6 @@ where
*c = self.recv_byte()?;
}

// Check and clear flags if they somehow ended up set
self.check_and_clear_error_flags(&self.i2c.isr.read())?;

Ok(())
self.end_transaction()
}
}
Loading

0 comments on commit aa934ca

Please sign in to comment.