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(|b| b.len())
345                        .unwrap_or(0);
346                    app_buf_length > 0
347                })
348                .map_err(|err| {
349                    if err == kernel::process::Error::NoSuchApp
350                        || err == kernel::process::Error::InactiveApp
351                    {
352                        self.processid.clear();
353                    }
354                })
355                .unwrap_or(false)
356        });
357        if !exists {
358            return Err(ErrorCode::NOMEM);
359        }
360
361        // save state for callback
362        self.active.set(true);
363        self.mode.set(AdcMode::SingleBuffer);
364        let ret = self.processid.map_or(Err(ErrorCode::NOMEM), |id| {
365            self.apps
366                .enter(id, |app, _| {
367                    app.app_buf_offset.set(0);
368                    self.channel.set(channel);
369                    // start a continuous sample
370                    let res = self.adc_buf1.take().map_or(Err(ErrorCode::BUSY), |buf1| {
371                        self.adc_buf2
372                            .take()
373                            .map_or(Err(ErrorCode::BUSY), move |buf2| {
374                                // determine request length
375                                let request_len = app_buf_length / 2;
376                                let len1;
377                                let len2;
378                                if request_len <= buf1.len() {
379                                    len1 = app_buf_length / 2;
380                                    len2 = 0;
381                                } else if request_len <= (buf1.len() + buf2.len()) {
382                                    len1 = buf1.len();
383                                    len2 = request_len - buf1.len();
384                                } else {
385                                    len1 = buf1.len();
386                                    len2 = buf2.len();
387                                }
388
389                                // begin sampling
390                                app.using_app_buf0.set(true);
391                                app.samples_remaining.set(request_len - len1 - len2);
392                                app.samples_outstanding.set(len1 + len2);
393                                self.adc
394                                    .sample_highspeed(chan, frequency, buf1, len1, buf2, len2)
395                                    .map_or_else(
396                                        |(ecode, buf1, buf2)| {
397                                            // store buffers again
398                                            self.replace_buffer(buf1);
399                                            self.replace_buffer(buf2);
400                                            Err(ecode)
401                                        },
402                                        |()| Ok(()),
403                                    )
404                            })
405                    });
406                    res
407                })
408                .map_err(|err| {
409                    if err == kernel::process::Error::NoSuchApp
410                        || err == kernel::process::Error::InactiveApp
411                    {
412                        self.processid.clear();
413                    }
414                })
415                .unwrap_or(Err(ErrorCode::NOMEM))
416        });
417        if ret != Ok(()) {
418            // failure, clear state
419            self.active.set(false);
420            self.mode.set(AdcMode::NoMode);
421            self.processid.map(|id| {
422                self.apps
423                    .enter(id, |app, _| {
424                        app.samples_remaining.set(0);
425                        app.samples_outstanding.set(0);
426                    })
427                    .map_err(|err| {
428                        if err == kernel::process::Error::NoSuchApp
429                            || err == kernel::process::Error::InactiveApp
430                        {
431                            self.processid.clear();
432                        }
433                    })
434            });
435        }
436        ret
437    }
438
439    /// Collect analog samples continuously.
440    ///
441    /// Fills one "allowed" application buffer at a time and then swaps to
442    /// filling the second buffer. Upcalls occur when the in use "allowed"
443    /// buffer fills.
444    ///
445    /// - `channel` - index into `channels` array, which channel to sample
446    /// - `frequency` - number of samples per second to collect
447    fn sample_buffer_continuous(&self, channel: usize, frequency: u32) -> Result<(), ErrorCode> {
448        // only one sample at a time
449        if self.active.get() {
450            return Err(ErrorCode::BUSY);
451        }
452
453        // convert channel index
454        if channel >= self.channels.len() {
455            return Err(ErrorCode::INVAL);
456        }
457        let chan = &self.channels[channel];
458
459        // cannot continuously sample without two buffers
460        let mut app_buf_length = 0;
461        let mut next_app_buf_length = 0;
462        let exists = self.processid.map_or(false, |id| {
463            self.apps
464                .enter(id, |_, kernel_data| {
465                    app_buf_length = kernel_data
466                        .get_readwrite_processbuffer(0)
467                        .map(|b| b.len())
468                        .unwrap_or(0);
469                    next_app_buf_length = kernel_data
470                        .get_readwrite_processbuffer(1)
471                        .map(|b| b.len())
472                        .unwrap_or(0);
473                    app_buf_length > 0 && next_app_buf_length > 0
474                })
475                .map_err(|err| {
476                    if err == kernel::process::Error::NoSuchApp
477                        || err == kernel::process::Error::InactiveApp
478                    {
479                        self.processid.clear();
480                    }
481                })
482                .unwrap_or(false)
483        });
484        if !exists {
485            return Err(ErrorCode::NOMEM);
486        }
487
488        // save state for callback
489        self.active.set(true);
490        self.mode.set(AdcMode::ContinuousBuffer);
491
492        let ret = self.processid.map_or(Err(ErrorCode::NOMEM), |id| {
493            self.apps
494                .enter(id, |app, _| {
495                    app.app_buf_offset.set(0);
496                    self.channel.set(channel);
497                    // start a continuous sample
498                    self.adc_buf1.take().map_or(Err(ErrorCode::BUSY), |buf1| {
499                        self.adc_buf2
500                            .take()
501                            .map_or(Err(ErrorCode::BUSY), move |buf2| {
502                                // determine request lengths
503                                let samples_needed = app_buf_length / 2;
504                                let next_samples_needed = next_app_buf_length / 2;
505
506                                // determine request lengths
507                                let len1;
508                                let len2;
509                                if samples_needed <= buf1.len() {
510                                    // we can fit the entire app_buffer request in the first
511                                    // buffer. The second buffer will be used for the next
512                                    // app_buffer
513                                    len1 = samples_needed;
514                                    len2 = cmp::min(next_samples_needed, buf2.len());
515                                    app.samples_remaining.set(0);
516                                    app.samples_outstanding.set(len1);
517                                } else if samples_needed <= (buf1.len() + buf2.len()) {
518                                    // we can fit the entire app_buffer request between the two
519                                    // buffers
520                                    len1 = buf1.len();
521                                    len2 = samples_needed - buf1.len();
522                                    app.samples_remaining.set(0);
523                                    app.samples_outstanding.set(len1 + len2);
524                                } else {
525                                    // the app_buffer is larger than both buffers, so just
526                                    // request max lengths
527                                    len1 = buf1.len();
528                                    len2 = buf2.len();
529                                    app.samples_remaining.set(samples_needed - len1 - len2);
530                                    app.samples_outstanding.set(len1 + len2);
531                                }
532
533                                // begin sampling
534                                app.using_app_buf0.set(true);
535                                self.adc
536                                    .sample_highspeed(chan, frequency, buf1, len1, buf2, len2)
537                                    .map_or_else(
538                                        |(ecode, buf1, buf2)| {
539                                            // store buffers again
540                                            self.replace_buffer(buf1);
541                                            self.replace_buffer(buf2);
542                                            Err(ecode)
543                                        },
544                                        |()| Ok(()),
545                                    )
546                            })
547                    })
548                })
549                .map_err(|err| {
550                    if err == kernel::process::Error::NoSuchApp
551                        || err == kernel::process::Error::InactiveApp
552                    {
553                        self.processid.clear();
554                    }
555                })
556                .unwrap_or(Err(ErrorCode::NOMEM))
557        });
558        if ret != Ok(()) {
559            // failure, clear state
560            self.active.set(false);
561            self.mode.set(AdcMode::NoMode);
562            self.processid.map(|id| {
563                self.apps
564                    .enter(id, |app, _| {
565                        app.samples_remaining.set(0);
566                        app.samples_outstanding.set(0);
567                    })
568                    .map_err(|err| {
569                        if err == kernel::process::Error::NoSuchApp
570                            || err == kernel::process::Error::InactiveApp
571                        {
572                            self.processid.clear();
573                        }
574                    })
575            });
576        }
577        ret
578    }
579
580    /// Stops sampling the ADC.
581    ///
582    /// Any active operation by the ADC is canceled. No additional callbacks
583    /// will occur. Also retrieves buffers from the ADC (if any).
584    fn stop_sampling(&self) -> Result<(), ErrorCode> {
585        if !self.active.get() || self.mode.get() == AdcMode::NoMode {
586            // already inactive!
587            return Ok(());
588        }
589
590        // clean up state
591        self.processid.map_or(Err(ErrorCode::FAIL), |id| {
592            self.apps
593                .enter(id, |app, _| {
594                    self.active.set(false);
595                    self.mode.set(AdcMode::NoMode);
596                    app.app_buf_offset.set(0);
597
598                    // actually cancel the operation
599                    let rc = self.adc.stop_sampling();
600                    if rc != Ok(()) {
601                        return rc;
602                    }
603
604                    // reclaim buffers
605                    match self.adc.retrieve_buffers() {
606                        Ok((buf1, buf2)) => {
607                            buf1.map(|buf| {
608                                self.replace_buffer(buf);
609                            });
610                            buf2.map(|buf| {
611                                self.replace_buffer(buf);
612                            });
613                            Ok(())
614                        }
615                        Err(ecode) => Err(ecode),
616                    }
617                })
618                .map_err(|err| {
619                    if err == kernel::process::Error::NoSuchApp
620                        || err == kernel::process::Error::InactiveApp
621                    {
622                        self.processid.clear();
623                    }
624                })
625                .unwrap_or(Err(ErrorCode::FAIL))
626        })
627    }
628
629    fn get_resolution_bits(&self) -> usize {
630        self.adc.get_resolution_bits()
631    }
632
633    fn get_voltage_reference_mv(&self) -> Option<usize> {
634        self.adc.get_voltage_reference_mv()
635    }
636}
637
638/// Functions to create, initialize, and interact with the virtualized ADC
639impl<'a> AdcVirtualized<'a> {
640    /// Create a new `Adc` application interface.
641    ///
642    /// - `drivers` - Virtual ADC drivers to provide application access to
643    pub fn new(
644        drivers: &'a [&'a dyn hil::adc::AdcChannel<'a>],
645        grant: Grant<AppSys, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<0>>,
646    ) -> AdcVirtualized<'a> {
647        AdcVirtualized {
648            drivers,
649            apps: grant,
650            current_process: OptionalCell::empty(),
651        }
652    }
653
654    /// Enqueue the command to be executed when the ADC is available.
655    fn enqueue_command(
656        &self,
657        command: Operation,
658        channel: usize,
659        processid: ProcessId,
660    ) -> Result<(), ErrorCode> {
661        if channel < self.drivers.len() {
662            if self.current_process.is_none() {
663                self.current_process.set(processid);
664                let r = self.call_driver(command, channel);
665                if r != Ok(()) {
666                    self.current_process.clear();
667                }
668                self.run_next_command();
669                Ok(())
670            } else {
671                match self
672                    .apps
673                    .enter(processid, |app, _| {
674                        if app.pending_command {
675                            Err(ErrorCode::BUSY)
676                        } else {
677                            app.pending_command = true;
678                            app.command.set(command);
679                            app.channel = channel;
680                            Ok(())
681                        }
682                    })
683                    .map_err(ErrorCode::from)
684                {
685                    Err(e) => Err(e),
686                    Ok(_) => Ok(()),
687                }
688            }
689        } else {
690            Err(ErrorCode::NODEVICE)
691        }
692    }
693
694    /// Run next command in queue, when available
695    fn run_next_command(&self) {
696        let mut command = Operation::OneSample;
697        let mut channel = 0;
698        for app in self.apps.iter() {
699            let processid = app.processid();
700            let start_command = app.enter(|app, _| {
701                if app.pending_command {
702                    app.pending_command = false;
703                    app.command.take().map(|c| {
704                        command = c;
705                    });
706                    channel = app.channel;
707                    self.current_process.set(processid);
708                    true
709                } else {
710                    false
711                }
712            });
713            if start_command {
714                match self.call_driver(command, channel) {
715                    Err(_) => {
716                        self.current_process.clear();
717                    }
718                    Ok(()) => {
719                        break;
720                    }
721                }
722            }
723        }
724    }
725
726    /// Request the sample from the specified channel
727    fn call_driver(&self, command: Operation, channel: usize) -> Result<(), ErrorCode> {
728        match command {
729            Operation::OneSample => self.drivers[channel].sample(),
730        }
731    }
732}
733
734/// Callbacks from the ADC driver
735impl<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> hil::adc::Client
736    for AdcDedicated<'a, A>
737{
738    /// Single sample operation complete.
739    ///
740    /// Collects the sample and provides a callback to the application.
741    ///
742    /// - `sample` - analog sample value
743    fn sample_ready(&self, sample: u16) {
744        let mut calledback = false;
745        if self.active.get() && self.mode.get() == AdcMode::SingleSample {
746            // single sample complete, clean up state
747            self.active.set(false);
748            self.mode.set(AdcMode::NoMode);
749
750            // perform callback
751
752            self.processid.map(|id| {
753                self.apps
754                    .enter(id, |_app, upcalls| {
755                        calledback = true;
756                        upcalls
757                            .schedule_upcall(
758                                0,
759                                (
760                                    AdcMode::SingleSample as usize,
761                                    self.channel.get(),
762                                    sample as usize,
763                                ),
764                            )
765                            .ok();
766                    })
767                    .map_err(|err| {
768                        if err == kernel::process::Error::NoSuchApp
769                            || err == kernel::process::Error::InactiveApp
770                        {
771                            self.processid.clear();
772                        }
773                    })
774            });
775        } else if self.active.get() && self.mode.get() == AdcMode::ContinuousSample {
776            // sample ready in continuous sampling operation, keep state
777
778            // perform callback
779            self.processid.map(|id| {
780                self.apps
781                    .enter(id, |_app, upcalls| {
782                        calledback = true;
783                        upcalls
784                            .schedule_upcall(
785                                0,
786                                (
787                                    AdcMode::ContinuousSample as usize,
788                                    self.channel.get(),
789                                    sample as usize,
790                                ),
791                            )
792                            .ok();
793                    })
794                    .map_err(|err| {
795                        if err == kernel::process::Error::NoSuchApp
796                            || err == kernel::process::Error::InactiveApp
797                        {
798                            self.processid.clear();
799                        }
800                    })
801            });
802        }
803        if !calledback {
804            // operation probably canceled. Make sure state is consistent. No
805            // callback
806            self.active.set(false);
807            self.mode.set(AdcMode::NoMode);
808
809            // Also make sure that no more samples are taken if we were in
810            // continuous mode.
811            let _ = self.adc.stop_sampling();
812        }
813    }
814}
815
816/// Callbacks from the High Speed ADC driver
817impl<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> hil::adc::HighSpeedClient
818    for AdcDedicated<'a, A>
819{
820    /// Internal buffer has filled from a buffered sampling operation.
821    /// Copies data over to application buffer, determines if more data is
822    /// needed, and performs a callback to the application if ready. If
823    /// continuously sampling, also swaps application buffers and continues
824    /// sampling when necessary. If only filling a single buffer, stops
825    /// sampling operation when the application buffer is full.
826    ///
827    /// - `buf` - internal buffer filled with analog samples
828    /// - `length` - number of valid samples in the buffer, guaranteed to be
829    ///   less than or equal to buffer length
830    fn samples_ready(&self, buf: &'static mut [u16], length: usize) {
831        let mut unexpected_state = false;
832
833        // Make sure in all cases we regain ownership of the buffer. However,
834        // we also get a reference back to it so we can copy the sampled values
835        // out and to an application.
836        let buffer_with_samples = self.replace_buffer(buf);
837
838        // do we expect a buffer?
839        if self.active.get()
840            && (self.mode.get() == AdcMode::SingleBuffer
841                || self.mode.get() == AdcMode::ContinuousBuffer)
842        {
843            // we did expect a buffer. Determine the current application state
844            self.processid.map(|id| {
845                self.apps
846                    .enter(id, |app, kernel_data| {
847                        // Get both buffers, this shouldn't ever fail since the grant was created
848                        // with enough space. The buffer still may be empty though
849                        let app_buf0 = match kernel_data.get_readwrite_processbuffer(0) {
850                            Ok(buf) => buf,
851                            Err(_) => return,
852                        };
853                        let app_buf1 = match kernel_data.get_readwrite_processbuffer(1) {
854                            Ok(buf) => buf,
855                            Err(_) => return,
856                        };
857                        // determine which app buffer to copy data into and which is
858                        // next up if we're in continuous mode
859                        let use0 = app.using_app_buf0.get();
860                        let next_app_buf;
861                        let app_buf_ref;
862                        if use0 {
863                            app_buf_ref = &app_buf0;
864                            next_app_buf = &app_buf1;
865                        } else {
866                            app_buf_ref = &app_buf1;
867                            next_app_buf = &app_buf0;
868                        }
869
870                        // update count of outstanding sample requests
871                        app.samples_outstanding
872                            .set(app.samples_outstanding.get() - length);
873
874                        // provide a new buffer and length request to the ADC if
875                        // necessary. If we haven't received enough samples for the
876                        // current app_buffer, we may need to place more requests. If we
877                        // have received enough, but are in continuous mode, we should
878                        // place a request for the next app_buffer. This is all
879                        // unfortunately made more complicated by the fact that there is
880                        // always one outstanding request to the ADC.
881                        let perform_callback;
882                        if app.samples_remaining.get() == 0 {
883                            // we have already placed outstanding requests for all the
884                            // samples needed to fill the current app_buffer
885
886                            if app.samples_outstanding.get() == 0 {
887                                // and the samples we just received are the last ones
888                                // we need
889                                perform_callback = true;
890
891                                if self.mode.get() == AdcMode::ContinuousBuffer {
892                                    // it's time to switch to the next app_buffer, but
893                                    // there's already an outstanding request to the ADC
894                                    // for the next app_buffer that was placed last
895                                    // time, so we need to account for that
896                                    let samples_needed =
897                                        next_app_buf.enter(|buf| buf.len() / 2).unwrap_or(0);
898                                    app.samples_remaining
899                                        .set(samples_needed - app.next_samples_outstanding.get());
900                                    app.samples_outstanding
901                                        .set(app.next_samples_outstanding.get());
902                                    app.using_app_buf0.set(!app.using_app_buf0.get());
903
904                                    // we also need to place our next request, however
905                                    // the outstanding request already placed for the
906                                    // next app_buffer might have completed it! So we
907                                    // have to account for that case
908                                    if app.samples_remaining.get() == 0 {
909                                        // oh boy. We actually need to place a request
910                                        // for the next next app_buffer (which is
911                                        // actually the current app_buf, but try not to
912                                        // think about that...). In practice, this
913                                        // should be a pretty uncommon case to hit, only
914                                        // occurring if the length of the app buffers
915                                        // are smaller than the length of the adc
916                                        // buffers, which is unsustainable at high
917                                        // sampling frequencies
918                                        let next_next_app_buf = &app_buf_ref;
919
920                                        // provide a new buffer. However, we cannot
921                                        // currently update state since the next
922                                        // app_buffer still has a request outstanding.
923                                        // We'll just make a request and handle the
924                                        // state updating on next callback
925                                        self.take_and_map_buffer(|adc_buf| {
926                                            let samples_needed = next_next_app_buf
927                                                .enter(|buf| buf.len() / 2)
928                                                .unwrap_or(0);
929                                            let request_len =
930                                                cmp::min(samples_needed, adc_buf.len());
931                                            app.next_samples_outstanding.set(request_len);
932                                            let _ = self
933                                                .adc
934                                                .provide_buffer(adc_buf, request_len)
935                                                .map_err(|(_, buf)| {
936                                                    self.replace_buffer(buf);
937                                                });
938                                        });
939                                    } else {
940                                        // okay, we still need more samples for the next
941                                        // app_buffer
942
943                                        // provide a new buffer and update state
944                                        self.take_and_map_buffer(|adc_buf| {
945                                            let request_len = cmp::min(
946                                                app.samples_remaining.get(),
947                                                adc_buf.len(),
948                                            );
949                                            app.samples_remaining
950                                                .set(app.samples_remaining.get() - request_len);
951                                            app.samples_outstanding
952                                                .set(app.samples_outstanding.get() + request_len);
953                                            let _ = self
954                                                .adc
955                                                .provide_buffer(adc_buf, request_len)
956                                                .map_err(|(_, buf)| {
957                                                    self.replace_buffer(buf);
958                                                });
959                                        });
960                                    }
961                                }
962                            } else {
963                                // but there are still outstanding samples for the
964                                // current app_buffer (actually exactly one request, the
965                                // one the ADC is currently acting on)
966                                perform_callback = false;
967
968                                if self.mode.get() == AdcMode::ContinuousBuffer {
969                                    // we're in continuous mode, so we need to start the
970                                    // first request for the next app_buffer
971
972                                    // provide a new buffer. However, we cannot
973                                    // currently update state since the current
974                                    // app_buffer still has a request outstanding. We'll
975                                    // just make a request and handle the state updating
976                                    // on next callback
977                                    self.take_and_map_buffer(|adc_buf| {
978                                        let samples_needed =
979                                            next_app_buf.enter(|buf| buf.len() / 2).unwrap_or(0);
980                                        let request_len = cmp::min(samples_needed, adc_buf.len());
981                                        app.next_samples_outstanding.set(request_len);
982                                        let _ = self
983                                            .adc
984                                            .provide_buffer(adc_buf, request_len)
985                                            .map_err(|(_, buf)| {
986                                                self.replace_buffer(buf);
987                                            });
988                                    });
989                                }
990                            }
991                        } else {
992                            // we need to get more samples for the current app_buffer
993                            perform_callback = false;
994
995                            // provide a new buffer and update state
996                            self.take_and_map_buffer(|adc_buf| {
997                                let request_len =
998                                    cmp::min(app.samples_remaining.get(), adc_buf.len());
999                                app.samples_remaining
1000                                    .set(app.samples_remaining.get() - request_len);
1001                                app.samples_outstanding
1002                                    .set(app.samples_outstanding.get() + request_len);
1003                                let _ = self.adc.provide_buffer(adc_buf, request_len).map_err(
1004                                    |(_, buf)| {
1005                                        self.replace_buffer(buf);
1006                                    },
1007                                );
1008                            });
1009                        }
1010
1011                        let skip_amt = app.app_buf_offset.get() / 2;
1012
1013                        {
1014                            let app_buf = if use0 { &app_buf0 } else { &app_buf1 };
1015
1016                            // next we should copy bytes to the app buffer
1017                            let _ = app_buf.mut_enter(|app_buf| {
1018                                // Copy bytes to app buffer by iterating over the
1019                                // data.
1020                                buffer_with_samples.map(|adc_buf| {
1021                                    // The `for` commands:
1022                                    //  * `chunks_mut`: get sets of two bytes from the app
1023                                    //                  buffer
1024                                    //  * `skip`: skips the already written bytes from the
1025                                    //            app buffer
1026                                    //  * `zip`: ties that iterator to an iterator on the
1027                                    //           adc buffer, limiting iteration length to
1028                                    //           the minimum of each of their lengths
1029                                    //  * `take`: limits us to the minimum of buffer lengths
1030                                    //            or sample length
1031                                    // We then split each sample into its two bytes and copy
1032                                    // them to the app buffer
1033                                    for (chunk, &sample) in app_buf
1034                                        .chunks(2)
1035                                        .skip(skip_amt)
1036                                        .zip(adc_buf.iter())
1037                                        .take(length)
1038                                    {
1039                                        let mut val = sample;
1040                                        for byte in chunk.iter() {
1041                                            byte.set((val & 0xFF) as u8);
1042                                            val >>= 8;
1043                                        }
1044                                    }
1045                                });
1046                            });
1047                        }
1048                        // update our byte offset based on how many samples we
1049                        // copied
1050                        app.app_buf_offset
1051                            .set(app.app_buf_offset.get() + length * 2);
1052
1053                        // let in_use_buf;
1054                        let (buf_ptr, buf_len) = if use0 {
1055                            (app_buf0.ptr(), app_buf0.len())
1056                        } else {
1057                            (app_buf1.ptr(), app_buf1.len())
1058                        };
1059                        // if the app_buffer is filled, perform callback
1060                        if perform_callback {
1061                            // actually schedule the callback
1062                            let len_chan = ((buf_len / 2) << 8) | (self.channel.get() & 0xFF);
1063                            kernel_data
1064                                .schedule_upcall(
1065                                    0,
1066                                    (self.mode.get() as usize, len_chan, buf_ptr as usize),
1067                                )
1068                                .ok();
1069
1070                            // if the mode is SingleBuffer, the operation is
1071                            // complete. Clean up state
1072                            if self.mode.get() == AdcMode::SingleBuffer {
1073                                self.active.set(false);
1074                                self.mode.set(AdcMode::NoMode);
1075                                app.app_buf_offset.set(0);
1076
1077                                // need to actually stop sampling
1078                                let _ = self.adc.stop_sampling();
1079
1080                                // reclaim buffers and store them
1081                                if let Ok((buf1, buf2)) = self.adc.retrieve_buffers() {
1082                                    buf1.map(|buf| {
1083                                        self.replace_buffer(buf);
1084                                    });
1085                                    buf2.map(|buf| {
1086                                        self.replace_buffer(buf);
1087                                    });
1088                                }
1089                            } else {
1090                                // if the mode is ContinuousBuffer, we've just
1091                                // switched app buffers. Reset our offset to zero
1092                                app.app_buf_offset.set(0);
1093                            }
1094                        }
1095                    })
1096                    .map_err(|err| {
1097                        if err == kernel::process::Error::NoSuchApp
1098                            || err == kernel::process::Error::InactiveApp
1099                        {
1100                            self.processid.clear();
1101                            unexpected_state = true;
1102                        }
1103                    })
1104            });
1105        } else {
1106            unexpected_state = true;
1107        }
1108
1109        if unexpected_state {
1110            // Operation was likely canceled, or the app crashed. Make sure
1111            // state is consistent. No callback.
1112            self.active.set(false);
1113            self.mode.set(AdcMode::NoMode);
1114            self.processid.map(|id| {
1115                self.apps
1116                    .enter(id, |app, _| {
1117                        app.app_buf_offset.set(0);
1118                    })
1119                    .map_err(|err| {
1120                        if err == kernel::process::Error::NoSuchApp
1121                            || err == kernel::process::Error::InactiveApp
1122                        {
1123                            self.processid.clear();
1124                        }
1125                    })
1126            });
1127
1128            // Make sure we do not take more samples since we know no app
1129            // is currently waiting on samples.
1130            let _ = self.adc.stop_sampling();
1131
1132            // Also retrieve any buffers we passed to the underlying ADC driver.
1133            if let Ok((buf1, buf2)) = self.adc.retrieve_buffers() {
1134                buf1.map(|buf| {
1135                    self.replace_buffer(buf);
1136                });
1137                buf2.map(|buf| {
1138                    self.replace_buffer(buf);
1139                });
1140            }
1141        }
1142    }
1143}
1144
1145/// Implementations of application syscalls
1146impl<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> SyscallDriver for AdcDedicated<'a, A> {
1147    /// Method for the application to command or query this driver.
1148    ///
1149    /// - `command_num` - which command call this is
1150    /// - `data` - value sent by the application, varying uses
1151    /// - `_processid` - application identifier, unused
1152    fn command(
1153        &self,
1154        command_num: usize,
1155        channel: usize,
1156        frequency: usize,
1157        processid: ProcessId,
1158    ) -> CommandReturn {
1159        // Return true if this app already owns the ADC capsule, if no app owns
1160        // the ADC capsule, or if the app that is marked as owning the ADC
1161        // capsule no longer exists.
1162        let match_or_empty_or_nonexistant = self.processid.map_or(true, |owning_app| {
1163            // We have recorded that an app has ownership of the ADC.
1164
1165            // If the ADC is still active, then we need to wait for the operation
1166            // to finish and the app, whether it exists or not (it may have crashed),
1167            // still owns this capsule. If the ADC is not active, then
1168            // we need to verify that that application still exists, and remove
1169            // it as owner if not.
1170            if self.active.get() {
1171                owning_app == processid
1172            } else {
1173                // Check the app still exists.
1174                //
1175                // If the `.enter()` succeeds, then the app is still valid, and
1176                // we can check if the owning app matches the one that called
1177                // the command. If the `.enter()` fails, then the owning app no
1178                // longer exists and we return `true` to signify the
1179                // "or_nonexistant" case.
1180                self.apps
1181                    .enter(owning_app, |_, _| owning_app == processid)
1182                    .unwrap_or(true)
1183            }
1184        });
1185        if match_or_empty_or_nonexistant {
1186            self.processid.set(processid);
1187        } else {
1188            return CommandReturn::failure(ErrorCode::NOMEM);
1189        }
1190        match command_num {
1191            // Driver existence check
1192            // TODO(Tock 3.0): TRD104 specifies that Command 0 should return Success, not SuccessU32,
1193            // but this driver is unchanged since it has been stabilized. It will be brought into
1194            // compliance as part of the next major release of Tock. See #3375.
1195            0 => CommandReturn::success_u32(self.channels.len() as u32),
1196
1197            // Single sample on channel
1198            1 => match self.sample(channel) {
1199                Ok(()) => CommandReturn::success(),
1200                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1201                    err
1202                } else {
1203                    panic!("ADC: invalid return code")
1204                }),
1205            },
1206
1207            // Repeated single samples on a channel
1208            2 => match self.sample_continuous(channel, frequency as u32) {
1209                Ok(()) => CommandReturn::success(),
1210                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1211                    err
1212                } else {
1213                    panic!("ADC: invalid return code")
1214                }),
1215            },
1216
1217            // Multiple sample on a channel
1218            3 => match self.sample_buffer(channel, frequency as u32) {
1219                Ok(()) => CommandReturn::success(),
1220                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1221                    err
1222                } else {
1223                    panic!("ADC: invalid return code")
1224                }),
1225            },
1226
1227            // Continuous buffered sampling on a channel
1228            4 => match self.sample_buffer_continuous(channel, frequency as u32) {
1229                Ok(()) => CommandReturn::success(),
1230                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1231                    err
1232                } else {
1233                    panic!("ADC: invalid return code")
1234                }),
1235            },
1236
1237            // Stop sampling
1238            5 => match self.stop_sampling() {
1239                Ok(()) => CommandReturn::success(),
1240                e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1241                    err
1242                } else {
1243                    panic!("ADC: invalid return code")
1244                }),
1245            },
1246
1247            // Get resolution bits
1248            101 => CommandReturn::success_u32(self.get_resolution_bits() as u32),
1249            // Get voltage reference mV
1250            102 => {
1251                if let Some(voltage) = self.get_voltage_reference_mv() {
1252                    CommandReturn::success_u32(voltage as u32)
1253                } else {
1254                    CommandReturn::failure(ErrorCode::NOSUPPORT)
1255                }
1256            }
1257
1258            // default
1259            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
1260        }
1261    }
1262
1263    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
1264        self.apps.enter(processid, |_, _| {})
1265    }
1266}
1267
1268/// Implementation of the syscalls for the virtualized ADC.
1269impl SyscallDriver for AdcVirtualized<'_> {
1270    /// Method for the application to command or query this driver.
1271    ///
1272    /// - `command_num` - which command call this is
1273    /// - `channel` - requested channel value
1274    /// - `_` - value sent by the application, unused
1275    /// - `processid` - application identifier
1276    fn command(
1277        &self,
1278        command_num: usize,
1279        channel: usize,
1280        _: usize,
1281        processid: ProcessId,
1282    ) -> CommandReturn {
1283        match command_num {
1284            // This driver exists and return the number of channels
1285            0 => CommandReturn::success_u32(self.drivers.len() as u32),
1286
1287            // Single sample.
1288            1 => {
1289                let res = self.enqueue_command(Operation::OneSample, channel, processid);
1290                if res == Ok(()) {
1291                    CommandReturn::success()
1292                } else {
1293                    match ErrorCode::try_from(res) {
1294                        Ok(error) => CommandReturn::failure(error),
1295                        _ => panic!("ADC Syscall: invalid error from enqueue_command"),
1296                    }
1297                }
1298            }
1299
1300            // Get resolution bits
1301            101 => {
1302                if channel < self.drivers.len() {
1303                    CommandReturn::success_u32(self.drivers[channel].get_resolution_bits() as u32)
1304                } else {
1305                    CommandReturn::failure(ErrorCode::NODEVICE)
1306                }
1307            }
1308
1309            // Get voltage reference mV
1310            102 => {
1311                if channel < self.drivers.len() {
1312                    if let Some(voltage) = self.drivers[channel].get_voltage_reference_mv() {
1313                        CommandReturn::success_u32(voltage as u32)
1314                    } else {
1315                        CommandReturn::failure(ErrorCode::NOSUPPORT)
1316                    }
1317                } else {
1318                    CommandReturn::failure(ErrorCode::NODEVICE)
1319                }
1320            }
1321
1322            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
1323        }
1324    }
1325
1326    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
1327        self.apps.enter(processid, |_, _| {})
1328    }
1329}
1330
1331impl hil::adc::Client for AdcVirtualized<'_> {
1332    fn sample_ready(&self, sample: u16) {
1333        self.current_process.take().map(|processid| {
1334            let _ = self.apps.enter(processid, |app, upcalls| {
1335                app.pending_command = false;
1336                let channel = app.channel;
1337                upcalls
1338                    .schedule_upcall(
1339                        0,
1340                        (AdcMode::SingleSample as usize, channel, sample as usize),
1341                    )
1342                    .ok();
1343            });
1344        });
1345        self.run_next_command();
1346    }
1347}