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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
//#[macro_use]
//pub mod memory;
use core::fmt::{UpperHex, Formatter, Debug};
/// Module that helps with creating a register interface
#[macro_use]
pub mod register;
#[cfg(feature = "async")]
#[macro_use]
pub mod register_async;
/// General Device trait
pub trait LowLevelDevice<I> {
/// Create a new instance of the device with the given interface
fn new(interface: I) -> Self
where
Self: Sized;
/// Destruct the device and give back the interface
fn free(self) -> I;
}
/// The base macro for low level.
/// Creates the struct and implements the right traits for it.
///
/// # Example
///
/// ```ignore
/// // Create our low level device. This holds all the hardware communication definitions
/// create_low_level_device!(
/// /// Our test device
/// MyDevice {
/// // The types of errors our low level error enum must contain
/// errors: [InterfaceError],
/// // Any hardware interface must implement the HardwareInterface trait that is created by this macro.
/// // This option allows us to specify which traits that new trait inherits. In this case that is RegisterInterface and Debug.
/// hardware_interface_requirements: { RegisterInterface + Debug },
/// // This specifies the contents of the HardwareInterface trait.
/// hardware_interface_capabilities: {
/// /// Resets the device
/// fn reset(&mut self) -> Result<(), InterfaceError>;
/// },
/// }
/// );
/// ```
#[macro_export]
macro_rules! create_low_level_device {
(
$(#[$device_doc:meta])*
$device_name:ident {
errors: [$($error_type:ident),*],
hardware_interface_requirements: {$($hardware_interface_bound_type:tt)*},
hardware_interface_capabilities: $hardware_interface_capabilities:tt $(,)?
}
) => {
use device_driver::ll::LowLevelDevice;
use device_driver::ll::ConversionError;
/// Marker trait for hardware interface implementations
pub trait HardwareInterface : $($hardware_interface_bound_type)* $hardware_interface_capabilities
$(#[$device_doc])*
pub struct $device_name<I: HardwareInterface> {
interface: I,
}
impl<I: HardwareInterface> $device_name<I> {
/// Access to the pure hardware interface type
pub fn interface(&mut self) -> &mut I {
&mut self.interface
}
}
impl<I: HardwareInterface> LowLevelDevice<I> for $device_name<I> {
fn new(interface: I) -> Self
where
Self: Sized,
{
Self { interface }
}
fn free(self) -> I {
self.interface
}
}
/// Error type containing all low level errors
#[derive(Debug)]
pub enum LowLevelError {
/// Error variant for type conversion errors
ConversionError,
$(
#[doc = concat!("Error variant containing [", stringify!($error_type), "]")]
$error_type($error_type)
)*
}
impl<T: core::fmt::UpperHex + core::fmt::Debug> From<ConversionError<T>> for LowLevelError {
fn from(_: ConversionError<T>) -> Self {
LowLevelError::ConversionError
}
}
$(
impl From<$error_type> for LowLevelError {
fn from(val: $error_type) -> Self {
LowLevelError::$error_type(val)
}
}
)*
};
}
/// Error type for type conversion errors
pub struct ConversionError<T: UpperHex + Debug> {
/// The raw value that was tried to have converted
pub raw: T,
}
impl<T: UpperHex + Debug> Debug for ConversionError<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ConversionError")
.field("raw", &format_args!("0x{:X}", self.raw))
.finish()
}
}