@@ -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,47 @@ 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
+ }
24
+
25
+ impl < ' a , ' c > Recv < ' a , ' c > {
26
+ fn new ( radio : & ' a mut Radio < ' c > ) -> Self {
27
+ Self { radio }
28
+ }
29
+
30
+ /// Check if receive is done
31
+ ///
32
+ /// This methods returns the `Ok` variant if the CRC included the
33
+ /// packet was successfully validated by the hardware. It returns
34
+ /// `Err(nb::Error::WouldBlock)` if a packet hasn't been received
35
+ /// yet, and `Err(nb::Error::Other)` if the CRC check failed.
36
+ pub fn is_done ( & mut self ) -> nb:: Result < u16 , u16 > {
37
+ if self . radio . radio . events_end . read ( ) . events_end ( ) . bit_is_set ( ) {
38
+ self . radio . radio . events_end . reset ( ) ;
39
+
40
+ dma_end_fence ( ) ;
41
+
42
+ let crc = self . radio . radio . rxcrc . read ( ) . rxcrc ( ) . bits ( ) as u16 ;
43
+
44
+ if self . radio . radio . crcstatus . read ( ) . crcstatus ( ) . bit_is_set ( ) {
45
+ Ok ( crc)
46
+ } else {
47
+ Err ( nb:: Error :: Other ( crc) )
48
+ }
49
+ } else {
50
+ Err ( nb:: Error :: WouldBlock )
51
+ }
52
+ }
53
+ }
54
+
55
+ impl < ' a , ' c > Drop for Recv < ' a , ' c > {
56
+ fn drop ( & mut self ) {
57
+ self . radio . cancel_recv ( ) ;
58
+ }
59
+ }
60
+
18
61
/// IEEE 802.15.4 radio
19
62
pub struct Radio < ' c > {
20
63
radio : RADIO ,
@@ -305,22 +348,24 @@ impl<'c> Radio<'c> {
305
348
/// validated by the hardware; otherwise it returns the `Err` variant. In either case, `packet`
306
349
/// will be updated with the received packet's data
307
350
pub fn recv ( & mut self , packet : & mut Packet ) -> Result < u16 , u16 > {
351
+ // Start non-blocking receive
352
+ let mut recv = self . recv_non_blocking ( packet) ;
353
+
354
+ // Block untill receive is done
355
+ block ! ( recv. is_done( ) )
356
+ }
357
+
358
+ /// Receives one radio packet and copies its contents into the given `packet` buffer
359
+ ///
360
+ /// This method is non-blocking
361
+ pub fn recv_non_blocking ( & mut self , packet : & mut Packet ) -> Recv < ' _ , ' c > {
308
362
// Start the read
309
363
// NOTE(unsafe) We block until reception completes or errors
310
364
unsafe {
311
365
self . start_recv ( packet) ;
312
366
}
313
367
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
- }
368
+ Recv :: new ( self )
324
369
}
325
370
326
371
/// Listens for a packet for no longer than the specified amount of microseconds
@@ -347,40 +392,32 @@ impl<'c> Radio<'c> {
347
392
// Start the timeout timer
348
393
timer. start ( microseconds) ;
349
394
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 ;
395
+ let result = {
396
+ // Start non-blocking receive
397
+ let mut recv = self . recv_non_blocking ( packet) ;
358
398
359
- loop {
360
- if self . radio . events_end . read ( ) . bits ( ) != 0 {
361
- // transfer complete
362
- dma_end_fence ( ) ;
363
- recv_completed = true ;
364
- break ;
365
- }
399
+ // Check if either receive is done, or timeout occurs
400
+ loop {
401
+ match recv. is_done ( ) {
402
+ Ok ( crc) => break Some ( Ok ( crc) ) ,
403
+ Err ( err) => match err {
404
+ nb:: Error :: Other ( crc) => break Some ( Err ( Error :: Crc ( crc) ) ) ,
405
+ nb:: Error :: WouldBlock => ( ) ,
406
+ } ,
407
+ }
366
408
367
- if timer. reset_if_finished ( ) {
368
- // timeout
369
- break ;
409
+ if timer. reset_if_finished ( ) {
410
+ // Break loop in case of timeout. Receive is
411
+ // cancelled when `recv` is dropped.
412
+ break None ;
413
+ }
370
414
}
371
- }
415
+ } ;
372
416
373
- if !recv_completed {
374
- // Cancel the reception if it did not complete until now
375
- self . cancel_recv ( ) ;
376
- Err ( Error :: Timeout )
417
+ if let Some ( result) = result {
418
+ result
377
419
} 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) )
383
- }
420
+ Err ( Error :: Timeout )
384
421
}
385
422
}
386
423
@@ -674,10 +711,6 @@ impl<'c> Radio<'c> {
674
711
675
712
fn wait_for_event ( & self , event : Event ) {
676
713
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
714
Event :: PhyEnd => {
682
715
while self
683
716
. radio
@@ -728,7 +761,6 @@ fn dma_end_fence() {
728
761
}
729
762
730
763
enum Event {
731
- End ,
732
764
PhyEnd ,
733
765
}
734
766
0 commit comments