Skip to content

Commit 7076639

Browse files
committed
add recv_timeout
1 parent 3ea430f commit 7076639

File tree

1 file changed

+96
-14
lines changed

1 file changed

+96
-14
lines changed

nrf52840-hal/src/ieee802154.rs

Lines changed: 96 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ use core::{
55
sync::atomic::{self, Ordering},
66
};
77

8-
use crate::clocks::{Clocks, ExternalOscillator};
9-
use crate::pac::{
10-
generic::Variant,
11-
radio::{state::STATE_A, txpower::TXPOWER_A},
12-
RADIO,
8+
use embedded_hal::timer::CountDown as _;
9+
10+
use crate::{
11+
clocks::{Clocks, ExternalOscillator},
12+
pac::{
13+
generic::Variant,
14+
radio::{state::STATE_A, txpower::TXPOWER_A},
15+
RADIO,
16+
},
17+
timer::{self, Timer},
1318
};
1419

1520
/// IEEE 802.15.4 radio
@@ -244,6 +249,78 @@ impl<'c> Radio<'c> {
244249
/// validated by the hardware; otherwise it returns the `Err` variant. In either case, `packet`
245250
/// will be updated with the received packet's data
246251
pub fn recv(&mut self, packet: &mut Packet) -> Result<u16, u16> {
252+
// Start the read
253+
self.start_recv(packet);
254+
255+
// wait until we have received something
256+
self.wait_for_event(Event::End);
257+
dma_end_fence();
258+
259+
let crc = self.radio.rxcrc.read().rxcrc().bits() as u16;
260+
if self.radio.crcstatus.read().crcstatus().bit_is_set() {
261+
Ok(crc)
262+
} else {
263+
Err(crc)
264+
}
265+
}
266+
267+
/// Listens for a packet for no longer than the specified amount of milliseconds
268+
///
269+
/// If no packet is received within the specified time then the `Timeout` error is returned
270+
///
271+
/// If a packet is received within the time span then the packet CRC is checked. If the CRC is
272+
/// incorrect then the `Crc` error is returned; otherwise the `Ok` variant is returned.
273+
///
274+
/// Note that the time it takes to switch the radio to RX mode is included in the timeout count.
275+
/// This transition may take up to a hundred of milliseconds; see the section 6.20.15.8 in the
276+
/// Product Specification for more details about timing
277+
pub fn recv_timeout<I>(
278+
&mut self,
279+
packet: &mut Packet,
280+
timer: &mut Timer<I>,
281+
millis: u32,
282+
) -> Result<u16, Error>
283+
where
284+
I: timer::Instance,
285+
{
286+
// Start the timeout timer
287+
timer.start(millis);
288+
289+
// Start the read
290+
self.start_recv(packet);
291+
292+
// Wait for transmission to end
293+
let mut recv_completed = false;
294+
295+
loop {
296+
if self.radio.events_end.read().bits() != 0 {
297+
// transfer complete
298+
dma_end_fence();
299+
recv_completed = true;
300+
break;
301+
}
302+
303+
if timer.wait().is_ok() {
304+
// timeout
305+
break;
306+
}
307+
}
308+
309+
if !recv_completed {
310+
// Cancel the reception if it did not complete until now
311+
self.cancel_recv();
312+
Err(Error::Timeout)
313+
} else {
314+
let crc = self.radio.rxcrc.read().rxcrc().bits() as u16;
315+
if self.radio.crcstatus.read().crcstatus().bit_is_set() {
316+
Ok(crc)
317+
} else {
318+
Err(Error::Crc(crc))
319+
}
320+
}
321+
}
322+
323+
fn start_recv(&mut self, packet: &mut Packet) {
247324
// NOTE we do NOT check the address of `packet`; see comment in `Packet::new` for details
248325

249326
// clear related events
@@ -263,17 +340,13 @@ impl<'c> Radio<'c> {
263340
// start transfer
264341
dma_start_fence();
265342
self.radio.tasks_start.write(|w| w.tasks_start().set_bit());
343+
}
266344

267-
// wait until we have received something
268-
self.wait_for_event(Event::End);
345+
fn cancel_recv(&mut self) {
346+
self.radio.tasks_stop.write(|w| w.tasks_stop().set_bit());
347+
self.wait_for_state_a(STATE_A::RXIDLE);
348+
// DMA transfer may have been in progress so synchronize with its memory operations
269349
dma_end_fence();
270-
271-
let crc = self.radio.rxcrc.read().rxcrc().bits() as u16;
272-
if self.radio.crcstatus.read().crcstatus().bit_is_set() {
273-
Ok(crc)
274-
} else {
275-
Err(crc)
276-
}
277350
}
278351

279352
/// Tries to send the given `packet`
@@ -540,6 +613,15 @@ impl<'c> Radio<'c> {
540613
}
541614
}
542615

616+
/// Error
617+
#[derive(Copy, Clone, Debug, PartialEq)]
618+
pub enum Error {
619+
/// Incorrect CRC
620+
Crc(u16),
621+
/// Timeout
622+
Timeout,
623+
}
624+
543625
/// Driver state
544626
///
545627
/// After, or at the start of, any method call the RADIO will be in one of these states

0 commit comments

Comments
 (0)