sdmmc-core 0.5.0

SD/MMC core data structures and algorithms
Documentation
use crate::lib_bitfield;
use crate::result::Result;

use super::{ExtCsd, ExtCsdIndex};

lib_bitfield! {
    /// Represents the `EXCEPTION_EVENTS_CTRL` field of the [ExtCsd] register.
    pub ExceptionEventsCtrl(u16): u8 {
        /// Enables the exception to indicate that an error was cause by `CMD53` or `CMD54`.
        pub extended_security_failure: 4;
        /// Enables the exception to indicate that an packed command caused an error.
        pub packed_failure: 3;
        /// Enables the exception to indicate that system resources pool is exhausted.
        pub syspool_exhausted: 2;
        /// Enables the exception to indicate that additional dynamic capacity is needed.
        pub dyncap_needed: 1;
    }
}

impl ExceptionEventsCtrl {
    /// Represents the bitmask of the [ExceptionEventsCtrl].
    pub const MASK: u16 = 0x1e;
    /// Represents the default byte value of the [ExceptionEventsCtrl].
    pub const DEFAULT: u16 = 0;

    /// Creates a new [ExceptionEventsCtrl].
    pub const fn new() -> Self {
        Self(Self::DEFAULT)
    }

    /// Converts a [`u16`] into a [ExceptionEventsCtrl].
    pub const fn from_bits(val: u16) -> Self {
        Self(val & Self::MASK)
    }

    /// Converts an inner representation to a [ExceptionEventsCtrl].
    pub const fn try_from_inner(val: u16) -> Result<Self> {
        Ok(Self::from_bits(val))
    }

    /// Converts a [ExceptionEventsCtrl] to an inner representation.
    pub const fn into_inner(self) -> u16 {
        self.bits()
    }
}

impl Default for ExceptionEventsCtrl {
    fn default() -> Self {
        Self::new()
    }
}

impl ExtCsd {
    /// Gets the `EXCEPTION_EVENTS_CTRL` field of the [ExtCsd] register.
    pub const fn exception_events_ctrl(&self) -> Result<ExceptionEventsCtrl> {
        let start = self.0[ExtCsdIndex::EXCEPTION_EVENTS_CTRL_START];
        let end = self.0[ExtCsdIndex::EXCEPTION_EVENTS_CTRL_END];

        ExceptionEventsCtrl::try_from_inner(u16::from_be_bytes([start, end]))
    }

    /// Sets the `EXCEPTION_EVENTS_CTRL` field of the [ExtCsd] register.
    pub fn set_exception_events_ctrl(&mut self, val: ExceptionEventsCtrl) {
        let [start, end] = val.into_inner().to_be_bytes();

        self.0[ExtCsdIndex::EXCEPTION_EVENTS_CTRL_START] = start;
        self.0[ExtCsdIndex::EXCEPTION_EVENTS_CTRL_END] = end;
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_exception_events_ctrl() {
        let mut ext_csd = ExtCsd::new();

        (1..=u8::BITS).map(|r| (1u16 << r) - 1).for_each(|raw| {
            let status = ExceptionEventsCtrl::from_bits(raw);
            assert_eq!(status.bits(), raw & ExceptionEventsCtrl::MASK);

            ext_csd.set_exception_events_ctrl(status);
            assert_eq!(ext_csd.exception_events_ctrl(), Ok(status));
        });
    }
}