@@ -6,6 +6,8 @@ use core::{
6
6
sync:: atomic:: { self , Ordering } ,
7
7
} ;
8
8
9
+ use nb:: block;
10
+
9
11
use crate :: {
10
12
clocks:: { Clocks , ExternalOscillator } ,
11
13
pac:: {
@@ -15,6 +17,51 @@ use crate::{
15
17
timer:: { self , Timer } ,
16
18
} ;
17
19
20
+ /// Non-blocking receive
21
+ pub struct Recv < ' a , ' c > {
22
+ radio : & ' a mut Radio < ' c > ,
23
+ _packet : & ' a mut Packet ,
24
+ }
25
+
26
+ impl < ' a , ' c > Recv < ' a , ' c > {
27
+ fn new ( radio : & ' a mut Radio < ' c > , packet : & ' a mut Packet ) -> Self {
28
+ Self {
29
+ radio,
30
+ _packet : packet,
31
+ }
32
+ }
33
+
34
+ /// Check if receive is done
35
+ ///
36
+ /// This methods returns the `Ok` variant if the CRC included the
37
+ /// packet was successfully validated by the hardware. It returns
38
+ /// `Err(nb::Error::WouldBlock)` if a packet hasn't been received
39
+ /// yet, and `Err(nb::Error::Other)` if the CRC check failed.
40
+ pub fn is_done ( & mut self ) -> nb:: Result < u16 , u16 > {
41
+ if self . radio . radio . events_end . read ( ) . events_end ( ) . bit_is_set ( ) {
42
+ self . radio . radio . events_end . reset ( ) ;
43
+
44
+ dma_end_fence ( ) ;
45
+
46
+ let crc = self . radio . radio . rxcrc . read ( ) . rxcrc ( ) . bits ( ) as u16 ;
47
+
48
+ if self . radio . radio . crcstatus . read ( ) . crcstatus ( ) . bit_is_set ( ) {
49
+ Ok ( crc)
50
+ } else {
51
+ Err ( nb:: Error :: Other ( crc) )
52
+ }
53
+ } else {
54
+ Err ( nb:: Error :: WouldBlock )
55
+ }
56
+ }
57
+ }
58
+
59
+ impl < ' a , ' c > Drop for Recv < ' a , ' c > {
60
+ fn drop ( & mut self ) {
61
+ self . radio . cancel_recv ( ) ;
62
+ }
63
+ }
64
+
18
65
/// IEEE 802.15.4 radio
19
66
pub struct Radio < ' c > {
20
67
radio : RADIO ,
@@ -305,22 +352,26 @@ impl<'c> Radio<'c> {
305
352
/// validated by the hardware; otherwise it returns the `Err` variant. In either case, `packet`
306
353
/// will be updated with the received packet's data
307
354
pub fn recv ( & mut self , packet : & mut Packet ) -> Result < u16 , u16 > {
355
+ // Start non-blocking receive
356
+ let mut recv = self . recv_non_blocking ( packet) ;
357
+
358
+ // Block untill receive is done
359
+ block ! ( recv. is_done( ) )
360
+ }
361
+
362
+ /// Receives one radio packet and copies its contents into the given `packet` buffer
363
+ ///
364
+ /// This method is non-blocking
365
+ pub fn recv_non_blocking < ' a > ( & ' a mut self , packet : & ' a mut Packet ) -> Recv < ' a , ' c > {
308
366
// Start the read
309
- // NOTE(unsafe) We block until reception completes or errors
367
+ // NOTE(unsafe)
368
+ // The packet must live until the transfer is done. Recv takes
369
+ // a mutable reference to the packet to enforce this.
310
370
unsafe {
311
371
self . start_recv ( packet) ;
312
372
}
313
373
314
- // wait until we have received something
315
- self . wait_for_event ( Event :: End ) ;
316
- dma_end_fence ( ) ;
317
-
318
- let crc = self . radio . rxcrc . read ( ) . rxcrc ( ) . bits ( ) as u16 ;
319
- if self . radio . crcstatus . read ( ) . crcstatus ( ) . bit_is_set ( ) {
320
- Ok ( crc)
321
- } else {
322
- Err ( crc)
323
- }
374
+ Recv :: new ( self , packet)
324
375
}
325
376
326
377
/// Listens for a packet for no longer than the specified amount of microseconds
@@ -347,39 +398,23 @@ impl<'c> Radio<'c> {
347
398
// Start the timeout timer
348
399
timer. start ( microseconds) ;
349
400
350
- // Start the read
351
- // NOTE(unsafe) We block until reception completes or errors
352
- unsafe {
353
- self . start_recv ( packet) ;
354
- }
355
-
356
- // Wait for transmission to end
357
- let mut recv_completed = false ;
401
+ // Start non-blocking receive
402
+ let mut recv = self . recv_non_blocking ( packet) ;
358
403
404
+ // Check if either receive is done or timeout occured
359
405
loop {
360
- if self . radio . events_end . read ( ) . bits ( ) != 0 {
361
- // transfer complete
362
- dma_end_fence ( ) ;
363
- recv_completed = true ;
364
- break ;
406
+ match recv. is_done ( ) {
407
+ Ok ( crc) => break Ok ( crc) ,
408
+ Err ( err) => match err {
409
+ nb:: Error :: Other ( crc) => break Err ( Error :: Crc ( crc) ) ,
410
+ nb:: Error :: WouldBlock => ( ) ,
411
+ } ,
365
412
}
366
413
367
414
if timer. reset_if_finished ( ) {
368
- // timeout
369
- break ;
370
- }
371
- }
372
-
373
- if !recv_completed {
374
- // Cancel the reception if it did not complete until now
375
- self . cancel_recv ( ) ;
376
- Err ( Error :: Timeout )
377
- } else {
378
- let crc = self . radio . rxcrc . read ( ) . rxcrc ( ) . bits ( ) as u16 ;
379
- if self . radio . crcstatus . read ( ) . crcstatus ( ) . bit_is_set ( ) {
380
- Ok ( crc)
381
- } else {
382
- Err ( Error :: Crc ( crc) )
415
+ // Break loop in case of timeout. Receive is
416
+ // cancelled when `recv` is dropped.
417
+ break Err ( Error :: Timeout ) ;
383
418
}
384
419
}
385
420
}
@@ -674,10 +709,6 @@ impl<'c> Radio<'c> {
674
709
675
710
fn wait_for_event ( & self , event : Event ) {
676
711
match event {
677
- Event :: End => {
678
- while self . radio . events_end . read ( ) . events_end ( ) . bit_is_clear ( ) { }
679
- self . radio . events_end . reset ( ) ;
680
- }
681
712
Event :: PhyEnd => {
682
713
while self
683
714
. radio
@@ -728,7 +759,6 @@ fn dma_end_fence() {
728
759
}
729
760
730
761
enum Event {
731
- End ,
732
762
PhyEnd ,
733
763
}
734
764
0 commit comments