Skip to content

Commit ef72189

Browse files
committed
Feature-gate async-await
1 parent 6c16e7d commit ef72189

File tree

8 files changed

+66
-49
lines changed

8 files changed

+66
-49
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,19 @@ ieee802_3_miim = "0.8"
2929
cortex-m = "0.7"
3030
log = { version = "0.4", optional = true }
3131
defmt = { version = "0.3", optional = true }
32-
futures = { version = "0.3", default-features = false, features = ["async-await"] }
32+
futures = { version = "0.3", default-features = false, features = ["async-await"], optional = true }
3333

3434
[dependencies.smoltcp]
3535
version = "0.9"
3636
default-features = false
3737
optional = true
3838

3939
[features]
40-
default = [ "defmt", "ptp" ]
40+
default = [ "defmt", "ptp", "async-await" ]
4141
device-selected = []
4242
fence = []
4343
ptp = [ ]
44+
async-await = ["dep:futures"]
4445

4546
stm32f107 = ["stm32f1xx-hal/stm32f107", "device-selected"]
4647

src/dma/mod.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
//! Ethernet DMA access and configuration.
22
3-
use core::task::Poll;
4-
53
use cortex_m::peripheral::NVIC;
6-
use futures::task::AtomicWaker;
74

85
use crate::{peripherals::ETHERNET_DMA, stm32::Interrupt};
96

@@ -12,6 +9,12 @@ mod smoltcp_phy;
129
#[cfg(feature = "smoltcp-phy")]
1310
pub use smoltcp_phy::*;
1411

12+
#[cfg(feature = "async-await")]
13+
use futures::task::AtomicWaker;
14+
15+
#[cfg(feature = "ptp")]
16+
use core::task::Poll;
17+
1518
pub(crate) mod desc;
1619

1720
pub(crate) mod ring;
@@ -115,8 +118,8 @@ impl<'rx, 'tx> EthernetDMA<'rx, 'tx> {
115118

116119
let mut dma = EthernetDMA {
117120
eth_dma,
118-
rx_ring: RxRing::new(rx_buffer, EthernetDMA::rx_waker()),
119-
tx_ring: TxRing::new(tx_buffer, EthernetDMA::tx_waker()),
121+
rx_ring: RxRing::new(rx_buffer),
122+
tx_ring: TxRing::new(tx_buffer),
120123
};
121124

122125
dma.rx_ring.start(&dma.eth_dma);
@@ -125,11 +128,13 @@ impl<'rx, 'tx> EthernetDMA<'rx, 'tx> {
125128
dma
126129
}
127130

131+
#[cfg(feature = "async-await")]
128132
pub(crate) fn rx_waker() -> &'static AtomicWaker {
129133
static WAKER: AtomicWaker = AtomicWaker::new();
130134
&WAKER
131135
}
132136

137+
#[cfg(feature = "async-await")]
133138
pub(crate) fn tx_waker() -> &'static AtomicWaker {
134139
static WAKER: AtomicWaker = AtomicWaker::new();
135140
&WAKER
@@ -144,8 +149,8 @@ impl<'rx, 'tx> EthernetDMA<'rx, 'tx> {
144149
/// Enable RX and TX interrupts
145150
///
146151
/// In your handler you must call
147-
/// [`EthernetDMA::interrupt_handler()`] to
148-
/// clear interrupt pending bits. Otherwise the interrupt will
152+
/// [`EthernetDMA::interrupt_handler()`] or [`stm32_eth::eth_interrupt_handler`](crate::eth_interrupt_handler)
153+
/// to clear interrupt pending bits. Otherwise the interrupt will
149154
/// reoccur immediately.
150155
pub fn enable_interrupt(&self) {
151156
self.eth_dma.dmaier.modify(|_, w| {
@@ -184,12 +189,15 @@ impl<'rx, 'tx> EthernetDMA<'rx, 'tx> {
184189
.dmasr
185190
.write(|w| w.nis().set_bit().ts().set_bit().rs().set_bit());
186191

187-
if status.is_tx {
188-
EthernetDMA::tx_waker().wake();
189-
}
192+
#[cfg(feature = "async-await")]
193+
{
194+
if status.is_tx {
195+
EthernetDMA::tx_waker().wake();
196+
}
190197

191-
if status.is_rx {
192-
EthernetDMA::rx_waker().wake();
198+
if status.is_rx {
199+
EthernetDMA::rx_waker().wake();
200+
}
193201
}
194202

195203
status
@@ -205,6 +213,7 @@ impl<'rx, 'tx> EthernetDMA<'rx, 'tx> {
205213
}
206214

207215
/// Receive a packet.
216+
#[cfg(feature = "async-await")]
208217
pub async fn recv(&mut self) -> RxPacket {
209218
self.rx_ring.recv().await
210219
}

src/dma/rx/descriptor.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ use crate::dma::{
33
ring::{RingDescriptor, RingEntry},
44
};
55

6+
use crate::dma::PacketId;
7+
68
#[cfg(feature = "ptp")]
7-
use crate::{dma::PacketId, ptp::Timestamp};
9+
use crate::ptp::Timestamp;
810

911
/// Errors that can occur during RX
1012
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -17,6 +19,8 @@ pub(crate) enum RxDescriptorError {
1719
}
1820

1921
/// RX timestamp valid
22+
/// NOTE(allow): unused if not(feature = "ptp")
23+
#[allow(unused)]
2024
const RXDESC_0_TIMESTAMP_VALID: u32 = 1 << 7;
2125
/// Owned by DMA engine
2226
const RXDESC_0_OWN: u32 = 1 << 31;
@@ -76,8 +80,6 @@ impl RxDescriptor {
7680
///
7781
/// Overrides old timestamp data
7882
pub fn set_owned(&mut self) {
79-
self.cached_timestamp = self.timestamp();
80-
8183
self.write_buffer1();
8284
self.write_buffer2();
8385

src/dma/rx/mod.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
use core::task::Poll;
2-
3-
use futures::task::AtomicWaker;
4-
51
pub(crate) use self::descriptor::RxDescriptor;
62

73
use self::descriptor::RxDescriptorError;
84
pub use self::descriptor::RxRingEntry;
95

10-
use super::{PacketId, PacketIdNotFound};
6+
use super::PacketId;
117
use crate::peripherals::ETHERNET_DMA;
128

139
mod descriptor;
1410

1511
#[cfg(feature = "ptp")]
16-
use crate::ptp::Timestamp;
12+
use crate::{dma::PacketIdNotFound, ptp::Timestamp};
13+
14+
#[cfg(feature = "async-await")]
15+
use core::task::Poll;
1716

1817
/// Errors that can occur during RX
1918
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -40,16 +39,14 @@ impl From<RxDescriptorError> for RxError {
4039
pub struct RxRing<'a> {
4140
entries: &'a mut [RxRingEntry],
4241
next_entry: usize,
43-
waker: &'static AtomicWaker,
4442
}
4543

4644
impl<'a> RxRing<'a> {
4745
/// Allocate
48-
pub fn new(entries: &'a mut [RxRingEntry], waker: &'static AtomicWaker) -> Self {
46+
pub fn new(entries: &'a mut [RxRingEntry]) -> Self {
4947
RxRing {
5048
entries,
5149
next_entry: 0,
52-
waker,
5350
}
5451
}
5552

@@ -165,14 +162,15 @@ impl<'a> RxRing<'a> {
165162
///
166163
/// The returned [`RxPacket`] can be used as a slice, and
167164
/// will contain the ethernet data.
165+
#[cfg(feature = "async-await")]
168166
pub async fn recv(&mut self) -> RxPacket {
169167
let (entry_num, length) = core::future::poll_fn(|ctx| {
170168
let res = self.recv_next_impl(None);
171169

172170
match res {
173171
Ok(value) => Poll::Ready(value),
174172
Err(_) => {
175-
self.waker.register(ctx.waker());
173+
crate::dma::EthernetDMA::rx_waker().register(ctx.waker());
176174
Poll::Pending
177175
}
178176
}

src/dma/tx/mod.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@ use super::{PacketIdNotFound, Timestamp};
66

77
mod descriptor;
88
pub use descriptor::{TxDescriptor, TxRingEntry};
9-
use futures::task::AtomicWaker;
109

11-
use core::{
12-
sync::atomic::{self, Ordering},
13-
task::Poll,
14-
};
10+
#[cfg(any(feature = "ptp", feature = "async-await"))]
11+
use core::task::Poll;
1512

1613
/// Errors that can occur during Ethernet TX
1714
#[derive(Debug, PartialEq)]
@@ -24,18 +21,16 @@ pub enum TxError {
2421
pub struct TxRing<'a> {
2522
pub(crate) entries: &'a mut [TxRingEntry],
2623
next_entry: usize,
27-
waker: &'static AtomicWaker,
2824
}
2925

3026
impl<'ring> TxRing<'ring> {
3127
/// Allocate
3228
///
3329
/// `start()` will be needed before `send()`
34-
pub fn new(entries: &'ring mut [TxRingEntry], waker: &'static AtomicWaker) -> Self {
30+
pub fn new(entries: &'ring mut [TxRingEntry]) -> Self {
3531
TxRing {
3632
entries,
3733
next_entry: 0,
38-
waker,
3934
}
4035
}
4136

@@ -64,7 +59,7 @@ impl<'ring> TxRing<'ring> {
6459

6560
// "Preceding reads and writes cannot be moved past subsequent writes."
6661
#[cfg(feature = "fence")]
67-
atomic::fence(Ordering::Release);
62+
core::sync::atomic::fence(core::sync::atomic::Ordering::Release);
6863

6964
// We don't need a compiler fence here because all interactions with `Descriptor` are
7065
// volatiles
@@ -130,6 +125,7 @@ impl<'ring> TxRing<'ring> {
130125
///
131126
/// When all data is copied into the TX buffer, use [`TxPacket::send()`]
132127
/// to transmit it.
128+
#[cfg(feature = "async-await")]
133129
pub async fn prepare_packet<'borrow>(
134130
&'borrow mut self,
135131
length: usize,
@@ -138,7 +134,7 @@ impl<'ring> TxRing<'ring> {
138134
let entry = core::future::poll_fn(|ctx| match self.send_next_impl() {
139135
Ok(packet) => Poll::Ready(packet),
140136
Err(_) => {
141-
self.waker.register(ctx.waker());
137+
crate::dma::EthernetDMA::tx_waker().register(ctx.waker());
142138
Poll::Pending
143139
}
144140
})
@@ -155,10 +151,6 @@ impl<'ring> TxRing<'ring> {
155151
}
156152
}
157153

158-
pub(crate) fn entry_available(&self, index: usize) -> bool {
159-
self.entries[index].is_available()
160-
}
161-
162154
/// Demand that the DMA engine polls the current `TxDescriptor`
163155
/// (when we just transferred ownership to the hardware).
164156
pub fn demand_poll(&self) {
@@ -217,6 +209,10 @@ impl TxRing<'_> {
217209
)
218210
}
219211

212+
pub(crate) fn entry_available(&self, index: usize) -> bool {
213+
self.entries[index].is_available()
214+
}
215+
220216
fn entry_timestamp(&self, index: usize) -> Option<Timestamp> {
221217
self.entries[index].timestamp()
222218
}

src/mac/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ impl EthernetMAC {
210210
}
211211
}
212212

213+
#[cfg(feature = "ptp")]
213214
pub(crate) fn mask_timestamp_trigger_interrupt() {
214215
// SAFETY: MACIMR only receives atomic writes.
215216
let mac = &unsafe { &*ETHERNET_MAC::ptr() };

src/peripherals.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,13 @@ mod pac_override_impl {
322322
impl ETHERNET_PTP {
323323
#[doc = r"Pointer to the register block"]
324324
pub const PTR: *const PtpRegisterBlock = 0x4002_8700 as *const _;
325+
326+
#[doc = r"Return the pointer to the register block"]
327+
#[inline(always)]
328+
#[allow(unused)]
329+
pub const fn ptr() -> *const PtpRegisterBlock {
330+
Self::PTR
331+
}
325332
}
326333

327334
impl core::ops::Deref for ETHERNET_PTP {

src/ptp/mod.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
//!
33
//! See [`EthernetPTP`] for a more details.
44
5-
use core::task::Poll;
6-
75
use crate::{dma::EthernetDMA, hal::rcc::Clocks, mac::EthernetMAC, peripherals::ETHERNET_PTP};
86

97
mod timestamp;
10-
use futures::task::AtomicWaker;
118
pub use timestamp::Timestamp;
129

10+
#[cfg(feature = "async-await")]
11+
use {core::task::Poll, futures::task::AtomicWaker};
12+
1313
mod subseconds;
1414
pub use subseconds::{Subseconds, NANOS_PER_SECOND, SUBSECONDS_PER_SECOND, SUBSECONDS_TO_SECONDS};
1515

@@ -68,11 +68,6 @@ impl EthernetPTP {
6868
(stssi, tsa)
6969
}
7070

71-
fn waker() -> &'static AtomicWaker {
72-
static WAKER: AtomicWaker = AtomicWaker::new();
73-
&WAKER
74-
}
75-
7671
pub(crate) fn new(
7772
eth_ptp: ETHERNET_PTP,
7873
clocks: Clocks,
@@ -225,6 +220,12 @@ impl EthernetPTP {
225220
/// clear the flag as the register required to do so does not exist.
226221
#[cfg(not(feature = "stm32f1xx-hal"))]
227222
impl EthernetPTP {
223+
#[cfg(feature = "async-await")]
224+
fn waker() -> &'static AtomicWaker {
225+
static WAKER: AtomicWaker = AtomicWaker::new();
226+
&WAKER
227+
}
228+
228229
/// Configure the target time.
229230
fn set_target_time(&mut self, timestamp: Timestamp) {
230231
let (high, low) = (timestamp.seconds(), timestamp.subseconds_signed());
@@ -247,6 +248,7 @@ impl EthernetPTP {
247248
}
248249

249250
/// Wait until the specified time.
251+
#[cfg(feature = "async-await")]
250252
pub async fn wait_until(&mut self, timestamp: Timestamp) {
251253
self.configure_target_time_interrupt(timestamp);
252254
core::future::poll_fn(|ctx| {
@@ -274,6 +276,7 @@ impl EthernetPTP {
274276
EthernetMAC::mask_timestamp_trigger_interrupt();
275277
}
276278

279+
#[cfg(feature = "async-await")]
277280
EthernetPTP::waker().wake();
278281

279282
is_tsint

0 commit comments

Comments
 (0)