Merge branch 'master' into usb_msc
This commit is contained in:
@ -17,7 +17,7 @@ flavors = [
|
||||
{ regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" },
|
||||
{ regex_feature = "stm32f2.*", target = "thumbv7m-none-eabi" },
|
||||
{ regex_feature = "stm32f3.*", target = "thumbv7em-none-eabi" },
|
||||
{ regex_feature = "stm32f42.*", target = "thumbv7em-none-eabi" },
|
||||
{ regex_feature = "stm32f4.*", target = "thumbv7em-none-eabi" },
|
||||
{ regex_feature = "stm32f7.*", target = "thumbv7em-none-eabi" },
|
||||
{ regex_feature = "stm32c0.*", target = "thumbv6m-none-eabi" },
|
||||
{ regex_feature = "stm32g0.*", target = "thumbv6m-none-eabi" },
|
||||
@ -58,7 +58,7 @@ cortex-m = "0.7.6"
|
||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||
rand_core = "0.6.3"
|
||||
sdio-host = "0.5.0"
|
||||
embedded-sdmmc = { git = "https://github.com/thalesfragoso/embedded-sdmmc-rs", branch = "async", optional = true }
|
||||
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "46d1b1c2ff13e31e282ec1e352421721694f126a", optional = true }
|
||||
critical-section = "1.1"
|
||||
atomic-polyfill = "1.0.1"
|
||||
stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt"] }
|
||||
@ -77,7 +77,6 @@ stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features
|
||||
|
||||
[features]
|
||||
defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-executor/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "embedded-io?/defmt", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt"]
|
||||
sdmmc-rs = ["embedded-sdmmc"]
|
||||
memory-x = ["stm32-metapac/memory-x"]
|
||||
subghz = []
|
||||
exti = []
|
||||
|
@ -192,6 +192,7 @@ mod low_level_api {
|
||||
options.flow_ctrl == crate::dma::FlowControl::Dma,
|
||||
"Peripheral flow control not supported"
|
||||
);
|
||||
assert!(options.fifo_threshold.is_none(), "FIFO mode not supported");
|
||||
|
||||
let ch = dma.ch(channel_number as _);
|
||||
|
||||
|
@ -4,7 +4,7 @@ use core::task::Waker;
|
||||
use embassy_cortex_m::interrupt::Priority;
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize};
|
||||
use super::{Burst, FifoThreshold, FlowControl, Request, TransferOptions, Word, WordSize};
|
||||
use crate::_generated::DMA_CHANNEL_COUNT;
|
||||
use crate::interrupt::{Interrupt, InterruptExt};
|
||||
use crate::pac::dma::{regs, vals};
|
||||
@ -40,6 +40,17 @@ 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 {
|
||||
waker: AtomicWaker,
|
||||
}
|
||||
@ -236,6 +247,16 @@ mod low_level_api {
|
||||
ch.par().write_value(peri_addr as u32);
|
||||
ch.m0ar().write_value(mem_addr as u32);
|
||||
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| {
|
||||
w.set_dir(dir);
|
||||
w.set_msize(data_size);
|
||||
@ -411,12 +432,8 @@ mod low_level_api {
|
||||
}
|
||||
|
||||
if isr.tcif(channel_num % 4) && cr.read().tcie() {
|
||||
if cr.read().dbm() == vals::Dbm::DISABLED {
|
||||
cr.write(|_| ()); // Disable channel with the default value.
|
||||
} else {
|
||||
// for double buffered mode, clear TCIF flag but do not stop the transfer
|
||||
dma.ifcr(channel_num / 4).write(|w| w.set_tcif(channel_num % 4, true));
|
||||
}
|
||||
/* acknowledge transfer complete interrupt */
|
||||
dma.ifcr(channel_num / 4).write(|w| w.set_tcif(channel_num % 4, true));
|
||||
STATE.channels[state_index].waker.wake();
|
||||
}
|
||||
}
|
||||
|
@ -176,8 +176,16 @@ mod low_level_api {
|
||||
mem_len: usize,
|
||||
incr_mem: bool,
|
||||
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."
|
||||
fence(Ordering::SeqCst);
|
||||
|
||||
|
@ -186,6 +186,19 @@ pub enum FlowControl {
|
||||
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)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct TransferOptions {
|
||||
@ -195,6 +208,8 @@ pub struct TransferOptions {
|
||||
pub mburst: Burst,
|
||||
/// Flow control configuration
|
||||
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 {
|
||||
@ -203,6 +218,7 @@ impl Default for TransferOptions {
|
||||
pburst: Burst::Single,
|
||||
mburst: Burst::Single,
|
||||
flow_ctrl: FlowControl::Dma,
|
||||
fifo_threshold: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -257,6 +273,7 @@ mod transfers {
|
||||
Transfer::new(channel)
|
||||
}
|
||||
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub(crate) struct Transfer<'a, C: Channel> {
|
||||
channel: PeripheralRef<'a, C>,
|
||||
}
|
||||
|
@ -198,6 +198,7 @@ mod eha {
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
struct ExtiInputFuture<'a> {
|
||||
pin: u8,
|
||||
phantom: PhantomData<&'a mut AnyPin>,
|
||||
|
@ -6,9 +6,6 @@ use crate::gpio::sealed::AFType;
|
||||
use crate::gpio::{Pull, Speed};
|
||||
use crate::Peripheral;
|
||||
|
||||
mod pins;
|
||||
pub use pins::*;
|
||||
|
||||
pub struct Fmc<'d, T: Instance> {
|
||||
peri: PhantomData<&'d mut T>,
|
||||
}
|
||||
@ -19,7 +16,7 @@ unsafe impl<'d, T> stm32_fmc::FmcPeripheral for Fmc<'d, T>
|
||||
where
|
||||
T: Instance,
|
||||
{
|
||||
const REGISTERS: *const () = crate::pac::FMC.0 as *const _;
|
||||
const REGISTERS: *const () = T::REGS.0 as *const _;
|
||||
|
||||
fn enable(&mut self) {
|
||||
<T as crate::rcc::sealed::RccPeripheral>::enable();
|
||||
@ -27,9 +24,13 @@ where
|
||||
}
|
||||
|
||||
fn memory_controller_enable(&mut self) {
|
||||
// The FMCEN bit of the FMC_BCR2..4 registers is don’t
|
||||
// care. It is only enabled through the FMC_BCR1 register.
|
||||
unsafe { T::regs().bcr1().modify(|r| r.set_fmcen(true)) };
|
||||
// fmc v1 and v2 does not have the fmcen bit
|
||||
// fsmc v1, v2 and v3 does not have the fmcen bit
|
||||
// This is a "not" because it is expected that all future versions have this bit
|
||||
#[cfg(not(any(fmc_v1x3, fmc_v2x1, fsmc_v1x0, fsmc_v1x3, fsmc_v2x3, fsmc_v3x1)))]
|
||||
unsafe {
|
||||
T::REGS.bcr1().modify(|r| r.set_fmcen(true))
|
||||
};
|
||||
}
|
||||
|
||||
fn source_clock_hz(&self) -> u32 {
|
||||
@ -107,6 +108,24 @@ impl<'d, T: Instance> Fmc<'d, T> {
|
||||
]
|
||||
));
|
||||
|
||||
fmc_sdram_constructor!(sdram_a12bits_d16bits_4banks_bank2: (
|
||||
bank: stm32_fmc::SdramTargetBank::Bank2,
|
||||
addr: [
|
||||
(a0: A0Pin), (a1: A1Pin), (a2: A2Pin), (a3: A3Pin), (a4: A4Pin), (a5: A5Pin), (a6: A6Pin), (a7: A7Pin), (a8: A8Pin), (a9: A9Pin), (a10: A10Pin), (a11: A11Pin)
|
||||
],
|
||||
ba: [(ba0: BA0Pin), (ba1: BA1Pin)],
|
||||
d: [
|
||||
(d0: D0Pin), (d1: D1Pin), (d2: D2Pin), (d3: D3Pin), (d4: D4Pin), (d5: D5Pin), (d6: D6Pin), (d7: D7Pin),
|
||||
(d8: D8Pin), (d9: D9Pin), (d10: D10Pin), (d11: D11Pin), (d12: D12Pin), (d13: D13Pin), (d14: D14Pin), (d15: D15Pin)
|
||||
],
|
||||
nbl: [
|
||||
(nbl0: NBL0Pin), (nbl1: NBL1Pin)
|
||||
],
|
||||
ctrl: [
|
||||
(sdcke: SDCKE1Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE1Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin)
|
||||
]
|
||||
));
|
||||
|
||||
fmc_sdram_constructor!(sdram_a12bits_d32bits_4banks_bank2: (
|
||||
bank: stm32_fmc::SdramTargetBank::Bank2,
|
||||
addr: [
|
||||
@ -128,13 +147,130 @@ impl<'d, T: Instance> Fmc<'d, T> {
|
||||
));
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
pub trait Instance: crate::rcc::sealed::RccPeripheral {
|
||||
const REGS: crate::pac::fmc::Fmc;
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Instance: sealed::Instance + 'static {}
|
||||
|
||||
foreach_peripheral!(
|
||||
(fmc, $inst:ident) => {
|
||||
impl crate::fmc::sealed::Instance for crate::peripherals::$inst {
|
||||
fn regs() -> stm32_metapac::fmc::Fmc {
|
||||
crate::pac::$inst
|
||||
}
|
||||
const REGS: crate::pac::fmc::Fmc = crate::pac::$inst;
|
||||
}
|
||||
impl crate::fmc::Instance for crate::peripherals::$inst {}
|
||||
};
|
||||
);
|
||||
|
||||
pin_trait!(SDNWEPin, Instance);
|
||||
pin_trait!(SDNCASPin, Instance);
|
||||
pin_trait!(SDNRASPin, Instance);
|
||||
|
||||
pin_trait!(SDNE0Pin, Instance);
|
||||
pin_trait!(SDNE1Pin, Instance);
|
||||
|
||||
pin_trait!(SDCKE0Pin, Instance);
|
||||
pin_trait!(SDCKE1Pin, Instance);
|
||||
|
||||
pin_trait!(SDCLKPin, Instance);
|
||||
|
||||
pin_trait!(NBL0Pin, Instance);
|
||||
pin_trait!(NBL1Pin, Instance);
|
||||
pin_trait!(NBL2Pin, Instance);
|
||||
pin_trait!(NBL3Pin, Instance);
|
||||
|
||||
pin_trait!(INTPin, Instance);
|
||||
pin_trait!(NLPin, Instance);
|
||||
pin_trait!(NWaitPin, Instance);
|
||||
|
||||
pin_trait!(NE1Pin, Instance);
|
||||
pin_trait!(NE2Pin, Instance);
|
||||
pin_trait!(NE3Pin, Instance);
|
||||
pin_trait!(NE4Pin, Instance);
|
||||
|
||||
pin_trait!(NCEPin, Instance);
|
||||
pin_trait!(NOEPin, Instance);
|
||||
pin_trait!(NWEPin, Instance);
|
||||
pin_trait!(ClkPin, Instance);
|
||||
|
||||
pin_trait!(BA0Pin, Instance);
|
||||
pin_trait!(BA1Pin, Instance);
|
||||
|
||||
pin_trait!(D0Pin, Instance);
|
||||
pin_trait!(D1Pin, Instance);
|
||||
pin_trait!(D2Pin, Instance);
|
||||
pin_trait!(D3Pin, Instance);
|
||||
pin_trait!(D4Pin, Instance);
|
||||
pin_trait!(D5Pin, Instance);
|
||||
pin_trait!(D6Pin, Instance);
|
||||
pin_trait!(D7Pin, Instance);
|
||||
pin_trait!(D8Pin, Instance);
|
||||
pin_trait!(D9Pin, Instance);
|
||||
pin_trait!(D10Pin, Instance);
|
||||
pin_trait!(D11Pin, Instance);
|
||||
pin_trait!(D12Pin, Instance);
|
||||
pin_trait!(D13Pin, Instance);
|
||||
pin_trait!(D14Pin, Instance);
|
||||
pin_trait!(D15Pin, Instance);
|
||||
pin_trait!(D16Pin, Instance);
|
||||
pin_trait!(D17Pin, Instance);
|
||||
pin_trait!(D18Pin, Instance);
|
||||
pin_trait!(D19Pin, Instance);
|
||||
pin_trait!(D20Pin, Instance);
|
||||
pin_trait!(D21Pin, Instance);
|
||||
pin_trait!(D22Pin, Instance);
|
||||
pin_trait!(D23Pin, Instance);
|
||||
pin_trait!(D24Pin, Instance);
|
||||
pin_trait!(D25Pin, Instance);
|
||||
pin_trait!(D26Pin, Instance);
|
||||
pin_trait!(D27Pin, Instance);
|
||||
pin_trait!(D28Pin, Instance);
|
||||
pin_trait!(D29Pin, Instance);
|
||||
pin_trait!(D30Pin, Instance);
|
||||
pin_trait!(D31Pin, Instance);
|
||||
|
||||
pin_trait!(DA0Pin, Instance);
|
||||
pin_trait!(DA1Pin, Instance);
|
||||
pin_trait!(DA2Pin, Instance);
|
||||
pin_trait!(DA3Pin, Instance);
|
||||
pin_trait!(DA4Pin, Instance);
|
||||
pin_trait!(DA5Pin, Instance);
|
||||
pin_trait!(DA6Pin, Instance);
|
||||
pin_trait!(DA7Pin, Instance);
|
||||
pin_trait!(DA8Pin, Instance);
|
||||
pin_trait!(DA9Pin, Instance);
|
||||
pin_trait!(DA10Pin, Instance);
|
||||
pin_trait!(DA11Pin, Instance);
|
||||
pin_trait!(DA12Pin, Instance);
|
||||
pin_trait!(DA13Pin, Instance);
|
||||
pin_trait!(DA14Pin, Instance);
|
||||
pin_trait!(DA15Pin, Instance);
|
||||
|
||||
pin_trait!(A0Pin, Instance);
|
||||
pin_trait!(A1Pin, Instance);
|
||||
pin_trait!(A2Pin, Instance);
|
||||
pin_trait!(A3Pin, Instance);
|
||||
pin_trait!(A4Pin, Instance);
|
||||
pin_trait!(A5Pin, Instance);
|
||||
pin_trait!(A6Pin, Instance);
|
||||
pin_trait!(A7Pin, Instance);
|
||||
pin_trait!(A8Pin, Instance);
|
||||
pin_trait!(A9Pin, Instance);
|
||||
pin_trait!(A10Pin, Instance);
|
||||
pin_trait!(A11Pin, Instance);
|
||||
pin_trait!(A12Pin, Instance);
|
||||
pin_trait!(A13Pin, Instance);
|
||||
pin_trait!(A14Pin, Instance);
|
||||
pin_trait!(A15Pin, Instance);
|
||||
pin_trait!(A16Pin, Instance);
|
||||
pin_trait!(A17Pin, Instance);
|
||||
pin_trait!(A18Pin, Instance);
|
||||
pin_trait!(A19Pin, Instance);
|
||||
pin_trait!(A20Pin, Instance);
|
||||
pin_trait!(A21Pin, Instance);
|
||||
pin_trait!(A22Pin, Instance);
|
||||
pin_trait!(A23Pin, Instance);
|
||||
pin_trait!(A24Pin, Instance);
|
||||
pin_trait!(A25Pin, Instance);
|
@ -1,118 +0,0 @@
|
||||
pub(crate) mod sealed {
|
||||
pub trait Instance: crate::rcc::sealed::RccPeripheral {
|
||||
fn regs() -> crate::pac::fmc::Fmc;
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Instance: sealed::Instance + 'static {}
|
||||
|
||||
pin_trait!(SDNWEPin, Instance);
|
||||
pin_trait!(SDNCASPin, Instance);
|
||||
pin_trait!(SDNRASPin, Instance);
|
||||
|
||||
pin_trait!(SDNE0Pin, Instance);
|
||||
pin_trait!(SDNE1Pin, Instance);
|
||||
|
||||
pin_trait!(SDCKE0Pin, Instance);
|
||||
pin_trait!(SDCKE1Pin, Instance);
|
||||
|
||||
pin_trait!(SDCLKPin, Instance);
|
||||
|
||||
pin_trait!(NBL0Pin, Instance);
|
||||
pin_trait!(NBL1Pin, Instance);
|
||||
pin_trait!(NBL2Pin, Instance);
|
||||
pin_trait!(NBL3Pin, Instance);
|
||||
|
||||
pin_trait!(INTPin, Instance);
|
||||
pin_trait!(NLPin, Instance);
|
||||
pin_trait!(NWaitPin, Instance);
|
||||
|
||||
pin_trait!(NE1Pin, Instance);
|
||||
pin_trait!(NE2Pin, Instance);
|
||||
pin_trait!(NE3Pin, Instance);
|
||||
pin_trait!(NE4Pin, Instance);
|
||||
|
||||
pin_trait!(NCEPin, Instance);
|
||||
pin_trait!(NOEPin, Instance);
|
||||
pin_trait!(NWEPin, Instance);
|
||||
pin_trait!(ClkPin, Instance);
|
||||
|
||||
pin_trait!(BA0Pin, Instance);
|
||||
pin_trait!(BA1Pin, Instance);
|
||||
|
||||
pin_trait!(D0Pin, Instance);
|
||||
pin_trait!(D1Pin, Instance);
|
||||
pin_trait!(D2Pin, Instance);
|
||||
pin_trait!(D3Pin, Instance);
|
||||
pin_trait!(D4Pin, Instance);
|
||||
pin_trait!(D5Pin, Instance);
|
||||
pin_trait!(D6Pin, Instance);
|
||||
pin_trait!(D7Pin, Instance);
|
||||
pin_trait!(D8Pin, Instance);
|
||||
pin_trait!(D9Pin, Instance);
|
||||
pin_trait!(D10Pin, Instance);
|
||||
pin_trait!(D11Pin, Instance);
|
||||
pin_trait!(D12Pin, Instance);
|
||||
pin_trait!(D13Pin, Instance);
|
||||
pin_trait!(D14Pin, Instance);
|
||||
pin_trait!(D15Pin, Instance);
|
||||
pin_trait!(D16Pin, Instance);
|
||||
pin_trait!(D17Pin, Instance);
|
||||
pin_trait!(D18Pin, Instance);
|
||||
pin_trait!(D19Pin, Instance);
|
||||
pin_trait!(D20Pin, Instance);
|
||||
pin_trait!(D21Pin, Instance);
|
||||
pin_trait!(D22Pin, Instance);
|
||||
pin_trait!(D23Pin, Instance);
|
||||
pin_trait!(D24Pin, Instance);
|
||||
pin_trait!(D25Pin, Instance);
|
||||
pin_trait!(D26Pin, Instance);
|
||||
pin_trait!(D27Pin, Instance);
|
||||
pin_trait!(D28Pin, Instance);
|
||||
pin_trait!(D29Pin, Instance);
|
||||
pin_trait!(D30Pin, Instance);
|
||||
pin_trait!(D31Pin, Instance);
|
||||
|
||||
pin_trait!(DA0Pin, Instance);
|
||||
pin_trait!(DA1Pin, Instance);
|
||||
pin_trait!(DA2Pin, Instance);
|
||||
pin_trait!(DA3Pin, Instance);
|
||||
pin_trait!(DA4Pin, Instance);
|
||||
pin_trait!(DA5Pin, Instance);
|
||||
pin_trait!(DA6Pin, Instance);
|
||||
pin_trait!(DA7Pin, Instance);
|
||||
pin_trait!(DA8Pin, Instance);
|
||||
pin_trait!(DA9Pin, Instance);
|
||||
pin_trait!(DA10Pin, Instance);
|
||||
pin_trait!(DA11Pin, Instance);
|
||||
pin_trait!(DA12Pin, Instance);
|
||||
pin_trait!(DA13Pin, Instance);
|
||||
pin_trait!(DA14Pin, Instance);
|
||||
pin_trait!(DA15Pin, Instance);
|
||||
|
||||
pin_trait!(A0Pin, Instance);
|
||||
pin_trait!(A1Pin, Instance);
|
||||
pin_trait!(A2Pin, Instance);
|
||||
pin_trait!(A3Pin, Instance);
|
||||
pin_trait!(A4Pin, Instance);
|
||||
pin_trait!(A5Pin, Instance);
|
||||
pin_trait!(A6Pin, Instance);
|
||||
pin_trait!(A7Pin, Instance);
|
||||
pin_trait!(A8Pin, Instance);
|
||||
pin_trait!(A9Pin, Instance);
|
||||
pin_trait!(A10Pin, Instance);
|
||||
pin_trait!(A11Pin, Instance);
|
||||
pin_trait!(A12Pin, Instance);
|
||||
pin_trait!(A13Pin, Instance);
|
||||
pin_trait!(A14Pin, Instance);
|
||||
pin_trait!(A15Pin, Instance);
|
||||
pin_trait!(A16Pin, Instance);
|
||||
pin_trait!(A17Pin, Instance);
|
||||
pin_trait!(A18Pin, Instance);
|
||||
pin_trait!(A19Pin, Instance);
|
||||
pin_trait!(A20Pin, Instance);
|
||||
pin_trait!(A21Pin, Instance);
|
||||
pin_trait!(A22Pin, Instance);
|
||||
pin_trait!(A23Pin, Instance);
|
||||
pin_trait!(A24Pin, Instance);
|
||||
pin_trait!(A25Pin, Instance);
|
@ -28,6 +28,21 @@ impl<'d, T: Pin> Flex<'d, T> {
|
||||
Self { pin }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn degrade(mut self) -> Flex<'d, AnyPin> {
|
||||
// Safety: We are about to drop the other copy of this pin, so
|
||||
// this clone is safe.
|
||||
let pin = unsafe { self.pin.clone_unchecked() };
|
||||
|
||||
// We don't want to run the destructor here, because that would
|
||||
// deconfigure the pin.
|
||||
core::mem::forget(self);
|
||||
|
||||
Flex {
|
||||
pin: pin.map_into::<AnyPin>(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Put the pin into input mode.
|
||||
#[inline]
|
||||
pub fn set_as_input(&mut self, pull: Pull) {
|
||||
@ -286,6 +301,13 @@ impl<'d, T: Pin> Input<'d, T> {
|
||||
Self { pin }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn degrade(self) -> Input<'d, AnyPin> {
|
||||
Input {
|
||||
pin: self.pin.degrade(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_high(&self) -> bool {
|
||||
self.pin.is_high()
|
||||
@ -345,6 +367,13 @@ impl<'d, T: Pin> Output<'d, T> {
|
||||
Self { pin }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn degrade(self) -> Output<'d, AnyPin> {
|
||||
Output {
|
||||
pin: self.pin.degrade(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the output as high.
|
||||
#[inline]
|
||||
pub fn set_high(&mut self) {
|
||||
@ -407,6 +436,13 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
|
||||
Self { pin }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn degrade(self) -> Output<'d, AnyPin> {
|
||||
Output {
|
||||
pin: self.pin.degrade(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_high(&self) -> bool {
|
||||
!self.pin.is_low()
|
||||
|
@ -64,7 +64,7 @@ impl Into<u8> for APBPrescaler {
|
||||
impl Into<u8> for AHBPrescaler {
|
||||
fn into(self) -> u8 {
|
||||
match self {
|
||||
AHBPrescaler::NotDivided => 1,
|
||||
AHBPrescaler::NotDivided => 0x0,
|
||||
AHBPrescaler::Div2 => 0x08,
|
||||
AHBPrescaler::Div3 => 0x01,
|
||||
AHBPrescaler::Div4 => 0x09,
|
||||
|
@ -158,7 +158,7 @@ impl Into<u8> for APBPrescaler {
|
||||
impl Into<u8> for AHBPrescaler {
|
||||
fn into(self) -> u8 {
|
||||
match self {
|
||||
AHBPrescaler::NotDivided => 1,
|
||||
AHBPrescaler::NotDivided => 0x0,
|
||||
AHBPrescaler::Div2 => 0x08,
|
||||
AHBPrescaler::Div3 => 0x01,
|
||||
AHBPrescaler::Div4 => 0x09,
|
||||
|
@ -32,6 +32,11 @@ impl<'d, T: Instance> Rng<'d, T> {
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
// rng_v2 locks up on seed error, needs reset
|
||||
#[cfg(rng_v2)]
|
||||
if unsafe { T::regs().sr().read().seis() } {
|
||||
T::reset();
|
||||
}
|
||||
unsafe {
|
||||
T::regs().cr().modify(|reg| {
|
||||
reg.set_rngen(true);
|
||||
@ -90,8 +95,10 @@ impl<'d, T: Instance> Rng<'d, T> {
|
||||
impl<'d, T: Instance> RngCore for Rng<'d, T> {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
loop {
|
||||
let bits = unsafe { T::regs().sr().read() };
|
||||
if bits.drdy() {
|
||||
let sr = unsafe { T::regs().sr().read() };
|
||||
if sr.seis() | sr.ceis() {
|
||||
self.reset();
|
||||
} else if sr.drdy() {
|
||||
return unsafe { T::regs().dr().read() };
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use core::default::Default;
|
||||
use core::future::poll_fn;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::task::Poll;
|
||||
|
||||
use embassy_hal_common::drop::OnDrop;
|
||||
@ -40,7 +41,23 @@ impl Default for Signalling {
|
||||
}
|
||||
|
||||
#[repr(align(4))]
|
||||
pub struct DataBlock([u8; 512]);
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct DataBlock(pub [u8; 512]);
|
||||
|
||||
impl Deref for DataBlock {
|
||||
type Target = [u8; 512];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for DataBlock {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors
|
||||
#[non_exhaustive]
|
||||
@ -123,10 +140,21 @@ cfg_if::cfg_if! {
|
||||
/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
|
||||
/// `sdmmc_ck` in Hertz.
|
||||
///
|
||||
/// Returns `(clk_div, clk_f)`, where `clk_div` is the divisor register
|
||||
/// value and `clk_f` is the resulting new clock frequency.
|
||||
fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(u8, Hertz), Error> {
|
||||
let clk_div = match ker_ck.0 / sdmmc_ck {
|
||||
/// Returns `(bypass, clk_div, clk_f)`, where `bypass` enables clock divisor bypass (only sdmmc_v1),
|
||||
/// `clk_div` is the divisor register value and `clk_f` is the resulting new clock frequency.
|
||||
fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> {
|
||||
// sdmmc_v1 maximum clock is 50 MHz
|
||||
if sdmmc_ck > 50_000_000 {
|
||||
return Err(Error::BadClock);
|
||||
}
|
||||
|
||||
// bypass divisor
|
||||
if ker_ck.0 <= sdmmc_ck {
|
||||
return Ok((true, 0, ker_ck));
|
||||
}
|
||||
|
||||
// `ker_ck / sdmmc_ck` rounded up
|
||||
let clk_div = match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
|
||||
0 | 1 => Ok(0),
|
||||
x @ 2..=258 => {
|
||||
Ok((x - 2) as u8)
|
||||
@ -136,22 +164,24 @@ cfg_if::cfg_if! {
|
||||
|
||||
// SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
|
||||
let clk_f = Hertz(ker_ck.0 / (clk_div as u32 + 2));
|
||||
Ok((clk_div, clk_f))
|
||||
Ok((false, clk_div, clk_f))
|
||||
}
|
||||
} else if #[cfg(sdmmc_v2)] {
|
||||
/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
|
||||
/// `sdmmc_ck` in Hertz.
|
||||
///
|
||||
/// Returns `(clk_div, clk_f)`, where `clk_div` is the divisor register
|
||||
/// value and `clk_f` is the resulting new clock frequency.
|
||||
fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(u16, Hertz), Error> {
|
||||
/// Returns `(bypass, clk_div, clk_f)`, where `bypass` enables clock divisor bypass (only sdmmc_v1),
|
||||
/// `clk_div` is the divisor register value and `clk_f` is the resulting new clock frequency.
|
||||
fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u16, Hertz), Error> {
|
||||
// `ker_ck / sdmmc_ck` rounded up
|
||||
match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
|
||||
0 | 1 => Ok((0, ker_ck)),
|
||||
0 | 1 => Ok((false, 0, ker_ck)),
|
||||
x @ 2..=2046 => {
|
||||
// SDMMC_CK frequency = SDMMCCLK / [CLKDIV + 2]
|
||||
let clk_div = ((x + 1) / 2) as u16;
|
||||
let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2));
|
||||
|
||||
Ok((clk_div, clk))
|
||||
Ok((false, clk_div, clk))
|
||||
}
|
||||
_ => Err(Error::BadClock),
|
||||
}
|
||||
@ -461,7 +491,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
||||
bus_width,
|
||||
&mut self.card,
|
||||
&mut self.signalling,
|
||||
T::frequency(),
|
||||
T::kernel_clk(),
|
||||
&mut self.clock,
|
||||
T::state(),
|
||||
self.config.data_transfer_timeout,
|
||||
@ -570,6 +600,12 @@ impl SdmmcInner {
|
||||
regs.clkcr().write(|w| {
|
||||
w.set_pwrsav(false);
|
||||
w.set_negedge(false);
|
||||
|
||||
// Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors.
|
||||
// See chip erratas for more details.
|
||||
#[cfg(sdmmc_v1)]
|
||||
w.set_hwfc_en(false);
|
||||
#[cfg(sdmmc_v2)]
|
||||
w.set_hwfc_en(true);
|
||||
|
||||
#[cfg(sdmmc_v1)]
|
||||
@ -602,7 +638,7 @@ impl SdmmcInner {
|
||||
unsafe {
|
||||
// While the SD/SDIO card or eMMC is in identification mode,
|
||||
// the SDMMC_CK frequency must be no more than 400 kHz.
|
||||
let (clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
|
||||
let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
|
||||
*clock = init_clock;
|
||||
|
||||
// CPSMACT and DPSMACT must be 0 to set WIDBUS
|
||||
@ -611,6 +647,8 @@ impl SdmmcInner {
|
||||
regs.clkcr().modify(|w| {
|
||||
w.set_widbus(0);
|
||||
w.set_clkdiv(clkdiv);
|
||||
#[cfg(sdmmc_v1)]
|
||||
w.set_bypass(_bypass);
|
||||
});
|
||||
|
||||
regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
|
||||
@ -807,10 +845,16 @@ impl SdmmcInner {
|
||||
let regs = self.0;
|
||||
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 {
|
||||
self.prepare_datapath_write(buffer as *const [u32; 128], 512, 9, data_transfer_timeout, dma);
|
||||
self.data_interrupts(true);
|
||||
}
|
||||
|
||||
#[cfg(sdmmc_v2)]
|
||||
self.cmd(Cmd::write_single_block(address), true)?;
|
||||
|
||||
let res = poll_fn(|cx| {
|
||||
@ -922,7 +966,9 @@ impl SdmmcInner {
|
||||
let request = dma.request();
|
||||
dma.start_read(request, regs.fifor().ptr() as *const u32, buffer, crate::dma::TransferOptions {
|
||||
pburst: crate::dma::Burst::Incr4,
|
||||
mburst: crate::dma::Burst::Incr4,
|
||||
flow_ctrl: crate::dma::FlowControl::Peripheral,
|
||||
fifo_threshold: Some(crate::dma::FifoThreshold::Full),
|
||||
..Default::default()
|
||||
});
|
||||
} else if #[cfg(sdmmc_v2)] {
|
||||
@ -970,7 +1016,9 @@ impl SdmmcInner {
|
||||
let request = dma.request();
|
||||
dma.start_write(request, buffer, regs.fifor().ptr() as *mut u32, crate::dma::TransferOptions {
|
||||
pburst: crate::dma::Burst::Incr4,
|
||||
mburst: crate::dma::Burst::Incr4,
|
||||
flow_ctrl: crate::dma::FlowControl::Peripheral,
|
||||
fifo_threshold: Some(crate::dma::FifoThreshold::Full),
|
||||
..Default::default()
|
||||
});
|
||||
} else if #[cfg(sdmmc_v2)] {
|
||||
@ -982,6 +1030,11 @@ impl SdmmcInner {
|
||||
regs.dctrl().modify(|w| {
|
||||
w.set_dblocksize(block_size);
|
||||
w.set_dtdir(false);
|
||||
#[cfg(sdmmc_v1)]
|
||||
{
|
||||
w.set_dmaen(true);
|
||||
w.set_dten(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1014,7 +1067,8 @@ impl SdmmcInner {
|
||||
_ => panic!("Invalid Bus Width"),
|
||||
};
|
||||
|
||||
let (clkdiv, new_clock) = clk_div(ker_ck, freq)?;
|
||||
let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?;
|
||||
|
||||
// Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
|
||||
// Section 55.5.8
|
||||
let sdmmc_bus_bandwidth = new_clock.0 * width_u32;
|
||||
@ -1025,7 +1079,11 @@ impl SdmmcInner {
|
||||
unsafe {
|
||||
// CPSMACT and DPSMACT must be 0 to set CLKDIV
|
||||
self.wait_idle();
|
||||
regs.clkcr().modify(|w| w.set_clkdiv(clkdiv));
|
||||
regs.clkcr().modify(|w| {
|
||||
w.set_clkdiv(clkdiv);
|
||||
#[cfg(sdmmc_v1)]
|
||||
w.set_bypass(_bypass);
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -1114,7 +1172,6 @@ impl SdmmcInner {
|
||||
}
|
||||
|
||||
/// Query the card status (CMD13, returns R1)
|
||||
///
|
||||
fn read_status(&self, card: &Card) -> Result<CardStatus, Error> {
|
||||
let regs = self.0;
|
||||
let rca = card.rca;
|
||||
@ -1485,6 +1542,7 @@ pub(crate) mod sealed {
|
||||
|
||||
fn inner() -> SdmmcInner;
|
||||
fn state() -> &'static AtomicWaker;
|
||||
fn kernel_clk() -> Hertz;
|
||||
}
|
||||
|
||||
pub trait Pins<T: Instance> {}
|
||||
@ -1512,6 +1570,61 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
// TODO, these could not be implemented, because required clocks are not exposed in RCC:
|
||||
// - H7 uses pll1_q_ck or pll2_r_ck depending on SDMMCSEL
|
||||
// - L1 uses pll48
|
||||
// - L4 uses clk48(pll48)
|
||||
// - L4+, L5, U5 uses clk48(pll48) or PLLSAI3CLK(PLLP) depending on SDMMCSEL
|
||||
if #[cfg(stm32f1)] {
|
||||
// F1 uses AHB1(HCLK), which is correct in PAC
|
||||
macro_rules! kernel_clk {
|
||||
($inst:ident) => {
|
||||
<peripherals::$inst as crate::rcc::sealed::RccPeripheral>::frequency()
|
||||
}
|
||||
}
|
||||
} else if #[cfg(any(stm32f2, stm32f4))] {
|
||||
// F2, F4 always use pll48
|
||||
macro_rules! kernel_clk {
|
||||
($inst:ident) => {
|
||||
critical_section::with(|_| unsafe {
|
||||
crate::rcc::get_freqs().pll48
|
||||
}).expect("PLL48 is required for SDIO")
|
||||
}
|
||||
}
|
||||
} else if #[cfg(stm32f7)] {
|
||||
macro_rules! kernel_clk {
|
||||
(SDMMC1) => {
|
||||
critical_section::with(|_| unsafe {
|
||||
let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc1sel();
|
||||
if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK {
|
||||
crate::rcc::get_freqs().sys
|
||||
} else {
|
||||
crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC")
|
||||
}
|
||||
})
|
||||
};
|
||||
(SDMMC2) => {
|
||||
critical_section::with(|_| unsafe {
|
||||
let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc2sel();
|
||||
if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK {
|
||||
crate::rcc::get_freqs().sys
|
||||
} else {
|
||||
crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC")
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Use default peripheral clock and hope it works
|
||||
macro_rules! kernel_clk {
|
||||
($inst:ident) => {
|
||||
<peripherals::$inst as crate::rcc::sealed::RccPeripheral>::frequency()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach_peripheral!(
|
||||
(sdmmc, $inst:ident) => {
|
||||
impl sealed::Instance for peripherals::$inst {
|
||||
@ -1526,13 +1639,17 @@ foreach_peripheral!(
|
||||
static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new();
|
||||
&WAKER
|
||||
}
|
||||
|
||||
fn kernel_clk() -> Hertz {
|
||||
kernel_clk!($inst)
|
||||
}
|
||||
}
|
||||
|
||||
impl Instance for peripherals::$inst {}
|
||||
};
|
||||
);
|
||||
|
||||
#[cfg(feature = "sdmmc-rs")]
|
||||
#[cfg(feature = "embedded-sdmmc")]
|
||||
mod sdmmc_rs {
|
||||
use core::future::Future;
|
||||
|
||||
@ -1540,7 +1657,7 @@ mod sdmmc_rs {
|
||||
|
||||
use super::*;
|
||||
|
||||
impl<'d, T: Instance, P: Pins<T>> BlockDevice for Sdmmc<'d, T, P> {
|
||||
impl<'d, T: Instance, Dma: SdmmcDma<T>> BlockDevice for Sdmmc<'d, T, Dma> {
|
||||
type Error = Error;
|
||||
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
|
||||
@ -1558,19 +1675,14 @@ mod sdmmc_rs {
|
||||
_reason: &str,
|
||||
) -> Self::ReadFuture<'a> {
|
||||
async move {
|
||||
let card_capacity = self.card()?.card_type;
|
||||
let inner = T::inner();
|
||||
let state = T::state();
|
||||
let mut address = start_block_idx.0;
|
||||
|
||||
for block in blocks.iter_mut() {
|
||||
let block: &mut [u8; 512] = &mut block.contents;
|
||||
|
||||
// NOTE(unsafe) Block uses align(4)
|
||||
let buf = unsafe { &mut *(block as *mut [u8; 512] as *mut [u32; 128]) };
|
||||
inner
|
||||
.read_block(address, buf, card_capacity, state, self.config.data_transfer_timeout)
|
||||
.await?;
|
||||
let block = unsafe { &mut *(block as *mut _ as *mut DataBlock) };
|
||||
self.read_block(address, block).await?;
|
||||
address += 1;
|
||||
}
|
||||
Ok(())
|
||||
@ -1579,19 +1691,14 @@ mod sdmmc_rs {
|
||||
|
||||
fn write<'a>(&'a mut self, blocks: &'a [Block], start_block_idx: BlockIdx) -> Self::WriteFuture<'a> {
|
||||
async move {
|
||||
let card = self.card.as_mut().ok_or(Error::NoCard)?;
|
||||
let inner = T::inner();
|
||||
let state = T::state();
|
||||
let mut address = start_block_idx.0;
|
||||
|
||||
for block in blocks.iter() {
|
||||
let block: &[u8; 512] = &block.contents;
|
||||
|
||||
// NOTE(unsafe) DataBlock uses align 4
|
||||
let buf = unsafe { &*(block as *const [u8; 512] as *const [u32; 128]) };
|
||||
inner
|
||||
.write_block(address, buf, card, state, self.config.data_transfer_timeout)
|
||||
.await?;
|
||||
let block = unsafe { &*(block as *const _ as *const DataBlock) };
|
||||
self.write_block(address, block).await?;
|
||||
address += 1;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -10,7 +10,7 @@ pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MO
|
||||
use self::sealed::WordSize;
|
||||
use crate::dma::{slice_ptr_parts, Transfer};
|
||||
use crate::gpio::sealed::{AFType, Pin as _};
|
||||
use crate::gpio::AnyPin;
|
||||
use crate::gpio::{AnyPin, Pull};
|
||||
use crate::pac::spi::{regs, vals, Spi as Regs};
|
||||
use crate::rcc::RccPeripheral;
|
||||
use crate::time::Hertz;
|
||||
@ -93,8 +93,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(peri, sck, mosi, miso);
|
||||
|
||||
let sck_pull_mode = match config.mode.polarity {
|
||||
Polarity::IdleLow => Pull::Down,
|
||||
Polarity::IdleHigh => Pull::Up,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
|
||||
sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode);
|
||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
|
||||
mosi.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
|
@ -770,7 +770,14 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32, enable
|
||||
|
||||
unsafe {
|
||||
r.brr().write_value(regs::Brr(div));
|
||||
r.cr2().write(|_w| {});
|
||||
r.cr2().write(|w| {
|
||||
w.set_stop(match config.stop_bits {
|
||||
StopBits::STOP0P5 => vals::Stop::STOP0P5,
|
||||
StopBits::STOP1 => vals::Stop::STOP1,
|
||||
StopBits::STOP1P5 => vals::Stop::STOP1P5,
|
||||
StopBits::STOP2 => vals::Stop::STOP2,
|
||||
});
|
||||
});
|
||||
r.cr1().write(|w| {
|
||||
// enable uart
|
||||
w.set_ue(true);
|
||||
@ -1148,7 +1155,7 @@ macro_rules! impl_lpuart {
|
||||
|
||||
foreach_interrupt!(
|
||||
($inst:ident, lpuart, $block:ident, $signal_name:ident, $irq:ident) => {
|
||||
impl_lpuart!($inst, $irq, 255);
|
||||
impl_lpuart!($inst, $irq, 256);
|
||||
};
|
||||
|
||||
($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
|
||||
|
@ -268,13 +268,13 @@ impl<'d, T: Instance> Driver<'d, T> {
|
||||
&mut self,
|
||||
ep_type: EndpointType,
|
||||
max_packet_size: u16,
|
||||
interval: u8,
|
||||
interval_ms: u8,
|
||||
) -> Result<Endpoint<'d, T, D>, driver::EndpointAllocError> {
|
||||
trace!(
|
||||
"allocating type={:?} mps={:?} interval={}, dir={:?}",
|
||||
"allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
|
||||
ep_type,
|
||||
max_packet_size,
|
||||
interval,
|
||||
interval_ms,
|
||||
D::dir()
|
||||
);
|
||||
|
||||
@ -345,7 +345,7 @@ impl<'d, T: Instance> Driver<'d, T> {
|
||||
addr: EndpointAddress::from_parts(index, D::dir()),
|
||||
ep_type,
|
||||
max_packet_size,
|
||||
interval,
|
||||
interval_ms,
|
||||
},
|
||||
buf,
|
||||
})
|
||||
@ -362,18 +362,18 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
|
||||
&mut self,
|
||||
ep_type: EndpointType,
|
||||
max_packet_size: u16,
|
||||
interval: u8,
|
||||
interval_ms: u8,
|
||||
) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
|
||||
self.alloc_endpoint(ep_type, max_packet_size, interval)
|
||||
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
|
||||
}
|
||||
|
||||
fn alloc_endpoint_out(
|
||||
&mut self,
|
||||
ep_type: EndpointType,
|
||||
max_packet_size: u16,
|
||||
interval: u8,
|
||||
interval_ms: u8,
|
||||
) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
|
||||
self.alloc_endpoint(ep_type, max_packet_size, interval)
|
||||
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
|
||||
}
|
||||
|
||||
fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
|
||||
|
@ -217,13 +217,13 @@ impl<'d, T: Instance> Driver<'d, T> {
|
||||
&mut self,
|
||||
ep_type: EndpointType,
|
||||
max_packet_size: u16,
|
||||
interval: u8,
|
||||
interval_ms: u8,
|
||||
) -> Result<Endpoint<'d, T, D>, EndpointAllocError> {
|
||||
trace!(
|
||||
"allocating type={:?} mps={:?} interval={}, dir={:?}",
|
||||
"allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
|
||||
ep_type,
|
||||
max_packet_size,
|
||||
interval,
|
||||
interval_ms,
|
||||
D::dir()
|
||||
);
|
||||
|
||||
@ -292,7 +292,7 @@ impl<'d, T: Instance> Driver<'d, T> {
|
||||
addr: EndpointAddress::from_parts(index, D::dir()),
|
||||
ep_type,
|
||||
max_packet_size,
|
||||
interval,
|
||||
interval_ms,
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -308,18 +308,18 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
|
||||
&mut self,
|
||||
ep_type: EndpointType,
|
||||
max_packet_size: u16,
|
||||
interval: u8,
|
||||
interval_ms: u8,
|
||||
) -> Result<Self::EndpointIn, EndpointAllocError> {
|
||||
self.alloc_endpoint(ep_type, max_packet_size, interval)
|
||||
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
|
||||
}
|
||||
|
||||
fn alloc_endpoint_out(
|
||||
&mut self,
|
||||
ep_type: EndpointType,
|
||||
max_packet_size: u16,
|
||||
interval: u8,
|
||||
interval_ms: u8,
|
||||
) -> Result<Self::EndpointOut, EndpointAllocError> {
|
||||
self.alloc_endpoint(ep_type, max_packet_size, interval)
|
||||
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
|
||||
}
|
||||
|
||||
fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
|
||||
|
Reference in New Issue
Block a user