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}