1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Debug capsule to cause a button press to make all apps fault.
//!
//! This is useful for debugging that capsules and apps work when they are
//! restarted by the kernel.
//!
//! Usage
//! -----
//!
//! ```rust,ignore
//! # use kernel::{capabilities, static_init};
//!
//! struct ProcessMgmtCap;
//! unsafe impl capabilities::ProcessManagementCapability for ProcessMgmtCap {}
//! let debug_process_restart = static_init!(
//!     capsules::debug_process_restart::DebugProcessRestart<
//!         'static,
//!         ProcessMgmtCap,
//!     >,
//!     capsules::debug_process_restart::DebugProcessRestart::new(
//!         board_kernel,
//!         ProcessMgmtCap
//!         &sam4l::gpio::PA[16],
//!         kernel::hil::gpio::ActivationMode::ActiveLow,
//!         kernel::hil::gpio::FloatingState::PullUp
//!     )
//! );
//! sam4l::gpio::PA[16].set_client(debug_process_restart);
//! ```

use kernel::capabilities::ProcessManagementCapability;
use kernel::hil::gpio;
use kernel::Kernel;

pub struct DebugProcessRestart<'a, C: ProcessManagementCapability> {
    kernel: &'static Kernel,
    capability: C,
    pin: &'a dyn gpio::InterruptPin<'a>,
    mode: gpio::ActivationMode,
}

impl<'a, C: ProcessManagementCapability> DebugProcessRestart<'a, C> {
    pub fn new(
        kernel: &'static Kernel,
        cap: C,
        pin: &'a dyn gpio::InterruptPin<'a>,
        mode: gpio::ActivationMode,
        floating_state: gpio::FloatingState,
    ) -> Self {
        pin.make_input();
        pin.set_floating_state(floating_state);
        pin.enable_interrupts(gpio::InterruptEdge::EitherEdge);

        DebugProcessRestart {
            kernel,
            capability: cap,
            pin,
            mode,
        }
    }
}

impl<C: ProcessManagementCapability> gpio::Client for DebugProcessRestart<'_, C> {
    fn fired(&self) {
        if self.pin.read_activation(self.mode) == gpio::ActivationState::Active {
            self.kernel.hardfault_all_apps(&self.capability);
        }
    }
}