Skip to content

Move embedded-hal implementations to subdirs #404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Dec 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed

- Move `embedded-hal` implementations to subdirs [#404]
- Qei macro cleanups [#403]
- Update RTIC to 1.0 [#401]
- Finish SDIO data transmission before querying card status in `write_block` [#395]
Expand All @@ -51,7 +52,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
[#393]: https://github.com/stm32-rs/stm32f4xx-hal/pull/393
[#395]: https://github.com/stm32-rs/stm32f4xx-hal/pull/395
[#401]: https://github.com/stm32-rs/stm32f4xx-hal/pull/401
[#401]: https://github.com/stm32-rs/stm32f4xx-hal/pull/403
[#403]: https://github.com/stm32-rs/stm32f4xx-hal/pull/403
[#404]: https://github.com/stm32-rs/stm32f4xx-hal/pull/404

## [v0.10.1] - 2021-10-26

Expand Down
29 changes: 18 additions & 11 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::dma::traits::PeriAddress;
use crate::rcc::{Enable, Reset};
use crate::{gpio::*, pac, signature::VrefCal, signature::VDDA_CALIB};
use core::fmt;
use embedded_hal::adc::{Channel, OneShot};

/// Vref internal signal, used for calibration
pub struct Vref;
Expand All @@ -26,7 +25,7 @@ pub struct Temperature;
macro_rules! adc_pins {
($($pin:ty => ($adc:ident, $chan:expr)),+ $(,)*) => {
$(
impl Channel<pac::$adc> for $pin {
impl embedded_hal::adc::Channel<pac::$adc> for $pin {
type ID = u8;
fn channel() -> u8 { $chan }
}
Expand Down Expand Up @@ -897,7 +896,7 @@ macro_rules! adc {
/// to sample for at a given ADC clock frequency
pub fn configure_channel<CHANNEL>(&mut self, _channel: &CHANNEL, sequence: config::Sequence, sample_time: config::SampleTime)
where
CHANNEL: Channel<pac::$adc_type, ID=u8>
CHANNEL: embedded_hal::adc::Channel<pac::$adc_type, ID=u8>
{
//Check the sequence is long enough
self.adc_reg.sqr1.modify(|r, w| {
Expand Down Expand Up @@ -977,7 +976,7 @@ macro_rules! adc {
/// Note that it reconfigures the adc sequence and doesn't restore it
pub fn convert<PIN>(&mut self, pin: &PIN, sample_time: config::SampleTime) -> u16
where
PIN: Channel<pac::$adc_type, ID=u8>
PIN: embedded_hal::adc::Channel<pac::$adc_type, ID=u8>
{
self.adc_reg.cr2.modify(|_, w| w
.dma().clear_bit() //Disable dma
Expand Down Expand Up @@ -1008,13 +1007,10 @@ macro_rules! adc {
}
}

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

fn read(&mut self, pin: &mut PIN) -> nb::Result<u16, Self::Error> {
impl Adc<pac::$adc_type> {
fn read<PIN>(&mut self, pin: &mut PIN) -> nb::Result<u16, ()>
where PIN: embedded_hal::adc::Channel<pac::$adc_type, ID=u8>,
{
let enabled = self.is_enabled();
if !enabled {
self.enable();
Expand All @@ -1030,6 +1026,17 @@ macro_rules! adc {
}
}

impl<PIN> embedded_hal::adc::OneShot<pac::$adc_type, u16, PIN> for Adc<pac::$adc_type>
where
PIN: embedded_hal::adc::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
143 changes: 143 additions & 0 deletions src/delay/hal_02.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//! 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, u32};
use cortex_m::peripheral::SYST;
use embedded_hal::blocking::delay::{DelayMs, DelayUs};

use super::{Delay, Wait};

impl DelayUs<u32> for Delay<SYST> {
fn delay_us(&mut self, us: u32) {
// 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();
}
}
}

impl DelayMs<u32> for Delay<SYST> {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
}
}

impl DelayUs<u16> for Delay<SYST> {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32(us))
}
}

impl DelayMs<u16> for Delay<SYST> {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(u32(ms));
}
}

impl DelayUs<u8> for Delay<SYST> {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
}
}

impl DelayMs<u8> for Delay<SYST> {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u32(ms));
}
}

impl<TIM> DelayUs<u32> for Delay<TIM>
where
Self: Wait,
{
/// Sleep for up to 2^32-1 microseconds (~71 minutes).
fn delay_us(&mut self, us: u32) {
// 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);
}
}

impl<TIM> DelayMs<u32> for Delay<TIM>
where
Self: Wait,
{
/// 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) {
// 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);
}
}

impl<TIM> DelayUs<u16> for Delay<TIM>
where
Self: Wait,
{
/// Sleep for up to 2^16-1 microseconds (~65 milliseconds).
fn delay_us(&mut self, us: u16) {
// See DelayUs<u32> for explanations.
let psc = u16(self.clk.0 / 1_000_000).expect("Prescaler does not fit in u16");
let arr = u32(us);
self.wait(psc, arr);
}
}

impl<TIM> DelayMs<u16> for Delay<TIM>
where
Self: Wait,
{
/// Sleep for up to (2^16)-1 milliseconds (~65 seconds).
fn delay_ms(&mut self, ms: u16) {
// See DelayMs<u32> for explanations. Since the value range is only 16 bit,
// we don't need an assert here.
let psc = u16(self.clk.0 / 1000 / 2).expect("Prescaler does not fit in u16");
let arr = u32(ms) << 1;
self.wait(psc, arr);
}
}
84 changes: 82 additions & 2 deletions src/delay/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
//! Delays

mod syst;
mod hal_02;

use crate::{
pac,
rcc::Clocks,
timer::{General, Timer},
};
use core::cmp::max;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;

use crate::time::Hertz;
Expand All @@ -19,4 +26,77 @@ impl<T> Delay<T> {
}
}

mod timer;
impl Delay<SYST> {
/// Configures the system timer (SysTick) as a delay provider
pub fn new(mut tim: SYST, clocks: &Clocks) -> Self {
tim.set_clock_source(SystClkSource::External);
Self {
tim,
clk: clocks.hclk(),
}
}
}

mod sealed {
pub trait Wait {
fn wait(&mut self, prescaler: u16, auto_reload_register: u32);
}
}
use sealed::Wait;

macro_rules! hal {
($($TIM:ty: ($tim:ident),)+) => {
$(
impl Timer<$TIM> {
pub fn delay(self) -> Delay<$TIM> {
let Self { tim, clk } = self;

// Enable one-pulse mode (counter stops counting at the next update
// event, clearing the CEN bit)
tim.cr1.modify(|_, w| w.opm().enabled());

Delay { tim, clk }
}
}

impl Delay<$TIM> {
/// Configures the timer as a delay provider
pub fn $tim(tim: $TIM, clocks: &Clocks) -> Self {
Timer::new(tim, clocks).delay()
}
}

impl Wait for Delay<$TIM> {
fn wait(&mut self, prescaler: u16, auto_reload_register: u32) {
// Write Prescaler (PSC)
self.tim.set_prescaler(prescaler);

// Write Auto-Reload Register (ARR)
// Note: Make it impossible to set the ARR value to 0, since this
// would cause an infinite loop.
self.tim.set_auto_reload(max(1, auto_reload_register)).unwrap();

// Trigger update event (UEV) in the event generation register (EGR)
// in order to immediately apply the config
self.tim.trigger_update();

// Configure the counter in one-pulse mode (counter stops counting at
// the next updateevent, clearing the CEN bit) and enable the counter.
self.tim.cr1.write(|w| w.opm().set_bit().cen().set_bit());

// Wait for CEN bit to clear
while self.tim.is_counter_enabled() { /* wait */ }
}
}
)+
}
}

hal! {
pac::TIM5: (tim5),
}

#[cfg(feature = "tim2")]
hal! {
pac::TIM2: (tim2),
}
Loading