stm32: Remove OptionalPin

The idea behind OptionalPin has a few problems:

- you need to impl the signal traits for NoPin which is a bit weird https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/dcmi.rs#L413-L416
- you can pass any combination of set/unset pins, which needs checking at runtime  https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/dcmi.rs#L130

The replacement is to do multiple `new` constructors for each combination of pins you want to take.
This commit is contained in:
Dario Nieuwenhuis 2022-02-10 02:34:59 +01:00
parent 1d265b73b2
commit 550da471be
15 changed files with 546 additions and 431 deletions

View File

@ -3,27 +3,21 @@
#[cfg_attr(dac_v1, path = "v1.rs")]
#[cfg_attr(dac_v2, path = "v2.rs")]
mod _version;
use crate::gpio::NoPin;
use crate::peripherals;
pub use _version::*;
pub(crate) mod sealed {
use crate::gpio::OptionalPin;
pub trait Instance {
fn regs() -> &'static crate::pac::dac::Dac;
}
pub trait DacPin<T: Instance, const C: u8>: OptionalPin {}
pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin {}
}
pub trait Instance: sealed::Instance + 'static {}
pub trait DacPin<T: Instance, const C: u8>: sealed::DacPin<T, C> + 'static {}
impl<T: Instance, const C: u8> DacPin<T, C> for NoPin {}
impl<T: Instance, const C: u8> sealed::DacPin<T, C> for NoPin {}
crate::pac::peripherals!(
(dac, $inst:ident) => {
impl crate::dac::sealed::Instance for peripherals::$inst {

View File

@ -1,33 +1,25 @@
use crate::dac::{DacPin, Instance};
use crate::gpio::AnyPin;
use crate::pac::dac;
use core::marker::PhantomData;
use embassy::util::Unborrow;
use embassy_hal_common::unborrow;
/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock
/// configuration.
unsafe fn enable() {
#[cfg(rcc_h7)]
crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
#[cfg(rcc_g0)]
crate::pac::RCC.apbenr1().modify(|w| w.set_dac1en(true));
#[cfg(rcc_l4)]
crate::pac::RCC.apb1enr1().modify(|w| w.set_dac1en(true));
}
#[derive(Debug)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
UnconfiguredChannel,
InvalidValue,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Channel {
Ch1,
Ch2,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Ch1Trigger {
Tim6,
Tim3,
@ -52,6 +44,8 @@ impl Ch1Trigger {
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Ch2Trigger {
Tim6,
Tim8,
@ -78,46 +72,61 @@ impl Ch2Trigger {
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Alignment {
Left,
Right,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Value {
Bit8(u8),
Bit12(u16, Alignment),
}
pub struct Dac<'d, T: Instance> {
ch1: Option<AnyPin>,
ch2: Option<AnyPin>,
channels: u8,
phantom: PhantomData<&'d mut T>,
}
impl<'d, T: Instance> Dac<'d, T> {
pub fn new(
_peri: impl Unborrow<Target = T> + 'd,
ch1: impl Unborrow<Target = impl DacPin<T, 1>>,
ch2: impl Unborrow<Target = impl DacPin<T, 2>>,
pub fn new_1ch(
peri: impl Unborrow<Target = T> + 'd,
_ch1: impl Unborrow<Target = impl DacPin<T, 1>> + 'd,
) -> Self {
unborrow!(ch1, ch2);
unborrow!(peri);
Self::new_inner(peri, 1)
}
pub fn new_2ch(
peri: impl Unborrow<Target = T> + 'd,
_ch1: impl Unborrow<Target = impl DacPin<T, 1>> + 'd,
_ch2: impl Unborrow<Target = impl DacPin<T, 2>> + 'd,
) -> Self {
unborrow!(peri);
Self::new_inner(peri, 2)
}
fn new_inner(_peri: T, channels: u8) -> Self {
unsafe {
enable();
}
// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock
// configuration.
#[cfg(rcc_h7)]
crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
#[cfg(rcc_g0)]
crate::pac::RCC.apbenr1().modify(|w| w.set_dac1en(true));
#[cfg(rcc_l4)]
crate::pac::RCC.apb1enr1().modify(|w| w.set_dac1en(true));
let ch1 = ch1.degrade_optional();
if ch1.is_some() {
unsafe {
if channels >= 1 {
T::regs().cr().modify(|reg| {
reg.set_en1(true);
});
}
}
let ch2 = ch2.degrade_optional();
if ch2.is_some() {
unsafe {
if channels >= 2 {
T::regs().cr().modify(|reg| {
reg.set_en2(true);
});
@ -125,41 +134,37 @@ impl<'d, T: Instance> Dac<'d, T> {
}
Self {
ch1,
ch2,
channels,
phantom: PhantomData,
}
}
fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> {
match ch {
Channel::Ch1 => {
if self.ch1.is_none() {
Err(Error::UnconfiguredChannel)
} else {
unsafe {
T::regs().cr().modify(|reg| {
reg.set_en1(on);
});
}
Ok(())
}
}
Channel::Ch2 => {
if self.ch2.is_none() {
Err(Error::UnconfiguredChannel)
} else {
unsafe {
T::regs().cr().modify(|reg| {
reg.set_en2(on);
});
}
Ok(())
}
}
/// Check the channel is configured
fn check_channel_exists(&self, ch: Channel) -> Result<(), Error> {
if ch == Channel::Ch2 && self.channels < 2 {
Err(Error::UnconfiguredChannel)
} else {
Ok(())
}
}
fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> {
self.check_channel_exists(ch)?;
match ch {
Channel::Ch1 => unsafe {
T::regs().cr().modify(|reg| {
reg.set_en1(on);
})
},
Channel::Ch2 => unsafe {
T::regs().cr().modify(|reg| {
reg.set_en2(on);
});
},
}
Ok(())
}
pub fn enable_channel(&mut self, ch: Channel) -> Result<(), Error> {
self.set_channel_enable(ch, true)
}
@ -169,9 +174,7 @@ impl<'d, T: Instance> Dac<'d, T> {
}
pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> {
if self.ch1.is_none() {
return Err(Error::UnconfiguredChannel);
}
self.check_channel_exists(Channel::Ch1)?;
unwrap!(self.disable_channel(Channel::Ch1));
unsafe {
T::regs().cr().modify(|reg| {
@ -182,9 +185,7 @@ impl<'d, T: Instance> Dac<'d, T> {
}
pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> {
if self.ch2.is_none() {
return Err(Error::UnconfiguredChannel);
}
self.check_channel_exists(Channel::Ch2)?;
unwrap!(self.disable_channel(Channel::Ch2));
unsafe {
T::regs().cr().modify(|reg| {
@ -195,32 +196,20 @@ impl<'d, T: Instance> Dac<'d, T> {
}
pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> {
self.check_channel_exists(ch)?;
match ch {
Channel::Ch1 => {
if self.ch1.is_none() {
Err(Error::UnconfiguredChannel)
} else {
unsafe {
T::regs().swtrigr().write(|reg| {
reg.set_swtrig1(true);
});
}
Ok(())
}
}
Channel::Ch2 => {
if self.ch2.is_none() {
Err(Error::UnconfiguredChannel)
} else {
unsafe {
T::regs().swtrigr().write(|reg| {
reg.set_swtrig2(true);
});
}
Ok(())
}
}
Channel::Ch1 => unsafe {
T::regs().swtrigr().write(|reg| {
reg.set_swtrig1(true);
});
},
Channel::Ch2 => unsafe {
T::regs().swtrigr().write(|reg| {
reg.set_swtrig2(true);
})
},
}
Ok(())
}
pub fn trigger_all(&mut self) {
@ -233,43 +222,31 @@ impl<'d, T: Instance> Dac<'d, T> {
}
pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> {
self.check_channel_exists(Channel::Ch2)?;
match ch {
Channel::Ch1 => {
if self.ch1.is_none() {
Err(Error::UnconfiguredChannel)
} else {
match value {
Value::Bit8(v) => unsafe {
T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v));
},
Value::Bit12(v, Alignment::Left) => unsafe {
T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v));
},
Value::Bit12(v, Alignment::Right) => unsafe {
T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v));
},
}
Ok(())
}
}
Channel::Ch2 => {
if self.ch2.is_none() {
Err(Error::UnconfiguredChannel)
} else {
match value {
Value::Bit8(v) => unsafe {
T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v));
},
Value::Bit12(v, Alignment::Left) => unsafe {
T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v));
},
Value::Bit12(v, Alignment::Right) => unsafe {
T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v));
},
}
Ok(())
}
}
Channel::Ch1 => match value {
Value::Bit8(v) => unsafe {
T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v));
},
Value::Bit12(v, Alignment::Left) => unsafe {
T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v));
},
Value::Bit12(v, Alignment::Right) => unsafe {
T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v));
},
},
Channel::Ch2 => match value {
Value::Bit8(v) => unsafe {
T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v));
},
Value::Bit12(v, Alignment::Left) => unsafe {
T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v));
},
Value::Bit12(v, Alignment::Right) => unsafe {
T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v));
},
},
}
Ok(())
}
}

View File

@ -9,6 +9,15 @@ use embassy::waitqueue::AtomicWaker;
use embassy_hal_common::unborrow;
use futures::future::poll_fn;
#[macro_export]
macro_rules! configure {
($($name:ident),*) => {
$(
unsafe { $name.unborrow() }.configure();
)*
}
}
/// The level on the VSync pin when the data is not valid on the parallel interface.
#[derive(Clone, Copy, PartialEq)]
pub enum VSyncDataInvalidLevel {
@ -50,6 +59,23 @@ pub enum Error {
PeripheralError,
}
#[non_exhaustive]
pub struct Config {
pub vsync_level: VSyncDataInvalidLevel,
pub hsync_level: HSyncDataInvalidLevel,
pub pixclk_polarity: PixelClockPolarity,
}
impl Default for Config {
fn default() -> Self {
Self {
vsync_level: VSyncDataInvalidLevel::High,
hsync_level: HSyncDataInvalidLevel::Low,
pixclk_polarity: PixelClockPolarity::RisingEdge,
}
}
}
pub struct Dcmi<'d, T: Instance, Dma: FrameDma> {
inner: T,
dma: Dma,
@ -61,13 +87,85 @@ where
T: Instance,
Dma: FrameDma,
{
pub fn new(
pub fn new_8bit(
peri: impl Unborrow<Target = T> + 'd,
dma: impl Unborrow<Target = Dma> + 'd,
irq: impl Unborrow<Target = T::Interrupt> + 'd,
d0: impl Unborrow<Target = impl D0Pin> + 'd,
d1: impl Unborrow<Target = impl D1Pin> + 'd,
d2: impl Unborrow<Target = impl D2Pin> + 'd,
d3: impl Unborrow<Target = impl D3Pin> + 'd,
d4: impl Unborrow<Target = impl D4Pin> + 'd,
d5: impl Unborrow<Target = impl D5Pin> + 'd,
d6: impl Unborrow<Target = impl D6Pin> + 'd,
d7: impl Unborrow<Target = impl D7Pin> + 'd,
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
config: Config,
) -> Self {
unborrow!(peri, dma, irq);
configure!(d0, d1, d2, d3, d4, d5, d6, d7);
configure!(v_sync, h_sync, pixclk);
Self::new_inner(peri, dma, irq, config, false, 0b00)
}
pub fn new_10bit(
peri: impl Unborrow<Target = T> + 'd,
dma: impl Unborrow<Target = Dma> + 'd,
irq: impl Unborrow<Target = T::Interrupt> + 'd,
d0: impl Unborrow<Target = impl D0Pin> + 'd,
d1: impl Unborrow<Target = impl D1Pin> + 'd,
d2: impl Unborrow<Target = impl D2Pin> + 'd,
d3: impl Unborrow<Target = impl D3Pin> + 'd,
d4: impl Unborrow<Target = impl D4Pin> + 'd,
d5: impl Unborrow<Target = impl D5Pin> + 'd,
d6: impl Unborrow<Target = impl D6Pin> + 'd,
d7: impl Unborrow<Target = impl D7Pin> + 'd,
d8: impl Unborrow<Target = impl D8Pin> + 'd,
d9: impl Unborrow<Target = impl D9Pin> + 'd,
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
config: Config,
) -> Self {
unborrow!(peri, dma, irq);
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
configure!(v_sync, h_sync, pixclk);
Self::new_inner(peri, dma, irq, config, false, 0b01)
}
pub fn new_12bit(
peri: impl Unborrow<Target = T> + 'd,
dma: impl Unborrow<Target = Dma> + 'd,
irq: impl Unborrow<Target = T::Interrupt> + 'd,
d0: impl Unborrow<Target = impl D0Pin> + 'd,
d1: impl Unborrow<Target = impl D1Pin> + 'd,
d2: impl Unborrow<Target = impl D2Pin> + 'd,
d3: impl Unborrow<Target = impl D3Pin> + 'd,
d4: impl Unborrow<Target = impl D4Pin> + 'd,
d5: impl Unborrow<Target = impl D5Pin> + 'd,
d6: impl Unborrow<Target = impl D6Pin> + 'd,
d7: impl Unborrow<Target = impl D7Pin> + 'd,
d8: impl Unborrow<Target = impl D8Pin> + 'd,
d9: impl Unborrow<Target = impl D9Pin> + 'd,
d10: impl Unborrow<Target = impl D10Pin> + 'd,
d11: impl Unborrow<Target = impl D11Pin> + 'd,
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
config: Config,
) -> Self {
unborrow!(peri, dma, irq);
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
configure!(v_sync, h_sync, pixclk);
Self::new_inner(peri, dma, irq, config, false, 0b10)
}
pub fn new_14bit(
peri: impl Unborrow<Target = T> + 'd,
dma: impl Unborrow<Target = Dma> + 'd,
vsync_level: VSyncDataInvalidLevel,
hsync_level: HSyncDataInvalidLevel,
pixclk_polarity: PixelClockPolarity,
use_embedded_synchronization: bool,
irq: impl Unborrow<Target = T::Interrupt> + 'd,
d0: impl Unborrow<Target = impl D0Pin> + 'd,
d1: impl Unborrow<Target = impl D1Pin> + 'd,
@ -86,58 +184,132 @@ where
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
config: Config,
) -> Self {
unborrow!(peri, dma, irq);
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
configure!(v_sync, h_sync, pixclk);
Self::new_inner(peri, dma, irq, config, false, 0b11)
}
pub fn new_es_8bit(
peri: impl Unborrow<Target = T> + 'd,
dma: impl Unborrow<Target = Dma> + 'd,
irq: impl Unborrow<Target = T::Interrupt> + 'd,
d0: impl Unborrow<Target = impl D0Pin> + 'd,
d1: impl Unborrow<Target = impl D1Pin> + 'd,
d2: impl Unborrow<Target = impl D2Pin> + 'd,
d3: impl Unborrow<Target = impl D3Pin> + 'd,
d4: impl Unborrow<Target = impl D4Pin> + 'd,
d5: impl Unborrow<Target = impl D5Pin> + 'd,
d6: impl Unborrow<Target = impl D6Pin> + 'd,
d7: impl Unborrow<Target = impl D7Pin> + 'd,
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
config: Config,
) -> Self {
unborrow!(peri, dma, irq);
configure!(d0, d1, d2, d3, d4, d5, d6, d7);
configure!(pixclk);
Self::new_inner(peri, dma, irq, config, true, 0b00)
}
pub fn new_es_10bit(
peri: impl Unborrow<Target = T> + 'd,
dma: impl Unborrow<Target = Dma> + 'd,
irq: impl Unborrow<Target = T::Interrupt> + 'd,
d0: impl Unborrow<Target = impl D0Pin> + 'd,
d1: impl Unborrow<Target = impl D1Pin> + 'd,
d2: impl Unborrow<Target = impl D2Pin> + 'd,
d3: impl Unborrow<Target = impl D3Pin> + 'd,
d4: impl Unborrow<Target = impl D4Pin> + 'd,
d5: impl Unborrow<Target = impl D5Pin> + 'd,
d6: impl Unborrow<Target = impl D6Pin> + 'd,
d7: impl Unborrow<Target = impl D7Pin> + 'd,
d8: impl Unborrow<Target = impl D8Pin> + 'd,
d9: impl Unborrow<Target = impl D9Pin> + 'd,
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
config: Config,
) -> Self {
unborrow!(peri, dma, irq);
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
configure!(pixclk);
Self::new_inner(peri, dma, irq, config, true, 0b01)
}
pub fn new_es_12bit(
peri: impl Unborrow<Target = T> + 'd,
dma: impl Unborrow<Target = Dma> + 'd,
irq: impl Unborrow<Target = T::Interrupt> + 'd,
d0: impl Unborrow<Target = impl D0Pin> + 'd,
d1: impl Unborrow<Target = impl D1Pin> + 'd,
d2: impl Unborrow<Target = impl D2Pin> + 'd,
d3: impl Unborrow<Target = impl D3Pin> + 'd,
d4: impl Unborrow<Target = impl D4Pin> + 'd,
d5: impl Unborrow<Target = impl D5Pin> + 'd,
d6: impl Unborrow<Target = impl D6Pin> + 'd,
d7: impl Unborrow<Target = impl D7Pin> + 'd,
d8: impl Unborrow<Target = impl D8Pin> + 'd,
d9: impl Unborrow<Target = impl D9Pin> + 'd,
d10: impl Unborrow<Target = impl D10Pin> + 'd,
d11: impl Unborrow<Target = impl D11Pin> + 'd,
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
config: Config,
) -> Self {
unborrow!(peri, dma, irq);
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
configure!(pixclk);
Self::new_inner(peri, dma, irq, config, true, 0b10)
}
pub fn new_es_14bit(
peri: impl Unborrow<Target = T> + 'd,
dma: impl Unborrow<Target = Dma> + 'd,
irq: impl Unborrow<Target = T::Interrupt> + 'd,
d0: impl Unborrow<Target = impl D0Pin> + 'd,
d1: impl Unborrow<Target = impl D1Pin> + 'd,
d2: impl Unborrow<Target = impl D2Pin> + 'd,
d3: impl Unborrow<Target = impl D3Pin> + 'd,
d4: impl Unborrow<Target = impl D4Pin> + 'd,
d5: impl Unborrow<Target = impl D5Pin> + 'd,
d6: impl Unborrow<Target = impl D6Pin> + 'd,
d7: impl Unborrow<Target = impl D7Pin> + 'd,
d8: impl Unborrow<Target = impl D8Pin> + 'd,
d9: impl Unborrow<Target = impl D9Pin> + 'd,
d10: impl Unborrow<Target = impl D10Pin> + 'd,
d11: impl Unborrow<Target = impl D11Pin> + 'd,
d12: impl Unborrow<Target = impl D12Pin> + 'd,
d13: impl Unborrow<Target = impl D13Pin> + 'd,
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
config: Config,
) -> Self {
unborrow!(peri, dma, irq);
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
configure!(pixclk);
Self::new_inner(peri, dma, irq, config, true, 0b11)
}
fn new_inner(
peri: T,
dma: Dma,
irq: T::Interrupt,
config: Config,
use_embedded_synchronization: bool,
edm: u8,
) -> Self {
T::reset();
T::enable();
unborrow!(
peri, dma, irq, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, v_sync,
h_sync, pixclk
);
d0.configure();
d1.configure();
d2.configure();
d3.configure();
d4.configure();
d5.configure();
d6.configure();
d7.configure();
d8.configure();
d9.configure();
d10.configure();
d11.configure();
d12.configure();
d13.configure();
v_sync.configure();
h_sync.configure();
pixclk.configure();
let edm = match (
d8.pin().is_some(),
d9.pin().is_some(),
d10.pin().is_some(),
d11.pin().is_some(),
d12.pin().is_some(),
d13.pin().is_some(),
) {
(true, true, true, true, true, true) => 0b11, // 14 bits
(true, true, true, true, false, false) => 0b10, // 12 bits
(true, true, false, false, false, false) => 0b01, // 10 bits
(false, false, false, false, false, false) => 0b00, // 8 bits
_ => {
panic!("Invalid pin configuration.");
}
};
unsafe {
peri.regs().cr().modify(|r| {
r.set_cm(true); // disable continuous mode (snapshot mode)
r.set_ess(use_embedded_synchronization);
r.set_pckpol(pixclk_polarity == PixelClockPolarity::RisingEdge);
r.set_vspol(vsync_level == VSyncDataInvalidLevel::High);
r.set_hspol(hsync_level == HSyncDataInvalidLevel::High);
r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge);
r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High);
r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High);
r.set_fcrc(0x00); // capture every frame
r.set_edm(edm); // extended data mode
});
@ -271,14 +443,6 @@ mod sealed {
};
}
macro_rules! optional_pin {
($name:ident) => {
pub trait $name: crate::gpio::OptionalPin {
fn configure(&mut self);
}
};
}
pin!(D0Pin);
pin!(D1Pin);
pin!(D2Pin);
@ -287,15 +451,15 @@ mod sealed {
pin!(D5Pin);
pin!(D6Pin);
pin!(D7Pin);
optional_pin!(D8Pin);
optional_pin!(D9Pin);
optional_pin!(D10Pin);
optional_pin!(D11Pin);
optional_pin!(D12Pin);
optional_pin!(D13Pin);
pin!(D8Pin);
pin!(D9Pin);
pin!(D10Pin);
pin!(D11Pin);
pin!(D12Pin);
pin!(D13Pin);
optional_pin!(HSyncPin);
optional_pin!(VSyncPin);
pin!(HSyncPin);
pin!(VSyncPin);
pin!(PixClkPin);
}
@ -408,24 +572,6 @@ macro_rules! impl_pin {
};
}
macro_rules! impl_no_pin {
($signal:ident) => {
impl sealed::$signal for crate::gpio::NoPin {
fn configure(&mut self) {}
}
impl $signal for crate::gpio::NoPin {}
};
}
impl_no_pin!(D8Pin);
impl_no_pin!(D9Pin);
impl_no_pin!(D10Pin);
impl_no_pin!(D11Pin);
impl_no_pin!(D12Pin);
impl_no_pin!(D13Pin);
impl_no_pin!(HSyncPin);
impl_no_pin!(VSyncPin);
crate::pac::peripheral_pins!(
($inst:ident, dcmi, DCMI, $pin:ident, D0, $af:expr) => {
impl_pin!($pin, D0Pin, $af);

View File

@ -544,54 +544,6 @@ impl sealed::Pin for AnyPin {
// ====================
pub trait OptionalPin: sealed::OptionalPin + Sized {
type Pin: Pin;
fn pin(&self) -> Option<&Self::Pin>;
fn pin_mut(&mut self) -> Option<&mut Self::Pin>;
/// Convert from concrete pin type PX_XX to type erased `Option<AnyPin>`.
#[inline]
fn degrade_optional(mut self) -> Option<AnyPin> {
self.pin_mut()
.map(|pin| unsafe { core::ptr::read(pin) }.degrade())
}
}
impl<T: Pin> sealed::OptionalPin for T {}
impl<T: Pin> OptionalPin for T {
type Pin = T;
#[inline]
fn pin(&self) -> Option<&T> {
Some(self)
}
#[inline]
fn pin_mut(&mut self) -> Option<&mut T> {
Some(self)
}
}
#[derive(Clone, Copy, Debug)]
pub struct NoPin;
unsafe_impl_unborrow!(NoPin);
impl sealed::OptionalPin for NoPin {}
impl OptionalPin for NoPin {
type Pin = AnyPin;
#[inline]
fn pin(&self) -> Option<&AnyPin> {
None
}
#[inline]
fn pin_mut(&mut self) -> Option<&mut AnyPin> {
None
}
}
// ====================
crate::pac::pins!(
($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => {
impl Pin for peripherals::$pin_name {

View File

@ -248,31 +248,6 @@ crate::pac::interrupts! {
};
}
#[allow(unused)]
macro_rules! impl_pwm_nopin {
($inst:ident) => {
impl_no_pin!($inst, Channel1Pin);
impl_no_pin!($inst, Channel1ComplementaryPin);
impl_no_pin!($inst, Channel2Pin);
impl_no_pin!($inst, Channel2ComplementaryPin);
impl_no_pin!($inst, Channel3Pin);
impl_no_pin!($inst, Channel3ComplementaryPin);
impl_no_pin!($inst, Channel4Pin);
impl_no_pin!($inst, Channel4ComplementaryPin);
impl_no_pin!($inst, ExternalTriggerPin);
impl_no_pin!($inst, BreakInputPin);
impl_no_pin!($inst, BreakInputComparator1Pin);
impl_no_pin!($inst, BreakInputComparator2Pin);
impl_no_pin!($inst, BreakInput2Pin);
impl_no_pin!($inst, BreakInput2Comparator1Pin);
impl_no_pin!($inst, BreakInput2Comparator2Pin);
};
}
crate::pac::peripherals!(
(timer, $inst:ident) => { impl_pwm_nopin!($inst); };
);
crate::pac::peripheral_pins!(
($inst:ident, timer, $block:ident, $pin:ident, CH1, $af:expr) => {
impl_pin!($inst, Channel1Pin, $pin, $af);

View File

@ -1,4 +1,4 @@
use crate::gpio::OptionalPin;
use crate::gpio::Pin;
#[cfg(feature = "unstable-pac")]
pub mod low_level {
@ -6,118 +6,106 @@ pub mod low_level {
}
pub(crate) mod sealed {
use crate::gpio::sealed::OptionalPin;
use crate::gpio::sealed::Pin;
pub trait Channel1Pin<Timer>: OptionalPin {
pub trait Channel1Pin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait Channel1ComplementaryPin<Timer>: OptionalPin {
pub trait Channel1ComplementaryPin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait Channel2Pin<Timer>: OptionalPin {
pub trait Channel2Pin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait Channel2ComplementaryPin<Timer>: OptionalPin {
pub trait Channel2ComplementaryPin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait Channel3Pin<Timer>: OptionalPin {
pub trait Channel3Pin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait Channel3ComplementaryPin<Timer>: OptionalPin {
pub trait Channel3ComplementaryPin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait Channel4Pin<Timer>: OptionalPin {
pub trait Channel4Pin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait Channel4ComplementaryPin<Timer>: OptionalPin {
pub trait Channel4ComplementaryPin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait ExternalTriggerPin<Timer>: OptionalPin {
pub trait ExternalTriggerPin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait BreakInputPin<Timer>: OptionalPin {
pub trait BreakInputPin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait BreakInputComparator1Pin<Timer>: OptionalPin {
pub trait BreakInputComparator1Pin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait BreakInputComparator2Pin<Timer>: OptionalPin {
pub trait BreakInputComparator2Pin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait BreakInput2Pin<Timer>: OptionalPin {
pub trait BreakInput2Pin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait BreakInput2Comparator1Pin<Timer>: OptionalPin {
pub trait BreakInput2Comparator1Pin<Timer>: Pin {
unsafe fn configure(&mut self);
}
pub trait BreakInput2Comparator2Pin<Timer>: OptionalPin {
pub trait BreakInput2Comparator2Pin<Timer>: Pin {
unsafe fn configure(&mut self);
}
}
pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + OptionalPin + 'static {}
pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + Pin + 'static {}
pub trait Channel1ComplementaryPin<Timer>:
sealed::Channel1ComplementaryPin<Timer> + OptionalPin + 'static
sealed::Channel1ComplementaryPin<Timer> + Pin + 'static
{
}
pub trait Channel2Pin<Timer>: sealed::Channel2Pin<Timer> + 'static {}
pub trait Channel2ComplementaryPin<Timer>:
sealed::Channel2ComplementaryPin<Timer> + OptionalPin + 'static
sealed::Channel2ComplementaryPin<Timer> + Pin + 'static
{
}
pub trait Channel3Pin<Timer>: sealed::Channel3Pin<Timer> + 'static {}
pub trait Channel3ComplementaryPin<Timer>:
sealed::Channel3ComplementaryPin<Timer> + OptionalPin + 'static
sealed::Channel3ComplementaryPin<Timer> + Pin + 'static
{
}
pub trait Channel4Pin<Timer>: sealed::Channel4Pin<Timer> + 'static {}
pub trait Channel4ComplementaryPin<Timer>:
sealed::Channel4ComplementaryPin<Timer> + OptionalPin + 'static
sealed::Channel4ComplementaryPin<Timer> + Pin + 'static
{
}
pub trait ExternalTriggerPin<Timer>:
sealed::ExternalTriggerPin<Timer> + OptionalPin + 'static
{
}
pub trait ExternalTriggerPin<Timer>: sealed::ExternalTriggerPin<Timer> + Pin + 'static {}
pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + OptionalPin + 'static {}
pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + Pin + 'static {}
pub trait BreakInputComparator1Pin<Timer>:
sealed::BreakInputComparator1Pin<Timer> + OptionalPin + 'static
sealed::BreakInputComparator1Pin<Timer> + Pin + 'static
{
}
pub trait BreakInputComparator2Pin<Timer>:
sealed::BreakInputComparator2Pin<Timer> + OptionalPin + 'static
sealed::BreakInputComparator2Pin<Timer> + Pin + 'static
{
}
pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + OptionalPin + 'static {}
pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + Pin + 'static {}
pub trait BreakInput2Comparator1Pin<Timer>:
sealed::BreakInput2Comparator1Pin<Timer> + OptionalPin + 'static
sealed::BreakInput2Comparator1Pin<Timer> + Pin + 'static
{
}
pub trait BreakInput2Comparator2Pin<Timer>:
sealed::BreakInput2Comparator2Pin<Timer> + OptionalPin + 'static
sealed::BreakInput2Comparator2Pin<Timer> + Pin + 'static
{
}
macro_rules! impl_no_pin {
($timer:ident, $signal:ident) => {
impl crate::pwm::pins::sealed::$signal<crate::peripherals::$timer> for crate::gpio::NoPin {
unsafe fn configure(&mut self) {}
}
impl crate::pwm::pins::$signal<crate::peripherals::$timer> for crate::gpio::NoPin {}
};
}
#[allow(unused)]
macro_rules! impl_pin {
($timer:ident, $signal:ident, $pin:ident, $af:expr) => {

View File

@ -12,7 +12,46 @@ pub struct SimplePwm<'d, T> {
}
impl<'d, T: CaptureCompareCapable16bitInstance> SimplePwm<'d, T> {
pub fn new<F: Into<Hertz>>(
pub fn new_1ch<F: Into<Hertz>>(
tim: impl Unborrow<Target = T> + 'd,
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
freq: F,
) -> Self {
unborrow!(ch1);
Self::new_inner(tim, freq, move || unsafe {
ch1.configure();
})
}
pub fn new_2ch<F: Into<Hertz>>(
tim: impl Unborrow<Target = T> + 'd,
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
freq: F,
) -> Self {
unborrow!(ch1, ch2);
Self::new_inner(tim, freq, move || unsafe {
ch1.configure();
ch2.configure();
})
}
pub fn new_3ch<F: Into<Hertz>>(
tim: impl Unborrow<Target = T> + 'd,
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
ch3: impl Unborrow<Target = impl Channel3Pin<T>> + 'd,
freq: F,
) -> Self {
unborrow!(ch1, ch2, ch3);
Self::new_inner(tim, freq, move || unsafe {
ch1.configure();
ch2.configure();
ch3.configure();
})
}
pub fn new_4ch<F: Into<Hertz>>(
tim: impl Unborrow<Target = T> + 'd,
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
@ -20,17 +59,26 @@ impl<'d, T: CaptureCompareCapable16bitInstance> SimplePwm<'d, T> {
ch4: impl Unborrow<Target = impl Channel4Pin<T>> + 'd,
freq: F,
) -> Self {
unborrow!(tim, ch1, ch2, ch3, ch4);
T::enable();
<T as crate::rcc::sealed::RccPeripheral>::reset();
unsafe {
unborrow!(ch1, ch2, ch3, ch4);
Self::new_inner(tim, freq, move || unsafe {
ch1.configure();
ch2.configure();
ch3.configure();
ch4.configure();
}
})
}
fn new_inner<F: Into<Hertz>>(
tim: impl Unborrow<Target = T> + 'd,
freq: F,
configure_pins: impl FnOnce(),
) -> Self {
unborrow!(tim);
T::enable();
<T as crate::rcc::sealed::RccPeripheral>::reset();
configure_pins();
let mut this = Self {
inner: tim,

View File

@ -8,8 +8,8 @@ use embassy_hal_common::unborrow;
use self::sealed::WordSize;
use crate::dma;
use crate::dma::NoDma;
use crate::gpio::sealed::{AFType, Pin};
use crate::gpio::{AnyPin, NoPin, OptionalPin};
use crate::gpio::sealed::{AFType, Pin as _};
use crate::gpio::{AnyPin, Pin};
use crate::pac::spi::{regs, vals};
use crate::peripherals;
use crate::rcc::RccPeripheral;
@ -92,10 +92,116 @@ pub struct Spi<'d, T: Instance, Tx, Rx> {
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
pub fn new<F>(
peri: impl Unborrow<Target = T> + 'd,
sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd,
miso: impl Unborrow<Target = impl MisoPin<T>> + 'd,
txdma: impl Unborrow<Target = Tx> + 'd,
rxdma: impl Unborrow<Target = Rx> + 'd,
freq: F,
config: Config,
) -> Self
where
F: Into<Hertz>,
{
unborrow!(sck, mosi, miso);
unsafe {
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
#[cfg(any(spi_v2, spi_v3))]
sck.set_speed(crate::gpio::Speed::VeryHigh);
mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
#[cfg(any(spi_v2, spi_v3))]
mosi.set_speed(crate::gpio::Speed::VeryHigh);
miso.set_as_af(miso.af_num(), AFType::Input);
#[cfg(any(spi_v2, spi_v3))]
miso.set_speed(crate::gpio::Speed::VeryHigh);
}
Self::new_inner(
peri,
Some(sck.degrade()),
Some(mosi.degrade()),
Some(miso.degrade()),
txdma,
rxdma,
freq,
config,
)
}
pub fn new_rxonly<F>(
peri: impl Unborrow<Target = T> + 'd,
sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
miso: impl Unborrow<Target = impl MisoPin<T>> + 'd,
txdma: impl Unborrow<Target = Tx> + 'd, // TODO remove
rxdma: impl Unborrow<Target = Rx> + 'd,
freq: F,
config: Config,
) -> Self
where
F: Into<Hertz>,
{
unborrow!(sck, miso);
unsafe {
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
#[cfg(any(spi_v2, spi_v3))]
sck.set_speed(crate::gpio::Speed::VeryHigh);
miso.set_as_af(miso.af_num(), AFType::Input);
#[cfg(any(spi_v2, spi_v3))]
miso.set_speed(crate::gpio::Speed::VeryHigh);
}
Self::new_inner(
peri,
Some(sck.degrade()),
None,
Some(miso.degrade()),
txdma,
rxdma,
freq,
config,
)
}
pub fn new_txonly<F>(
peri: impl Unborrow<Target = T> + 'd,
sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd,
txdma: impl Unborrow<Target = Tx> + 'd,
rxdma: impl Unborrow<Target = Rx> + 'd, // TODO remove
freq: F,
config: Config,
) -> Self
where
F: Into<Hertz>,
{
unborrow!(sck, mosi);
unsafe {
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
#[cfg(any(spi_v2, spi_v3))]
sck.set_speed(crate::gpio::Speed::VeryHigh);
mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
#[cfg(any(spi_v2, spi_v3))]
mosi.set_speed(crate::gpio::Speed::VeryHigh);
}
Self::new_inner(
peri,
Some(sck.degrade()),
Some(mosi.degrade()),
None,
txdma,
rxdma,
freq,
config,
)
}
fn new_inner<F>(
_peri: impl Unborrow<Target = T> + 'd,
sck: impl Unborrow<Target = impl SckPin<T>>,
mosi: impl Unborrow<Target = impl MosiPin<T>>,
miso: impl Unborrow<Target = impl MisoPin<T>>,
sck: Option<AnyPin>,
mosi: Option<AnyPin>,
miso: Option<AnyPin>,
txdma: impl Unborrow<Target = Tx>,
rxdma: impl Unborrow<Target = Rx>,
freq: F,
@ -104,32 +210,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
where
F: Into<Hertz>,
{
unborrow!(sck, mosi, miso, txdma, rxdma);
let sck_af = sck.af_num();
let mosi_af = mosi.af_num();
let miso_af = miso.af_num();
let sck = sck.degrade_optional();
let mosi = mosi.degrade_optional();
let miso = miso.degrade_optional();
unsafe {
sck.as_ref().map(|x| {
x.set_as_af(sck_af, AFType::OutputPushPull);
#[cfg(any(spi_v2, spi_v3))]
x.set_speed(crate::gpio::Speed::VeryHigh);
});
mosi.as_ref().map(|x| {
x.set_as_af(mosi_af, AFType::OutputPushPull);
#[cfg(any(spi_v2, spi_v3))]
x.set_speed(crate::gpio::Speed::VeryHigh);
});
miso.as_ref().map(|x| {
x.set_as_af(miso_af, AFType::Input);
#[cfg(any(spi_v2, spi_v3))]
x.set_speed(crate::gpio::Speed::VeryHigh);
});
}
unborrow!(txdma, rxdma);
let pclk = T::frequency();
let br = compute_baud_rate(pclk, freq.into());
@ -719,15 +800,15 @@ pub(crate) mod sealed {
fn regs() -> &'static crate::pac::spi::Spi;
}
pub trait SckPin<T: Instance>: OptionalPin {
pub trait SckPin<T: Instance>: Pin {
fn af_num(&self) -> u8;
}
pub trait MosiPin<T: Instance>: OptionalPin {
pub trait MosiPin<T: Instance>: Pin {
fn af_num(&self) -> u8;
}
pub trait MisoPin<T: Instance>: OptionalPin {
pub trait MisoPin<T: Instance>: Pin {
fn af_num(&self) -> u8;
}
@ -865,26 +946,6 @@ crate::pac::peripheral_pins!(
};
);
macro_rules! impl_nopin {
($inst:ident, $signal:ident) => {
impl $signal<peripherals::$inst> for NoPin {}
impl sealed::$signal<peripherals::$inst> for NoPin {
fn af_num(&self) -> u8 {
0
}
}
};
}
crate::pac::peripherals!(
(spi, $inst:ident) => {
impl_nopin!($inst, SckPin);
impl_nopin!($inst, MosiPin);
impl_nopin!($inst, MisoPin);
};
);
macro_rules! impl_dma {
($inst:ident, {dmamux: $dmamux:ident}, $signal:ident, $request:expr) => {
impl<T> sealed::$signal<peripherals::$inst> for T

View File

@ -215,11 +215,11 @@ impl<'d, Tx, Rx> SubGhz<'d, Tx, Rx> {
/// clock.
pub fn new(
peri: impl Unborrow<Target = SUBGHZSPI> + 'd,
sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>>,
mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>>,
miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>>,
txdma: impl Unborrow<Target = Tx>,
rxdma: impl Unborrow<Target = Rx>,
sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>> + 'd,
mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>> + 'd,
miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>> + 'd,
txdma: impl Unborrow<Target = Tx> + 'd,
rxdma: impl Unborrow<Target = Rx> + 'd,
) -> Self {
Self::pulse_radio_reset();

View File

@ -6,7 +6,6 @@
mod example_common;
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy_stm32::gpio::NoPin;
use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
use embassy_stm32::time::U32Ext;
use embassy_stm32::Peripherals;
@ -16,7 +15,7 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
let mut pwm = SimplePwm::new(p.TIM2, p.PA5, NoPin, NoPin, NoPin, 10000.hz());
let mut pwm = SimplePwm::new_1ch(p.TIM2, p.PA5, 10000.hz());
let max = pwm.get_max_duty();
pwm.enable(Channel::Ch1);

View File

@ -4,8 +4,8 @@
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy_stm32::dcmi::*;
use embassy_stm32::gpio::{Level, NoPin, Output, Speed};
use embassy_stm32::dcmi::{self, *};
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::i2c::I2c;
use embassy_stm32::interrupt;
use embassy_stm32::rcc::{Mco, Mco1Source, McoClock};
@ -78,31 +78,10 @@ async fn main(_spawner: Spawner, p: Peripherals) {
);
let dcmi_irq = interrupt::take!(DCMI);
let mut dcmi = Dcmi::new(
p.DCMI,
p.DMA1_CH0,
VSyncDataInvalidLevel::High,
HSyncDataInvalidLevel::Low,
PixelClockPolarity::RisingEdge,
false,
dcmi_irq,
p.PC6,
p.PC7,
p.PE0,
p.PE1,
p.PE4,
p.PD3,
p.PE5,
p.PE6,
NoPin,
NoPin,
NoPin,
NoPin,
NoPin,
NoPin,
p.PB7,
p.PA4,
p.PA6,
let config = dcmi::Config::default();
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, config,
);
defmt::info!("attempting capture");

View File

@ -5,7 +5,6 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy_stm32::gpio::NoPin;
use example_common::*;
use cortex_m_rt::entry;
@ -17,7 +16,7 @@ fn main() -> ! {
let p = embassy_stm32::init(config());
let mut dac = Dac::new(p.DAC1, p.PA4, NoPin);
let mut dac = Dac::new_1ch(p.DAC1, p.PA4);
loop {
for v in 0..=255 {

View File

@ -10,7 +10,6 @@ use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy::util::Unborrow;
use embassy_hal_common::unborrow;
use embassy_stm32::gpio::NoPin;
use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode};
use embassy_stm32::time::{Hertz, U32Ext};
use embassy_stm32::timer::GeneralPurpose32bitInstance;
@ -33,7 +32,7 @@ pub fn config() -> Config {
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
let mut pwm = SimplePwm32::new(p.TIM5, p.PA0, NoPin, NoPin, NoPin, 10000.hz());
let mut pwm = SimplePwm32::new(p.TIM5, p.PA0, p.PA1, p.PA2, p.PA3, 10000.hz());
let max = pwm.get_max_duty();
pwm.enable(Channel::Ch1);

View File

@ -6,7 +6,6 @@
mod example_common;
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy_stm32::gpio::NoPin;
use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
use embassy_stm32::time::U32Ext;
use embassy_stm32::{Config, Peripherals};
@ -28,7 +27,7 @@ pub fn config() -> Config {
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
let mut pwm = SimplePwm::new(p.TIM3, p.PA6, NoPin, NoPin, NoPin, 10000.hz());
let mut pwm = SimplePwm::new_1ch(p.TIM3, p.PA6, 10000.hz());
let max = pwm.get_max_duty();
pwm.enable(Channel::Ch1);

View File

@ -6,7 +6,6 @@
mod example_common;
use embassy_stm32::dac::{Channel, Dac, Value};
use embassy_stm32::gpio::NoPin;
use embassy_stm32::pac;
use example_common::*;
@ -22,7 +21,7 @@ fn main() -> ! {
let p = embassy_stm32::init(Default::default());
let mut dac = Dac::new(p.DAC1, p.PA4, NoPin);
let mut dac = Dac::new_1ch(p.DAC1, p.PA4);
loop {
for v in 0..=255 {