capsules_extra/
cycle_count.rs1use capsules_core::driver;
18pub const DRIVER_NUM: usize = driver::NUM::CycleCount as usize;
19
20use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
21use kernel::syscall::{CommandReturn, SyscallDriver};
22use kernel::utilities::cells::OptionalCell;
23use kernel::{hil, ErrorCode, ProcessId};
24
25#[derive(Default)]
26pub struct App;
27
28pub struct CycleCount<'a, P: hil::hw_debug::CycleCounter> {
29 counters: &'a P,
30 apps: Grant<App, UpcallCount<0>, AllowRoCount<0>, AllowRwCount<0>>,
31 controlling_app: OptionalCell<ProcessId>,
32}
33
34impl<'a, P: hil::hw_debug::CycleCounter> CycleCount<'a, P> {
35 pub fn new(
36 counters: &'a P,
37 grant: Grant<App, UpcallCount<0>, AllowRoCount<0>, AllowRwCount<0>>,
38 ) -> Self {
39 Self {
40 counters,
41 apps: grant,
42 controlling_app: OptionalCell::empty(),
43 }
44 }
45}
46
47impl<P: hil::hw_debug::CycleCounter> SyscallDriver for CycleCount<'_, P> {
48 fn command(
58 &self,
59 command_num: usize,
60 _data: usize,
61 _: usize,
62 processid: ProcessId,
63 ) -> CommandReturn {
64 let try_claim_driver = || {
65 let match_or_empty_or_nonexistant =
66 self.controlling_app.map_or(true, |controlling_app| {
67 self.apps
68 .enter(controlling_app, |_, _| controlling_app == processid)
69 .unwrap_or(true)
70 });
71 if match_or_empty_or_nonexistant {
72 self.controlling_app.set(processid);
73 true
74 } else {
75 false
76 }
77 };
78 match command_num {
79 0 => CommandReturn::success(),
80
81 1 => {
82 if try_claim_driver() {
83 self.counters.start();
84 CommandReturn::success()
85 } else {
86 CommandReturn::failure(ErrorCode::RESERVE)
87 }
88 }
89 2 => CommandReturn::success_u64(self.counters.count()),
90 3 => {
91 if try_claim_driver() {
92 self.counters.reset();
93 CommandReturn::success()
94 } else {
95 CommandReturn::failure(ErrorCode::RESERVE)
96 }
97 }
98 4 => {
99 if try_claim_driver() {
100 self.counters.stop();
101 CommandReturn::success()
102 } else {
103 CommandReturn::failure(ErrorCode::RESERVE)
104 }
105 }
106 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
107 }
108 }
109
110 fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
111 self.apps.enter(processid, |_, _| {})
112 }
113}