diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index 5b913f15..21360bf6 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -1,3 +1,4 @@ +//! ADC driver. use core::future::poll_fn; use core::marker::PhantomData; use core::mem; @@ -16,6 +17,7 @@ use crate::{dma, interrupt, pac, peripherals, Peripheral, RegExt}; static WAKER: AtomicWaker = AtomicWaker::new(); +/// ADC config. #[non_exhaustive] pub struct Config {} @@ -30,9 +32,11 @@ enum Source<'p> { TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>), } +/// ADC channel. pub struct Channel<'p>(Source<'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, pull: Pull) -> Self { into_ref!(pin); pin.pad_ctrl().modify(|w| { @@ -49,6 +53,7 @@ impl<'p> Channel<'p> { 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) -> Self {
let r = pac::ADC;
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)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(transparent)]
pub struct Sample(u16);
impl Sample {
+ /// Sample is valid.
pub fn good(&self) -> bool {
self.0 < 0x8000
}
+ /// Sample value.
pub fn value(&self) -> u16 {
self.0 & !0x8000
}
}
+/// ADC error.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
+ /// Error converting value.
ConversionFailed,
}
+/// ADC mode.
pub trait Mode {}
+/// ADC async mode.
pub struct Async;
impl Mode for Async {}
+/// ADC blocking mode.
pub struct Blocking;
impl Mode for Blocking {}
+/// ADC driver.
pub struct Adc<'d, M: Mode> {
phantom: PhantomData<(&'d ADC, M)>,
}
@@ -150,6 +164,7 @@ impl<'d, M: Mode> Adc<'d, M> {
while !r.cs().read().ready() {}
}
+ /// Sample a value from a channel in blocking mode.
pub fn blocking_read(&mut self, ch: &mut Channel) -> Result + 'd,
_irq: impl Binding + 'd, _config: Config) -> Self {
Self::setup();
@@ -306,6 +326,7 @@ impl<'d> Adc<'d, Blocking> {
}
}
+/// Interrupt handler.
pub struct InterruptHandler {
_empty: (),
}
@@ -324,6 +345,7 @@ mod sealed {
pub trait AdcChannel {}
}
+/// ADC sample.
pub trait AdcSample: sealed::AdcSample {}
impl sealed::AdcSample for u16 {}
@@ -332,7 +354,9 @@ impl AdcSample for u16 {}
impl sealed::AdcSample for u8 {}
impl AdcSample for u8 {}
+/// ADC channel.
pub trait AdcChannel: sealed::AdcChannel {}
+/// ADC pin.
pub trait AdcPin: AdcChannel + gpio::Pin {}
macro_rules! impl_pin {
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index 2f064561..19232b80 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -45,15 +45,20 @@ static CLOCKS: Clocks = Clocks {
rtc: AtomicU16::new(0),
};
-/// Enumeration of supported clock sources.
+/// Peripheral clock sources.
#[repr(u8)]
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PeriClkSrc {
+ /// SYS.
Sys = ClkPeriCtrlAuxsrc::CLK_SYS as _,
+ /// PLL SYS.
PllSys = ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS as _,
+ /// PLL USB.
PllUsb = ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB as _,
+ /// ROSC.
Rosc = ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH as _,
+ /// XOSC.
Xosc = ClkPeriCtrlAuxsrc::XOSC_CLKSRC as _,
// Gpin0 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
@@ -83,6 +88,7 @@ pub struct ClockConfig {
}
impl ClockConfig {
+ /// Clock configuration derived from external crystal.
pub fn crystal(crystal_hz: u32) -> Self {
Self {
rosc: Some(RoscConfig {
@@ -141,6 +147,7 @@ impl ClockConfig {
}
}
+ /// Clock configuration from internal oscillator.
pub fn rosc() -> Self {
Self {
rosc: Some(RoscConfig {
@@ -190,13 +197,18 @@ impl ClockConfig {
// }
}
+/// ROSC freq range.
#[repr(u16)]
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RoscRange {
+ /// Low range.
Low = pac::rosc::vals::FreqRange::LOW.0,
+ /// Medium range (1.33x low)
Medium = pac::rosc::vals::FreqRange::MEDIUM.0,
+ /// High range (2x low)
High = pac::rosc::vals::FreqRange::HIGH.0,
+ /// Too high. Should not be used.
TooHigh = pac::rosc::vals::FreqRange::TOOHIGH.0,
}
@@ -239,96 +251,136 @@ pub struct PllConfig {
pub post_div2: u8,
}
-/// Reference
+/// Reference clock config.
pub struct RefClkConfig {
+ /// Reference clock source.
pub src: RefClkSrc,
+ /// Reference clock divider.
pub div: u8,
}
+/// Reference clock source.
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RefClkSrc {
- // main sources
+ /// XOSC.
Xosc,
+ /// ROSC.
Rosc,
- // aux sources
+ /// PLL USB.
PllUsb,
// Gpin0,
// Gpin1,
}
+/// SYS clock source.
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SysClkSrc {
- // main sources
+ /// REF.
Ref,
- // aux sources
+ /// PLL SYS.
PllSys,
+ /// PLL USB.
PllUsb,
+ /// ROSC.
Rosc,
+ /// XOSC.
Xosc,
// Gpin0,
// Gpin1,
}
+/// SYS clock config.
pub struct SysClkConfig {
+ /// SYS clock source.
pub src: SysClkSrc,
+ /// SYS clock divider.
pub div_int: u32,
+ /// SYS clock fraction.
pub div_frac: u8,
}
+/// USB clock source.
#[repr(u8)]
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum UsbClkSrc {
+ /// PLL USB.
PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _,
+ /// PLL SYS.
PllSys = ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS as _,
+ /// ROSC.
Rosc = ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH as _,
+ /// XOSC.
Xosc = ClkUsbCtrlAuxsrc::XOSC_CLKSRC as _,
// Gpin0 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
}
+/// USB clock config.
pub struct UsbClkConfig {
+ /// USB clock source.
pub src: UsbClkSrc,
+ /// USB clock divider.
pub div: u8,
+ /// USB clock phase.
pub phase: u8,
}
+/// ADC clock source.
#[repr(u8)]
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AdcClkSrc {
+ /// PLL USB.
PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _,
+ /// PLL SYS.
PllSys = ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
+ /// ROSC.
Rosc = ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
+ /// XOSC.
Xosc = ClkAdcCtrlAuxsrc::XOSC_CLKSRC as _,
// Gpin0 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
}
+/// ADC clock config.
pub struct AdcClkConfig {
+ /// ADC clock source.
pub src: AdcClkSrc,
+ /// ADC clock divider.
pub div: u8,
+ /// ADC clock phase.
pub phase: u8,
}
+/// RTC clock source.
#[repr(u8)]
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RtcClkSrc {
+ /// PLL USB.
PllUsb = ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB as _,
+ /// PLL SYS.
PllSys = ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
+ /// ROSC.
Rosc = ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
+ /// XOSC.
Xosc = ClkRtcCtrlAuxsrc::XOSC_CLKSRC as _,
// Gpin0 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
}
+/// RTC clock config.
pub struct RtcClkConfig {
+ /// RTC clock source.
pub src: RtcClkSrc,
+ /// RTC clock divider.
pub div_int: u32,
+ /// RTC clock divider fraction.
pub div_frac: u8,
+ /// RTC clock phase.
pub phase: u8,
}
@@ -605,10 +657,12 @@ fn configure_rosc(config: RoscConfig) -> u32 {
config.hz
}
+/// ROSC clock frequency.
pub fn rosc_freq() -> u32 {
CLOCKS.rosc.load(Ordering::Relaxed)
}
+/// XOSC clock frequency.
pub fn xosc_freq() -> u32 {
CLOCKS.xosc.load(Ordering::Relaxed)
}
@@ -620,34 +674,42 @@ pub fn xosc_freq() -> u32 {
// CLOCKS.gpin1.load(Ordering::Relaxed)
// }
+/// PLL SYS clock frequency.
pub fn pll_sys_freq() -> u32 {
CLOCKS.pll_sys.load(Ordering::Relaxed)
}
+/// PLL USB clock frequency.
pub fn pll_usb_freq() -> u32 {
CLOCKS.pll_usb.load(Ordering::Relaxed)
}
+/// SYS clock frequency.
pub fn clk_sys_freq() -> u32 {
CLOCKS.sys.load(Ordering::Relaxed)
}
+/// REF clock frequency.
pub fn clk_ref_freq() -> u32 {
CLOCKS.reference.load(Ordering::Relaxed)
}
+/// Peripheral clock frequency.
pub fn clk_peri_freq() -> u32 {
CLOCKS.peri.load(Ordering::Relaxed)
}
+/// USB clock frequency.
pub fn clk_usb_freq() -> u32 {
CLOCKS.usb.load(Ordering::Relaxed)
}
+/// ADC clock frequency.
pub fn clk_adc_freq() -> u32 {
CLOCKS.adc.load(Ordering::Relaxed)
}
+/// RTC clock frequency.
pub fn clk_rtc_freq() -> u16 {
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)
}
+/// General purpose input clock pin.
pub trait GpinPin: crate::gpio::Pin {
+ /// Pin number.
const NR: usize;
}
@@ -723,12 +787,14 @@ macro_rules! impl_gpinpin {
impl_gpinpin!(PIN_20, 20, 0);
impl_gpinpin!(PIN_22, 22, 1);
+/// General purpose clock input driver.
pub struct Gpin<'d, T: Pin> {
gpin: PeripheralRef<'d, AnyPin>,
_phantom: PhantomData + 'd) -> Gpin<'d, P> {
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 {
+ /// Pin number.
fn number(&self) -> usize;
}
@@ -773,26 +841,38 @@ impl_gpoutpin!(PIN_23, 1);
impl_gpoutpin!(PIN_24, 2);
impl_gpoutpin!(PIN_25, 3);
+/// Gpout clock source.
#[repr(u8)]
pub enum GpoutSrc {
+ /// Sys PLL.
PllSys = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS as _,
// Gpin0 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
// Gpin1 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
+ /// USB PLL.
PllUsb = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB as _,
+ /// ROSC.
Rosc = ClkGpoutCtrlAuxsrc::ROSC_CLKSRC as _,
+ /// XOSC.
Xosc = ClkGpoutCtrlAuxsrc::XOSC_CLKSRC as _,
+ /// SYS.
Sys = ClkGpoutCtrlAuxsrc::CLK_SYS as _,
+ /// USB.
Usb = ClkGpoutCtrlAuxsrc::CLK_USB as _,
+ /// ADC.
Adc = ClkGpoutCtrlAuxsrc::CLK_ADC as _,
+ /// RTC.
Rtc = ClkGpoutCtrlAuxsrc::CLK_RTC as _,
+ /// REF.
Ref = ClkGpoutCtrlAuxsrc::CLK_REF as _,
}
+/// General purpose clock output driver.
pub struct Gpout<'d, T: GpoutPin> {
gpout: PeripheralRef<'d, T>,
}
impl<'d, T: GpoutPin> Gpout<'d, T> {
+ /// Create new general purpose cloud output.
pub fn new(gpout: impl Peripheral + 'd) -> Self {
into_ref!(gpout);
@@ -801,6 +881,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
Self { gpout }
}
+ /// Set clock divider.
pub fn set_div(&self, int: u32, frac: u8) {
let c = pac::CLOCKS;
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) {
let c = pac::CLOCKS;
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) {
let c = pac::CLOCKS;
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) {
let c = pac::CLOCKS;
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 {
let c = pac::CLOCKS;
let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc();
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 45ca21a7..088a842a 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -38,6 +38,9 @@ pub(crate) unsafe fn init() {
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>(
ch: impl Peripheral + 'a,
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>(
ch: impl Peripheral + 'a,
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 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>(
ch: impl Peripheral + 'a,
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>(
ch: impl Peripheral + 'a,
from: &[W],
@@ -152,6 +164,7 @@ fn copy_inner<'a, C: Channel>(
Transfer::new(ch)
}
+/// DMA transfer driver.
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Transfer<'a, C: Channel> {
channel: PeripheralRef<'a, C>,
@@ -201,19 +214,25 @@ mod sealed {
pub trait Word {}
}
+/// DMA channel interface.
pub trait Channel: Peripheral + sealed::Channel + Into + 'd) -> Self {
Self {
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> {
+ /// Create a new flash driver in async mode.
pub fn new(_flash: impl Peripheral + 'd, dma: impl Peripheral + 'd) -> Self {
into_ref!(dma);
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>(
&'a mut self,
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> {
use core::mem::MaybeUninit;
@@ -874,7 +910,9 @@ mod sealed {
pub trait Mode {}
}
+/// Flash instance.
pub trait Instance: sealed::Instance {}
+/// Flash mode.
pub trait Mode: sealed::Mode {}
impl sealed::Instance for FLASH {}
@@ -887,7 +925,9 @@ macro_rules! impl_mode {
};
}
+/// Flash blocking mode.
pub struct Blocking;
+/// Flash async mode.
pub struct Async;
impl_mode!(Blocking);
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 23273e62..2e6692ab 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -1,3 +1,4 @@
+//! GPIO driver.
#![macro_use]
use core::convert::Infallible;
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.
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Level {
+ /// Logical low.
Low,
+ /// Logical high.
High,
}
@@ -48,48 +51,66 @@ impl From + 'd, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
@@ -104,11 +125,13 @@ impl<'d, T: Pin> Input<'d, T> {
self.pin.set_schmitt(enable)
}
+ /// Get whether the pin input level is high.
#[inline]
pub fn is_high(&mut self) -> bool {
self.pin.is_high()
}
+ /// Get whether the pin input level is low.
#[inline]
pub fn is_low(&mut self) -> bool {
self.pin.is_low()
@@ -120,31 +143,37 @@ impl<'d, T: Pin> Input<'d, T> {
self.pin.get_level()
}
+ /// Wait until the pin is high. If it is already high, return immediately.
#[inline]
pub async fn wait_for_high(&mut self) {
self.pin.wait_for_high().await;
}
+ /// Wait until the pin is low. If it is already low, return immediately.
#[inline]
pub async fn wait_for_low(&mut self) {
self.pin.wait_for_low().await;
}
+ /// Wait for the pin to undergo a transition from low to high.
#[inline]
pub async fn wait_for_rising_edge(&mut self) {
self.pin.wait_for_rising_edge().await;
}
+ /// Wait for the pin to undergo a transition from high to low.
#[inline]
pub async fn wait_for_falling_edge(&mut self) {
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]
pub async fn wait_for_any_edge(&mut self) {
self.pin.wait_for_any_edge().await;
}
+ /// Configure dormant wake.
#[inline]
pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake + 'd, level: InterruptTrigger) -> Self {
into_ref!(pin);
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> {
pin: Flex<'d, T>,
}
impl<'d, T: Pin> Output<'d, T> {
+ /// Create GPIO output driver for a [Pin] with the provided [Level].
#[inline]
pub fn new(pin: impl Peripheral + 'd, initial_output: Level) -> Self {
let mut pin = Flex::new(pin);
@@ -331,7 +368,7 @@ impl<'d, T: Pin> Output<'d, T> {
self.pin.set_drive_strength(strength)
}
- // Set the pin's slew rate.
+ /// Set the pin's slew rate.
#[inline]
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
self.pin.set_slew_rate(slew_rate)
@@ -386,6 +423,7 @@ pub struct OutputOpenDrain<'d, T: Pin> {
}
impl<'d, T: Pin> OutputOpenDrain<'d, T> {
+ /// Create GPIO output driver for a [Pin] in open drain mode with the provided [Level].
#[inline]
pub fn new(pin: impl Peripheral + 'd, initial_output: Level) -> Self {
let mut pin = Flex::new(pin);
@@ -403,7 +441,7 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
self.pin.set_drive_strength(strength)
}
- // Set the pin's slew rate.
+ /// Set the pin's slew rate.
#[inline]
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
self.pin.set_slew_rate(slew_rate)
@@ -456,11 +494,13 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
self.pin.toggle_set_as_output()
}
+ /// Get whether the pin input level is high.
#[inline]
pub fn is_high(&mut self) -> bool {
self.pin.is_high()
}
+ /// Get whether the pin input level is low.
#[inline]
pub fn is_low(&mut self) -> bool {
self.pin.is_low()
@@ -472,26 +512,31 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
self.is_high().into()
}
+ /// Wait until the pin is high. If it is already high, return immediately.
#[inline]
pub async fn wait_for_high(&mut self) {
self.pin.wait_for_high().await;
}
+ /// Wait until the pin is low. If it is already low, return immediately.
#[inline]
pub async fn wait_for_low(&mut self) {
self.pin.wait_for_low().await;
}
+ /// Wait for the pin to undergo a transition from low to high.
#[inline]
pub async fn wait_for_rising_edge(&mut self) {
self.pin.wait_for_rising_edge().await;
}
+ /// Wait for the pin to undergo a transition from high to low.
#[inline]
pub async fn wait_for_falling_edge(&mut self) {
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]
pub async fn wait_for_any_edge(&mut self) {
self.pin.wait_for_any_edge().await;
@@ -508,6 +553,10 @@ pub struct Flex<'d, T: Pin> {
}
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]
pub fn new(pin: impl Peripheral + 'd) -> Self {
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]
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
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())
}
+ /// Set as output pin.
#[inline]
pub fn is_set_as_output(&mut self) -> bool {
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
}
+ /// Toggle output pin.
#[inline]
pub fn toggle_set_as_output(&mut self) {
self.pin.sio_oe().value_xor().write_value(self.bit())
}
+ /// Get whether the pin input level is high.
#[inline]
pub fn is_high(&mut self) -> bool {
!self.is_low()
}
+ /// Get whether the pin input level is low.
#[inline]
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())
}
+ /// Wait until the pin is high. If it is already high, return immediately.
#[inline]
pub async fn wait_for_high(&mut self) {
InputFuture::new(&mut self.pin, InterruptTrigger::LevelHigh).await;
}
+ /// Wait until the pin is low. If it is already low, return immediately.
#[inline]
pub async fn wait_for_low(&mut self) {
InputFuture::new(&mut self.pin, InterruptTrigger::LevelLow).await;
}
+ /// Wait for the pin to undergo a transition from low to high.
#[inline]
pub async fn wait_for_rising_edge(&mut self) {
InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await;
}
+ /// Wait for the pin to undergo a transition from high to low.
#[inline]
pub async fn wait_for_falling_edge(&mut self) {
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]
pub async fn wait_for_any_edge(&mut self) {
InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await;
}
+ /// Configure dormant wake.
#[inline]
pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake + Into + Into + 'd,
scl: impl Peripheral > + 'd,
@@ -72,6 +79,7 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> {
}
impl<'d, T: Instance> I2c<'d, T, Async> {
+ /// Create a new driver instance in async mode.
pub fn new_async(
peri: impl Peripheral + 'd,
scl: impl Peripheral > + '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> {
Self::setup(addr)?;
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 + 'd,
scl: impl Peripheral > + 'd,
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index 2c49787d..004b9458 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -1,6 +1,7 @@
#![no_std]
#![allow(async_fn_in_trait)]
#![doc = include_str!("../README.md")]
+#![warn(missing_docs)]
// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;
diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs
index ae91d1e8..ca979502 100644
--- a/embassy-rp/src/pio/mod.rs
+++ b/embassy-rp/src/pio/mod.rs
@@ -1,3 +1,4 @@
+//! PIO driver.
use core::future::Future;
use core::marker::PhantomData;
use core::pin::Pin as FuturePin;
diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs
index 5b96557a..784a05f9 100644
--- a/embassy-rp/src/pwm.rs
+++ b/embassy-rp/src/pwm.rs
@@ -119,11 +119,13 @@ impl<'d, T: Channel> Pwm<'d, T> {
}
}
+ /// Create PWM driver without any configured pins.
#[inline]
pub fn new_free(inner: impl Peripheral + 'd, config: Config) -> Self {
Self::new_inner(inner, None, None, config, Divmode::DIV)
}
+ /// Create PWM driver with a single 'a' as output.
#[inline]
pub fn new_output_a(
inner: impl Peripheral + 'd,
@@ -134,6 +136,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
Self::new_inner(inner, Some(a.map_into()), None, config, Divmode::DIV)
}
+ /// Create PWM driver with a single 'b' pin as output.
#[inline]
pub fn new_output_b(
inner: impl Peripheral + 'd,
@@ -144,6 +147,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
Self::new_inner(inner, None, Some(b.map_into()), config, Divmode::DIV)
}
+ /// Create PWM driver with a 'a' and 'b' pins as output.
#[inline]
pub fn new_output_ab(
inner: impl Peripheral + '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)
}
+ /// Create PWM driver with a single 'b' as input pin.
#[inline]
pub fn new_input(
inner: impl Peripheral + 'd,
@@ -166,6 +171,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
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]
pub fn new_output_input(
inner: impl Peripheral + '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())
}
+ /// Set the PWM config.
pub fn set_config(&mut self, config: &Config) {
Self::configure(self.inner.regs(), config);
}
@@ -221,28 +228,33 @@ impl<'d, T: Channel> Pwm<'d, T> {
while p.csr().read().ph_ret() {}
}
+ /// Read PWM counter.
#[inline]
pub fn counter(&self) -> u16 {
self.inner.regs().ctr().read().ctr()
}
+ /// Write PWM counter.
#[inline]
pub fn set_counter(&self, ctr: u16) {
self.inner.regs().ctr().write(|w| w.set_ctr(ctr))
}
+ /// Wait for channel interrupt.
#[inline]
pub fn wait_for_wrap(&mut self) {
while !self.wrapped() {}
self.clear_wrapped();
}
+ /// Check if interrupt for channel is set.
#[inline]
pub fn wrapped(&mut self) -> bool {
pac::PWM.intr().read().0 & self.bit() != 0
}
#[inline]
+ /// Clear interrupt flag.
pub fn clear_wrapped(&mut self) {
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);
impl PwmBatch {
#[inline]
+ /// Enable a PWM channel in this batch.
pub fn enable(&mut self, pwm: &Pwm<'_, impl Channel>) {
self.0 |= pwm.bit();
}
#[inline]
+ /// Enable channels in this batch in a PWM.
pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) {
let mut en = PwmBatch(0);
batch(&mut en);
@@ -289,9 +304,12 @@ mod sealed {
pub trait Channel {}
}
+/// PWM Channel.
pub trait Channel: Peripheral + sealed::Channel + Sized + 'static {
+ /// Channel number.
fn number(&self) -> u8;
+ /// Channel register block.
fn regs(&self) -> pac::pwm::Channel {
pac::PWM.ch(self.number() as _)
}
@@ -317,7 +335,9 @@ channel!(PWM_CH5, 5);
channel!(PWM_CH6, 6);
channel!(PWM_CH7, 7);
+/// PWM Pin A.
pub trait PwmPinA