stm32: move to bind_interrupts
disable lora functionality for now
This commit is contained in:
parent
627d7f66ef
commit
316be179af
3
ci.sh
3
ci.sh
@ -112,7 +112,6 @@ cargo batch \
|
|||||||
--- build --release --manifest-path examples/stm32l5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32l5 \
|
--- build --release --manifest-path examples/stm32l5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32l5 \
|
||||||
--- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32u5 \
|
--- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32u5 \
|
||||||
--- build --release --manifest-path examples/stm32wb/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wb \
|
--- build --release --manifest-path examples/stm32wb/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wb \
|
||||||
--- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wl \
|
|
||||||
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 --out-dir out/examples/boot/nrf --bin b \
|
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 --out-dir out/examples/boot/nrf --bin b \
|
||||||
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns --out-dir out/examples/boot/nrf --bin b \
|
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns --out-dir out/examples/boot/nrf --bin b \
|
||||||
--- build --release --manifest-path examples/boot/application/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/boot/rp --bin b \
|
--- build --release --manifest-path examples/boot/application/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/boot/rp --bin b \
|
||||||
@ -143,6 +142,8 @@ cargo batch \
|
|||||||
$BUILD_EXTRA
|
$BUILD_EXTRA
|
||||||
|
|
||||||
|
|
||||||
|
# --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wl \
|
||||||
|
|
||||||
function run_elf {
|
function run_elf {
|
||||||
echo Running target=$1 elf=$2
|
echo Running target=$1 elf=$2
|
||||||
STATUSCODE=$(
|
STATUSCODE=$(
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
|
use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
@ -8,7 +9,31 @@ use crate::dma::Transfer;
|
|||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::gpio::Speed;
|
use crate::gpio::Speed;
|
||||||
use crate::interrupt::{Interrupt, InterruptExt};
|
use crate::interrupt::{Interrupt, InterruptExt};
|
||||||
use crate::Peripheral;
|
use crate::{interrupt, Peripheral};
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler<T: Instance> {
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
|
unsafe fn on_interrupt() {
|
||||||
|
let ris = crate::pac::DCMI.ris().read();
|
||||||
|
if ris.err_ris() {
|
||||||
|
trace!("DCMI IRQ: Error.");
|
||||||
|
crate::pac::DCMI.ier().modify(|ier| ier.set_err_ie(false));
|
||||||
|
}
|
||||||
|
if ris.ovr_ris() {
|
||||||
|
trace!("DCMI IRQ: Overrun.");
|
||||||
|
crate::pac::DCMI.ier().modify(|ier| ier.set_ovr_ie(false));
|
||||||
|
}
|
||||||
|
if ris.frame_ris() {
|
||||||
|
trace!("DCMI IRQ: Frame captured.");
|
||||||
|
crate::pac::DCMI.ier().modify(|ier| ier.set_frame_ie(false));
|
||||||
|
}
|
||||||
|
STATE.waker.wake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The level on the VSync pin when the data is not valid on the parallel interface.
|
/// The level on the VSync pin when the data is not valid on the parallel interface.
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
@ -94,7 +119,7 @@ where
|
|||||||
pub fn new_8bit(
|
pub fn new_8bit(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
@ -108,17 +133,17 @@ where
|
|||||||
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma, irq);
|
into_ref!(peri, dma);
|
||||||
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7);
|
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7);
|
||||||
config_pins!(v_sync, h_sync, pixclk);
|
config_pins!(v_sync, h_sync, pixclk);
|
||||||
|
|
||||||
Self::new_inner(peri, dma, irq, config, false, 0b00)
|
Self::new_inner(peri, dma, config, false, 0b00)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_10bit(
|
pub fn new_10bit(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
@ -134,17 +159,17 @@ where
|
|||||||
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma, irq);
|
into_ref!(peri, dma);
|
||||||
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
|
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
|
||||||
config_pins!(v_sync, h_sync, pixclk);
|
config_pins!(v_sync, h_sync, pixclk);
|
||||||
|
|
||||||
Self::new_inner(peri, dma, irq, config, false, 0b01)
|
Self::new_inner(peri, dma, config, false, 0b01)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_12bit(
|
pub fn new_12bit(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
@ -162,17 +187,17 @@ where
|
|||||||
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma, irq);
|
into_ref!(peri, dma);
|
||||||
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
|
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
|
||||||
config_pins!(v_sync, h_sync, pixclk);
|
config_pins!(v_sync, h_sync, pixclk);
|
||||||
|
|
||||||
Self::new_inner(peri, dma, irq, config, false, 0b10)
|
Self::new_inner(peri, dma, config, false, 0b10)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_14bit(
|
pub fn new_14bit(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
@ -192,17 +217,17 @@ where
|
|||||||
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma, irq);
|
into_ref!(peri, dma);
|
||||||
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
|
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
|
||||||
config_pins!(v_sync, h_sync, pixclk);
|
config_pins!(v_sync, h_sync, pixclk);
|
||||||
|
|
||||||
Self::new_inner(peri, dma, irq, config, false, 0b11)
|
Self::new_inner(peri, dma, config, false, 0b11)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_es_8bit(
|
pub fn new_es_8bit(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
@ -214,17 +239,17 @@ where
|
|||||||
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma, irq);
|
into_ref!(peri, dma);
|
||||||
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7);
|
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7);
|
||||||
config_pins!(pixclk);
|
config_pins!(pixclk);
|
||||||
|
|
||||||
Self::new_inner(peri, dma, irq, config, true, 0b00)
|
Self::new_inner(peri, dma, config, true, 0b00)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_es_10bit(
|
pub fn new_es_10bit(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
@ -238,17 +263,17 @@ where
|
|||||||
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma, irq);
|
into_ref!(peri, dma);
|
||||||
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
|
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
|
||||||
config_pins!(pixclk);
|
config_pins!(pixclk);
|
||||||
|
|
||||||
Self::new_inner(peri, dma, irq, config, true, 0b01)
|
Self::new_inner(peri, dma, config, true, 0b01)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_es_12bit(
|
pub fn new_es_12bit(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
@ -264,17 +289,17 @@ where
|
|||||||
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma, irq);
|
into_ref!(peri, dma);
|
||||||
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
|
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
|
||||||
config_pins!(pixclk);
|
config_pins!(pixclk);
|
||||||
|
|
||||||
Self::new_inner(peri, dma, irq, config, true, 0b10)
|
Self::new_inner(peri, dma, config, true, 0b10)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_es_14bit(
|
pub fn new_es_14bit(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
@ -292,17 +317,16 @@ where
|
|||||||
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma, irq);
|
into_ref!(peri, dma);
|
||||||
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
|
config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
|
||||||
config_pins!(pixclk);
|
config_pins!(pixclk);
|
||||||
|
|
||||||
Self::new_inner(peri, dma, irq, config, true, 0b11)
|
Self::new_inner(peri, dma, config, true, 0b11)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
peri: PeripheralRef<'d, T>,
|
peri: PeripheralRef<'d, T>,
|
||||||
dma: PeripheralRef<'d, Dma>,
|
dma: PeripheralRef<'d, Dma>,
|
||||||
irq: PeripheralRef<'d, T::Interrupt>,
|
|
||||||
config: Config,
|
config: Config,
|
||||||
use_embedded_synchronization: bool,
|
use_embedded_synchronization: bool,
|
||||||
edm: u8,
|
edm: u8,
|
||||||
@ -322,30 +346,12 @@ where
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
irq.set_handler(Self::on_interrupt);
|
unsafe { T::Interrupt::steal() }.unpend();
|
||||||
irq.unpend();
|
unsafe { T::Interrupt::steal() }.enable();
|
||||||
irq.enable();
|
|
||||||
|
|
||||||
Self { inner: peri, dma }
|
Self { inner: peri, dma }
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn on_interrupt(_: *mut ()) {
|
|
||||||
let ris = crate::pac::DCMI.ris().read();
|
|
||||||
if ris.err_ris() {
|
|
||||||
trace!("DCMI IRQ: Error.");
|
|
||||||
crate::pac::DCMI.ier().modify(|ier| ier.set_err_ie(false));
|
|
||||||
}
|
|
||||||
if ris.ovr_ris() {
|
|
||||||
trace!("DCMI IRQ: Overrun.");
|
|
||||||
crate::pac::DCMI.ier().modify(|ier| ier.set_ovr_ie(false));
|
|
||||||
}
|
|
||||||
if ris.frame_ris() {
|
|
||||||
trace!("DCMI IRQ: Frame captured.");
|
|
||||||
crate::pac::DCMI.ier().modify(|ier| ier.set_frame_ie(false));
|
|
||||||
}
|
|
||||||
STATE.waker.wake();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn toggle(enable: bool) {
|
unsafe fn toggle(enable: bool) {
|
||||||
crate::pac::DCMI.cr().modify(|r| {
|
crate::pac::DCMI.cr().modify(|r| {
|
||||||
r.set_enable(enable);
|
r.set_enable(enable);
|
||||||
|
@ -11,7 +11,7 @@ use core::task::Context;
|
|||||||
use embassy_net_driver::{Capabilities, LinkState};
|
use embassy_net_driver::{Capabilities, LinkState};
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
pub use self::_version::*;
|
pub use self::_version::{InterruptHandler, *};
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
const MTU: usize = 1514;
|
const MTU: usize = 1514;
|
||||||
|
@ -5,7 +5,7 @@ mod tx_desc;
|
|||||||
|
|
||||||
use core::sync::atomic::{fence, Ordering};
|
use core::sync::atomic::{fence, Ordering};
|
||||||
|
|
||||||
use embassy_cortex_m::interrupt::InterruptExt;
|
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
|
||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf};
|
use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf};
|
||||||
|
|
||||||
@ -19,7 +19,30 @@ use crate::pac::AFIO;
|
|||||||
#[cfg(any(eth_v1b, eth_v1c))]
|
#[cfg(any(eth_v1b, eth_v1c))]
|
||||||
use crate::pac::SYSCFG;
|
use crate::pac::SYSCFG;
|
||||||
use crate::pac::{ETH, RCC};
|
use crate::pac::{ETH, RCC};
|
||||||
use crate::Peripheral;
|
use crate::{interrupt, Peripheral};
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler {}
|
||||||
|
|
||||||
|
impl interrupt::Handler<interrupt::ETH> for InterruptHandler {
|
||||||
|
unsafe fn on_interrupt() {
|
||||||
|
WAKER.wake();
|
||||||
|
|
||||||
|
// TODO: Check and clear more flags
|
||||||
|
unsafe {
|
||||||
|
let dma = ETH.ethernet_dma();
|
||||||
|
|
||||||
|
dma.dmasr().modify(|w| {
|
||||||
|
w.set_ts(true);
|
||||||
|
w.set_rs(true);
|
||||||
|
w.set_nis(true);
|
||||||
|
});
|
||||||
|
// Delay two peripheral's clock
|
||||||
|
dma.dmasr().read();
|
||||||
|
dma.dmasr().read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Ethernet<'d, T: Instance, P: PHY> {
|
pub struct Ethernet<'d, T: Instance, P: PHY> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
@ -77,7 +100,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
|||||||
pub fn new<const TX: usize, const RX: usize>(
|
pub fn new<const TX: usize, const RX: usize>(
|
||||||
queue: &'d mut PacketQueue<TX, RX>,
|
queue: &'d mut PacketQueue<TX, RX>,
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
interrupt: impl Peripheral<P = crate::interrupt::ETH> + 'd,
|
_irq: impl interrupt::Binding<interrupt::ETH, InterruptHandler> + 'd,
|
||||||
ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd,
|
ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd,
|
||||||
mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd,
|
mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd,
|
||||||
mdc: impl Peripheral<P = impl MDCPin<T>> + 'd,
|
mdc: impl Peripheral<P = impl MDCPin<T>> + 'd,
|
||||||
@ -91,7 +114,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
|||||||
mac_addr: [u8; 6],
|
mac_addr: [u8; 6],
|
||||||
phy_addr: u8,
|
phy_addr: u8,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, interrupt, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
|
into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// Enable the necessary Clocks
|
// Enable the necessary Clocks
|
||||||
@ -244,30 +267,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
|||||||
P::phy_reset(&mut this);
|
P::phy_reset(&mut this);
|
||||||
P::phy_init(&mut this);
|
P::phy_init(&mut this);
|
||||||
|
|
||||||
interrupt.set_handler(Self::on_interrupt);
|
interrupt::ETH::steal().unpend();
|
||||||
interrupt.enable();
|
interrupt::ETH::steal().enable();
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_interrupt(_cx: *mut ()) {
|
|
||||||
WAKER.wake();
|
|
||||||
|
|
||||||
// TODO: Check and clear more flags
|
|
||||||
unsafe {
|
|
||||||
let dma = ETH.ethernet_dma();
|
|
||||||
|
|
||||||
dma.dmasr().modify(|w| {
|
|
||||||
w.set_ts(true);
|
|
||||||
w.set_rs(true);
|
|
||||||
w.set_nis(true);
|
|
||||||
});
|
|
||||||
// Delay two peripheral's clock
|
|
||||||
dma.dmasr().read();
|
|
||||||
dma.dmasr().read();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> {
|
unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> {
|
||||||
|
@ -2,7 +2,7 @@ mod descriptors;
|
|||||||
|
|
||||||
use core::sync::atomic::{fence, Ordering};
|
use core::sync::atomic::{fence, Ordering};
|
||||||
|
|
||||||
use embassy_cortex_m::interrupt::InterruptExt;
|
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
|
||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
|
|
||||||
pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing};
|
pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing};
|
||||||
@ -10,7 +10,30 @@ use super::*;
|
|||||||
use crate::gpio::sealed::{AFType, Pin as _};
|
use crate::gpio::sealed::{AFType, Pin as _};
|
||||||
use crate::gpio::{AnyPin, Speed};
|
use crate::gpio::{AnyPin, Speed};
|
||||||
use crate::pac::ETH;
|
use crate::pac::ETH;
|
||||||
use crate::Peripheral;
|
use crate::{interrupt, Peripheral};
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler {}
|
||||||
|
|
||||||
|
impl interrupt::Handler<interrupt::ETH> for InterruptHandler {
|
||||||
|
unsafe fn on_interrupt() {
|
||||||
|
WAKER.wake();
|
||||||
|
|
||||||
|
// TODO: Check and clear more flags
|
||||||
|
unsafe {
|
||||||
|
let dma = ETH.ethernet_dma();
|
||||||
|
|
||||||
|
dma.dmacsr().modify(|w| {
|
||||||
|
w.set_ti(true);
|
||||||
|
w.set_ri(true);
|
||||||
|
w.set_nis(true);
|
||||||
|
});
|
||||||
|
// Delay two peripheral's clock
|
||||||
|
dma.dmacsr().read();
|
||||||
|
dma.dmacsr().read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const MTU: usize = 1514; // 14 Ethernet header + 1500 IP packet
|
const MTU: usize = 1514; // 14 Ethernet header + 1500 IP packet
|
||||||
|
|
||||||
@ -41,7 +64,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
|||||||
pub fn new<const TX: usize, const RX: usize>(
|
pub fn new<const TX: usize, const RX: usize>(
|
||||||
queue: &'d mut PacketQueue<TX, RX>,
|
queue: &'d mut PacketQueue<TX, RX>,
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
interrupt: impl Peripheral<P = crate::interrupt::ETH> + 'd,
|
_irq: impl interrupt::Binding<interrupt::ETH, InterruptHandler> + 'd,
|
||||||
ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd,
|
ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd,
|
||||||
mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd,
|
mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd,
|
||||||
mdc: impl Peripheral<P = impl MDCPin<T>> + 'd,
|
mdc: impl Peripheral<P = impl MDCPin<T>> + 'd,
|
||||||
@ -55,7 +78,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
|||||||
mac_addr: [u8; 6],
|
mac_addr: [u8; 6],
|
||||||
phy_addr: u8,
|
phy_addr: u8,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, interrupt, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
|
into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// Enable the necessary Clocks
|
// Enable the necessary Clocks
|
||||||
@ -215,30 +238,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
|||||||
P::phy_reset(&mut this);
|
P::phy_reset(&mut this);
|
||||||
P::phy_init(&mut this);
|
P::phy_init(&mut this);
|
||||||
|
|
||||||
interrupt.set_handler(Self::on_interrupt);
|
interrupt::ETH::steal().unpend();
|
||||||
interrupt.enable();
|
interrupt::ETH::steal().enable();
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_interrupt(_cx: *mut ()) {
|
|
||||||
WAKER.wake();
|
|
||||||
|
|
||||||
// TODO: Check and clear more flags
|
|
||||||
unsafe {
|
|
||||||
let dma = ETH.ethernet_dma();
|
|
||||||
|
|
||||||
dma.dmacsr().modify(|w| {
|
|
||||||
w.set_ti(true);
|
|
||||||
w.set_ri(true);
|
|
||||||
w.set_nis(true);
|
|
||||||
});
|
|
||||||
// Delay two peripheral's clock
|
|
||||||
dma.dmacsr().read();
|
|
||||||
dma.dmacsr().read();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> {
|
unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> {
|
||||||
|
@ -9,7 +9,16 @@ use crate::gpio::Pull;
|
|||||||
use crate::i2c::{Error, Instance, SclPin, SdaPin};
|
use crate::i2c::{Error, Instance, SclPin, SdaPin};
|
||||||
use crate::pac::i2c;
|
use crate::pac::i2c;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::Peripheral;
|
use crate::{interrupt, Peripheral};
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler<T: Instance> {
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
|
unsafe fn on_interrupt() {}
|
||||||
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -48,7 +57,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
_peri: impl Peripheral<P = T> + 'd,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||||
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
||||||
_irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
tx_dma: impl Peripheral<P = TXDMA> + 'd,
|
tx_dma: impl Peripheral<P = TXDMA> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RXDMA> + 'd,
|
rx_dma: impl Peripheral<P = RXDMA> + 'd,
|
||||||
freq: Hertz,
|
freq: Hertz,
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use core::cmp;
|
use core::cmp;
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
|
use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
|
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
|
||||||
use embassy_embedded_hal::SetConfig;
|
use embassy_embedded_hal::SetConfig;
|
||||||
use embassy_hal_common::drop::OnDrop;
|
use embassy_hal_common::drop::OnDrop;
|
||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
@ -11,10 +13,30 @@ use crate::dma::{NoDma, Transfer};
|
|||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::gpio::Pull;
|
use crate::gpio::Pull;
|
||||||
use crate::i2c::{Error, Instance, SclPin, SdaPin};
|
use crate::i2c::{Error, Instance, SclPin, SdaPin};
|
||||||
use crate::interrupt::InterruptExt;
|
|
||||||
use crate::pac::i2c;
|
use crate::pac::i2c;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::Peripheral;
|
use crate::{interrupt, Peripheral};
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler<T: Instance> {
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
|
unsafe fn on_interrupt() {
|
||||||
|
let regs = T::regs();
|
||||||
|
let isr = regs.isr().read();
|
||||||
|
|
||||||
|
if isr.tcr() || isr.tc() {
|
||||||
|
T::state().waker.wake();
|
||||||
|
}
|
||||||
|
// The flag can only be cleared by writting to nbytes, we won't do that here, so disable
|
||||||
|
// the interrupt
|
||||||
|
critical_section::with(|_| {
|
||||||
|
regs.cr1().modify(|w| w.set_tcie(false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -56,13 +78,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||||
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
tx_dma: impl Peripheral<P = TXDMA> + 'd,
|
tx_dma: impl Peripheral<P = TXDMA> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RXDMA> + 'd,
|
rx_dma: impl Peripheral<P = RXDMA> + 'd,
|
||||||
freq: Hertz,
|
freq: Hertz,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, irq, scl, sda, tx_dma, rx_dma);
|
into_ref!(peri, scl, sda, tx_dma, rx_dma);
|
||||||
|
|
||||||
T::enable();
|
T::enable();
|
||||||
T::reset();
|
T::reset();
|
||||||
@ -111,9 +133,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
irq.set_handler(Self::on_interrupt);
|
unsafe { T::Interrupt::steal() }.unpend();
|
||||||
irq.unpend();
|
unsafe { T::Interrupt::steal() }.enable();
|
||||||
irq.enable();
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
_peri: peri,
|
_peri: peri,
|
||||||
@ -122,20 +143,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn on_interrupt(_: *mut ()) {
|
|
||||||
let regs = T::regs();
|
|
||||||
let isr = regs.isr().read();
|
|
||||||
|
|
||||||
if isr.tcr() || isr.tc() {
|
|
||||||
T::state().waker.wake();
|
|
||||||
}
|
|
||||||
// The flag can only be cleared by writting to nbytes, we won't do that here, so disable
|
|
||||||
// the interrupt
|
|
||||||
critical_section::with(|_| {
|
|
||||||
regs.cr1().modify(|w| w.set_tcie(false));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn master_stop(&mut self) {
|
fn master_stop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
T::regs().cr2().write(|w| w.set_stop(true));
|
T::regs().cr2().write(|w| w.set_stop(true));
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
pub use critical_section::{CriticalSection, Mutex};
|
|
||||||
pub use embassy_cortex_m::interrupt::*;
|
|
||||||
|
|
||||||
pub use crate::_generated::interrupt::*;
|
|
@ -6,7 +6,6 @@ pub mod fmt;
|
|||||||
include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
pub mod interrupt;
|
|
||||||
pub mod time;
|
pub mod time;
|
||||||
mod traits;
|
mod traits;
|
||||||
|
|
||||||
@ -73,6 +72,41 @@ pub(crate) mod _generated {
|
|||||||
include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod interrupt {
|
||||||
|
//! Interrupt definitions and macros to bind them.
|
||||||
|
pub use cortex_m::interrupt::{CriticalSection, Mutex};
|
||||||
|
pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, InterruptExt, Priority};
|
||||||
|
|
||||||
|
pub use crate::_generated::interrupt::*;
|
||||||
|
|
||||||
|
/// Macro to bind interrupts to handlers.
|
||||||
|
///
|
||||||
|
/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
|
||||||
|
/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
|
||||||
|
/// prove at compile-time that the right interrupts have been bound.
|
||||||
|
// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! bind_interrupts {
|
||||||
|
($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
|
||||||
|
$vis struct $name;
|
||||||
|
|
||||||
|
$(
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn $irq() {
|
||||||
|
$(
|
||||||
|
<$handler as $crate::interrupt::Handler<$crate::interrupt::$irq>>::on_interrupt();
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
unsafe impl $crate::interrupt::Binding<$crate::interrupt::$irq, $handler> for $name {}
|
||||||
|
)*
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
pub use _generated::{peripherals, Peripherals};
|
pub use _generated::{peripherals, Peripherals};
|
||||||
pub use embassy_cortex_m::executor;
|
pub use embassy_cortex_m::executor;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
|
use core::marker::PhantomData;
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
@ -17,7 +18,36 @@ use crate::interrupt::{Interrupt, InterruptExt};
|
|||||||
use crate::pac::sdmmc::Sdmmc as RegBlock;
|
use crate::pac::sdmmc::Sdmmc as RegBlock;
|
||||||
use crate::rcc::RccPeripheral;
|
use crate::rcc::RccPeripheral;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{interrupt, peripherals, Peripheral};
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler<T: Instance> {
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> InterruptHandler<T> {
|
||||||
|
fn data_interrupts(enable: bool) {
|
||||||
|
let regs = T::regs();
|
||||||
|
// NOTE(unsafe) Atomic write
|
||||||
|
unsafe {
|
||||||
|
regs.maskr().write(|w| {
|
||||||
|
w.set_dcrcfailie(enable);
|
||||||
|
w.set_dtimeoutie(enable);
|
||||||
|
w.set_dataendie(enable);
|
||||||
|
|
||||||
|
#[cfg(sdmmc_v2)]
|
||||||
|
w.set_dabortie(enable);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
|
unsafe fn on_interrupt() {
|
||||||
|
Self::data_interrupts(false);
|
||||||
|
T::state().wake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Frequency used for SD Card initialization. Must be no higher than 400 kHz.
|
/// Frequency used for SD Card initialization. Must be no higher than 400 kHz.
|
||||||
const SD_INIT_FREQ: Hertz = Hertz(400_000);
|
const SD_INIT_FREQ: Hertz = Hertz(400_000);
|
||||||
@ -223,7 +253,6 @@ impl Default for Config {
|
|||||||
/// Sdmmc device
|
/// Sdmmc device
|
||||||
pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
|
pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
irq: PeripheralRef<'d, T::Interrupt>,
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
dma: PeripheralRef<'d, Dma>,
|
dma: PeripheralRef<'d, Dma>,
|
||||||
|
|
||||||
@ -247,7 +276,7 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
|
|||||||
impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
||||||
pub fn new_1bit(
|
pub fn new_1bit(
|
||||||
sdmmc: impl Peripheral<P = T> + 'd,
|
sdmmc: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
clk: impl Peripheral<P = impl CkPin<T>> + 'd,
|
clk: impl Peripheral<P = impl CkPin<T>> + 'd,
|
||||||
cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
|
cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
|
||||||
@ -268,7 +297,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
|||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
sdmmc,
|
sdmmc,
|
||||||
irq,
|
|
||||||
dma,
|
dma,
|
||||||
clk.map_into(),
|
clk.map_into(),
|
||||||
cmd.map_into(),
|
cmd.map_into(),
|
||||||
@ -282,7 +310,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
|||||||
|
|
||||||
pub fn new_4bit(
|
pub fn new_4bit(
|
||||||
sdmmc: impl Peripheral<P = T> + 'd,
|
sdmmc: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
clk: impl Peripheral<P = impl CkPin<T>> + 'd,
|
clk: impl Peripheral<P = impl CkPin<T>> + 'd,
|
||||||
cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
|
cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
|
||||||
@ -312,7 +340,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
|||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
sdmmc,
|
sdmmc,
|
||||||
irq,
|
|
||||||
dma,
|
dma,
|
||||||
clk.map_into(),
|
clk.map_into(),
|
||||||
cmd.map_into(),
|
cmd.map_into(),
|
||||||
@ -329,7 +356,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
|||||||
impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
|
impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
|
||||||
pub fn new_1bit(
|
pub fn new_1bit(
|
||||||
sdmmc: impl Peripheral<P = T> + 'd,
|
sdmmc: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
clk: impl Peripheral<P = impl CkPin<T>> + 'd,
|
clk: impl Peripheral<P = impl CkPin<T>> + 'd,
|
||||||
cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
|
cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
@ -349,7 +376,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
|
|||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
sdmmc,
|
sdmmc,
|
||||||
irq,
|
|
||||||
NoDma.into_ref(),
|
NoDma.into_ref(),
|
||||||
clk.map_into(),
|
clk.map_into(),
|
||||||
cmd.map_into(),
|
cmd.map_into(),
|
||||||
@ -363,7 +389,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
|
|||||||
|
|
||||||
pub fn new_4bit(
|
pub fn new_4bit(
|
||||||
sdmmc: impl Peripheral<P = T> + 'd,
|
sdmmc: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
clk: impl Peripheral<P = impl CkPin<T>> + 'd,
|
clk: impl Peripheral<P = impl CkPin<T>> + 'd,
|
||||||
cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
|
cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
@ -392,7 +418,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
|
|||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
sdmmc,
|
sdmmc,
|
||||||
irq,
|
|
||||||
NoDma.into_ref(),
|
NoDma.into_ref(),
|
||||||
clk.map_into(),
|
clk.map_into(),
|
||||||
cmd.map_into(),
|
cmd.map_into(),
|
||||||
@ -408,7 +433,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
|
|||||||
impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
sdmmc: impl Peripheral<P = T> + 'd,
|
sdmmc: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
clk: PeripheralRef<'d, AnyPin>,
|
clk: PeripheralRef<'d, AnyPin>,
|
||||||
cmd: PeripheralRef<'d, AnyPin>,
|
cmd: PeripheralRef<'d, AnyPin>,
|
||||||
@ -418,14 +442,13 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
d3: Option<PeripheralRef<'d, AnyPin>>,
|
d3: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(sdmmc, irq, dma);
|
into_ref!(sdmmc, dma);
|
||||||
|
|
||||||
T::enable();
|
T::enable();
|
||||||
T::reset();
|
T::reset();
|
||||||
|
|
||||||
irq.set_handler(Self::on_interrupt);
|
unsafe { T::Interrupt::steal() }.unpend();
|
||||||
irq.unpend();
|
unsafe { T::Interrupt::steal() }.enable();
|
||||||
irq.enable();
|
|
||||||
|
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -451,7 +474,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
_peri: sdmmc,
|
_peri: sdmmc,
|
||||||
irq,
|
|
||||||
dma,
|
dma,
|
||||||
|
|
||||||
clk,
|
clk,
|
||||||
@ -691,7 +713,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
|
let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
|
||||||
|
|
||||||
let transfer = self.prepare_datapath_read(&mut status, 64, 6);
|
let transfer = self.prepare_datapath_read(&mut status, 64, 6);
|
||||||
Self::data_interrupts(true);
|
InterruptHandler::<T>::data_interrupts(true);
|
||||||
Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6
|
Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6
|
||||||
|
|
||||||
let res = poll_fn(|cx| {
|
let res = poll_fn(|cx| {
|
||||||
@ -767,7 +789,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
|
let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
|
||||||
|
|
||||||
let transfer = self.prepare_datapath_read(&mut status, 64, 6);
|
let transfer = self.prepare_datapath_read(&mut status, 64, 6);
|
||||||
Self::data_interrupts(true);
|
InterruptHandler::<T>::data_interrupts(true);
|
||||||
Self::cmd(Cmd::card_status(0), true)?;
|
Self::cmd(Cmd::card_status(0), true)?;
|
||||||
|
|
||||||
let res = poll_fn(|cx| {
|
let res = poll_fn(|cx| {
|
||||||
@ -849,23 +871,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables the interrupts for data transfer
|
|
||||||
#[inline(always)]
|
|
||||||
fn data_interrupts(enable: bool) {
|
|
||||||
let regs = T::regs();
|
|
||||||
// NOTE(unsafe) Atomic write
|
|
||||||
unsafe {
|
|
||||||
regs.maskr().write(|w| {
|
|
||||||
w.set_dcrcfailie(enable);
|
|
||||||
w.set_dtimeoutie(enable);
|
|
||||||
w.set_dataendie(enable);
|
|
||||||
|
|
||||||
#[cfg(sdmmc_v2)]
|
|
||||||
w.set_dabortie(enable);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
|
async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
|
||||||
// Read the the 64-bit SCR register
|
// Read the the 64-bit SCR register
|
||||||
Self::cmd(Cmd::set_block_length(8), false)?; // CMD16
|
Self::cmd(Cmd::set_block_length(8), false)?; // CMD16
|
||||||
@ -878,7 +883,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
|
let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
|
||||||
|
|
||||||
let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3);
|
let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3);
|
||||||
Self::data_interrupts(true);
|
InterruptHandler::<T>::data_interrupts(true);
|
||||||
Self::cmd(Cmd::cmd51(), true)?;
|
Self::cmd(Cmd::cmd51(), true)?;
|
||||||
|
|
||||||
let res = poll_fn(|cx| {
|
let res = poll_fn(|cx| {
|
||||||
@ -996,7 +1001,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
// Wait for the abort
|
// Wait for the abort
|
||||||
while Self::data_active() {}
|
while Self::data_active() {}
|
||||||
}
|
}
|
||||||
Self::data_interrupts(false);
|
InterruptHandler::<T>::data_interrupts(false);
|
||||||
Self::clear_interrupt_flags();
|
Self::clear_interrupt_flags();
|
||||||
Self::stop_datapath();
|
Self::stop_datapath();
|
||||||
}
|
}
|
||||||
@ -1170,7 +1175,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
|
let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
|
||||||
|
|
||||||
let transfer = self.prepare_datapath_read(buffer, 512, 9);
|
let transfer = self.prepare_datapath_read(buffer, 512, 9);
|
||||||
Self::data_interrupts(true);
|
InterruptHandler::<T>::data_interrupts(true);
|
||||||
Self::cmd(Cmd::read_single_block(address), true)?;
|
Self::cmd(Cmd::read_single_block(address), true)?;
|
||||||
|
|
||||||
let res = poll_fn(|cx| {
|
let res = poll_fn(|cx| {
|
||||||
@ -1219,7 +1224,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
Self::cmd(Cmd::write_single_block(address), true)?;
|
Self::cmd(Cmd::write_single_block(address), true)?;
|
||||||
|
|
||||||
let transfer = self.prepare_datapath_write(buffer, 512, 9);
|
let transfer = self.prepare_datapath_write(buffer, 512, 9);
|
||||||
Self::data_interrupts(true);
|
InterruptHandler::<T>::data_interrupts(true);
|
||||||
|
|
||||||
#[cfg(sdmmc_v2)]
|
#[cfg(sdmmc_v2)]
|
||||||
Self::cmd(Cmd::write_single_block(address), true)?;
|
Self::cmd(Cmd::write_single_block(address), true)?;
|
||||||
@ -1279,17 +1284,11 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
pub fn clock(&self) -> Hertz {
|
pub fn clock(&self) -> Hertz {
|
||||||
self.clock
|
self.clock
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn on_interrupt(_: *mut ()) {
|
|
||||||
Self::data_interrupts(false);
|
|
||||||
T::state().wake();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> {
|
impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.irq.disable();
|
unsafe { T::Interrupt::steal() }.disable();
|
||||||
unsafe { Self::on_drop() };
|
unsafe { Self::on_drop() };
|
||||||
|
|
||||||
critical_section::with(|_| unsafe {
|
critical_section::with(|_| unsafe {
|
||||||
|
@ -4,13 +4,14 @@ use core::sync::atomic::{compiler_fence, Ordering};
|
|||||||
use core::{mem, ptr};
|
use core::{mem, ptr};
|
||||||
|
|
||||||
use atomic_polyfill::{AtomicU32, AtomicU8};
|
use atomic_polyfill::{AtomicU32, AtomicU8};
|
||||||
|
use critical_section::CriticalSection;
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::blocking_mutex::Mutex;
|
use embassy_sync::blocking_mutex::Mutex;
|
||||||
use embassy_time::driver::{AlarmHandle, Driver};
|
use embassy_time::driver::{AlarmHandle, Driver};
|
||||||
use embassy_time::TICK_HZ;
|
use embassy_time::TICK_HZ;
|
||||||
use stm32_metapac::timer::regs;
|
use stm32_metapac::timer::regs;
|
||||||
|
|
||||||
use crate::interrupt::{CriticalSection, InterruptExt};
|
use crate::interrupt::InterruptExt;
|
||||||
use crate::pac::timer::vals;
|
use crate::pac::timer::vals;
|
||||||
use crate::rcc::sealed::RccPeripheral;
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance};
|
use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
use bit_field::BitField;
|
use bit_field::BitField;
|
||||||
use embassy_cortex_m::interrupt::InterruptExt;
|
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::channel::Channel;
|
use embassy_sync::channel::Channel;
|
||||||
|
|
||||||
@ -12,7 +11,7 @@ use self::mm::MemoryManager;
|
|||||||
use self::shci::{shci_ble_init, ShciBleInitCmdParam};
|
use self::shci::{shci_ble_init, ShciBleInitCmdParam};
|
||||||
use self::sys::Sys;
|
use self::sys::Sys;
|
||||||
use self::unsafe_linked_list::LinkedListNode;
|
use self::unsafe_linked_list::LinkedListNode;
|
||||||
use crate::_generated::interrupt::{IPCC_C1_RX, IPCC_C1_TX};
|
use crate::interrupt;
|
||||||
use crate::ipcc::Ipcc;
|
use crate::ipcc::Ipcc;
|
||||||
|
|
||||||
mod ble;
|
mod ble;
|
||||||
@ -55,6 +54,19 @@ pub struct FusInfoTable {
|
|||||||
fus_info: u32,
|
fus_info: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct ReceiveInterruptHandler {}
|
||||||
|
|
||||||
|
impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler {
|
||||||
|
unsafe fn on_interrupt() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TransmitInterruptHandler {}
|
||||||
|
|
||||||
|
impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler {
|
||||||
|
unsafe fn on_interrupt() {}
|
||||||
|
}
|
||||||
|
|
||||||
/// # Version
|
/// # Version
|
||||||
/// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version
|
/// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version
|
||||||
/// - 4 -> 7 = branch - 0: Mass Market - x: ...
|
/// - 4 -> 7 = branch - 0: Mass Market - x: ...
|
||||||
@ -285,7 +297,11 @@ pub struct TlMbox {
|
|||||||
|
|
||||||
impl TlMbox {
|
impl TlMbox {
|
||||||
/// initializes low-level transport between CPU1 and BLE stack on CPU2
|
/// initializes low-level transport between CPU1 and BLE stack on CPU2
|
||||||
pub fn init(ipcc: &mut Ipcc, rx_irq: IPCC_C1_RX, tx_irq: IPCC_C1_TX) -> TlMbox {
|
pub fn init(
|
||||||
|
ipcc: &mut Ipcc,
|
||||||
|
_irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler>
|
||||||
|
+ interrupt::Binding<interrupt::IPCC_C1_TX, TransmitInterruptHandler>,
|
||||||
|
) -> TlMbox {
|
||||||
unsafe {
|
unsafe {
|
||||||
TL_REF_TABLE = MaybeUninit::new(RefTable {
|
TL_REF_TABLE = MaybeUninit::new(RefTable {
|
||||||
device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(),
|
device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(),
|
||||||
@ -326,23 +342,23 @@ impl TlMbox {
|
|||||||
let _ble = Ble::new(ipcc);
|
let _ble = Ble::new(ipcc);
|
||||||
let _mm = MemoryManager::new();
|
let _mm = MemoryManager::new();
|
||||||
|
|
||||||
rx_irq.disable();
|
// rx_irq.disable();
|
||||||
tx_irq.disable();
|
// tx_irq.disable();
|
||||||
|
//
|
||||||
rx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ());
|
// rx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ());
|
||||||
tx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ());
|
// tx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ());
|
||||||
|
//
|
||||||
rx_irq.set_handler(|ipcc| {
|
// rx_irq.set_handler(|ipcc| {
|
||||||
let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() };
|
// let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() };
|
||||||
Self::interrupt_ipcc_rx_handler(ipcc);
|
// Self::interrupt_ipcc_rx_handler(ipcc);
|
||||||
});
|
// });
|
||||||
tx_irq.set_handler(|ipcc| {
|
// tx_irq.set_handler(|ipcc| {
|
||||||
let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() };
|
// let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() };
|
||||||
Self::interrupt_ipcc_tx_handler(ipcc);
|
// Self::interrupt_ipcc_tx_handler(ipcc);
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
rx_irq.enable();
|
// rx_irq.enable();
|
||||||
tx_irq.enable();
|
// tx_irq.enable();
|
||||||
|
|
||||||
TlMbox { _sys, _ble, _mm }
|
TlMbox { _sys, _ble, _mm }
|
||||||
}
|
}
|
||||||
@ -374,6 +390,7 @@ impl TlMbox {
|
|||||||
TL_CHANNEL.recv().await
|
TL_CHANNEL.recv().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
fn interrupt_ipcc_rx_handler(ipcc: &mut Ipcc) {
|
fn interrupt_ipcc_rx_handler(ipcc: &mut Ipcc) {
|
||||||
if ipcc.is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) {
|
if ipcc.is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) {
|
||||||
sys::Sys::evt_handler(ipcc);
|
sys::Sys::evt_handler(ipcc);
|
||||||
@ -384,6 +401,7 @@ impl TlMbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
fn interrupt_ipcc_tx_handler(ipcc: &mut Ipcc) {
|
fn interrupt_ipcc_tx_handler(ipcc: &mut Ipcc) {
|
||||||
if ipcc.is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) {
|
if ipcc.is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) {
|
||||||
// TODO: handle this case
|
// TODO: handle this case
|
||||||
|
@ -8,6 +8,78 @@ use embassy_sync::waitqueue::AtomicWaker;
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler<T: BasicInstance> {
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: BasicInstance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
|
unsafe fn on_interrupt() {
|
||||||
|
let r = T::regs();
|
||||||
|
let state = T::buffered_state();
|
||||||
|
|
||||||
|
// RX
|
||||||
|
unsafe {
|
||||||
|
let sr = sr(r).read();
|
||||||
|
clear_interrupt_flags(r, sr);
|
||||||
|
|
||||||
|
if sr.rxne() {
|
||||||
|
if sr.pe() {
|
||||||
|
warn!("Parity error");
|
||||||
|
}
|
||||||
|
if sr.fe() {
|
||||||
|
warn!("Framing error");
|
||||||
|
}
|
||||||
|
if sr.ne() {
|
||||||
|
warn!("Noise error");
|
||||||
|
}
|
||||||
|
if sr.ore() {
|
||||||
|
warn!("Overrun error");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut rx_writer = state.rx_buf.writer();
|
||||||
|
let buf = rx_writer.push_slice();
|
||||||
|
if !buf.is_empty() {
|
||||||
|
// This read also clears the error and idle interrupt flags on v1.
|
||||||
|
buf[0] = rdr(r).read_volatile();
|
||||||
|
rx_writer.push_done(1);
|
||||||
|
} else {
|
||||||
|
// FIXME: Should we disable any further RX interrupts when the buffer becomes full.
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.rx_buf.is_full() {
|
||||||
|
state.rx_waker.wake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sr.idle() {
|
||||||
|
state.rx_waker.wake();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TX
|
||||||
|
unsafe {
|
||||||
|
if sr(r).read().txe() {
|
||||||
|
let mut tx_reader = state.tx_buf.reader();
|
||||||
|
let buf = tx_reader.pop_slice();
|
||||||
|
if !buf.is_empty() {
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
w.set_txeie(true);
|
||||||
|
});
|
||||||
|
tdr(r).write_volatile(buf[0].into());
|
||||||
|
tx_reader.pop_done(1);
|
||||||
|
state.tx_waker.wake();
|
||||||
|
} else {
|
||||||
|
// Disable interrupt until we have something to transmit again
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
w.set_txeie(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
rx_waker: AtomicWaker,
|
rx_waker: AtomicWaker,
|
||||||
rx_buf: RingBuffer,
|
rx_buf: RingBuffer,
|
||||||
@ -43,7 +115,7 @@ pub struct BufferedUartRx<'d, T: BasicInstance> {
|
|||||||
impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
tx_buffer: &'d mut [u8],
|
tx_buffer: &'d mut [u8],
|
||||||
@ -53,12 +125,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||||||
T::enable();
|
T::enable();
|
||||||
T::reset();
|
T::reset();
|
||||||
|
|
||||||
Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config)
|
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_rtscts(
|
pub fn new_with_rtscts(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
|
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
|
||||||
@ -81,13 +153,13 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config)
|
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||||
pub fn new_with_de(
|
pub fn new_with_de(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
de: impl Peripheral<P = impl DePin<T>> + 'd,
|
de: impl Peripheral<P = impl DePin<T>> + 'd,
|
||||||
@ -107,19 +179,18 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config)
|
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
_peri: impl Peripheral<P = T> + 'd,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
tx_buffer: &'d mut [u8],
|
tx_buffer: &'d mut [u8],
|
||||||
rx_buffer: &'d mut [u8],
|
rx_buffer: &'d mut [u8],
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> BufferedUart<'d, T> {
|
) -> BufferedUart<'d, T> {
|
||||||
into_ref!(_peri, rx, tx, irq);
|
into_ref!(_peri, rx, tx);
|
||||||
|
|
||||||
let state = T::buffered_state();
|
let state = T::buffered_state();
|
||||||
let len = tx_buffer.len();
|
let len = tx_buffer.len();
|
||||||
@ -145,9 +216,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
irq.set_handler(on_interrupt::<T>);
|
unsafe { T::Interrupt::steal() }.unpend();
|
||||||
irq.unpend();
|
unsafe { T::Interrupt::steal() }.enable();
|
||||||
irq.enable();
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
rx: BufferedUartRx { phantom: PhantomData },
|
rx: BufferedUartRx { phantom: PhantomData },
|
||||||
@ -336,71 +406,6 @@ impl<'d, T: BasicInstance> Drop for BufferedUartTx<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn on_interrupt<T: BasicInstance>(_: *mut ()) {
|
|
||||||
let r = T::regs();
|
|
||||||
let state = T::buffered_state();
|
|
||||||
|
|
||||||
// RX
|
|
||||||
unsafe {
|
|
||||||
let sr = sr(r).read();
|
|
||||||
clear_interrupt_flags(r, sr);
|
|
||||||
|
|
||||||
if sr.rxne() {
|
|
||||||
if sr.pe() {
|
|
||||||
warn!("Parity error");
|
|
||||||
}
|
|
||||||
if sr.fe() {
|
|
||||||
warn!("Framing error");
|
|
||||||
}
|
|
||||||
if sr.ne() {
|
|
||||||
warn!("Noise error");
|
|
||||||
}
|
|
||||||
if sr.ore() {
|
|
||||||
warn!("Overrun error");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut rx_writer = state.rx_buf.writer();
|
|
||||||
let buf = rx_writer.push_slice();
|
|
||||||
if !buf.is_empty() {
|
|
||||||
// This read also clears the error and idle interrupt flags on v1.
|
|
||||||
buf[0] = rdr(r).read_volatile();
|
|
||||||
rx_writer.push_done(1);
|
|
||||||
} else {
|
|
||||||
// FIXME: Should we disable any further RX interrupts when the buffer becomes full.
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.rx_buf.is_full() {
|
|
||||||
state.rx_waker.wake();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if sr.idle() {
|
|
||||||
state.rx_waker.wake();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// TX
|
|
||||||
unsafe {
|
|
||||||
if sr(r).read().txe() {
|
|
||||||
let mut tx_reader = state.tx_buf.reader();
|
|
||||||
let buf = tx_reader.pop_slice();
|
|
||||||
if !buf.is_empty() {
|
|
||||||
r.cr1().modify(|w| {
|
|
||||||
w.set_txeie(true);
|
|
||||||
});
|
|
||||||
tdr(r).write_volatile(buf[0].into());
|
|
||||||
tx_reader.pop_done(1);
|
|
||||||
state.tx_waker.wake();
|
|
||||||
} else {
|
|
||||||
// Disable interrupt until we have something to transmit again
|
|
||||||
r.cr1().modify(|w| {
|
|
||||||
w.set_txeie(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl embedded_io::Error for Error {
|
impl embedded_io::Error for Error {
|
||||||
fn kind(&self) -> embedded_io::ErrorKind {
|
fn kind(&self) -> embedded_io::ErrorKind {
|
||||||
embedded_io::ErrorKind::Other
|
embedded_io::ErrorKind::Other
|
||||||
|
@ -5,7 +5,7 @@ use core::marker::PhantomData;
|
|||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_cortex_m::interrupt::InterruptExt;
|
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
|
||||||
use embassy_hal_common::drop::OnDrop;
|
use embassy_hal_common::drop::OnDrop;
|
||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
use futures::future::{select, Either};
|
use futures::future::{select, Either};
|
||||||
@ -18,7 +18,71 @@ use crate::pac::usart::Lpuart as Regs;
|
|||||||
use crate::pac::usart::Usart as Regs;
|
use crate::pac::usart::Usart as Regs;
|
||||||
use crate::pac::usart::{regs, vals};
|
use crate::pac::usart::{regs, vals};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{interrupt, peripherals, Peripheral};
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler<T: BasicInstance> {
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: BasicInstance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
|
unsafe fn on_interrupt() {
|
||||||
|
let r = T::regs();
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
|
let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) };
|
||||||
|
|
||||||
|
let mut wake = false;
|
||||||
|
let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
|
||||||
|
if has_errors {
|
||||||
|
// clear all interrupts and DMA Rx Request
|
||||||
|
unsafe {
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
// disable RXNE interrupt
|
||||||
|
w.set_rxneie(false);
|
||||||
|
// disable parity interrupt
|
||||||
|
w.set_peie(false);
|
||||||
|
// disable idle line interrupt
|
||||||
|
w.set_idleie(false);
|
||||||
|
});
|
||||||
|
r.cr3().modify(|w| {
|
||||||
|
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||||
|
w.set_eie(false);
|
||||||
|
// disable DMA Rx Request
|
||||||
|
w.set_dmar(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
wake = true;
|
||||||
|
} else {
|
||||||
|
if cr1.idleie() && sr.idle() {
|
||||||
|
// IDLE detected: no more data will come
|
||||||
|
unsafe {
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
// disable idle line detection
|
||||||
|
w.set_idleie(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
wake = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if cr1.rxneie() {
|
||||||
|
// We cannot check the RXNE flag as it is auto-cleared by the DMA controller
|
||||||
|
|
||||||
|
// It is up to the listener to determine if this in fact was a RX event and disable the RXNE detection
|
||||||
|
|
||||||
|
wake = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if wake {
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
s.rx_waker.wake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub enum DataBits {
|
pub enum DataBits {
|
||||||
@ -215,7 +279,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
/// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power.
|
/// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
@ -223,12 +287,12 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
T::enable();
|
T::enable();
|
||||||
T::reset();
|
T::reset();
|
||||||
|
|
||||||
Self::new_inner(peri, irq, rx, rx_dma, config)
|
Self::new_inner(peri, rx, rx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_rts(
|
pub fn new_with_rts(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
|
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||||
@ -246,17 +310,16 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::new_inner(peri, irq, rx, rx_dma, config)
|
Self::new_inner(peri, rx, rx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, irq, rx, rx_dma);
|
into_ref!(peri, rx, rx_dma);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
@ -266,9 +329,8 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
|
|
||||||
configure(r, &config, T::frequency(), T::KIND, true, false);
|
configure(r, &config, T::frequency(), T::KIND, true, false);
|
||||||
|
|
||||||
irq.set_handler(Self::on_interrupt);
|
unsafe { T::Interrupt::steal() }.unpend();
|
||||||
irq.unpend();
|
unsafe { T::Interrupt::steal() }.enable();
|
||||||
irq.enable();
|
|
||||||
|
|
||||||
// create state once!
|
// create state once!
|
||||||
let _s = T::state();
|
let _s = T::state();
|
||||||
@ -282,63 +344,6 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_interrupt(_: *mut ()) {
|
|
||||||
let r = T::regs();
|
|
||||||
let s = T::state();
|
|
||||||
|
|
||||||
let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) };
|
|
||||||
|
|
||||||
let mut wake = false;
|
|
||||||
let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
|
|
||||||
if has_errors {
|
|
||||||
// clear all interrupts and DMA Rx Request
|
|
||||||
unsafe {
|
|
||||||
r.cr1().modify(|w| {
|
|
||||||
// disable RXNE interrupt
|
|
||||||
w.set_rxneie(false);
|
|
||||||
// disable parity interrupt
|
|
||||||
w.set_peie(false);
|
|
||||||
// disable idle line interrupt
|
|
||||||
w.set_idleie(false);
|
|
||||||
});
|
|
||||||
r.cr3().modify(|w| {
|
|
||||||
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
|
||||||
w.set_eie(false);
|
|
||||||
// disable DMA Rx Request
|
|
||||||
w.set_dmar(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
wake = true;
|
|
||||||
} else {
|
|
||||||
if cr1.idleie() && sr.idle() {
|
|
||||||
// IDLE detected: no more data will come
|
|
||||||
unsafe {
|
|
||||||
r.cr1().modify(|w| {
|
|
||||||
// disable idle line detection
|
|
||||||
w.set_idleie(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
wake = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if cr1.rxneie() {
|
|
||||||
// We cannot check the RXNE flag as it is auto-cleared by the DMA controller
|
|
||||||
|
|
||||||
// It is up to the listener to determine if this in fact was a RX event and disable the RXNE detection
|
|
||||||
|
|
||||||
wake = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if wake {
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
s.rx_waker.wake();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(usart_v1, usart_v2))]
|
#[cfg(any(usart_v1, usart_v2))]
|
||||||
unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> {
|
unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
@ -643,7 +648,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
@ -651,14 +656,14 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
T::enable();
|
T::enable();
|
||||||
T::reset();
|
T::reset();
|
||||||
|
|
||||||
Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
|
Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_rtscts(
|
pub fn new_with_rtscts(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
|
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
|
||||||
cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
|
cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
|
||||||
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
||||||
@ -678,7 +683,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
w.set_ctse(true);
|
w.set_ctse(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
|
Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||||
@ -686,7 +691,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
de: impl Peripheral<P = impl DePin<T>> + 'd,
|
de: impl Peripheral<P = impl DePin<T>> + 'd,
|
||||||
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||||
@ -703,19 +708,18 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
w.set_dem(true);
|
w.set_dem(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
|
Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
|
||||||
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, rx, tx, irq, tx_dma, rx_dma);
|
into_ref!(peri, rx, tx, tx_dma, rx_dma);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
@ -726,9 +730,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
|
|
||||||
configure(r, &config, T::frequency(), T::KIND, true, true);
|
configure(r, &config, T::frequency(), T::KIND, true, true);
|
||||||
|
|
||||||
irq.set_handler(UartRx::<T, RxDma>::on_interrupt);
|
unsafe { T::Interrupt::steal() }.unpend();
|
||||||
irq.unpend();
|
unsafe { T::Interrupt::steal() }.enable();
|
||||||
irq.enable();
|
|
||||||
|
|
||||||
// create state once!
|
// create state once!
|
||||||
let _s = T::state();
|
let _s = T::state();
|
||||||
@ -1068,6 +1071,9 @@ mod eio {
|
|||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
pub use buffered::*;
|
pub use buffered::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "nightly")]
|
||||||
|
pub use crate::usart::buffered::InterruptHandler as BufferedInterruptHandler;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
mod buffered;
|
mod buffered;
|
||||||
|
|
||||||
|
@ -14,12 +14,99 @@ use embassy_usb_driver::{
|
|||||||
|
|
||||||
use super::{DmPin, DpPin, Instance};
|
use super::{DmPin, DpPin, Instance};
|
||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::interrupt::InterruptExt;
|
use crate::interrupt::{Interrupt, InterruptExt};
|
||||||
use crate::pac::usb::regs;
|
use crate::pac::usb::regs;
|
||||||
use crate::pac::usb::vals::{EpType, Stat};
|
use crate::pac::usb::vals::{EpType, Stat};
|
||||||
use crate::pac::USBRAM;
|
use crate::pac::USBRAM;
|
||||||
use crate::rcc::sealed::RccPeripheral;
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
use crate::Peripheral;
|
use crate::{interrupt, Peripheral};
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler<T: Instance> {
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
|
unsafe fn on_interrupt() {
|
||||||
|
unsafe {
|
||||||
|
let regs = T::regs();
|
||||||
|
//let x = regs.istr().read().0;
|
||||||
|
//trace!("USB IRQ: {:08x}", x);
|
||||||
|
|
||||||
|
let istr = regs.istr().read();
|
||||||
|
|
||||||
|
if istr.susp() {
|
||||||
|
//trace!("USB IRQ: susp");
|
||||||
|
IRQ_SUSPEND.store(true, Ordering::Relaxed);
|
||||||
|
regs.cntr().modify(|w| {
|
||||||
|
w.set_fsusp(true);
|
||||||
|
w.set_lpmode(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Write 0 to clear.
|
||||||
|
let mut clear = regs::Istr(!0);
|
||||||
|
clear.set_susp(false);
|
||||||
|
regs.istr().write_value(clear);
|
||||||
|
|
||||||
|
// Wake main thread.
|
||||||
|
BUS_WAKER.wake();
|
||||||
|
}
|
||||||
|
|
||||||
|
if istr.wkup() {
|
||||||
|
//trace!("USB IRQ: wkup");
|
||||||
|
IRQ_RESUME.store(true, Ordering::Relaxed);
|
||||||
|
regs.cntr().modify(|w| {
|
||||||
|
w.set_fsusp(false);
|
||||||
|
w.set_lpmode(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Write 0 to clear.
|
||||||
|
let mut clear = regs::Istr(!0);
|
||||||
|
clear.set_wkup(false);
|
||||||
|
regs.istr().write_value(clear);
|
||||||
|
|
||||||
|
// Wake main thread.
|
||||||
|
BUS_WAKER.wake();
|
||||||
|
}
|
||||||
|
|
||||||
|
if istr.reset() {
|
||||||
|
//trace!("USB IRQ: reset");
|
||||||
|
IRQ_RESET.store(true, Ordering::Relaxed);
|
||||||
|
|
||||||
|
// Write 0 to clear.
|
||||||
|
let mut clear = regs::Istr(!0);
|
||||||
|
clear.set_reset(false);
|
||||||
|
regs.istr().write_value(clear);
|
||||||
|
|
||||||
|
// Wake main thread.
|
||||||
|
BUS_WAKER.wake();
|
||||||
|
}
|
||||||
|
|
||||||
|
if istr.ctr() {
|
||||||
|
let index = istr.ep_id() as usize;
|
||||||
|
let mut epr = regs.epr(index).read();
|
||||||
|
if epr.ctr_rx() {
|
||||||
|
if index == 0 && epr.setup() {
|
||||||
|
EP0_SETUP.store(true, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
//trace!("EP {} RX, setup={}", index, epr.setup());
|
||||||
|
EP_OUT_WAKERS[index].wake();
|
||||||
|
}
|
||||||
|
if epr.ctr_tx() {
|
||||||
|
//trace!("EP {} TX", index);
|
||||||
|
EP_IN_WAKERS[index].wake();
|
||||||
|
}
|
||||||
|
epr.set_dtog_rx(false);
|
||||||
|
epr.set_dtog_tx(false);
|
||||||
|
epr.set_stat_rx(Stat(0));
|
||||||
|
epr.set_stat_tx(Stat(0));
|
||||||
|
epr.set_ctr_rx(!epr.ctr_rx());
|
||||||
|
epr.set_ctr_tx(!epr.ctr_tx());
|
||||||
|
regs.epr(index).write_value(epr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const EP_COUNT: usize = 8;
|
const EP_COUNT: usize = 8;
|
||||||
|
|
||||||
@ -168,14 +255,13 @@ pub struct Driver<'d, T: Instance> {
|
|||||||
impl<'d, T: Instance> Driver<'d, T> {
|
impl<'d, T: Instance> Driver<'d, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
_usb: impl Peripheral<P = T> + 'd,
|
_usb: impl Peripheral<P = T> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
dp: impl Peripheral<P = impl DpPin<T>> + 'd,
|
dp: impl Peripheral<P = impl DpPin<T>> + 'd,
|
||||||
dm: impl Peripheral<P = impl DmPin<T>> + 'd,
|
dm: impl Peripheral<P = impl DmPin<T>> + 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(irq, dp, dm);
|
into_ref!(dp, dm);
|
||||||
irq.set_handler(Self::on_interrupt);
|
unsafe { T::Interrupt::steal() }.unpend();
|
||||||
irq.unpend();
|
unsafe { T::Interrupt::steal() }.enable();
|
||||||
irq.enable();
|
|
||||||
|
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
|
|
||||||
@ -225,86 +311,6 @@ impl<'d, T: Instance> Driver<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_interrupt(_: *mut ()) {
|
|
||||||
unsafe {
|
|
||||||
let regs = T::regs();
|
|
||||||
//let x = regs.istr().read().0;
|
|
||||||
//trace!("USB IRQ: {:08x}", x);
|
|
||||||
|
|
||||||
let istr = regs.istr().read();
|
|
||||||
|
|
||||||
if istr.susp() {
|
|
||||||
//trace!("USB IRQ: susp");
|
|
||||||
IRQ_SUSPEND.store(true, Ordering::Relaxed);
|
|
||||||
regs.cntr().modify(|w| {
|
|
||||||
w.set_fsusp(true);
|
|
||||||
w.set_lpmode(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Write 0 to clear.
|
|
||||||
let mut clear = regs::Istr(!0);
|
|
||||||
clear.set_susp(false);
|
|
||||||
regs.istr().write_value(clear);
|
|
||||||
|
|
||||||
// Wake main thread.
|
|
||||||
BUS_WAKER.wake();
|
|
||||||
}
|
|
||||||
|
|
||||||
if istr.wkup() {
|
|
||||||
//trace!("USB IRQ: wkup");
|
|
||||||
IRQ_RESUME.store(true, Ordering::Relaxed);
|
|
||||||
regs.cntr().modify(|w| {
|
|
||||||
w.set_fsusp(false);
|
|
||||||
w.set_lpmode(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Write 0 to clear.
|
|
||||||
let mut clear = regs::Istr(!0);
|
|
||||||
clear.set_wkup(false);
|
|
||||||
regs.istr().write_value(clear);
|
|
||||||
|
|
||||||
// Wake main thread.
|
|
||||||
BUS_WAKER.wake();
|
|
||||||
}
|
|
||||||
|
|
||||||
if istr.reset() {
|
|
||||||
//trace!("USB IRQ: reset");
|
|
||||||
IRQ_RESET.store(true, Ordering::Relaxed);
|
|
||||||
|
|
||||||
// Write 0 to clear.
|
|
||||||
let mut clear = regs::Istr(!0);
|
|
||||||
clear.set_reset(false);
|
|
||||||
regs.istr().write_value(clear);
|
|
||||||
|
|
||||||
// Wake main thread.
|
|
||||||
BUS_WAKER.wake();
|
|
||||||
}
|
|
||||||
|
|
||||||
if istr.ctr() {
|
|
||||||
let index = istr.ep_id() as usize;
|
|
||||||
let mut epr = regs.epr(index).read();
|
|
||||||
if epr.ctr_rx() {
|
|
||||||
if index == 0 && epr.setup() {
|
|
||||||
EP0_SETUP.store(true, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
//trace!("EP {} RX, setup={}", index, epr.setup());
|
|
||||||
EP_OUT_WAKERS[index].wake();
|
|
||||||
}
|
|
||||||
if epr.ctr_tx() {
|
|
||||||
//trace!("EP {} TX", index);
|
|
||||||
EP_IN_WAKERS[index].wake();
|
|
||||||
}
|
|
||||||
epr.set_dtog_rx(false);
|
|
||||||
epr.set_dtog_tx(false);
|
|
||||||
epr.set_stat_rx(Stat(0));
|
|
||||||
epr.set_stat_tx(Stat(0));
|
|
||||||
epr.set_ctr_rx(!epr.ctr_rx());
|
|
||||||
epr.set_ctr_tx(!epr.ctr_tx());
|
|
||||||
regs.epr(index).write_value(epr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_ep_mem(&mut self, len: u16) -> u16 {
|
fn alloc_ep_mem(&mut self, len: u16) -> u16 {
|
||||||
assert!(len as usize % USBRAM_ALIGN == 0);
|
assert!(len as usize % USBRAM_ALIGN == 0);
|
||||||
let addr = self.ep_mem_free;
|
let addr = self.ep_mem_free;
|
||||||
|
@ -4,7 +4,7 @@ use core::task::Poll;
|
|||||||
|
|
||||||
use atomic_polyfill::{AtomicBool, AtomicU16, Ordering};
|
use atomic_polyfill::{AtomicBool, AtomicU16, Ordering};
|
||||||
use embassy_cortex_m::interrupt::InterruptExt;
|
use embassy_cortex_m::interrupt::InterruptExt;
|
||||||
use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
|
use embassy_hal_common::{into_ref, Peripheral};
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
use embassy_usb_driver::{
|
use embassy_usb_driver::{
|
||||||
self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut,
|
self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut,
|
||||||
@ -14,490 +14,18 @@ use futures::future::poll_fn;
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
|
use crate::interrupt;
|
||||||
use crate::pac::otg::{regs, vals};
|
use crate::pac::otg::{regs, vals};
|
||||||
use crate::rcc::sealed::RccPeripheral;
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
|
||||||
macro_rules! config_ulpi_pins {
|
/// Interrupt handler.
|
||||||
($($pin:ident),*) => {
|
pub struct InterruptHandler<T: Instance> {
|
||||||
into_ref!($($pin),*);
|
_phantom: PhantomData<T>,
|
||||||
// NOTE(unsafe) Exclusive access to the registers
|
|
||||||
critical_section::with(|_| unsafe {
|
|
||||||
$(
|
|
||||||
$pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
|
|
||||||
#[cfg(gpio_v2)]
|
|
||||||
$pin.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
)*
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// From `synopsys-usb-otg` crate:
|
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
// This calculation doesn't correspond to one in a Reference Manual.
|
unsafe fn on_interrupt() {
|
||||||
// In fact, the required number of words is higher than indicated in RM.
|
|
||||||
// The following numbers are pessimistic and were figured out empirically.
|
|
||||||
const RX_FIFO_EXTRA_SIZE_WORDS: u16 = 30;
|
|
||||||
|
|
||||||
/// USB PHY type
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
||||||
pub enum PhyType {
|
|
||||||
/// Internal Full-Speed PHY
|
|
||||||
///
|
|
||||||
/// Available on most High-Speed peripherals.
|
|
||||||
InternalFullSpeed,
|
|
||||||
/// Internal High-Speed PHY
|
|
||||||
///
|
|
||||||
/// Available on a few STM32 chips.
|
|
||||||
InternalHighSpeed,
|
|
||||||
/// External ULPI High-Speed PHY
|
|
||||||
ExternalHighSpeed,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PhyType {
|
|
||||||
pub fn internal(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
|
|
||||||
PhyType::ExternalHighSpeed => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn high_speed(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
PhyType::InternalFullSpeed => false,
|
|
||||||
PhyType::ExternalHighSpeed | PhyType::InternalHighSpeed => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_dspd(&self) -> vals::Dspd {
|
|
||||||
match self {
|
|
||||||
PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
|
|
||||||
PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
|
|
||||||
PhyType::ExternalHighSpeed => vals::Dspd::HIGH_SPEED,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Indicates that [State::ep_out_buffers] is empty.
|
|
||||||
const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
|
|
||||||
|
|
||||||
pub struct State<const EP_COUNT: usize> {
|
|
||||||
/// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true.
|
|
||||||
ep0_setup_data: UnsafeCell<[u8; 8]>,
|
|
||||||
ep0_setup_ready: AtomicBool,
|
|
||||||
ep_in_wakers: [AtomicWaker; EP_COUNT],
|
|
||||||
ep_out_wakers: [AtomicWaker; EP_COUNT],
|
|
||||||
/// RX FIFO is shared so extra buffers are needed to dequeue all data without waiting on each endpoint.
|
|
||||||
/// Buffers are ready when associated [State::ep_out_size] != [EP_OUT_BUFFER_EMPTY].
|
|
||||||
ep_out_buffers: [UnsafeCell<*mut u8>; EP_COUNT],
|
|
||||||
ep_out_size: [AtomicU16; EP_COUNT],
|
|
||||||
bus_waker: AtomicWaker,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {}
|
|
||||||
unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
|
|
||||||
|
|
||||||
impl<const EP_COUNT: usize> State<EP_COUNT> {
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
const NEW_AW: AtomicWaker = AtomicWaker::new();
|
|
||||||
const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _);
|
|
||||||
const NEW_SIZE: AtomicU16 = AtomicU16::new(EP_OUT_BUFFER_EMPTY);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
ep0_setup_data: UnsafeCell::new([0u8; 8]),
|
|
||||||
ep0_setup_ready: AtomicBool::new(false),
|
|
||||||
ep_in_wakers: [NEW_AW; EP_COUNT],
|
|
||||||
ep_out_wakers: [NEW_AW; EP_COUNT],
|
|
||||||
ep_out_buffers: [NEW_BUF; EP_COUNT],
|
|
||||||
ep_out_size: [NEW_SIZE; EP_COUNT],
|
|
||||||
bus_waker: NEW_AW,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
struct EndpointData {
|
|
||||||
ep_type: EndpointType,
|
|
||||||
max_packet_size: u16,
|
|
||||||
fifo_size_words: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Driver<'d, T: Instance> {
|
|
||||||
phantom: PhantomData<&'d mut T>,
|
|
||||||
irq: PeripheralRef<'d, T::Interrupt>,
|
|
||||||
ep_in: [Option<EndpointData>; MAX_EP_COUNT],
|
|
||||||
ep_out: [Option<EndpointData>; MAX_EP_COUNT],
|
|
||||||
ep_out_buffer: &'d mut [u8],
|
|
||||||
ep_out_buffer_offset: usize,
|
|
||||||
phy_type: PhyType,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> Driver<'d, T> {
|
|
||||||
/// Initializes USB OTG peripheral with internal Full-Speed PHY.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `ep_out_buffer` - An internal buffer used to temporarily store recevied packets.
|
|
||||||
/// Must be large enough to fit all OUT endpoint max packet sizes.
|
|
||||||
/// Endpoint allocation will fail if it is too small.
|
|
||||||
pub fn new_fs(
|
|
||||||
_peri: impl Peripheral<P = T> + 'd,
|
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
|
||||||
dp: impl Peripheral<P = impl DpPin<T>> + 'd,
|
|
||||||
dm: impl Peripheral<P = impl DmPin<T>> + 'd,
|
|
||||||
ep_out_buffer: &'d mut [u8],
|
|
||||||
) -> Self {
|
|
||||||
into_ref!(dp, dm, irq);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
dp.set_as_af(dp.af_num(), AFType::OutputPushPull);
|
|
||||||
dm.set_as_af(dm.af_num(), AFType::OutputPushPull);
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
|
||||||
phantom: PhantomData,
|
|
||||||
irq,
|
|
||||||
ep_in: [None; MAX_EP_COUNT],
|
|
||||||
ep_out: [None; MAX_EP_COUNT],
|
|
||||||
ep_out_buffer,
|
|
||||||
ep_out_buffer_offset: 0,
|
|
||||||
phy_type: PhyType::InternalFullSpeed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initializes USB OTG peripheral with external High-Speed PHY.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `ep_out_buffer` - An internal buffer used to temporarily store recevied packets.
|
|
||||||
/// Must be large enough to fit all OUT endpoint max packet sizes.
|
|
||||||
/// Endpoint allocation will fail if it is too small.
|
|
||||||
pub fn new_hs_ulpi(
|
|
||||||
_peri: impl Peripheral<P = T> + 'd,
|
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
|
||||||
ulpi_clk: impl Peripheral<P = impl UlpiClkPin<T>> + 'd,
|
|
||||||
ulpi_dir: impl Peripheral<P = impl UlpiDirPin<T>> + 'd,
|
|
||||||
ulpi_nxt: impl Peripheral<P = impl UlpiNxtPin<T>> + 'd,
|
|
||||||
ulpi_stp: impl Peripheral<P = impl UlpiStpPin<T>> + 'd,
|
|
||||||
ulpi_d0: impl Peripheral<P = impl UlpiD0Pin<T>> + 'd,
|
|
||||||
ulpi_d1: impl Peripheral<P = impl UlpiD1Pin<T>> + 'd,
|
|
||||||
ulpi_d2: impl Peripheral<P = impl UlpiD2Pin<T>> + 'd,
|
|
||||||
ulpi_d3: impl Peripheral<P = impl UlpiD3Pin<T>> + 'd,
|
|
||||||
ulpi_d4: impl Peripheral<P = impl UlpiD4Pin<T>> + 'd,
|
|
||||||
ulpi_d5: impl Peripheral<P = impl UlpiD5Pin<T>> + 'd,
|
|
||||||
ulpi_d6: impl Peripheral<P = impl UlpiD6Pin<T>> + 'd,
|
|
||||||
ulpi_d7: impl Peripheral<P = impl UlpiD7Pin<T>> + 'd,
|
|
||||||
ep_out_buffer: &'d mut [u8],
|
|
||||||
) -> Self {
|
|
||||||
assert!(T::HIGH_SPEED == true, "Peripheral is not capable of high-speed USB");
|
|
||||||
|
|
||||||
config_ulpi_pins!(
|
|
||||||
ulpi_clk, ulpi_dir, ulpi_nxt, ulpi_stp, ulpi_d0, ulpi_d1, ulpi_d2, ulpi_d3, ulpi_d4, ulpi_d5, ulpi_d6,
|
|
||||||
ulpi_d7
|
|
||||||
);
|
|
||||||
|
|
||||||
into_ref!(irq);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
phantom: PhantomData,
|
|
||||||
irq,
|
|
||||||
ep_in: [None; MAX_EP_COUNT],
|
|
||||||
ep_out: [None; MAX_EP_COUNT],
|
|
||||||
ep_out_buffer,
|
|
||||||
ep_out_buffer_offset: 0,
|
|
||||||
phy_type: PhyType::ExternalHighSpeed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns total amount of words (u32) allocated in dedicated FIFO
|
|
||||||
fn allocated_fifo_words(&self) -> u16 {
|
|
||||||
RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out) + ep_fifo_size(&self.ep_in)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_endpoint<D: Dir>(
|
|
||||||
&mut self,
|
|
||||||
ep_type: EndpointType,
|
|
||||||
max_packet_size: u16,
|
|
||||||
interval_ms: u8,
|
|
||||||
) -> Result<Endpoint<'d, T, D>, EndpointAllocError> {
|
|
||||||
trace!(
|
|
||||||
"allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
|
|
||||||
ep_type,
|
|
||||||
max_packet_size,
|
|
||||||
interval_ms,
|
|
||||||
D::dir()
|
|
||||||
);
|
|
||||||
|
|
||||||
if D::dir() == Direction::Out {
|
|
||||||
if self.ep_out_buffer_offset + max_packet_size as usize >= self.ep_out_buffer.len() {
|
|
||||||
error!("Not enough endpoint out buffer capacity");
|
|
||||||
return Err(EndpointAllocError);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let fifo_size_words = match D::dir() {
|
|
||||||
Direction::Out => (max_packet_size + 3) / 4,
|
|
||||||
// INEPTXFD requires minimum size of 16 words
|
|
||||||
Direction::In => u16::max((max_packet_size + 3) / 4, 16),
|
|
||||||
};
|
|
||||||
|
|
||||||
if fifo_size_words + self.allocated_fifo_words() > T::FIFO_DEPTH_WORDS {
|
|
||||||
error!("Not enough FIFO capacity");
|
|
||||||
return Err(EndpointAllocError);
|
|
||||||
}
|
|
||||||
|
|
||||||
let eps = match D::dir() {
|
|
||||||
Direction::Out => &mut self.ep_out,
|
|
||||||
Direction::In => &mut self.ep_in,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find free endpoint slot
|
|
||||||
let slot = eps.iter_mut().enumerate().find(|(i, ep)| {
|
|
||||||
if *i == 0 && ep_type != EndpointType::Control {
|
|
||||||
// reserved for control pipe
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
ep.is_none()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let index = match slot {
|
|
||||||
Some((index, ep)) => {
|
|
||||||
*ep = Some(EndpointData {
|
|
||||||
ep_type,
|
|
||||||
max_packet_size,
|
|
||||||
fifo_size_words,
|
|
||||||
});
|
|
||||||
index
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
error!("No free endpoints available");
|
|
||||||
return Err(EndpointAllocError);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
trace!(" index={}", index);
|
|
||||||
|
|
||||||
if D::dir() == Direction::Out {
|
|
||||||
// Buffer capacity check was done above, now allocation cannot fail
|
|
||||||
unsafe {
|
|
||||||
*T::state().ep_out_buffers[index].get() =
|
|
||||||
self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _);
|
|
||||||
}
|
|
||||||
self.ep_out_buffer_offset += max_packet_size as usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Endpoint {
|
|
||||||
_phantom: PhantomData,
|
|
||||||
info: EndpointInfo {
|
|
||||||
addr: EndpointAddress::from_parts(index, D::dir()),
|
|
||||||
ep_type,
|
|
||||||
max_packet_size,
|
|
||||||
interval_ms,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
|
|
||||||
type EndpointOut = Endpoint<'d, T, Out>;
|
|
||||||
type EndpointIn = Endpoint<'d, T, In>;
|
|
||||||
type ControlPipe = ControlPipe<'d, T>;
|
|
||||||
type Bus = Bus<'d, T>;
|
|
||||||
|
|
||||||
fn alloc_endpoint_in(
|
|
||||||
&mut self,
|
|
||||||
ep_type: EndpointType,
|
|
||||||
max_packet_size: u16,
|
|
||||||
interval_ms: u8,
|
|
||||||
) -> Result<Self::EndpointIn, EndpointAllocError> {
|
|
||||||
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_endpoint_out(
|
|
||||||
&mut self,
|
|
||||||
ep_type: EndpointType,
|
|
||||||
max_packet_size: u16,
|
|
||||||
interval_ms: u8,
|
|
||||||
) -> Result<Self::EndpointOut, EndpointAllocError> {
|
|
||||||
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
|
|
||||||
let ep_out = self
|
|
||||||
.alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
|
|
||||||
.unwrap();
|
|
||||||
let ep_in = self
|
|
||||||
.alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(ep_out.info.addr.index(), 0);
|
|
||||||
assert_eq!(ep_in.info.addr.index(), 0);
|
|
||||||
|
|
||||||
trace!("start");
|
|
||||||
|
|
||||||
(
|
|
||||||
Bus {
|
|
||||||
phantom: PhantomData,
|
|
||||||
irq: self.irq,
|
|
||||||
ep_in: self.ep_in,
|
|
||||||
ep_out: self.ep_out,
|
|
||||||
phy_type: self.phy_type,
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
ControlPipe {
|
|
||||||
_phantom: PhantomData,
|
|
||||||
max_packet_size: control_max_packet_size,
|
|
||||||
ep_out,
|
|
||||||
ep_in,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Bus<'d, T: Instance> {
|
|
||||||
phantom: PhantomData<&'d mut T>,
|
|
||||||
irq: PeripheralRef<'d, T::Interrupt>,
|
|
||||||
ep_in: [Option<EndpointData>; MAX_EP_COUNT],
|
|
||||||
ep_out: [Option<EndpointData>; MAX_EP_COUNT],
|
|
||||||
phy_type: PhyType,
|
|
||||||
enabled: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> Bus<'d, T> {
|
|
||||||
fn restore_irqs() {
|
|
||||||
// SAFETY: atomic write
|
|
||||||
unsafe {
|
|
||||||
T::regs().gintmsk().write(|w| {
|
|
||||||
w.set_usbrst(true);
|
|
||||||
w.set_enumdnem(true);
|
|
||||||
w.set_usbsuspm(true);
|
|
||||||
w.set_wuim(true);
|
|
||||||
w.set_iepint(true);
|
|
||||||
w.set_oepint(true);
|
|
||||||
w.set_rxflvlm(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> Bus<'d, T> {
|
|
||||||
fn init_fifo(&mut self) {
|
|
||||||
trace!("init_fifo");
|
|
||||||
|
|
||||||
let r = T::regs();
|
|
||||||
|
|
||||||
// Configure RX fifo size. All endpoints share the same FIFO area.
|
|
||||||
let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out);
|
|
||||||
trace!("configuring rx fifo size={}", rx_fifo_size_words);
|
|
||||||
|
|
||||||
// SAFETY: register is exclusive to `Bus` with `&mut self`
|
|
||||||
unsafe { r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)) };
|
|
||||||
|
|
||||||
// Configure TX (USB in direction) fifo size for each endpoint
|
|
||||||
let mut fifo_top = rx_fifo_size_words;
|
|
||||||
for i in 0..T::ENDPOINT_COUNT {
|
|
||||||
if let Some(ep) = self.ep_in[i] {
|
|
||||||
trace!(
|
|
||||||
"configuring tx fifo ep={}, offset={}, size={}",
|
|
||||||
i,
|
|
||||||
fifo_top,
|
|
||||||
ep.fifo_size_words
|
|
||||||
);
|
|
||||||
|
|
||||||
let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) };
|
|
||||||
|
|
||||||
// SAFETY: register is exclusive to `Bus` with `&mut self`
|
|
||||||
unsafe {
|
|
||||||
dieptxf.write(|w| {
|
|
||||||
w.set_fd(ep.fifo_size_words);
|
|
||||||
w.set_sa(fifo_top);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fifo_top += ep.fifo_size_words;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
fifo_top <= T::FIFO_DEPTH_WORDS,
|
|
||||||
"FIFO allocations exceeded maximum capacity"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn configure_endpoints(&mut self) {
|
|
||||||
trace!("configure_endpoints");
|
|
||||||
|
|
||||||
let r = T::regs();
|
|
||||||
|
|
||||||
// Configure IN endpoints
|
|
||||||
for (index, ep) in self.ep_in.iter().enumerate() {
|
|
||||||
if let Some(ep) = ep {
|
|
||||||
// SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW
|
|
||||||
critical_section::with(|_| unsafe {
|
|
||||||
r.diepctl(index).write(|w| {
|
|
||||||
if index == 0 {
|
|
||||||
w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
|
|
||||||
} else {
|
|
||||||
w.set_mpsiz(ep.max_packet_size);
|
|
||||||
w.set_eptyp(to_eptyp(ep.ep_type));
|
|
||||||
w.set_sd0pid_sevnfrm(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure OUT endpoints
|
|
||||||
for (index, ep) in self.ep_out.iter().enumerate() {
|
|
||||||
if let Some(ep) = ep {
|
|
||||||
// SAFETY: DOEPCTL/DOEPTSIZ is shared with `Endpoint` so critical section is needed for RMW
|
|
||||||
critical_section::with(|_| unsafe {
|
|
||||||
r.doepctl(index).write(|w| {
|
|
||||||
if index == 0 {
|
|
||||||
w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
|
|
||||||
} else {
|
|
||||||
w.set_mpsiz(ep.max_packet_size);
|
|
||||||
w.set_eptyp(to_eptyp(ep.ep_type));
|
|
||||||
w.set_sd0pid_sevnfrm(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
r.doeptsiz(index).modify(|w| {
|
|
||||||
w.set_xfrsiz(ep.max_packet_size as _);
|
|
||||||
if index == 0 {
|
|
||||||
w.set_rxdpid_stupcnt(1);
|
|
||||||
} else {
|
|
||||||
w.set_pktcnt(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable IRQs for allocated endpoints
|
|
||||||
// SAFETY: register is exclusive to `Bus` with `&mut self`
|
|
||||||
unsafe {
|
|
||||||
r.daintmsk().modify(|w| {
|
|
||||||
w.set_iepm(ep_irq_mask(&self.ep_in));
|
|
||||||
// OUT interrupts not used, handled in RXFLVL
|
|
||||||
// w.set_oepm(ep_irq_mask(&self.ep_out));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn disable(&mut self) {
|
|
||||||
self.irq.disable();
|
|
||||||
self.irq.remove_handler();
|
|
||||||
|
|
||||||
<T as RccPeripheral>::disable();
|
|
||||||
|
|
||||||
#[cfg(stm32l4)]
|
|
||||||
unsafe {
|
|
||||||
crate::pac::PWR.cr2().modify(|w| w.set_usv(false));
|
|
||||||
// Cannot disable PWR, because other peripherals might be using it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_interrupt(_: *mut ()) {
|
|
||||||
trace!("irq");
|
trace!("irq");
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
let state = T::state();
|
let state = T::state();
|
||||||
@ -641,6 +169,478 @@ impl<'d, T: Instance> Bus<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! config_ulpi_pins {
|
||||||
|
($($pin:ident),*) => {
|
||||||
|
into_ref!($($pin),*);
|
||||||
|
// NOTE(unsafe) Exclusive access to the registers
|
||||||
|
critical_section::with(|_| unsafe {
|
||||||
|
$(
|
||||||
|
$pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
|
||||||
|
#[cfg(gpio_v2)]
|
||||||
|
$pin.set_speed(crate::gpio::Speed::VeryHigh);
|
||||||
|
)*
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// From `synopsys-usb-otg` crate:
|
||||||
|
// This calculation doesn't correspond to one in a Reference Manual.
|
||||||
|
// In fact, the required number of words is higher than indicated in RM.
|
||||||
|
// The following numbers are pessimistic and were figured out empirically.
|
||||||
|
const RX_FIFO_EXTRA_SIZE_WORDS: u16 = 30;
|
||||||
|
|
||||||
|
/// USB PHY type
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum PhyType {
|
||||||
|
/// Internal Full-Speed PHY
|
||||||
|
///
|
||||||
|
/// Available on most High-Speed peripherals.
|
||||||
|
InternalFullSpeed,
|
||||||
|
/// Internal High-Speed PHY
|
||||||
|
///
|
||||||
|
/// Available on a few STM32 chips.
|
||||||
|
InternalHighSpeed,
|
||||||
|
/// External ULPI High-Speed PHY
|
||||||
|
ExternalHighSpeed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhyType {
|
||||||
|
pub fn internal(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
|
||||||
|
PhyType::ExternalHighSpeed => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn high_speed(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
PhyType::InternalFullSpeed => false,
|
||||||
|
PhyType::ExternalHighSpeed | PhyType::InternalHighSpeed => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_dspd(&self) -> vals::Dspd {
|
||||||
|
match self {
|
||||||
|
PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
|
||||||
|
PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
|
||||||
|
PhyType::ExternalHighSpeed => vals::Dspd::HIGH_SPEED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Indicates that [State::ep_out_buffers] is empty.
|
||||||
|
const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
|
||||||
|
|
||||||
|
pub struct State<const EP_COUNT: usize> {
|
||||||
|
/// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true.
|
||||||
|
ep0_setup_data: UnsafeCell<[u8; 8]>,
|
||||||
|
ep0_setup_ready: AtomicBool,
|
||||||
|
ep_in_wakers: [AtomicWaker; EP_COUNT],
|
||||||
|
ep_out_wakers: [AtomicWaker; EP_COUNT],
|
||||||
|
/// RX FIFO is shared so extra buffers are needed to dequeue all data without waiting on each endpoint.
|
||||||
|
/// Buffers are ready when associated [State::ep_out_size] != [EP_OUT_BUFFER_EMPTY].
|
||||||
|
ep_out_buffers: [UnsafeCell<*mut u8>; EP_COUNT],
|
||||||
|
ep_out_size: [AtomicU16; EP_COUNT],
|
||||||
|
bus_waker: AtomicWaker,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {}
|
||||||
|
unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
|
||||||
|
|
||||||
|
impl<const EP_COUNT: usize> State<EP_COUNT> {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
const NEW_AW: AtomicWaker = AtomicWaker::new();
|
||||||
|
const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _);
|
||||||
|
const NEW_SIZE: AtomicU16 = AtomicU16::new(EP_OUT_BUFFER_EMPTY);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
ep0_setup_data: UnsafeCell::new([0u8; 8]),
|
||||||
|
ep0_setup_ready: AtomicBool::new(false),
|
||||||
|
ep_in_wakers: [NEW_AW; EP_COUNT],
|
||||||
|
ep_out_wakers: [NEW_AW; EP_COUNT],
|
||||||
|
ep_out_buffers: [NEW_BUF; EP_COUNT],
|
||||||
|
ep_out_size: [NEW_SIZE; EP_COUNT],
|
||||||
|
bus_waker: NEW_AW,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct EndpointData {
|
||||||
|
ep_type: EndpointType,
|
||||||
|
max_packet_size: u16,
|
||||||
|
fifo_size_words: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Driver<'d, T: Instance> {
|
||||||
|
phantom: PhantomData<&'d mut T>,
|
||||||
|
ep_in: [Option<EndpointData>; MAX_EP_COUNT],
|
||||||
|
ep_out: [Option<EndpointData>; MAX_EP_COUNT],
|
||||||
|
ep_out_buffer: &'d mut [u8],
|
||||||
|
ep_out_buffer_offset: usize,
|
||||||
|
phy_type: PhyType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> Driver<'d, T> {
|
||||||
|
/// Initializes USB OTG peripheral with internal Full-Speed PHY.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `ep_out_buffer` - An internal buffer used to temporarily store recevied packets.
|
||||||
|
/// Must be large enough to fit all OUT endpoint max packet sizes.
|
||||||
|
/// Endpoint allocation will fail if it is too small.
|
||||||
|
pub fn new_fs(
|
||||||
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
|
dp: impl Peripheral<P = impl DpPin<T>> + 'd,
|
||||||
|
dm: impl Peripheral<P = impl DmPin<T>> + 'd,
|
||||||
|
ep_out_buffer: &'d mut [u8],
|
||||||
|
) -> Self {
|
||||||
|
into_ref!(dp, dm);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
dp.set_as_af(dp.af_num(), AFType::OutputPushPull);
|
||||||
|
dm.set_as_af(dm.af_num(), AFType::OutputPushPull);
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
phantom: PhantomData,
|
||||||
|
ep_in: [None; MAX_EP_COUNT],
|
||||||
|
ep_out: [None; MAX_EP_COUNT],
|
||||||
|
ep_out_buffer,
|
||||||
|
ep_out_buffer_offset: 0,
|
||||||
|
phy_type: PhyType::InternalFullSpeed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes USB OTG peripheral with external High-Speed PHY.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `ep_out_buffer` - An internal buffer used to temporarily store recevied packets.
|
||||||
|
/// Must be large enough to fit all OUT endpoint max packet sizes.
|
||||||
|
/// Endpoint allocation will fail if it is too small.
|
||||||
|
pub fn new_hs_ulpi(
|
||||||
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
|
ulpi_clk: impl Peripheral<P = impl UlpiClkPin<T>> + 'd,
|
||||||
|
ulpi_dir: impl Peripheral<P = impl UlpiDirPin<T>> + 'd,
|
||||||
|
ulpi_nxt: impl Peripheral<P = impl UlpiNxtPin<T>> + 'd,
|
||||||
|
ulpi_stp: impl Peripheral<P = impl UlpiStpPin<T>> + 'd,
|
||||||
|
ulpi_d0: impl Peripheral<P = impl UlpiD0Pin<T>> + 'd,
|
||||||
|
ulpi_d1: impl Peripheral<P = impl UlpiD1Pin<T>> + 'd,
|
||||||
|
ulpi_d2: impl Peripheral<P = impl UlpiD2Pin<T>> + 'd,
|
||||||
|
ulpi_d3: impl Peripheral<P = impl UlpiD3Pin<T>> + 'd,
|
||||||
|
ulpi_d4: impl Peripheral<P = impl UlpiD4Pin<T>> + 'd,
|
||||||
|
ulpi_d5: impl Peripheral<P = impl UlpiD5Pin<T>> + 'd,
|
||||||
|
ulpi_d6: impl Peripheral<P = impl UlpiD6Pin<T>> + 'd,
|
||||||
|
ulpi_d7: impl Peripheral<P = impl UlpiD7Pin<T>> + 'd,
|
||||||
|
ep_out_buffer: &'d mut [u8],
|
||||||
|
) -> Self {
|
||||||
|
assert!(T::HIGH_SPEED == true, "Peripheral is not capable of high-speed USB");
|
||||||
|
|
||||||
|
config_ulpi_pins!(
|
||||||
|
ulpi_clk, ulpi_dir, ulpi_nxt, ulpi_stp, ulpi_d0, ulpi_d1, ulpi_d2, ulpi_d3, ulpi_d4, ulpi_d5, ulpi_d6,
|
||||||
|
ulpi_d7
|
||||||
|
);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
phantom: PhantomData,
|
||||||
|
ep_in: [None; MAX_EP_COUNT],
|
||||||
|
ep_out: [None; MAX_EP_COUNT],
|
||||||
|
ep_out_buffer,
|
||||||
|
ep_out_buffer_offset: 0,
|
||||||
|
phy_type: PhyType::ExternalHighSpeed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns total amount of words (u32) allocated in dedicated FIFO
|
||||||
|
fn allocated_fifo_words(&self) -> u16 {
|
||||||
|
RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out) + ep_fifo_size(&self.ep_in)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc_endpoint<D: Dir>(
|
||||||
|
&mut self,
|
||||||
|
ep_type: EndpointType,
|
||||||
|
max_packet_size: u16,
|
||||||
|
interval_ms: u8,
|
||||||
|
) -> Result<Endpoint<'d, T, D>, EndpointAllocError> {
|
||||||
|
trace!(
|
||||||
|
"allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
|
||||||
|
ep_type,
|
||||||
|
max_packet_size,
|
||||||
|
interval_ms,
|
||||||
|
D::dir()
|
||||||
|
);
|
||||||
|
|
||||||
|
if D::dir() == Direction::Out {
|
||||||
|
if self.ep_out_buffer_offset + max_packet_size as usize >= self.ep_out_buffer.len() {
|
||||||
|
error!("Not enough endpoint out buffer capacity");
|
||||||
|
return Err(EndpointAllocError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let fifo_size_words = match D::dir() {
|
||||||
|
Direction::Out => (max_packet_size + 3) / 4,
|
||||||
|
// INEPTXFD requires minimum size of 16 words
|
||||||
|
Direction::In => u16::max((max_packet_size + 3) / 4, 16),
|
||||||
|
};
|
||||||
|
|
||||||
|
if fifo_size_words + self.allocated_fifo_words() > T::FIFO_DEPTH_WORDS {
|
||||||
|
error!("Not enough FIFO capacity");
|
||||||
|
return Err(EndpointAllocError);
|
||||||
|
}
|
||||||
|
|
||||||
|
let eps = match D::dir() {
|
||||||
|
Direction::Out => &mut self.ep_out,
|
||||||
|
Direction::In => &mut self.ep_in,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find free endpoint slot
|
||||||
|
let slot = eps.iter_mut().enumerate().find(|(i, ep)| {
|
||||||
|
if *i == 0 && ep_type != EndpointType::Control {
|
||||||
|
// reserved for control pipe
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
ep.is_none()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let index = match slot {
|
||||||
|
Some((index, ep)) => {
|
||||||
|
*ep = Some(EndpointData {
|
||||||
|
ep_type,
|
||||||
|
max_packet_size,
|
||||||
|
fifo_size_words,
|
||||||
|
});
|
||||||
|
index
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
error!("No free endpoints available");
|
||||||
|
return Err(EndpointAllocError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
trace!(" index={}", index);
|
||||||
|
|
||||||
|
if D::dir() == Direction::Out {
|
||||||
|
// Buffer capacity check was done above, now allocation cannot fail
|
||||||
|
unsafe {
|
||||||
|
*T::state().ep_out_buffers[index].get() =
|
||||||
|
self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _);
|
||||||
|
}
|
||||||
|
self.ep_out_buffer_offset += max_packet_size as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Endpoint {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
info: EndpointInfo {
|
||||||
|
addr: EndpointAddress::from_parts(index, D::dir()),
|
||||||
|
ep_type,
|
||||||
|
max_packet_size,
|
||||||
|
interval_ms,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
|
||||||
|
type EndpointOut = Endpoint<'d, T, Out>;
|
||||||
|
type EndpointIn = Endpoint<'d, T, In>;
|
||||||
|
type ControlPipe = ControlPipe<'d, T>;
|
||||||
|
type Bus = Bus<'d, T>;
|
||||||
|
|
||||||
|
fn alloc_endpoint_in(
|
||||||
|
&mut self,
|
||||||
|
ep_type: EndpointType,
|
||||||
|
max_packet_size: u16,
|
||||||
|
interval_ms: u8,
|
||||||
|
) -> Result<Self::EndpointIn, EndpointAllocError> {
|
||||||
|
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc_endpoint_out(
|
||||||
|
&mut self,
|
||||||
|
ep_type: EndpointType,
|
||||||
|
max_packet_size: u16,
|
||||||
|
interval_ms: u8,
|
||||||
|
) -> Result<Self::EndpointOut, EndpointAllocError> {
|
||||||
|
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
|
||||||
|
let ep_out = self
|
||||||
|
.alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
|
||||||
|
.unwrap();
|
||||||
|
let ep_in = self
|
||||||
|
.alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(ep_out.info.addr.index(), 0);
|
||||||
|
assert_eq!(ep_in.info.addr.index(), 0);
|
||||||
|
|
||||||
|
trace!("start");
|
||||||
|
|
||||||
|
(
|
||||||
|
Bus {
|
||||||
|
phantom: PhantomData,
|
||||||
|
ep_in: self.ep_in,
|
||||||
|
ep_out: self.ep_out,
|
||||||
|
phy_type: self.phy_type,
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
ControlPipe {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
max_packet_size: control_max_packet_size,
|
||||||
|
ep_out,
|
||||||
|
ep_in,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Bus<'d, T: Instance> {
|
||||||
|
phantom: PhantomData<&'d mut T>,
|
||||||
|
ep_in: [Option<EndpointData>; MAX_EP_COUNT],
|
||||||
|
ep_out: [Option<EndpointData>; MAX_EP_COUNT],
|
||||||
|
phy_type: PhyType,
|
||||||
|
enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> Bus<'d, T> {
|
||||||
|
fn restore_irqs() {
|
||||||
|
// SAFETY: atomic write
|
||||||
|
unsafe {
|
||||||
|
T::regs().gintmsk().write(|w| {
|
||||||
|
w.set_usbrst(true);
|
||||||
|
w.set_enumdnem(true);
|
||||||
|
w.set_usbsuspm(true);
|
||||||
|
w.set_wuim(true);
|
||||||
|
w.set_iepint(true);
|
||||||
|
w.set_oepint(true);
|
||||||
|
w.set_rxflvlm(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> Bus<'d, T> {
|
||||||
|
fn init_fifo(&mut self) {
|
||||||
|
trace!("init_fifo");
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
|
||||||
|
// Configure RX fifo size. All endpoints share the same FIFO area.
|
||||||
|
let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out);
|
||||||
|
trace!("configuring rx fifo size={}", rx_fifo_size_words);
|
||||||
|
|
||||||
|
// SAFETY: register is exclusive to `Bus` with `&mut self`
|
||||||
|
unsafe { r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)) };
|
||||||
|
|
||||||
|
// Configure TX (USB in direction) fifo size for each endpoint
|
||||||
|
let mut fifo_top = rx_fifo_size_words;
|
||||||
|
for i in 0..T::ENDPOINT_COUNT {
|
||||||
|
if let Some(ep) = self.ep_in[i] {
|
||||||
|
trace!(
|
||||||
|
"configuring tx fifo ep={}, offset={}, size={}",
|
||||||
|
i,
|
||||||
|
fifo_top,
|
||||||
|
ep.fifo_size_words
|
||||||
|
);
|
||||||
|
|
||||||
|
let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) };
|
||||||
|
|
||||||
|
// SAFETY: register is exclusive to `Bus` with `&mut self`
|
||||||
|
unsafe {
|
||||||
|
dieptxf.write(|w| {
|
||||||
|
w.set_fd(ep.fifo_size_words);
|
||||||
|
w.set_sa(fifo_top);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fifo_top += ep.fifo_size_words;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
fifo_top <= T::FIFO_DEPTH_WORDS,
|
||||||
|
"FIFO allocations exceeded maximum capacity"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configure_endpoints(&mut self) {
|
||||||
|
trace!("configure_endpoints");
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
|
||||||
|
// Configure IN endpoints
|
||||||
|
for (index, ep) in self.ep_in.iter().enumerate() {
|
||||||
|
if let Some(ep) = ep {
|
||||||
|
// SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW
|
||||||
|
critical_section::with(|_| unsafe {
|
||||||
|
r.diepctl(index).write(|w| {
|
||||||
|
if index == 0 {
|
||||||
|
w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
|
||||||
|
} else {
|
||||||
|
w.set_mpsiz(ep.max_packet_size);
|
||||||
|
w.set_eptyp(to_eptyp(ep.ep_type));
|
||||||
|
w.set_sd0pid_sevnfrm(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure OUT endpoints
|
||||||
|
for (index, ep) in self.ep_out.iter().enumerate() {
|
||||||
|
if let Some(ep) = ep {
|
||||||
|
// SAFETY: DOEPCTL/DOEPTSIZ is shared with `Endpoint` so critical section is needed for RMW
|
||||||
|
critical_section::with(|_| unsafe {
|
||||||
|
r.doepctl(index).write(|w| {
|
||||||
|
if index == 0 {
|
||||||
|
w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
|
||||||
|
} else {
|
||||||
|
w.set_mpsiz(ep.max_packet_size);
|
||||||
|
w.set_eptyp(to_eptyp(ep.ep_type));
|
||||||
|
w.set_sd0pid_sevnfrm(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
r.doeptsiz(index).modify(|w| {
|
||||||
|
w.set_xfrsiz(ep.max_packet_size as _);
|
||||||
|
if index == 0 {
|
||||||
|
w.set_rxdpid_stupcnt(1);
|
||||||
|
} else {
|
||||||
|
w.set_pktcnt(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable IRQs for allocated endpoints
|
||||||
|
// SAFETY: register is exclusive to `Bus` with `&mut self`
|
||||||
|
unsafe {
|
||||||
|
r.daintmsk().modify(|w| {
|
||||||
|
w.set_iepm(ep_irq_mask(&self.ep_in));
|
||||||
|
// OUT interrupts not used, handled in RXFLVL
|
||||||
|
// w.set_oepm(ep_irq_mask(&self.ep_out));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disable(&mut self) {
|
||||||
|
unsafe { T::Interrupt::steal() }.disable();
|
||||||
|
|
||||||
|
<T as RccPeripheral>::disable();
|
||||||
|
|
||||||
|
#[cfg(stm32l4)]
|
||||||
|
unsafe {
|
||||||
|
crate::pac::PWR.cr2().modify(|w| w.set_usv(false));
|
||||||
|
// Cannot disable PWR, because other peripherals might be using it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
|
impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
|
||||||
async fn poll(&mut self) -> Event {
|
async fn poll(&mut self) -> Event {
|
||||||
poll_fn(move |cx| {
|
poll_fn(move |cx| {
|
||||||
@ -902,9 +902,8 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
|
|||||||
<T as RccPeripheral>::enable();
|
<T as RccPeripheral>::enable();
|
||||||
<T as RccPeripheral>::reset();
|
<T as RccPeripheral>::reset();
|
||||||
|
|
||||||
self.irq.set_handler(Self::on_interrupt);
|
T::Interrupt::steal().unpend();
|
||||||
self.irq.unpend();
|
T::Interrupt::steal().enable();
|
||||||
self.irq.enable();
|
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
let core_id = r.cid().read().0;
|
let core_id = r.cid().read().0;
|
||||||
|
@ -8,13 +8,17 @@ use embassy_futures::join::join;
|
|||||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usb::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USB_LP_CAN1_RX0 => usb::InterruptHandler<peripherals::USB>;
|
||||||
|
});
|
||||||
|
|
||||||
#[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();
|
||||||
@ -35,8 +39,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(USB_LP_CAN1_RX0);
|
let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
|
||||||
let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
|
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -7,19 +7,22 @@ use core::fmt::Write;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART1 => usart::InterruptHandler<peripherals::USART1>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(USART1);
|
let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, Irqs, p.DMA1_CH4, NoDma, config);
|
||||||
let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, irq, p.DMA1_CH4, NoDma, config);
|
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -8,13 +8,17 @@ use embassy_futures::join::join;
|
|||||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::usb::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USB_LP_CAN_RX0 => usb::InterruptHandler<peripherals::USB>;
|
||||||
|
});
|
||||||
|
|
||||||
#[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();
|
||||||
@ -33,8 +37,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
dp_pullup.set_high();
|
dp_pullup.set_high();
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(USB_LP_CAN_RX0);
|
let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
|
||||||
let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
|
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -6,25 +6,28 @@ use defmt::*;
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
|
use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
|
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
||||||
use embassy_time::Duration;
|
use embassy_time::Duration;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x5F;
|
const ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello world!");
|
info!("Hello world!");
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let irq = interrupt::take!(I2C2_EV);
|
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new(
|
||||||
p.I2C2,
|
p.I2C2,
|
||||||
p.PB10,
|
p.PB10,
|
||||||
p.PB11,
|
p.PB11,
|
||||||
irq,
|
Irqs,
|
||||||
NoDma,
|
NoDma,
|
||||||
NoDma,
|
NoDma,
|
||||||
Hertz(100_000),
|
Hertz(100_000),
|
||||||
|
@ -6,13 +6,17 @@ use defmt::*;
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::sdmmc::{DataBlock, Sdmmc};
|
use embassy_stm32::sdmmc::{DataBlock, Sdmmc};
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
/// This is a safeguard to not overwrite any data on the SD card.
|
/// This is a safeguard to not overwrite any data on the SD card.
|
||||||
/// If you don't care about SD card contents, set this to `true` to test writes.
|
/// If you don't care about SD card contents, set this to `true` to test writes.
|
||||||
const ALLOW_WRITES: bool = false;
|
const ALLOW_WRITES: bool = false;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
SDIO => sdmmc::InterruptHandler<peripherals::SDIO>;
|
||||||
|
});
|
||||||
|
|
||||||
#[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();
|
||||||
@ -21,11 +25,9 @@ async fn main(_spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let irq = interrupt::take!(SDIO);
|
|
||||||
|
|
||||||
let mut sdmmc = Sdmmc::new_4bit(
|
let mut sdmmc = Sdmmc::new_4bit(
|
||||||
p.SDIO,
|
p.SDIO,
|
||||||
irq,
|
Irqs,
|
||||||
p.DMA2_CH3,
|
p.DMA2_CH3,
|
||||||
p.PC12,
|
p.PC12,
|
||||||
p.PD2,
|
p.PD2,
|
||||||
|
@ -5,10 +5,14 @@
|
|||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART3 => usart::InterruptHandler<peripherals::USART3>;
|
||||||
|
});
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -16,8 +20,7 @@ fn main() -> ! {
|
|||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(USART3);
|
let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, NoDma, NoDma, config);
|
||||||
let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, NoDma, NoDma, config);
|
|
||||||
|
|
||||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -4,11 +4,15 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{BufferedUart, Config};
|
use embassy_stm32::usart::{BufferedUart, Config};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use embedded_io::asynch::BufRead;
|
use embedded_io::asynch::BufRead;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART3 => usart::BufferedInterruptHandler<peripherals::USART3>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
@ -16,10 +20,9 @@ async fn main(_spawner: Spawner) {
|
|||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
|
|
||||||
let irq = interrupt::take!(USART3);
|
|
||||||
let mut tx_buf = [0u8; 32];
|
let mut tx_buf = [0u8; 32];
|
||||||
let mut rx_buf = [0u8; 32];
|
let mut rx_buf = [0u8; 32];
|
||||||
let mut buf_usart = BufferedUart::new(p.USART3, irq, p.PD9, p.PD8, &mut tx_buf, &mut rx_buf, config);
|
let mut buf_usart = BufferedUart::new(p.USART3, Irqs, p.PD9, p.PD8, &mut tx_buf, &mut rx_buf, config);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let buf = buf_usart.fill_buf().await.unwrap();
|
let buf = buf_usart.fill_buf().await.unwrap();
|
||||||
|
@ -7,19 +7,22 @@ use core::fmt::Write;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART3 => usart::InterruptHandler<peripherals::USART3>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(USART3);
|
let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, p.DMA1_CH3, NoDma, config);
|
||||||
let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, p.DMA1_CH3, NoDma, config);
|
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -9,7 +9,7 @@ use embassy_net::{Stack, StackResources};
|
|||||||
use embassy_stm32::rng::Rng;
|
use embassy_stm32::rng::Rng;
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::usb_otg::Driver;
|
use embassy_stm32::usb_otg::Driver;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
||||||
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
||||||
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
||||||
use embassy_usb::{Builder, UsbDevice};
|
use embassy_usb::{Builder, UsbDevice};
|
||||||
@ -45,6 +45,10 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
|
|||||||
stack.run().await
|
stack.run().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -56,9 +60,8 @@ async fn main(spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(OTG_FS);
|
|
||||||
let ep_out_buffer = &mut singleton!([0; 256])[..];
|
let ep_out_buffer = &mut singleton!([0; 256])[..];
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, ep_out_buffer);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer);
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -6,13 +6,17 @@ use defmt::{panic, *};
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::usb_otg::{Driver, Instance};
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use futures::future::join;
|
use futures::future::join;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -24,9 +28,8 @@ async fn main(_spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(OTG_FS);
|
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -11,7 +11,7 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
|
|||||||
use embassy_stm32::peripherals::ETH;
|
use embassy_stm32::peripherals::ETH;
|
||||||
use embassy_stm32::rng::Rng;
|
use embassy_stm32::rng::Rng;
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, eth, Config};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embedded_io::asynch::Write;
|
use embedded_io::asynch::Write;
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
@ -27,6 +27,10 @@ macro_rules! singleton {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
ETH => eth::InterruptHandler;
|
||||||
|
});
|
||||||
|
|
||||||
type Device = Ethernet<'static, ETH, GenericSMI>;
|
type Device = Ethernet<'static, ETH, GenericSMI>;
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
@ -48,13 +52,12 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
rng.fill_bytes(&mut seed);
|
rng.fill_bytes(&mut seed);
|
||||||
let seed = u64::from_le_bytes(seed);
|
let seed = u64::from_le_bytes(seed);
|
||||||
|
|
||||||
let eth_int = interrupt::take!(ETH);
|
|
||||||
let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
|
let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
|
||||||
|
|
||||||
let device = Ethernet::new(
|
let device = Ethernet::new(
|
||||||
singleton!(PacketQueue::<16, 16>::new()),
|
singleton!(PacketQueue::<16, 16>::new()),
|
||||||
p.ETH,
|
p.ETH,
|
||||||
eth_int,
|
Irqs,
|
||||||
p.PA1,
|
p.PA1,
|
||||||
p.PA2,
|
p.PA2,
|
||||||
p.PC1,
|
p.PC1,
|
||||||
|
@ -6,9 +6,13 @@ use defmt::*;
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::sdmmc::Sdmmc;
|
use embassy_stm32::sdmmc::Sdmmc;
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
SDMMC1 => sdmmc::InterruptHandler<peripherals::SDMMC1>;
|
||||||
|
});
|
||||||
|
|
||||||
#[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();
|
||||||
@ -18,11 +22,9 @@ async fn main(_spawner: Spawner) {
|
|||||||
|
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let irq = interrupt::take!(SDMMC1);
|
|
||||||
|
|
||||||
let mut sdmmc = Sdmmc::new_4bit(
|
let mut sdmmc = Sdmmc::new_4bit(
|
||||||
p.SDMMC1,
|
p.SDMMC1,
|
||||||
irq,
|
Irqs,
|
||||||
p.DMA2_CH3,
|
p.DMA2_CH3,
|
||||||
p.PC12,
|
p.PC12,
|
||||||
p.PD2,
|
p.PD2,
|
||||||
|
@ -7,17 +7,20 @@ use core::fmt::Write;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
UART7 => usart::InterruptHandler<peripherals::UART7>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(UART7);
|
let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, Irqs, p.DMA1_CH1, NoDma, config);
|
||||||
let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, irq, p.DMA1_CH1, NoDma, config);
|
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -6,13 +6,17 @@ use defmt::{panic, *};
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::usb_otg::{Driver, Instance};
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use futures::future::join;
|
use futures::future::join;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -25,9 +29,8 @@ async fn main(_spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(OTG_FS);
|
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -12,7 +12,7 @@ use embassy_stm32::peripherals::ETH;
|
|||||||
use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale};
|
use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale};
|
||||||
use embassy_stm32::rng::Rng;
|
use embassy_stm32::rng::Rng;
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, eth, Config};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embedded_io::asynch::Write;
|
use embedded_io::asynch::Write;
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
@ -28,6 +28,10 @@ macro_rules! singleton {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
ETH => eth::InterruptHandler;
|
||||||
|
});
|
||||||
|
|
||||||
type Device = Ethernet<'static, ETH, GenericSMI>;
|
type Device = Ethernet<'static, ETH, GenericSMI>;
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
@ -67,13 +71,12 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
rng.fill_bytes(&mut seed);
|
rng.fill_bytes(&mut seed);
|
||||||
let seed = u64::from_le_bytes(seed);
|
let seed = u64::from_le_bytes(seed);
|
||||||
|
|
||||||
let eth_int = interrupt::take!(ETH);
|
|
||||||
let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
|
let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
|
||||||
|
|
||||||
let device = Ethernet::new(
|
let device = Ethernet::new(
|
||||||
singleton!(PacketQueue::<4, 4>::new()),
|
singleton!(PacketQueue::<4, 4>::new()),
|
||||||
p.ETH,
|
p.ETH,
|
||||||
eth_int,
|
Irqs,
|
||||||
p.PA1,
|
p.PA1,
|
||||||
p.PA2,
|
p.PA2,
|
||||||
p.PC1,
|
p.PC1,
|
||||||
|
@ -5,25 +5,28 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
|
use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
|
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
||||||
use embassy_time::Duration;
|
use embassy_time::Duration;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x5F;
|
const ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello world!");
|
info!("Hello world!");
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let irq = interrupt::take!(I2C2_EV);
|
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new(
|
||||||
p.I2C2,
|
p.I2C2,
|
||||||
p.PB10,
|
p.PB10,
|
||||||
p.PB11,
|
p.PB11,
|
||||||
irq,
|
Irqs,
|
||||||
p.GPDMA1_CH4,
|
p.GPDMA1_CH4,
|
||||||
p.GPDMA1_CH5,
|
p.GPDMA1_CH5,
|
||||||
Hertz(100_000),
|
Hertz(100_000),
|
||||||
|
@ -6,18 +6,21 @@ use cortex_m_rt::entry;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
UART7 => usart::InterruptHandler<peripherals::UART7>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn main_task() {
|
async fn main_task() {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(UART7);
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, NoDma, NoDma, config);
|
||||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, NoDma, NoDma, config);
|
|
||||||
|
|
||||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -8,19 +8,22 @@ use cortex_m_rt::entry;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
UART7 => usart::InterruptHandler<peripherals::UART7>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn main_task() {
|
async fn main_task() {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(UART7);
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, NoDma, config);
|
||||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.GPDMA1_CH0, NoDma, config);
|
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -5,13 +5,17 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::peripherals::{GPDMA1_CH1, UART7};
|
use embassy_stm32::peripherals::{GPDMA1_CH1, UART7};
|
||||||
use embassy_stm32::usart::{Config, Uart, UartRx};
|
use embassy_stm32::usart::{Config, Uart, UartRx};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||||
use embassy_sync::channel::Channel;
|
use embassy_sync::channel::Channel;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
UART7 => usart::InterruptHandler<peripherals::UART7>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
|
async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
|
||||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
@ -32,8 +36,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(UART7);
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1, config);
|
||||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.GPDMA1_CH0, p.GPDMA1_CH1, config);
|
|
||||||
unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
|
unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
|
||||||
|
|
||||||
let (mut tx, rx) = usart.split();
|
let (mut tx, rx) = usart.split();
|
||||||
|
@ -7,13 +7,17 @@ use embassy_executor::Spawner;
|
|||||||
use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale};
|
use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale};
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usb::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{interrupt, pac, Config};
|
use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use futures::future::join;
|
use futures::future::join;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USB_DRD_FS => usb::InterruptHandler<peripherals::USB>;
|
||||||
|
});
|
||||||
|
|
||||||
#[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();
|
||||||
@ -48,8 +52,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(USB_DRD_FS);
|
let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
|
||||||
let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
|
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -8,7 +8,7 @@ use embassy_stm32::gpio::{Level, Output, Speed};
|
|||||||
use embassy_stm32::i2c::I2c;
|
use embassy_stm32::i2c::I2c;
|
||||||
use embassy_stm32::rcc::{Mco, Mco1Source, McoClock};
|
use embassy_stm32::rcc::{Mco, Mco1Source, McoClock};
|
||||||
use embassy_stm32::time::{khz, mhz};
|
use embassy_stm32::time::{khz, mhz};
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, i2c, peripherals, Config};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use ov7725::*;
|
use ov7725::*;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
@ -18,6 +18,11 @@ const HEIGHT: usize = 100;
|
|||||||
|
|
||||||
static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2];
|
static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2];
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2C1_EV => i2c::InterruptHandler<peripherals::I2C1>;
|
||||||
|
DCMI => dcmi::InterruptHandler<peripherals::DCMI>;
|
||||||
|
});
|
||||||
|
|
||||||
#[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();
|
||||||
@ -34,12 +39,11 @@ async fn main(_spawner: Spawner) {
|
|||||||
let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::Hsi, McoClock::Divided(3));
|
let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::Hsi, McoClock::Divided(3));
|
||||||
|
|
||||||
let mut led = Output::new(p.PE3, Level::High, Speed::Low);
|
let mut led = Output::new(p.PE3, Level::High, Speed::Low);
|
||||||
let i2c_irq = interrupt::take!(I2C1_EV);
|
|
||||||
let cam_i2c = I2c::new(
|
let cam_i2c = I2c::new(
|
||||||
p.I2C1,
|
p.I2C1,
|
||||||
p.PB8,
|
p.PB8,
|
||||||
p.PB9,
|
p.PB9,
|
||||||
i2c_irq,
|
Irqs,
|
||||||
p.DMA1_CH1,
|
p.DMA1_CH1,
|
||||||
p.DMA1_CH2,
|
p.DMA1_CH2,
|
||||||
khz(100),
|
khz(100),
|
||||||
@ -55,11 +59,9 @@ async fn main(_spawner: Spawner) {
|
|||||||
|
|
||||||
defmt::info!("manufacturer: 0x{:x}, pid: 0x{:x}", manufacturer_id, camera_id);
|
defmt::info!("manufacturer: 0x{:x}, pid: 0x{:x}", manufacturer_id, camera_id);
|
||||||
|
|
||||||
let dcmi_irq = interrupt::take!(DCMI);
|
|
||||||
let config = dcmi::Config::default();
|
let config = dcmi::Config::default();
|
||||||
let mut dcmi = Dcmi::new_8bit(
|
let mut dcmi = Dcmi::new_8bit(
|
||||||
p.DCMI, p.DMA1_CH0, dcmi_irq, p.PC6, p.PC7, p.PE0, p.PE1, p.PE4, p.PD3, p.PE5, p.PE6, p.PB7, p.PA4, p.PA6,
|
p.DCMI, p.DMA1_CH0, Irqs, p.PC6, p.PC7, p.PE0, p.PE1, p.PE4, p.PD3, p.PE5, p.PE6, p.PB7, p.PA4, p.PA6, config,
|
||||||
config,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
defmt::info!("attempting capture");
|
defmt::info!("attempting capture");
|
||||||
|
@ -11,7 +11,7 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
|
|||||||
use embassy_stm32::peripherals::ETH;
|
use embassy_stm32::peripherals::ETH;
|
||||||
use embassy_stm32::rng::Rng;
|
use embassy_stm32::rng::Rng;
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, eth, Config};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embedded_io::asynch::Write;
|
use embedded_io::asynch::Write;
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
@ -27,6 +27,10 @@ macro_rules! singleton {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
ETH => eth::InterruptHandler;
|
||||||
|
});
|
||||||
|
|
||||||
type Device = Ethernet<'static, ETH, GenericSMI>;
|
type Device = Ethernet<'static, ETH, GenericSMI>;
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
@ -49,13 +53,12 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
rng.fill_bytes(&mut seed);
|
rng.fill_bytes(&mut seed);
|
||||||
let seed = u64::from_le_bytes(seed);
|
let seed = u64::from_le_bytes(seed);
|
||||||
|
|
||||||
let eth_int = interrupt::take!(ETH);
|
|
||||||
let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
|
let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
|
||||||
|
|
||||||
let device = Ethernet::new(
|
let device = Ethernet::new(
|
||||||
singleton!(PacketQueue::<16, 16>::new()),
|
singleton!(PacketQueue::<16, 16>::new()),
|
||||||
p.ETH,
|
p.ETH,
|
||||||
eth_int,
|
Irqs,
|
||||||
p.PA1,
|
p.PA1,
|
||||||
p.PA2,
|
p.PA2,
|
||||||
p.PC1,
|
p.PC1,
|
||||||
|
@ -11,7 +11,7 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
|
|||||||
use embassy_stm32::peripherals::ETH;
|
use embassy_stm32::peripherals::ETH;
|
||||||
use embassy_stm32::rng::Rng;
|
use embassy_stm32::rng::Rng;
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, eth, Config};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embedded_io::asynch::Write;
|
use embedded_io::asynch::Write;
|
||||||
use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect};
|
use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect};
|
||||||
@ -28,6 +28,10 @@ macro_rules! singleton {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
ETH => eth::InterruptHandler;
|
||||||
|
});
|
||||||
|
|
||||||
type Device = Ethernet<'static, ETH, GenericSMI>;
|
type Device = Ethernet<'static, ETH, GenericSMI>;
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
@ -50,13 +54,12 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
rng.fill_bytes(&mut seed);
|
rng.fill_bytes(&mut seed);
|
||||||
let seed = u64::from_le_bytes(seed);
|
let seed = u64::from_le_bytes(seed);
|
||||||
|
|
||||||
let eth_int = interrupt::take!(ETH);
|
|
||||||
let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
|
let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
|
||||||
|
|
||||||
let device = Ethernet::new(
|
let device = Ethernet::new(
|
||||||
singleton!(PacketQueue::<16, 16>::new()),
|
singleton!(PacketQueue::<16, 16>::new()),
|
||||||
p.ETH,
|
p.ETH,
|
||||||
eth_int,
|
Irqs,
|
||||||
p.PA1,
|
p.PA1,
|
||||||
p.PA2,
|
p.PA2,
|
||||||
p.PC1,
|
p.PC1,
|
||||||
|
@ -5,25 +5,28 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
|
use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
|
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
||||||
use embassy_time::Duration;
|
use embassy_time::Duration;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x5F;
|
const ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello world!");
|
info!("Hello world!");
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let irq = interrupt::take!(I2C2_EV);
|
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new(
|
||||||
p.I2C2,
|
p.I2C2,
|
||||||
p.PB10,
|
p.PB10,
|
||||||
p.PB11,
|
p.PB11,
|
||||||
irq,
|
Irqs,
|
||||||
p.DMA1_CH4,
|
p.DMA1_CH4,
|
||||||
p.DMA1_CH5,
|
p.DMA1_CH5,
|
||||||
Hertz(100_000),
|
Hertz(100_000),
|
||||||
|
@ -6,9 +6,13 @@ use defmt::*;
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::sdmmc::Sdmmc;
|
use embassy_stm32::sdmmc::Sdmmc;
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
SDMMC1 => sdmmc::InterruptHandler<peripherals::SDMMC1>;
|
||||||
|
});
|
||||||
|
|
||||||
#[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();
|
||||||
@ -16,11 +20,9 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let irq = interrupt::take!(SDMMC1);
|
|
||||||
|
|
||||||
let mut sdmmc = Sdmmc::new_4bit(
|
let mut sdmmc = Sdmmc::new_4bit(
|
||||||
p.SDMMC1,
|
p.SDMMC1,
|
||||||
irq,
|
Irqs,
|
||||||
p.PC12,
|
p.PC12,
|
||||||
p.PD2,
|
p.PD2,
|
||||||
p.PC8,
|
p.PC8,
|
||||||
|
@ -6,18 +6,21 @@ use cortex_m_rt::entry;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
UART7 => usart::InterruptHandler<peripherals::UART7>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn main_task() {
|
async fn main_task() {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(UART7);
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, NoDma, NoDma, config);
|
||||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, NoDma, NoDma, config);
|
|
||||||
|
|
||||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -8,19 +8,22 @@ use cortex_m_rt::entry;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
UART7 => usart::InterruptHandler<peripherals::UART7>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn main_task() {
|
async fn main_task() {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(UART7);
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.DMA1_CH0, NoDma, config);
|
||||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, NoDma, config);
|
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -5,13 +5,17 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::peripherals::{DMA1_CH1, UART7};
|
use embassy_stm32::peripherals::{DMA1_CH1, UART7};
|
||||||
use embassy_stm32::usart::{Config, Uart, UartRx};
|
use embassy_stm32::usart::{Config, Uart, UartRx};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||||
use embassy_sync::channel::Channel;
|
use embassy_sync::channel::Channel;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
UART7 => usart::InterruptHandler<peripherals::UART7>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
|
async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
|
||||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
@ -32,8 +36,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(UART7);
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.DMA1_CH0, p.DMA1_CH1, config);
|
||||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, p.DMA1_CH1, config);
|
|
||||||
unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
|
unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
|
||||||
|
|
||||||
let (mut tx, rx) = usart.split();
|
let (mut tx, rx) = usart.split();
|
||||||
|
@ -6,13 +6,17 @@ use defmt::{panic, *};
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::usb_otg::{Driver, Instance};
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use futures::future::join;
|
use futures::future::join;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -24,9 +28,8 @@ async fn main(_spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(OTG_FS);
|
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -4,15 +4,18 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART1 => usart::InterruptHandler<peripherals::USART1>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let irq = interrupt::take!(USART1);
|
let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, Irqs, p.DMA1_CH2, p.DMA1_CH3, Config::default());
|
||||||
let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, irq, p.DMA1_CH2, p.DMA1_CH3, Config::default());
|
|
||||||
|
|
||||||
usart.write(b"Hello Embassy World!\r\n").await.unwrap();
|
usart.write(b"Hello Embassy World!\r\n").await.unwrap();
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -4,11 +4,15 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{BufferedUart, Config};
|
use embassy_stm32::usart::{BufferedUart, Config};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use embedded_io::asynch::{Read, Write};
|
use embedded_io::asynch::{Read, Write};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART2 => usart::BufferedInterruptHandler<peripherals::USART2>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
@ -20,8 +24,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.baudrate = 9600;
|
config.baudrate = 9600;
|
||||||
|
|
||||||
let irq = interrupt::take!(USART2);
|
let mut usart = unsafe { BufferedUart::new(p.USART2, Irqs, p.PA3, p.PA2, &mut TX_BUFFER, &mut RX_BUFFER, config) };
|
||||||
let mut usart = unsafe { BufferedUart::new(p.USART2, irq, p.PA3, p.PA2, &mut TX_BUFFER, &mut RX_BUFFER, config) };
|
|
||||||
|
|
||||||
usart.write_all(b"Hello Embassy World!\r\n").await.unwrap();
|
usart.write_all(b"Hello Embassy World!\r\n").await.unwrap();
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -6,22 +6,25 @@ use defmt::*;
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::i2c::I2c;
|
use embassy_stm32::i2c::I2c;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
|
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x5F;
|
const ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let irq = interrupt::take!(I2C2_EV);
|
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new(
|
||||||
p.I2C2,
|
p.I2C2,
|
||||||
p.PB10,
|
p.PB10,
|
||||||
p.PB11,
|
p.PB11,
|
||||||
irq,
|
Irqs,
|
||||||
NoDma,
|
NoDma,
|
||||||
NoDma,
|
NoDma,
|
||||||
Hertz(100_000),
|
Hertz(100_000),
|
||||||
|
@ -7,23 +7,26 @@ use embassy_embedded_hal::adapter::BlockingAsync;
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::i2c::I2c;
|
use embassy_stm32::i2c::I2c;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
|
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
||||||
use embedded_hal_async::i2c::I2c as I2cTrait;
|
use embedded_hal_async::i2c::I2c as I2cTrait;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x5F;
|
const ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let irq = interrupt::take!(I2C2_EV);
|
|
||||||
let i2c = I2c::new(
|
let i2c = I2c::new(
|
||||||
p.I2C2,
|
p.I2C2,
|
||||||
p.PB10,
|
p.PB10,
|
||||||
p.PB11,
|
p.PB11,
|
||||||
irq,
|
Irqs,
|
||||||
NoDma,
|
NoDma,
|
||||||
NoDma,
|
NoDma,
|
||||||
Hertz(100_000),
|
Hertz(100_000),
|
||||||
|
@ -5,22 +5,25 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::i2c::I2c;
|
use embassy_stm32::i2c::I2c;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
|
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x5F;
|
const ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let irq = interrupt::take!(I2C2_EV);
|
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new(
|
||||||
p.I2C2,
|
p.I2C2,
|
||||||
p.PB10,
|
p.PB10,
|
||||||
p.PB11,
|
p.PB11,
|
||||||
irq,
|
Irqs,
|
||||||
p.DMA1_CH4,
|
p.DMA1_CH4,
|
||||||
p.DMA1_CH5,
|
p.DMA1_CH5,
|
||||||
Hertz(100_000),
|
Hertz(100_000),
|
||||||
|
@ -4,10 +4,14 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
UART4 => usart::InterruptHandler<peripherals::UART4>;
|
||||||
|
});
|
||||||
|
|
||||||
#[cortex_m_rt::entry]
|
#[cortex_m_rt::entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -15,8 +19,7 @@ fn main() -> ! {
|
|||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(UART4);
|
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, NoDma, NoDma, config);
|
||||||
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, NoDma, NoDma, config);
|
|
||||||
|
|
||||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -7,19 +7,22 @@ use core::fmt::Write;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
UART4 => usart::InterruptHandler<peripherals::UART4>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let irq = interrupt::take!(UART4);
|
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, p.DMA1_CH3, NoDma, config);
|
||||||
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, p.DMA1_CH3, NoDma, config);
|
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -7,13 +7,17 @@ use defmt_rtt as _; // global logger
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::rcc::*;
|
use embassy_stm32::rcc::*;
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::usb_otg::{Driver, Instance};
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use futures::future::join;
|
use futures::future::join;
|
||||||
use panic_probe as _;
|
use panic_probe as _;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -25,9 +29,8 @@ async fn main(_spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(OTG_FS);
|
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -9,7 +9,7 @@ use embassy_net::{Stack, StackResources};
|
|||||||
use embassy_stm32::rcc::*;
|
use embassy_stm32::rcc::*;
|
||||||
use embassy_stm32::rng::Rng;
|
use embassy_stm32::rng::Rng;
|
||||||
use embassy_stm32::usb::Driver;
|
use embassy_stm32::usb::Driver;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
||||||
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
||||||
use embassy_usb::{Builder, UsbDevice};
|
use embassy_usb::{Builder, UsbDevice};
|
||||||
@ -31,6 +31,10 @@ macro_rules! singleton {
|
|||||||
|
|
||||||
const MTU: usize = 1514;
|
const MTU: usize = 1514;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USB_FS => usb::InterruptHandler<peripherals::USB>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! {
|
async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! {
|
||||||
device.run().await
|
device.run().await
|
||||||
@ -54,8 +58,7 @@ async fn main(spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(USB_FS);
|
let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
|
||||||
let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
|
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -7,7 +7,7 @@ use embassy_executor::Spawner;
|
|||||||
use embassy_futures::join::join;
|
use embassy_futures::join::join;
|
||||||
use embassy_stm32::rcc::*;
|
use embassy_stm32::rcc::*;
|
||||||
use embassy_stm32::usb::Driver;
|
use embassy_stm32::usb::Driver;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
|
use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
|
||||||
use embassy_usb::control::OutResponse;
|
use embassy_usb::control::OutResponse;
|
||||||
@ -15,6 +15,10 @@ use embassy_usb::Builder;
|
|||||||
use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
|
use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USB_FS => usb::InterruptHandler<peripherals::USB>;
|
||||||
|
});
|
||||||
|
|
||||||
#[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();
|
||||||
@ -23,8 +27,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(USB_FS);
|
let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
|
||||||
let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
|
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -7,12 +7,16 @@ use embassy_executor::Spawner;
|
|||||||
use embassy_futures::join::join;
|
use embassy_futures::join::join;
|
||||||
use embassy_stm32::rcc::*;
|
use embassy_stm32::rcc::*;
|
||||||
use embassy_stm32::usb::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USB_FS => usb::InterruptHandler<peripherals::USB>;
|
||||||
|
});
|
||||||
|
|
||||||
#[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();
|
||||||
@ -23,8 +27,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(USB_FS);
|
let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
|
||||||
let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
|
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -7,13 +7,17 @@ use defmt_rtt as _; // global logger
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::rcc::*;
|
use embassy_stm32::rcc::*;
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::usb_otg::{Driver, Instance};
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use futures::future::join;
|
use futures::future::join;
|
||||||
use panic_probe as _;
|
use panic_probe as _;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -26,9 +30,8 @@ async fn main(_spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let irq = interrupt::take!(OTG_FS);
|
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
|
||||||
|
@ -4,12 +4,17 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::ipcc::{Config, Ipcc};
|
use embassy_stm32::ipcc::{Config, Ipcc};
|
||||||
use embassy_stm32::tl_mbox::TlMbox;
|
use embassy_stm32::tl_mbox::TlMbox;
|
||||||
|
use embassy_stm32::{bind_interrupts, tl_mbox};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs{
|
||||||
|
IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler;
|
||||||
|
IPCC_C1_TX => tl_mbox::TransmitInterruptHandler;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
/*
|
/*
|
||||||
@ -42,10 +47,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut ipcc = Ipcc::new(p.IPCC, config);
|
let mut ipcc = Ipcc::new(p.IPCC, config);
|
||||||
|
|
||||||
let rx_irq = interrupt::take!(IPCC_C1_RX);
|
let mbox = TlMbox::init(&mut ipcc, Irqs);
|
||||||
let tx_irq = interrupt::take!(IPCC_C1_TX);
|
|
||||||
|
|
||||||
let mbox = TlMbox::init(&mut ipcc, rx_irq, tx_irq);
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let wireless_fw_info = mbox.wireless_fw_info();
|
let wireless_fw_info = mbox.wireless_fw_info();
|
||||||
|
@ -4,11 +4,16 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::ipcc::{Config, Ipcc};
|
use embassy_stm32::ipcc::{Config, Ipcc};
|
||||||
use embassy_stm32::tl_mbox::TlMbox;
|
use embassy_stm32::tl_mbox::TlMbox;
|
||||||
|
use embassy_stm32::{bind_interrupts, tl_mbox};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs{
|
||||||
|
IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler;
|
||||||
|
IPCC_C1_TX => tl_mbox::TransmitInterruptHandler;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
/*
|
/*
|
||||||
@ -41,10 +46,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut ipcc = Ipcc::new(p.IPCC, config);
|
let mut ipcc = Ipcc::new(p.IPCC, config);
|
||||||
|
|
||||||
let rx_irq = interrupt::take!(IPCC_C1_RX);
|
let mbox = TlMbox::init(&mut ipcc, Irqs);
|
||||||
let tx_irq = interrupt::take!(IPCC_C1_TX);
|
|
||||||
|
|
||||||
let mbox = TlMbox::init(&mut ipcc, rx_irq, tx_irq);
|
|
||||||
|
|
||||||
// initialize ble stack, does not return a response
|
// initialize ble stack, does not return a response
|
||||||
mbox.shci_ble_init(&mut ipcc, Default::default());
|
mbox.shci_ble_init(&mut ipcc, Default::default());
|
||||||
|
@ -7,9 +7,13 @@ use defmt::{assert_eq, *};
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::sdmmc::{DataBlock, Sdmmc};
|
use embassy_stm32::sdmmc::{DataBlock, Sdmmc};
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::{interrupt, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
SDIO => sdmmc::InterruptHandler<peripherals::SDIO>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -20,17 +24,8 @@ async fn main(_spawner: Spawner) {
|
|||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
#[cfg(feature = "stm32f429zi")]
|
#[cfg(feature = "stm32f429zi")]
|
||||||
let (mut sdmmc, mut irq, mut dma, mut clk, mut cmd, mut d0, mut d1, mut d2, mut d3) = (
|
let (mut sdmmc, mut dma, mut clk, mut cmd, mut d0, mut d1, mut d2, mut d3) =
|
||||||
p.SDIO,
|
(p.SDIO, p.DMA2_CH3, p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11);
|
||||||
interrupt::take!(SDIO),
|
|
||||||
p.DMA2_CH3,
|
|
||||||
p.PC12,
|
|
||||||
p.PD2,
|
|
||||||
p.PC8,
|
|
||||||
p.PC9,
|
|
||||||
p.PC10,
|
|
||||||
p.PC11,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Arbitrary block index
|
// Arbitrary block index
|
||||||
let block_idx = 16;
|
let block_idx = 16;
|
||||||
@ -48,7 +43,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
info!("initializing in 4-bit mode...");
|
info!("initializing in 4-bit mode...");
|
||||||
let mut s = Sdmmc::new_4bit(
|
let mut s = Sdmmc::new_4bit(
|
||||||
&mut sdmmc,
|
&mut sdmmc,
|
||||||
&mut irq,
|
Irqs,
|
||||||
&mut dma,
|
&mut dma,
|
||||||
&mut clk,
|
&mut clk,
|
||||||
&mut cmd,
|
&mut cmd,
|
||||||
@ -97,7 +92,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
info!("initializing in 1-bit mode...");
|
info!("initializing in 1-bit mode...");
|
||||||
let mut s = Sdmmc::new_1bit(
|
let mut s = Sdmmc::new_1bit(
|
||||||
&mut sdmmc,
|
&mut sdmmc,
|
||||||
&mut irq,
|
Irqs,
|
||||||
&mut dma,
|
&mut dma,
|
||||||
&mut clk,
|
&mut clk,
|
||||||
&mut cmd,
|
&mut cmd,
|
||||||
|
@ -7,11 +7,37 @@ mod example_common;
|
|||||||
use defmt::assert_eq;
|
use defmt::assert_eq;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Error, Uart};
|
use embassy_stm32::usart::{Config, Error, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use embassy_time::{Duration, Instant};
|
use embassy_time::{Duration, Instant};
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "stm32f103c8",
|
||||||
|
feature = "stm32g491re",
|
||||||
|
feature = "stm32g071rb",
|
||||||
|
feature = "stm32h755zi",
|
||||||
|
feature = "stm32c031c6",
|
||||||
|
))]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART1 => usart::InterruptHandler<peripherals::USART1>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "stm32u585ai")]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART3 => usart::InterruptHandler<peripherals::USART3>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "stm32f429zi")]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART6 => usart::InterruptHandler<peripherals::USART6>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(any(feature = "stm32wb55rg", feature = "stm32h563zi"))]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
LPUART1 => usart::InterruptHandler<peripherals::LPUART1>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(config());
|
let p = embassy_stm32::init(config());
|
||||||
@ -20,27 +46,27 @@ async fn main(_spawner: Spawner) {
|
|||||||
// Arduino pins D0 and D1
|
// Arduino pins D0 and D1
|
||||||
// They're connected together with a 1K resistor.
|
// They're connected together with a 1K resistor.
|
||||||
#[cfg(feature = "stm32f103c8")]
|
#[cfg(feature = "stm32f103c8")]
|
||||||
let (mut tx, mut rx, mut usart, mut irq) = (p.PA9, p.PA10, p.USART1, interrupt::take!(USART1));
|
let (mut tx, mut rx, mut usart) = (p.PA9, p.PA10, p.USART1);
|
||||||
#[cfg(feature = "stm32g491re")]
|
#[cfg(feature = "stm32g491re")]
|
||||||
let (mut tx, mut rx, mut usart, mut irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
|
let (mut tx, mut rx, mut usart) = (p.PC4, p.PC5, p.USART1);
|
||||||
#[cfg(feature = "stm32g071rb")]
|
#[cfg(feature = "stm32g071rb")]
|
||||||
let (mut tx, mut rx, mut usart, mut irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
|
let (mut tx, mut rx, mut usart) = (p.PC4, p.PC5, p.USART1);
|
||||||
#[cfg(feature = "stm32f429zi")]
|
#[cfg(feature = "stm32f429zi")]
|
||||||
let (mut tx, mut rx, mut usart, mut irq) = (p.PG14, p.PG9, p.USART6, interrupt::take!(USART6));
|
let (mut tx, mut rx, mut usart) = (p.PG14, p.PG9, p.USART6);
|
||||||
#[cfg(feature = "stm32wb55rg")]
|
#[cfg(feature = "stm32wb55rg")]
|
||||||
let (mut tx, mut rx, mut usart, mut irq) = (p.PA2, p.PA3, p.LPUART1, interrupt::take!(LPUART1));
|
let (mut tx, mut rx, mut usart) = (p.PA2, p.PA3, p.LPUART1);
|
||||||
#[cfg(feature = "stm32h755zi")]
|
#[cfg(feature = "stm32h755zi")]
|
||||||
let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1));
|
let (mut tx, mut rx, mut usart) = (p.PB6, p.PB7, p.USART1);
|
||||||
#[cfg(feature = "stm32u585ai")]
|
#[cfg(feature = "stm32u585ai")]
|
||||||
let (mut tx, mut rx, mut usart, mut irq) = (p.PD8, p.PD9, p.USART3, interrupt::take!(USART3));
|
let (mut tx, mut rx, mut usart) = (p.PD8, p.PD9, p.USART3);
|
||||||
#[cfg(feature = "stm32h563zi")]
|
#[cfg(feature = "stm32h563zi")]
|
||||||
let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.LPUART1, interrupt::take!(LPUART1));
|
let (mut tx, mut rx, mut usart) = (p.PB6, p.PB7, p.LPUART1);
|
||||||
#[cfg(feature = "stm32c031c6")]
|
#[cfg(feature = "stm32c031c6")]
|
||||||
let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1));
|
let (mut tx, mut rx, mut usart) = (p.PB6, p.PB7, p.USART1);
|
||||||
|
|
||||||
{
|
{
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config);
|
let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, Irqs, NoDma, NoDma, config);
|
||||||
|
|
||||||
// We can't send too many bytes, they have to fit in the FIFO.
|
// We can't send too many bytes, they have to fit in the FIFO.
|
||||||
// This is because we aren't sending+receiving at the same time.
|
// This is because we aren't sending+receiving at the same time.
|
||||||
@ -56,7 +82,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
// Test error handling with with an overflow error
|
// Test error handling with with an overflow error
|
||||||
{
|
{
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config);
|
let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, Irqs, NoDma, NoDma, config);
|
||||||
|
|
||||||
// Send enough bytes to fill the RX FIFOs off all USART versions.
|
// Send enough bytes to fill the RX FIFOs off all USART versions.
|
||||||
let data = [0xC0, 0xDE, 0x12, 0x23, 0x34];
|
let data = [0xC0, 0xDE, 0x12, 0x23, 0x34];
|
||||||
@ -90,7 +116,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
|
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.baudrate = baudrate;
|
config.baudrate = baudrate;
|
||||||
let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config);
|
let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, Irqs, NoDma, NoDma, config);
|
||||||
|
|
||||||
let n = (baudrate as usize / 100).max(64);
|
let n = (baudrate as usize / 100).max(64);
|
||||||
|
|
||||||
|
@ -7,10 +7,36 @@ mod example_common;
|
|||||||
use defmt::assert_eq;
|
use defmt::assert_eq;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::join::join;
|
use embassy_futures::join::join;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "stm32f103c8",
|
||||||
|
feature = "stm32g491re",
|
||||||
|
feature = "stm32g071rb",
|
||||||
|
feature = "stm32h755zi",
|
||||||
|
feature = "stm32c031c6",
|
||||||
|
))]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART1 => usart::InterruptHandler<peripherals::USART1>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "stm32u585ai")]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART3 => usart::InterruptHandler<peripherals::USART3>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "stm32f429zi")]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART6 => usart::InterruptHandler<peripherals::USART6>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(any(feature = "stm32wb55rg", feature = "stm32h563zi"))]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
LPUART1 => usart::InterruptHandler<peripherals::LPUART1>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(config());
|
let p = embassy_stm32::init(config());
|
||||||
@ -19,62 +45,23 @@ async fn main(_spawner: Spawner) {
|
|||||||
// Arduino pins D0 and D1
|
// Arduino pins D0 and D1
|
||||||
// They're connected together with a 1K resistor.
|
// They're connected together with a 1K resistor.
|
||||||
#[cfg(feature = "stm32f103c8")]
|
#[cfg(feature = "stm32f103c8")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, Irqs, p.DMA1_CH4, p.DMA1_CH5);
|
||||||
p.PA9,
|
|
||||||
p.PA10,
|
|
||||||
p.USART1,
|
|
||||||
interrupt::take!(USART1),
|
|
||||||
p.DMA1_CH4,
|
|
||||||
p.DMA1_CH5,
|
|
||||||
);
|
|
||||||
#[cfg(feature = "stm32g491re")]
|
#[cfg(feature = "stm32g491re")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, Irqs, p.DMA1_CH1, p.DMA1_CH2);
|
||||||
(p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
|
|
||||||
#[cfg(feature = "stm32g071rb")]
|
#[cfg(feature = "stm32g071rb")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, Irqs, p.DMA1_CH1, p.DMA1_CH2);
|
||||||
(p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
|
|
||||||
#[cfg(feature = "stm32f429zi")]
|
#[cfg(feature = "stm32f429zi")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PG14, p.PG9, p.USART6, Irqs, p.DMA2_CH6, p.DMA2_CH1);
|
||||||
p.PG14,
|
|
||||||
p.PG9,
|
|
||||||
p.USART6,
|
|
||||||
interrupt::take!(USART6),
|
|
||||||
p.DMA2_CH6,
|
|
||||||
p.DMA2_CH1,
|
|
||||||
);
|
|
||||||
#[cfg(feature = "stm32wb55rg")]
|
#[cfg(feature = "stm32wb55rg")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PA2, p.PA3, p.LPUART1, Irqs, p.DMA1_CH1, p.DMA1_CH2);
|
||||||
p.PA2,
|
|
||||||
p.PA3,
|
|
||||||
p.LPUART1,
|
|
||||||
interrupt::take!(LPUART1),
|
|
||||||
p.DMA1_CH1,
|
|
||||||
p.DMA1_CH2,
|
|
||||||
);
|
|
||||||
#[cfg(feature = "stm32h755zi")]
|
#[cfg(feature = "stm32h755zi")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, Irqs, p.DMA1_CH0, p.DMA1_CH1);
|
||||||
(p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH0, p.DMA1_CH1);
|
|
||||||
#[cfg(feature = "stm32u585ai")]
|
#[cfg(feature = "stm32u585ai")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PD8, p.PD9, p.USART3, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1);
|
||||||
p.PD8,
|
|
||||||
p.PD9,
|
|
||||||
p.USART3,
|
|
||||||
interrupt::take!(USART3),
|
|
||||||
p.GPDMA1_CH0,
|
|
||||||
p.GPDMA1_CH1,
|
|
||||||
);
|
|
||||||
#[cfg(feature = "stm32h563zi")]
|
#[cfg(feature = "stm32h563zi")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PB6, p.PB7, p.LPUART1, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1);
|
||||||
p.PB6,
|
|
||||||
p.PB7,
|
|
||||||
p.LPUART1,
|
|
||||||
interrupt::take!(LPUART1),
|
|
||||||
p.GPDMA1_CH0,
|
|
||||||
p.GPDMA1_CH1,
|
|
||||||
);
|
|
||||||
#[cfg(feature = "stm32c031c6")]
|
#[cfg(feature = "stm32c031c6")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, Irqs, p.DMA1_CH1, p.DMA1_CH2);
|
||||||
(p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
|
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config);
|
let usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config);
|
||||||
|
@ -8,13 +8,40 @@
|
|||||||
mod example_common;
|
mod example_common;
|
||||||
use defmt::{assert_eq, panic};
|
use defmt::{assert_eq, panic};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx};
|
use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
use rand_chacha::ChaCha8Rng;
|
use rand_chacha::ChaCha8Rng;
|
||||||
use rand_core::{RngCore, SeedableRng};
|
use rand_core::{RngCore, SeedableRng};
|
||||||
|
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "stm32f103c8",
|
||||||
|
feature = "stm32g491re",
|
||||||
|
feature = "stm32g071rb",
|
||||||
|
feature = "stm32h755zi",
|
||||||
|
feature = "stm32c031c6",
|
||||||
|
))]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART1 => usart::InterruptHandler<peripherals::USART1>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "stm32u585ai")]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART3 => usart::InterruptHandler<peripherals::USART3>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "stm32f429zi")]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART1 => usart::InterruptHandler<peripherals::USART1>;
|
||||||
|
USART6 => usart::InterruptHandler<peripherals::USART6>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(any(feature = "stm32wb55rg", feature = "stm32h563zi"))]
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
LPUART1 => usart::InterruptHandler<peripherals::LPUART1>;
|
||||||
|
});
|
||||||
|
|
||||||
#[cfg(feature = "stm32f103c8")]
|
#[cfg(feature = "stm32f103c8")]
|
||||||
mod board {
|
mod board {
|
||||||
pub type Uart = embassy_stm32::peripherals::USART1;
|
pub type Uart = embassy_stm32::peripherals::USART1;
|
||||||
@ -74,53 +101,21 @@ async fn main(spawner: Spawner) {
|
|||||||
// Arduino pins D0 and D1
|
// Arduino pins D0 and D1
|
||||||
// They're connected together with a 1K resistor.
|
// They're connected together with a 1K resistor.
|
||||||
#[cfg(feature = "stm32f103c8")]
|
#[cfg(feature = "stm32f103c8")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH4, p.DMA1_CH5);
|
||||||
p.PA9,
|
|
||||||
p.PA10,
|
|
||||||
p.USART1,
|
|
||||||
interrupt::take!(USART1),
|
|
||||||
p.DMA1_CH4,
|
|
||||||
p.DMA1_CH5,
|
|
||||||
);
|
|
||||||
#[cfg(feature = "stm32g491re")]
|
#[cfg(feature = "stm32g491re")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
|
||||||
(p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
|
|
||||||
#[cfg(feature = "stm32g071rb")]
|
#[cfg(feature = "stm32g071rb")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
|
||||||
(p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
|
|
||||||
#[cfg(feature = "stm32f429zi")]
|
#[cfg(feature = "stm32f429zi")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
let (tx, rx, usart, tx_dma, rx_dma) = (p.PG14, p.PG9, p.USART6, p.DMA2_CH6, p.DMA2_CH1);
|
||||||
p.PG14,
|
|
||||||
p.PG9,
|
|
||||||
p.USART6,
|
|
||||||
interrupt::take!(USART6),
|
|
||||||
p.DMA2_CH6,
|
|
||||||
p.DMA2_CH1,
|
|
||||||
);
|
|
||||||
#[cfg(feature = "stm32wb55rg")]
|
#[cfg(feature = "stm32wb55rg")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
let (tx, rx, usart, tx_dma, rx_dma) = (p.PA2, p.PA3, p.LPUART1, p.DMA1_CH1, p.DMA1_CH2);
|
||||||
p.PA2,
|
|
||||||
p.PA3,
|
|
||||||
p.LPUART1,
|
|
||||||
interrupt::take!(LPUART1),
|
|
||||||
p.DMA1_CH1,
|
|
||||||
p.DMA1_CH2,
|
|
||||||
);
|
|
||||||
#[cfg(feature = "stm32h755zi")]
|
#[cfg(feature = "stm32h755zi")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
let (tx, rx, usart, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, p.DMA1_CH0, p.DMA1_CH1);
|
||||||
(p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH0, p.DMA1_CH1);
|
|
||||||
#[cfg(feature = "stm32u585ai")]
|
#[cfg(feature = "stm32u585ai")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
let (tx, rx, usart, tx_dma, rx_dma) = (p.PD8, p.PD9, p.USART3, p.GPDMA1_CH0, p.GPDMA1_CH1);
|
||||||
p.PD8,
|
|
||||||
p.PD9,
|
|
||||||
p.USART3,
|
|
||||||
interrupt::take!(USART3),
|
|
||||||
p.GPDMA1_CH0,
|
|
||||||
p.GPDMA1_CH1,
|
|
||||||
);
|
|
||||||
#[cfg(feature = "stm32c031c6")]
|
#[cfg(feature = "stm32c031c6")]
|
||||||
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
let (tx, rx, usart, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
|
||||||
(p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
|
|
||||||
|
|
||||||
// To run this test, use the saturating_serial test utility to saturate the serial port
|
// To run this test, use the saturating_serial test utility to saturate the serial port
|
||||||
|
|
||||||
@ -132,7 +127,7 @@ async fn main(spawner: Spawner) {
|
|||||||
config.stop_bits = StopBits::STOP1;
|
config.stop_bits = StopBits::STOP1;
|
||||||
config.parity = Parity::ParityNone;
|
config.parity = Parity::ParityNone;
|
||||||
|
|
||||||
let usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config);
|
let usart = Uart::new(usart, rx, tx, Irqs, tx_dma, rx_dma, config);
|
||||||
let (tx, rx) = usart.split();
|
let (tx, rx) = usart.split();
|
||||||
static mut DMA_BUF: [u8; DMA_BUF_SIZE] = [0; DMA_BUF_SIZE];
|
static mut DMA_BUF: [u8; DMA_BUF_SIZE] = [0; DMA_BUF_SIZE];
|
||||||
let dma_buf = unsafe { DMA_BUF.as_mut() };
|
let dma_buf = unsafe { DMA_BUF.as_mut() };
|
||||||
|
Loading…
Reference in New Issue
Block a user