Skip to content

Commit 0c05a0a

Browse files
authored
Merge pull request #537 from Dirbaio/delay-ns
Rename `DelayUs` to `BasicDelay`, add `delay_ns`.
2 parents 0b95d0a + c2eab4d commit 0c05a0a

File tree

11 files changed

+92
-70
lines changed

11 files changed

+92
-70
lines changed

embedded-hal-async/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
- Minor document fixes.
1111
- Add #[inline] hints to most of `embedded-hal-async` functions.
12+
- delay: Rename `DelayUs` to `DelayNs`
13+
- delay: Add `DelayNs::delay_ns()`
14+
- delay: Add default impls of `delay_ms` and `delay_us` based on `delay_ns`.
15+
- spi: Rename `Operation::DelayUs` to `Operation::DelayNs`, with nanosecond precision.
1216

1317
## [v1.0.0-rc.1] - 2023-08-15
1418

embedded-hal-async/src/delay.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,42 @@
11
//! Delays.
22
3-
/// Microsecond delay.
4-
pub trait DelayUs {
3+
/// Delay with up to nanosecond precision.
4+
pub trait DelayNs {
5+
/// Pauses execution for at minimum `ns` nanoseconds. Pause can be longer
6+
/// if the implementation requires it due to precision/timing issues.
7+
async fn delay_ns(&mut self, ns: u32);
8+
59
/// Pauses execution for at minimum `us` microseconds. Pause can be longer
610
/// if the implementation requires it due to precision/timing issues.
7-
async fn delay_us(&mut self, us: u32);
11+
async fn delay_us(&mut self, mut us: u32) {
12+
while us > 4_294_967 {
13+
us -= 4_294_967;
14+
self.delay_ns(4_294_967_000).await;
15+
}
16+
self.delay_ns(us * 1_000).await;
17+
}
818

919
/// Pauses execution for at minimum `ms` milliseconds. Pause can be longer
1020
/// if the implementation requires it due to precision/timing issues.
11-
async fn delay_ms(&mut self, ms: u32);
21+
#[inline]
22+
async fn delay_ms(&mut self, mut ms: u32) {
23+
while ms > 4294 {
24+
ms -= 4294;
25+
self.delay_ns(4_294_000_000).await;
26+
}
27+
self.delay_ns(ms * 1_000_000).await;
28+
}
1229
}
1330

14-
impl<T> DelayUs for &mut T
31+
impl<T> DelayNs for &mut T
1532
where
16-
T: DelayUs + ?Sized,
33+
T: DelayNs + ?Sized,
1734
{
35+
#[inline]
36+
async fn delay_ns(&mut self, ns: u32) {
37+
T::delay_ns(self, ns).await;
38+
}
39+
1840
#[inline]
1941
async fn delay_us(&mut self, us: u32) {
2042
T::delay_us(self, us).await;

embedded-hal-bus/src/spi/critical_section.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use core::cell::RefCell;
22
use critical_section::Mutex;
3-
use embedded_hal::delay::DelayUs;
3+
use embedded_hal::delay::DelayNs;
44
use embedded_hal::digital::OutputPin;
55
use embedded_hal::spi::{ErrorType, Operation, SpiBus, SpiDevice};
66

@@ -37,7 +37,7 @@ impl<'a, BUS, CS> CriticalSectionDevice<'a, BUS, CS, super::NoDelay> {
3737
/// # Panics
3838
///
3939
/// The returned device will panic if you try to execute a transaction
40-
/// that contains any operations of type [`Operation::DelayUs`].
40+
/// that contains any operations of type [`Operation::DelayNs`].
4141
#[inline]
4242
pub fn new_no_delay(bus: &'a Mutex<RefCell<BUS>>, cs: CS) -> Self {
4343
Self {
@@ -60,7 +60,7 @@ impl<'a, Word: Copy + 'static, BUS, CS, D> SpiDevice<Word> for CriticalSectionDe
6060
where
6161
BUS: SpiBus<Word>,
6262
CS: OutputPin,
63-
D: DelayUs,
63+
D: DelayNs,
6464
{
6565
#[inline]
6666
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {

embedded-hal-bus/src/spi/exclusive.rs

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
//! SPI bus sharing mechanisms.
22
3-
use embedded_hal::delay::DelayUs;
3+
use embedded_hal::delay::DelayNs;
44
use embedded_hal::digital::OutputPin;
55
use embedded_hal::spi::{ErrorType, Operation, SpiBus, SpiDevice};
66
#[cfg(feature = "async")]
77
use embedded_hal_async::{
8-
delay::DelayUs as AsyncDelayUs,
8+
delay::DelayNs as AsyncDelayNs,
99
spi::{SpiBus as AsyncSpiBus, SpiDevice as AsyncSpiDevice},
1010
};
1111

12+
use super::shared::transaction;
1213
use super::DeviceError;
1314

1415
/// [`SpiDevice`] implementation with exclusive access to the bus (not shared).
@@ -47,7 +48,7 @@ impl<BUS, CS> ExclusiveDevice<BUS, CS, super::NoDelay> {
4748
/// # Panics
4849
///
4950
/// The returned device will panic if you try to execute a transaction
50-
/// that contains any operations of type `Operation::DelayUs`.
51+
/// that contains any operations of type [`Operation::DelayNs`].
5152
#[inline]
5253
pub fn new_no_delay(bus: BUS, cs: CS) -> Self {
5354
Self {
@@ -70,33 +71,11 @@ impl<Word: Copy + 'static, BUS, CS, D> SpiDevice<Word> for ExclusiveDevice<BUS,
7071
where
7172
BUS: SpiBus<Word>,
7273
CS: OutputPin,
73-
D: DelayUs,
74+
D: DelayNs,
7475
{
7576
#[inline]
7677
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
77-
self.cs.set_low().map_err(DeviceError::Cs)?;
78-
79-
let op_res = operations.iter_mut().try_for_each(|op| match op {
80-
Operation::Read(buf) => self.bus.read(buf),
81-
Operation::Write(buf) => self.bus.write(buf),
82-
Operation::Transfer(read, write) => self.bus.transfer(read, write),
83-
Operation::TransferInPlace(buf) => self.bus.transfer_in_place(buf),
84-
Operation::DelayUs(us) => {
85-
self.bus.flush()?;
86-
self.delay.delay_us(*us);
87-
Ok(())
88-
}
89-
});
90-
91-
// On failure, it's important to still flush and deassert CS.
92-
let flush_res = self.bus.flush();
93-
let cs_res = self.cs.set_high();
94-
95-
op_res.map_err(DeviceError::Spi)?;
96-
flush_res.map_err(DeviceError::Spi)?;
97-
cs_res.map_err(DeviceError::Cs)?;
98-
99-
Ok(())
78+
transaction(operations, &mut self.bus, &mut self.delay, &mut self.cs)
10079
}
10180
}
10281

@@ -106,7 +85,7 @@ impl<Word: Copy + 'static, BUS, CS, D> AsyncSpiDevice<Word> for ExclusiveDevice<
10685
where
10786
BUS: AsyncSpiBus<Word>,
10887
CS: OutputPin,
109-
D: AsyncDelayUs,
88+
D: AsyncDelayNs,
11089
{
11190
#[inline]
11291
async fn transaction(
@@ -122,10 +101,10 @@ where
122101
Operation::Write(buf) => self.bus.write(buf).await,
123102
Operation::Transfer(read, write) => self.bus.transfer(read, write).await,
124103
Operation::TransferInPlace(buf) => self.bus.transfer_in_place(buf).await,
125-
Operation::DelayUs(us) => match self.bus.flush().await {
104+
Operation::DelayNs(ns) => match self.bus.flush().await {
126105
Err(e) => Err(e),
127106
Ok(()) => {
128-
self.delay.delay_us(*us).await;
107+
self.delay.delay_ns(*ns).await;
129108
Ok(())
130109
}
131110
},

embedded-hal-bus/src/spi/mod.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,33 +43,28 @@ where
4343
}
4444
}
4545

46-
/// Dummy `DelayUs` implementation that panics on use.
46+
/// Dummy [`DelayNs`](embedded_hal::delay::DelayNs) implementation that panics on use.
4747
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
4848
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
4949
pub struct NoDelay;
5050

5151
#[cold]
5252
fn no_delay_panic() {
53-
panic!("You've tried to execute a SPI transaction containing a `Operation::Delay` in a `SpiDevice` created with `new_no_delay()`. Create it with `new()` instead, passing a `DelayUs` implementation.");
53+
panic!("You've tried to execute a SPI transaction containing a `Operation::DelayNs` in a `SpiDevice` created with `new_no_delay()`. Create it with `new()` instead, passing a `DelayNs` implementation.");
5454
}
5555

56-
impl embedded_hal::delay::DelayUs for NoDelay {
56+
impl embedded_hal::delay::DelayNs for NoDelay {
5757
#[inline]
58-
fn delay_us(&mut self, _us: u32) {
58+
fn delay_ns(&mut self, _ns: u32) {
5959
no_delay_panic();
6060
}
6161
}
6262

6363
#[cfg(feature = "async")]
6464
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
65-
impl embedded_hal_async::delay::DelayUs for NoDelay {
65+
impl embedded_hal_async::delay::DelayNs for NoDelay {
6666
#[inline]
67-
async fn delay_us(&mut self, _us: u32) {
68-
no_delay_panic();
69-
}
70-
71-
#[inline]
72-
async fn delay_ms(&mut self, _ms: u32) {
67+
async fn delay_ns(&mut self, _ns: u32) {
7368
no_delay_panic();
7469
}
7570
}

embedded-hal-bus/src/spi/mutex.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use embedded_hal::delay::DelayUs;
1+
use embedded_hal::delay::DelayNs;
22
use embedded_hal::digital::OutputPin;
33
use embedded_hal::spi::{ErrorType, Operation, SpiBus, SpiDevice};
44
use std::sync::Mutex;
@@ -35,7 +35,7 @@ impl<'a, BUS, CS> MutexDevice<'a, BUS, CS, super::NoDelay> {
3535
/// # Panics
3636
///
3737
/// The returned device will panic if you try to execute a transaction
38-
/// that contains any operations of type `Operation::DelayUs`.
38+
/// that contains any operations of type [`Operation::DelayNs`].
3939
#[inline]
4040
pub fn new_no_delay(bus: &'a Mutex<BUS>, cs: CS) -> Self {
4141
Self {
@@ -58,7 +58,7 @@ impl<'a, Word: Copy + 'static, BUS, CS, D> SpiDevice<Word> for MutexDevice<'a, B
5858
where
5959
BUS: SpiBus<Word>,
6060
CS: OutputPin,
61-
D: DelayUs,
61+
D: DelayNs,
6262
{
6363
#[inline]
6464
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {

embedded-hal-bus/src/spi/refcell.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::cell::RefCell;
2-
use embedded_hal::delay::DelayUs;
2+
use embedded_hal::delay::DelayNs;
33
use embedded_hal::digital::OutputPin;
44
use embedded_hal::spi::{ErrorType, Operation, SpiBus, SpiDevice};
55

@@ -34,7 +34,7 @@ impl<'a, BUS, CS> RefCellDevice<'a, BUS, CS, super::NoDelay> {
3434
/// # Panics
3535
///
3636
/// The returned device will panic if you try to execute a transaction
37-
/// that contains any operations of type `Operation::DelayUs`.
37+
/// that contains any operations of type [`Operation::DelayNs`].
3838
#[inline]
3939
pub fn new_no_delay(bus: &'a RefCell<BUS>, cs: CS) -> Self {
4040
Self {
@@ -57,7 +57,7 @@ impl<'a, Word: Copy + 'static, BUS, CS, D> SpiDevice<Word> for RefCellDevice<'a,
5757
where
5858
BUS: SpiBus<Word>,
5959
CS: OutputPin,
60-
D: DelayUs,
60+
D: DelayNs,
6161
{
6262
#[inline]
6363
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {

embedded-hal-bus/src/spi/shared.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use embedded_hal::delay::DelayUs;
1+
use embedded_hal::delay::DelayNs;
22
use embedded_hal::digital::OutputPin;
33
use embedded_hal::spi::{ErrorType, Operation, SpiBus};
44

@@ -15,7 +15,7 @@ pub fn transaction<Word, BUS, CS, D>(
1515
where
1616
BUS: SpiBus<Word> + ErrorType,
1717
CS: OutputPin,
18-
D: DelayUs,
18+
D: DelayNs,
1919
Word: Copy,
2020
{
2121
cs.set_low().map_err(DeviceError::Cs)?;
@@ -25,9 +25,9 @@ where
2525
Operation::Write(buf) => bus.write(buf),
2626
Operation::Transfer(read, write) => bus.transfer(read, write),
2727
Operation::TransferInPlace(buf) => bus.transfer_in_place(buf),
28-
Operation::DelayUs(us) => {
28+
Operation::DelayNs(ns) => {
2929
bus.flush()?;
30-
delay.delay_us(*us);
30+
delay.delay_ns(*ns);
3131
Ok(())
3232
}
3333
});

embedded-hal/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
- Minor document fixes.
1111
- Add #[inline] hints to most of `embedded-hal` functions.
1212
- pwm: rename `get_max_duty_cycle` to `max_duty_cycle`.
13+
- delay: Rename `DelayUs` to `DelayNs`
14+
- delay: Add `DelayNs::delay_ns()`
15+
- delay: Add default impls of `delay_ms` and `delay_us` based on `delay_ns`.
16+
- delay: Make the default impl of `delay_ms` more efficient, it now does less calls to the underlying `delay_ns` (previously `delay_us`).
17+
- spi: Rename `Operation::DelayUs` to `Operation::DelayNs`, with nanosecond precision.
1318

1419
## [v1.0.0-rc.1] - 2023-08-15
1520

embedded-hal/src/delay.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,42 @@
11
//! Delays.
22
3-
/// Microsecond delay.
4-
pub trait DelayUs {
3+
/// Delay with up to nanosecond precision.
4+
pub trait DelayNs {
5+
/// Pauses execution for at minimum `ns` nanoseconds. Pause can be longer
6+
/// if the implementation requires it due to precision/timing issues.
7+
fn delay_ns(&mut self, ns: u32);
8+
59
/// Pauses execution for at minimum `us` microseconds. Pause can be longer
610
/// if the implementation requires it due to precision/timing issues.
7-
fn delay_us(&mut self, us: u32);
11+
fn delay_us(&mut self, mut us: u32) {
12+
while us > 4_294_967 {
13+
us -= 4_294_967;
14+
self.delay_ns(4_294_967_000);
15+
}
16+
self.delay_ns(us * 1_000);
17+
}
818

919
/// Pauses execution for at minimum `ms` milliseconds. Pause can be longer
1020
/// if the implementation requires it due to precision/timing issues.
1121
#[inline]
12-
fn delay_ms(&mut self, ms: u32) {
13-
for _ in 0..ms {
14-
self.delay_us(1000);
22+
fn delay_ms(&mut self, mut ms: u32) {
23+
while ms > 4294 {
24+
ms -= 4294;
25+
self.delay_ns(4_294_000_000);
1526
}
27+
self.delay_ns(ms * 1_000_000);
1628
}
1729
}
1830

19-
impl<T> DelayUs for &mut T
31+
impl<T> DelayNs for &mut T
2032
where
21-
T: DelayUs + ?Sized,
33+
T: DelayNs + ?Sized,
2234
{
35+
#[inline]
36+
fn delay_ns(&mut self, ns: u32) {
37+
T::delay_ns(self, ns);
38+
}
39+
2340
#[inline]
2441
fn delay_us(&mut self, us: u32) {
2542
T::delay_us(self, us);

0 commit comments

Comments
 (0)