mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 08:12:30 +00:00
Merge branch 'main' of github.com:reneherrero/embassy
This commit is contained in:
commit
2f2869f195
@ -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 <https://probe.rs>.
|
||||
- Change directory to the sample's base directory. For example:
|
||||
|
||||
```bash
|
||||
|
@ -23,7 +23,7 @@ TODO:
|
||||
|
||||
## Running the examples
|
||||
|
||||
- `cargo install probe-rs --features cli`
|
||||
- Install `probe-rs` following the instructions at <https://probe.rs>.
|
||||
- `cd examples/rp`
|
||||
### Example 1: Scan the wifi stations
|
||||
- `cargo run --release --bin wifi_scan`
|
||||
|
@ -81,24 +81,22 @@ impl From<InputMode> for Divmode {
|
||||
}
|
||||
|
||||
/// PWM driver.
|
||||
pub struct Pwm<'d, T: Slice> {
|
||||
inner: PeripheralRef<'d, T>,
|
||||
pub struct Pwm<'d> {
|
||||
pin_a: Option<PeripheralRef<'d, AnyPin>>,
|
||||
pin_b: Option<PeripheralRef<'d, AnyPin>>,
|
||||
slice: usize,
|
||||
}
|
||||
|
||||
impl<'d, T: Slice> Pwm<'d, T> {
|
||||
impl<'d> Pwm<'d> {
|
||||
fn new_inner(
|
||||
inner: impl Peripheral<P = T> + 'd,
|
||||
slice: usize,
|
||||
a: Option<PeripheralRef<'d, AnyPin>>,
|
||||
b: Option<PeripheralRef<'d, AnyPin>>,
|
||||
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<P = T> + 'd, config: Config) -> Self {
|
||||
Self::new_inner(inner, None, None, Pull::None, config, Divmode::DIV)
|
||||
pub fn new_free<T: Slice>(slice: impl Peripheral<P = T> + '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<P = T> + 'd,
|
||||
pub fn new_output_a<T: Slice>(
|
||||
slice: impl Peripheral<P = T> + 'd,
|
||||
a: impl Peripheral<P = impl ChannelAPin<T>> + '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<P = T> + 'd,
|
||||
pub fn new_output_b<T: Slice>(
|
||||
slice: impl Peripheral<P = T> + 'd,
|
||||
b: impl Peripheral<P = impl ChannelBPin<T>> + '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<P = T> + 'd,
|
||||
pub fn new_output_ab<T: Slice>(
|
||||
slice: impl Peripheral<P = T> + 'd,
|
||||
a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
|
||||
b: impl Peripheral<P = impl ChannelBPin<T>> + '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<P = T> + 'd,
|
||||
pub fn new_input<T: Slice>(
|
||||
slice: impl Peripheral<P = T> + 'd,
|
||||
b: impl Peripheral<P = impl ChannelBPin<T>> + '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<P = T> + 'd,
|
||||
pub fn new_output_input<T: Slice>(
|
||||
slice: impl Peripheral<P = T> + 'd,
|
||||
a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
|
||||
b: impl Peripheral<P = impl ChannelBPin<T>> + '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<P = Self> + 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
|
||||
}
|
||||
}
|
||||
|
@ -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<PeripheralRef<'d, AnyPin>>,
|
||||
d0: Option<PeripheralRef<'d, AnyPin>>,
|
||||
@ -167,259 +170,13 @@ pub struct Ospi<'d, T: Instance, Dma> {
|
||||
d7: Option<PeripheralRef<'d, AnyPin>>,
|
||||
nss: Option<PeripheralRef<'d, AnyPin>>,
|
||||
dqs: Option<PeripheralRef<'d, AnyPin>>,
|
||||
dma: PeripheralRef<'d, Dma>,
|
||||
dma: Option<ChannelAndRequest<'d>>,
|
||||
_phantom: PhantomData<M>,
|
||||
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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
|
||||
d0: Option<PeripheralRef<'d, AnyPin>>,
|
||||
@ -433,12 +190,12 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||
nss: Option<PeripheralRef<'d, AnyPin>>,
|
||||
dqs: Option<PeripheralRef<'d, AnyPin>>,
|
||||
dma: impl Peripheral<P = Dma> + 'd,
|
||||
dma: Option<ChannelAndRequest<'d>>,
|
||||
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<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError>
|
||||
where
|
||||
Dma: OctoDma<T>,
|
||||
{
|
||||
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<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError>
|
||||
where
|
||||
Dma: OctoDma<T>,
|
||||
{
|
||||
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<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError>
|
||||
where
|
||||
Dma: OctoDma<T>,
|
||||
{
|
||||
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<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError>
|
||||
where
|
||||
Dma: OctoDma<T>,
|
||||
{
|
||||
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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = impl OctoDma<T>> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = impl OctoDma<T>> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = impl OctoDma<T>> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = impl OctoDma<T>> + '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<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||
dma: impl Peripheral<P = impl OctoDma<T>> + '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<W: Word>(&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<W: Word>(&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<W: Word>(&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<W: Word>(&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()
|
||||
|
@ -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!(
|
||||
|
@ -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))]
|
||||
{
|
||||
|
@ -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<CriticalSectionRawMutex, RefCell<Option<Pwm<PWM_SLICE4>>>> = Mutex::new(RefCell::new(None));
|
||||
static PWM: Mutex<CriticalSectionRawMutex, RefCell<Option<Pwm>>> = Mutex::new(RefCell::new(None));
|
||||
static ADC: Mutex<CriticalSectionRawMutex, RefCell<Option<(Adc<Blocking>, adc::Channel)>>> =
|
||||
Mutex::new(RefCell::new(None));
|
||||
static ADC_VALUES: Channel<CriticalSectionRawMutex, u16, 2048> = Channel::new();
|
||||
|
Loading…
Reference in New Issue
Block a user