@ -192,7 +192,6 @@ mod low_level_api {
|
|||||||
options.flow_ctrl == crate::dma::FlowControl::Dma,
|
options.flow_ctrl == crate::dma::FlowControl::Dma,
|
||||||
"Peripheral flow control not supported"
|
"Peripheral flow control not supported"
|
||||||
);
|
);
|
||||||
assert!(options.fifo_threshold.is_none(), "FIFO mode not supported");
|
|
||||||
|
|
||||||
let ch = dma.ch(channel_number as _);
|
let ch = dma.ch(channel_number as _);
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use core::task::Waker;
|
|||||||
use embassy_cortex_m::interrupt::Priority;
|
use embassy_cortex_m::interrupt::Priority;
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
use super::{Burst, FifoThreshold, FlowControl, Request, TransferOptions, Word, WordSize};
|
use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize};
|
||||||
use crate::_generated::DMA_CHANNEL_COUNT;
|
use crate::_generated::DMA_CHANNEL_COUNT;
|
||||||
use crate::interrupt::{Interrupt, InterruptExt};
|
use crate::interrupt::{Interrupt, InterruptExt};
|
||||||
use crate::pac::dma::{regs, vals};
|
use crate::pac::dma::{regs, vals};
|
||||||
@ -40,17 +40,6 @@ impl From<FlowControl> for vals::Pfctrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<FifoThreshold> for vals::Fth {
|
|
||||||
fn from(value: FifoThreshold) -> Self {
|
|
||||||
match value {
|
|
||||||
FifoThreshold::Quarter => vals::Fth::QUARTER,
|
|
||||||
FifoThreshold::Half => vals::Fth::HALF,
|
|
||||||
FifoThreshold::ThreeQuarters => vals::Fth::THREEQUARTERS,
|
|
||||||
FifoThreshold::Full => vals::Fth::FULL,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ChannelState {
|
struct ChannelState {
|
||||||
waker: AtomicWaker,
|
waker: AtomicWaker,
|
||||||
}
|
}
|
||||||
@ -247,16 +236,6 @@ mod low_level_api {
|
|||||||
ch.par().write_value(peri_addr as u32);
|
ch.par().write_value(peri_addr as u32);
|
||||||
ch.m0ar().write_value(mem_addr as u32);
|
ch.m0ar().write_value(mem_addr as u32);
|
||||||
ch.ndtr().write_value(regs::Ndtr(mem_len as _));
|
ch.ndtr().write_value(regs::Ndtr(mem_len as _));
|
||||||
ch.fcr().write(|w| {
|
|
||||||
if let Some(fth) = options.fifo_threshold {
|
|
||||||
// FIFO mode
|
|
||||||
w.set_dmdis(vals::Dmdis::DISABLED);
|
|
||||||
w.set_fth(fth.into());
|
|
||||||
} else {
|
|
||||||
// Direct mode
|
|
||||||
w.set_dmdis(vals::Dmdis::ENABLED);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ch.cr().write(|w| {
|
ch.cr().write(|w| {
|
||||||
w.set_dir(dir);
|
w.set_dir(dir);
|
||||||
w.set_msize(data_size);
|
w.set_msize(data_size);
|
||||||
|
@ -176,16 +176,8 @@ mod low_level_api {
|
|||||||
mem_len: usize,
|
mem_len: usize,
|
||||||
incr_mem: bool,
|
incr_mem: bool,
|
||||||
data_size: WordSize,
|
data_size: WordSize,
|
||||||
options: TransferOptions,
|
_options: TransferOptions,
|
||||||
) {
|
) {
|
||||||
assert!(options.mburst == crate::dma::Burst::Single, "Burst mode not supported");
|
|
||||||
assert!(options.pburst == crate::dma::Burst::Single, "Burst mode not supported");
|
|
||||||
assert!(
|
|
||||||
options.flow_ctrl == crate::dma::FlowControl::Dma,
|
|
||||||
"Peripheral flow control not supported"
|
|
||||||
);
|
|
||||||
assert!(options.fifo_threshold.is_none(), "FIFO mode not supported");
|
|
||||||
|
|
||||||
// "Preceding reads and writes cannot be moved past subsequent writes."
|
// "Preceding reads and writes cannot be moved past subsequent writes."
|
||||||
fence(Ordering::SeqCst);
|
fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
@ -186,19 +186,6 @@ pub enum FlowControl {
|
|||||||
Peripheral,
|
Peripheral,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
||||||
pub enum FifoThreshold {
|
|
||||||
/// 1/4 full FIFO
|
|
||||||
Quarter,
|
|
||||||
/// 1/2 full FIFO
|
|
||||||
Half,
|
|
||||||
/// 3/4 full FIFO
|
|
||||||
ThreeQuarters,
|
|
||||||
/// Full FIFO
|
|
||||||
Full,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct TransferOptions {
|
pub struct TransferOptions {
|
||||||
@ -208,8 +195,6 @@ pub struct TransferOptions {
|
|||||||
pub mburst: Burst,
|
pub mburst: Burst,
|
||||||
/// Flow control configuration
|
/// Flow control configuration
|
||||||
pub flow_ctrl: FlowControl,
|
pub flow_ctrl: FlowControl,
|
||||||
/// FIFO threshold for DMA FIFO mode. If none, direct mode is used.
|
|
||||||
pub fifo_threshold: Option<FifoThreshold>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TransferOptions {
|
impl Default for TransferOptions {
|
||||||
@ -218,7 +203,6 @@ impl Default for TransferOptions {
|
|||||||
pburst: Burst::Single,
|
pburst: Burst::Single,
|
||||||
mburst: Burst::Single,
|
mburst: Burst::Single,
|
||||||
flow_ctrl: FlowControl::Dma,
|
flow_ctrl: FlowControl::Dma,
|
||||||
fifo_threshold: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,14 +764,6 @@ impl SdmmcInner {
|
|||||||
}
|
}
|
||||||
self.cmd(Cmd::read_single_block(address), true)?;
|
self.cmd(Cmd::read_single_block(address), true)?;
|
||||||
|
|
||||||
// Start data DMA transfer *after* sending the command
|
|
||||||
// #[cfg(sdmmc_v1)]
|
|
||||||
// unsafe {
|
|
||||||
// regs.dctrl().modify(|w| {
|
|
||||||
// w.set_dmaen(true);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
let res = poll_fn(|cx| {
|
let res = poll_fn(|cx| {
|
||||||
waker_reg.register(cx.waker());
|
waker_reg.register(cx.waker());
|
||||||
let status = unsafe { regs.star().read() };
|
let status = unsafe { regs.star().read() };
|
||||||
@ -815,16 +807,10 @@ impl SdmmcInner {
|
|||||||
let regs = self.0;
|
let regs = self.0;
|
||||||
let on_drop = OnDrop::new(|| unsafe { self.on_drop() });
|
let on_drop = OnDrop::new(|| unsafe { self.on_drop() });
|
||||||
|
|
||||||
// sdmmc_v1 uses different cmd/dma order than v2, but only for writes
|
|
||||||
#[cfg(sdmmc_v1)]
|
|
||||||
self.cmd(Cmd::write_single_block(address), true)?;
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.prepare_datapath_write(buffer as *const [u32; 128], 512, 9, data_transfer_timeout, dma);
|
self.prepare_datapath_write(buffer as *const [u32; 128], 512, 9, data_transfer_timeout, dma);
|
||||||
self.data_interrupts(true);
|
self.data_interrupts(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(sdmmc_v2)]
|
|
||||||
self.cmd(Cmd::write_single_block(address), true)?;
|
self.cmd(Cmd::write_single_block(address), true)?;
|
||||||
|
|
||||||
let res = poll_fn(|cx| {
|
let res = poll_fn(|cx| {
|
||||||
@ -936,9 +922,7 @@ impl SdmmcInner {
|
|||||||
let request = dma.request();
|
let request = dma.request();
|
||||||
dma.start_read(request, regs.fifor().ptr() as *const u32, buffer, crate::dma::TransferOptions {
|
dma.start_read(request, regs.fifor().ptr() as *const u32, buffer, crate::dma::TransferOptions {
|
||||||
pburst: crate::dma::Burst::Incr4,
|
pburst: crate::dma::Burst::Incr4,
|
||||||
mburst: crate::dma::Burst::Incr4,
|
|
||||||
flow_ctrl: crate::dma::FlowControl::Peripheral,
|
flow_ctrl: crate::dma::FlowControl::Peripheral,
|
||||||
fifo_threshold: Some(crate::dma::FifoThreshold::Full),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
} else if #[cfg(sdmmc_v2)] {
|
} else if #[cfg(sdmmc_v2)] {
|
||||||
@ -952,8 +936,8 @@ impl SdmmcInner {
|
|||||||
w.set_dtdir(true);
|
w.set_dtdir(true);
|
||||||
#[cfg(sdmmc_v1)]
|
#[cfg(sdmmc_v1)]
|
||||||
{
|
{
|
||||||
w.set_dten(true);
|
|
||||||
w.set_dmaen(true);
|
w.set_dmaen(true);
|
||||||
|
w.set_dten(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -986,9 +970,7 @@ impl SdmmcInner {
|
|||||||
let request = dma.request();
|
let request = dma.request();
|
||||||
dma.start_write(request, buffer, regs.fifor().ptr() as *mut u32, crate::dma::TransferOptions {
|
dma.start_write(request, buffer, regs.fifor().ptr() as *mut u32, crate::dma::TransferOptions {
|
||||||
pburst: crate::dma::Burst::Incr4,
|
pburst: crate::dma::Burst::Incr4,
|
||||||
mburst: crate::dma::Burst::Incr4,
|
|
||||||
flow_ctrl: crate::dma::FlowControl::Peripheral,
|
flow_ctrl: crate::dma::FlowControl::Peripheral,
|
||||||
fifo_threshold: Some(crate::dma::FifoThreshold::Full),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
} else if #[cfg(sdmmc_v2)] {
|
} else if #[cfg(sdmmc_v2)] {
|
||||||
@ -1000,11 +982,6 @@ impl SdmmcInner {
|
|||||||
regs.dctrl().modify(|w| {
|
regs.dctrl().modify(|w| {
|
||||||
w.set_dblocksize(block_size);
|
w.set_dblocksize(block_size);
|
||||||
w.set_dtdir(false);
|
w.set_dtdir(false);
|
||||||
#[cfg(sdmmc_v1)]
|
|
||||||
{
|
|
||||||
w.set_dten(true);
|
|
||||||
w.set_dmaen(true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,9 +9,6 @@ use embassy_stm32::time::mhz;
|
|||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{interrupt, Config};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
#[repr(align(4))]
|
|
||||||
struct AlignedBuffer([u8; 512]);
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
@ -37,24 +34,11 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
// Should print 400kHz for initialization
|
// Should print 400kHz for initialization
|
||||||
info!("Configured clock: {}", sdmmc.clock().0);
|
info!("Configured clock: {}", sdmmc.clock().0);
|
||||||
|
|
||||||
unwrap!(sdmmc.init_card(mhz(2)).await);
|
unwrap!(sdmmc.init_card(mhz(25)).await);
|
||||||
|
|
||||||
let card = unwrap!(sdmmc.card());
|
let card = unwrap!(sdmmc.card());
|
||||||
|
|
||||||
info!("Card: {:#?}", Debug2Format(card));
|
info!("Card: {:#?}", Debug2Format(card));
|
||||||
info!("Clock: {}", sdmmc.clock());
|
|
||||||
|
|
||||||
let mut buf = AlignedBuffer([0u8; 512]);
|
|
||||||
|
|
||||||
info!("read");
|
|
||||||
sdmmc.read_block(512, &mut buf.0).await.unwrap();
|
|
||||||
info!("read done: {:?}, {:?}", buf.0[..10], buf.0[502..]);
|
|
||||||
|
|
||||||
let buf = AlignedBuffer([6u8; 512]);
|
|
||||||
|
|
||||||
info!("writing");
|
|
||||||
sdmmc.write_block(0, &buf.0).await.unwrap();
|
|
||||||
info!("Write done!");
|
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user