Merge pull request #2317 from embassy-rs/embassy-rp-rustdoc-2

docs: document all embassy-rp public apis
This commit is contained in:
Ulf Lilleengen 2023-12-19 13:52:21 +00:00 committed by GitHub
commit 5e76c8b41a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 294 additions and 11 deletions

View File

@ -1,3 +1,4 @@
//! ADC driver.
use core::future::poll_fn; use core::future::poll_fn;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem; use core::mem;
@ -16,6 +17,7 @@ use crate::{dma, interrupt, pac, peripherals, Peripheral, RegExt};
static WAKER: AtomicWaker = AtomicWaker::new(); static WAKER: AtomicWaker = AtomicWaker::new();
/// ADC config.
#[non_exhaustive] #[non_exhaustive]
pub struct Config {} pub struct Config {}
@ -30,9 +32,11 @@ enum Source<'p> {
TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>), TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>),
} }
/// ADC channel.
pub struct Channel<'p>(Source<'p>); pub struct Channel<'p>(Source<'p>);
impl<'p> Channel<'p> { impl<'p> Channel<'p> {
/// Create a new ADC channel from pin with the provided [Pull] configuration.
pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self { pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self {
into_ref!(pin); into_ref!(pin);
pin.pad_ctrl().modify(|w| { pin.pad_ctrl().modify(|w| {
@ -49,6 +53,7 @@ impl<'p> Channel<'p> {
Self(Source::Pin(pin.map_into())) Self(Source::Pin(pin.map_into()))
} }
/// Create a new ADC channel for the internal temperature sensor.
pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self { pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self {
let r = pac::ADC; let r = pac::ADC;
r.cs().write_set(|w| w.set_ts_en(true)); r.cs().write_set(|w| w.set_ts_en(true));
@ -83,35 +88,44 @@ impl<'p> Drop for Source<'p> {
} }
} }
/// ADC sample.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(transparent)] #[repr(transparent)]
pub struct Sample(u16); pub struct Sample(u16);
impl Sample { impl Sample {
/// Sample is valid.
pub fn good(&self) -> bool { pub fn good(&self) -> bool {
self.0 < 0x8000 self.0 < 0x8000
} }
/// Sample value.
pub fn value(&self) -> u16 { pub fn value(&self) -> u16 {
self.0 & !0x8000 self.0 & !0x8000
} }
} }
/// ADC error.
#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error { pub enum Error {
/// Error converting value.
ConversionFailed, ConversionFailed,
} }
/// ADC mode.
pub trait Mode {} pub trait Mode {}
/// ADC async mode.
pub struct Async; pub struct Async;
impl Mode for Async {} impl Mode for Async {}
/// ADC blocking mode.
pub struct Blocking; pub struct Blocking;
impl Mode for Blocking {} impl Mode for Blocking {}
/// ADC driver.
pub struct Adc<'d, M: Mode> { pub struct Adc<'d, M: Mode> {
phantom: PhantomData<(&'d ADC, M)>, phantom: PhantomData<(&'d ADC, M)>,
} }
@ -150,6 +164,7 @@ impl<'d, M: Mode> Adc<'d, M> {
while !r.cs().read().ready() {} while !r.cs().read().ready() {}
} }
/// Sample a value from a channel in blocking mode.
pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> { pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> {
let r = Self::regs(); let r = Self::regs();
r.cs().modify(|w| { r.cs().modify(|w| {
@ -166,6 +181,7 @@ impl<'d, M: Mode> Adc<'d, M> {
} }
impl<'d> Adc<'d, Async> { impl<'d> Adc<'d, Async> {
/// Create ADC driver in async mode.
pub fn new( pub fn new(
_inner: impl Peripheral<P = ADC> + 'd, _inner: impl Peripheral<P = ADC> + 'd,
_irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>, _irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>,
@ -194,6 +210,7 @@ impl<'d> Adc<'d, Async> {
.await; .await;
} }
/// Sample a value from a channel until completed.
pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> { pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> {
let r = Self::regs(); let r = Self::regs();
r.cs().modify(|w| { r.cs().modify(|w| {
@ -272,6 +289,7 @@ impl<'d> Adc<'d, Async> {
} }
} }
/// Sample multiple values from a channel using DMA.
#[inline] #[inline]
pub async fn read_many<S: AdcSample>( pub async fn read_many<S: AdcSample>(
&mut self, &mut self,
@ -283,6 +301,7 @@ impl<'d> Adc<'d, Async> {
self.read_many_inner(ch, buf, false, div, dma).await self.read_many_inner(ch, buf, false, div, dma).await
} }
/// Sample multiple values from a channel using DMA with errors inlined in samples.
#[inline] #[inline]
pub async fn read_many_raw( pub async fn read_many_raw(
&mut self, &mut self,
@ -299,6 +318,7 @@ impl<'d> Adc<'d, Async> {
} }
impl<'d> Adc<'d, Blocking> { impl<'d> Adc<'d, Blocking> {
/// Create ADC driver in blocking mode.
pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self { pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self {
Self::setup(); Self::setup();
@ -306,6 +326,7 @@ impl<'d> Adc<'d, Blocking> {
} }
} }
/// Interrupt handler.
pub struct InterruptHandler { pub struct InterruptHandler {
_empty: (), _empty: (),
} }
@ -324,6 +345,7 @@ mod sealed {
pub trait AdcChannel {} pub trait AdcChannel {}
} }
/// ADC sample.
pub trait AdcSample: sealed::AdcSample {} pub trait AdcSample: sealed::AdcSample {}
impl sealed::AdcSample for u16 {} impl sealed::AdcSample for u16 {}
@ -332,7 +354,9 @@ impl AdcSample for u16 {}
impl sealed::AdcSample for u8 {} impl sealed::AdcSample for u8 {}
impl AdcSample for u8 {} impl AdcSample for u8 {}
/// ADC channel.
pub trait AdcChannel: sealed::AdcChannel {} pub trait AdcChannel: sealed::AdcChannel {}
/// ADC pin.
pub trait AdcPin: AdcChannel + gpio::Pin {} pub trait AdcPin: AdcChannel + gpio::Pin {}
macro_rules! impl_pin { macro_rules! impl_pin {

View File

@ -45,15 +45,20 @@ static CLOCKS: Clocks = Clocks {
rtc: AtomicU16::new(0), rtc: AtomicU16::new(0),
}; };
/// Enumeration of supported clock sources. /// Peripheral clock sources.
#[repr(u8)] #[repr(u8)]
#[non_exhaustive] #[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PeriClkSrc { pub enum PeriClkSrc {
/// SYS.
Sys = ClkPeriCtrlAuxsrc::CLK_SYS as _, Sys = ClkPeriCtrlAuxsrc::CLK_SYS as _,
/// PLL SYS.
PllSys = ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS as _, PllSys = ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS as _,
/// PLL USB.
PllUsb = ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB as _, PllUsb = ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB as _,
/// ROSC.
Rosc = ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH as _, Rosc = ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH as _,
/// XOSC.
Xosc = ClkPeriCtrlAuxsrc::XOSC_CLKSRC as _, Xosc = ClkPeriCtrlAuxsrc::XOSC_CLKSRC as _,
// Gpin0 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 as _ , // Gpin0 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ , // Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
@ -83,6 +88,7 @@ pub struct ClockConfig {
} }
impl ClockConfig { impl ClockConfig {
/// Clock configuration derived from external crystal.
pub fn crystal(crystal_hz: u32) -> Self { pub fn crystal(crystal_hz: u32) -> Self {
Self { Self {
rosc: Some(RoscConfig { rosc: Some(RoscConfig {
@ -141,6 +147,7 @@ impl ClockConfig {
} }
} }
/// Clock configuration from internal oscillator.
pub fn rosc() -> Self { pub fn rosc() -> Self {
Self { Self {
rosc: Some(RoscConfig { rosc: Some(RoscConfig {
@ -190,13 +197,18 @@ impl ClockConfig {
// } // }
} }
/// ROSC freq range.
#[repr(u16)] #[repr(u16)]
#[non_exhaustive] #[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RoscRange { pub enum RoscRange {
/// Low range.
Low = pac::rosc::vals::FreqRange::LOW.0, Low = pac::rosc::vals::FreqRange::LOW.0,
/// Medium range (1.33x low)
Medium = pac::rosc::vals::FreqRange::MEDIUM.0, Medium = pac::rosc::vals::FreqRange::MEDIUM.0,
/// High range (2x low)
High = pac::rosc::vals::FreqRange::HIGH.0, High = pac::rosc::vals::FreqRange::HIGH.0,
/// Too high. Should not be used.
TooHigh = pac::rosc::vals::FreqRange::TOOHIGH.0, TooHigh = pac::rosc::vals::FreqRange::TOOHIGH.0,
} }
@ -239,96 +251,136 @@ pub struct PllConfig {
pub post_div2: u8, pub post_div2: u8,
} }
/// Reference /// Reference clock config.
pub struct RefClkConfig { pub struct RefClkConfig {
/// Reference clock source.
pub src: RefClkSrc, pub src: RefClkSrc,
/// Reference clock divider.
pub div: u8, pub div: u8,
} }
/// Reference clock source.
#[non_exhaustive] #[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RefClkSrc { pub enum RefClkSrc {
// main sources /// XOSC.
Xosc, Xosc,
/// ROSC.
Rosc, Rosc,
// aux sources /// PLL USB.
PllUsb, PllUsb,
// Gpin0, // Gpin0,
// Gpin1, // Gpin1,
} }
/// SYS clock source.
#[non_exhaustive] #[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SysClkSrc { pub enum SysClkSrc {
// main sources /// REF.
Ref, Ref,
// aux sources /// PLL SYS.
PllSys, PllSys,
/// PLL USB.
PllUsb, PllUsb,
/// ROSC.
Rosc, Rosc,
/// XOSC.
Xosc, Xosc,
// Gpin0, // Gpin0,
// Gpin1, // Gpin1,
} }
/// SYS clock config.
pub struct SysClkConfig { pub struct SysClkConfig {
/// SYS clock source.
pub src: SysClkSrc, pub src: SysClkSrc,
/// SYS clock divider.
pub div_int: u32, pub div_int: u32,
/// SYS clock fraction.
pub div_frac: u8, pub div_frac: u8,
} }
/// USB clock source.
#[repr(u8)] #[repr(u8)]
#[non_exhaustive] #[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum UsbClkSrc { pub enum UsbClkSrc {
/// PLL USB.
PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _, PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _,
/// PLL SYS.
PllSys = ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS as _, PllSys = ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS as _,
/// ROSC.
Rosc = ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH as _, Rosc = ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH as _,
/// XOSC.
Xosc = ClkUsbCtrlAuxsrc::XOSC_CLKSRC as _, Xosc = ClkUsbCtrlAuxsrc::XOSC_CLKSRC as _,
// Gpin0 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 as _ , // Gpin0 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 as _ , // Gpin1 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
} }
/// USB clock config.
pub struct UsbClkConfig { pub struct UsbClkConfig {
/// USB clock source.
pub src: UsbClkSrc, pub src: UsbClkSrc,
/// USB clock divider.
pub div: u8, pub div: u8,
/// USB clock phase.
pub phase: u8, pub phase: u8,
} }
/// ADC clock source.
#[repr(u8)] #[repr(u8)]
#[non_exhaustive] #[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AdcClkSrc { pub enum AdcClkSrc {
/// PLL USB.
PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _, PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _,
/// PLL SYS.
PllSys = ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS as _, PllSys = ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
/// ROSC.
Rosc = ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH as _, Rosc = ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
/// XOSC.
Xosc = ClkAdcCtrlAuxsrc::XOSC_CLKSRC as _, Xosc = ClkAdcCtrlAuxsrc::XOSC_CLKSRC as _,
// Gpin0 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 as _ , // Gpin0 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 as _ , // Gpin1 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
} }
/// ADC clock config.
pub struct AdcClkConfig { pub struct AdcClkConfig {
/// ADC clock source.
pub src: AdcClkSrc, pub src: AdcClkSrc,
/// ADC clock divider.
pub div: u8, pub div: u8,
/// ADC clock phase.
pub phase: u8, pub phase: u8,
} }
/// RTC clock source.
#[repr(u8)] #[repr(u8)]
#[non_exhaustive] #[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RtcClkSrc { pub enum RtcClkSrc {
/// PLL USB.
PllUsb = ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB as _, PllUsb = ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB as _,
/// PLL SYS.
PllSys = ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS as _, PllSys = ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
/// ROSC.
Rosc = ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH as _, Rosc = ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
/// XOSC.
Xosc = ClkRtcCtrlAuxsrc::XOSC_CLKSRC as _, Xosc = ClkRtcCtrlAuxsrc::XOSC_CLKSRC as _,
// Gpin0 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 as _ , // Gpin0 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 as _ , // Gpin1 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
} }
/// RTC clock config.
pub struct RtcClkConfig { pub struct RtcClkConfig {
/// RTC clock source.
pub src: RtcClkSrc, pub src: RtcClkSrc,
/// RTC clock divider.
pub div_int: u32, pub div_int: u32,
/// RTC clock divider fraction.
pub div_frac: u8, pub div_frac: u8,
/// RTC clock phase.
pub phase: u8, pub phase: u8,
} }
@ -605,10 +657,12 @@ fn configure_rosc(config: RoscConfig) -> u32 {
config.hz config.hz
} }
/// ROSC clock frequency.
pub fn rosc_freq() -> u32 { pub fn rosc_freq() -> u32 {
CLOCKS.rosc.load(Ordering::Relaxed) CLOCKS.rosc.load(Ordering::Relaxed)
} }
/// XOSC clock frequency.
pub fn xosc_freq() -> u32 { pub fn xosc_freq() -> u32 {
CLOCKS.xosc.load(Ordering::Relaxed) CLOCKS.xosc.load(Ordering::Relaxed)
} }
@ -620,34 +674,42 @@ pub fn xosc_freq() -> u32 {
// CLOCKS.gpin1.load(Ordering::Relaxed) // CLOCKS.gpin1.load(Ordering::Relaxed)
// } // }
/// PLL SYS clock frequency.
pub fn pll_sys_freq() -> u32 { pub fn pll_sys_freq() -> u32 {
CLOCKS.pll_sys.load(Ordering::Relaxed) CLOCKS.pll_sys.load(Ordering::Relaxed)
} }
/// PLL USB clock frequency.
pub fn pll_usb_freq() -> u32 { pub fn pll_usb_freq() -> u32 {
CLOCKS.pll_usb.load(Ordering::Relaxed) CLOCKS.pll_usb.load(Ordering::Relaxed)
} }
/// SYS clock frequency.
pub fn clk_sys_freq() -> u32 { pub fn clk_sys_freq() -> u32 {
CLOCKS.sys.load(Ordering::Relaxed) CLOCKS.sys.load(Ordering::Relaxed)
} }
/// REF clock frequency.
pub fn clk_ref_freq() -> u32 { pub fn clk_ref_freq() -> u32 {
CLOCKS.reference.load(Ordering::Relaxed) CLOCKS.reference.load(Ordering::Relaxed)
} }
/// Peripheral clock frequency.
pub fn clk_peri_freq() -> u32 { pub fn clk_peri_freq() -> u32 {
CLOCKS.peri.load(Ordering::Relaxed) CLOCKS.peri.load(Ordering::Relaxed)
} }
/// USB clock frequency.
pub fn clk_usb_freq() -> u32 { pub fn clk_usb_freq() -> u32 {
CLOCKS.usb.load(Ordering::Relaxed) CLOCKS.usb.load(Ordering::Relaxed)
} }
/// ADC clock frequency.
pub fn clk_adc_freq() -> u32 { pub fn clk_adc_freq() -> u32 {
CLOCKS.adc.load(Ordering::Relaxed) CLOCKS.adc.load(Ordering::Relaxed)
} }
/// RTC clock frequency.
pub fn clk_rtc_freq() -> u16 { pub fn clk_rtc_freq() -> u16 {
CLOCKS.rtc.load(Ordering::Relaxed) CLOCKS.rtc.load(Ordering::Relaxed)
} }
@ -708,7 +770,9 @@ fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 {
vco_freq / ((config.post_div1 * config.post_div2) as u32) vco_freq / ((config.post_div1 * config.post_div2) as u32)
} }
/// General purpose input clock pin.
pub trait GpinPin: crate::gpio::Pin { pub trait GpinPin: crate::gpio::Pin {
/// Pin number.
const NR: usize; const NR: usize;
} }
@ -723,12 +787,14 @@ macro_rules! impl_gpinpin {
impl_gpinpin!(PIN_20, 20, 0); impl_gpinpin!(PIN_20, 20, 0);
impl_gpinpin!(PIN_22, 22, 1); impl_gpinpin!(PIN_22, 22, 1);
/// General purpose clock input driver.
pub struct Gpin<'d, T: Pin> { pub struct Gpin<'d, T: Pin> {
gpin: PeripheralRef<'d, AnyPin>, gpin: PeripheralRef<'d, AnyPin>,
_phantom: PhantomData<T>, _phantom: PhantomData<T>,
} }
impl<'d, T: Pin> Gpin<'d, T> { impl<'d, T: Pin> Gpin<'d, T> {
/// Create new gpin driver.
pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> { pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> {
into_ref!(gpin); into_ref!(gpin);
@ -754,7 +820,9 @@ impl<'d, T: Pin> Drop for Gpin<'d, T> {
} }
} }
/// General purpose clock output pin.
pub trait GpoutPin: crate::gpio::Pin { pub trait GpoutPin: crate::gpio::Pin {
/// Pin number.
fn number(&self) -> usize; fn number(&self) -> usize;
} }
@ -773,26 +841,38 @@ impl_gpoutpin!(PIN_23, 1);
impl_gpoutpin!(PIN_24, 2); impl_gpoutpin!(PIN_24, 2);
impl_gpoutpin!(PIN_25, 3); impl_gpoutpin!(PIN_25, 3);
/// Gpout clock source.
#[repr(u8)] #[repr(u8)]
pub enum GpoutSrc { pub enum GpoutSrc {
/// Sys PLL.
PllSys = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS as _, PllSys = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS as _,
// Gpin0 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 as _ , // Gpin0 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 as _ , // Gpin1 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
/// USB PLL.
PllUsb = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB as _, PllUsb = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB as _,
/// ROSC.
Rosc = ClkGpoutCtrlAuxsrc::ROSC_CLKSRC as _, Rosc = ClkGpoutCtrlAuxsrc::ROSC_CLKSRC as _,
/// XOSC.
Xosc = ClkGpoutCtrlAuxsrc::XOSC_CLKSRC as _, Xosc = ClkGpoutCtrlAuxsrc::XOSC_CLKSRC as _,
/// SYS.
Sys = ClkGpoutCtrlAuxsrc::CLK_SYS as _, Sys = ClkGpoutCtrlAuxsrc::CLK_SYS as _,
/// USB.
Usb = ClkGpoutCtrlAuxsrc::CLK_USB as _, Usb = ClkGpoutCtrlAuxsrc::CLK_USB as _,
/// ADC.
Adc = ClkGpoutCtrlAuxsrc::CLK_ADC as _, Adc = ClkGpoutCtrlAuxsrc::CLK_ADC as _,
/// RTC.
Rtc = ClkGpoutCtrlAuxsrc::CLK_RTC as _, Rtc = ClkGpoutCtrlAuxsrc::CLK_RTC as _,
/// REF.
Ref = ClkGpoutCtrlAuxsrc::CLK_REF as _, Ref = ClkGpoutCtrlAuxsrc::CLK_REF as _,
} }
/// General purpose clock output driver.
pub struct Gpout<'d, T: GpoutPin> { pub struct Gpout<'d, T: GpoutPin> {
gpout: PeripheralRef<'d, T>, gpout: PeripheralRef<'d, T>,
} }
impl<'d, T: GpoutPin> Gpout<'d, T> { impl<'d, T: GpoutPin> Gpout<'d, T> {
/// Create new general purpose cloud output.
pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self { pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self {
into_ref!(gpout); into_ref!(gpout);
@ -801,6 +881,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
Self { gpout } Self { gpout }
} }
/// Set clock divider.
pub fn set_div(&self, int: u32, frac: u8) { pub fn set_div(&self, int: u32, frac: u8) {
let c = pac::CLOCKS; let c = pac::CLOCKS;
c.clk_gpout_div(self.gpout.number()).write(|w| { c.clk_gpout_div(self.gpout.number()).write(|w| {
@ -809,6 +890,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
}); });
} }
/// Set clock source.
pub fn set_src(&self, src: GpoutSrc) { pub fn set_src(&self, src: GpoutSrc) {
let c = pac::CLOCKS; let c = pac::CLOCKS;
c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
@ -816,6 +898,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
}); });
} }
/// Enable clock.
pub fn enable(&self) { pub fn enable(&self) {
let c = pac::CLOCKS; let c = pac::CLOCKS;
c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
@ -823,6 +906,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
}); });
} }
/// Disable clock.
pub fn disable(&self) { pub fn disable(&self) {
let c = pac::CLOCKS; let c = pac::CLOCKS;
c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
@ -830,6 +914,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
}); });
} }
/// Clock frequency.
pub fn get_freq(&self) -> u32 { pub fn get_freq(&self) -> u32 {
let c = pac::CLOCKS; let c = pac::CLOCKS;
let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc(); let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc();

View File

@ -38,6 +38,9 @@ pub(crate) unsafe fn init() {
interrupt::DMA_IRQ_0.enable(); interrupt::DMA_IRQ_0.enable();
} }
/// DMA read.
///
/// SAFETY: Slice must point to a valid location reachable by DMA.
pub unsafe fn read<'a, C: Channel, W: Word>( pub unsafe fn read<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a, ch: impl Peripheral<P = C> + 'a,
from: *const W, from: *const W,
@ -57,6 +60,9 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
) )
} }
/// DMA write.
///
/// SAFETY: Slice must point to a valid location reachable by DMA.
pub unsafe fn write<'a, C: Channel, W: Word>( pub unsafe fn write<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a, ch: impl Peripheral<P = C> + 'a,
from: *const [W], from: *const [W],
@ -79,6 +85,9 @@ pub unsafe fn write<'a, C: Channel, W: Word>(
// static mut so that this is allocated in RAM. // static mut so that this is allocated in RAM.
static mut DUMMY: u32 = 0; static mut DUMMY: u32 = 0;
/// DMA repeated write.
///
/// SAFETY: Slice must point to a valid location reachable by DMA.
pub unsafe fn write_repeated<'a, C: Channel, W: Word>( pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a, ch: impl Peripheral<P = C> + 'a,
to: *mut W, to: *mut W,
@ -97,6 +106,9 @@ pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
) )
} }
/// DMA copy between slices.
///
/// SAFETY: Slices must point to locations reachable by DMA.
pub unsafe fn copy<'a, C: Channel, W: Word>( pub unsafe fn copy<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a, ch: impl Peripheral<P = C> + 'a,
from: &[W], from: &[W],
@ -152,6 +164,7 @@ fn copy_inner<'a, C: Channel>(
Transfer::new(ch) Transfer::new(ch)
} }
/// DMA transfer driver.
#[must_use = "futures do nothing unless you `.await` or poll them"] #[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Transfer<'a, C: Channel> { pub struct Transfer<'a, C: Channel> {
channel: PeripheralRef<'a, C>, channel: PeripheralRef<'a, C>,
@ -201,19 +214,25 @@ mod sealed {
pub trait Word {} pub trait Word {}
} }
/// DMA channel interface.
pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static { pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static {
/// Channel number.
fn number(&self) -> u8; fn number(&self) -> u8;
/// Channel registry block.
fn regs(&self) -> pac::dma::Channel { fn regs(&self) -> pac::dma::Channel {
pac::DMA.ch(self.number() as _) pac::DMA.ch(self.number() as _)
} }
/// Convert into type-erased [AnyChannel].
fn degrade(self) -> AnyChannel { fn degrade(self) -> AnyChannel {
AnyChannel { number: self.number() } AnyChannel { number: self.number() }
} }
} }
/// DMA word.
pub trait Word: sealed::Word { pub trait Word: sealed::Word {
/// Word size.
fn size() -> vals::DataSize; fn size() -> vals::DataSize;
} }
@ -238,6 +257,7 @@ impl Word for u32 {
} }
} }
/// Type erased DMA channel.
pub struct AnyChannel { pub struct AnyChannel {
number: u8, number: u8,
} }

View File

@ -1,3 +1,4 @@
//! Flash driver.
use core::future::Future; use core::future::Future;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::pin::Pin; use core::pin::Pin;
@ -13,9 +14,10 @@ use crate::dma::{AnyChannel, Channel, Transfer};
use crate::pac; use crate::pac;
use crate::peripherals::FLASH; use crate::peripherals::FLASH;
/// Flash base address.
pub const FLASH_BASE: *const u32 = 0x10000000 as _; pub const FLASH_BASE: *const u32 = 0x10000000 as _;
// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead. /// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead.
// TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance. // TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance.
pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram"); pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram");
@ -24,10 +26,15 @@ pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram");
// These limitations are currently enforced because of using the // These limitations are currently enforced because of using the
// RP2040 boot-rom flash functions, that are optimized for flash compatibility // RP2040 boot-rom flash functions, that are optimized for flash compatibility
// rather than performance. // rather than performance.
/// Flash page size.
pub const PAGE_SIZE: usize = 256; pub const PAGE_SIZE: usize = 256;
/// Flash write size.
pub const WRITE_SIZE: usize = 1; pub const WRITE_SIZE: usize = 1;
/// Flash read size.
pub const READ_SIZE: usize = 1; pub const READ_SIZE: usize = 1;
/// Flash erase size.
pub const ERASE_SIZE: usize = 4096; pub const ERASE_SIZE: usize = 4096;
/// Flash DMA read size.
pub const ASYNC_READ_SIZE: usize = 4; pub const ASYNC_READ_SIZE: usize = 4;
/// Error type for NVMC operations. /// Error type for NVMC operations.
@ -38,7 +45,9 @@ pub enum Error {
OutOfBounds, OutOfBounds,
/// Unaligned operation or using unaligned buffers. /// Unaligned operation or using unaligned buffers.
Unaligned, Unaligned,
/// Accessed from the wrong core.
InvalidCore, InvalidCore,
/// Other error
Other, Other,
} }
@ -96,12 +105,18 @@ impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Drop for BackgroundRead<'a, '
} }
} }
/// Flash driver.
pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> { pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> {
dma: Option<PeripheralRef<'d, AnyChannel>>, dma: Option<PeripheralRef<'d, AnyChannel>>,
phantom: PhantomData<(&'d mut T, M)>, phantom: PhantomData<(&'d mut T, M)>,
} }
impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> { impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> {
/// Blocking read.
///
/// The offset and buffer must be aligned.
///
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
trace!( trace!(
"Reading from 0x{:x} to 0x{:x}", "Reading from 0x{:x} to 0x{:x}",
@ -116,10 +131,14 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
Ok(()) Ok(())
} }
/// Flash capacity.
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize {
FLASH_SIZE FLASH_SIZE
} }
/// Blocking erase.
///
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
check_erase(self, from, to)?; check_erase(self, from, to)?;
@ -136,6 +155,11 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
Ok(()) Ok(())
} }
/// Blocking write.
///
/// The offset and buffer must be aligned.
///
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
check_write(self, offset, bytes.len())?; check_write(self, offset, bytes.len())?;
@ -219,6 +243,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
} }
impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> { impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> {
/// Create a new flash driver in blocking mode.
pub fn new_blocking(_flash: impl Peripheral<P = T> + 'd) -> Self { pub fn new_blocking(_flash: impl Peripheral<P = T> + 'd) -> Self {
Self { Self {
dma: None, dma: None,
@ -228,6 +253,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE
} }
impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> { impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
/// Create a new flash driver in async mode.
pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self { pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self {
into_ref!(dma); into_ref!(dma);
Self { Self {
@ -236,6 +262,11 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
} }
} }
/// Start a background read operation.
///
/// The offset and buffer must be aligned.
///
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
pub fn background_read<'a>( pub fn background_read<'a>(
&'a mut self, &'a mut self,
offset: u32, offset: u32,
@ -279,6 +310,11 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
}) })
} }
/// Async read.
///
/// The offset and buffer must be aligned.
///
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
@ -874,7 +910,9 @@ mod sealed {
pub trait Mode {} pub trait Mode {}
} }
/// Flash instance.
pub trait Instance: sealed::Instance {} pub trait Instance: sealed::Instance {}
/// Flash mode.
pub trait Mode: sealed::Mode {} pub trait Mode: sealed::Mode {}
impl sealed::Instance for FLASH {} impl sealed::Instance for FLASH {}
@ -887,7 +925,9 @@ macro_rules! impl_mode {
}; };
} }
/// Flash blocking mode.
pub struct Blocking; pub struct Blocking;
/// Flash async mode.
pub struct Async; pub struct Async;
impl_mode!(Blocking); impl_mode!(Blocking);

View File

@ -1,3 +1,4 @@
//! GPIO driver.
#![macro_use] #![macro_use]
use core::convert::Infallible; use core::convert::Infallible;
use core::future::Future; use core::future::Future;
@ -23,7 +24,9 @@ static QSPI_WAKERS: [AtomicWaker; QSPI_PIN_COUNT] = [NEW_AW; QSPI_PIN_COUNT];
/// Represents a digital input or output level. /// Represents a digital input or output level.
#[derive(Debug, Eq, PartialEq, Clone, Copy)] #[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Level { pub enum Level {
/// Logical low.
Low, Low,
/// Logical high.
High, High,
} }
@ -48,48 +51,66 @@ impl From<Level> for bool {
/// Represents a pull setting for an input. /// Represents a pull setting for an input.
#[derive(Debug, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Pull { pub enum Pull {
/// No pull.
None, None,
/// Internal pull-up resistor.
Up, Up,
/// Internal pull-down resistor.
Down, Down,
} }
/// Drive strength of an output /// Drive strength of an output
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum Drive { pub enum Drive {
/// 2 mA drive.
_2mA, _2mA,
/// 4 mA drive.
_4mA, _4mA,
/// 8 mA drive.
_8mA, _8mA,
/// 1 2mA drive.
_12mA, _12mA,
} }
/// Slew rate of an output /// Slew rate of an output
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum SlewRate { pub enum SlewRate {
/// Fast slew rate.
Fast, Fast,
/// Slow slew rate.
Slow, Slow,
} }
/// A GPIO bank with up to 32 pins. /// A GPIO bank with up to 32 pins.
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum Bank { pub enum Bank {
/// Bank 0.
Bank0 = 0, Bank0 = 0,
/// QSPI.
#[cfg(feature = "qspi-as-gpio")] #[cfg(feature = "qspi-as-gpio")]
Qspi = 1, Qspi = 1,
} }
/// Dormant mode config.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)] #[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct DormantWakeConfig { pub struct DormantWakeConfig {
/// Wake on edge high.
pub edge_high: bool, pub edge_high: bool,
/// Wake on edge low.
pub edge_low: bool, pub edge_low: bool,
/// Wake on level high.
pub level_high: bool, pub level_high: bool,
/// Wake on level low.
pub level_low: bool, pub level_low: bool,
} }
/// GPIO input driver.
pub struct Input<'d, T: Pin> { pub struct Input<'d, T: Pin> {
pin: Flex<'d, T>, pin: Flex<'d, T>,
} }
impl<'d, T: Pin> Input<'d, T> { impl<'d, T: Pin> Input<'d, T> {
/// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
#[inline] #[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self { pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
let mut pin = Flex::new(pin); let mut pin = Flex::new(pin);
@ -104,11 +125,13 @@ impl<'d, T: Pin> Input<'d, T> {
self.pin.set_schmitt(enable) self.pin.set_schmitt(enable)
} }
/// Get whether the pin input level is high.
#[inline] #[inline]
pub fn is_high(&mut self) -> bool { pub fn is_high(&mut self) -> bool {
self.pin.is_high() self.pin.is_high()
} }
/// Get whether the pin input level is low.
#[inline] #[inline]
pub fn is_low(&mut self) -> bool { pub fn is_low(&mut self) -> bool {
self.pin.is_low() self.pin.is_low()
@ -120,31 +143,37 @@ impl<'d, T: Pin> Input<'d, T> {
self.pin.get_level() self.pin.get_level()
} }
/// Wait until the pin is high. If it is already high, return immediately.
#[inline] #[inline]
pub async fn wait_for_high(&mut self) { pub async fn wait_for_high(&mut self) {
self.pin.wait_for_high().await; self.pin.wait_for_high().await;
} }
/// Wait until the pin is low. If it is already low, return immediately.
#[inline] #[inline]
pub async fn wait_for_low(&mut self) { pub async fn wait_for_low(&mut self) {
self.pin.wait_for_low().await; self.pin.wait_for_low().await;
} }
/// Wait for the pin to undergo a transition from low to high.
#[inline] #[inline]
pub async fn wait_for_rising_edge(&mut self) { pub async fn wait_for_rising_edge(&mut self) {
self.pin.wait_for_rising_edge().await; self.pin.wait_for_rising_edge().await;
} }
/// Wait for the pin to undergo a transition from high to low.
#[inline] #[inline]
pub async fn wait_for_falling_edge(&mut self) { pub async fn wait_for_falling_edge(&mut self) {
self.pin.wait_for_falling_edge().await; self.pin.wait_for_falling_edge().await;
} }
/// Wait for the pin to undergo any transition, i.e low to high OR high to low.
#[inline] #[inline]
pub async fn wait_for_any_edge(&mut self) { pub async fn wait_for_any_edge(&mut self) {
self.pin.wait_for_any_edge().await; self.pin.wait_for_any_edge().await;
} }
/// Configure dormant wake.
#[inline] #[inline]
pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> { pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
self.pin.dormant_wake(cfg) self.pin.dormant_wake(cfg)
@ -155,10 +184,15 @@ impl<'d, T: Pin> Input<'d, T> {
#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum InterruptTrigger { pub enum InterruptTrigger {
/// Trigger on pin low.
LevelLow, LevelLow,
/// Trigger on pin high.
LevelHigh, LevelHigh,
/// Trigger on high to low transition.
EdgeLow, EdgeLow,
/// Trigger on low to high transition.
EdgeHigh, EdgeHigh,
/// Trigger on any transition.
AnyEdge, AnyEdge,
} }
@ -226,6 +260,7 @@ struct InputFuture<'a, T: Pin> {
} }
impl<'d, T: Pin> InputFuture<'d, T> { impl<'d, T: Pin> InputFuture<'d, T> {
/// Create a new future wiating for input trigger.
pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self { pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self {
into_ref!(pin); into_ref!(pin);
let pin_group = (pin.pin() % 8) as usize; let pin_group = (pin.pin() % 8) as usize;
@ -308,11 +343,13 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> {
} }
} }
/// GPIO output driver.
pub struct Output<'d, T: Pin> { pub struct Output<'d, T: Pin> {
pin: Flex<'d, T>, pin: Flex<'d, T>,
} }
impl<'d, T: Pin> Output<'d, T> { impl<'d, T: Pin> Output<'d, T> {
/// Create GPIO output driver for a [Pin] with the provided [Level].
#[inline] #[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self { pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
let mut pin = Flex::new(pin); let mut pin = Flex::new(pin);
@ -331,7 +368,7 @@ impl<'d, T: Pin> Output<'d, T> {
self.pin.set_drive_strength(strength) self.pin.set_drive_strength(strength)
} }
// Set the pin's slew rate. /// Set the pin's slew rate.
#[inline] #[inline]
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
self.pin.set_slew_rate(slew_rate) self.pin.set_slew_rate(slew_rate)
@ -386,6 +423,7 @@ pub struct OutputOpenDrain<'d, T: Pin> {
} }
impl<'d, T: Pin> OutputOpenDrain<'d, T> { impl<'d, T: Pin> OutputOpenDrain<'d, T> {
/// Create GPIO output driver for a [Pin] in open drain mode with the provided [Level].
#[inline] #[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self { pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
let mut pin = Flex::new(pin); let mut pin = Flex::new(pin);
@ -403,7 +441,7 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
self.pin.set_drive_strength(strength) self.pin.set_drive_strength(strength)
} }
// Set the pin's slew rate. /// Set the pin's slew rate.
#[inline] #[inline]
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
self.pin.set_slew_rate(slew_rate) self.pin.set_slew_rate(slew_rate)
@ -456,11 +494,13 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
self.pin.toggle_set_as_output() self.pin.toggle_set_as_output()
} }
/// Get whether the pin input level is high.
#[inline] #[inline]
pub fn is_high(&mut self) -> bool { pub fn is_high(&mut self) -> bool {
self.pin.is_high() self.pin.is_high()
} }
/// Get whether the pin input level is low.
#[inline] #[inline]
pub fn is_low(&mut self) -> bool { pub fn is_low(&mut self) -> bool {
self.pin.is_low() self.pin.is_low()
@ -472,26 +512,31 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
self.is_high().into() self.is_high().into()
} }
/// Wait until the pin is high. If it is already high, return immediately.
#[inline] #[inline]
pub async fn wait_for_high(&mut self) { pub async fn wait_for_high(&mut self) {
self.pin.wait_for_high().await; self.pin.wait_for_high().await;
} }
/// Wait until the pin is low. If it is already low, return immediately.
#[inline] #[inline]
pub async fn wait_for_low(&mut self) { pub async fn wait_for_low(&mut self) {
self.pin.wait_for_low().await; self.pin.wait_for_low().await;
} }
/// Wait for the pin to undergo a transition from low to high.
#[inline] #[inline]
pub async fn wait_for_rising_edge(&mut self) { pub async fn wait_for_rising_edge(&mut self) {
self.pin.wait_for_rising_edge().await; self.pin.wait_for_rising_edge().await;
} }
/// Wait for the pin to undergo a transition from high to low.
#[inline] #[inline]
pub async fn wait_for_falling_edge(&mut self) { pub async fn wait_for_falling_edge(&mut self) {
self.pin.wait_for_falling_edge().await; self.pin.wait_for_falling_edge().await;
} }
/// Wait for the pin to undergo any transition, i.e low to high OR high to low.
#[inline] #[inline]
pub async fn wait_for_any_edge(&mut self) { pub async fn wait_for_any_edge(&mut self) {
self.pin.wait_for_any_edge().await; self.pin.wait_for_any_edge().await;
@ -508,6 +553,10 @@ pub struct Flex<'d, T: Pin> {
} }
impl<'d, T: Pin> Flex<'d, T> { impl<'d, T: Pin> Flex<'d, T> {
/// Wrap the pin in a `Flex`.
///
/// The pin remains disconnected. The initial output level is unspecified, but can be changed
/// before the pin is put into output mode.
#[inline] #[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self { pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self {
into_ref!(pin); into_ref!(pin);
@ -556,7 +605,7 @@ impl<'d, T: Pin> Flex<'d, T> {
}); });
} }
// Set the pin's slew rate. /// Set the pin's slew rate.
#[inline] #[inline]
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
self.pin.pad_ctrl().modify(|w| { self.pin.pad_ctrl().modify(|w| {
@ -589,6 +638,7 @@ impl<'d, T: Pin> Flex<'d, T> {
self.pin.sio_oe().value_set().write_value(self.bit()) self.pin.sio_oe().value_set().write_value(self.bit())
} }
/// Set as output pin.
#[inline] #[inline]
pub fn is_set_as_output(&mut self) -> bool { pub fn is_set_as_output(&mut self) -> bool {
self.ref_is_set_as_output() self.ref_is_set_as_output()
@ -599,15 +649,18 @@ impl<'d, T: Pin> Flex<'d, T> {
(self.pin.sio_oe().value().read() & self.bit()) != 0 (self.pin.sio_oe().value().read() & self.bit()) != 0
} }
/// Toggle output pin.
#[inline] #[inline]
pub fn toggle_set_as_output(&mut self) { pub fn toggle_set_as_output(&mut self) {
self.pin.sio_oe().value_xor().write_value(self.bit()) self.pin.sio_oe().value_xor().write_value(self.bit())
} }
/// Get whether the pin input level is high.
#[inline] #[inline]
pub fn is_high(&mut self) -> bool { pub fn is_high(&mut self) -> bool {
!self.is_low() !self.is_low()
} }
/// Get whether the pin input level is low.
#[inline] #[inline]
pub fn is_low(&mut self) -> bool { pub fn is_low(&mut self) -> bool {
@ -675,31 +728,37 @@ impl<'d, T: Pin> Flex<'d, T> {
self.pin.sio_out().value_xor().write_value(self.bit()) self.pin.sio_out().value_xor().write_value(self.bit())
} }
/// Wait until the pin is high. If it is already high, return immediately.
#[inline] #[inline]
pub async fn wait_for_high(&mut self) { pub async fn wait_for_high(&mut self) {
InputFuture::new(&mut self.pin, InterruptTrigger::LevelHigh).await; InputFuture::new(&mut self.pin, InterruptTrigger::LevelHigh).await;
} }
/// Wait until the pin is low. If it is already low, return immediately.
#[inline] #[inline]
pub async fn wait_for_low(&mut self) { pub async fn wait_for_low(&mut self) {
InputFuture::new(&mut self.pin, InterruptTrigger::LevelLow).await; InputFuture::new(&mut self.pin, InterruptTrigger::LevelLow).await;
} }
/// Wait for the pin to undergo a transition from low to high.
#[inline] #[inline]
pub async fn wait_for_rising_edge(&mut self) { pub async fn wait_for_rising_edge(&mut self) {
InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await; InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await;
} }
/// Wait for the pin to undergo a transition from high to low.
#[inline] #[inline]
pub async fn wait_for_falling_edge(&mut self) { pub async fn wait_for_falling_edge(&mut self) {
InputFuture::new(&mut self.pin, InterruptTrigger::EdgeLow).await; InputFuture::new(&mut self.pin, InterruptTrigger::EdgeLow).await;
} }
/// Wait for the pin to undergo any transition, i.e low to high OR high to low.
#[inline] #[inline]
pub async fn wait_for_any_edge(&mut self) { pub async fn wait_for_any_edge(&mut self) {
InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await; InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await;
} }
/// Configure dormant wake.
#[inline] #[inline]
pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> { pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
let idx = self.pin._pin() as usize; let idx = self.pin._pin() as usize;
@ -737,6 +796,7 @@ impl<'d, T: Pin> Drop for Flex<'d, T> {
} }
} }
/// Dormant wake driver.
pub struct DormantWake<'w, T: Pin> { pub struct DormantWake<'w, T: Pin> {
pin: PeripheralRef<'w, T>, pin: PeripheralRef<'w, T>,
cfg: DormantWakeConfig, cfg: DormantWakeConfig,
@ -818,6 +878,7 @@ pub(crate) mod sealed {
} }
} }
/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an [AnyPin].
pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static {
/// Degrade to a generic pin struct /// Degrade to a generic pin struct
fn degrade(self) -> AnyPin { fn degrade(self) -> AnyPin {
@ -839,6 +900,7 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
} }
} }
/// Type-erased GPIO pin
pub struct AnyPin { pub struct AnyPin {
pin_bank: u8, pin_bank: u8,
} }

View File

@ -1,3 +1,4 @@
//! I2C driver.
use core::future; use core::future;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::task::Poll; use core::task::Poll;
@ -22,6 +23,7 @@ pub enum AbortReason {
ArbitrationLoss, ArbitrationLoss,
/// Transmit ended with data still in fifo /// Transmit ended with data still in fifo
TxNotEmpty(u16), TxNotEmpty(u16),
/// Other reason.
Other(u32), Other(u32),
} }
@ -41,9 +43,11 @@ pub enum Error {
AddressReserved(u16), AddressReserved(u16),
} }
/// I2C config.
#[non_exhaustive] #[non_exhaustive]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Config { pub struct Config {
/// Frequency.
pub frequency: u32, pub frequency: u32,
} }
@ -53,13 +57,16 @@ impl Default for Config {
} }
} }
/// Size of I2C FIFO.
pub const FIFO_SIZE: u8 = 16; pub const FIFO_SIZE: u8 = 16;
/// I2C driver.
pub struct I2c<'d, T: Instance, M: Mode> { pub struct I2c<'d, T: Instance, M: Mode> {
phantom: PhantomData<(&'d mut T, M)>, phantom: PhantomData<(&'d mut T, M)>,
} }
impl<'d, T: Instance> I2c<'d, T, Blocking> { impl<'d, T: Instance> I2c<'d, T, Blocking> {
/// Create a new driver instance in blocking mode.
pub fn new_blocking( pub fn new_blocking(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd, scl: impl Peripheral<P = impl SclPin<T>> + 'd,
@ -72,6 +79,7 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> {
} }
impl<'d, T: Instance> I2c<'d, T, Async> { impl<'d, T: Instance> I2c<'d, T, Async> {
/// Create a new driver instance in async mode.
pub fn new_async( pub fn new_async(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd, scl: impl Peripheral<P = impl SclPin<T>> + 'd,
@ -292,16 +300,19 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
} }
} }
/// Read from address into buffer using DMA.
pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> { pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> {
Self::setup(addr)?; Self::setup(addr)?;
self.read_async_internal(buffer, true, true).await self.read_async_internal(buffer, true, true).await
} }
/// Write to address from buffer using DMA.
pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> { pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> {
Self::setup(addr)?; Self::setup(addr)?;
self.write_async_internal(bytes, true).await self.write_async_internal(bytes, true).await
} }
/// Write to address from bytes and read from address into buffer using DMA.
pub async fn write_read_async( pub async fn write_read_async(
&mut self, &mut self,
addr: u16, addr: u16,
@ -314,6 +325,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
} }
} }
/// Interrupt handler.
pub struct InterruptHandler<T: Instance> { pub struct InterruptHandler<T: Instance> {
_uart: PhantomData<T>, _uart: PhantomData<T>,
} }
@ -569,17 +581,20 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
// Blocking public API // Blocking public API
// ========================= // =========================
/// Read from address into buffer blocking caller until done.
pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
Self::setup(address.into())?; Self::setup(address.into())?;
self.read_blocking_internal(read, true, true) self.read_blocking_internal(read, true, true)
// Automatic Stop // Automatic Stop
} }
/// Write to address from buffer blocking caller until done.
pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
Self::setup(address.into())?; Self::setup(address.into())?;
self.write_blocking_internal(write, true) self.write_blocking_internal(write, true)
} }
/// Write to address from bytes and read from address into buffer blocking caller until done.
pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
Self::setup(address.into())?; Self::setup(address.into())?;
self.write_blocking_internal(write, false)?; self.write_blocking_internal(write, false)?;
@ -742,6 +757,7 @@ where
} }
} }
/// Check if address is reserved.
pub fn i2c_reserved_addr(addr: u16) -> bool { pub fn i2c_reserved_addr(addr: u16) -> bool {
((addr & 0x78) == 0 || (addr & 0x78) == 0x78) && addr != 0 ((addr & 0x78) == 0 || (addr & 0x78) == 0x78) && addr != 0
} }
@ -768,6 +784,7 @@ mod sealed {
pub trait SclPin<T: Instance> {} pub trait SclPin<T: Instance> {}
} }
/// Driver mode.
pub trait Mode: sealed::Mode {} pub trait Mode: sealed::Mode {}
macro_rules! impl_mode { macro_rules! impl_mode {
@ -777,12 +794,15 @@ macro_rules! impl_mode {
}; };
} }
/// Blocking mode.
pub struct Blocking; pub struct Blocking;
/// Async mode.
pub struct Async; pub struct Async;
impl_mode!(Blocking); impl_mode!(Blocking);
impl_mode!(Async); impl_mode!(Async);
/// I2C instance.
pub trait Instance: sealed::Instance {} pub trait Instance: sealed::Instance {}
macro_rules! impl_instance { macro_rules! impl_instance {
@ -819,7 +839,9 @@ macro_rules! impl_instance {
impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33); impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33);
impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35); impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35);
/// SDA pin.
pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {} pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {}
/// SCL pin.
pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {} pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {}
macro_rules! impl_pin { macro_rules! impl_pin {

View File

@ -1,3 +1,4 @@
//! I2C slave driver.
use core::future; use core::future;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::task::Poll; use core::task::Poll;
@ -63,11 +64,13 @@ impl Default for Config {
} }
} }
/// I2CSlave driver.
pub struct I2cSlave<'d, T: Instance> { pub struct I2cSlave<'d, T: Instance> {
phantom: PhantomData<&'d mut T>, phantom: PhantomData<&'d mut T>,
} }
impl<'d, T: Instance> I2cSlave<'d, T> { impl<'d, T: Instance> I2cSlave<'d, T> {
/// Create a new instance.
pub fn new( pub fn new(
_peri: impl Peripheral<P = T> + 'd, _peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd, scl: impl Peripheral<P = impl SclPin<T>> + 'd,

View File

@ -1,6 +1,7 @@
#![no_std] #![no_std]
#![allow(async_fn_in_trait)] #![allow(async_fn_in_trait)]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![warn(missing_docs)]
// This mod MUST go first, so that the others see its macros. // This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt; pub(crate) mod fmt;

View File

@ -1,3 +1,4 @@
//! PIO driver.
use core::future::Future; use core::future::Future;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::pin::Pin as FuturePin; use core::pin::Pin as FuturePin;

View File

@ -119,11 +119,13 @@ impl<'d, T: Channel> Pwm<'d, T> {
} }
} }
/// Create PWM driver without any configured pins.
#[inline] #[inline]
pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self { pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self {
Self::new_inner(inner, None, None, config, Divmode::DIV) Self::new_inner(inner, None, None, config, Divmode::DIV)
} }
/// Create PWM driver with a single 'a' as output.
#[inline] #[inline]
pub fn new_output_a( pub fn new_output_a(
inner: impl Peripheral<P = T> + 'd, inner: impl Peripheral<P = T> + 'd,
@ -134,6 +136,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
Self::new_inner(inner, Some(a.map_into()), None, config, Divmode::DIV) Self::new_inner(inner, Some(a.map_into()), None, config, Divmode::DIV)
} }
/// Create PWM driver with a single 'b' pin as output.
#[inline] #[inline]
pub fn new_output_b( pub fn new_output_b(
inner: impl Peripheral<P = T> + 'd, inner: impl Peripheral<P = T> + 'd,
@ -144,6 +147,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
Self::new_inner(inner, None, Some(b.map_into()), config, Divmode::DIV) Self::new_inner(inner, None, Some(b.map_into()), config, Divmode::DIV)
} }
/// Create PWM driver with a 'a' and 'b' pins as output.
#[inline] #[inline]
pub fn new_output_ab( pub fn new_output_ab(
inner: impl Peripheral<P = T> + 'd, inner: impl Peripheral<P = T> + 'd,
@ -155,6 +159,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, Divmode::DIV) Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, Divmode::DIV)
} }
/// Create PWM driver with a single 'b' as input pin.
#[inline] #[inline]
pub fn new_input( pub fn new_input(
inner: impl Peripheral<P = T> + 'd, inner: impl Peripheral<P = T> + 'd,
@ -166,6 +171,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
Self::new_inner(inner, None, Some(b.map_into()), config, mode.into()) Self::new_inner(inner, None, Some(b.map_into()), config, mode.into())
} }
/// Create PWM driver with a 'a' and 'b' pins in the desired input mode.
#[inline] #[inline]
pub fn new_output_input( pub fn new_output_input(
inner: impl Peripheral<P = T> + 'd, inner: impl Peripheral<P = T> + 'd,
@ -178,6 +184,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, mode.into()) Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, mode.into())
} }
/// Set the PWM config.
pub fn set_config(&mut self, config: &Config) { pub fn set_config(&mut self, config: &Config) {
Self::configure(self.inner.regs(), config); Self::configure(self.inner.regs(), config);
} }
@ -221,28 +228,33 @@ impl<'d, T: Channel> Pwm<'d, T> {
while p.csr().read().ph_ret() {} while p.csr().read().ph_ret() {}
} }
/// Read PWM counter.
#[inline] #[inline]
pub fn counter(&self) -> u16 { pub fn counter(&self) -> u16 {
self.inner.regs().ctr().read().ctr() self.inner.regs().ctr().read().ctr()
} }
/// Write PWM counter.
#[inline] #[inline]
pub fn set_counter(&self, ctr: u16) { pub fn set_counter(&self, ctr: u16) {
self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) self.inner.regs().ctr().write(|w| w.set_ctr(ctr))
} }
/// Wait for channel interrupt.
#[inline] #[inline]
pub fn wait_for_wrap(&mut self) { pub fn wait_for_wrap(&mut self) {
while !self.wrapped() {} while !self.wrapped() {}
self.clear_wrapped(); self.clear_wrapped();
} }
/// Check if interrupt for channel is set.
#[inline] #[inline]
pub fn wrapped(&mut self) -> bool { pub fn wrapped(&mut self) -> bool {
pac::PWM.intr().read().0 & self.bit() != 0 pac::PWM.intr().read().0 & self.bit() != 0
} }
#[inline] #[inline]
/// Clear interrupt flag.
pub fn clear_wrapped(&mut self) { pub fn clear_wrapped(&mut self) {
pac::PWM.intr().write_value(Intr(self.bit() as _)); pac::PWM.intr().write_value(Intr(self.bit() as _));
} }
@ -253,15 +265,18 @@ impl<'d, T: Channel> Pwm<'d, T> {
} }
} }
/// Batch representation of PWM channels.
pub struct PwmBatch(u32); pub struct PwmBatch(u32);
impl PwmBatch { impl PwmBatch {
#[inline] #[inline]
/// Enable a PWM channel in this batch.
pub fn enable(&mut self, pwm: &Pwm<'_, impl Channel>) { pub fn enable(&mut self, pwm: &Pwm<'_, impl Channel>) {
self.0 |= pwm.bit(); self.0 |= pwm.bit();
} }
#[inline] #[inline]
/// Enable channels in this batch in a PWM.
pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) { pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) {
let mut en = PwmBatch(0); let mut en = PwmBatch(0);
batch(&mut en); batch(&mut en);
@ -289,9 +304,12 @@ mod sealed {
pub trait Channel {} pub trait Channel {}
} }
/// PWM Channel.
pub trait Channel: Peripheral<P = Self> + sealed::Channel + Sized + 'static { pub trait Channel: Peripheral<P = Self> + sealed::Channel + Sized + 'static {
/// Channel number.
fn number(&self) -> u8; fn number(&self) -> u8;
/// Channel register block.
fn regs(&self) -> pac::pwm::Channel { fn regs(&self) -> pac::pwm::Channel {
pac::PWM.ch(self.number() as _) pac::PWM.ch(self.number() as _)
} }
@ -317,7 +335,9 @@ channel!(PWM_CH5, 5);
channel!(PWM_CH6, 6); channel!(PWM_CH6, 6);
channel!(PWM_CH7, 7); channel!(PWM_CH7, 7);
/// PWM Pin A.
pub trait PwmPinA<T: Channel>: GpioPin {} pub trait PwmPinA<T: Channel>: GpioPin {}
/// PWM Pin B.
pub trait PwmPinB<T: Channel>: GpioPin {} pub trait PwmPinB<T: Channel>: GpioPin {}
macro_rules! impl_pin { macro_rules! impl_pin {

View File

@ -1,3 +1,4 @@
//! RTC driver.
mod filter; mod filter;
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};

View File

@ -1,3 +1,4 @@
//! Timer driver.
use core::cell::Cell; use core::cell::Cell;
use atomic_polyfill::{AtomicU8, Ordering}; use atomic_polyfill::{AtomicU8, Ordering};

View File

@ -1,3 +1,4 @@
//! Buffered UART driver.
use core::future::{poll_fn, Future}; use core::future::{poll_fn, Future};
use core::slice; use core::slice;
use core::task::Poll; use core::task::Poll;

View File

@ -1,3 +1,4 @@
//! UART driver.
use core::future::poll_fn; use core::future::poll_fn;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::task::Poll; use core::task::Poll;
@ -947,7 +948,7 @@ pub struct Async;
impl_mode!(Blocking); impl_mode!(Blocking);
impl_mode!(Async); impl_mode!(Async);
/// UART instance trait. /// UART instance.
pub trait Instance: sealed::Instance {} pub trait Instance: sealed::Instance {}
macro_rules! impl_instance { macro_rules! impl_instance {

View File

@ -1,3 +1,4 @@
//! USB driver.
use core::future::poll_fn; use core::future::poll_fn;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::slice; use core::slice;