Skip to main content

capsules_core/
adc.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//! Syscall driver capsules for ADC sampling.
6//!
7//! This module has two ADC syscall driver capsule implementations.
8//!
9//! The first, called AdcDedicated, assumes that it has complete (dedicated)
10//! control of the kernel ADC. This capsule provides userspace with
11//! the ability to perform single, continuous, and high speed samples.
12//! However, using this capsule means that no other
13//! capsule or kernel service can use the ADC. It also allows only
14//! a single process to use the ADC: other processes will receive
15//! NOMEM errors.
16//!
17//! The second, called AdcVirtualized, sits top of an ADC virtualizer.
18//! This capsule shares the ADC with the rest of the kernel through this
19//! virtualizer, so allows other kernel services and capsules to use the
20//! ADC. It also supports multiple processes requesting ADC samples
21//! concurrently. However, it only supports processes requesting single
22//! ADC samples: they cannot sample continuously or at high speed.
23//!
24//!
25//! Usage
26//! -----
27//!
28//! ```rust,ignore
29//! # use kernel::static_init;
30//!
31//! let adc_channels = static_init!(
32//!     [&'static sam4l::adc::AdcChannel; 6],
33//!     [
34//!         &sam4l::adc::CHANNEL_AD0, // A0
35//!         &sam4l::adc::CHANNEL_AD1, // A1
36//!         &sam4l::adc::CHANNEL_AD3, // A2
37//!         &sam4l::adc::CHANNEL_AD4, // A3
38//!         &sam4l::adc::CHANNEL_AD5, // A4
39//!         &sam4l::adc::CHANNEL_AD6, // A5
40//!     ]
41//! );
42//! let adc = static_init!(
43//!     capsules_core::adc::AdcDedicated<'static, sam4l::adc::Adc>,
44//!     capsules_core::adc::AdcDedicated::new(
45//!         &mut sam4l::adc::ADC0,
46//!         adc_channels,
47//!         &mut capsules_core::adc::ADC_BUFFER1,
48//!         &mut capsules_core::adc::ADC_BUFFER2,
49//!         &mut capsules_core::adc::ADC_BUFFER3
50//!     )
51//! );
52//! sam4l::adc::ADC0.set_client(adc);
53//! ```
54
55use core::cell::Cell;
56use core::cmp;
57
58use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
59use kernel::hil;
60use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer};
61use kernel::syscall::{CommandReturn, SyscallDriver};
62use kernel::utilities::cells::{OptionalCell, TakeCell};
63use kernel::{ErrorCode, ProcessId};
64
65/// Syscall driver number.
66use crate::driver;
67use crate::virtualizers::virtual_adc::Operation;
68pub const DRIVER_NUM: usize = driver::NUM::Adc as usize;
69
70/// Multiplexed ADC syscall driver, used by applications and capsules.
71///
72/// Virtualized, and can be use by multiple applications at the same time;
73/// requests are queued. Does not support continuous or high-speed sampling.
74pub struct AdcVirtualized<'a> {
75    drivers: &'a [&'a dyn hil::adc::AdcChannel<'a>],
76    apps: Grant<AppSys, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<0>>,
77    current_process: OptionalCell<ProcessId>,
78}
79
80/// ADC syscall driver, used by applications to interact with ADC.
81///
82/// Not currently virtualized: does not share the ADC with other capsules
83/// and only one application can use it at a time. Supports continuous and
84/// high speed sampling.
85pub struct AdcDedicated<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> {
86    // ADC driver
87    adc: &'a A,
88    channels: &'a [<A as hil::adc::Adc<'a>>::Channel],
89
90    // ADC state
91    active: Cell<bool>,
92    mode: Cell<AdcMode>,
93
94    // App state
95    apps: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<2>>,
96    processid: OptionalCell<ProcessId>,
97    channel: Cell<usize>,
98
99    // ADC buffers
100    adc_buf1: TakeCell<'static, [u16]>,
101    adc_buf2: TakeCell<'static, [u16]>,
102    adc_buf3: TakeCell<'static, [u16]>,
103}
104
105/// ADC modes, used to track internal state and to signify to applications which
106/// state a callback came from
107#[derive(Copy, Clone, Debug, PartialEq)]
108pub(crate) enum AdcMode {
109    NoMode = -1,
110    SingleSample = 0,
111    ContinuousSample = 1,
112    SingleBuffer = 2,
113    ContinuousBuffer = 3,
114}
115
116// Datas passed by the application to us
117pub struct AppSys {
118    pending_command: bool,
119    command: OptionalCell<Operation>,
120    channel: usize,
121}
122
123/// Holds buffers that the application has passed us
124pub struct App {
125    app_buf_offset: Cell<usize>,
126    samples_remaining: Cell<usize>,
127    samples_outstanding: Cell<usize>,
128    next_samples_outstanding: Cell<usize>,
129    using_app_buf0: Cell<bool>,
130}
131
132impl Default for App {
133    fn default() -> App {
134        App {
135            app_buf_offset: Cell::new(0),
136            samples_remaining: Cell::new(0),
137            samples_outstanding: Cell::new(0),
138            next_samples_outstanding: Cell::new(0),
139            using_app_buf0: Cell::new(true),
140        }
141    }
142}
143
144impl Default for AppSys {
145    fn default() -> AppSys {
146        AppSys {
147            pending_command: false,
148            command: OptionalCell::empty(),
149            channel: 0,
150        }
151    }
152}
153/// Buffers to use for DMA transfers.
154///
155/// The size is chosen somewhat arbitrarily, but has been tested. At 175000 Hz,
156/// buffers need to be swapped every 70 us and copied over before the next
157/// swap. In testing, it seems to keep up fine.
158pub const BUF_LEN: usize = 128;
159
160impl<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> AdcDedicated<'a, A> {
161    /// Create a new `Adc` application interface.
162    ///
163    /// - `adc` - ADC driver to provide application access to
164    /// - `channels` - list of ADC channels usable by applications
165    /// - `adc_buf1` - buffer used to hold ADC samples
166    /// - `adc_buf2` - second buffer used when continuously sampling ADC
167    pub fn new(
168        adc: &'a A,
169        grant: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<2>>,
170        channels: &'a [<A as hil::adc::Adc<'a>>::Channel],
171        adc_buf1: &'static mut [u16; 128],
172        adc_buf2: &'static mut [u16; 128],
173        adc_buf3: &'static mut [u16; 128],
174    ) -> AdcDedicated<'a, A> {
175        AdcDedicated {
176            // ADC driver
177            adc,
178            channels,
179
180            // ADC state
181            active: Cell::new(false),
182            mode: Cell::new(AdcMode::NoMode),
183
184            // App state
185            apps: grant,
186            processid: OptionalCell::empty(),
187            channel: Cell::new(0),
188
189            // ADC buffers
190            adc_buf1: TakeCell::new(adc_buf1),
191            adc_buf2: TakeCell::new(adc_buf2),
192            adc_buf3: TakeCell::new(adc_buf3),
193        }
194    }
195
196    /// Store a buffer we've regained ownership of and return a handle to it.
197    /// The handle can have `map()` called on it in order to process the data in
198    /// the buffer.
199    ///
200    /// - `buf` - buffer to be stored
201    fn replace_buffer(&self, buf: &'static mut [u16]) -> &TakeCell<'static, [u16]> {
202        // We play a little trick here where we always insert replaced buffers
203        // in the last position but pull new buffers (in `take_and_map_buffer`)
204        // from the beginning. We do this to get around Rust ownership rules
205        // when handling errors. When we are doing continuous buffering, we need
206        // to make sure that we re-gain ownership of the buffer passed back from
207        // the ADC driver, AND we have to copy from that buffer the samples the
208        // ADC driver took. To allow us to ensure we re-gain ownership, even if
209        // an error occurs (like the app crashes), we unconditionally save
210        // ownership of the returned buffer first (by calling this function).
211        // However, we also pass zero or one buffers back to the ADC driver, and
212        // we must ensure we do not pass the same buffer right back to the
213        // driver before we have had a chance to save the samples.
214
215        if self.adc_buf3.is_none() {
216            self.adc_buf3.replace(buf);
217        } else {
218            let temp = self.adc_buf3.take();
219            self.adc_buf3.replace(buf);
220
221            // Find a place to insert the buffer we removed from the last slot.
222            if self.adc_buf2.is_none() {
223                temp.map(|likely_buffer| self.adc_buf2.replace(likely_buffer));
224            } else {
225                temp.map(|likely_buffer| self.adc_buf1.replace(likely_buffer));
226            }
227        }
228
229        &self.adc_buf3
230    }
231
232    /// Find a buffer to give to the ADC to store samples in.
233    ///
234    /// - `closure` - function to run on the found buffer
235    fn take_and_map_buffer<F: FnOnce(&'static mut [u16])>(&self, closure: F) {
236        if self.adc_buf1.is_some() {
237            self.adc_buf1.take().map(|val| {
238                closure(val);
239            });
240        } else if self.adc_buf2.is_some() {
241            self.adc_buf2.take().map(|val| {
242                closure(val);
243            });
244        } else if self.adc_buf3.is_some() {
245            self.adc_buf3.take().map(|val| {
246                closure(val);
247            });
248        }
249    }
250
251    /// Collect a single analog sample on a channel.
252    ///
253    /// - `channel` - index into `channels` array, which channel to sample
254    fn sample(&self, channel: usize) -> Result<(), ErrorCode> {
255        // only one sample at a time
256        if self.active.get() {
257            return Err(ErrorCode::BUSY);
258        }
259
260        // convert channel index
261        if channel >= self.channels.len() {
262            return Err(ErrorCode::INVAL);
263        }
264        let chan = &self.channels[channel];
265
266        // save state for callback
267        self.active.set(true);
268        self.mode.set(AdcMode::SingleSample);
269        self.channel.set(channel);
270
271        // start a single sample
272        let res = self.adc.sample(chan);
273        if res != Ok(()) {
274            // failure, clear state
275            self.active.set(false);
276            self.mode.set(AdcMode::NoMode);
277
278            return res;
279        }
280
281        Ok(())
282    }
283
284    /// Collect repeated single analog samples on a channel.
285    ///
286    /// - `channel` - index into `channels` array, which channel to sample
287    /// - `frequency` - number of samples per second to collect
288    fn sample_continuous(&self, channel: usize, frequency: u32) -> Result<(), ErrorCode> {
289        // only one sample at a time
290        if self.active.get() {
291            return Err(ErrorCode::BUSY);
292        }
293
294        // convert channel index
295        if channel >= self.channels.len() {
296            return Err(ErrorCode::INVAL);
297        }
298        let chan = &self.channels[channel];
299
300        // save state for callback
301        self.active.set(true);
302        self.mode.set(AdcMode::ContinuousSample);
303        self.channel.set(channel);
304
305        // start a single sample
306        let res = self.adc.sample_continuous(chan, frequency);
307        if res != Ok(()) {
308            // failure, clear state
309            self.active.set(false);
310            self.mode.set(AdcMode::NoMode);
311
312            return res;
313        }
314
315        Ok(())
316    }
317
318    /// Collect a buffer-full of analog samples.
319    ///
320    /// Samples are collected into the first app buffer provided. The number of
321    /// samples collected is equal to the size of the buffer "allowed".
322    ///
323    /// - `channel` - index into `channels` array, which channel to sample
324    /// - `frequency` - number of samples per second to collect
325    fn sample_buffer(&self, channel: usize, frequency: u32) -> Result<(), ErrorCode> {
326        // only one sample at a time
327        if self.active.get() {
328            return Err(ErrorCode::BUSY);
329        }
330
331        // convert channel index
332        if channel >= self.channels.len() {
333            return Err(ErrorCode::INVAL);
334        }
335        let chan = &self.channels[channel];
336
337        // cannot sample a buffer without a buffer to sample into
338        let mut app_buf_length = 0;
339        let exists = self.processid.map_or(false, |id| {
340            self.apps
341                .enter(id, |_, kernel_data| {
342                    app_buf_length = kernel_data
343                        .get_readwrite_processbuffer(0)
344                        .map_or(0, |b| b.len());
345                    app_buf_length > 0
346                })
347                .map_err(|err| {
348                    if err == kernel::process::Error::NoSuchApp
349                        || err == kernel::process::Error::InactiveApp
350                    {
351                        self.processid.clear();
352                    }
353                })
354                .unwrap_or(false)
355        });
356        if !exists {
357            return Err(ErrorCode::NOMEM);
358        }
359
360        // save state for callback
361        self.active.set(true);
362        self.mode.set(AdcMode::SingleBuffer);
363        let ret = self.processid.map_or(Err(ErrorCode::NOMEM), |id| {
364            self.apps
365                .enter(id, |app, _| {
366                    app.app_buf_offset.set(0);
367                    self.channel.set(channel);
368                    // start a continuous sample
369                    let res = self.adc_buf1.take().map_or(Err(ErrorCode::BUSY), |buf1| {
370                        self.adc_buf2
371                            .take()
372                            .map_or(Err(ErrorCode::BUSY), move |buf2| {
373                                // determine request length
374                                let request_len = app_buf_length / 2;
375                                let len1;
376                                let len2;
377                                if request_len <= buf1.len() {
378                                    len1 = app_buf_length / 2;
379                                    len2 = 0;
380                                } else if request_len <= (buf1.len() + buf2.len()) {
381                                    len1 = buf1.len();
382                                    len2 = request_len - buf1.len();
383                                } else {
384                                    len1 = buf1.len();
385                                    len2 = buf2.len();
386                                }
387
388                                // begin sampling
389                                app.using_app_buf0.set(true);
390                                app.samples_remaining.set(request_len - len1 - len2);
391                                app.samples_outstanding.set(len1 + len2);
392                                self.adc
393                                    .sample_highspeed(chan, frequency, buf1, len1, buf2, len2)
394                                    .map_or_else(
395                                        |(ecode, buf1, buf2)| {
396                                            // store buffers again
397                                            self.replace_buffer(buf1);
398                                            self.replace_buffer(buf2);
399                                            Err(ecode)
400                                        },
401                                        |()| Ok(()),
402                                    )
403                            })
404                    });
405                    res
406                })
407                .map_err(|err| {
408                    if err == kernel::process::Error::NoSuchApp
409                        || err == kernel::process::Error::InactiveApp
410                    {
411                        self.processid.clear();
412                    }
413                })
414                .unwrap_or(Err(ErrorCode::NOMEM))
415        });
416        if ret != Ok(()) {
417            // failure, clear state
418            self.active.set(false);
419            self.mode.set(AdcMode::NoMode);
420            self.processid.map(|id| {
421                self.apps
422                    .enter(id, |app, _| {
423                        app.samples_remaining.set(0);
424                        app.samples_outstanding.set(0);
425                    })
426                    .map_err(|err| {
427                        if err == kernel::process::Error::NoSuchApp
428                            || err == kernel::process::Error::InactiveApp
429                        {
430                            self.processid.clear();
431                        }
432                    })
433            });
434        }
435        ret
436    }
437
438    /// Collect analog samples continuously.
439    ///
440    /// Fills one "allowed" application buffer at a time and then swaps to
441    /// filling the second buffer. Upcalls occur when the in use "allowed"
442    /// buffer fills.
443    ///
444    /// - `channel` - index into `channels` array, which channel to sample
445    /// - `frequency` - number of samples per second to collect
446    fn sample_buffer_continuous(&self, channel: usize, frequency: u32) -> Result<(), ErrorCode> {
447        // only one sample at a time
448        if self.active.get() {
449            return Err(ErrorCode::BUSY);
450        }
451
452        // convert channel index
453        if channel >= self.channels.len() {
454            return Err(ErrorCode::INVAL);
455        }
456        let chan = &self.channels[channel];
457
458        // cannot continuously sample without two buffers
459        let mut app_buf_length = 0;
460        let mut next_app_buf_length = 0;
461        let exists = self.processid.map_or(false, |id| {
462            self.apps
463                .enter(id, |_, kernel_data| {
464                    app_buf_length = kernel_data
465                        .get_readwrite_processbuffer(0)
466                        .map_or(0, |b| b.len());
467                    next_app_buf_length = kernel_data
468                        .get_readwrite_processbuffer(1)
469                        .map_or(0, |b| b.len());
470                    app_buf_length > 0 && next_app_buf_length > 0
471                })
472                .map_err(|err| {
473                    if err == kernel::process::Error::NoSuchApp
474                        || err == kernel::process::Error::InactiveApp
475                    {
476                        self.processid.clear();
477                    }
478                })
479                .unwrap_or(false)
480        });
481        if !exists {
482            return Err(ErrorCode::NOMEM);
483        }
484
485        // save state for callback
486        self.active.set(true);
487        self.mode.set(AdcMode::ContinuousBuffer);
488
489        let ret = self.processid.map_or(Err(ErrorCode::NOMEM), |id| {
490            self.apps
491                .enter(id, |app, _| {
492                    app.app_buf_offset.set(0);
493                    self.channel.set(channel);
494                    // start a continuous sample
495                    self.adc_buf1.take().map_or(Err(ErrorCode::BUSY), |buf1| {
496                        self.adc_buf2
497                            .take()
498                            .map_or(Err(ErrorCode::BUSY), move |buf2| {
499                                // determine request lengths
500                                let samples_needed = app_buf_length / 2;
501                                let next_samples_needed = next_app_buf_length / 2;
502
503                                // determine request lengths
504                                let len1;
505                                let len2;
506                                if samples_needed <= buf1.len() {
507                                    // we can fit the entire app_buffer request in the first
508                                    // buffer. The second buffer will be used for the next
509                                    // app_buffer
510                                    len1 = samples_needed;
511                                    len2 = cmp::min(next_samples_needed, buf2.len());
512                                    app.samples_remaining.set(0);
513                                    app.samples_outstanding.set(len1);
514                                } else if samples_needed <= (buf1.len() + buf2.len()) {
515                                    // we can fit the entire app_buffer request between the two
516                                    // buffers
517                                    len1 = buf1.len();
518                                    len2 = samples_needed - buf1.len();
519                                    app.samples_remaining.set(0);
520                                    app.samples_outstanding.set(len1 + len2);
521                                } else {
522                                    // the app_buffer is larger than both buffers, so just
523                                    // request max lengths
524                                    len1 = buf1.len();
525                                    len2 = buf2.len();
526                                    app.samples_remaining.set(samples_needed - len1 - len2);
527                                    app.samples_outstanding.set(len1 + len2);
528                                }
529
530                                // begin sampling
531                                app.using_app_buf0.set(true);
532                                self.adc
533                                    .sample_highspeed(chan, frequency, buf1, len1, buf2, len2)
534                                    .map_or_else(
535                                        |(ecode, buf1, buf2)| {
536                                            // store buffers again
537                                            self.replace_buffer(buf1);
538                                            self.replace_buffer(buf2);
539                                            Err(ecode)
540                                        },
541                                        |()| Ok(()),
542                                    )
543                            })
544                    })
545                })
546                .map_err(|err| {
547                    if err == kernel::process::Error::NoSuchApp
548                        || err == kernel::process::Error::InactiveApp
549                    {
550                        self.processid.clear();
551                    }
552                })
553                .unwrap_or(Err(ErrorCode::NOMEM))
554        });
555        if ret != Ok(()) {
556            // failure, clear state
557            self.active.set(false);
558            self.mode.set(AdcMode::NoMode);
559            self.processid.map(|id| {
560                self.apps
561                    .enter(id, |app, _| {
562                        app.samples_remaining.set(0);
563                        app.samples_outstanding.set(0);
564                    })
565                    .map_err(|err| {
566                        if err == kernel::process::Error::NoSuchApp
567                            || err == kernel::process::Error::InactiveApp
568                        {
569                            self.processid.clear();
570                        }
571                    })
572            });
573        }
574        ret
575    }
576
577    /// Stops sampling the ADC.
578    ///
579    /// Any active operation by the ADC is canceled. No additional callbacks
580    /// will occur. Also retrieves buffers from the ADC (if any).
581    fn stop_sampling(&self) -> Result<(), ErrorCode> {
582        if !self.active.get() || self.mode.get() == AdcMode::NoMode {
583            // already inactive!
584            return Ok(());
585        }
586
587        // clean up state
588        self.processid.map_or(Err(ErrorCode::FAIL), |id| {
589            self.apps
590                .enter(id, |app, _| {
591                    self.active.set(false);
592                    self.mode.set(AdcMode::NoMode);
593                    app.app_buf_offset.set(0);
594
595                    // actually cancel the operation
596                    let rc = self.adc.stop_sampling();
597                    if rc != Ok(()) {
598                        return rc;
599                    }
600
601                    // reclaim buffers
602                    match self.adc.retrieve_buffers() {
603                        Ok((buf1, buf2)) => {
604                            buf1.map(|buf| {
605                                self.replace_buffer(buf);
606                            });
607                            buf2.map(|buf| {
608                                self.replace_buffer(buf);
609                            });
610                            Ok(())
611                        }
612                        Err(ecode) => Err(ecode),
613                    }
614                })
615                .map_err(|err| {
616                    if err == kernel::process::Error::NoSuchApp
617                        || err == kernel::process::Error::InactiveApp
618                    {
619                        self.processid.clear();
620                    }
621                })
622                .unwrap_or(Err(ErrorCode::FAIL))
623        })
624    }
625
626    fn get_resolution_bits(&self) -> usize {
627        self.adc.get_resolution_bits()
628    }
629
630    fn get_voltage_reference_mv(&self) -> Option<usize> {
631        self.adc.get_voltage_reference_mv()
632    }
633}
634
635/// Functions to create, initialize, and interact with the virtualized ADC
636impl<'a> AdcVirtualized<'a> {
637    /// Create a new `Adc` application interface.
638    ///
639    /// - `drivers` - Virtual ADC drivers to provide application access to
640    pub fn new(
641        drivers: &'a [&'a dyn hil::adc::AdcChannel<'a>],
642        grant: Grant<AppSys, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<0>>,
643    ) -> AdcVirtualized<'a> {
644        AdcVirtualized {
645            drivers,
646            apps: grant,
647            current_process: OptionalCell::empty(),
648        }
649    }
650
651    /// Enqueue the command to be executed when the ADC is available.
652    fn enqueue_command(
653        &self,
654        command: Operation,
655        channel: usize,
656        processid: ProcessId,
657    ) -> Result<(), ErrorCode> {
658        if channel < self.drivers.len() {
659            if self.current_process.is_none() {
660                self.current_process.set(processid);
661                let r = self.call_driver(command, channel);
662                if r != Ok(()) {
663                    self.current_process.clear();
664                }
665                self.run_next_command();
666                Ok(())
667            } else {
668                match self
669                    .apps
670                    .enter(processid, |app, _| {
671                        if app.pending_command {
672                            Err(ErrorCode::BUSY)
673                        } else {
674                            app.pending_command = true;
675                            app.command.set(command);
676                            app.channel = channel;
677                            Ok(())
678                        }
679                    })
680                    .map_err(ErrorCode::from)
681                {
682                    Err(e) => Err(e),
683                    Ok(_) => Ok(()),
684                }
685            }
686        } else {
687            Err(ErrorCode::NODEVICE)
688        }
689    }
690
691    /// Run next command in queue, when available
692    fn run_next_command(&self) {
693        let mut command = Operation::OneSample;
694        let mut channel = 0;
695        for app in self.apps.iter() {
696            let processid = app.processid();
697            let start_command = app.enter(|app, _| {
698                if app.pending_command {
699                    app.pending_command = false;
700                    app.command.take().map(|c| {
701                        command = c;
702                    });
703                    channel = app.channel;
704                    self.current_process.set(processid);
705                    true
706                } else {
707                    false
708                }
709            });
710            if start_command {
711                match self.call_driver(command, channel) {
712                    Err(_) => {
713                        self.current_process.clear();
714                    }
715                    Ok(()) => {
716                        break;
717                    }
718                }
719            }
720        }
721    }
722
723    /// Request the sample from the specified channel
724    fn call_driver(&self, command: Operation, channel: usize) -> Result<(), ErrorCode> {
725        match command {
726            Operation::OneSample => self.drivers[channel].sample(),
727        }
728    }
729}
730
731/// Callbacks from the ADC driver
732impl<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> hil::adc::Client
733    for AdcDedicated<'a, A>
734{
735    /// Single sample operation complete.
736    ///
737    /// Collects the sample and provides a callback to the application.
738    ///
739    /// - `sample` - analog sample value
740    fn sample_ready(&self, sample: u16) {
741        let mut calledback = false;
742        if self.active.get() && self.mode.get() == AdcMode::SingleSample {
743            // single sample complete, clean up state
744            self.active.set(false);
745            self.mode.set(AdcMode::NoMode);
746
747            // perform callback
748
749            self.processid.map(|id| {
750                self.apps
751                    .enter(id, |_app, upcalls| {
752                        calledback = true;
753                        let _ = upcalls.schedule_upcall(
754                            0,
755                            (
756                                AdcMode::SingleSample as usize,
757                                self.channel.get(),
758                                sample as usize,
759                            ),
760                        );
761                    })
762                    .map_err(|err| {
763                        if err == kernel::process::Error::NoSuchApp
764                            || err == kernel::process::Error::InactiveApp
765                        {
766                            self.processid.clear();
767                        }
768                    })
769            });
770        } else if self.active.get() && self.mode.get() == AdcMode::ContinuousSample {
771            // sample ready in continuous sampling operation, keep state
772
773            // perform callback
774            self.processid.map(|id| {
775                self.apps
776                    .enter(id, |_app, upcalls| {
777                        calledback = true;
778                        let _ = upcalls.schedule_upcall(
779                            0,
780                            (
781                                AdcMode::ContinuousSample as usize,
782                                self.channel.get(),
783                                sample as usize,
784                            ),
785                        );
786                    })
787                    .map_err(|err| {
788                        if err == kernel::process::Error::NoSuchApp
789                            || err == kernel::process::Error::InactiveApp
790                        {
791                            self.processid.clear();
792                        }
793                    })
794            });
795        }
796        if !calledback {
797            // operation probably canceled. Make sure state is consistent. No
798            // callback
799            self.active.set(false);
800            self.mode.set(AdcMode::NoMode);
801
802            // Also make sure that no more samples are taken if we were in
803            // continuous mode.
804            let _ = self.adc.stop_sampling();
805        }
806    }
807}
808
809/// Callbacks from the High Speed ADC driver
810impl<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> hil::adc::HighSpeedClient
811    for AdcDedicated<'a, A>
812{
813    /// Internal buffer has filled from a buffered sampling operation.
814    /// Copies data over to application buffer, determines if more data is
815    /// needed, and performs a callback to the application if ready. If
816    /// continuously sampling, also swaps application buffers and continues
817    /// sampling when necessary. If only filling a single buffer, stops
818    /// sampling operation when the application buffer is full.
819    ///
820    /// - `buf` - internal buffer filled with analog samples
821    /// - `length` - number of valid samples in the buffer, guaranteed to be
822    ///   less than or equal to buffer length
823    fn samples_ready(&self, buf: &'static mut [u16], length: usize) {
824        let mut unexpected_state = false;
825
826        // Make sure in all cases we regain ownership of the buffer. However,
827        // we also get a reference back to it so we can copy the sampled values
828        // out and to an application.
829        let buffer_with_samples = self.replace_buffer(buf);
830
831        // do we expect a buffer?
832        if self.active.get()
833            && (self.mode.get() == AdcMode::SingleBuffer
834                || self.mode.get() == AdcMode::ContinuousBuffer)
835        {
836            // we did expect a buffer. Determine the current application state
837            self.processid.map(|id| {
838                self.apps
839                    .enter(id, |app, kernel_data| {
840                        // Get both buffers, this shouldn't ever fail since the grant was created
841                        // with enough space. The buffer still may be empty though
842                        let app_buf0 = match kernel_data.get_readwrite_processbuffer(0) {
843                            Ok(buf) => buf,
844                            Err(_) => return,
845                        };
846                        let app_buf1 = match kernel_data.get_readwrite_processbuffer(1) {
847                            Ok(buf) => buf,
848                            Err(_) => return,
849                        };
850                        // determine which app buffer to copy data into and which is
851                        // next up if we're in continuous mode
852                        let use0 = app.using_app_buf0.get();
853                        let next_app_buf;
854                        let app_buf_ref;
855                        if use0 {
856                            app_buf_ref = &app_buf0;
857                            next_app_buf = &app_buf1;
858                        } else {
859                            app_buf_ref = &app_buf1;
860                            next_app_buf = &app_buf0;
861                        }
862
863                        // update count of outstanding sample requests
864                        app.samples_outstanding
865                            .set(app.samples_outstanding.get() - length);
866
867                        // provide a new buffer and length request to the ADC if
868                        // necessary. If we haven't received enough samples for the
869                        // current app_buffer, we may need to place more requests. If we
870                        // have received enough, but are in continuous mode, we should
871                        // place a request for the next app_buffer. This is all
872                        // unfortunately made more complicated by the fact that there is
873                        // always one outstanding request to the ADC.
874                        let perform_callback;
875                        if app.samples_remaining.get() == 0 {
876                            // we have already placed outstanding requests for all the
877                            // samples needed to fill the current app_buffer
878
879                            if app.samples_outstanding.get() == 0 {
880                                // and the samples we just received are the last ones
881                                // we need
882                                perform_callback = true;
883
884                                if self.mode.get() == AdcMode::ContinuousBuffer {
885                                    // it's time to switch to the next app_buffer, but
886                                    // there's already an outstanding request to the ADC
887                                    // for the next app_buffer that was placed last
888                                    // time, so we need to account for that
889                                    let samples_needed =
890                                        next_app_buf.enter(|buf| buf.len() / 2).unwrap_or(0);
891                                    app.samples_remaining
892                                        .set(samples_needed - app.next_samples_outstanding.get());
893                                    app.samples_outstanding
894                                        .set(app.next_samples_outstanding.get());
895                                    app.using_app_buf0.set(!app.using_app_buf0.get());
896
897                                    // we also need to place our next request, however
898                                    // the outstanding request already placed for the
899                                    // next app_buffer might have completed it! So we
900                                    // have to account for that case
901                                    if app.samples_remaining.get() == 0 {
902                                        // oh boy. We actually need to place a request
903                                        // for the next next app_buffer (which is
904                                        // actually the current app_buf, but try not to
905                                        // think about that...). In practice, this
906                                        // should be a pretty uncommon case to hit, only
907                                        // occurring if the length of the app buffers
908                                        // are smaller than the length of the adc
909                                        // buffers, which is unsustainable at high
910                                        // sampling frequencies
911                                        let next_next_app_buf = &app_buf_ref;
912
913                                        // provide a new buffer. However, we cannot
914                                        // currently update state since the next
915                                        // app_buffer still has a request outstanding.
916                                        // We'll just make a request and handle the
917                                        // state updating on next callback
918                                        self.take_and_map_buffer(|adc_buf| {
919                                            let samples_needed = next_next_app_buf
920                                                .enter(|buf| buf.len() / 2)
921                                                .unwrap_or(0);
922                                            let request_len =
923                                                cmp::min(samples_needed, adc_buf.len());
924                                            app.next_samples_outstanding.set(request_len);
925                                            let _ = self
926                                                .adc
927                                                .provide_buffer(adc_buf, request_len)
928                                                .map_err(|(_, buf)| {
929                                                    self.replace_buffer(buf);
930                                                });
931                                        });
932                                    } else {
933                                        // okay, we still need more samples for the next
934                                        // app_buffer
935
936                                        // provide a new buffer and update state
937                                        self.take_and_map_buffer(|adc_buf| {
938                                            let request_len = cmp::min(
939                                                app.samples_remaining.get(),
940                                                adc_buf.len(),
941                                            );
942                                            app.samples_remaining
943                                                .set(app.samples_remaining.get() - request_len);
944                                            app.samples_outstanding
945                                                .set(app.samples_outstanding.get() + request_len);
946                                            let _ = self
947                                                .adc
948                                                .provide_buffer(adc_buf, request_len)
949                                                .map_err(|(_, buf)| {
950                                                    self.replace_buffer(buf);
951                                                });
952                                        });
953                                    }
954                                }
955                            } else {
956                                // but there are still outstanding samples for the
957                                // current app_buffer (actually exactly one request, the
958                                // one the ADC is currently acting on)
959                                perform_callback = false;
960
961                                if self.mode.get() == AdcMode::ContinuousBuffer {
962                                    // we're in continuous mode, so we need to start the
963                                    // first request for the next app_buffer
964
965                                    // provide a new buffer. However, we cannot
966                                    // currently update state since the current
967                                    // app_buffer still has a request outstanding. We'll
968                                    // just make a request and handle the state updating
969                                    // on next callback
970                                    self.take_and_map_buffer(|adc_buf| {
971                                        let samples_needed =
972                                            next_app_buf.enter(|buf| buf.len() / 2).unwrap_or(0);
973                                        let request_len = cmp::min(samples_needed, adc_buf.len());
974                                        app.next_samples_outstanding.set(request_len);
975                                        let _ = self
976                                            .adc
977                                            .provide_buffer(adc_buf, request_len)
978                                            .map_err(|(_, buf)| {
979                                                self.replace_buffer(buf);
980                                            });
981                                    });
982                                }
983                            }
984                        } else {
985                            // we need to get more samples for the current app_buffer
986                            perform_callback = false;
987
988                            // provide a new buffer and update state
989                            self.take_and_map_buffer(|adc_buf| {
990                                let request_len =
991                                    cmp::min(app.samples_remaining.get(), adc_buf.len());
992                                app.samples_remaining
993                                    .set(app.samples_remaining.get() - request_len);
994                                app.samples_outstanding
995                                    .set(app.samples_outstanding.get() + request_len);
996                                let _ = self.adc.provide_buffer(adc_buf, request_len).map_err(
997                                    |(_, buf)| {
998                                        self.replace_buffer(buf);
999                                    },
1000                                );
1001                            });
1002                        }
1003
1004                        let skip_amt = app.app_buf_offset.get() / 2;
1005
1006                        {
1007                            let app_buf = if use0 { &app_buf0 } else { &app_buf1 };
1008
1009                            // next we should copy bytes to the app buffer
1010                            let _ = app_buf.mut_enter(|app_buf| {
1011                                // Copy bytes to app buffer by iterating over the
1012                                // data.
1013                                buffer_with_samples.map(|adc_buf| {
1014                                    // The `for` commands:
1015                                    //  * `chunks_mut`: get sets of two bytes from the app
1016                                    //                  buffer
1017                                    //  * `skip`: skips the already written bytes from the
1018                                    //            app buffer
1019                                    //  * `zip`: ties that iterator to an iterator on the
1020                                    //           adc buffer, limiting iteration length to
1021                                    //           the minimum of each of their lengths
1022                                    //  * `take`: limits us to the minimum of buffer lengths
1023                                    //            or sample length
1024                                    // We then split each sample into its two bytes and copy
1025                                    // them to the app buffer
1026                                    for (chunk, &sample) in app_buf
1027                                        .chunks(2)
1028                                        .skip(skip_amt)
1029                                        .zip(adc_buf.iter())
1030                                        .take(length)
1031                                    {
1032                                        let mut val = sample;
1033                                        for byte in chunk.iter() {
1034                                            byte.set((val & 0xFF) as u8);
1035                                            val >>= 8;
1036                                        }
1037                                    }
1038                                });
1039                            });
1040                        }
1041                        // update our byte offset based on how many samples we
1042                        // copied
1043                        app.app_buf_offset
1044                            .set(app.app_buf_offset.get() + length * 2);
1045
1046                        // let in_use_buf;
1047                        let (buf_ptr, buf_len) = if use0 {
1048                            (app_buf0.ptr(), app_buf0.len())
1049                        } else {
1050                            (app_buf1.ptr(), app_buf1.len())
1051                        };
1052                        // if the app_buffer is filled, perform callback
1053                        if perform_callback {
1054                            // actually schedule the callback
1055                            let len_chan = ((buf_len / 2) << 8) | (self.channel.get() & 0xFF);
1056                            let _ = kernel_data.schedule_upcall(
1057                                0,
1058                                (self.mode.get() as usize, len_chan, buf_ptr as usize),
1059                            );
1060
1061                            // if the mode is SingleBuffer, the operation is
1062                            // complete. Clean up state
1063                            if self.mode.get() == AdcMode::SingleBuffer {
1064                                self.active.set(false);
1065                                self.mode.set(AdcMode::NoMode);
1066                                app.app_buf_offset.set(0);
1067
1068                                // need to actually stop sampling
1069                                let _ = self.adc.stop_sampling();
1070
1071                                // reclaim buffers and store them
1072                                if let Ok((buf1, buf2)) = self.adc.retrieve_buffers() {
1073                                    buf1.map(|buf| {
1074                                        self.replace_buffer(buf);
1075                                    });
1076                                    buf2.map(|buf| {
1077                                        self.replace_buffer(buf);
1078                                    });
1079                                }
1080                            } else {
1081                                // if the mode is ContinuousBuffer, we've just
1082                                // switched app buffers. Reset our offset to zero
1083                                app.app_buf_offset.set(0);
1084                            }
1085                        }
1086                    })
1087                    .map_err(|err| {
1088                        if err == kernel::process::Error::NoSuchApp
1089                            || err == kernel::process::Error::InactiveApp
1090                        {
1091                            self.processid.clear();
1092                            unexpected_state = true;
1093                        }
1094                    })
1095            });
1096        } else {
1097            unexpected_state = true;
1098        }
1099
1100        if unexpected_state {
1101            // Operation was likely canceled, or the app crashed. Make sure
1102            // state is consistent. No callback.
1103            self.active.set(false);
1104            self.mode.set(AdcMode::NoMode);
1105            self.processid.map(|id| {
1106                self.apps
1107                    .enter(id, |app, _| {
1108                        app.app_buf_offset.set(0);
1109                    })
1110                    .map_err(|err| {
1111                        if err == kernel::process::Error::NoSuchApp
1112                            || err == kernel::process::Error::InactiveApp
1113                        {
1114                            self.processid.clear();
1115                        }
1116                    })
1117            });
1118
1119            // Make sure we do not take more samples since we know no app
1120            // is currently waiting on samples.
1121            let _ = self.adc.stop_sampling();
1122
1123            // Also retrieve any buffers we passed to the underlying ADC driver.
1124            if let Ok((buf1, buf2)) = self.adc.retrieve_buffers() {
1125                buf1.map(|buf| {
1126                    self.replace_buffer(buf);
1127                });
1128                buf2.map(|buf| {
1129                    self.replace_buffer(buf);
1130                });
1131            }
1132        }
1133    }
1134}
1135
1136/// Implementations of application syscalls
1137impl<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> SyscallDriver for AdcDedicated<'a, A> {
1138    /// Method for the application to command or query this driver.
1139    ///
1140    /// - `command_num` - which command call this is
1141    /// - `data` - value sent by the application, varying uses
1142    /// - `_processid` - application identifier, unused
1143    fn command(
1144        &self,
1145        command_num: usize,
1146        channel: usize,
1147        frequency: usize,
1148        processid: ProcessId,
1149    ) -> CommandReturn {
1150        // Return true if this app already owns the ADC capsule, if no app owns
1151        // the ADC capsule, or if the app that is marked as owning the ADC
1152        // capsule no longer exists.
1153        let match_or_empty_or_nonexistant = self.processid.map_or(true, |owning_app| {
1154            // We have recorded that an app has ownership of the ADC.
1155
1156            // If the ADC is still active, then we need to wait for the operation
1157            // to finish and the app, whether it exists or not (it may have crashed),
1158            // still owns this capsule. If the ADC is not active, then
1159            // we need to verify that that application still exists, and remove
1160            // it as owner if not.
1161            if self.active.get() {
1162                owning_app == processid
1163            } else {
1164                // Check the app still exists.
1165                //
1166                // If the `.enter()` succeeds, then the app is still valid, and
1167                // we can check if the owning app matches the one that called
1168                // the command. If the `.enter()` fails, then the owning app no
1169                // longer exists and we return `true` to signify the
1170                // "or_nonexistant" case.
1171                self.apps
1172                    .enter(owning_app, |_, _| owning_app == processid)
1173                    .unwrap_or(true)
1174            }
1175        });
1176        if match_or_empty_or_nonexistant {
1177            self.processid.set(processid);
1178        } else {
1179            return CommandReturn::failure(ErrorCode::NOMEM);
1180        }
1181        match command_num {
1182            // Driver existence check
1183            // TODO(Tock 3.0): TRD104 specifies that Command 0 should return Success, not SuccessU32,
1184            // but this driver is unchanged since it has been stabilized. It will be brought into
1185            // compliance as part of the next major release of Tock. See #3375.
1186            0 => CommandReturn::success_u32(self.channels.len() as u32),
1187
1188            // Single sample on channel
1189            1 => match self.sample(channel) {
1190                Ok(()) => CommandReturn::success(),
1191                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1192                    err
1193                } else {
1194                    panic!("ADC: invalid return code")
1195                }),
1196            },
1197
1198            // Repeated single samples on a channel
1199            2 => match self.sample_continuous(channel, frequency as u32) {
1200                Ok(()) => CommandReturn::success(),
1201                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1202                    err
1203                } else {
1204                    panic!("ADC: invalid return code")
1205                }),
1206            },
1207
1208            // Multiple sample on a channel
1209            3 => match self.sample_buffer(channel, frequency as u32) {
1210                Ok(()) => CommandReturn::success(),
1211                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1212                    err
1213                } else {
1214                    panic!("ADC: invalid return code")
1215                }),
1216            },
1217
1218            // Continuous buffered sampling on a channel
1219            4 => match self.sample_buffer_continuous(channel, frequency as u32) {
1220                Ok(()) => CommandReturn::success(),
1221                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1222                    err
1223                } else {
1224                    panic!("ADC: invalid return code")
1225                }),
1226            },
1227
1228            // Stop sampling
1229            5 => match self.stop_sampling() {
1230                Ok(()) => CommandReturn::success(),
1231                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1232                    err
1233                } else {
1234                    panic!("ADC: invalid return code")
1235                }),
1236            },
1237
1238            // Get resolution bits
1239            101 => CommandReturn::success_u32(self.get_resolution_bits() as u32),
1240            // Get voltage reference mV
1241            102 => {
1242                if let Some(voltage) = self.get_voltage_reference_mv() {
1243                    CommandReturn::success_u32(voltage as u32)
1244                } else {
1245                    CommandReturn::failure(ErrorCode::NOSUPPORT)
1246                }
1247            }
1248
1249            // default
1250            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
1251        }
1252    }
1253
1254    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
1255        self.apps.enter(processid, |_, _| {})
1256    }
1257}
1258
1259/// Implementation of the syscalls for the virtualized ADC.
1260impl SyscallDriver for AdcVirtualized<'_> {
1261    /// Method for the application to command or query this driver.
1262    ///
1263    /// - `command_num` - which command call this is
1264    /// - `channel` - requested channel value
1265    /// - `_` - value sent by the application, unused
1266    /// - `processid` - application identifier
1267    fn command(
1268        &self,
1269        command_num: usize,
1270        channel: usize,
1271        _: usize,
1272        processid: ProcessId,
1273    ) -> CommandReturn {
1274        match command_num {
1275            // This driver exists and return the number of channels
1276            0 => CommandReturn::success_u32(self.drivers.len() as u32),
1277
1278            // Single sample.
1279            1 => {
1280                let res = self.enqueue_command(Operation::OneSample, channel, processid);
1281                if res == Ok(()) {
1282                    CommandReturn::success()
1283                } else {
1284                    match ErrorCode::try_from(res) {
1285                        Ok(error) => CommandReturn::failure(error),
1286                        _ => panic!("ADC Syscall: invalid error from enqueue_command"),
1287                    }
1288                }
1289            }
1290
1291            // Get resolution bits
1292            101 => {
1293                if channel < self.drivers.len() {
1294                    CommandReturn::success_u32(self.drivers[channel].get_resolution_bits() as u32)
1295                } else {
1296                    CommandReturn::failure(ErrorCode::NODEVICE)
1297                }
1298            }
1299
1300            // Get voltage reference mV
1301            102 => {
1302                if channel < self.drivers.len() {
1303                    if let Some(voltage) = self.drivers[channel].get_voltage_reference_mv() {
1304                        CommandReturn::success_u32(voltage as u32)
1305                    } else {
1306                        CommandReturn::failure(ErrorCode::NOSUPPORT)
1307                    }
1308                } else {
1309                    CommandReturn::failure(ErrorCode::NODEVICE)
1310                }
1311            }
1312
1313            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
1314        }
1315    }
1316
1317    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
1318        self.apps.enter(processid, |_, _| {})
1319    }
1320}
1321
1322impl hil::adc::Client for AdcVirtualized<'_> {
1323    fn sample_ready(&self, sample: u16) {
1324        self.current_process.take().map(|processid| {
1325            let _ = self.apps.enter(processid, |app, upcalls| {
1326                app.pending_command = false;
1327                let channel = app.channel;
1328                let _ = upcalls.schedule_upcall(
1329                    0,
1330                    (AdcMode::SingleSample as usize, channel, sample as usize),
1331                );
1332            });
1333        });
1334        self.run_next_command();
1335    }
1336}