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}