Skip to content

Commit cdda367

Browse files
committed
eh-1.0.0: timers and delays
1 parent 07b50ea commit cdda367

File tree

12 files changed

+86
-163
lines changed

12 files changed

+86
-163
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
* Upgraded to embedded-hal v1.0.0-rc.3
66

7+
* delay: `delay_ms` and 'delay_us` methods now require importing: `use embedded_hal::delay::DelayNs;`
8+
79
* pwm: Renamed `get_max_duty` -> `max_duty_cycle`; `set_duty` -> `set_duty_cycle`
810
* pwm: `enable` method now returns type `Result<(), PwmError>`
911

examples/can-echo.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::hal::{
1818
rcc,
1919
rcc::rec,
2020
};
21+
use embedded_hal::delay::DelayNs;
2122
use fdcan::{
2223
config::NominalBitTiming,
2324
filter::{StandardFilter, StandardFilterSlot},
@@ -135,7 +136,7 @@ fn main() -> ! {
135136
info!("Received Header: {:#X?}", rxheader);
136137
info!("received data: {:X?}", &buffer);
137138

138-
delay.delay_ms(1_u16);
139+
delay.delay_ms(1);
139140
block!(can.transmit(rxheader.unwrap().to_tx_header(None), &buffer))
140141
.unwrap();
141142
info!("Transmit: {:X?}", buffer);

examples/can-fd.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use crate::hal::{
3030
rcc,
3131
rcc::rec,
3232
};
33+
use embedded_hal::delay::DelayNs;
3334
use fdcan::{
3435
config::{DataBitTiming, FrameTransmissionConfig, NominalBitTiming},
3536
filter::{StandardFilter, StandardFilterSlot},
@@ -167,7 +168,7 @@ fn main() -> ! {
167168
info!("Received Header: {:#X?}", rxheader);
168169
info!("received data: {:X?}", &buffer);
169170

170-
delay.delay_ms(1_u16);
171+
delay.delay_ms(1);
171172
block!(can.transmit(rxheader.unwrap().to_tx_header(None), &buffer))
172173
.unwrap();
173174
info!("Transmit: {:X?}", buffer);

examples/embedded-graphics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extern crate cortex_m_rt as rt;
2020
use core::sync::atomic::{AtomicU32, Ordering};
2121
use cortex_m_rt::{entry, exception};
2222

23+
use embedded_hal::delay::DelayNs;
2324
use stm32h7xx_hal::gpio::Speed;
2425
use stm32h7xx_hal::rcc::CoreClocks;
2526
use stm32h7xx_hal::{ltdc, xspi};
@@ -203,7 +204,7 @@ fn main() -> ! {
203204
let mut lcd_disp_ctrl = gpiod.pd10.into_push_pull_output();
204205
let mut lcd_bl_ctrl = gpiog.pg15.into_push_pull_output();
205206

206-
delay.delay_ms(40u8);
207+
delay.delay_ms(40);
207208

208209
let mut ltdc = ltdc::Ltdc::new(dp.LTDC, ccdr.peripheral.LTDC, &ccdr.clocks);
209210

examples/reset_reason.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use cortex_m_rt::entry;
99
#[macro_use]
1010
mod utilities;
11+
12+
use embedded_hal::delay::DelayNs;
1113
use stm32h7xx_hal::{pac, prelude::*, rcc::ResetReason};
1214

1315
use log::info;
@@ -48,7 +50,7 @@ fn main() -> ! {
4850

4951
// delay 10s
5052
let mut delay = cp.SYST.delay(ccdr.clocks);
51-
delay.delay_ms(10_000u16);
53+
delay.delay_ms(10_000);
5254

5355
// system reset
5456
stm32h7xx_hal::pac::SCB::sys_reset()

examples/sdmmc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
mod utilities;
1212

1313
use cortex_m_rt::entry;
14+
use embedded_hal::delay::DelayNs;
1415
use stm32h7xx_hal::gpio::Speed;
1516
use stm32h7xx_hal::sdmmc::{SdCard, Sdmmc};
1617
use stm32h7xx_hal::{pac, prelude::*};
@@ -114,7 +115,7 @@ fn main() -> ! {
114115

115116
info!("Waiting for card...");
116117

117-
delay.delay_ms(1000u32);
118+
delay.delay_ms(1000);
118119
led.toggle();
119120
}
120121

examples/sdmmc_fat.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![no_std]
33

44
use {
5+
embedded_hal::delay::DelayNs,
56
embedded_sdmmc::{Controller, Mode, VolumeIdx},
67
stm32h7xx_hal::sdmmc::{SdCard, Sdmmc},
78
stm32h7xx_hal::{pac, prelude::*, rcc},

examples/usb_phy_serial_interrupt.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use {
99
core::cell::RefCell,
1010
cortex_m::interrupt::{free as interrupt_free, Mutex},
11+
embedded_hal::delay::DelayNs,
1112
stm32h7xx_hal::{
1213
interrupt, pac,
1314
prelude::*,
@@ -105,20 +106,20 @@ unsafe fn main() -> ! {
105106
// clock source. Sometimes you have to enable them by yourself.
106107
// This is the case on the Arduino Portenta H7.
107108
let mut oscen = gpioh.ph1.into_push_pull_output();
108-
delay.delay_ms(10u32);
109+
delay.delay_ms(10);
109110
oscen.set_high();
110111
// Wait for osc to be stable
111-
delay.delay_ms(100u32);
112+
delay.delay_ms(100);
112113

113114
// Set USB OTG pin floating
114115
let mut _usb_otg = gpioj.pj6.into_floating_input();
115116

116117
// Reset USB Phy
117118
let mut usb_phy_rst = gpioj.pj4.into_push_pull_output();
118119
usb_phy_rst.set_low();
119-
delay.delay_ms(10u8);
120+
delay.delay_ms(10);
120121
usb_phy_rst.set_high();
121-
delay.delay_ms(10u8);
122+
delay.delay_ms(10);
122123

123124
// Enable USB OTG_HS interrupt
124125
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::OTG_HS);

src/delay.rs

Lines changed: 33 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,12 @@
3838
//!
3939
//! - [Blinky](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/blinky.rs)
4040
41-
use cast::u32;
4241
use cortex_m::peripheral::syst::SystClkSource;
4342
use cortex_m::peripheral::SYST;
44-
use embedded_hal::{
45-
blocking::delay::{DelayMs, DelayUs},
46-
timer::CountDown,
47-
};
43+
use embedded_hal::delay::DelayNs;
4844
use void::Void;
4945

50-
use crate::nb::block;
5146
use crate::rcc::CoreClocks;
52-
use crate::time::Hertz;
53-
use fugit::RateExtU32;
5447

5548
pub trait DelayExt {
5649
fn delay(self, clocks: CoreClocks) -> Delay;
@@ -68,7 +61,7 @@ pub struct Delay {
6861
syst: SYST,
6962
}
7063

71-
/// Implements [CountDown](embedded_hal::timer::CountDown) for the System timer (SysTick).
64+
/// Countdown for the System timer (SysTick).
7265
pub struct Countdown<'a> {
7366
clocks: CoreClocks,
7467
syst: &'a mut SYST,
@@ -77,7 +70,7 @@ pub struct Countdown<'a> {
7770
}
7871

7972
impl<'a> Countdown<'a> {
80-
/// Create a new [CountDown] measured in microseconds.
73+
/// Create a new [Countdown] measured in microseconds.
8174
pub fn new(syst: &'a mut SYST, clocks: CoreClocks) -> Self {
8275
Self {
8376
syst,
@@ -111,12 +104,11 @@ impl<'a> Countdown<'a> {
111104
}
112105
}
113106

114-
impl<'a> CountDown for Countdown<'a> {
115-
type Time = fugit::MicrosDurationU32;
116-
117-
fn start<T>(&mut self, count: T)
107+
impl<'a> Countdown<'a> {
108+
/// Starts a new count down
109+
pub fn start<T>(&mut self, count: T)
118110
where
119-
T: Into<Self::Time>,
111+
T: Into<fugit::MicrosDurationU32>,
120112
{
121113
let us = count.into().ticks();
122114

@@ -136,7 +128,8 @@ impl<'a> CountDown for Countdown<'a> {
136128
self.start_wait();
137129
}
138130

139-
fn wait(&mut self) -> nb::Result<(), Void> {
131+
/// Non-blockingly “waits” until the count down finishes
132+
pub fn wait(&mut self) -> nb::Result<(), Void> {
140133
if self.finished {
141134
return Ok(());
142135
}
@@ -164,42 +157,12 @@ impl Delay {
164157
}
165158
}
166159

167-
impl DelayMs<u32> for Delay {
168-
fn delay_ms(&mut self, ms: u32) {
169-
self.delay_us(ms * 1_000);
170-
}
171-
}
172-
173-
impl DelayMs<u16> for Delay {
174-
fn delay_ms(&mut self, ms: u16) {
175-
self.delay_ms(u32(ms));
176-
}
177-
}
178-
179-
impl DelayMs<u8> for Delay {
180-
fn delay_ms(&mut self, ms: u8) {
181-
self.delay_ms(u32(ms));
182-
}
183-
}
184-
185-
impl DelayUs<u32> for Delay {
186-
fn delay_us(&mut self, us: u32) {
160+
impl Delay {
161+
/// Internal method to delay cycles with systick
162+
fn systick_delay_cycles(&mut self, mut total_rvr: u64) {
187163
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
188164
const MAX_RVR: u32 = 0x00FF_FFFF;
189165

190-
// With c_ck up to 480e6, we need u64 for delays > 8.9s
191-
192-
let mut total_rvr = if cfg!(not(feature = "revision_v")) {
193-
// See errata ES0392 §2.2.3. Revision Y does not have the /8 divider
194-
u64::from(us) * u64::from(self.clocks.c_ck().raw() / 1_000_000)
195-
} else if cfg!(feature = "cm4") {
196-
// CM4 derived from HCLK
197-
u64::from(us) * u64::from(self.clocks.hclk().raw() / 8_000_000)
198-
} else {
199-
// Normally divide by 8
200-
u64::from(us) * u64::from(self.clocks.c_ck().raw() / 8_000_000)
201-
};
202-
203166
while total_rvr != 0 {
204167
let current_rvr = if total_rvr <= MAX_RVR.into() {
205168
total_rvr as u32
@@ -219,90 +182,32 @@ impl DelayUs<u32> for Delay {
219182
self.syst.disable_counter();
220183
}
221184
}
222-
}
223-
224-
impl DelayUs<u16> for Delay {
225-
fn delay_us(&mut self, us: u16) {
226-
self.delay_us(u32(us))
227-
}
228-
}
229-
230-
impl DelayUs<u8> for Delay {
231-
fn delay_us(&mut self, us: u8) {
232-
self.delay_us(u32(us))
185+
/// Internal method that returns the clock frequency of systick
186+
fn systick_clock(&self) -> u64 {
187+
if cfg!(not(feature = "revision_v")) {
188+
// See errata ES0392 §2.2.3. Revision Y does not have the /8 divider
189+
u64::from(self.clocks.c_ck().raw())
190+
} else if cfg!(feature = "cm4") {
191+
// CM4 derived from HCLK
192+
u64::from(self.clocks.hclk().raw() / 8)
193+
} else {
194+
// Normally divide by 8
195+
u64::from(self.clocks.c_ck().raw() / 8)
196+
}
233197
}
234198
}
235199

236-
/// CountDown Timer as a delay provider
237-
pub struct DelayFromCountDownTimer<T>(T);
238-
239-
impl<T> DelayFromCountDownTimer<T> {
240-
/// Creates delay provider from a CountDown timer
241-
pub fn new(timer: T) -> Self {
242-
Self(timer)
243-
}
200+
impl DelayNs for Delay {
201+
fn delay_ns(&mut self, ns: u32) {
202+
// With c_ck up to 480e6, 1 cycle is always > 2ns
244203

245-
/// Releases the Timer
246-
pub fn free(self) -> T {
247-
self.0
204+
self.systick_delay_cycles(u64::from(ns + 1) / 2);
248205
}
249-
}
250-
251-
macro_rules! impl_delay_from_count_down_timer {
252-
($(($Delay:ident, $delay:ident, $num:expr)),+) => {
253-
$(
254-
255-
impl<T> $Delay<u32> for DelayFromCountDownTimer<T>
256-
where
257-
T: CountDown<Time = Hertz>,
258-
{
259-
fn $delay(&mut self, t: u32) {
260-
let mut time_left = t;
261-
262-
// Due to the LpTimer having only a 3 bit scaler, it is
263-
// possible that the max timeout we can set is
264-
// (128 * 65536) / clk_hz milliseconds.
265-
// Assuming the fastest clk_hz = 480Mhz this is roughly ~17ms,
266-
// or a frequency of ~57.2Hz. We use a 60Hz frequency for each
267-
// loop step here to ensure that we stay within these bounds.
268-
let looping_delay = $num / 60;
269-
let looping_delay_hz = Hertz::from_raw($num / looping_delay);
270-
271-
self.0.start(looping_delay_hz);
272-
while time_left > looping_delay {
273-
block!(self.0.wait()).ok();
274-
time_left -= looping_delay;
275-
}
276-
277-
if time_left > 0 {
278-
self.0.start(($num / time_left).Hz());
279-
block!(self.0.wait()).ok();
280-
}
281-
}
282-
}
283-
284-
impl<T> $Delay<u16> for DelayFromCountDownTimer<T>
285-
where
286-
T: CountDown<Time = Hertz>,
287-
{
288-
fn $delay(&mut self, t: u16) {
289-
self.$delay(t as u32);
290-
}
291-
}
206+
fn delay_us(&mut self, us: u32) {
207+
// With c_ck up to 480e6, we need u64 for delays > 8.9s
292208

293-
impl<T> $Delay<u8> for DelayFromCountDownTimer<T>
294-
where
295-
T: CountDown<Time = Hertz>,
296-
{
297-
fn $delay(&mut self, t: u8) {
298-
self.$delay(t as u32);
299-
}
300-
}
301-
)+
209+
let total_rvr =
210+
u64::from(us) * ((self.systick_clock() + 999_999) / 1_000_000);
211+
self.systick_delay_cycles(total_rvr);
302212
}
303213
}
304-
305-
impl_delay_from_count_down_timer! {
306-
(DelayMs, delay_ms, 1_000),
307-
(DelayUs, delay_us, 1_000_000)
308-
}

0 commit comments

Comments
 (0)