Skip to main content

sdmmc_protocol/
error.rs

1//! Error and diagnostic context types returned by drivers and parsers.
2//!
3//! See [`Phase`] and [`ErrorContext`] for the operational metadata that
4//! recoverable [`Error`] variants carry.
5
6/// Where in the driver pipeline a fault was observed.
7///
8/// Attached to recoverable [`Error`] variants via [`ErrorContext`] so callers
9/// can distinguish e.g. a CMD0 send timeout from a `BusyWait` programming
10/// timeout without parsing log strings.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
12pub enum Phase {
13    /// Phase was not recorded.
14    ///
15    /// Used as a default placeholder; real driver paths should pick a
16    /// concrete variant.
17    #[default]
18    Unspecified,
19    /// Power-up / running CMD0 → ACMD41 / sending CMD2/3/9/7.
20    Init,
21    /// Putting the command bytes onto the bus.
22    CommandSend,
23    /// Waiting for the card's response token / R1–R7 payload.
24    ResponseWait,
25    /// Streaming a data block to the card (CMD24 / CMD25 etc).
26    DataWrite,
27    /// Streaming a data block from the card (CMD17 / CMD18 etc).
28    DataRead,
29    /// Polling the card's busy line / programming status.
30    BusyWait,
31    /// Switching bus speed, width or function (CMD6 / ACMD6).
32    Switch,
33    /// Erase sequence (CMD32 / CMD33 / CMD38).
34    Erase,
35}
36
37/// Operational context attached to recoverable bus / protocol errors.
38///
39/// Helps callers triage failures: which phase of the SD/MMC pipeline
40/// raised the error, and which CMD/ACMD index was being processed at
41/// the time, when known.
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
43pub struct ErrorContext {
44    /// Pipeline phase when the fault was raised.
45    pub phase: Phase,
46    /// CMD/ACMD index being processed, if applicable.
47    pub cmd: Option<u8>,
48}
49
50impl ErrorContext {
51    /// Build a context with only the phase populated.
52    #[inline]
53    pub const fn new(phase: Phase) -> Self {
54        Self { phase, cmd: None }
55    }
56
57    /// Build a context tied to a specific CMD/ACMD index.
58    #[inline]
59    pub const fn for_cmd(phase: Phase, cmd: u8) -> Self {
60        Self {
61            phase,
62            cmd: Some(cmd),
63        }
64    }
65}
66
67/// Errors returned by SD/MMC protocol parsers and drivers.
68///
69/// Recoverable bus / protocol variants carry an [`ErrorContext`] pinpointing
70/// the phase and (when known) command index that raised them. Caller-facing
71/// programming errors (`Misaligned`, `InvalidArgument`) and card-state
72/// reports (`NoCard`, `CardError`, `CardLocked`) do not.
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum Error {
75    /// No response from card within the deadline for the wrapped phase.
76    Timeout(ErrorContext),
77    /// CRC check failed during the wrapped phase.
78    Crc(ErrorContext),
79    /// Card is not responding or not inserted.
80    NoCard,
81    /// Command index is not supported on this transport.
82    UnsupportedCommand,
83    /// Bad response received during the wrapped phase.
84    BadResponse(ErrorContext),
85    /// Card returned an error in its R1 response.
86    CardError(CardError),
87    /// Write operation failed during the wrapped phase.
88    WriteError(ErrorContext),
89    /// Read operation failed during the wrapped phase.
90    ReadError(ErrorContext),
91    /// Misaligned address or length passed by the caller.
92    Misaligned,
93    /// Caller passed an invalid argument.
94    InvalidArgument,
95    /// Card is locked (host needs to unlock before further I/O).
96    CardLocked,
97    /// Generic communication error on the bus during the wrapped phase.
98    BusError(ErrorContext),
99}
100
101/// Per-bit error status decoded out of an R1 response.
102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
103pub enum CardError {
104    /// A command was issued out of sequence.
105    IllegalCommand,
106    /// CRC check of the last command failed.
107    CommandCrcFailed,
108    /// Erase sequence error.
109    EraseSequence,
110    /// Address alignment error.
111    AddressError,
112    /// Card internal ECC error.
113    CardEccFailed,
114    /// Generic controller error.
115    ControllerError,
116    /// Unknown error bit set.
117    Unknown(u8),
118}