#![deny(missing_docs)]
use cortex_m::asm;
use rlvgl_core::fs::{BlockDevice, FsError};
use stm32h7xx_hal::pac::SDMMC1;
use stm32h7xx_hal::sdmmc::{SdCard, Sdmmc};
use crate::hwcore::dca::{DcaCache, DcaCacheCtx};
pub struct DiscoSdBlockDevice {
sdmmc: Sdmmc<SDMMC1, SdCard>,
block_size: usize,
}
impl DiscoSdBlockDevice {
pub fn new(sdmmc: Sdmmc<SDMMC1, SdCard>) -> Self {
Self {
sdmmc,
block_size: 512,
}
}
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 DiscoSdBlockDevice {
fn read_blocks(&mut self, lba: u64, buf: &mut [u8]) -> Result<(), FsError> {
if buf.len() % self.block_size != 0 {
return Err(FsError::Device);
}
Self::invalidate(buf);
self.sdmmc
.read_blocks(lba as u32, buf)
.map_err(|_| FsError::Device)?;
Self::invalidate(buf);
Ok(())
}
fn write_blocks(&mut self, lba: u64, buf: &[u8]) -> Result<(), FsError> {
if buf.len() % self.block_size != 0 {
return Err(FsError::Device);
}
Self::clean(buf);
self.sdmmc
.write_blocks(lba as u32, buf)
.map_err(|_| FsError::Device)
}
fn block_size(&self) -> usize {
self.block_size
}
fn num_blocks(&self) -> u64 {
self.sdmmc
.card()
.map(|c| c.csd.block_count() as u64)
.unwrap_or(0)
}
fn flush(&mut self) -> Result<(), FsError> {
self.sdmmc.card().map(|_| ()).map_err(|_| FsError::Device)
}
}