diff --git a/README.md b/README.md index ffc7899d7..65ccaa967 100644 --- a/README.md +++ b/README.md @@ -100,12 +100,7 @@ Examples are found in the `examples/` folder separated by the chip manufacturer ### Running examples -- Install `probe-rs`. - -```bash -cargo install probe-rs --features cli -``` - +- Install `probe-rs` following the instructions at . - Change directory to the sample's base directory. For example: ```bash diff --git a/cyw43/README.md b/cyw43/README.md index dabdf0471..5b4a5d789 100644 --- a/cyw43/README.md +++ b/cyw43/README.md @@ -23,7 +23,7 @@ TODO: ## Running the examples -- `cargo install probe-rs --features cli` +- Install `probe-rs` following the instructions at . - `cd examples/rp` ### Example 1: Scan the wifi stations - `cargo run --release --bin wifi_scan` diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs index a1f400cfb..20b5c4d58 100644 --- a/embassy-rp/src/pwm.rs +++ b/embassy-rp/src/pwm.rs @@ -81,24 +81,22 @@ impl From for Divmode { } /// PWM driver. -pub struct Pwm<'d, T: Slice> { - inner: PeripheralRef<'d, T>, +pub struct Pwm<'d> { pin_a: Option>, pin_b: Option>, + slice: usize, } -impl<'d, T: Slice> Pwm<'d, T> { +impl<'d> Pwm<'d> { fn new_inner( - inner: impl Peripheral

+ 'd, + slice: usize, a: Option>, b: Option>, b_pull: Pull, config: Config, divmode: Divmode, ) -> Self { - into_ref!(inner); - - let p = inner.regs(); + let p = pac::PWM.ch(slice); p.csr().modify(|w| { w.set_divmode(divmode); w.set_en(false); @@ -117,51 +115,67 @@ impl<'d, T: Slice> Pwm<'d, T> { }); } Self { - inner, + // inner: p.into(), pin_a: a, pin_b: b, + slice, } } /// Create PWM driver without any configured pins. #[inline] - pub fn new_free(inner: impl Peripheral

+ 'd, config: Config) -> Self { - Self::new_inner(inner, None, None, Pull::None, config, Divmode::DIV) + pub fn new_free(slice: impl Peripheral

+ 'd, config: Config) -> Self { + into_ref!(slice); + Self::new_inner(slice.number(), None, None, Pull::None, config, Divmode::DIV) } /// Create PWM driver with a single 'a' as output. #[inline] - pub fn new_output_a( - inner: impl Peripheral

+ 'd, + pub fn new_output_a( + slice: impl Peripheral

+ 'd, a: impl Peripheral

> + 'd, config: Config, ) -> Self { - into_ref!(a); - Self::new_inner(inner, Some(a.map_into()), None, Pull::None, config, Divmode::DIV) + into_ref!(slice, a); + Self::new_inner( + slice.number(), + Some(a.map_into()), + None, + Pull::None, + config, + Divmode::DIV, + ) } /// Create PWM driver with a single 'b' pin as output. #[inline] - pub fn new_output_b( - inner: impl Peripheral

+ 'd, + pub fn new_output_b( + slice: impl Peripheral

+ 'd, b: impl Peripheral

> + 'd, config: Config, ) -> Self { - into_ref!(b); - Self::new_inner(inner, None, Some(b.map_into()), Pull::None, config, Divmode::DIV) + into_ref!(slice, b); + Self::new_inner( + slice.number(), + None, + Some(b.map_into()), + Pull::None, + config, + Divmode::DIV, + ) } /// Create PWM driver with a 'a' and 'b' pins as output. #[inline] - pub fn new_output_ab( - inner: impl Peripheral

+ 'd, + pub fn new_output_ab( + slice: impl Peripheral

+ 'd, a: impl Peripheral

> + 'd, b: impl Peripheral

> + 'd, config: Config, ) -> Self { - into_ref!(a, b); + into_ref!(slice, a, b); Self::new_inner( - inner, + slice.number(), Some(a.map_into()), Some(b.map_into()), Pull::None, @@ -172,30 +186,30 @@ impl<'d, T: Slice> Pwm<'d, T> { /// Create PWM driver with a single 'b' as input pin. #[inline] - pub fn new_input( - inner: impl Peripheral

+ 'd, + pub fn new_input( + slice: impl Peripheral

+ 'd, b: impl Peripheral

> + 'd, b_pull: Pull, mode: InputMode, config: Config, ) -> Self { - into_ref!(b); - Self::new_inner(inner, None, Some(b.map_into()), b_pull, config, mode.into()) + into_ref!(slice, b); + Self::new_inner(slice.number(), None, Some(b.map_into()), b_pull, config, mode.into()) } /// Create PWM driver with a 'a' and 'b' pins in the desired input mode. #[inline] - pub fn new_output_input( - inner: impl Peripheral

+ 'd, + pub fn new_output_input( + slice: impl Peripheral

+ 'd, a: impl Peripheral

> + 'd, b: impl Peripheral

> + 'd, b_pull: Pull, mode: InputMode, config: Config, ) -> Self { - into_ref!(a, b); + into_ref!(slice, a, b); Self::new_inner( - inner, + slice.number(), Some(a.map_into()), Some(b.map_into()), b_pull, @@ -206,7 +220,7 @@ impl<'d, T: Slice> Pwm<'d, T> { /// Set the PWM config. pub fn set_config(&mut self, config: &Config) { - Self::configure(self.inner.regs(), config); + Self::configure(pac::PWM.ch(self.slice), config); } fn configure(p: pac::pwm::Channel, config: &Config) { @@ -228,22 +242,22 @@ impl<'d, T: Slice> Pwm<'d, T> { }); } - /// Advances a slice’s output phase by one count while it is running + /// Advances a slice's output phase by one count while it is running /// by inserting a pulse into the clock enable. The counter /// will not count faster than once per cycle. #[inline] pub fn phase_advance(&mut self) { - let p = self.inner.regs(); + let p = pac::PWM.ch(self.slice); p.csr().write_set(|w| w.set_ph_adv(true)); while p.csr().read().ph_adv() {} } - /// Retards a slice’s output phase by one count while it is running + /// Retards a slice's output phase by one count while it is running /// by deleting a pulse from the clock enable. The counter will not - /// count backward when clock enable is permenantly low. + /// count backward when clock enable is permanently low. #[inline] pub fn phase_retard(&mut self) { - let p = self.inner.regs(); + let p = pac::PWM.ch(self.slice); p.csr().write_set(|w| w.set_ph_ret(true)); while p.csr().read().ph_ret() {} } @@ -251,13 +265,13 @@ impl<'d, T: Slice> Pwm<'d, T> { /// Read PWM counter. #[inline] pub fn counter(&self) -> u16 { - self.inner.regs().ctr().read().ctr() + pac::PWM.ch(self.slice).ctr().read().ctr() } /// Write PWM counter. #[inline] pub fn set_counter(&self, ctr: u16) { - self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) + pac::PWM.ch(self.slice).ctr().write(|w| w.set_ctr(ctr)) } /// Wait for channel interrupt. @@ -281,7 +295,7 @@ impl<'d, T: Slice> Pwm<'d, T> { #[inline] fn bit(&self) -> u32 { - 1 << self.inner.number() as usize + 1 << self.slice as usize } } @@ -291,7 +305,7 @@ pub struct PwmBatch(u32); impl PwmBatch { #[inline] /// Enable a PWM slice in this batch. - pub fn enable(&mut self, pwm: &Pwm<'_, impl Slice>) { + pub fn enable(&mut self, pwm: &Pwm<'_>) { self.0 |= pwm.bit(); } @@ -308,9 +322,9 @@ impl PwmBatch { } } -impl<'d, T: Slice> Drop for Pwm<'d, T> { +impl<'d> Drop for Pwm<'d> { fn drop(&mut self) { - self.inner.regs().csr().write_clear(|w| w.set_en(false)); + pac::PWM.ch(self.slice).csr().write_clear(|w| w.set_en(false)); if let Some(pin) = &self.pin_a { pin.gpio().ctrl().write(|w| w.set_funcsel(31)); } @@ -326,19 +340,14 @@ trait SealedSlice {} #[allow(private_bounds)] pub trait Slice: Peripheral

+ SealedSlice + Sized + 'static { /// Slice number. - fn number(&self) -> u8; - - /// Slice register block. - fn regs(&self) -> pac::pwm::Channel { - pac::PWM.ch(self.number() as _) - } + fn number(&self) -> usize; } macro_rules! slice { ($name:ident, $num:expr) => { impl SealedSlice for peripherals::$name {} impl Slice for peripherals::$name { - fn number(&self) -> u8 { + fn number(&self) -> usize { $num } } diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs index c25ac4d24..536da4ca0 100644 --- a/embassy-stm32/src/ospi/mod.rs +++ b/embassy-stm32/src/ospi/mod.rs @@ -5,13 +5,16 @@ pub mod enums; +use core::marker::PhantomData; + use embassy_embedded_hal::{GetConfig, SetConfig}; use embassy_hal_internal::{into_ref, PeripheralRef}; pub use enums::*; use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits}; -use crate::dma::{word, Transfer}; -use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _}; +use crate::dma::{word, ChannelAndRequest}; +use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; +use crate::mode::{Async, Blocking, Mode as PeriMode}; use crate::pac::octospi::{vals, Octospi as Regs}; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; @@ -154,7 +157,7 @@ pub enum OspiError { } /// OSPI driver. -pub struct Ospi<'d, T: Instance, Dma> { +pub struct Ospi<'d, T: Instance, M: PeriMode> { _peri: PeripheralRef<'d, T>, sck: Option>, d0: Option>, @@ -167,259 +170,13 @@ pub struct Ospi<'d, T: Instance, Dma> { d7: Option>, nss: Option>, dqs: Option>, - dma: PeripheralRef<'d, Dma>, + dma: Option>, + _phantom: PhantomData, config: Config, width: OspiWidth, } -impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { - /// Create new OSPI driver for a single spi external chip - pub fn new_singlespi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::Input, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - None, - None, - None, - None, - None, - None, - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::SING, - false, - ) - } - - /// Create new OSPI driver for a dualspi external chip - pub fn new_dualspi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - None, - None, - None, - None, - None, - None, - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::DUAL, - false, - ) - } - - /// Create new OSPI driver for a quadspi external chip - pub fn new_quadspi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - d2: impl Peripheral

> + 'd, - d3: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, d2, d3, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None); - d3.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - Some(d2.map_into()), - Some(d3.map_into()), - None, - None, - None, - None, - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::QUAD, - false, - ) - } - - /// Create new OSPI driver for two quadspi external chips - pub fn new_dualquadspi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - d2: impl Peripheral

> + 'd, - d3: impl Peripheral

> + 'd, - d4: impl Peripheral

> + 'd, - d5: impl Peripheral

> + 'd, - d6: impl Peripheral

> + 'd, - d7: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, d2, d3, d4, d5, d6, d7, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None); - d3.set_speed(crate::gpio::Speed::VeryHigh); - d4.set_as_af_pull(d4.af_num(), AFType::OutputPushPull, Pull::None); - d4.set_speed(crate::gpio::Speed::VeryHigh); - d5.set_as_af_pull(d5.af_num(), AFType::OutputPushPull, Pull::None); - d5.set_speed(crate::gpio::Speed::VeryHigh); - d6.set_as_af_pull(d6.af_num(), AFType::OutputPushPull, Pull::None); - d6.set_speed(crate::gpio::Speed::VeryHigh); - d7.set_as_af_pull(d7.af_num(), AFType::OutputPushPull, Pull::None); - d7.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - Some(d2.map_into()), - Some(d3.map_into()), - Some(d4.map_into()), - Some(d5.map_into()), - Some(d6.map_into()), - Some(d7.map_into()), - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::QUAD, - true, - ) - } - - /// Create new OSPI driver for octospi external chips - pub fn new_octospi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - d2: impl Peripheral

> + 'd, - d3: impl Peripheral

> + 'd, - d4: impl Peripheral

> + 'd, - d5: impl Peripheral

> + 'd, - d6: impl Peripheral

> + 'd, - d7: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, d2, d3, d4, d5, d6, d7, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None); - d3.set_speed(crate::gpio::Speed::VeryHigh); - d4.set_as_af_pull(d4.af_num(), AFType::OutputPushPull, Pull::None); - d4.set_speed(crate::gpio::Speed::VeryHigh); - d5.set_as_af_pull(d5.af_num(), AFType::OutputPushPull, Pull::None); - d5.set_speed(crate::gpio::Speed::VeryHigh); - d6.set_as_af_pull(d6.af_num(), AFType::OutputPushPull, Pull::None); - d6.set_speed(crate::gpio::Speed::VeryHigh); - d7.set_as_af_pull(d7.af_num(), AFType::OutputPushPull, Pull::None); - d7.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - Some(d2.map_into()), - Some(d3.map_into()), - Some(d4.map_into()), - Some(d5.map_into()), - Some(d6.map_into()), - Some(d7.map_into()), - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::OCTO, - false, - ) - } - +impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { fn new_inner( peri: impl Peripheral

+ 'd, d0: Option>, @@ -433,12 +190,12 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { sck: Option>, nss: Option>, dqs: Option>, - dma: impl Peripheral

+ 'd, + dma: Option>, config: Config, width: OspiWidth, dual_quad: bool, ) -> Self { - into_ref!(peri, dma); + into_ref!(peri); // System configuration T::enable_and_reset(); @@ -519,6 +276,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { nss, dqs, dma, + _phantom: PhantomData, config, width, } @@ -702,170 +460,6 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { Ok(()) } - /// Blocking read with DMA transfer - pub fn blocking_read_dma(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> - where - Dma: OctoDma, - { - if buf.is_empty() { - return Err(OspiError::EmptyBuffer); - } - - // Wait for peripheral to be free - while T::REGS.sr().read().busy() {} - - self.configure_command(&transaction, Some(buf.len()))?; - - let current_address = T::REGS.ar().read().address(); - let current_instruction = T::REGS.ir().read().instruction(); - - // For a indirect read transaction, the transaction begins when the instruction/address is set - T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD)); - if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE { - T::REGS.ir().write(|v| v.set_instruction(current_instruction)); - } else { - T::REGS.ar().write(|v| v.set_address(current_address)); - } - - let request = self.dma.request(); - let transfer = unsafe { - Transfer::new_read( - &mut self.dma, - request, - T::REGS.dr().as_ptr() as *mut W, - buf, - Default::default(), - ) - }; - - T::REGS.cr().modify(|w| w.set_dmaen(true)); - - transfer.blocking_wait(); - - finish_dma(T::REGS); - - Ok(()) - } - - /// Blocking write with DMA transfer - pub fn blocking_write_dma(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> - where - Dma: OctoDma, - { - if buf.is_empty() { - return Err(OspiError::EmptyBuffer); - } - - // Wait for peripheral to be free - while T::REGS.sr().read().busy() {} - - self.configure_command(&transaction, Some(buf.len()))?; - T::REGS - .cr() - .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); - - let request = self.dma.request(); - let transfer = unsafe { - Transfer::new_write( - &mut self.dma, - request, - buf, - T::REGS.dr().as_ptr() as *mut W, - Default::default(), - ) - }; - - T::REGS.cr().modify(|w| w.set_dmaen(true)); - - transfer.blocking_wait(); - - finish_dma(T::REGS); - - Ok(()) - } - - /// Asynchronous read from external device - pub async fn read(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> - where - Dma: OctoDma, - { - if buf.is_empty() { - return Err(OspiError::EmptyBuffer); - } - - // Wait for peripheral to be free - while T::REGS.sr().read().busy() {} - - self.configure_command(&transaction, Some(buf.len()))?; - - let current_address = T::REGS.ar().read().address(); - let current_instruction = T::REGS.ir().read().instruction(); - - // For a indirect read transaction, the transaction begins when the instruction/address is set - T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD)); - if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE { - T::REGS.ir().write(|v| v.set_instruction(current_instruction)); - } else { - T::REGS.ar().write(|v| v.set_address(current_address)); - } - - let request = self.dma.request(); - let transfer = unsafe { - Transfer::new_read( - &mut self.dma, - request, - T::REGS.dr().as_ptr() as *mut W, - buf, - Default::default(), - ) - }; - - T::REGS.cr().modify(|w| w.set_dmaen(true)); - - transfer.await; - - finish_dma(T::REGS); - - Ok(()) - } - - /// Asynchronous write to external device - pub async fn write(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> - where - Dma: OctoDma, - { - if buf.is_empty() { - return Err(OspiError::EmptyBuffer); - } - - // Wait for peripheral to be free - while T::REGS.sr().read().busy() {} - - self.configure_command(&transaction, Some(buf.len()))?; - T::REGS - .cr() - .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); - - let request = self.dma.request(); - let transfer = unsafe { - Transfer::new_write( - &mut self.dma, - request, - buf, - T::REGS.dr().as_ptr() as *mut W, - Default::default(), - ) - }; - - T::REGS.cr().modify(|w| w.set_dmaen(true)); - - transfer.await; - - finish_dma(T::REGS); - - Ok(()) - } - /// Set new bus configuration pub fn set_config(&mut self, config: &Config) { // Wait for busy flag to clear @@ -942,7 +536,470 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { } } -impl<'d, T: Instance, Dma> Drop for Ospi<'d, T, Dma> { +impl<'d, T: Instance> Ospi<'d, T, Blocking> { + /// Create new blocking OSPI driver for a single spi external chip + pub fn new_blocking_singlespi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::Input, Speed::VeryHigh), + None, + None, + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::SING, + false, + ) + } + + /// Create new blocking OSPI driver for a dualspi external chip + pub fn new_blocking_dualspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + None, + None, + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::DUAL, + false, + ) + } + + /// Create new blocking OSPI driver for a quadspi external chip + pub fn new_blocking_quadspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::QUAD, + false, + ) + } + + /// Create new blocking OSPI driver for two quadspi external chips + pub fn new_blocking_dualquadspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + d4: impl Peripheral

> + 'd, + d5: impl Peripheral

> + 'd, + d6: impl Peripheral

> + 'd, + d7: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::QUAD, + true, + ) + } + + /// Create new blocking OSPI driver for octospi external chips + pub fn new_blocking_octospi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + d4: impl Peripheral

> + 'd, + d5: impl Peripheral

> + 'd, + d6: impl Peripheral

> + 'd, + d7: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::OCTO, + false, + ) + } +} + +impl<'d, T: Instance> Ospi<'d, T, Async> { + /// Create new blocking OSPI driver for a single spi external chip + pub fn new_singlespi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::Input, Speed::VeryHigh), + None, + None, + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::SING, + false, + ) + } + + /// Create new blocking OSPI driver for a dualspi external chip + pub fn new_dualspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + None, + None, + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::DUAL, + false, + ) + } + + /// Create new blocking OSPI driver for a quadspi external chip + pub fn new_quadspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::QUAD, + false, + ) + } + + /// Create new blocking OSPI driver for two quadspi external chips + pub fn new_dualquadspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + d4: impl Peripheral

> + 'd, + d5: impl Peripheral

> + 'd, + d6: impl Peripheral

> + 'd, + d7: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::QUAD, + true, + ) + } + + /// Create new blocking OSPI driver for octospi external chips + pub fn new_octospi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + d4: impl Peripheral

> + 'd, + d5: impl Peripheral

> + 'd, + d6: impl Peripheral

> + 'd, + d7: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::OCTO, + false, + ) + } + + /// Blocking read with DMA transfer + pub fn blocking_read_dma(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> { + if buf.is_empty() { + return Err(OspiError::EmptyBuffer); + } + + // Wait for peripheral to be free + while T::REGS.sr().read().busy() {} + + self.configure_command(&transaction, Some(buf.len()))?; + + let current_address = T::REGS.ar().read().address(); + let current_instruction = T::REGS.ir().read().instruction(); + + // For a indirect read transaction, the transaction begins when the instruction/address is set + T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD)); + if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE { + T::REGS.ir().write(|v| v.set_instruction(current_instruction)); + } else { + T::REGS.ar().write(|v| v.set_address(current_address)); + } + + let transfer = unsafe { + self.dma + .as_mut() + .unwrap() + .read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default()) + }; + + T::REGS.cr().modify(|w| w.set_dmaen(true)); + + transfer.blocking_wait(); + + finish_dma(T::REGS); + + Ok(()) + } + + /// Blocking write with DMA transfer + pub fn blocking_write_dma(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> { + if buf.is_empty() { + return Err(OspiError::EmptyBuffer); + } + + // Wait for peripheral to be free + while T::REGS.sr().read().busy() {} + + self.configure_command(&transaction, Some(buf.len()))?; + T::REGS + .cr() + .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); + + let transfer = unsafe { + self.dma + .as_mut() + .unwrap() + .write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default()) + }; + + T::REGS.cr().modify(|w| w.set_dmaen(true)); + + transfer.blocking_wait(); + + finish_dma(T::REGS); + + Ok(()) + } + + /// Asynchronous read from external device + pub async fn read(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> { + if buf.is_empty() { + return Err(OspiError::EmptyBuffer); + } + + // Wait for peripheral to be free + while T::REGS.sr().read().busy() {} + + self.configure_command(&transaction, Some(buf.len()))?; + + let current_address = T::REGS.ar().read().address(); + let current_instruction = T::REGS.ir().read().instruction(); + + // For a indirect read transaction, the transaction begins when the instruction/address is set + T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD)); + if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE { + T::REGS.ir().write(|v| v.set_instruction(current_instruction)); + } else { + T::REGS.ar().write(|v| v.set_address(current_address)); + } + + let transfer = unsafe { + self.dma + .as_mut() + .unwrap() + .read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default()) + }; + + T::REGS.cr().modify(|w| w.set_dmaen(true)); + + transfer.await; + + finish_dma(T::REGS); + + Ok(()) + } + + /// Asynchronous write to external device + pub async fn write(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> { + if buf.is_empty() { + return Err(OspiError::EmptyBuffer); + } + + // Wait for peripheral to be free + while T::REGS.sr().read().busy() {} + + self.configure_command(&transaction, Some(buf.len()))?; + T::REGS + .cr() + .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); + + let transfer = unsafe { + self.dma + .as_mut() + .unwrap() + .write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default()) + }; + + T::REGS.cr().modify(|w| w.set_dmaen(true)); + + transfer.await; + + finish_dma(T::REGS); + + Ok(()) + } +} + +impl<'d, T: Instance, M: PeriMode> Drop for Ospi<'d, T, M> { fn drop(&mut self) { self.sck.as_ref().map(|x| x.set_as_disconnected()); self.d0.as_ref().map(|x| x.set_as_disconnected()); @@ -1005,7 +1062,7 @@ foreach_peripheral!( }; ); -impl<'d, T: Instance, Dma> SetConfig for Ospi<'d, T, Dma> { +impl<'d, T: Instance, M: PeriMode> SetConfig for Ospi<'d, T, M> { type Config = Config; type ConfigError = (); fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { @@ -1014,7 +1071,7 @@ impl<'d, T: Instance, Dma> SetConfig for Ospi<'d, T, Dma> { } } -impl<'d, T: Instance, Dma> GetConfig for Ospi<'d, T, Dma> { +impl<'d, T: Instance, M: PeriMode> GetConfig for Ospi<'d, T, M> { type Config = Config; fn get_config(&self) -> Self::Config { self.get_config() diff --git a/embassy-stm32/src/rcc/f247.rs b/embassy-stm32/src/rcc/f247.rs index 555dd63a1..61f687d30 100644 --- a/embassy-stm32/src/rcc/f247.rs +++ b/embassy-stm32/src/rcc/f247.rs @@ -146,17 +146,18 @@ pub(crate) unsafe fn init(config: Config) { while !PWR.csr1().read().odswrdy() {} } + // Turn on the HSI + RCC.cr().modify(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + + // Use the HSI clock as system clock during the actual clock setup + RCC.cfgr().modify(|w| w.set_sw(Sysclk::HSI)); + while RCC.cfgr().read().sws() != Sysclk::HSI {} + // Configure HSI let hsi = match config.hsi { - false => { - RCC.cr().modify(|w| w.set_hsion(false)); - None - } - true => { - RCC.cr().modify(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - Some(HSI_FREQ) - } + false => None, + true => Some(HSI_FREQ), }; // Configure HSE @@ -260,6 +261,11 @@ pub(crate) unsafe fn init(config: Config) { }); while RCC.cfgr().read().sws() != config.sys {} + // Disable HSI if not used + if !config.hsi { + RCC.cr().modify(|w| w.set_hsion(false)); + } + config.mux.init(); set_clocks!( diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs index 76c06e9f8..e9266c65b 100644 --- a/embassy-stm32/src/rcc/l.rs +++ b/embassy-stm32/src/rcc/l.rs @@ -159,6 +159,13 @@ pub(crate) unsafe fn init(config: Config) { while RCC.cfgr().read().sws() != Sysclk::MSI {} } + #[cfg(stm32wl)] + { + // Set max latency + FLASH.acr().modify(|w| w.set_prften(true)); + FLASH.acr().modify(|w| w.set_latency(2)); + } + // Set voltage scale #[cfg(any(stm32l0, stm32l1))] { diff --git a/examples/rp/src/bin/interrupt.rs b/examples/rp/src/bin/interrupt.rs index d334d35d7..5b9d7027e 100644 --- a/examples/rp/src/bin/interrupt.rs +++ b/examples/rp/src/bin/interrupt.rs @@ -15,7 +15,6 @@ use embassy_executor::Spawner; use embassy_rp::adc::{self, Adc, Blocking}; use embassy_rp::gpio::Pull; use embassy_rp::interrupt; -use embassy_rp::peripherals::PWM_SLICE4; use embassy_rp::pwm::{Config, Pwm}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; @@ -26,7 +25,7 @@ use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; static COUNTER: AtomicU32 = AtomicU32::new(0); -static PWM: Mutex>>> = Mutex::new(RefCell::new(None)); +static PWM: Mutex>> = Mutex::new(RefCell::new(None)); static ADC: Mutex, adc::Channel)>>> = Mutex::new(RefCell::new(None)); static ADC_VALUES: Channel = Channel::new();