@@ -6,6 +6,28 @@ use embedded_hal::spi::{Error, ErrorKind, ErrorType, Operation, SpiBus, SpiDevic
6
6
use super :: DeviceError ;
7
7
use crate :: spi:: shared:: transaction;
8
8
9
+ /// Cell type used by [`AtomicDevice`].
10
+ ///
11
+ /// To use [`AtomicDevice`], you must wrap the bus with this struct, and then
12
+ /// construct multiple [`AtomicDevice`] instances with references to it.
13
+ pub struct AtomicCell < BUS > {
14
+ bus : UnsafeCell < BUS > ,
15
+ busy : portable_atomic:: AtomicBool ,
16
+ }
17
+
18
+ unsafe impl < BUS : Send > Send for AtomicCell < BUS > { }
19
+ unsafe impl < BUS : Send > Sync for AtomicCell < BUS > { }
20
+
21
+ impl < BUS > AtomicCell < BUS > {
22
+ /// Create a new `AtomicCell`
23
+ pub fn new ( bus : BUS ) -> Self {
24
+ Self {
25
+ bus : UnsafeCell :: new ( bus) ,
26
+ busy : portable_atomic:: AtomicBool :: from ( false ) ,
27
+ }
28
+ }
29
+ }
30
+
9
31
/// `UnsafeCell`-based shared bus [`SpiDevice`] implementation.
10
32
///
11
33
/// This allows for sharing an [`SpiBus`], obtaining multiple [`SpiDevice`] instances,
@@ -19,10 +41,9 @@ use crate::spi::shared::transaction;
19
41
/// rules, such as the RTIC framework.
20
42
///
21
43
pub struct AtomicDevice < ' a , BUS , CS , D > {
22
- bus : & ' a UnsafeCell < BUS > ,
44
+ bus : & ' a AtomicCell < BUS > ,
23
45
cs : CS ,
24
46
delay : D ,
25
- busy : portable_atomic:: AtomicBool ,
26
47
}
27
48
28
49
#[ derive( Debug , Copy , Clone ) ]
@@ -40,13 +61,8 @@ pub enum AtomicError<T: Error> {
40
61
impl < ' a , BUS , CS , D > AtomicDevice < ' a , BUS , CS , D > {
41
62
/// Create a new [`AtomicDevice`].
42
63
#[ inline]
43
- pub fn new ( bus : & ' a UnsafeCell < BUS > , cs : CS , delay : D ) -> Self {
44
- Self {
45
- bus,
46
- cs,
47
- delay,
48
- busy : portable_atomic:: AtomicBool :: from ( false ) ,
49
- }
64
+ pub fn new ( bus : & ' a AtomicCell < BUS > , cs : CS , delay : D ) -> Self {
65
+ Self { bus, cs, delay }
50
66
}
51
67
}
52
68
@@ -72,18 +88,15 @@ where
72
88
/// The returned device will panic if you try to execute a transaction
73
89
/// that contains any operations of type [`Operation::DelayNs`].
74
90
#[ inline]
75
- pub fn new_no_delay ( bus : & ' a UnsafeCell < BUS > , cs : CS ) -> Self {
91
+ pub fn new_no_delay ( bus : & ' a AtomicCell < BUS > , cs : CS ) -> Self {
76
92
Self {
77
93
bus,
78
94
cs,
79
95
delay : super :: NoDelay ,
80
- busy : portable_atomic:: AtomicBool :: from ( false ) ,
81
96
}
82
97
}
83
98
}
84
99
85
- unsafe impl < ' a , BUS , CS , D > Send for AtomicDevice < ' a , BUS , CS , D > { }
86
-
87
100
impl < T : Error > Error for AtomicError < T > {
88
101
fn kind ( & self ) -> ErrorKind {
89
102
match self {
@@ -109,7 +122,8 @@ where
109
122
{
110
123
#[ inline]
111
124
fn transaction ( & mut self , operations : & mut [ Operation < ' _ , Word > ] ) -> Result < ( ) , Self :: Error > {
112
- self . busy
125
+ self . bus
126
+ . busy
113
127
. compare_exchange (
114
128
false ,
115
129
true ,
@@ -118,11 +132,13 @@ where
118
132
)
119
133
. map_err ( |_| AtomicError :: Busy ) ?;
120
134
121
- let bus = unsafe { & mut * self . bus . get ( ) } ;
135
+ let bus = unsafe { & mut * self . bus . bus . get ( ) } ;
122
136
123
137
let result = transaction ( operations, bus, & mut self . delay , & mut self . cs ) ;
124
138
125
- self . busy . store ( false , core:: sync:: atomic:: Ordering :: SeqCst ) ;
139
+ self . bus
140
+ . busy
141
+ . store ( false , core:: sync:: atomic:: Ordering :: SeqCst ) ;
126
142
127
143
result. map_err ( AtomicError :: Other )
128
144
}
0 commit comments