sdmmc-core 0.5.0

SD/MMC core data structures and algorithms
Documentation
//! Represents the `EXT_CSD` extended CSD register.
//!
//! The register can be accessed with the `SWITCH` and `SEND_EXT_CSD` commands.

use crate::const_try;
use crate::result::{Error, Result};

pub mod acc_size;
pub mod barrier_ctrl;
pub mod barrier_support;
pub mod bkops_en;
pub mod bkops_start;
pub mod bkops_status;
pub mod bkops_support;
pub mod boot_bus_conditions;
pub mod boot_config_prot;
pub mod boot_info;
pub mod boot_size_mult;
pub mod boot_wp;
pub mod boot_wp_status;
pub mod bus_width;
pub mod cache_ctrl;
pub mod cache_flush_policy;
pub mod cache_size;
pub mod class6_ctrl;
pub mod cmd_set;
pub mod cmd_set_rev;
pub mod cmdq;
pub mod cmdq_mode_en;
pub mod command_set;
pub mod context_capabilities;
pub mod context_conf;
pub mod correctly_prg_sectors_num;
pub mod csd_structure;
pub mod data_sector_size;
pub mod data_tag_support;
pub mod device_life_time_est;
pub mod device_type;
pub mod device_version;
pub mod driver_strength;
pub mod enh_size_mult;
pub mod enh_start_addr;
pub mod erase_group_def;
pub mod erase_timeout_mult;
pub mod erased_mem_cont;
pub mod exception_events_ctrl;
pub mod exception_events_status;
pub mod ext_csd_rev;
pub mod ext_partitions_attribute;
pub mod ext_security_err;
pub mod ext_support;
pub mod ffu_arg;
pub mod ffu_features;
pub mod ffu_status;
pub mod firmware_version;
pub mod flush_cache;
pub mod fw_config;
pub mod generic_cmd6_time;
pub mod gp_size_mult;
pub mod hc_erase_grp_size;
pub mod hc_wp_grp_size;
pub mod hpi_features;
pub mod hpi_mgmt;
pub mod hs_timing;
pub mod index;
pub mod ini_timeout_ap;
pub mod ini_timeout_emu;
pub mod large_unit_size_m1;
pub mod max_enh_size_mult;
pub mod max_packed;
pub mod max_pre_loading_data_size;
pub mod min_perf;
pub mod mode_config;
pub mod mode_operation_codes;
pub mod native_sector_size;
pub mod number_of_fw_sectors_correctly_programmed;
pub mod operation_codes_timeout;
pub mod optimal_read_size;
pub mod optimal_trim_unit_size;
pub mod optimal_write_size;
pub mod out_of_interrupt_time;
pub mod packed_command_status;
pub mod packed_failure_index;
pub mod partition_config;
pub mod partition_setting_completed;
pub mod partition_switch_time;
pub mod partitioning_support;
pub mod partitions_attribute;
pub mod periodic_wakeup;
pub mod power_class;
pub mod power_class_code;
pub mod power_off_long_time;
pub mod power_off_notification;
pub mod pre_eol_info;
pub mod pre_loading_data_size;
pub mod product_state_awareness_enablement;
pub mod production_state_awareness;
pub mod production_state_awareness_timeout;
pub mod program_cid_csd_ddr_support;
pub mod pwr_cl;
pub mod rel_wr_sec_c;
pub mod rpmb_size_mult;
pub mod rst_n_function;
pub mod s_a_timeout;
pub mod s_c_vcc;
pub mod s_cmd_set;
pub mod sanitize_start;
pub mod sec_bad_blk_mgmnt;
pub mod sec_count;
pub mod sec_erase_mult;
pub mod sec_feature_support;
pub mod sec_trim_mult;
pub mod secure_removal_type;
pub mod secure_wp_info;
pub mod size_mult;
pub mod sleep_notification_time;
pub mod strobe_support;
pub mod supported_modes;
pub mod tag_size;
pub mod tcase_support;
pub mod trim_mult;
pub mod use_native_sector;
pub mod user_wp;
pub mod vendor_proprietary_health_report;
pub mod vendor_specific;
pub mod wr_rel_param;
pub mod wr_rel_set;

pub mod fields;
pub(crate) use fields::*;

/// Represents the `EXT_CSD` register.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ExtCsd([u8; 512]);

impl ExtCsd {
    /// Represents the byte length of the [ExtCsd] register.
    pub const LEN: usize = 512;
    /// Represents the default byte value of the [ExtCsd] register.
    #[rustfmt::skip]
    pub const DEFAULT: [u8; Self::LEN] = [
        // 0                                      8
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 16                                    24
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 32                                    40
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 48                                    56
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 64                                    72
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 80                                    88
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 96                                   104
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 112                                  120
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 128                                  136
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 144                                  152
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 160                                  168
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 176                                  184
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 192                                  200
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 208                                  216
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8,
        // 224                                  232
        0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 240                                  248
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 256                                  264
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 1u8, 1u8, 1u8, 0u8, 0u8,
        // 272                                  280
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 288                                  296
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 304                                  312
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 320                                  328
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 336                                  344
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 352                                  360
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 368                                  376
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 384                                  392
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 400                                  408
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 416                                  424
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 432                                  440
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 448                                  456
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 464                                  472
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
        // 480                                  488
        0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8,
        // 496                                  504
        5u8, 0u8, 0u8, 0u8, 3u8, 5u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
    ];

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

    /// Converts the [ExtCsd] into its inner representation.
    pub const fn into_inner(self) -> [u8; Self::LEN] {
        self.0
    }

    /// Attempts to convert an inner representation into an [ExtCsd].
    pub const fn try_from_inner(val: [u8; Self::LEN]) -> Result<Self> {
        let e = Self(val);

        /*
         * check fallible fields for errors
         */
        const_try!(e.acc_size());
        const_try!(e.bkops_status());
        const_try!(e.boot_bus_conditions());
        const_try!(e.boot_wp_status());
        const_try!(e.bus_width());
        const_try!(e.class_6_ctrl());
        const_try!(e.cmd_set());
        const_try!(e.cmd_set_rev());
        const_try!(e.context_capabilities());
        const_try!(e.context_conf_all());
        const_try!(e.csd_structure());
        const_try!(e.data_sector_size());
        const_try!(e.device_life_time_est_typ_a());
        const_try!(e.device_life_time_est_typ_b());
        const_try!(e.device_type());
        const_try!(e.erased_mem_cont());
        const_try!(e.exception_events_ctrl());
        const_try!(e.exception_events_status());
        const_try!(e.ext_csd_rev());
        const_try!(e.ext_partitions_attribute());
        const_try!(e.ffu_status());
        const_try!(e.flush_cache());
        const_try!(e.hs_timing());
        const_try!(e.max_packed_reads());
        const_try!(e.max_packed_writes());

        const_try!(e.min_perf_ddr_r_8_52());
        const_try!(e.min_perf_ddr_w_8_52());
        const_try!(e.min_perf_r_8_26_4_52());
        const_try!(e.min_perf_w_8_26_4_52());
        const_try!(e.min_perf_r_4_26());
        const_try!(e.min_perf_w_4_26());
        const_try!(e.min_perf_r_8_52());
        const_try!(e.min_perf_w_8_52());

        const_try!(e.mode_config());
        const_try!(e.mode_operation_codes());
        const_try!(e.native_sector_size());
        const_try!(e.operation_codes_timeout());
        const_try!(e.optimal_trim_unit_size());
        const_try!(e.partition_config());
        const_try!(e.periodic_wakeup());
        const_try!(e.power_class());
        const_try!(e.power_off_notification());
        const_try!(e.pre_eol_info());
        const_try!(e.product_state_awareness());
        const_try!(e.production_state_awareness());
        const_try!(e.production_state_awareness_timeout());

        const_try!(e.pwr_cl_200_130());
        const_try!(e.pwr_cl_200_195());
        const_try!(e.pwr_cl_26_195());
        const_try!(e.pwr_cl_26_360());
        const_try!(e.pwr_cl_52_195());
        const_try!(e.pwr_cl_52_360());
        const_try!(e.pwr_cl_ddr_200_360());
        const_try!(e.pwr_cl_ddr_52_195());
        const_try!(e.pwr_cl_ddr_52_360());

        const_try!(e.rel_wr_sec_c());
        const_try!(e.rpmb_size_mult());
        const_try!(e.rst_n_function());
        const_try!(e.s_a_timeout());
        const_try!(e.s_c_vcc());
        const_try!(e.s_c_vccq());
        const_try!(e.secure_removal_type());
        const_try!(e.sleep_notification_time());
        const_try!(e.tag_res_size());
        const_try!(e.tcase_support());
        const_try!(e.use_native_sector());

        Ok(e)
    }
}

impl AsRef<[u8]> for ExtCsd {
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref()
    }
}

impl TryFrom<[u8; ExtCsd::LEN]> for ExtCsd {
    type Error = Error;

    fn try_from(val: [u8; Self::LEN]) -> Result<Self> {
        Self::try_from_inner(val)
    }
}

impl TryFrom<&[u8]> for ExtCsd {
    type Error = Error;

    fn try_from(val: &[u8]) -> Result<Self> {
        match val.len() {
            len if len < Self::LEN => Err(Error::invalid_length(len, Self::LEN)),
            _ => <[u8; Self::LEN]>::try_from(&val[..Self::LEN])
                .map_err(Error::from)
                .and_then(Self::try_from),
        }
    }
}

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

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

    #[test]
    fn test_ext_csd() {
        assert_eq!(ExtCsd::try_from_inner(ExtCsd::DEFAULT), Ok(ExtCsd::new()));
    }
}