blob: 0a9ba661c03fab56973621a7d187685858268d1d [file]
use crate::adc::AdcDriver;
use crate::buttons::ButtonDriver;
use crate::console::ConsoleDriver;
use crate::gpio::GpioDriver;
use crate::led::LedDriver;
use crate::result::OtherError;
use crate::result::TockError;
use crate::result::TockResult;
use crate::rng::RngDriver;
use crate::sensors::ninedof::NinedofDriver;
use crate::sensors::AmbientLightSensor;
use crate::sensors::HumiditySensor;
use crate::sensors::TemperatureSensor;
use crate::simple_ble::BleAdvertisingDriver;
use crate::simple_ble::BleScanningDriver;
use crate::temperature::TemperatureDriver;
use crate::timer::DriverContext;
use core::cell::Cell;
/// Struct containing all drivers constructible through retrieve_hardware()
#[non_exhaustive]
pub struct Hardware {
pub console_driver: ConsoleDriver,
pub led_driver: LedDriver,
pub timer_context: DriverContext,
pub gpio_driver: GpioDriver,
pub temperature_driver: TemperatureDriver,
pub button_driver: ButtonDriver,
pub adc_driver: AdcDriver,
pub rng_driver: RngDriver,
pub ble_advertising_driver: BleAdvertisingDriver,
pub ble_scanning_driver: BleScanningDriver,
pub ambient_light_sensor: AmbientLightSensor,
pub temperature_sensor: TemperatureSensor,
pub humidity_sensor: HumiditySensor,
pub ninedof_driver: NinedofDriver,
}
/// Retrieve Hardware struct. Returns Hardware only once.
pub fn retrieve_hardware() -> TockResult<Hardware> {
match unsafe { HARDWARE_SINGLETON.take() } {
Some(hardware) => Ok(hardware),
None => Err(TockError::Other(OtherError::DriverAlreadyTaken)),
}
}
/// Retrieve [Hardware] struct without check whether it has already been taken
/// at a different point.
/// # Safety
/// This shall only used in special situations where drivers cannot be passed as arguments
/// as in the panic handler. Otherwise global mutable state (as shared buffers) may be exposed
/// in an unsafe manner.
pub unsafe fn retrieve_hardware_unsafe() -> Hardware {
HARDWARE
}
#[allow(clippy::declare_interior_mutable_const)]
const HARDWARE: Hardware = Hardware {
console_driver: ConsoleDriver {
_unconstructible: (),
},
led_driver: LedDriver {
_unconstructible: (),
},
timer_context: DriverContext {
active_timer: Cell::new(None),
},
gpio_driver: GpioDriver {
_unconstructible: (),
},
temperature_driver: TemperatureDriver {
_unconstructible: (),
},
button_driver: ButtonDriver {
_unconstructible: (),
},
adc_driver: AdcDriver {
_unconstructible: (),
},
rng_driver: RngDriver {
_unconstructible: (),
},
ble_advertising_driver: BleAdvertisingDriver {
_unconstructible: (),
},
ble_scanning_driver: BleScanningDriver {
_unconstructible: (),
},
ambient_light_sensor: AmbientLightSensor {
_unconstructible: (),
},
temperature_sensor: TemperatureSensor {
_unconstructible: (),
},
humidity_sensor: HumiditySensor {
_unconstructible: (),
},
ninedof_driver: NinedofDriver {
_unconstructible: (),
},
};
static mut HARDWARE_SINGLETON: Option<Hardware> = Some(HARDWARE);
#[cfg(test)]
mod test {
use crate::retrieve_hardware;
#[test]
pub fn can_be_retrieved_once() {
reset_hardware_singleton();
assert!(retrieve_hardware().is_ok());
assert!(retrieve_hardware().is_err());
}
fn reset_hardware_singleton() {
unsafe {
super::HARDWARE_SINGLETON = Some(super::HARDWARE);
};
}
}