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 let _ = upcalls.schedule_upcall(
757 0,
758 (
759 AdcMode::SingleSample as usize,
760 self.channel.get(),
761 sample as usize,
762 ),
763 );
764 })
765 .map_err(|err| {
766 if err == kernel::process::Error::NoSuchApp
767 || err == kernel::process::Error::InactiveApp
768 {
769 self.processid.clear();
770 }
771 })
772 });
773 } else if self.active.get() && self.mode.get() == AdcMode::ContinuousSample {
774 // sample ready in continuous sampling operation, keep state
775
776 // perform callback
777 self.processid.map(|id| {
778 self.apps
779 .enter(id, |_app, upcalls| {
780 calledback = true;
781 let _ = upcalls.schedule_upcall(
782 0,
783 (
784 AdcMode::ContinuousSample as usize,
785 self.channel.get(),
786 sample as usize,
787 ),
788 );
789 })
790 .map_err(|err| {
791 if err == kernel::process::Error::NoSuchApp
792 || err == kernel::process::Error::InactiveApp
793 {
794 self.processid.clear();
795 }
796 })
797 });
798 }
799 if !calledback {
800 // operation probably canceled. Make sure state is consistent. No
801 // callback
802 self.active.set(false);
803 self.mode.set(AdcMode::NoMode);
804
805 // Also make sure that no more samples are taken if we were in
806 // continuous mode.
807 let _ = self.adc.stop_sampling();
808 }
809 }
810}
811
812/// Callbacks from the High Speed ADC driver
813impl<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> hil::adc::HighSpeedClient
814 for AdcDedicated<'a, A>
815{
816 /// Internal buffer has filled from a buffered sampling operation.
817 /// Copies data over to application buffer, determines if more data is
818 /// needed, and performs a callback to the application if ready. If
819 /// continuously sampling, also swaps application buffers and continues
820 /// sampling when necessary. If only filling a single buffer, stops
821 /// sampling operation when the application buffer is full.
822 ///
823 /// - `buf` - internal buffer filled with analog samples
824 /// - `length` - number of valid samples in the buffer, guaranteed to be
825 /// less than or equal to buffer length
826 fn samples_ready(&self, buf: &'static mut [u16], length: usize) {
827 let mut unexpected_state = false;
828
829 // Make sure in all cases we regain ownership of the buffer. However,
830 // we also get a reference back to it so we can copy the sampled values
831 // out and to an application.
832 let buffer_with_samples = self.replace_buffer(buf);
833
834 // do we expect a buffer?
835 if self.active.get()
836 && (self.mode.get() == AdcMode::SingleBuffer
837 || self.mode.get() == AdcMode::ContinuousBuffer)
838 {
839 // we did expect a buffer. Determine the current application state
840 self.processid.map(|id| {
841 self.apps
842 .enter(id, |app, kernel_data| {
843 // Get both buffers, this shouldn't ever fail since the grant was created
844 // with enough space. The buffer still may be empty though
845 let app_buf0 = match kernel_data.get_readwrite_processbuffer(0) {
846 Ok(buf) => buf,
847 Err(_) => return,
848 };
849 let app_buf1 = match kernel_data.get_readwrite_processbuffer(1) {
850 Ok(buf) => buf,
851 Err(_) => return,
852 };
853 // determine which app buffer to copy data into and which is
854 // next up if we're in continuous mode
855 let use0 = app.using_app_buf0.get();
856 let next_app_buf;
857 let app_buf_ref;
858 if use0 {
859 app_buf_ref = &app_buf0;
860 next_app_buf = &app_buf1;
861 } else {
862 app_buf_ref = &app_buf1;
863 next_app_buf = &app_buf0;
864 }
865
866 // update count of outstanding sample requests
867 app.samples_outstanding
868 .set(app.samples_outstanding.get() - length);
869
870 // provide a new buffer and length request to the ADC if
871 // necessary. If we haven't received enough samples for the
872 // current app_buffer, we may need to place more requests. If we
873 // have received enough, but are in continuous mode, we should
874 // place a request for the next app_buffer. This is all
875 // unfortunately made more complicated by the fact that there is
876 // always one outstanding request to the ADC.
877 let perform_callback;
878 if app.samples_remaining.get() == 0 {
879 // we have already placed outstanding requests for all the
880 // samples needed to fill the current app_buffer
881
882 if app.samples_outstanding.get() == 0 {
883 // and the samples we just received are the last ones
884 // we need
885 perform_callback = true;
886
887 if self.mode.get() == AdcMode::ContinuousBuffer {
888 // it's time to switch to the next app_buffer, but
889 // there's already an outstanding request to the ADC
890 // for the next app_buffer that was placed last
891 // time, so we need to account for that
892 let samples_needed =
893 next_app_buf.enter(|buf| buf.len() / 2).unwrap_or(0);
894 app.samples_remaining
895 .set(samples_needed - app.next_samples_outstanding.get());
896 app.samples_outstanding
897 .set(app.next_samples_outstanding.get());
898 app.using_app_buf0.set(!app.using_app_buf0.get());
899
900 // we also need to place our next request, however
901 // the outstanding request already placed for the
902 // next app_buffer might have completed it! So we
903 // have to account for that case
904 if app.samples_remaining.get() == 0 {
905 // oh boy. We actually need to place a request
906 // for the next next app_buffer (which is
907 // actually the current app_buf, but try not to
908 // think about that...). In practice, this
909 // should be a pretty uncommon case to hit, only
910 // occurring if the length of the app buffers
911 // are smaller than the length of the adc
912 // buffers, which is unsustainable at high
913 // sampling frequencies
914 let next_next_app_buf = &app_buf_ref;
915
916 // provide a new buffer. However, we cannot
917 // currently update state since the next
918 // app_buffer still has a request outstanding.
919 // We'll just make a request and handle the
920 // state updating on next callback
921 self.take_and_map_buffer(|adc_buf| {
922 let samples_needed = next_next_app_buf
923 .enter(|buf| buf.len() / 2)
924 .unwrap_or(0);
925 let request_len =
926 cmp::min(samples_needed, adc_buf.len());
927 app.next_samples_outstanding.set(request_len);
928 let _ = self
929 .adc
930 .provide_buffer(adc_buf, request_len)
931 .map_err(|(_, buf)| {
932 self.replace_buffer(buf);
933 });
934 });
935 } else {
936 // okay, we still need more samples for the next
937 // app_buffer
938
939 // provide a new buffer and update state
940 self.take_and_map_buffer(|adc_buf| {
941 let request_len = cmp::min(
942 app.samples_remaining.get(),
943 adc_buf.len(),
944 );
945 app.samples_remaining
946 .set(app.samples_remaining.get() - request_len);
947 app.samples_outstanding
948 .set(app.samples_outstanding.get() + request_len);
949 let _ = self
950 .adc
951 .provide_buffer(adc_buf, request_len)
952 .map_err(|(_, buf)| {
953 self.replace_buffer(buf);
954 });
955 });
956 }
957 }
958 } else {
959 // but there are still outstanding samples for the
960 // current app_buffer (actually exactly one request, the
961 // one the ADC is currently acting on)
962 perform_callback = false;
963
964 if self.mode.get() == AdcMode::ContinuousBuffer {
965 // we're in continuous mode, so we need to start the
966 // first request for the next app_buffer
967
968 // provide a new buffer. However, we cannot
969 // currently update state since the current
970 // app_buffer still has a request outstanding. We'll
971 // just make a request and handle the state updating
972 // on next callback
973 self.take_and_map_buffer(|adc_buf| {
974 let samples_needed =
975 next_app_buf.enter(|buf| buf.len() / 2).unwrap_or(0);
976 let request_len = cmp::min(samples_needed, adc_buf.len());
977 app.next_samples_outstanding.set(request_len);
978 let _ = self
979 .adc
980 .provide_buffer(adc_buf, request_len)
981 .map_err(|(_, buf)| {
982 self.replace_buffer(buf);
983 });
984 });
985 }
986 }
987 } else {
988 // we need to get more samples for the current app_buffer
989 perform_callback = false;
990
991 // provide a new buffer and update state
992 self.take_and_map_buffer(|adc_buf| {
993 let request_len =
994 cmp::min(app.samples_remaining.get(), adc_buf.len());
995 app.samples_remaining
996 .set(app.samples_remaining.get() - request_len);
997 app.samples_outstanding
998 .set(app.samples_outstanding.get() + request_len);
999 let _ = self.adc.provide_buffer(adc_buf, request_len).map_err(
1000 |(_, buf)| {
1001 self.replace_buffer(buf);
1002 },
1003 );
1004 });
1005 }
1006
1007 let skip_amt = app.app_buf_offset.get() / 2;
1008
1009 {
1010 let app_buf = if use0 { &app_buf0 } else { &app_buf1 };
1011
1012 // next we should copy bytes to the app buffer
1013 let _ = app_buf.mut_enter(|app_buf| {
1014 // Copy bytes to app buffer by iterating over the
1015 // data.
1016 buffer_with_samples.map(|adc_buf| {
1017 // The `for` commands:
1018 // * `chunks_mut`: get sets of two bytes from the app
1019 // buffer
1020 // * `skip`: skips the already written bytes from the
1021 // app buffer
1022 // * `zip`: ties that iterator to an iterator on the
1023 // adc buffer, limiting iteration length to
1024 // the minimum of each of their lengths
1025 // * `take`: limits us to the minimum of buffer lengths
1026 // or sample length
1027 // We then split each sample into its two bytes and copy
1028 // them to the app buffer
1029 for (chunk, &sample) in app_buf
1030 .chunks(2)
1031 .skip(skip_amt)
1032 .zip(adc_buf.iter())
1033 .take(length)
1034 {
1035 let mut val = sample;
1036 for byte in chunk.iter() {
1037 byte.set((val & 0xFF) as u8);
1038 val >>= 8;
1039 }
1040 }
1041 });
1042 });
1043 }
1044 // update our byte offset based on how many samples we
1045 // copied
1046 app.app_buf_offset
1047 .set(app.app_buf_offset.get() + length * 2);
1048
1049 // let in_use_buf;
1050 let (buf_ptr, buf_len) = if use0 {
1051 (app_buf0.ptr(), app_buf0.len())
1052 } else {
1053 (app_buf1.ptr(), app_buf1.len())
1054 };
1055 // if the app_buffer is filled, perform callback
1056 if perform_callback {
1057 // actually schedule the callback
1058 let len_chan = ((buf_len / 2) << 8) | (self.channel.get() & 0xFF);
1059 let _ = kernel_data.schedule_upcall(
1060 0,
1061 (self.mode.get() as usize, len_chan, buf_ptr as usize),
1062 );
1063
1064 // if the mode is SingleBuffer, the operation is
1065 // complete. Clean up state
1066 if self.mode.get() == AdcMode::SingleBuffer {
1067 self.active.set(false);
1068 self.mode.set(AdcMode::NoMode);
1069 app.app_buf_offset.set(0);
1070
1071 // need to actually stop sampling
1072 let _ = self.adc.stop_sampling();
1073
1074 // reclaim buffers and store them
1075 if let Ok((buf1, buf2)) = self.adc.retrieve_buffers() {
1076 buf1.map(|buf| {
1077 self.replace_buffer(buf);
1078 });
1079 buf2.map(|buf| {
1080 self.replace_buffer(buf);
1081 });
1082 }
1083 } else {
1084 // if the mode is ContinuousBuffer, we've just
1085 // switched app buffers. Reset our offset to zero
1086 app.app_buf_offset.set(0);
1087 }
1088 }
1089 })
1090 .map_err(|err| {
1091 if err == kernel::process::Error::NoSuchApp
1092 || err == kernel::process::Error::InactiveApp
1093 {
1094 self.processid.clear();
1095 unexpected_state = true;
1096 }
1097 })
1098 });
1099 } else {
1100 unexpected_state = true;
1101 }
1102
1103 if unexpected_state {
1104 // Operation was likely canceled, or the app crashed. Make sure
1105 // state is consistent. No callback.
1106 self.active.set(false);
1107 self.mode.set(AdcMode::NoMode);
1108 self.processid.map(|id| {
1109 self.apps
1110 .enter(id, |app, _| {
1111 app.app_buf_offset.set(0);
1112 })
1113 .map_err(|err| {
1114 if err == kernel::process::Error::NoSuchApp
1115 || err == kernel::process::Error::InactiveApp
1116 {
1117 self.processid.clear();
1118 }
1119 })
1120 });
1121
1122 // Make sure we do not take more samples since we know no app
1123 // is currently waiting on samples.
1124 let _ = self.adc.stop_sampling();
1125
1126 // Also retrieve any buffers we passed to the underlying ADC driver.
1127 if let Ok((buf1, buf2)) = self.adc.retrieve_buffers() {
1128 buf1.map(|buf| {
1129 self.replace_buffer(buf);
1130 });
1131 buf2.map(|buf| {
1132 self.replace_buffer(buf);
1133 });
1134 }
1135 }
1136 }
1137}
1138
1139/// Implementations of application syscalls
1140impl<'a, A: hil::adc::Adc<'a> + hil::adc::AdcHighSpeed<'a>> SyscallDriver for AdcDedicated<'a, A> {
1141 /// Method for the application to command or query this driver.
1142 ///
1143 /// - `command_num` - which command call this is
1144 /// - `data` - value sent by the application, varying uses
1145 /// - `_processid` - application identifier, unused
1146 fn command(
1147 &self,
1148 command_num: usize,
1149 channel: usize,
1150 frequency: usize,
1151 processid: ProcessId,
1152 ) -> CommandReturn {
1153 // Return true if this app already owns the ADC capsule, if no app owns
1154 // the ADC capsule, or if the app that is marked as owning the ADC
1155 // capsule no longer exists.
1156 let match_or_empty_or_nonexistant = self.processid.map_or(true, |owning_app| {
1157 // We have recorded that an app has ownership of the ADC.
1158
1159 // If the ADC is still active, then we need to wait for the operation
1160 // to finish and the app, whether it exists or not (it may have crashed),
1161 // still owns this capsule. If the ADC is not active, then
1162 // we need to verify that that application still exists, and remove
1163 // it as owner if not.
1164 if self.active.get() {
1165 owning_app == processid
1166 } else {
1167 // Check the app still exists.
1168 //
1169 // If the `.enter()` succeeds, then the app is still valid, and
1170 // we can check if the owning app matches the one that called
1171 // the command. If the `.enter()` fails, then the owning app no
1172 // longer exists and we return `true` to signify the
1173 // "or_nonexistant" case.
1174 self.apps
1175 .enter(owning_app, |_, _| owning_app == processid)
1176 .unwrap_or(true)
1177 }
1178 });
1179 if match_or_empty_or_nonexistant {
1180 self.processid.set(processid);
1181 } else {
1182 return CommandReturn::failure(ErrorCode::NOMEM);
1183 }
1184 match command_num {
1185 // Driver existence check
1186 // TODO(Tock 3.0): TRD104 specifies that Command 0 should return Success, not SuccessU32,
1187 // but this driver is unchanged since it has been stabilized. It will be brought into
1188 // compliance as part of the next major release of Tock. See #3375.
1189 0 => CommandReturn::success_u32(self.channels.len() as u32),
1190
1191 // Single sample on channel
1192 1 => match self.sample(channel) {
1193 Ok(()) => CommandReturn::success(),
1194 e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1195 err
1196 } else {
1197 panic!("ADC: invalid return code")
1198 }),
1199 },
1200
1201 // Repeated single samples on a channel
1202 2 => match self.sample_continuous(channel, frequency as u32) {
1203 Ok(()) => CommandReturn::success(),
1204 e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1205 err
1206 } else {
1207 panic!("ADC: invalid return code")
1208 }),
1209 },
1210
1211 // Multiple sample on a channel
1212 3 => match self.sample_buffer(channel, frequency as u32) {
1213 Ok(()) => CommandReturn::success(),
1214 e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1215 err
1216 } else {
1217 panic!("ADC: invalid return code")
1218 }),
1219 },
1220
1221 // Continuous buffered sampling on a channel
1222 4 => match self.sample_buffer_continuous(channel, frequency as u32) {
1223 Ok(()) => CommandReturn::success(),
1224 e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1225 err
1226 } else {
1227 panic!("ADC: invalid return code")
1228 }),
1229 },
1230
1231 // Stop sampling
1232 5 => match self.stop_sampling() {
1233 Ok(()) => CommandReturn::success(),
1234 e => CommandReturn::failure(if let Ok(err) = ErrorCode::try_from(e) {
1235 err
1236 } else {
1237 panic!("ADC: invalid return code")
1238 }),
1239 },
1240
1241 // Get resolution bits
1242 101 => CommandReturn::success_u32(self.get_resolution_bits() as u32),
1243 // Get voltage reference mV
1244 102 => {
1245 if let Some(voltage) = self.get_voltage_reference_mv() {
1246 CommandReturn::success_u32(voltage as u32)
1247 } else {
1248 CommandReturn::failure(ErrorCode::NOSUPPORT)
1249 }
1250 }
1251
1252 // default
1253 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
1254 }
1255 }
1256
1257 fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
1258 self.apps.enter(processid, |_, _| {})
1259 }
1260}
1261
1262/// Implementation of the syscalls for the virtualized ADC.
1263impl SyscallDriver for AdcVirtualized<'_> {
1264 /// Method for the application to command or query this driver.
1265 ///
1266 /// - `command_num` - which command call this is
1267 /// - `channel` - requested channel value
1268 /// - `_` - value sent by the application, unused
1269 /// - `processid` - application identifier
1270 fn command(
1271 &self,
1272 command_num: usize,
1273 channel: usize,
1274 _: usize,
1275 processid: ProcessId,
1276 ) -> CommandReturn {
1277 match command_num {
1278 // This driver exists and return the number of channels
1279 0 => CommandReturn::success_u32(self.drivers.len() as u32),
1280
1281 // Single sample.
1282 1 => {
1283 let res = self.enqueue_command(Operation::OneSample, channel, processid);
1284 if res == Ok(()) {
1285 CommandReturn::success()
1286 } else {
1287 match ErrorCode::try_from(res) {
1288 Ok(error) => CommandReturn::failure(error),
1289 _ => panic!("ADC Syscall: invalid error from enqueue_command"),
1290 }
1291 }
1292 }
1293
1294 // Get resolution bits
1295 101 => {
1296 if channel < self.drivers.len() {
1297 CommandReturn::success_u32(self.drivers[channel].get_resolution_bits() as u32)
1298 } else {
1299 CommandReturn::failure(ErrorCode::NODEVICE)
1300 }
1301 }
1302
1303 // Get voltage reference mV
1304 102 => {
1305 if channel < self.drivers.len() {
1306 if let Some(voltage) = self.drivers[channel].get_voltage_reference_mv() {
1307 CommandReturn::success_u32(voltage as u32)
1308 } else {
1309 CommandReturn::failure(ErrorCode::NOSUPPORT)
1310 }
1311 } else {
1312 CommandReturn::failure(ErrorCode::NODEVICE)
1313 }
1314 }
1315
1316 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
1317 }
1318 }
1319
1320 fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
1321 self.apps.enter(processid, |_, _| {})
1322 }
1323}
1324
1325impl hil::adc::Client for AdcVirtualized<'_> {
1326 fn sample_ready(&self, sample: u16) {
1327 self.current_process.take().map(|processid| {
1328 let _ = self.apps.enter(processid, |app, upcalls| {
1329 app.pending_command = false;
1330 let channel = app.channel;
1331 let _ = upcalls.schedule_upcall(
1332 0,
1333 (AdcMode::SingleSample as usize, channel, sample as usize),
1334 );
1335 });
1336 });
1337 self.run_next_command();
1338 }
1339}