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_STATUS` field of the [ExtCsd] register.
    pub ExceptionEventsStatus(u16): u8 {
        /// Indicates that an error was cause by `CMD53` or `CMD54`.
        pub extended_security_failure: 4;
        /// Indicates that an packed command caused an error.
        pub packed_failure: 3;
        /// Indicates that system resources pool is exhausted.
        pub syspool_exhausted: 2;
        /// Indicates that additional dynamic capacity is needed.
        pub dyncap_needed: 1;
        /// Indicates that urgent background operations needed.
        pub urgent_bkops: 0;
    }
}

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

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

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

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

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

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

impl ExtCsd {
    /// Gets the `EXCEPTION_EVENTS_STATUS` field of the [ExtCsd] register.
    pub const fn exception_events_status(&self) -> Result<ExceptionEventsStatus> {
        let start = self.0[ExtCsdIndex::EXCEPTION_EVENTS_STATUS_START];
        let end = self.0[ExtCsdIndex::EXCEPTION_EVENTS_STATUS_END];

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

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

        self.0[ExtCsdIndex::EXCEPTION_EVENTS_STATUS_START] = start;
        self.0[ExtCsdIndex::EXCEPTION_EVENTS_STATUS_END] = end;
    }
}

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

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

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

            ext_csd.set_exception_events_status(status);
            assert_eq!(ext_csd.exception_events_status(), Ok(status));
        });
    }
}