Merge pull request #1669 from embassy-rs/nocrlf
ci: add check for no CRLF line endings.
This commit is contained in:
commit
27a3d2cd0b
41
.gitattributes
vendored
Normal file
41
.gitattributes
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
* text=auto
|
||||||
|
|
||||||
|
*.adoc text
|
||||||
|
*.html text
|
||||||
|
*.in text
|
||||||
|
*.json text
|
||||||
|
*.md text
|
||||||
|
*.proto text
|
||||||
|
*.py text
|
||||||
|
*.rs text
|
||||||
|
*.service text
|
||||||
|
*.sh text
|
||||||
|
*.toml text
|
||||||
|
*.txt text
|
||||||
|
*.x text
|
||||||
|
*.yml text
|
||||||
|
|
||||||
|
*.raw binary
|
||||||
|
*.bin binary
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
|
*.jpeg binary
|
||||||
|
*.gif binary
|
||||||
|
*.ico binary
|
||||||
|
*.mov binary
|
||||||
|
*.mp4 binary
|
||||||
|
*.mp3 binary
|
||||||
|
*.flv binary
|
||||||
|
*.fla binary
|
||||||
|
*.swf binary
|
||||||
|
*.gz binary
|
||||||
|
*.zip binary
|
||||||
|
*.7z binary
|
||||||
|
*.ttf binary
|
||||||
|
*.eot binary
|
||||||
|
*.woff binary
|
||||||
|
*.pyc binary
|
||||||
|
*.pdf binary
|
||||||
|
*.ez binary
|
||||||
|
*.bz2 binary
|
||||||
|
*.swp binary
|
17
.github/ci/crlf.sh
vendored
Executable file
17
.github/ci/crlf.sh
vendored
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
## on push branch~=gh-readonly-queue/main/.*
|
||||||
|
## on pull_request
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
FILES_WITH_CRLF=$(find ! -path "./.git/*" -not -type d | xargs file -N | (grep " CRLF " || true))
|
||||||
|
|
||||||
|
if [ -z "$FILES_WITH_CRLF" ]; then
|
||||||
|
echo -e "No files with CRLF endings found."
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
NR_FILES=$(echo "$FILES_WITH_CRLF" | wc -l)
|
||||||
|
echo -e "ERROR: Found ${NR_FILES} files with CRLF endings."
|
||||||
|
echo "$FILES_WITH_CRLF"
|
||||||
|
exit "$NR_FILES"
|
||||||
|
fi
|
@ -1,294 +1,294 @@
|
|||||||
//! Pulse Density Modulation (PDM) mirophone driver.
|
//! Pulse Density Modulation (PDM) mirophone driver.
|
||||||
|
|
||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_hal_common::drop::OnDrop;
|
use embassy_hal_common::drop::OnDrop;
|
||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
|
|
||||||
use crate::chip::EASY_DMA_SIZE;
|
use crate::chip::EASY_DMA_SIZE;
|
||||||
use crate::gpio::sealed::Pin;
|
use crate::gpio::sealed::Pin;
|
||||||
use crate::gpio::{AnyPin, Pin as GpioPin};
|
use crate::gpio::{AnyPin, Pin as GpioPin};
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
use crate::{interrupt, Peripheral};
|
use crate::{interrupt, Peripheral};
|
||||||
|
|
||||||
/// Interrupt handler.
|
/// Interrupt handler.
|
||||||
pub struct InterruptHandler<T: Instance> {
|
pub struct InterruptHandler<T: Instance> {
|
||||||
_phantom: PhantomData<T>,
|
_phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
|
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
unsafe fn on_interrupt() {
|
unsafe fn on_interrupt() {
|
||||||
T::regs().intenclr.write(|w| w.end().clear());
|
T::regs().intenclr.write(|w| w.end().clear());
|
||||||
T::state().waker.wake();
|
T::state().waker.wake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PDM microphone interface
|
/// PDM microphone interface
|
||||||
pub struct Pdm<'d, T: Instance> {
|
pub struct Pdm<'d, T: Instance> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PDM error.
|
/// PDM error.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Buffer is too long.
|
/// Buffer is too long.
|
||||||
BufferTooLong,
|
BufferTooLong,
|
||||||
/// Buffer is empty
|
/// Buffer is empty
|
||||||
BufferZeroLength,
|
BufferZeroLength,
|
||||||
/// PDM is not running
|
/// PDM is not running
|
||||||
NotRunning,
|
NotRunning,
|
||||||
}
|
}
|
||||||
|
|
||||||
static DUMMY_BUFFER: [i16; 1] = [0; 1];
|
static DUMMY_BUFFER: [i16; 1] = [0; 1];
|
||||||
|
|
||||||
impl<'d, T: Instance> Pdm<'d, T> {
|
impl<'d, T: Instance> Pdm<'d, T> {
|
||||||
/// Create PDM driver
|
/// Create PDM driver
|
||||||
pub fn new(
|
pub fn new(
|
||||||
pdm: impl Peripheral<P = T> + 'd,
|
pdm: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
clk: impl Peripheral<P = impl GpioPin> + 'd,
|
clk: impl Peripheral<P = impl GpioPin> + 'd,
|
||||||
din: impl Peripheral<P = impl GpioPin> + 'd,
|
din: impl Peripheral<P = impl GpioPin> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(pdm, clk, din);
|
into_ref!(pdm, clk, din);
|
||||||
Self::new_inner(pdm, clk.map_into(), din.map_into(), config)
|
Self::new_inner(pdm, clk.map_into(), din.map_into(), config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
pdm: PeripheralRef<'d, T>,
|
pdm: PeripheralRef<'d, T>,
|
||||||
clk: PeripheralRef<'d, AnyPin>,
|
clk: PeripheralRef<'d, AnyPin>,
|
||||||
din: PeripheralRef<'d, AnyPin>,
|
din: PeripheralRef<'d, AnyPin>,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(pdm);
|
into_ref!(pdm);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
// setup gpio pins
|
// setup gpio pins
|
||||||
din.conf().write(|w| w.input().set_bit());
|
din.conf().write(|w| w.input().set_bit());
|
||||||
r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) });
|
r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) });
|
||||||
clk.set_low();
|
clk.set_low();
|
||||||
clk.conf().write(|w| w.dir().output());
|
clk.conf().write(|w| w.dir().output());
|
||||||
r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) });
|
r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) });
|
||||||
|
|
||||||
// configure
|
// configure
|
||||||
// use default for
|
// use default for
|
||||||
// - gain right
|
// - gain right
|
||||||
// - gain left
|
// - gain left
|
||||||
// - clk
|
// - clk
|
||||||
// - ratio
|
// - ratio
|
||||||
r.mode.write(|w| {
|
r.mode.write(|w| {
|
||||||
w.edge().bit(config.edge == Edge::LeftRising);
|
w.edge().bit(config.edge == Edge::LeftRising);
|
||||||
w.operation().bit(config.operation_mode == OperationMode::Mono);
|
w.operation().bit(config.operation_mode == OperationMode::Mono);
|
||||||
w
|
w
|
||||||
});
|
});
|
||||||
r.gainl.write(|w| w.gainl().default_gain());
|
r.gainl.write(|w| w.gainl().default_gain());
|
||||||
r.gainr.write(|w| w.gainr().default_gain());
|
r.gainr.write(|w| w.gainr().default_gain());
|
||||||
|
|
||||||
// IRQ
|
// IRQ
|
||||||
T::Interrupt::unpend();
|
T::Interrupt::unpend();
|
||||||
unsafe { T::Interrupt::enable() };
|
unsafe { T::Interrupt::enable() };
|
||||||
|
|
||||||
r.enable.write(|w| w.enable().set_bit());
|
r.enable.write(|w| w.enable().set_bit());
|
||||||
|
|
||||||
Self { _peri: pdm }
|
Self { _peri: pdm }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start sampling microphon data into a dummy buffer
|
/// Start sampling microphon data into a dummy buffer
|
||||||
/// Usefull to start the microphon and keep it active between recording samples
|
/// Usefull to start the microphon and keep it active between recording samples
|
||||||
pub async fn start(&mut self) {
|
pub async fn start(&mut self) {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
// start dummy sampling because microphon needs some setup time
|
// start dummy sampling because microphon needs some setup time
|
||||||
r.sample
|
r.sample
|
||||||
.ptr
|
.ptr
|
||||||
.write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
|
.write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
|
||||||
r.sample
|
r.sample
|
||||||
.maxcnt
|
.maxcnt
|
||||||
.write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
|
.write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
|
||||||
|
|
||||||
r.tasks_start.write(|w| unsafe { w.bits(1) });
|
r.tasks_start.write(|w| unsafe { w.bits(1) });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stop sampling microphon data inta a dummy buffer
|
/// Stop sampling microphon data inta a dummy buffer
|
||||||
pub async fn stop(&mut self) {
|
pub async fn stop(&mut self) {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||||
r.events_started.reset();
|
r.events_started.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sample data into the given buffer.
|
/// Sample data into the given buffer.
|
||||||
pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> {
|
pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> {
|
||||||
if buffer.len() == 0 {
|
if buffer.len() == 0 {
|
||||||
return Err(Error::BufferZeroLength);
|
return Err(Error::BufferZeroLength);
|
||||||
}
|
}
|
||||||
if buffer.len() > EASY_DMA_SIZE {
|
if buffer.len() > EASY_DMA_SIZE {
|
||||||
return Err(Error::BufferTooLong);
|
return Err(Error::BufferTooLong);
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
if r.events_started.read().bits() == 0 {
|
if r.events_started.read().bits() == 0 {
|
||||||
return Err(Error::NotRunning);
|
return Err(Error::NotRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
let drop = OnDrop::new(move || {
|
let drop = OnDrop::new(move || {
|
||||||
r.intenclr.write(|w| w.end().clear());
|
r.intenclr.write(|w| w.end().clear());
|
||||||
r.events_stopped.reset();
|
r.events_stopped.reset();
|
||||||
|
|
||||||
// reset to dummy buffer
|
// reset to dummy buffer
|
||||||
r.sample
|
r.sample
|
||||||
.ptr
|
.ptr
|
||||||
.write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
|
.write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
|
||||||
r.sample
|
r.sample
|
||||||
.maxcnt
|
.maxcnt
|
||||||
.write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
|
.write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
|
||||||
|
|
||||||
while r.events_stopped.read().bits() == 0 {}
|
while r.events_stopped.read().bits() == 0 {}
|
||||||
});
|
});
|
||||||
|
|
||||||
// setup user buffer
|
// setup user buffer
|
||||||
let ptr = buffer.as_ptr();
|
let ptr = buffer.as_ptr();
|
||||||
let len = buffer.len();
|
let len = buffer.len();
|
||||||
r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) });
|
r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) });
|
||||||
r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) });
|
r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) });
|
||||||
|
|
||||||
// wait till the current sample is finished and the user buffer sample is started
|
// wait till the current sample is finished and the user buffer sample is started
|
||||||
Self::wait_for_sample().await;
|
Self::wait_for_sample().await;
|
||||||
|
|
||||||
// reset the buffer back to the dummy buffer
|
// reset the buffer back to the dummy buffer
|
||||||
r.sample
|
r.sample
|
||||||
.ptr
|
.ptr
|
||||||
.write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
|
.write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
|
||||||
r.sample
|
r.sample
|
||||||
.maxcnt
|
.maxcnt
|
||||||
.write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
|
.write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
|
||||||
|
|
||||||
// wait till the user buffer is sampled
|
// wait till the user buffer is sampled
|
||||||
Self::wait_for_sample().await;
|
Self::wait_for_sample().await;
|
||||||
|
|
||||||
drop.defuse();
|
drop.defuse();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn wait_for_sample() {
|
async fn wait_for_sample() {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
r.events_end.reset();
|
r.events_end.reset();
|
||||||
r.intenset.write(|w| w.end().set());
|
r.intenset.write(|w| w.end().set());
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().waker.register(cx.waker());
|
T::state().waker.register(cx.waker());
|
||||||
if r.events_end.read().bits() != 0 {
|
if r.events_end.read().bits() != 0 {
|
||||||
return Poll::Ready(());
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PDM microphone driver Config
|
/// PDM microphone driver Config
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Use stero or mono operation
|
/// Use stero or mono operation
|
||||||
pub operation_mode: OperationMode,
|
pub operation_mode: OperationMode,
|
||||||
/// On which edge the left channel should be samples
|
/// On which edge the left channel should be samples
|
||||||
pub edge: Edge,
|
pub edge: Edge,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
operation_mode: OperationMode::Mono,
|
operation_mode: OperationMode::Mono,
|
||||||
edge: Edge::LeftFalling,
|
edge: Edge::LeftFalling,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PDM operation mode.
|
/// PDM operation mode.
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum OperationMode {
|
pub enum OperationMode {
|
||||||
/// Mono (1 channel)
|
/// Mono (1 channel)
|
||||||
Mono,
|
Mono,
|
||||||
/// Stereo (2 channels)
|
/// Stereo (2 channels)
|
||||||
Stereo,
|
Stereo,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PDM edge polarity
|
/// PDM edge polarity
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum Edge {
|
pub enum Edge {
|
||||||
/// Left edge is rising
|
/// Left edge is rising
|
||||||
LeftRising,
|
LeftRising,
|
||||||
/// Left edge is falling
|
/// Left edge is falling
|
||||||
LeftFalling,
|
LeftFalling,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Drop for Pdm<'d, T> {
|
impl<'d, T: Instance> Drop for Pdm<'d, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||||
|
|
||||||
r.enable.write(|w| w.enable().disabled());
|
r.enable.write(|w| w.enable().disabled());
|
||||||
|
|
||||||
r.psel.din.reset();
|
r.psel.din.reset();
|
||||||
r.psel.clk.reset();
|
r.psel.clk.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
/// Peripheral static state
|
/// Peripheral static state
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub waker: AtomicWaker,
|
pub waker: AtomicWaker,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
waker: AtomicWaker::new(),
|
waker: AtomicWaker::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Instance {
|
pub trait Instance {
|
||||||
fn regs() -> &'static crate::pac::pdm::RegisterBlock;
|
fn regs() -> &'static crate::pac::pdm::RegisterBlock;
|
||||||
fn state() -> &'static State;
|
fn state() -> &'static State;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PDM peripheral instance.
|
/// PDM peripheral instance.
|
||||||
pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
|
pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
|
||||||
/// Interrupt for this peripheral.
|
/// Interrupt for this peripheral.
|
||||||
type Interrupt: interrupt::typelevel::Interrupt;
|
type Interrupt: interrupt::typelevel::Interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_pdm {
|
macro_rules! impl_pdm {
|
||||||
($type:ident, $pac_type:ident, $irq:ident) => {
|
($type:ident, $pac_type:ident, $irq:ident) => {
|
||||||
impl crate::pdm::sealed::Instance for peripherals::$type {
|
impl crate::pdm::sealed::Instance for peripherals::$type {
|
||||||
fn regs() -> &'static crate::pac::pdm::RegisterBlock {
|
fn regs() -> &'static crate::pac::pdm::RegisterBlock {
|
||||||
unsafe { &*pac::$pac_type::ptr() }
|
unsafe { &*pac::$pac_type::ptr() }
|
||||||
}
|
}
|
||||||
fn state() -> &'static crate::pdm::sealed::State {
|
fn state() -> &'static crate::pdm::sealed::State {
|
||||||
static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new();
|
static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new();
|
||||||
&STATE
|
&STATE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl crate::pdm::Instance for peripherals::$type {
|
impl crate::pdm::Instance for peripherals::$type {
|
||||||
type Interrupt = crate::interrupt::typelevel::$irq;
|
type Interrupt = crate::interrupt::typelevel::$irq;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,332 +1,332 @@
|
|||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
pub mod enums;
|
pub mod enums;
|
||||||
|
|
||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
use enums::*;
|
use enums::*;
|
||||||
|
|
||||||
use crate::dma::Transfer;
|
use crate::dma::Transfer;
|
||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::gpio::AnyPin;
|
use crate::gpio::AnyPin;
|
||||||
use crate::pac::quadspi::Quadspi as Regs;
|
use crate::pac::quadspi::Quadspi as Regs;
|
||||||
use crate::rcc::RccPeripheral;
|
use crate::rcc::RccPeripheral;
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{peripherals, Peripheral};
|
||||||
|
|
||||||
pub struct TransferConfig {
|
pub struct TransferConfig {
|
||||||
/// Instraction width (IMODE)
|
/// Instraction width (IMODE)
|
||||||
pub iwidth: QspiWidth,
|
pub iwidth: QspiWidth,
|
||||||
/// Address width (ADMODE)
|
/// Address width (ADMODE)
|
||||||
pub awidth: QspiWidth,
|
pub awidth: QspiWidth,
|
||||||
/// Data width (DMODE)
|
/// Data width (DMODE)
|
||||||
pub dwidth: QspiWidth,
|
pub dwidth: QspiWidth,
|
||||||
/// Instruction Id
|
/// Instruction Id
|
||||||
pub instruction: u8,
|
pub instruction: u8,
|
||||||
/// Flash memory address
|
/// Flash memory address
|
||||||
pub address: Option<u32>,
|
pub address: Option<u32>,
|
||||||
/// Number of dummy cycles (DCYC)
|
/// Number of dummy cycles (DCYC)
|
||||||
pub dummy: DummyCycles,
|
pub dummy: DummyCycles,
|
||||||
/// Length of data
|
/// Length of data
|
||||||
pub data_len: Option<usize>,
|
pub data_len: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TransferConfig {
|
impl Default for TransferConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
iwidth: QspiWidth::NONE,
|
iwidth: QspiWidth::NONE,
|
||||||
awidth: QspiWidth::NONE,
|
awidth: QspiWidth::NONE,
|
||||||
dwidth: QspiWidth::NONE,
|
dwidth: QspiWidth::NONE,
|
||||||
instruction: 0,
|
instruction: 0,
|
||||||
address: None,
|
address: None,
|
||||||
dummy: DummyCycles::_0,
|
dummy: DummyCycles::_0,
|
||||||
data_len: None,
|
data_len: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen.
|
/// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen.
|
||||||
/// If you need other value the whose predefined use `Other` variant.
|
/// If you need other value the whose predefined use `Other` variant.
|
||||||
pub memory_size: MemorySize,
|
pub memory_size: MemorySize,
|
||||||
/// Address size (8/16/24/32-bit)
|
/// Address size (8/16/24/32-bit)
|
||||||
pub address_size: AddressSize,
|
pub address_size: AddressSize,
|
||||||
/// Scalar factor for generating CLK [0-255]
|
/// Scalar factor for generating CLK [0-255]
|
||||||
pub prescaler: u8,
|
pub prescaler: u8,
|
||||||
/// Number of bytes to trigger FIFO threshold flag.
|
/// Number of bytes to trigger FIFO threshold flag.
|
||||||
pub fifo_threshold: FIFOThresholdLevel,
|
pub fifo_threshold: FIFOThresholdLevel,
|
||||||
/// Minimum number of cycles that chip select must be high between issued commands
|
/// Minimum number of cycles that chip select must be high between issued commands
|
||||||
pub cs_high_time: ChipSelectHightTime,
|
pub cs_high_time: ChipSelectHightTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
memory_size: MemorySize::Other(0),
|
memory_size: MemorySize::Other(0),
|
||||||
address_size: AddressSize::_24bit,
|
address_size: AddressSize::_24bit,
|
||||||
prescaler: 128,
|
prescaler: 128,
|
||||||
fifo_threshold: FIFOThresholdLevel::_17Bytes,
|
fifo_threshold: FIFOThresholdLevel::_17Bytes,
|
||||||
cs_high_time: ChipSelectHightTime::_5Cycle,
|
cs_high_time: ChipSelectHightTime::_5Cycle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct Qspi<'d, T: Instance, Dma> {
|
pub struct Qspi<'d, T: Instance, Dma> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
d0: Option<PeripheralRef<'d, AnyPin>>,
|
d0: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
d1: Option<PeripheralRef<'d, AnyPin>>,
|
d1: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
d2: Option<PeripheralRef<'d, AnyPin>>,
|
d2: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
d3: Option<PeripheralRef<'d, AnyPin>>,
|
d3: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
nss: Option<PeripheralRef<'d, AnyPin>>,
|
nss: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
dma: PeripheralRef<'d, Dma>,
|
dma: PeripheralRef<'d, Dma>,
|
||||||
config: Config,
|
config: Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, d0, d1, d2, d3, sck, nss);
|
into_ref!(peri, d0, d1, d2, d3, sck, nss);
|
||||||
|
|
||||||
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
|
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
|
||||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
||||||
nss.set_as_af(nss.af_num(), AFType::OutputPushPull);
|
nss.set_as_af(nss.af_num(), AFType::OutputPushPull);
|
||||||
nss.set_speed(crate::gpio::Speed::VeryHigh);
|
nss.set_speed(crate::gpio::Speed::VeryHigh);
|
||||||
d0.set_as_af(d0.af_num(), AFType::OutputPushPull);
|
d0.set_as_af(d0.af_num(), AFType::OutputPushPull);
|
||||||
d0.set_speed(crate::gpio::Speed::VeryHigh);
|
d0.set_speed(crate::gpio::Speed::VeryHigh);
|
||||||
d1.set_as_af(d1.af_num(), AFType::OutputPushPull);
|
d1.set_as_af(d1.af_num(), AFType::OutputPushPull);
|
||||||
d1.set_speed(crate::gpio::Speed::VeryHigh);
|
d1.set_speed(crate::gpio::Speed::VeryHigh);
|
||||||
d2.set_as_af(d2.af_num(), AFType::OutputPushPull);
|
d2.set_as_af(d2.af_num(), AFType::OutputPushPull);
|
||||||
d2.set_speed(crate::gpio::Speed::VeryHigh);
|
d2.set_speed(crate::gpio::Speed::VeryHigh);
|
||||||
d3.set_as_af(d3.af_num(), AFType::OutputPushPull);
|
d3.set_as_af(d3.af_num(), AFType::OutputPushPull);
|
||||||
d3.set_speed(crate::gpio::Speed::VeryHigh);
|
d3.set_speed(crate::gpio::Speed::VeryHigh);
|
||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
peri,
|
peri,
|
||||||
Some(d0.map_into()),
|
Some(d0.map_into()),
|
||||||
Some(d1.map_into()),
|
Some(d1.map_into()),
|
||||||
Some(d2.map_into()),
|
Some(d2.map_into()),
|
||||||
Some(d3.map_into()),
|
Some(d3.map_into()),
|
||||||
Some(sck.map_into()),
|
Some(sck.map_into()),
|
||||||
Some(nss.map_into()),
|
Some(nss.map_into()),
|
||||||
dma,
|
dma,
|
||||||
config,
|
config,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
d0: Option<PeripheralRef<'d, AnyPin>>,
|
d0: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
d1: Option<PeripheralRef<'d, AnyPin>>,
|
d1: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
d2: Option<PeripheralRef<'d, AnyPin>>,
|
d2: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
d3: Option<PeripheralRef<'d, AnyPin>>,
|
d3: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
nss: Option<PeripheralRef<'d, AnyPin>>,
|
nss: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: impl Peripheral<P = Dma> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma);
|
into_ref!(peri, dma);
|
||||||
|
|
||||||
T::enable();
|
T::enable();
|
||||||
T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into()));
|
T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into()));
|
||||||
|
|
||||||
while T::REGS.sr().read().busy() {}
|
while T::REGS.sr().read().busy() {}
|
||||||
|
|
||||||
T::REGS.cr().write(|w| {
|
T::REGS.cr().write(|w| {
|
||||||
w.set_prescaler(config.prescaler);
|
w.set_prescaler(config.prescaler);
|
||||||
w.set_en(true);
|
w.set_en(true);
|
||||||
});
|
});
|
||||||
T::REGS.dcr().write(|w| {
|
T::REGS.dcr().write(|w| {
|
||||||
w.set_fsize(config.memory_size.into());
|
w.set_fsize(config.memory_size.into());
|
||||||
w.set_csht(config.cs_high_time.into());
|
w.set_csht(config.cs_high_time.into());
|
||||||
w.set_ckmode(false);
|
w.set_ckmode(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
_peri: peri,
|
_peri: peri,
|
||||||
sck,
|
sck,
|
||||||
d0,
|
d0,
|
||||||
d1,
|
d1,
|
||||||
d2,
|
d2,
|
||||||
d3,
|
d3,
|
||||||
nss,
|
nss,
|
||||||
dma,
|
dma,
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn command(&mut self, transaction: TransferConfig) {
|
pub fn command(&mut self, transaction: TransferConfig) {
|
||||||
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
||||||
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
||||||
|
|
||||||
while !T::REGS.sr().read().tcf() {}
|
while !T::REGS.sr().read().tcf() {}
|
||||||
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) {
|
pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) {
|
||||||
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
||||||
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
||||||
|
|
||||||
if let Some(len) = transaction.data_len {
|
if let Some(len) = transaction.data_len {
|
||||||
let current_ar = T::REGS.ar().read().address();
|
let current_ar = T::REGS.ar().read().address();
|
||||||
T::REGS.ccr().modify(|v| {
|
T::REGS.ccr().modify(|v| {
|
||||||
v.set_fmode(QspiMode::IndirectRead.into());
|
v.set_fmode(QspiMode::IndirectRead.into());
|
||||||
});
|
});
|
||||||
T::REGS.ar().write(|v| {
|
T::REGS.ar().write(|v| {
|
||||||
v.set_address(current_ar);
|
v.set_address(current_ar);
|
||||||
});
|
});
|
||||||
|
|
||||||
for idx in 0..len {
|
for idx in 0..len {
|
||||||
while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
|
while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
|
||||||
buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() };
|
buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while !T::REGS.sr().read().tcf() {}
|
while !T::REGS.sr().read().tcf() {}
|
||||||
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) {
|
pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) {
|
||||||
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
||||||
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
||||||
|
|
||||||
if let Some(len) = transaction.data_len {
|
if let Some(len) = transaction.data_len {
|
||||||
T::REGS.ccr().modify(|v| {
|
T::REGS.ccr().modify(|v| {
|
||||||
v.set_fmode(QspiMode::IndirectWrite.into());
|
v.set_fmode(QspiMode::IndirectWrite.into());
|
||||||
});
|
});
|
||||||
|
|
||||||
for idx in 0..len {
|
for idx in 0..len {
|
||||||
while !T::REGS.sr().read().ftf() {}
|
while !T::REGS.sr().read().ftf() {}
|
||||||
unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) };
|
unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while !T::REGS.sr().read().tcf() {}
|
while !T::REGS.sr().read().tcf() {}
|
||||||
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig)
|
pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig)
|
||||||
where
|
where
|
||||||
Dma: QuadDma<T>,
|
Dma: QuadDma<T>,
|
||||||
{
|
{
|
||||||
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
||||||
|
|
||||||
T::REGS.ccr().modify(|v| {
|
T::REGS.ccr().modify(|v| {
|
||||||
v.set_fmode(QspiMode::IndirectRead.into());
|
v.set_fmode(QspiMode::IndirectRead.into());
|
||||||
});
|
});
|
||||||
let current_ar = T::REGS.ar().read().address();
|
let current_ar = T::REGS.ar().read().address();
|
||||||
T::REGS.ar().write(|v| {
|
T::REGS.ar().write(|v| {
|
||||||
v.set_address(current_ar);
|
v.set_address(current_ar);
|
||||||
});
|
});
|
||||||
|
|
||||||
let request = self.dma.request();
|
let request = self.dma.request();
|
||||||
let transfer = unsafe {
|
let transfer = unsafe {
|
||||||
Transfer::new_read(
|
Transfer::new_read(
|
||||||
&mut self.dma,
|
&mut self.dma,
|
||||||
request,
|
request,
|
||||||
T::REGS.dr().as_ptr() as *mut u8,
|
T::REGS.dr().as_ptr() as *mut u8,
|
||||||
buf,
|
buf,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
T::REGS.cr().modify(|v| v.set_dmaen(true));
|
T::REGS.cr().modify(|v| v.set_dmaen(true));
|
||||||
|
|
||||||
transfer.blocking_wait();
|
transfer.blocking_wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig)
|
pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig)
|
||||||
where
|
where
|
||||||
Dma: QuadDma<T>,
|
Dma: QuadDma<T>,
|
||||||
{
|
{
|
||||||
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
self.setup_transaction(QspiMode::IndirectWrite, &transaction);
|
||||||
|
|
||||||
T::REGS.ccr().modify(|v| {
|
T::REGS.ccr().modify(|v| {
|
||||||
v.set_fmode(QspiMode::IndirectWrite.into());
|
v.set_fmode(QspiMode::IndirectWrite.into());
|
||||||
});
|
});
|
||||||
|
|
||||||
let request = self.dma.request();
|
let request = self.dma.request();
|
||||||
let transfer = unsafe {
|
let transfer = unsafe {
|
||||||
Transfer::new_write(
|
Transfer::new_write(
|
||||||
&mut self.dma,
|
&mut self.dma,
|
||||||
request,
|
request,
|
||||||
buf,
|
buf,
|
||||||
T::REGS.dr().as_ptr() as *mut u8,
|
T::REGS.dr().as_ptr() as *mut u8,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
T::REGS.cr().modify(|v| v.set_dmaen(true));
|
T::REGS.cr().modify(|v| v.set_dmaen(true));
|
||||||
|
|
||||||
transfer.blocking_wait();
|
transfer.blocking_wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) {
|
fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) {
|
||||||
T::REGS.fcr().modify(|v| {
|
T::REGS.fcr().modify(|v| {
|
||||||
v.set_csmf(true);
|
v.set_csmf(true);
|
||||||
v.set_ctcf(true);
|
v.set_ctcf(true);
|
||||||
v.set_ctef(true);
|
v.set_ctef(true);
|
||||||
v.set_ctof(true);
|
v.set_ctof(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
while T::REGS.sr().read().busy() {}
|
while T::REGS.sr().read().busy() {}
|
||||||
|
|
||||||
if let Some(len) = transaction.data_len {
|
if let Some(len) = transaction.data_len {
|
||||||
T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1));
|
T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
T::REGS.ccr().write(|v| {
|
T::REGS.ccr().write(|v| {
|
||||||
v.set_fmode(fmode.into());
|
v.set_fmode(fmode.into());
|
||||||
v.set_imode(transaction.iwidth.into());
|
v.set_imode(transaction.iwidth.into());
|
||||||
v.set_instruction(transaction.instruction);
|
v.set_instruction(transaction.instruction);
|
||||||
v.set_admode(transaction.awidth.into());
|
v.set_admode(transaction.awidth.into());
|
||||||
v.set_adsize(self.config.address_size.into());
|
v.set_adsize(self.config.address_size.into());
|
||||||
v.set_dmode(transaction.dwidth.into());
|
v.set_dmode(transaction.dwidth.into());
|
||||||
v.set_abmode(QspiWidth::NONE.into());
|
v.set_abmode(QspiWidth::NONE.into());
|
||||||
v.set_dcyc(transaction.dummy.into());
|
v.set_dcyc(transaction.dummy.into());
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(addr) = transaction.address {
|
if let Some(addr) = transaction.address {
|
||||||
T::REGS.ar().write(|v| {
|
T::REGS.ar().write(|v| {
|
||||||
v.set_address(addr);
|
v.set_address(addr);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub trait Instance {
|
pub trait Instance {
|
||||||
const REGS: Regs;
|
const REGS: Regs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
|
pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
|
||||||
|
|
||||||
pin_trait!(SckPin, Instance);
|
pin_trait!(SckPin, Instance);
|
||||||
pin_trait!(D0Pin, Instance);
|
pin_trait!(D0Pin, Instance);
|
||||||
pin_trait!(D1Pin, Instance);
|
pin_trait!(D1Pin, Instance);
|
||||||
pin_trait!(D2Pin, Instance);
|
pin_trait!(D2Pin, Instance);
|
||||||
pin_trait!(D3Pin, Instance);
|
pin_trait!(D3Pin, Instance);
|
||||||
pin_trait!(NSSPin, Instance);
|
pin_trait!(NSSPin, Instance);
|
||||||
|
|
||||||
dma_trait!(QuadDma, Instance);
|
dma_trait!(QuadDma, Instance);
|
||||||
|
|
||||||
foreach_peripheral!(
|
foreach_peripheral!(
|
||||||
(quadspi, $inst:ident) => {
|
(quadspi, $inst:ident) => {
|
||||||
impl sealed::Instance for peripherals::$inst {
|
impl sealed::Instance for peripherals::$inst {
|
||||||
const REGS: Regs = crate::pac::$inst;
|
const REGS: Regs = crate::pac::$inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance for peripherals::$inst {}
|
impl Instance for peripherals::$inst {}
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user