Merge #669
669: Add SDMMC v1 and SDIO support r=Dirbaio a=chemicstry SDMMC v2 peripheral is an extension of SDMMC v1 (or SDIO) so I managed to reuse most of the code, with some cfg's. Apart from small differeces in registers, the biggest change is that v2 uses internal DMA, while v1 has to use shared DMA peripheral. This makes code a bit uglier, because DMA channel for v1 has to be passed around. Not sure if it's possible to make it any cleaner. This also adds `TransferOptions` structure to DMA, because SDMMC v1 requires setting peripheral flow control and burst transfers. Let me know if some alternative way would be prefered. I tested this on STM32F429ZIT6 (with sd card) and STM32H745ZIT6 (with oscilloscope). Depends on: https://github.com/embassy-rs/stm32-data/pull/130 Co-authored-by: chemicstry <chemicstry@gmail.com>
This commit is contained in:
commit
37ada65a33
@ -407,17 +407,17 @@ fn main() {
|
|||||||
(("timer", "BKIN2"), (quote!(crate::pwm::BreakInput2Pin), quote!())),
|
(("timer", "BKIN2"), (quote!(crate::pwm::BreakInput2Pin), quote!())),
|
||||||
(("timer", "BKIN2_COMP1"), (quote!(crate::pwm::BreakInput2Comparator1Pin), quote!())),
|
(("timer", "BKIN2_COMP1"), (quote!(crate::pwm::BreakInput2Comparator1Pin), quote!())),
|
||||||
(("timer", "BKIN2_COMP2"), (quote!(crate::pwm::BreakInput2Comparator2Pin), quote!())),
|
(("timer", "BKIN2_COMP2"), (quote!(crate::pwm::BreakInput2Comparator2Pin), quote!())),
|
||||||
(("sdmmc", "CK"), (quote!(crate::sdmmc::CkPin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "CK"), (quote!(crate::sdmmc::CkPin), quote!())),
|
||||||
(("sdmmc", "CMD"), (quote!(crate::sdmmc::CmdPin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "CMD"), (quote!(crate::sdmmc::CmdPin), quote!())),
|
||||||
(("sdmmc", "D0"), (quote!(crate::sdmmc::D0Pin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "D0"), (quote!(crate::sdmmc::D0Pin), quote!())),
|
||||||
(("sdmmc", "D1"), (quote!(crate::sdmmc::D1Pin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "D1"), (quote!(crate::sdmmc::D1Pin), quote!())),
|
||||||
(("sdmmc", "D2"), (quote!(crate::sdmmc::D2Pin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "D2"), (quote!(crate::sdmmc::D2Pin), quote!())),
|
||||||
(("sdmmc", "D3"), (quote!(crate::sdmmc::D3Pin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "D3"), (quote!(crate::sdmmc::D3Pin), quote!())),
|
||||||
(("sdmmc", "D4"), (quote!(crate::sdmmc::D4Pin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "D4"), (quote!(crate::sdmmc::D4Pin), quote!())),
|
||||||
(("sdmmc", "D5"), (quote!(crate::sdmmc::D5Pin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "D5"), (quote!(crate::sdmmc::D5Pin), quote!())),
|
||||||
(("sdmmc", "D6"), (quote!(crate::sdmmc::D6Pin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "D6"), (quote!(crate::sdmmc::D6Pin), quote!())),
|
||||||
(("sdmmc", "D6"), (quote!(crate::sdmmc::D7Pin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "D6"), (quote!(crate::sdmmc::D7Pin), quote!())),
|
||||||
(("sdmmc", "D8"), (quote!(crate::sdmmc::D8Pin), quote!(#[cfg(feature="sdmmc-rs")]))),
|
(("sdmmc", "D8"), (quote!(crate::sdmmc::D8Pin), quote!())),
|
||||||
].into();
|
].into();
|
||||||
|
|
||||||
for p in METADATA.peripherals {
|
for p in METADATA.peripherals {
|
||||||
@ -483,6 +483,8 @@ fn main() {
|
|||||||
(("i2c", "TX"), quote!(crate::i2c::TxDma)),
|
(("i2c", "TX"), quote!(crate::i2c::TxDma)),
|
||||||
(("dcmi", "DCMI"), quote!(crate::dcmi::FrameDma)),
|
(("dcmi", "DCMI"), quote!(crate::dcmi::FrameDma)),
|
||||||
(("dcmi", "PSSI"), quote!(crate::dcmi::FrameDma)),
|
(("dcmi", "PSSI"), quote!(crate::dcmi::FrameDma)),
|
||||||
|
// SDMMCv1 uses the same channel for both directions, so just implement for RX
|
||||||
|
(("sdmmc", "RX"), quote!(crate::sdmmc::SdmmcDma)),
|
||||||
]
|
]
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ use crate::dma::Request;
|
|||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::pac::bdma::vals;
|
use crate::pac::bdma::vals;
|
||||||
|
|
||||||
use super::{Word, WordSize};
|
use super::{TransferOptions, Word, WordSize};
|
||||||
|
|
||||||
impl From<WordSize> for vals::Size {
|
impl From<WordSize> for vals::Size {
|
||||||
fn from(raw: WordSize) -> Self {
|
fn from(raw: WordSize) -> Self {
|
||||||
@ -55,7 +55,7 @@ foreach_dma_channel! {
|
|||||||
($channel_peri:ident, $dma_peri:ident, bdma, $channel_num:expr, $index:expr, $dmamux:tt) => {
|
($channel_peri:ident, $dma_peri:ident, bdma, $channel_num:expr, $index:expr, $dmamux:tt) => {
|
||||||
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
|
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
|
||||||
|
|
||||||
unsafe fn start_write<W: Word>(&mut self, _request: Request, buf: *const[W], reg_addr: *mut W) {
|
unsafe fn start_write<W: Word>(&mut self, _request: Request, buf: *const[W], reg_addr: *mut W, options: TransferOptions) {
|
||||||
let (ptr, len) = super::slice_ptr_parts(buf);
|
let (ptr, len) = super::slice_ptr_parts(buf);
|
||||||
low_level_api::start_transfer(
|
low_level_api::start_transfer(
|
||||||
pac::$dma_peri,
|
pac::$dma_peri,
|
||||||
@ -68,6 +68,7 @@ foreach_dma_channel! {
|
|||||||
len,
|
len,
|
||||||
true,
|
true,
|
||||||
vals::Size::from(W::bits()),
|
vals::Size::from(W::bits()),
|
||||||
|
options,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
@ -76,7 +77,7 @@ foreach_dma_channel! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsafe fn start_write_repeated<W: Word>(&mut self, _request: Request, repeated: W, count: usize, reg_addr: *mut W) {
|
unsafe fn start_write_repeated<W: Word>(&mut self, _request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) {
|
||||||
let buf = [repeated];
|
let buf = [repeated];
|
||||||
low_level_api::start_transfer(
|
low_level_api::start_transfer(
|
||||||
pac::$dma_peri,
|
pac::$dma_peri,
|
||||||
@ -89,6 +90,7 @@ foreach_dma_channel! {
|
|||||||
count,
|
count,
|
||||||
false,
|
false,
|
||||||
vals::Size::from(W::bits()),
|
vals::Size::from(W::bits()),
|
||||||
|
options,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
@ -96,7 +98,7 @@ foreach_dma_channel! {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn start_read<W: Word>(&mut self, _request: Request, reg_addr: *const W, buf: *mut [W]) {
|
unsafe fn start_read<W: Word>(&mut self, _request: Request, reg_addr: *const W, buf: *mut [W], options: TransferOptions) {
|
||||||
let (ptr, len) = super::slice_ptr_parts_mut(buf);
|
let (ptr, len) = super::slice_ptr_parts_mut(buf);
|
||||||
low_level_api::start_transfer(
|
low_level_api::start_transfer(
|
||||||
pac::$dma_peri,
|
pac::$dma_peri,
|
||||||
@ -109,6 +111,7 @@ foreach_dma_channel! {
|
|||||||
len,
|
len,
|
||||||
true,
|
true,
|
||||||
vals::Size::from(W::bits()),
|
vals::Size::from(W::bits()),
|
||||||
|
options,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
@ -155,9 +158,23 @@ mod low_level_api {
|
|||||||
mem_len: usize,
|
mem_len: usize,
|
||||||
incr_mem: bool,
|
incr_mem: bool,
|
||||||
data_size: vals::Size,
|
data_size: vals::Size,
|
||||||
|
options: TransferOptions,
|
||||||
#[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
|
#[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
|
||||||
#[cfg(dmamux)] dmamux_ch_num: u8,
|
#[cfg(dmamux)] dmamux_ch_num: u8,
|
||||||
) {
|
) {
|
||||||
|
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"
|
||||||
|
);
|
||||||
|
|
||||||
let ch = dma.ch(channel_number as _);
|
let ch = dma.ch(channel_number as _);
|
||||||
|
|
||||||
reset_status(dma, channel_number);
|
reset_status(dma, channel_number);
|
||||||
|
@ -9,7 +9,7 @@ use crate::interrupt;
|
|||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::pac::dma::{regs, vals};
|
use crate::pac::dma::{regs, vals};
|
||||||
|
|
||||||
use super::{Request, Word, WordSize};
|
use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize};
|
||||||
|
|
||||||
impl From<WordSize> for vals::Size {
|
impl From<WordSize> for vals::Size {
|
||||||
fn from(raw: WordSize) -> Self {
|
fn from(raw: WordSize) -> Self {
|
||||||
@ -21,6 +21,26 @@ impl From<WordSize> for vals::Size {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Burst> for vals::Burst {
|
||||||
|
fn from(burst: Burst) -> Self {
|
||||||
|
match burst {
|
||||||
|
Burst::Single => vals::Burst::SINGLE,
|
||||||
|
Burst::Incr4 => vals::Burst::INCR4,
|
||||||
|
Burst::Incr8 => vals::Burst::INCR8,
|
||||||
|
Burst::Incr16 => vals::Burst::INCR16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<FlowControl> for vals::Pfctrl {
|
||||||
|
fn from(flow: FlowControl) -> Self {
|
||||||
|
match flow {
|
||||||
|
FlowControl::Dma => vals::Pfctrl::DMA,
|
||||||
|
FlowControl::Peripheral => vals::Pfctrl::PERIPHERAL,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
ch_wakers: [AtomicWaker; DMA_CHANNEL_COUNT],
|
ch_wakers: [AtomicWaker; DMA_CHANNEL_COUNT],
|
||||||
}
|
}
|
||||||
@ -49,7 +69,7 @@ pub(crate) unsafe fn init() {
|
|||||||
foreach_dma_channel! {
|
foreach_dma_channel! {
|
||||||
($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $index:expr, $dmamux:tt) => {
|
($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $index:expr, $dmamux:tt) => {
|
||||||
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
|
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
|
||||||
unsafe fn start_write<W: Word>(&mut self, request: Request, buf: *const [W], reg_addr: *mut W) {
|
unsafe fn start_write<W: Word>(&mut self, request: Request, buf: *const [W], reg_addr: *mut W, options: TransferOptions) {
|
||||||
let (ptr, len) = super::slice_ptr_parts(buf);
|
let (ptr, len) = super::slice_ptr_parts(buf);
|
||||||
low_level_api::start_transfer(
|
low_level_api::start_transfer(
|
||||||
pac::$dma_peri,
|
pac::$dma_peri,
|
||||||
@ -61,6 +81,7 @@ foreach_dma_channel! {
|
|||||||
len,
|
len,
|
||||||
true,
|
true,
|
||||||
vals::Size::from(W::bits()),
|
vals::Size::from(W::bits()),
|
||||||
|
options,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
@ -68,7 +89,7 @@ foreach_dma_channel! {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) {
|
unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) {
|
||||||
let buf = [repeated];
|
let buf = [repeated];
|
||||||
low_level_api::start_transfer(
|
low_level_api::start_transfer(
|
||||||
pac::$dma_peri,
|
pac::$dma_peri,
|
||||||
@ -80,6 +101,7 @@ foreach_dma_channel! {
|
|||||||
count,
|
count,
|
||||||
false,
|
false,
|
||||||
vals::Size::from(W::bits()),
|
vals::Size::from(W::bits()),
|
||||||
|
options,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
@ -87,7 +109,7 @@ foreach_dma_channel! {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *const W, buf: *mut [W]) {
|
unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *const W, buf: *mut [W], options: TransferOptions) {
|
||||||
let (ptr, len) = super::slice_ptr_parts_mut(buf);
|
let (ptr, len) = super::slice_ptr_parts_mut(buf);
|
||||||
low_level_api::start_transfer(
|
low_level_api::start_transfer(
|
||||||
pac::$dma_peri,
|
pac::$dma_peri,
|
||||||
@ -99,6 +121,7 @@ foreach_dma_channel! {
|
|||||||
len,
|
len,
|
||||||
true,
|
true,
|
||||||
vals::Size::from(W::bits()),
|
vals::Size::from(W::bits()),
|
||||||
|
options,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
@ -146,6 +169,7 @@ mod low_level_api {
|
|||||||
mem_len: usize,
|
mem_len: usize,
|
||||||
incr_mem: bool,
|
incr_mem: bool,
|
||||||
data_size: vals::Size,
|
data_size: vals::Size,
|
||||||
|
options: TransferOptions,
|
||||||
#[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
|
#[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
|
||||||
#[cfg(dmamux)] dmamux_ch_num: u8,
|
#[cfg(dmamux)] dmamux_ch_num: u8,
|
||||||
) {
|
) {
|
||||||
@ -180,6 +204,10 @@ mod low_level_api {
|
|||||||
#[cfg(dma_v2)]
|
#[cfg(dma_v2)]
|
||||||
w.set_chsel(request);
|
w.set_chsel(request);
|
||||||
|
|
||||||
|
w.set_pburst(options.pburst.into());
|
||||||
|
w.set_mburst(options.mburst.into());
|
||||||
|
w.set_pfctrl(options.flow_ctrl.into());
|
||||||
|
|
||||||
w.set_en(true);
|
w.set_en(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ pub(crate) mod sealed {
|
|||||||
request: Request,
|
request: Request,
|
||||||
buf: *const [W],
|
buf: *const [W],
|
||||||
reg_addr: *mut W,
|
reg_addr: *mut W,
|
||||||
|
options: TransferOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Starts this channel for writing a word repeatedly.
|
/// Starts this channel for writing a word repeatedly.
|
||||||
@ -58,6 +59,7 @@ pub(crate) mod sealed {
|
|||||||
repeated: W,
|
repeated: W,
|
||||||
count: usize,
|
count: usize,
|
||||||
reg_addr: *mut W,
|
reg_addr: *mut W,
|
||||||
|
options: TransferOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Starts this channel for reading a stream of words.
|
/// Starts this channel for reading a stream of words.
|
||||||
@ -71,6 +73,7 @@ pub(crate) mod sealed {
|
|||||||
request: Request,
|
request: Request,
|
||||||
reg_addr: *const W,
|
reg_addr: *const W,
|
||||||
buf: *mut [W],
|
buf: *mut [W],
|
||||||
|
options: TransferOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Requests the channel to stop.
|
/// Requests the channel to stop.
|
||||||
@ -126,6 +129,45 @@ impl Word for u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Burst {
|
||||||
|
/// Single transfer
|
||||||
|
Single,
|
||||||
|
/// Incremental burst of 4 beats
|
||||||
|
Incr4,
|
||||||
|
/// Incremental burst of 8 beats
|
||||||
|
Incr8,
|
||||||
|
/// Incremental burst of 16 beats
|
||||||
|
Incr16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum FlowControl {
|
||||||
|
/// Flow control by DMA
|
||||||
|
Dma,
|
||||||
|
/// Flow control by peripheral
|
||||||
|
Peripheral,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TransferOptions {
|
||||||
|
/// Peripheral burst transfer configuration
|
||||||
|
pub pburst: Burst,
|
||||||
|
/// Memory burst transfer configuration
|
||||||
|
pub mburst: Burst,
|
||||||
|
/// Flow control configuration
|
||||||
|
pub flow_ctrl: FlowControl,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TransferOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
pburst: Burst::Single,
|
||||||
|
mburst: Burst::Single,
|
||||||
|
flow_ctrl: FlowControl::Dma,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod transfers {
|
mod transfers {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -139,7 +181,7 @@ mod transfers {
|
|||||||
assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
|
assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
|
||||||
unborrow!(channel);
|
unborrow!(channel);
|
||||||
|
|
||||||
unsafe { channel.start_read::<W>(request, reg_addr, buf) };
|
unsafe { channel.start_read::<W>(request, reg_addr, buf, Default::default()) };
|
||||||
|
|
||||||
Transfer::new(channel)
|
Transfer::new(channel)
|
||||||
}
|
}
|
||||||
@ -154,7 +196,7 @@ mod transfers {
|
|||||||
assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
|
assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
|
||||||
unborrow!(channel);
|
unborrow!(channel);
|
||||||
|
|
||||||
unsafe { channel.start_write::<W>(request, buf, reg_addr) };
|
unsafe { channel.start_write::<W>(request, buf, reg_addr, Default::default()) };
|
||||||
|
|
||||||
Transfer::new(channel)
|
Transfer::new(channel)
|
||||||
}
|
}
|
||||||
@ -169,7 +211,15 @@ mod transfers {
|
|||||||
) -> impl Future<Output = ()> + 'a {
|
) -> impl Future<Output = ()> + 'a {
|
||||||
unborrow!(channel);
|
unborrow!(channel);
|
||||||
|
|
||||||
unsafe { channel.start_write_repeated::<W>(request, repeated, count, reg_addr) };
|
unsafe {
|
||||||
|
channel.start_write_repeated::<W>(
|
||||||
|
request,
|
||||||
|
repeated,
|
||||||
|
count,
|
||||||
|
reg_addr,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
Transfer::new(channel)
|
Transfer::new(channel)
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
|||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -424,7 +424,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
|
|
||||||
let tx_request = self.txdma.request();
|
let tx_request = self.txdma.request();
|
||||||
let tx_dst = T::REGS.tx_ptr();
|
let tx_dst = T::REGS.tx_ptr();
|
||||||
unsafe { self.txdma.start_write(tx_request, data, tx_dst) }
|
unsafe {
|
||||||
|
self.txdma
|
||||||
|
.start_write(tx_request, data, tx_dst, Default::default())
|
||||||
|
}
|
||||||
let tx_f = Transfer::new(&mut self.txdma);
|
let tx_f = Transfer::new(&mut self.txdma);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -470,7 +473,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
|
|
||||||
let rx_request = self.rxdma.request();
|
let rx_request = self.rxdma.request();
|
||||||
let rx_src = T::REGS.rx_ptr();
|
let rx_src = T::REGS.rx_ptr();
|
||||||
unsafe { self.rxdma.start_read(rx_request, rx_src, data) };
|
unsafe {
|
||||||
|
self.rxdma
|
||||||
|
.start_read(rx_request, rx_src, data, Default::default())
|
||||||
|
};
|
||||||
let rx_f = Transfer::new(&mut self.rxdma);
|
let rx_f = Transfer::new(&mut self.rxdma);
|
||||||
|
|
||||||
let tx_request = self.txdma.request();
|
let tx_request = self.txdma.request();
|
||||||
@ -532,12 +538,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
|
|
||||||
let rx_request = self.rxdma.request();
|
let rx_request = self.rxdma.request();
|
||||||
let rx_src = T::REGS.rx_ptr();
|
let rx_src = T::REGS.rx_ptr();
|
||||||
unsafe { self.rxdma.start_read(rx_request, rx_src, read) };
|
unsafe {
|
||||||
|
self.rxdma
|
||||||
|
.start_read(rx_request, rx_src, read, Default::default())
|
||||||
|
};
|
||||||
let rx_f = Transfer::new(&mut self.rxdma);
|
let rx_f = Transfer::new(&mut self.rxdma);
|
||||||
|
|
||||||
let tx_request = self.txdma.request();
|
let tx_request = self.txdma.request();
|
||||||
let tx_dst = T::REGS.tx_ptr();
|
let tx_dst = T::REGS.tx_ptr();
|
||||||
unsafe { self.txdma.start_write(tx_request, write, tx_dst) }
|
unsafe {
|
||||||
|
self.txdma
|
||||||
|
.start_write(tx_request, write, tx_dst, Default::default())
|
||||||
|
}
|
||||||
let tx_f = Transfer::new(&mut self.txdma);
|
let tx_f = Transfer::new(&mut self.txdma);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
44
examples/stm32f4/src/bin/sdmmc.rs
Normal file
44
examples/stm32f4/src/bin/sdmmc.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
#[path = "../example_common.rs"]
|
||||||
|
mod example_common;
|
||||||
|
|
||||||
|
use embassy::executor::Spawner;
|
||||||
|
use embassy_stm32::sdmmc::Sdmmc;
|
||||||
|
use embassy_stm32::time::U32Ext;
|
||||||
|
use embassy_stm32::{interrupt, Config, Peripherals};
|
||||||
|
use example_common::*;
|
||||||
|
|
||||||
|
fn config() -> Config {
|
||||||
|
let mut config = Config::default();
|
||||||
|
config.rcc.sys_ck = Some(48.mhz().into());
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy::main(config = "config()")]
|
||||||
|
async fn main(_spawner: Spawner, p: Peripherals) -> ! {
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let irq = interrupt::take!(SDIO);
|
||||||
|
|
||||||
|
let mut sdmmc = Sdmmc::new(
|
||||||
|
p.SDIO,
|
||||||
|
(p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11),
|
||||||
|
irq,
|
||||||
|
Default::default(),
|
||||||
|
p.DMA2_CH3,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should print 400kHz for initialization
|
||||||
|
info!("Configured clock: {}", sdmmc.clock().0);
|
||||||
|
|
||||||
|
unwrap!(sdmmc.init_card(25.mhz()).await);
|
||||||
|
|
||||||
|
let card = unwrap!(sdmmc.card());
|
||||||
|
|
||||||
|
info!("Card: {:#?}", Debug2Format(card));
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
44
examples/stm32f7/src/bin/sdmmc.rs
Normal file
44
examples/stm32f7/src/bin/sdmmc.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
#[path = "../example_common.rs"]
|
||||||
|
mod example_common;
|
||||||
|
|
||||||
|
use embassy::executor::Spawner;
|
||||||
|
use embassy_stm32::sdmmc::Sdmmc;
|
||||||
|
use embassy_stm32::time::U32Ext;
|
||||||
|
use embassy_stm32::{interrupt, Config, Peripherals};
|
||||||
|
use example_common::*;
|
||||||
|
|
||||||
|
fn config() -> Config {
|
||||||
|
let mut config = Config::default();
|
||||||
|
config.rcc.sys_ck = Some(200.mhz().into());
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy::main(config = "config()")]
|
||||||
|
async fn main(_spawner: Spawner, p: Peripherals) -> ! {
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let irq = interrupt::take!(SDMMC1);
|
||||||
|
|
||||||
|
let mut sdmmc = Sdmmc::new(
|
||||||
|
p.SDMMC1,
|
||||||
|
(p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11),
|
||||||
|
irq,
|
||||||
|
Default::default(),
|
||||||
|
p.DMA2_CH3,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should print 400kHz for initialization
|
||||||
|
info!("Configured clock: {}", sdmmc.clock().0);
|
||||||
|
|
||||||
|
unwrap!(sdmmc.init_card(25.mhz()).await);
|
||||||
|
|
||||||
|
let card = unwrap!(sdmmc.card());
|
||||||
|
|
||||||
|
info!("Card: {:#?}", Debug2Format(card));
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
43
examples/stm32h7/src/bin/sdmmc.rs
Normal file
43
examples/stm32h7/src/bin/sdmmc.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
#[path = "../example_common.rs"]
|
||||||
|
mod example_common;
|
||||||
|
|
||||||
|
use embassy::executor::Spawner;
|
||||||
|
use embassy_stm32::sdmmc::Sdmmc;
|
||||||
|
use embassy_stm32::time::U32Ext;
|
||||||
|
use embassy_stm32::{interrupt, Config, Peripherals};
|
||||||
|
use example_common::*;
|
||||||
|
|
||||||
|
fn config() -> Config {
|
||||||
|
let mut config = Config::default();
|
||||||
|
config.rcc.sys_ck = Some(200.mhz().into());
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy::main(config = "config()")]
|
||||||
|
async fn main(_spawner: Spawner, p: Peripherals) -> ! {
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let irq = interrupt::take!(SDMMC1);
|
||||||
|
|
||||||
|
let mut sdmmc = Sdmmc::new(
|
||||||
|
p.SDMMC1,
|
||||||
|
(p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11),
|
||||||
|
irq,
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should print 400kHz for initialization
|
||||||
|
info!("Configured clock: {}", sdmmc.clock().0);
|
||||||
|
|
||||||
|
unwrap!(sdmmc.init_card(25.mhz()).await);
|
||||||
|
|
||||||
|
let card = unwrap!(sdmmc.card());
|
||||||
|
|
||||||
|
info!("Card: {:#?}", Debug2Format(card));
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
Subproject commit d3e8a2fe63eeb403102559f3f9917d9fcf27e1a1
|
Subproject commit 938770167164faa46970af4f6096ec7c8b195914
|
Loading…
x
Reference in New Issue
Block a user