#![no_std]
use aligned::{A4, Aligned};
use embedded_hal_async::delay::DelayNs;
use crate::sd::{
CardCapacity, CardStatus, read_multiple_blocks, read_single_block, set_block_length,
write_multiple_blocks, write_single_block,
};
pub mod common;
pub mod emmc;
pub mod sd;
pub mod sdio;
pub mod spi;
const INIT_FREQ: u32 = 400_000;
#[derive(Debug)]
pub enum MmcError {
Timeout,
Crc,
IllegalCommand,
Busy,
Io,
SignalingSwitchFailed,
Unsupported,
Other,
}
#[derive(Debug, Clone, Copy)]
pub enum BusWidth {
W1,
W4,
W8,
}
pub enum ResponseLen {
Zero,
R48,
R136,
}
pub trait Response: Sized {
const CRC: bool;
const BUSY: bool;
const LEN: ResponseLen;
fn from_words(buf: &[u32; 4]) -> Self;
}
pub trait Command {
const INDEX: u8;
type Resp<'a>: Response
where
Self: 'a;
fn index(&self) -> u8 {
Self::INDEX
}
fn arg(&self) -> u32;
}
pub trait BlockCommand: Command {
fn block_size(&self) -> u16;
fn block_count(&self) -> u32;
}
pub trait ByteCommand: Command {
fn byte_count(&self) -> usize;
}
pub trait ControlCommand: Command {}
pub trait BlockReadCommand: BlockCommand {
fn buf(&mut self) -> &mut Aligned<A4, [u8]>;
}
pub trait BlockWriteCommand: BlockCommand {
fn buf(&self) -> &Aligned<A4, [u8]>;
}
pub trait ByteReadCommand: ByteCommand {
fn buf(&mut self) -> &mut Aligned<A4, [u8]>;
}
pub trait ByteWriteCommand: ByteCommand {
fn buf(&self) -> &Aligned<A4, [u8]>;
}
pub trait MmcBus {
fn send_command<'a, C>(
&mut self,
cmd: C,
) -> impl Future<Output = Result<C::Resp<'a>, MmcError>>
where
C: ControlCommand + 'a;
fn read_blocks<'a, C>(&mut self, cmd: C) -> impl Future<Output = Result<C::Resp<'a>, MmcError>>
where
C: BlockReadCommand + 'a;
fn write_blocks<'a, C>(
&mut self,
cmd: C,
) -> impl Future<Output = Result<C::Resp<'a>, MmcError>>
where
C: BlockWriteCommand + 'a;
fn read_bytes<'a, C>(&mut self, cmd: C) -> impl Future<Output = Result<C::Resp<'a>, MmcError>>
where
C: ByteReadCommand + 'a;
fn write_bytes<'a, C>(&mut self, cmd: C) -> impl Future<Output = Result<C::Resp<'a>, MmcError>>
where
C: ByteWriteCommand + 'a;
fn init_idle(&mut self, hz: u32) -> impl Future<Output = Result<(), MmcError>>;
fn set_bus(&mut self, width: BusWidth, hz: u32) -> impl Future<Output = Result<(), MmcError>>;
fn supports_mmc(&self) -> bool {
false
}
fn supports_bus_width(&self) -> BusWidth {
BusWidth::W1
}
fn supports_1v8(&self) -> bool {
false
}
fn supports_frequency(&self) -> u32 {
25_000_000
}
}
pub struct R1 {
pub status: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CardState {
Idle, Ready, Ident, Standby, Transfer, Data, Receive, Programming, Reserved(u8), }
impl R1 {
pub const ERR_MASK: u32 = 0xFDF9_8008;
pub fn is_error(&self) -> bool {
self.status & Self::ERR_MASK != 0
}
pub fn app_cmd(&self) -> bool {
self.status & (1 << 5) != 0
}
pub fn ready_for_data(&self) -> bool {
self.status & (1 << 8) != 0
}
pub fn current_state(&self) -> CardState {
let v = ((self.status >> 9) & 0xF) as u8;
match v {
0 => CardState::Idle,
1 => CardState::Ready,
2 => CardState::Ident,
3 => CardState::Standby,
4 => CardState::Transfer,
5 => CardState::Data,
6 => CardState::Receive,
7 => CardState::Programming,
other => CardState::Reserved(other),
}
}
}
impl Response for R1 {
const CRC: bool = true;
const LEN: ResponseLen = ResponseLen::R48;
const BUSY: bool = false;
fn from_words(buf: &[u32; 4]) -> Self {
R1 { status: buf[0] }
}
}
pub struct R1b {
pub status: u32,
}
impl Response for R1b {
const CRC: bool = true;
const LEN: ResponseLen = ResponseLen::R48;
const BUSY: bool = true;
fn from_words(buf: &[u32; 4]) -> Self {
R1b { status: buf[0] }
}
}
pub struct R2 {
pub words: [u32; 4],
}
impl Response for R2 {
const CRC: bool = true;
const LEN: ResponseLen = ResponseLen::R136;
const BUSY: bool = false;
fn from_words(buf: &[u32; 4]) -> Self {
R2 {
words: [buf[0], buf[1], buf[2], buf[3]],
}
}
}
pub struct R3 {
pub ocr: u32,
}
impl Response for R3 {
const CRC: bool = false;
const LEN: ResponseLen = ResponseLen::R48;
const BUSY: bool = false;
fn from_words(buf: &[u32; 4]) -> Self {
R3 { ocr: buf[0] }
}
}
pub struct R6 {
pub rca: u16,
pub status: u16,
}
impl Response for R6 {
const CRC: bool = true;
const LEN: ResponseLen = ResponseLen::R48;
const BUSY: bool = false;
fn from_words(buf: &[u32; 4]) -> Self {
let v = buf[0];
R6 {
rca: (v >> 16) as u16,
status: (v & 0xFFFF) as u16,
}
}
}
pub struct R7 {
pub voltage: u8,
pub check_pattern: u8,
}
impl Response for R7 {
const CRC: bool = true;
const LEN: ResponseLen = ResponseLen::R48;
const BUSY: bool = false;
fn from_words(buf: &[u32; 4]) -> Self {
let v = buf[0];
R7 {
voltage: ((v >> 8) & 0xF) as u8,
check_pattern: (v & 0xFF) as u8,
}
}
}
pub struct R4 {
pub ocr: u32,
}
impl Response for R4 {
const CRC: bool = false;
const LEN: ResponseLen = ResponseLen::R48;
const BUSY: bool = false;
fn from_words(buf: &[u32; 4]) -> Self {
R4 { ocr: buf[0] }
}
}
pub struct R5 {
pub flags: u8,
pub data: u8,
}
impl R5 {
pub const FLAG_COM_CRC_ERROR: u8 = 1 << 7;
pub const FLAG_ILLEGAL_COMMAND: u8 = 1 << 6;
pub const FLAG_ERROR: u8 = 1 << 5;
pub const FLAG_FUNCTION_NUMBER: u8 = 1 << 1;
pub const FLAG_OUT_OF_RANGE: u8 = 1 << 0;
pub const ERROR_FLAGS: u8 = Self::FLAG_COM_CRC_ERROR
| Self::FLAG_ILLEGAL_COMMAND
| Self::FLAG_ERROR
| Self::FLAG_FUNCTION_NUMBER
| Self::FLAG_OUT_OF_RANGE;
pub fn is_error(&self) -> bool {
self.flags & Self::ERROR_FLAGS != 0
}
}
impl Response for R5 {
const CRC: bool = true;
const LEN: ResponseLen = ResponseLen::R48;
const BUSY: bool = false;
fn from_words(buf: &[u32; 4]) -> Self {
let v = buf[0];
R5 {
flags: ((v >> 8) & 0xFF) as u8,
data: (v & 0xFF) as u8,
}
}
}
struct BusAdapter<B: MmcBus, D: DelayNs> {
pub bus: B,
pub delay: D,
pub rca: u16,
}
impl<B: MmcBus, D: DelayNs> BusAdapter<B, D> {
pub async fn select_card(&mut self, rca: Option<u16>) -> Result<(), MmcError> {
match self
.send_command(common::select_card(rca.unwrap_or(0)), false)
.await
{
Err(MmcError::Timeout) if rca == None => Ok(()),
result => result.map(|_| ()),
}
}
async fn app_cmd(&mut self, app_cmd: bool) -> Result<(), MmcError> {
if app_cmd {
self.bus.send_command(sd::app_cmd(self.rca)).await?;
}
Ok(())
}
pub async fn wait_if_required<C: Command>(&mut self) -> Result<(), MmcError> {
if !C::Resp::BUSY {
return Ok(());
}
for _ in 0..750 {
let status: CardStatus<()> = self
.bus
.send_command(common::card_status(self.rca, false))
.await?
.into();
if status.ready_for_data() {
return Ok(());
}
self.delay.delay_ms(1).await;
}
Err(MmcError::Timeout)
}
pub async fn send_command<'a, C: ControlCommand + 'a>(
&'a mut self,
cmd: C,
app_cmd: bool,
) -> Result<C::Resp<'a>, MmcError> {
self.app_cmd(app_cmd).await?;
let res = self.bus.send_command(cmd).await?;
self.wait_if_required::<C>().await?;
Ok(res)
}
pub async fn read_blocks<'a, C: BlockReadCommand + 'a>(
&mut self,
cmd: C,
app_cmd: bool,
) -> Result<C::Resp<'a>, MmcError> {
let block_size = cmd.block_size();
self.bus
.send_command(set_block_length(block_size as u32))
.await?;
self.app_cmd(app_cmd).await?;
let res = self.bus.read_blocks(cmd).await?;
self.wait_if_required::<C>().await?;
Ok(res)
}
pub async fn write_blocks<'a, C: BlockWriteCommand + 'a>(
&mut self,
cmd: C,
app_cmd: bool,
) -> Result<C::Resp<'a>, MmcError> {
let block_size = cmd.block_size();
self.bus
.send_command(set_block_length(block_size as u32))
.await?;
self.app_cmd(app_cmd).await?;
let res = self.bus.write_blocks(cmd).await?;
self.wait_if_required::<C>().await?;
Ok(res)
}
}
pub trait Addressable: Sized + Clone {
type Ext;
fn get_capacity(&self) -> CardCapacity;
fn size(&self) -> u64;
fn supports_cmd23(&self) -> bool;
}
#[non_exhaustive]
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
pub enum Signalling {
#[default]
SDR12,
SDR25,
SDR50,
SDR104,
DDR50,
}
pub struct BlockDevice<T: Addressable, B: MmcBus, D: DelayNs, const BLOCK_SIZE: usize> {
info: T,
bus: BusAdapter<B, D>,
}
impl<A: Addressable, B: MmcBus, D: DelayNs, const BLOCK_SIZE: usize>
BlockDevice<A, B, D, BLOCK_SIZE>
{
pub fn card(&self) -> A {
self.info.clone()
}
#[inline]
async fn read_block(
&mut self,
block_idx: u32,
block: &mut Aligned<A4, [u8; BLOCK_SIZE]>,
) -> Result<(), MmcError> {
let card_capacity = self.info.get_capacity();
let addr = match card_capacity {
CardCapacity::StandardCapacity => block_idx * BLOCK_SIZE as u32,
_ => block_idx,
};
self.bus
.read_blocks(read_single_block(addr, block), false)
.await?;
Ok(())
}
#[inline]
async fn read_blocks(
&mut self,
block_idx: u32,
blocks: &mut [Aligned<A4, [u8; BLOCK_SIZE]>],
) -> Result<(), MmcError> {
let card_capacity = self.info.get_capacity();
let addr = match card_capacity {
CardCapacity::StandardCapacity => block_idx * BLOCK_SIZE as u32,
_ => block_idx,
};
self.bus
.read_blocks(read_multiple_blocks(addr, blocks), false)
.await?;
Ok(())
}
#[inline]
async fn write_block(
&mut self,
block_idx: u32,
block: &Aligned<A4, [u8; BLOCK_SIZE]>,
) -> Result<(), MmcError> {
let card_capacity = self.info.get_capacity();
let addr = match card_capacity {
CardCapacity::StandardCapacity => block_idx * BLOCK_SIZE as u32,
_ => block_idx,
};
self.bus
.write_blocks(write_single_block(addr, block), false)
.await?;
Ok(())
}
#[inline]
async fn write_blocks(
&mut self,
block_idx: u32,
blocks: &[Aligned<A4, [u8; BLOCK_SIZE]>],
) -> Result<(), MmcError> {
let card_capacity = self.info.get_capacity();
let addr = match card_capacity {
CardCapacity::StandardCapacity => block_idx * BLOCK_SIZE as u32,
_ => block_idx,
};
self.bus
.write_blocks(write_multiple_blocks(addr, blocks), false)
.await?;
Ok(())
}
}
impl<A: Addressable, B: MmcBus, D: DelayNs, const BLOCK_SIZE: usize>
block_device_driver::BlockDevice<BLOCK_SIZE> for BlockDevice<A, B, D, BLOCK_SIZE>
{
type Align = A4;
type Error = MmcError;
#[inline]
async fn read(
&mut self,
block_address: u32,
blocks: &mut [aligned::Aligned<Self::Align, [u8; BLOCK_SIZE]>],
) -> Result<(), Self::Error> {
assert_eq!(BLOCK_SIZE % 4, 0);
if blocks.len() == 1 {
self.read_block(block_address, &mut blocks[0]).await?;
} else {
self.read_blocks(block_address, blocks).await?;
}
Ok(())
}
#[inline]
async fn write(
&mut self,
block_address: u32,
blocks: &[aligned::Aligned<Self::Align, [u8; BLOCK_SIZE]>],
) -> Result<(), Self::Error> {
assert_eq!(BLOCK_SIZE % 4, 0);
if blocks.len() == 1 {
self.write_block(block_address, &blocks[0]).await?;
} else {
self.write_blocks(block_address, blocks).await?;
}
Ok(())
}
async fn size(&mut self) -> Result<u64, Self::Error> {
Ok(self.info.size())
}
}