capsules_core/virtualizers/
virtual_spi.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Virtualize a SPI master bus to enable multiple users of the SPI bus.
6
7use core::cell::Cell;
8use kernel::collections::list::{List, ListLink, ListNode};
9use kernel::deferred_call::{DeferredCall, DeferredCallClient};
10use kernel::hil;
11use kernel::hil::spi::SpiMasterClient;
12use kernel::utilities::cells::{MapCell, OptionalCell};
13use kernel::utilities::leasable_buffer::SubSliceMut;
14use kernel::ErrorCode;
15
16/// The Mux struct manages multiple Spi clients. Each client may have
17/// at most one outstanding Spi request.
18pub struct MuxSpiMaster<'a, Spi: hil::spi::SpiMaster<'a>> {
19    spi: &'a Spi,
20    devices: List<'a, VirtualSpiMasterDevice<'a, Spi>>,
21    inflight: OptionalCell<&'a VirtualSpiMasterDevice<'a, Spi>>,
22    deferred_call: DeferredCall,
23}
24
25impl<'a, Spi: hil::spi::SpiMaster<'a>> hil::spi::SpiMasterClient for MuxSpiMaster<'a, Spi> {
26    fn read_write_done(
27        &self,
28        write_buffer: SubSliceMut<'static, u8>,
29        read_buffer: Option<SubSliceMut<'static, u8>>,
30        status: Result<usize, ErrorCode>,
31    ) {
32        let dev = self.inflight.take();
33        // Need to do next op before signaling so we get some kind of
34        // sharing. Otherwise a call to read_write in the callback
35        // can allow this client to never relinquish the device.
36        // -pal 7/30/21
37        self.do_next_op();
38        dev.map(move |device| {
39            device.read_write_done(write_buffer, read_buffer, status);
40        });
41    }
42}
43
44impl<'a, Spi: hil::spi::SpiMaster<'a>> MuxSpiMaster<'a, Spi> {
45    pub fn new(spi: &'a Spi) -> Self {
46        Self {
47            spi,
48            devices: List::new(),
49            inflight: OptionalCell::empty(),
50            deferred_call: DeferredCall::new(),
51        }
52    }
53
54    fn do_next_op(&self) {
55        if self.inflight.is_none() {
56            let mnode = self
57                .devices
58                .iter()
59                .find(|node| node.operation.get() != Op::Idle);
60            mnode.map(|node| {
61                let configuration = node.configuration.get();
62                let cs = configuration.chip_select;
63                let _ = self.spi.specify_chip_select(cs);
64
65                let op = node.operation.get();
66                // Need to set idle here in case callback changes state
67                node.operation.set(Op::Idle);
68                match op {
69                    Op::ReadWriteBytes => {
70                        // Only async operations want to block by setting
71                        // the devices as inflight.
72                        self.inflight.set(node);
73                        node.txbuffer.take().map(|txbuffer| {
74                            let rresult = self.spi.set_rate(configuration.rate);
75                            let polresult = self.spi.set_polarity(configuration.polarity);
76                            let phaseresult = self.spi.set_phase(configuration.phase);
77                            if rresult.is_err() || polresult.is_err() || phaseresult.is_err() {
78                                node.txbuffer.replace(txbuffer);
79                                node.operation.set(Op::ReadWriteDone(Err(ErrorCode::INVAL)));
80                                self.do_next_op_async();
81                            } else {
82                                let rxbuffer = node.rxbuffer.take();
83                                if let Err((e, write_buffer, read_buffer)) =
84                                    self.spi.read_write_bytes(txbuffer, rxbuffer)
85                                {
86                                    node.txbuffer.replace(write_buffer);
87                                    read_buffer.map(|buffer| {
88                                        node.rxbuffer.replace(buffer);
89                                    });
90                                    node.operation.set(Op::ReadWriteDone(Err(e)));
91                                    self.do_next_op_async();
92                                }
93                            }
94                        });
95                    }
96                    Op::ReadWriteDone(status) => {
97                        node.txbuffer.take().map(|write_buffer| {
98                            let read_buffer = node.rxbuffer.take();
99                            self.read_write_done(write_buffer, read_buffer, status);
100                        });
101                    }
102                    Op::Idle => {} // Can't get here...
103                }
104            });
105        } else {
106            self.inflight.map(|node| {
107                match node.operation.get() {
108                    // we have to report an error
109                    Op::ReadWriteDone(status) => {
110                        node.txbuffer.take().map(|write_buffer| {
111                            let read_buffer = node.rxbuffer.take();
112                            self.read_write_done(write_buffer, read_buffer, status);
113                        });
114                    }
115                    _ => {} // Something is really in flight
116                }
117            });
118        }
119    }
120
121    /// Asynchronously executes the next operation, if any. Used by calls
122    /// to trigger do_next_op such that it will execute after the call
123    /// returns. This is important in case the operation triggers an error,
124    /// requiring a callback with an error condition; if the operation
125    /// is executed synchronously, the callback may be reentrant (executed
126    /// during the downcall). Please see
127    /// <https://github.com/tock/tock/issues/1496>
128    fn do_next_op_async(&self) {
129        self.deferred_call.set();
130    }
131}
132
133impl<'a, Spi: hil::spi::SpiMaster<'a>> DeferredCallClient for MuxSpiMaster<'a, Spi> {
134    fn handle_deferred_call(&self) {
135        self.do_next_op();
136    }
137
138    fn register(&'static self) {
139        self.deferred_call.register(self);
140    }
141}
142
143#[derive(Copy, Clone, PartialEq)]
144enum Op {
145    Idle,
146    ReadWriteBytes,
147    ReadWriteDone(Result<usize, ErrorCode>),
148}
149
150// Structure used to store the SPI configuration of a client/virtual device,
151// so it can restored on each operation.
152struct SpiConfiguration<'a, Spi: hil::spi::SpiMaster<'a>> {
153    chip_select: Spi::ChipSelect,
154    polarity: hil::spi::ClockPolarity,
155    phase: hil::spi::ClockPhase,
156    rate: u32,
157}
158
159// Have to do this manually because otherwise the Copy and Clone are parameterized
160// by Spi::ChipSelect and don't work for Cells.
161// https://stackoverflow.com/questions/63132174/how-do-i-fix-the-method-clone-exists-but-the-following-trait-bounds-were-not
162impl<'a, Spi: hil::spi::SpiMaster<'a>> Copy for SpiConfiguration<'a, Spi> {}
163impl<'a, Spi: hil::spi::SpiMaster<'a>> Clone for SpiConfiguration<'a, Spi> {
164    fn clone(&self) -> SpiConfiguration<'a, Spi> {
165        *self
166    }
167}
168
169pub struct VirtualSpiMasterDevice<'a, Spi: hil::spi::SpiMaster<'a>> {
170    mux: &'a MuxSpiMaster<'a, Spi>,
171    configuration: Cell<SpiConfiguration<'a, Spi>>,
172    txbuffer: MapCell<SubSliceMut<'static, u8>>,
173    rxbuffer: MapCell<SubSliceMut<'static, u8>>,
174    operation: Cell<Op>,
175    next: ListLink<'a, VirtualSpiMasterDevice<'a, Spi>>,
176    client: OptionalCell<&'a dyn hil::spi::SpiMasterClient>,
177}
178
179impl<'a, Spi: hil::spi::SpiMaster<'a>> VirtualSpiMasterDevice<'a, Spi> {
180    pub fn new(
181        mux: &'a MuxSpiMaster<'a, Spi>,
182        chip_select: Spi::ChipSelect,
183    ) -> VirtualSpiMasterDevice<'a, Spi> {
184        VirtualSpiMasterDevice {
185            mux,
186            configuration: Cell::new(SpiConfiguration {
187                chip_select,
188                polarity: hil::spi::ClockPolarity::IdleLow,
189                phase: hil::spi::ClockPhase::SampleLeading,
190                rate: 100_000,
191            }),
192            txbuffer: MapCell::empty(),
193            rxbuffer: MapCell::empty(),
194            operation: Cell::new(Op::Idle),
195            next: ListLink::empty(),
196            client: OptionalCell::empty(),
197        }
198    }
199
200    /// Must be called right after `static_init!()`.
201    pub fn setup(&'a self) {
202        self.mux.devices.push_head(self);
203    }
204}
205
206impl<'a, Spi: hil::spi::SpiMaster<'a>> hil::spi::SpiMasterClient
207    for VirtualSpiMasterDevice<'a, Spi>
208{
209    fn read_write_done(
210        &self,
211        write_buffer: SubSliceMut<'static, u8>,
212        read_buffer: Option<SubSliceMut<'static, u8>>,
213        status: Result<usize, ErrorCode>,
214    ) {
215        self.client.map(move |client| {
216            client.read_write_done(write_buffer, read_buffer, status);
217        });
218    }
219}
220
221impl<'a, Spi: hil::spi::SpiMaster<'a>> ListNode<'a, VirtualSpiMasterDevice<'a, Spi>>
222    for VirtualSpiMasterDevice<'a, Spi>
223{
224    fn next(&'a self) -> &'a ListLink<'a, VirtualSpiMasterDevice<'a, Spi>> {
225        &self.next
226    }
227}
228
229impl<'a, Spi: hil::spi::SpiMaster<'a>> hil::spi::SpiMasterDevice<'a>
230    for VirtualSpiMasterDevice<'a, Spi>
231{
232    fn set_client(&self, client: &'a dyn SpiMasterClient) {
233        self.client.set(client);
234    }
235
236    fn configure(
237        &self,
238        cpol: hil::spi::ClockPolarity,
239        cpal: hil::spi::ClockPhase,
240        rate: u32,
241    ) -> Result<(), ErrorCode> {
242        if self.operation.get() == Op::Idle {
243            let mut configuration = self.configuration.get();
244            configuration.polarity = cpol;
245            configuration.phase = cpal;
246            configuration.rate = rate;
247            self.configuration.set(configuration);
248            Ok(())
249        } else {
250            Err(ErrorCode::BUSY)
251        }
252    }
253
254    fn read_write_bytes(
255        &self,
256        write_buffer: SubSliceMut<'static, u8>,
257        mut read_buffer: Option<SubSliceMut<'static, u8>>,
258    ) -> Result<
259        (),
260        (
261            ErrorCode,
262            SubSliceMut<'static, u8>,
263            Option<SubSliceMut<'static, u8>>,
264        ),
265    > {
266        if self.operation.get() == Op::Idle {
267            self.txbuffer.replace(write_buffer);
268            if let Some(rb) = read_buffer.take() {
269                self.rxbuffer.put(rb);
270            }
271            self.operation.set(Op::ReadWriteBytes);
272            self.mux.do_next_op();
273            Ok(())
274        } else {
275            Err((ErrorCode::BUSY, write_buffer, read_buffer))
276        }
277    }
278
279    fn set_polarity(&self, cpol: hil::spi::ClockPolarity) -> Result<(), ErrorCode> {
280        if self.operation.get() == Op::Idle {
281            let mut configuration = self.configuration.get();
282            configuration.polarity = cpol;
283            self.configuration.set(configuration);
284            Ok(())
285        } else {
286            Err(ErrorCode::BUSY)
287        }
288    }
289
290    fn set_phase(&self, cpal: hil::spi::ClockPhase) -> Result<(), ErrorCode> {
291        if self.operation.get() == Op::Idle {
292            let mut configuration = self.configuration.get();
293            configuration.phase = cpal;
294            self.configuration.set(configuration);
295            Ok(())
296        } else {
297            Err(ErrorCode::BUSY)
298        }
299    }
300
301    fn set_rate(&self, rate: u32) -> Result<(), ErrorCode> {
302        if self.operation.get() == Op::Idle {
303            let mut configuration = self.configuration.get();
304            configuration.rate = rate;
305            self.configuration.set(configuration);
306            Ok(())
307        } else {
308            Err(ErrorCode::BUSY)
309        }
310    }
311
312    fn get_polarity(&self) -> hil::spi::ClockPolarity {
313        self.configuration.get().polarity
314    }
315
316    fn get_phase(&self) -> hil::spi::ClockPhase {
317        self.configuration.get().phase
318    }
319
320    fn get_rate(&self) -> u32 {
321        self.configuration.get().rate
322    }
323}
324
325pub struct SpiSlaveDevice<'a, Spi: hil::spi::SpiSlave<'a>> {
326    spi: &'a Spi,
327    client: OptionalCell<&'a dyn hil::spi::SpiSlaveClient>,
328}
329
330impl<'a, Spi: hil::spi::SpiSlave<'a>> SpiSlaveDevice<'a, Spi> {
331    pub const fn new(spi: &'a Spi) -> SpiSlaveDevice<'a, Spi> {
332        SpiSlaveDevice {
333            spi,
334            client: OptionalCell::empty(),
335        }
336    }
337}
338
339impl<'a, Spi: hil::spi::SpiSlave<'a>> hil::spi::SpiSlaveClient for SpiSlaveDevice<'a, Spi> {
340    fn read_write_done(
341        &self,
342        write_buffer: Option<&'static mut [u8]>,
343        read_buffer: Option<&'static mut [u8]>,
344        len: usize,
345        status: Result<(), ErrorCode>,
346    ) {
347        self.client.map(move |client| {
348            client.read_write_done(write_buffer, read_buffer, len, status);
349        });
350    }
351
352    fn chip_selected(&self) {
353        self.client.map(move |client| {
354            client.chip_selected();
355        });
356    }
357}
358
359impl<'a, Spi: hil::spi::SpiSlave<'a>> hil::spi::SpiSlaveDevice<'a> for SpiSlaveDevice<'a, Spi> {
360    fn set_client(&self, client: &'a dyn hil::spi::SpiSlaveClient) {
361        self.client.set(client);
362    }
363
364    fn configure(
365        &self,
366        cpol: hil::spi::ClockPolarity,
367        cpal: hil::spi::ClockPhase,
368    ) -> Result<(), ErrorCode> {
369        self.spi.set_polarity(cpol)?;
370        self.spi.set_phase(cpal)
371    }
372
373    fn read_write_bytes(
374        &self,
375        write_buffer: Option<&'static mut [u8]>,
376        read_buffer: Option<&'static mut [u8]>,
377        len: usize,
378    ) -> Result<
379        (),
380        (
381            ErrorCode,
382            Option<&'static mut [u8]>,
383            Option<&'static mut [u8]>,
384        ),
385    > {
386        self.spi.read_write_bytes(write_buffer, read_buffer, len)
387    }
388
389    fn set_polarity(&self, cpol: hil::spi::ClockPolarity) -> Result<(), ErrorCode> {
390        self.spi.set_polarity(cpol)
391    }
392
393    fn set_phase(&self, cpal: hil::spi::ClockPhase) -> Result<(), ErrorCode> {
394        self.spi.set_phase(cpal)
395    }
396
397    fn get_polarity(&self) -> hil::spi::ClockPolarity {
398        self.spi.get_polarity()
399    }
400
401    fn get_phase(&self) -> hil::spi::ClockPhase {
402        self.spi.get_phase()
403    }
404}