use core::cell::RefCell;
use cortex_m::asm;
use embedded_sdmmc::blockdevice::{Block, BlockCount, BlockDevice, BlockIdx};
use stm32h7xx_hal::pac::SDMMC1;
use stm32h7xx_hal::sdmmc::{SdCard, Sdmmc};
use crate::hwcore::dca::{DcaCache, DcaCacheCtx};
pub struct SdMmcBlockDev {
sdmmc: RefCell<Sdmmc<SDMMC1, SdCard>>,
}
#[derive(Debug, Clone, Copy)]
pub enum SdError {
Hal,
}
impl SdMmcBlockDev {
pub fn new(sdmmc: Sdmmc<SDMMC1, SdCard>) -> Self {
Self {
sdmmc: RefCell::new(sdmmc),
}
}
fn invalidate(buf: &mut [u8]) {
unsafe {
let mut scb = cortex_m::Peripherals::steal().SCB;
let mut ctx = DcaCacheCtx::new(&mut scb);
ctx.cache_mut().invalidate(buf.as_ptr() as usize, buf.len());
}
asm::dmb();
}
fn clean(buf: &[u8]) {
unsafe {
let mut scb = cortex_m::Peripherals::steal().SCB;
let mut ctx = DcaCacheCtx::new(&mut scb);
ctx.cache_mut().clean(buf.as_ptr() as usize, buf.len());
}
asm::dmb();
}
}
impl BlockDevice for SdMmcBlockDev {
type Error = SdError;
fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> {
let mut sdmmc = self.sdmmc.borrow_mut();
for (i, block) in blocks.iter_mut().enumerate() {
Self::invalidate(&mut block.contents);
sdmmc
.read_blocks(start_block_idx.0 + i as u32, &mut block.contents)
.map_err(|_| SdError::Hal)?;
Self::invalidate(&mut block.contents);
}
Ok(())
}
fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> {
let mut sdmmc = self.sdmmc.borrow_mut();
for (i, block) in blocks.iter().enumerate() {
Self::clean(&block.contents);
sdmmc
.write_blocks(start_block_idx.0 + i as u32, &block.contents)
.map_err(|_| SdError::Hal)?;
}
Ok(())
}
fn num_blocks(&self) -> Result<BlockCount, Self::Error> {
let sdmmc = self.sdmmc.borrow();
let count = sdmmc
.card()
.map(|c| c.csd.block_count() as u32)
.unwrap_or(0);
Ok(BlockCount(count))
}
}
pub struct DummyTimeSource;
impl embedded_sdmmc::TimeSource for DummyTimeSource {
fn get_timestamp(&self) -> embedded_sdmmc::Timestamp {
embedded_sdmmc::Timestamp {
year_since_1970: 55,
zero_indexed_month: 0,
zero_indexed_day: 0,
hours: 0,
minutes: 0,
seconds: 0,
}
}
}