aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/adc.rs24
-rw-r--r--embassy-rp/src/clocks.rs97
-rw-r--r--embassy-rp/src/dma.rs20
-rw-r--r--embassy-rp/src/flash.rs42
-rw-r--r--embassy-rp/src/gpio.rs68
-rw-r--r--embassy-rp/src/i2c.rs22
-rw-r--r--embassy-rp/src/i2c_slave.rs3
-rw-r--r--embassy-rp/src/lib.rs1
-rw-r--r--embassy-rp/src/pio/mod.rs1
-rw-r--r--embassy-rp/src/pwm.rs20
-rw-r--r--embassy-rp/src/rtc/mod.rs1
-rw-r--r--embassy-rp/src/timer.rs1
-rw-r--r--embassy-rp/src/uart/buffered.rs1
-rw-r--r--embassy-rp/src/uart/mod.rs3
-rw-r--r--embassy-rp/src/usb.rs1
15 files changed, 294 insertions, 11 deletions
diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs
index 5b913f156..21360bf66 100644
--- a/embassy-rp/src/adc.rs
+++ b/embassy-rp/src/adc.rs
@@ -1,3 +1,4 @@
1//! ADC driver.
1use core::future::poll_fn; 2use core::future::poll_fn;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::mem; 4use core::mem;
@@ -16,6 +17,7 @@ use crate::{dma, interrupt, pac, peripherals, Peripheral, RegExt};
16 17
17static WAKER: AtomicWaker = AtomicWaker::new(); 18static WAKER: AtomicWaker = AtomicWaker::new();
18 19
20/// ADC config.
19#[non_exhaustive] 21#[non_exhaustive]
20pub struct Config {} 22pub struct Config {}
21 23
@@ -30,9 +32,11 @@ enum Source<'p> {
30 TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>), 32 TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>),
31} 33}
32 34
35/// ADC channel.
33pub struct Channel<'p>(Source<'p>); 36pub struct Channel<'p>(Source<'p>);
34 37
35impl<'p> Channel<'p> { 38impl<'p> Channel<'p> {
39 /// Create a new ADC channel from pin with the provided [Pull] configuration.
36 pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self { 40 pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self {
37 into_ref!(pin); 41 into_ref!(pin);
38 pin.pad_ctrl().modify(|w| { 42 pin.pad_ctrl().modify(|w| {
@@ -49,6 +53,7 @@ impl<'p> Channel<'p> {
49 Self(Source::Pin(pin.map_into())) 53 Self(Source::Pin(pin.map_into()))
50 } 54 }
51 55
56 /// Create a new ADC channel for the internal temperature sensor.
52 pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self { 57 pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self {
53 let r = pac::ADC; 58 let r = pac::ADC;
54 r.cs().write_set(|w| w.set_ts_en(true)); 59 r.cs().write_set(|w| w.set_ts_en(true));
@@ -83,35 +88,44 @@ impl<'p> Drop for Source<'p> {
83 } 88 }
84} 89}
85 90
91/// ADC sample.
86#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)] 92#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))] 93#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88#[repr(transparent)] 94#[repr(transparent)]
89pub struct Sample(u16); 95pub struct Sample(u16);
90 96
91impl Sample { 97impl Sample {
98 /// Sample is valid.
92 pub fn good(&self) -> bool { 99 pub fn good(&self) -> bool {
93 self.0 < 0x8000 100 self.0 < 0x8000
94 } 101 }
95 102
103 /// Sample value.
96 pub fn value(&self) -> u16 { 104 pub fn value(&self) -> u16 {
97 self.0 & !0x8000 105 self.0 & !0x8000
98 } 106 }
99} 107}
100 108
109/// ADC error.
101#[derive(Debug, Eq, PartialEq, Copy, Clone)] 110#[derive(Debug, Eq, PartialEq, Copy, Clone)]
102#[cfg_attr(feature = "defmt", derive(defmt::Format))] 111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
103pub enum Error { 112pub enum Error {
113 /// Error converting value.
104 ConversionFailed, 114 ConversionFailed,
105} 115}
106 116
117/// ADC mode.
107pub trait Mode {} 118pub trait Mode {}
108 119
120/// ADC async mode.
109pub struct Async; 121pub struct Async;
110impl Mode for Async {} 122impl Mode for Async {}
111 123
124/// ADC blocking mode.
112pub struct Blocking; 125pub struct Blocking;
113impl Mode for Blocking {} 126impl Mode for Blocking {}
114 127
128/// ADC driver.
115pub struct Adc<'d, M: Mode> { 129pub struct Adc<'d, M: Mode> {
116 phantom: PhantomData<(&'d ADC, M)>, 130 phantom: PhantomData<(&'d ADC, M)>,
117} 131}
@@ -150,6 +164,7 @@ impl<'d, M: Mode> Adc<'d, M> {
150 while !r.cs().read().ready() {} 164 while !r.cs().read().ready() {}
151 } 165 }
152 166
167 /// Sample a value from a channel in blocking mode.
153 pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> { 168 pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> {
154 let r = Self::regs(); 169 let r = Self::regs();
155 r.cs().modify(|w| { 170 r.cs().modify(|w| {
@@ -166,6 +181,7 @@ impl<'d, M: Mode> Adc<'d, M> {
166} 181}
167 182
168impl<'d> Adc<'d, Async> { 183impl<'d> Adc<'d, Async> {
184 /// Create ADC driver in async mode.
169 pub fn new( 185 pub fn new(
170 _inner: impl Peripheral<P = ADC> + 'd, 186 _inner: impl Peripheral<P = ADC> + 'd,
171 _irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>, 187 _irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>,
@@ -194,6 +210,7 @@ impl<'d> Adc<'d, Async> {
194 .await; 210 .await;
195 } 211 }
196 212
213 /// Sample a value from a channel until completed.
197 pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> { 214 pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> {
198 let r = Self::regs(); 215 let r = Self::regs();
199 r.cs().modify(|w| { 216 r.cs().modify(|w| {
@@ -272,6 +289,7 @@ impl<'d> Adc<'d, Async> {
272 } 289 }
273 } 290 }
274 291
292 /// Sample multiple values from a channel using DMA.
275 #[inline] 293 #[inline]
276 pub async fn read_many<S: AdcSample>( 294 pub async fn read_many<S: AdcSample>(
277 &mut self, 295 &mut self,
@@ -283,6 +301,7 @@ impl<'d> Adc<'d, Async> {
283 self.read_many_inner(ch, buf, false, div, dma).await 301 self.read_many_inner(ch, buf, false, div, dma).await
284 } 302 }
285 303
304 /// Sample multiple values from a channel using DMA with errors inlined in samples.
286 #[inline] 305 #[inline]
287 pub async fn read_many_raw( 306 pub async fn read_many_raw(
288 &mut self, 307 &mut self,
@@ -299,6 +318,7 @@ impl<'d> Adc<'d, Async> {
299} 318}
300 319
301impl<'d> Adc<'d, Blocking> { 320impl<'d> Adc<'d, Blocking> {
321 /// Create ADC driver in blocking mode.
302 pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self { 322 pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self {
303 Self::setup(); 323 Self::setup();
304 324
@@ -306,6 +326,7 @@ impl<'d> Adc<'d, Blocking> {
306 } 326 }
307} 327}
308 328
329/// Interrupt handler.
309pub struct InterruptHandler { 330pub struct InterruptHandler {
310 _empty: (), 331 _empty: (),
311} 332}
@@ -324,6 +345,7 @@ mod sealed {
324 pub trait AdcChannel {} 345 pub trait AdcChannel {}
325} 346}
326 347
348/// ADC sample.
327pub trait AdcSample: sealed::AdcSample {} 349pub trait AdcSample: sealed::AdcSample {}
328 350
329impl sealed::AdcSample for u16 {} 351impl sealed::AdcSample for u16 {}
@@ -332,7 +354,9 @@ impl AdcSample for u16 {}
332impl sealed::AdcSample for u8 {} 354impl sealed::AdcSample for u8 {}
333impl AdcSample for u8 {} 355impl AdcSample for u8 {}
334 356
357/// ADC channel.
335pub trait AdcChannel: sealed::AdcChannel {} 358pub trait AdcChannel: sealed::AdcChannel {}
359/// ADC pin.
336pub trait AdcPin: AdcChannel + gpio::Pin {} 360pub trait AdcPin: AdcChannel + gpio::Pin {}
337 361
338macro_rules! impl_pin { 362macro_rules! impl_pin {
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index 2f0645615..19232b801 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -45,15 +45,20 @@ static CLOCKS: Clocks = Clocks {
45 rtc: AtomicU16::new(0), 45 rtc: AtomicU16::new(0),
46}; 46};
47 47
48/// Enumeration of supported clock sources. 48/// Peripheral clock sources.
49#[repr(u8)] 49#[repr(u8)]
50#[non_exhaustive] 50#[non_exhaustive]
51#[derive(Clone, Copy, Debug, PartialEq, Eq)] 51#[derive(Clone, Copy, Debug, PartialEq, Eq)]
52pub enum PeriClkSrc { 52pub enum PeriClkSrc {
53 /// SYS.
53 Sys = ClkPeriCtrlAuxsrc::CLK_SYS as _, 54 Sys = ClkPeriCtrlAuxsrc::CLK_SYS as _,
55 /// PLL SYS.
54 PllSys = ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS as _, 56 PllSys = ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS as _,
57 /// PLL USB.
55 PllUsb = ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB as _, 58 PllUsb = ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB as _,
59 /// ROSC.
56 Rosc = ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH as _, 60 Rosc = ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH as _,
61 /// XOSC.
57 Xosc = ClkPeriCtrlAuxsrc::XOSC_CLKSRC as _, 62 Xosc = ClkPeriCtrlAuxsrc::XOSC_CLKSRC as _,
58 // Gpin0 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 as _ , 63 // Gpin0 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
59 // Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ , 64 // Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
@@ -83,6 +88,7 @@ pub struct ClockConfig {
83} 88}
84 89
85impl ClockConfig { 90impl ClockConfig {
91 /// Clock configuration derived from external crystal.
86 pub fn crystal(crystal_hz: u32) -> Self { 92 pub fn crystal(crystal_hz: u32) -> Self {
87 Self { 93 Self {
88 rosc: Some(RoscConfig { 94 rosc: Some(RoscConfig {
@@ -141,6 +147,7 @@ impl ClockConfig {
141 } 147 }
142 } 148 }
143 149
150 /// Clock configuration from internal oscillator.
144 pub fn rosc() -> Self { 151 pub fn rosc() -> Self {
145 Self { 152 Self {
146 rosc: Some(RoscConfig { 153 rosc: Some(RoscConfig {
@@ -190,13 +197,18 @@ impl ClockConfig {
190 // } 197 // }
191} 198}
192 199
200/// ROSC freq range.
193#[repr(u16)] 201#[repr(u16)]
194#[non_exhaustive] 202#[non_exhaustive]
195#[derive(Clone, Copy, Debug, PartialEq, Eq)] 203#[derive(Clone, Copy, Debug, PartialEq, Eq)]
196pub enum RoscRange { 204pub enum RoscRange {
205 /// Low range.
197 Low = pac::rosc::vals::FreqRange::LOW.0, 206 Low = pac::rosc::vals::FreqRange::LOW.0,
207 /// Medium range (1.33x low)
198 Medium = pac::rosc::vals::FreqRange::MEDIUM.0, 208 Medium = pac::rosc::vals::FreqRange::MEDIUM.0,
209 /// High range (2x low)
199 High = pac::rosc::vals::FreqRange::HIGH.0, 210 High = pac::rosc::vals::FreqRange::HIGH.0,
211 /// Too high. Should not be used.
200 TooHigh = pac::rosc::vals::FreqRange::TOOHIGH.0, 212 TooHigh = pac::rosc::vals::FreqRange::TOOHIGH.0,
201} 213}
202 214
@@ -239,96 +251,136 @@ pub struct PllConfig {
239 pub post_div2: u8, 251 pub post_div2: u8,
240} 252}
241 253
242/// Reference 254/// Reference clock config.
243pub struct RefClkConfig { 255pub struct RefClkConfig {
256 /// Reference clock source.
244 pub src: RefClkSrc, 257 pub src: RefClkSrc,
258 /// Reference clock divider.
245 pub div: u8, 259 pub div: u8,
246} 260}
247 261
262/// Reference clock source.
248#[non_exhaustive] 263#[non_exhaustive]
249#[derive(Clone, Copy, Debug, PartialEq, Eq)] 264#[derive(Clone, Copy, Debug, PartialEq, Eq)]
250pub enum RefClkSrc { 265pub enum RefClkSrc {
251 // main sources 266 /// XOSC.
252 Xosc, 267 Xosc,
268 /// ROSC.
253 Rosc, 269 Rosc,
254 // aux sources 270 /// PLL USB.
255 PllUsb, 271 PllUsb,
256 // Gpin0, 272 // Gpin0,
257 // Gpin1, 273 // Gpin1,
258} 274}
259 275
276/// SYS clock source.
260#[non_exhaustive] 277#[non_exhaustive]
261#[derive(Clone, Copy, Debug, PartialEq, Eq)] 278#[derive(Clone, Copy, Debug, PartialEq, Eq)]
262pub enum SysClkSrc { 279pub enum SysClkSrc {
263 // main sources 280 /// REF.
264 Ref, 281 Ref,
265 // aux sources 282 /// PLL SYS.
266 PllSys, 283 PllSys,
284 /// PLL USB.
267 PllUsb, 285 PllUsb,
286 /// ROSC.
268 Rosc, 287 Rosc,
288 /// XOSC.
269 Xosc, 289 Xosc,
270 // Gpin0, 290 // Gpin0,
271 // Gpin1, 291 // Gpin1,
272} 292}
273 293
294/// SYS clock config.
274pub struct SysClkConfig { 295pub struct SysClkConfig {
296 /// SYS clock source.
275 pub src: SysClkSrc, 297 pub src: SysClkSrc,
298 /// SYS clock divider.
276 pub div_int: u32, 299 pub div_int: u32,
300 /// SYS clock fraction.
277 pub div_frac: u8, 301 pub div_frac: u8,
278} 302}
279 303
304/// USB clock source.
280#[repr(u8)] 305#[repr(u8)]
281#[non_exhaustive] 306#[non_exhaustive]
282#[derive(Clone, Copy, Debug, PartialEq, Eq)] 307#[derive(Clone, Copy, Debug, PartialEq, Eq)]
283pub enum UsbClkSrc { 308pub enum UsbClkSrc {
309 /// PLL USB.
284 PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _, 310 PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _,
311 /// PLL SYS.
285 PllSys = ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS as _, 312 PllSys = ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS as _,
313 /// ROSC.
286 Rosc = ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH as _, 314 Rosc = ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH as _,
315 /// XOSC.
287 Xosc = ClkUsbCtrlAuxsrc::XOSC_CLKSRC as _, 316 Xosc = ClkUsbCtrlAuxsrc::XOSC_CLKSRC as _,
288 // Gpin0 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 as _ , 317 // Gpin0 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
289 // Gpin1 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 as _ , 318 // Gpin1 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
290} 319}
291 320
321/// USB clock config.
292pub struct UsbClkConfig { 322pub struct UsbClkConfig {
323 /// USB clock source.
293 pub src: UsbClkSrc, 324 pub src: UsbClkSrc,
325 /// USB clock divider.
294 pub div: u8, 326 pub div: u8,
327 /// USB clock phase.
295 pub phase: u8, 328 pub phase: u8,
296} 329}
297 330
331/// ADC clock source.
298#[repr(u8)] 332#[repr(u8)]
299#[non_exhaustive] 333#[non_exhaustive]
300#[derive(Clone, Copy, Debug, PartialEq, Eq)] 334#[derive(Clone, Copy, Debug, PartialEq, Eq)]
301pub enum AdcClkSrc { 335pub enum AdcClkSrc {
336 /// PLL USB.
302 PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _, 337 PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _,
338 /// PLL SYS.
303 PllSys = ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS as _, 339 PllSys = ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
340 /// ROSC.
304 Rosc = ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH as _, 341 Rosc = ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
342 /// XOSC.
305 Xosc = ClkAdcCtrlAuxsrc::XOSC_CLKSRC as _, 343 Xosc = ClkAdcCtrlAuxsrc::XOSC_CLKSRC as _,
306 // Gpin0 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 as _ , 344 // Gpin0 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
307 // Gpin1 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 as _ , 345 // Gpin1 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
308} 346}
309 347
348/// ADC clock config.
310pub struct AdcClkConfig { 349pub struct AdcClkConfig {
350 /// ADC clock source.
311 pub src: AdcClkSrc, 351 pub src: AdcClkSrc,
352 /// ADC clock divider.
312 pub div: u8, 353 pub div: u8,
354 /// ADC clock phase.
313 pub phase: u8, 355 pub phase: u8,
314} 356}
315 357
358/// RTC clock source.
316#[repr(u8)] 359#[repr(u8)]
317#[non_exhaustive] 360#[non_exhaustive]
318#[derive(Clone, Copy, Debug, PartialEq, Eq)] 361#[derive(Clone, Copy, Debug, PartialEq, Eq)]
319pub enum RtcClkSrc { 362pub enum RtcClkSrc {
363 /// PLL USB.
320 PllUsb = ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB as _, 364 PllUsb = ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB as _,
365 /// PLL SYS.
321 PllSys = ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS as _, 366 PllSys = ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
367 /// ROSC.
322 Rosc = ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH as _, 368 Rosc = ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
369 /// XOSC.
323 Xosc = ClkRtcCtrlAuxsrc::XOSC_CLKSRC as _, 370 Xosc = ClkRtcCtrlAuxsrc::XOSC_CLKSRC as _,
324 // Gpin0 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 as _ , 371 // Gpin0 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
325 // Gpin1 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 as _ , 372 // Gpin1 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
326} 373}
327 374
375/// RTC clock config.
328pub struct RtcClkConfig { 376pub struct RtcClkConfig {
377 /// RTC clock source.
329 pub src: RtcClkSrc, 378 pub src: RtcClkSrc,
379 /// RTC clock divider.
330 pub div_int: u32, 380 pub div_int: u32,
381 /// RTC clock divider fraction.
331 pub div_frac: u8, 382 pub div_frac: u8,
383 /// RTC clock phase.
332 pub phase: u8, 384 pub phase: u8,
333} 385}
334 386
@@ -605,10 +657,12 @@ fn configure_rosc(config: RoscConfig) -> u32 {
605 config.hz 657 config.hz
606} 658}
607 659
660/// ROSC clock frequency.
608pub fn rosc_freq() -> u32 { 661pub fn rosc_freq() -> u32 {
609 CLOCKS.rosc.load(Ordering::Relaxed) 662 CLOCKS.rosc.load(Ordering::Relaxed)
610} 663}
611 664
665/// XOSC clock frequency.
612pub fn xosc_freq() -> u32 { 666pub fn xosc_freq() -> u32 {
613 CLOCKS.xosc.load(Ordering::Relaxed) 667 CLOCKS.xosc.load(Ordering::Relaxed)
614} 668}
@@ -620,34 +674,42 @@ pub fn xosc_freq() -> u32 {
620// CLOCKS.gpin1.load(Ordering::Relaxed) 674// CLOCKS.gpin1.load(Ordering::Relaxed)
621// } 675// }
622 676
677/// PLL SYS clock frequency.
623pub fn pll_sys_freq() -> u32 { 678pub fn pll_sys_freq() -> u32 {
624 CLOCKS.pll_sys.load(Ordering::Relaxed) 679 CLOCKS.pll_sys.load(Ordering::Relaxed)
625} 680}
626 681
682/// PLL USB clock frequency.
627pub fn pll_usb_freq() -> u32 { 683pub fn pll_usb_freq() -> u32 {
628 CLOCKS.pll_usb.load(Ordering::Relaxed) 684 CLOCKS.pll_usb.load(Ordering::Relaxed)
629} 685}
630 686
687/// SYS clock frequency.
631pub fn clk_sys_freq() -> u32 { 688pub fn clk_sys_freq() -> u32 {
632 CLOCKS.sys.load(Ordering::Relaxed) 689 CLOCKS.sys.load(Ordering::Relaxed)
633} 690}
634 691
692/// REF clock frequency.
635pub fn clk_ref_freq() -> u32 { 693pub fn clk_ref_freq() -> u32 {
636 CLOCKS.reference.load(Ordering::Relaxed) 694 CLOCKS.reference.load(Ordering::Relaxed)
637} 695}
638 696
697/// Peripheral clock frequency.
639pub fn clk_peri_freq() -> u32 { 698pub fn clk_peri_freq() -> u32 {
640 CLOCKS.peri.load(Ordering::Relaxed) 699 CLOCKS.peri.load(Ordering::Relaxed)
641} 700}
642 701
702/// USB clock frequency.
643pub fn clk_usb_freq() -> u32 { 703pub fn clk_usb_freq() -> u32 {
644 CLOCKS.usb.load(Ordering::Relaxed) 704 CLOCKS.usb.load(Ordering::Relaxed)
645} 705}
646 706
707/// ADC clock frequency.
647pub fn clk_adc_freq() -> u32 { 708pub fn clk_adc_freq() -> u32 {
648 CLOCKS.adc.load(Ordering::Relaxed) 709 CLOCKS.adc.load(Ordering::Relaxed)
649} 710}
650 711
712/// RTC clock frequency.
651pub fn clk_rtc_freq() -> u16 { 713pub fn clk_rtc_freq() -> u16 {
652 CLOCKS.rtc.load(Ordering::Relaxed) 714 CLOCKS.rtc.load(Ordering::Relaxed)
653} 715}
@@ -708,7 +770,9 @@ fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 {
708 vco_freq / ((config.post_div1 * config.post_div2) as u32) 770 vco_freq / ((config.post_div1 * config.post_div2) as u32)
709} 771}
710 772
773/// General purpose input clock pin.
711pub trait GpinPin: crate::gpio::Pin { 774pub trait GpinPin: crate::gpio::Pin {
775 /// Pin number.
712 const NR: usize; 776 const NR: usize;
713} 777}
714 778
@@ -723,12 +787,14 @@ macro_rules! impl_gpinpin {
723impl_gpinpin!(PIN_20, 20, 0); 787impl_gpinpin!(PIN_20, 20, 0);
724impl_gpinpin!(PIN_22, 22, 1); 788impl_gpinpin!(PIN_22, 22, 1);
725 789
790/// General purpose clock input driver.
726pub struct Gpin<'d, T: Pin> { 791pub struct Gpin<'d, T: Pin> {
727 gpin: PeripheralRef<'d, AnyPin>, 792 gpin: PeripheralRef<'d, AnyPin>,
728 _phantom: PhantomData<T>, 793 _phantom: PhantomData<T>,
729} 794}
730 795
731impl<'d, T: Pin> Gpin<'d, T> { 796impl<'d, T: Pin> Gpin<'d, T> {
797 /// Create new gpin driver.
732 pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> { 798 pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> {
733 into_ref!(gpin); 799 into_ref!(gpin);
734 800
@@ -754,7 +820,9 @@ impl<'d, T: Pin> Drop for Gpin<'d, T> {
754 } 820 }
755} 821}
756 822
823/// General purpose clock output pin.
757pub trait GpoutPin: crate::gpio::Pin { 824pub trait GpoutPin: crate::gpio::Pin {
825 /// Pin number.
758 fn number(&self) -> usize; 826 fn number(&self) -> usize;
759} 827}
760 828
@@ -773,26 +841,38 @@ impl_gpoutpin!(PIN_23, 1);
773impl_gpoutpin!(PIN_24, 2); 841impl_gpoutpin!(PIN_24, 2);
774impl_gpoutpin!(PIN_25, 3); 842impl_gpoutpin!(PIN_25, 3);
775 843
844/// Gpout clock source.
776#[repr(u8)] 845#[repr(u8)]
777pub enum GpoutSrc { 846pub enum GpoutSrc {
847 /// Sys PLL.
778 PllSys = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS as _, 848 PllSys = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS as _,
779 // Gpin0 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 as _ , 849 // Gpin0 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
780 // Gpin1 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 as _ , 850 // Gpin1 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
851 /// USB PLL.
781 PllUsb = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB as _, 852 PllUsb = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB as _,
853 /// ROSC.
782 Rosc = ClkGpoutCtrlAuxsrc::ROSC_CLKSRC as _, 854 Rosc = ClkGpoutCtrlAuxsrc::ROSC_CLKSRC as _,
855 /// XOSC.
783 Xosc = ClkGpoutCtrlAuxsrc::XOSC_CLKSRC as _, 856 Xosc = ClkGpoutCtrlAuxsrc::XOSC_CLKSRC as _,
857 /// SYS.
784 Sys = ClkGpoutCtrlAuxsrc::CLK_SYS as _, 858 Sys = ClkGpoutCtrlAuxsrc::CLK_SYS as _,
859 /// USB.
785 Usb = ClkGpoutCtrlAuxsrc::CLK_USB as _, 860 Usb = ClkGpoutCtrlAuxsrc::CLK_USB as _,
861 /// ADC.
786 Adc = ClkGpoutCtrlAuxsrc::CLK_ADC as _, 862 Adc = ClkGpoutCtrlAuxsrc::CLK_ADC as _,
863 /// RTC.
787 Rtc = ClkGpoutCtrlAuxsrc::CLK_RTC as _, 864 Rtc = ClkGpoutCtrlAuxsrc::CLK_RTC as _,
865 /// REF.
788 Ref = ClkGpoutCtrlAuxsrc::CLK_REF as _, 866 Ref = ClkGpoutCtrlAuxsrc::CLK_REF as _,
789} 867}
790 868
869/// General purpose clock output driver.
791pub struct Gpout<'d, T: GpoutPin> { 870pub struct Gpout<'d, T: GpoutPin> {
792 gpout: PeripheralRef<'d, T>, 871 gpout: PeripheralRef<'d, T>,
793} 872}
794 873
795impl<'d, T: GpoutPin> Gpout<'d, T> { 874impl<'d, T: GpoutPin> Gpout<'d, T> {
875 /// Create new general purpose cloud output.
796 pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self { 876 pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self {
797 into_ref!(gpout); 877 into_ref!(gpout);
798 878
@@ -801,6 +881,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
801 Self { gpout } 881 Self { gpout }
802 } 882 }
803 883
884 /// Set clock divider.
804 pub fn set_div(&self, int: u32, frac: u8) { 885 pub fn set_div(&self, int: u32, frac: u8) {
805 let c = pac::CLOCKS; 886 let c = pac::CLOCKS;
806 c.clk_gpout_div(self.gpout.number()).write(|w| { 887 c.clk_gpout_div(self.gpout.number()).write(|w| {
@@ -809,6 +890,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
809 }); 890 });
810 } 891 }
811 892
893 /// Set clock source.
812 pub fn set_src(&self, src: GpoutSrc) { 894 pub fn set_src(&self, src: GpoutSrc) {
813 let c = pac::CLOCKS; 895 let c = pac::CLOCKS;
814 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { 896 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
@@ -816,6 +898,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
816 }); 898 });
817 } 899 }
818 900
901 /// Enable clock.
819 pub fn enable(&self) { 902 pub fn enable(&self) {
820 let c = pac::CLOCKS; 903 let c = pac::CLOCKS;
821 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { 904 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
@@ -823,6 +906,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
823 }); 906 });
824 } 907 }
825 908
909 /// Disable clock.
826 pub fn disable(&self) { 910 pub fn disable(&self) {
827 let c = pac::CLOCKS; 911 let c = pac::CLOCKS;
828 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { 912 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
@@ -830,6 +914,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
830 }); 914 });
831 } 915 }
832 916
917 /// Clock frequency.
833 pub fn get_freq(&self) -> u32 { 918 pub fn get_freq(&self) -> u32 {
834 let c = pac::CLOCKS; 919 let c = pac::CLOCKS;
835 let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc(); 920 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 45ca21a75..088a842a1 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -38,6 +38,9 @@ pub(crate) unsafe fn init() {
38 interrupt::DMA_IRQ_0.enable(); 38 interrupt::DMA_IRQ_0.enable();
39} 39}
40 40
41/// DMA read.
42///
43/// SAFETY: Slice must point to a valid location reachable by DMA.
41pub unsafe fn read<'a, C: Channel, W: Word>( 44pub unsafe fn read<'a, C: Channel, W: Word>(
42 ch: impl Peripheral<P = C> + 'a, 45 ch: impl Peripheral<P = C> + 'a,
43 from: *const W, 46 from: *const W,
@@ -57,6 +60,9 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
57 ) 60 )
58} 61}
59 62
63/// DMA write.
64///
65/// SAFETY: Slice must point to a valid location reachable by DMA.
60pub unsafe fn write<'a, C: Channel, W: Word>( 66pub unsafe fn write<'a, C: Channel, W: Word>(
61 ch: impl Peripheral<P = C> + 'a, 67 ch: impl Peripheral<P = C> + 'a,
62 from: *const [W], 68 from: *const [W],
@@ -79,6 +85,9 @@ pub unsafe fn write<'a, C: Channel, W: Word>(
79// static mut so that this is allocated in RAM. 85// static mut so that this is allocated in RAM.
80static mut DUMMY: u32 = 0; 86static mut DUMMY: u32 = 0;
81 87
88/// DMA repeated write.
89///
90/// SAFETY: Slice must point to a valid location reachable by DMA.
82pub unsafe fn write_repeated<'a, C: Channel, W: Word>( 91pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
83 ch: impl Peripheral<P = C> + 'a, 92 ch: impl Peripheral<P = C> + 'a,
84 to: *mut W, 93 to: *mut W,
@@ -97,6 +106,9 @@ pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
97 ) 106 )
98} 107}
99 108
109/// DMA copy between slices.
110///
111/// SAFETY: Slices must point to locations reachable by DMA.
100pub unsafe fn copy<'a, C: Channel, W: Word>( 112pub unsafe fn copy<'a, C: Channel, W: Word>(
101 ch: impl Peripheral<P = C> + 'a, 113 ch: impl Peripheral<P = C> + 'a,
102 from: &[W], 114 from: &[W],
@@ -152,6 +164,7 @@ fn copy_inner<'a, C: Channel>(
152 Transfer::new(ch) 164 Transfer::new(ch)
153} 165}
154 166
167/// DMA transfer driver.
155#[must_use = "futures do nothing unless you `.await` or poll them"] 168#[must_use = "futures do nothing unless you `.await` or poll them"]
156pub struct Transfer<'a, C: Channel> { 169pub struct Transfer<'a, C: Channel> {
157 channel: PeripheralRef<'a, C>, 170 channel: PeripheralRef<'a, C>,
@@ -201,19 +214,25 @@ mod sealed {
201 pub trait Word {} 214 pub trait Word {}
202} 215}
203 216
217/// DMA channel interface.
204pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static { 218pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static {
219 /// Channel number.
205 fn number(&self) -> u8; 220 fn number(&self) -> u8;
206 221
222 /// Channel registry block.
207 fn regs(&self) -> pac::dma::Channel { 223 fn regs(&self) -> pac::dma::Channel {
208 pac::DMA.ch(self.number() as _) 224 pac::DMA.ch(self.number() as _)
209 } 225 }
210 226
227 /// Convert into type-erased [AnyChannel].
211 fn degrade(self) -> AnyChannel { 228 fn degrade(self) -> AnyChannel {
212 AnyChannel { number: self.number() } 229 AnyChannel { number: self.number() }
213 } 230 }
214} 231}
215 232
233/// DMA word.
216pub trait Word: sealed::Word { 234pub trait Word: sealed::Word {
235 /// Word size.
217 fn size() -> vals::DataSize; 236 fn size() -> vals::DataSize;
218} 237}
219 238
@@ -238,6 +257,7 @@ impl Word for u32 {
238 } 257 }
239} 258}
240 259
260/// Type erased DMA channel.
241pub struct AnyChannel { 261pub struct AnyChannel {
242 number: u8, 262 number: u8,
243} 263}
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs
index 1b20561da..2d673cf6c 100644
--- a/embassy-rp/src/flash.rs
+++ b/embassy-rp/src/flash.rs
@@ -1,3 +1,4 @@
1//! Flash driver.
1use core::future::Future; 2use core::future::Future;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::pin::Pin; 4use core::pin::Pin;
@@ -13,9 +14,10 @@ use crate::dma::{AnyChannel, Channel, Transfer};
13use crate::pac; 14use crate::pac;
14use crate::peripherals::FLASH; 15use crate::peripherals::FLASH;
15 16
17/// Flash base address.
16pub const FLASH_BASE: *const u32 = 0x10000000 as _; 18pub const FLASH_BASE: *const u32 = 0x10000000 as _;
17 19
18// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead. 20/// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead.
19// TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance. 21// TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance.
20pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram"); 22pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram");
21 23
@@ -24,10 +26,15 @@ pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram");
24// These limitations are currently enforced because of using the 26// These limitations are currently enforced because of using the
25// RP2040 boot-rom flash functions, that are optimized for flash compatibility 27// RP2040 boot-rom flash functions, that are optimized for flash compatibility
26// rather than performance. 28// rather than performance.
29/// Flash page size.
27pub const PAGE_SIZE: usize = 256; 30pub const PAGE_SIZE: usize = 256;
31/// Flash write size.
28pub const WRITE_SIZE: usize = 1; 32pub const WRITE_SIZE: usize = 1;
33/// Flash read size.
29pub const READ_SIZE: usize = 1; 34pub const READ_SIZE: usize = 1;
35/// Flash erase size.
30pub const ERASE_SIZE: usize = 4096; 36pub const ERASE_SIZE: usize = 4096;
37/// Flash DMA read size.
31pub const ASYNC_READ_SIZE: usize = 4; 38pub const ASYNC_READ_SIZE: usize = 4;
32 39
33/// Error type for NVMC operations. 40/// Error type for NVMC operations.
@@ -38,7 +45,9 @@ pub enum Error {
38 OutOfBounds, 45 OutOfBounds,
39 /// Unaligned operation or using unaligned buffers. 46 /// Unaligned operation or using unaligned buffers.
40 Unaligned, 47 Unaligned,
48 /// Accessed from the wrong core.
41 InvalidCore, 49 InvalidCore,
50 /// Other error
42 Other, 51 Other,
43} 52}
44 53
@@ -96,12 +105,18 @@ impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Drop for BackgroundRead<'a, '
96 } 105 }
97} 106}
98 107
108/// Flash driver.
99pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> { 109pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> {
100 dma: Option<PeripheralRef<'d, AnyChannel>>, 110 dma: Option<PeripheralRef<'d, AnyChannel>>,
101 phantom: PhantomData<(&'d mut T, M)>, 111 phantom: PhantomData<(&'d mut T, M)>,
102} 112}
103 113
104impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> { 114impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> {
115 /// Blocking read.
116 ///
117 /// The offset and buffer must be aligned.
118 ///
119 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
105 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 120 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
106 trace!( 121 trace!(
107 "Reading from 0x{:x} to 0x{:x}", 122 "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
116 Ok(()) 131 Ok(())
117 } 132 }
118 133
134 /// Flash capacity.
119 pub fn capacity(&self) -> usize { 135 pub fn capacity(&self) -> usize {
120 FLASH_SIZE 136 FLASH_SIZE
121 } 137 }
122 138
139 /// Blocking erase.
140 ///
141 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
123 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 142 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
124 check_erase(self, from, to)?; 143 check_erase(self, from, to)?;
125 144
@@ -136,6 +155,11 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
136 Ok(()) 155 Ok(())
137 } 156 }
138 157
158 /// Blocking write.
159 ///
160 /// The offset and buffer must be aligned.
161 ///
162 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
139 pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 163 pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
140 check_write(self, offset, bytes.len())?; 164 check_write(self, offset, bytes.len())?;
141 165
@@ -219,6 +243,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
219} 243}
220 244
221impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> { 245impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> {
246 /// Create a new flash driver in blocking mode.
222 pub fn new_blocking(_flash: impl Peripheral<P = T> + 'd) -> Self { 247 pub fn new_blocking(_flash: impl Peripheral<P = T> + 'd) -> Self {
223 Self { 248 Self {
224 dma: None, 249 dma: None,
@@ -228,6 +253,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE
228} 253}
229 254
230impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> { 255impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
256 /// Create a new flash driver in async mode.
231 pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self { 257 pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self {
232 into_ref!(dma); 258 into_ref!(dma);
233 Self { 259 Self {
@@ -236,6 +262,11 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
236 } 262 }
237 } 263 }
238 264
265 /// Start a background read operation.
266 ///
267 /// The offset and buffer must be aligned.
268 ///
269 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
239 pub fn background_read<'a>( 270 pub fn background_read<'a>(
240 &'a mut self, 271 &'a mut self,
241 offset: u32, 272 offset: u32,
@@ -279,6 +310,11 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
279 }) 310 })
280 } 311 }
281 312
313 /// Async read.
314 ///
315 /// The offset and buffer must be aligned.
316 ///
317 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
282 pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 318 pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
283 use core::mem::MaybeUninit; 319 use core::mem::MaybeUninit;
284 320
@@ -874,7 +910,9 @@ mod sealed {
874 pub trait Mode {} 910 pub trait Mode {}
875} 911}
876 912
913/// Flash instance.
877pub trait Instance: sealed::Instance {} 914pub trait Instance: sealed::Instance {}
915/// Flash mode.
878pub trait Mode: sealed::Mode {} 916pub trait Mode: sealed::Mode {}
879 917
880impl sealed::Instance for FLASH {} 918impl sealed::Instance for FLASH {}
@@ -887,7 +925,9 @@ macro_rules! impl_mode {
887 }; 925 };
888} 926}
889 927
928/// Flash blocking mode.
890pub struct Blocking; 929pub struct Blocking;
930/// Flash async mode.
891pub struct Async; 931pub struct Async;
892 932
893impl_mode!(Blocking); 933impl_mode!(Blocking);
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 23273e627..2e6692abe 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -1,3 +1,4 @@
1//! GPIO driver.
1#![macro_use] 2#![macro_use]
2use core::convert::Infallible; 3use core::convert::Infallible;
3use core::future::Future; 4use core::future::Future;
@@ -23,7 +24,9 @@ static QSPI_WAKERS: [AtomicWaker; QSPI_PIN_COUNT] = [NEW_AW; QSPI_PIN_COUNT];
23/// Represents a digital input or output level. 24/// Represents a digital input or output level.
24#[derive(Debug, Eq, PartialEq, Clone, Copy)] 25#[derive(Debug, Eq, PartialEq, Clone, Copy)]
25pub enum Level { 26pub enum Level {
27 /// Logical low.
26 Low, 28 Low,
29 /// Logical high.
27 High, 30 High,
28} 31}
29 32
@@ -48,48 +51,66 @@ impl From<Level> for bool {
48/// Represents a pull setting for an input. 51/// Represents a pull setting for an input.
49#[derive(Debug, Clone, Copy, Eq, PartialEq)] 52#[derive(Debug, Clone, Copy, Eq, PartialEq)]
50pub enum Pull { 53pub enum Pull {
54 /// No pull.
51 None, 55 None,
56 /// Internal pull-up resistor.
52 Up, 57 Up,
58 /// Internal pull-down resistor.
53 Down, 59 Down,
54} 60}
55 61
56/// Drive strength of an output 62/// Drive strength of an output
57#[derive(Debug, Eq, PartialEq)] 63#[derive(Debug, Eq, PartialEq)]
58pub enum Drive { 64pub enum Drive {
65 /// 2 mA drive.
59 _2mA, 66 _2mA,
67 /// 4 mA drive.
60 _4mA, 68 _4mA,
69 /// 8 mA drive.
61 _8mA, 70 _8mA,
71 /// 1 2mA drive.
62 _12mA, 72 _12mA,
63} 73}
64/// Slew rate of an output 74/// Slew rate of an output
65#[derive(Debug, Eq, PartialEq)] 75#[derive(Debug, Eq, PartialEq)]
66pub enum SlewRate { 76pub enum SlewRate {
77 /// Fast slew rate.
67 Fast, 78 Fast,
79 /// Slow slew rate.
68 Slow, 80 Slow,
69} 81}
70 82
71/// A GPIO bank with up to 32 pins. 83/// A GPIO bank with up to 32 pins.
72#[derive(Debug, Eq, PartialEq)] 84#[derive(Debug, Eq, PartialEq)]
73pub enum Bank { 85pub enum Bank {
86 /// Bank 0.
74 Bank0 = 0, 87 Bank0 = 0,
88 /// QSPI.
75 #[cfg(feature = "qspi-as-gpio")] 89 #[cfg(feature = "qspi-as-gpio")]
76 Qspi = 1, 90 Qspi = 1,
77} 91}
78 92
93/// Dormant mode config.
79#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)] 94#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))] 95#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub struct DormantWakeConfig { 96pub struct DormantWakeConfig {
97 /// Wake on edge high.
82 pub edge_high: bool, 98 pub edge_high: bool,
99 /// Wake on edge low.
83 pub edge_low: bool, 100 pub edge_low: bool,
101 /// Wake on level high.
84 pub level_high: bool, 102 pub level_high: bool,
103 /// Wake on level low.
85 pub level_low: bool, 104 pub level_low: bool,
86} 105}
87 106
107/// GPIO input driver.
88pub struct Input<'d, T: Pin> { 108pub struct Input<'d, T: Pin> {
89 pin: Flex<'d, T>, 109 pin: Flex<'d, T>,
90} 110}
91 111
92impl<'d, T: Pin> Input<'d, T> { 112impl<'d, T: Pin> Input<'d, T> {
113 /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
93 #[inline] 114 #[inline]
94 pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self { 115 pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
95 let mut pin = Flex::new(pin); 116 let mut pin = Flex::new(pin);
@@ -104,11 +125,13 @@ impl<'d, T: Pin> Input<'d, T> {
104 self.pin.set_schmitt(enable) 125 self.pin.set_schmitt(enable)
105 } 126 }
106 127
128 /// Get whether the pin input level is high.
107 #[inline] 129 #[inline]
108 pub fn is_high(&mut self) -> bool { 130 pub fn is_high(&mut self) -> bool {
109 self.pin.is_high() 131 self.pin.is_high()
110 } 132 }
111 133
134 /// Get whether the pin input level is low.
112 #[inline] 135 #[inline]
113 pub fn is_low(&mut self) -> bool { 136 pub fn is_low(&mut self) -> bool {
114 self.pin.is_low() 137 self.pin.is_low()
@@ -120,31 +143,37 @@ impl<'d, T: Pin> Input<'d, T> {
120 self.pin.get_level() 143 self.pin.get_level()
121 } 144 }
122 145
146 /// Wait until the pin is high. If it is already high, return immediately.
123 #[inline] 147 #[inline]
124 pub async fn wait_for_high(&mut self) { 148 pub async fn wait_for_high(&mut self) {
125 self.pin.wait_for_high().await; 149 self.pin.wait_for_high().await;
126 } 150 }
127 151
152 /// Wait until the pin is low. If it is already low, return immediately.
128 #[inline] 153 #[inline]
129 pub async fn wait_for_low(&mut self) { 154 pub async fn wait_for_low(&mut self) {
130 self.pin.wait_for_low().await; 155 self.pin.wait_for_low().await;
131 } 156 }
132 157
158 /// Wait for the pin to undergo a transition from low to high.
133 #[inline] 159 #[inline]
134 pub async fn wait_for_rising_edge(&mut self) { 160 pub async fn wait_for_rising_edge(&mut self) {
135 self.pin.wait_for_rising_edge().await; 161 self.pin.wait_for_rising_edge().await;
136 } 162 }
137 163
164 /// Wait for the pin to undergo a transition from high to low.
138 #[inline] 165 #[inline]
139 pub async fn wait_for_falling_edge(&mut self) { 166 pub async fn wait_for_falling_edge(&mut self) {
140 self.pin.wait_for_falling_edge().await; 167 self.pin.wait_for_falling_edge().await;
141 } 168 }
142 169
170 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
143 #[inline] 171 #[inline]
144 pub async fn wait_for_any_edge(&mut self) { 172 pub async fn wait_for_any_edge(&mut self) {
145 self.pin.wait_for_any_edge().await; 173 self.pin.wait_for_any_edge().await;
146 } 174 }
147 175
176 /// Configure dormant wake.
148 #[inline] 177 #[inline]
149 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> { 178 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
150 self.pin.dormant_wake(cfg) 179 self.pin.dormant_wake(cfg)
@@ -155,10 +184,15 @@ impl<'d, T: Pin> Input<'d, T> {
155#[derive(Debug, Eq, PartialEq, Copy, Clone)] 184#[derive(Debug, Eq, PartialEq, Copy, Clone)]
156#[cfg_attr(feature = "defmt", derive(defmt::Format))] 185#[cfg_attr(feature = "defmt", derive(defmt::Format))]
157pub enum InterruptTrigger { 186pub enum InterruptTrigger {
187 /// Trigger on pin low.
158 LevelLow, 188 LevelLow,
189 /// Trigger on pin high.
159 LevelHigh, 190 LevelHigh,
191 /// Trigger on high to low transition.
160 EdgeLow, 192 EdgeLow,
193 /// Trigger on low to high transition.
161 EdgeHigh, 194 EdgeHigh,
195 /// Trigger on any transition.
162 AnyEdge, 196 AnyEdge,
163} 197}
164 198
@@ -226,6 +260,7 @@ struct InputFuture<'a, T: Pin> {
226} 260}
227 261
228impl<'d, T: Pin> InputFuture<'d, T> { 262impl<'d, T: Pin> InputFuture<'d, T> {
263 /// Create a new future wiating for input trigger.
229 pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self { 264 pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self {
230 into_ref!(pin); 265 into_ref!(pin);
231 let pin_group = (pin.pin() % 8) as usize; 266 let pin_group = (pin.pin() % 8) as usize;
@@ -308,11 +343,13 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> {
308 } 343 }
309} 344}
310 345
346/// GPIO output driver.
311pub struct Output<'d, T: Pin> { 347pub struct Output<'d, T: Pin> {
312 pin: Flex<'d, T>, 348 pin: Flex<'d, T>,
313} 349}
314 350
315impl<'d, T: Pin> Output<'d, T> { 351impl<'d, T: Pin> Output<'d, T> {
352 /// Create GPIO output driver for a [Pin] with the provided [Level].
316 #[inline] 353 #[inline]
317 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self { 354 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
318 let mut pin = Flex::new(pin); 355 let mut pin = Flex::new(pin);
@@ -331,7 +368,7 @@ impl<'d, T: Pin> Output<'d, T> {
331 self.pin.set_drive_strength(strength) 368 self.pin.set_drive_strength(strength)
332 } 369 }
333 370
334 // Set the pin's slew rate. 371 /// Set the pin's slew rate.
335 #[inline] 372 #[inline]
336 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { 373 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
337 self.pin.set_slew_rate(slew_rate) 374 self.pin.set_slew_rate(slew_rate)
@@ -386,6 +423,7 @@ pub struct OutputOpenDrain<'d, T: Pin> {
386} 423}
387 424
388impl<'d, T: Pin> OutputOpenDrain<'d, T> { 425impl<'d, T: Pin> OutputOpenDrain<'d, T> {
426 /// Create GPIO output driver for a [Pin] in open drain mode with the provided [Level].
389 #[inline] 427 #[inline]
390 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self { 428 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
391 let mut pin = Flex::new(pin); 429 let mut pin = Flex::new(pin);
@@ -403,7 +441,7 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
403 self.pin.set_drive_strength(strength) 441 self.pin.set_drive_strength(strength)
404 } 442 }
405 443
406 // Set the pin's slew rate. 444 /// Set the pin's slew rate.
407 #[inline] 445 #[inline]
408 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { 446 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
409 self.pin.set_slew_rate(slew_rate) 447 self.pin.set_slew_rate(slew_rate)
@@ -456,11 +494,13 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
456 self.pin.toggle_set_as_output() 494 self.pin.toggle_set_as_output()
457 } 495 }
458 496
497 /// Get whether the pin input level is high.
459 #[inline] 498 #[inline]
460 pub fn is_high(&mut self) -> bool { 499 pub fn is_high(&mut self) -> bool {
461 self.pin.is_high() 500 self.pin.is_high()
462 } 501 }
463 502
503 /// Get whether the pin input level is low.
464 #[inline] 504 #[inline]
465 pub fn is_low(&mut self) -> bool { 505 pub fn is_low(&mut self) -> bool {
466 self.pin.is_low() 506 self.pin.is_low()
@@ -472,26 +512,31 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
472 self.is_high().into() 512 self.is_high().into()
473 } 513 }
474 514
515 /// Wait until the pin is high. If it is already high, return immediately.
475 #[inline] 516 #[inline]
476 pub async fn wait_for_high(&mut self) { 517 pub async fn wait_for_high(&mut self) {
477 self.pin.wait_for_high().await; 518 self.pin.wait_for_high().await;
478 } 519 }
479 520
521 /// Wait until the pin is low. If it is already low, return immediately.
480 #[inline] 522 #[inline]
481 pub async fn wait_for_low(&mut self) { 523 pub async fn wait_for_low(&mut self) {
482 self.pin.wait_for_low().await; 524 self.pin.wait_for_low().await;
483 } 525 }
484 526
527 /// Wait for the pin to undergo a transition from low to high.
485 #[inline] 528 #[inline]
486 pub async fn wait_for_rising_edge(&mut self) { 529 pub async fn wait_for_rising_edge(&mut self) {
487 self.pin.wait_for_rising_edge().await; 530 self.pin.wait_for_rising_edge().await;
488 } 531 }
489 532
533 /// Wait for the pin to undergo a transition from high to low.
490 #[inline] 534 #[inline]
491 pub async fn wait_for_falling_edge(&mut self) { 535 pub async fn wait_for_falling_edge(&mut self) {
492 self.pin.wait_for_falling_edge().await; 536 self.pin.wait_for_falling_edge().await;
493 } 537 }
494 538
539 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
495 #[inline] 540 #[inline]
496 pub async fn wait_for_any_edge(&mut self) { 541 pub async fn wait_for_any_edge(&mut self) {
497 self.pin.wait_for_any_edge().await; 542 self.pin.wait_for_any_edge().await;
@@ -508,6 +553,10 @@ pub struct Flex<'d, T: Pin> {
508} 553}
509 554
510impl<'d, T: Pin> Flex<'d, T> { 555impl<'d, T: Pin> Flex<'d, T> {
556 /// Wrap the pin in a `Flex`.
557 ///
558 /// The pin remains disconnected. The initial output level is unspecified, but can be changed
559 /// before the pin is put into output mode.
511 #[inline] 560 #[inline]
512 pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self { 561 pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self {
513 into_ref!(pin); 562 into_ref!(pin);
@@ -556,7 +605,7 @@ impl<'d, T: Pin> Flex<'d, T> {
556 }); 605 });
557 } 606 }
558 607
559 // Set the pin's slew rate. 608 /// Set the pin's slew rate.
560 #[inline] 609 #[inline]
561 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { 610 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
562 self.pin.pad_ctrl().modify(|w| { 611 self.pin.pad_ctrl().modify(|w| {
@@ -589,6 +638,7 @@ impl<'d, T: Pin> Flex<'d, T> {
589 self.pin.sio_oe().value_set().write_value(self.bit()) 638 self.pin.sio_oe().value_set().write_value(self.bit())
590 } 639 }
591 640
641 /// Set as output pin.
592 #[inline] 642 #[inline]
593 pub fn is_set_as_output(&mut self) -> bool { 643 pub fn is_set_as_output(&mut self) -> bool {
594 self.ref_is_set_as_output() 644 self.ref_is_set_as_output()
@@ -599,15 +649,18 @@ impl<'d, T: Pin> Flex<'d, T> {
599 (self.pin.sio_oe().value().read() & self.bit()) != 0 649 (self.pin.sio_oe().value().read() & self.bit()) != 0
600 } 650 }
601 651
652 /// Toggle output pin.
602 #[inline] 653 #[inline]
603 pub fn toggle_set_as_output(&mut self) { 654 pub fn toggle_set_as_output(&mut self) {
604 self.pin.sio_oe().value_xor().write_value(self.bit()) 655 self.pin.sio_oe().value_xor().write_value(self.bit())
605 } 656 }
606 657
658 /// Get whether the pin input level is high.
607 #[inline] 659 #[inline]
608 pub fn is_high(&mut self) -> bool { 660 pub fn is_high(&mut self) -> bool {
609 !self.is_low() 661 !self.is_low()
610 } 662 }
663 /// Get whether the pin input level is low.
611 664
612 #[inline] 665 #[inline]
613 pub fn is_low(&mut self) -> bool { 666 pub fn is_low(&mut self) -> bool {
@@ -675,31 +728,37 @@ impl<'d, T: Pin> Flex<'d, T> {
675 self.pin.sio_out().value_xor().write_value(self.bit()) 728 self.pin.sio_out().value_xor().write_value(self.bit())
676 } 729 }
677 730
731 /// Wait until the pin is high. If it is already high, return immediately.
678 #[inline] 732 #[inline]
679 pub async fn wait_for_high(&mut self) { 733 pub async fn wait_for_high(&mut self) {
680 InputFuture::new(&mut self.pin, InterruptTrigger::LevelHigh).await; 734 InputFuture::new(&mut self.pin, InterruptTrigger::LevelHigh).await;
681 } 735 }
682 736
737 /// Wait until the pin is low. If it is already low, return immediately.
683 #[inline] 738 #[inline]
684 pub async fn wait_for_low(&mut self) { 739 pub async fn wait_for_low(&mut self) {
685 InputFuture::new(&mut self.pin, InterruptTrigger::LevelLow).await; 740 InputFuture::new(&mut self.pin, InterruptTrigger::LevelLow).await;
686 } 741 }
687 742
743 /// Wait for the pin to undergo a transition from low to high.
688 #[inline] 744 #[inline]
689 pub async fn wait_for_rising_edge(&mut self) { 745 pub async fn wait_for_rising_edge(&mut self) {
690 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await; 746 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await;
691 } 747 }
692 748
749 /// Wait for the pin to undergo a transition from high to low.
693 #[inline] 750 #[inline]
694 pub async fn wait_for_falling_edge(&mut self) { 751 pub async fn wait_for_falling_edge(&mut self) {
695 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeLow).await; 752 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeLow).await;
696 } 753 }
697 754
755 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
698 #[inline] 756 #[inline]
699 pub async fn wait_for_any_edge(&mut self) { 757 pub async fn wait_for_any_edge(&mut self) {
700 InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await; 758 InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await;
701 } 759 }
702 760
761 /// Configure dormant wake.
703 #[inline] 762 #[inline]
704 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> { 763 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
705 let idx = self.pin._pin() as usize; 764 let idx = self.pin._pin() as usize;
@@ -737,6 +796,7 @@ impl<'d, T: Pin> Drop for Flex<'d, T> {
737 } 796 }
738} 797}
739 798
799/// Dormant wake driver.
740pub struct DormantWake<'w, T: Pin> { 800pub struct DormantWake<'w, T: Pin> {
741 pin: PeripheralRef<'w, T>, 801 pin: PeripheralRef<'w, T>,
742 cfg: DormantWakeConfig, 802 cfg: DormantWakeConfig,
@@ -818,6 +878,7 @@ pub(crate) mod sealed {
818 } 878 }
819} 879}
820 880
881/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an [AnyPin].
821pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { 882pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static {
822 /// Degrade to a generic pin struct 883 /// Degrade to a generic pin struct
823 fn degrade(self) -> AnyPin { 884 fn degrade(self) -> AnyPin {
@@ -839,6 +900,7 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
839 } 900 }
840} 901}
841 902
903/// Type-erased GPIO pin
842pub struct AnyPin { 904pub struct AnyPin {
843 pin_bank: u8, 905 pin_bank: u8,
844} 906}
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs
index 15095236a..74d015792 100644
--- a/embassy-rp/src/i2c.rs
+++ b/embassy-rp/src/i2c.rs
@@ -1,3 +1,4 @@
1//! I2C driver.
1use core::future; 2use core::future;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::task::Poll; 4use core::task::Poll;
@@ -22,6 +23,7 @@ pub enum AbortReason {
22 ArbitrationLoss, 23 ArbitrationLoss,
23 /// Transmit ended with data still in fifo 24 /// Transmit ended with data still in fifo
24 TxNotEmpty(u16), 25 TxNotEmpty(u16),
26 /// Other reason.
25 Other(u32), 27 Other(u32),
26} 28}
27 29
@@ -41,9 +43,11 @@ pub enum Error {
41 AddressReserved(u16), 43 AddressReserved(u16),
42} 44}
43 45
46/// I2C config.
44#[non_exhaustive] 47#[non_exhaustive]
45#[derive(Copy, Clone)] 48#[derive(Copy, Clone)]
46pub struct Config { 49pub struct Config {
50 /// Frequency.
47 pub frequency: u32, 51 pub frequency: u32,
48} 52}
49 53
@@ -53,13 +57,16 @@ impl Default for Config {
53 } 57 }
54} 58}
55 59
60/// Size of I2C FIFO.
56pub const FIFO_SIZE: u8 = 16; 61pub const FIFO_SIZE: u8 = 16;
57 62
63/// I2C driver.
58pub struct I2c<'d, T: Instance, M: Mode> { 64pub struct I2c<'d, T: Instance, M: Mode> {
59 phantom: PhantomData<(&'d mut T, M)>, 65 phantom: PhantomData<(&'d mut T, M)>,
60} 66}
61 67
62impl<'d, T: Instance> I2c<'d, T, Blocking> { 68impl<'d, T: Instance> I2c<'d, T, Blocking> {
69 /// Create a new driver instance in blocking mode.
63 pub fn new_blocking( 70 pub fn new_blocking(
64 peri: impl Peripheral<P = T> + 'd, 71 peri: impl Peripheral<P = T> + 'd,
65 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 72 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
@@ -72,6 +79,7 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> {
72} 79}
73 80
74impl<'d, T: Instance> I2c<'d, T, Async> { 81impl<'d, T: Instance> I2c<'d, T, Async> {
82 /// Create a new driver instance in async mode.
75 pub fn new_async( 83 pub fn new_async(
76 peri: impl Peripheral<P = T> + 'd, 84 peri: impl Peripheral<P = T> + 'd,
77 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 85 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
@@ -292,16 +300,19 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
292 } 300 }
293 } 301 }
294 302
303 /// Read from address into buffer using DMA.
295 pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> { 304 pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> {
296 Self::setup(addr)?; 305 Self::setup(addr)?;
297 self.read_async_internal(buffer, true, true).await 306 self.read_async_internal(buffer, true, true).await
298 } 307 }
299 308
309 /// Write to address from buffer using DMA.
300 pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> { 310 pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> {
301 Self::setup(addr)?; 311 Self::setup(addr)?;
302 self.write_async_internal(bytes, true).await 312 self.write_async_internal(bytes, true).await
303 } 313 }
304 314
315 /// Write to address from bytes and read from address into buffer using DMA.
305 pub async fn write_read_async( 316 pub async fn write_read_async(
306 &mut self, 317 &mut self,
307 addr: u16, 318 addr: u16,
@@ -314,6 +325,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
314 } 325 }
315} 326}
316 327
328/// Interrupt handler.
317pub struct InterruptHandler<T: Instance> { 329pub struct InterruptHandler<T: Instance> {
318 _uart: PhantomData<T>, 330 _uart: PhantomData<T>,
319} 331}
@@ -569,17 +581,20 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
569 // Blocking public API 581 // Blocking public API
570 // ========================= 582 // =========================
571 583
584 /// Read from address into buffer blocking caller until done.
572 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { 585 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
573 Self::setup(address.into())?; 586 Self::setup(address.into())?;
574 self.read_blocking_internal(read, true, true) 587 self.read_blocking_internal(read, true, true)
575 // Automatic Stop 588 // Automatic Stop
576 } 589 }
577 590
591 /// Write to address from buffer blocking caller until done.
578 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 592 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
579 Self::setup(address.into())?; 593 Self::setup(address.into())?;
580 self.write_blocking_internal(write, true) 594 self.write_blocking_internal(write, true)
581 } 595 }
582 596
597 /// Write to address from bytes and read from address into buffer blocking caller until done.
583 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 598 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
584 Self::setup(address.into())?; 599 Self::setup(address.into())?;
585 self.write_blocking_internal(write, false)?; 600 self.write_blocking_internal(write, false)?;
@@ -742,6 +757,7 @@ where
742 } 757 }
743} 758}
744 759
760/// Check if address is reserved.
745pub fn i2c_reserved_addr(addr: u16) -> bool { 761pub fn i2c_reserved_addr(addr: u16) -> bool {
746 ((addr & 0x78) == 0 || (addr & 0x78) == 0x78) && addr != 0 762 ((addr & 0x78) == 0 || (addr & 0x78) == 0x78) && addr != 0
747} 763}
@@ -768,6 +784,7 @@ mod sealed {
768 pub trait SclPin<T: Instance> {} 784 pub trait SclPin<T: Instance> {}
769} 785}
770 786
787/// Driver mode.
771pub trait Mode: sealed::Mode {} 788pub trait Mode: sealed::Mode {}
772 789
773macro_rules! impl_mode { 790macro_rules! impl_mode {
@@ -777,12 +794,15 @@ macro_rules! impl_mode {
777 }; 794 };
778} 795}
779 796
797/// Blocking mode.
780pub struct Blocking; 798pub struct Blocking;
799/// Async mode.
781pub struct Async; 800pub struct Async;
782 801
783impl_mode!(Blocking); 802impl_mode!(Blocking);
784impl_mode!(Async); 803impl_mode!(Async);
785 804
805/// I2C instance.
786pub trait Instance: sealed::Instance {} 806pub trait Instance: sealed::Instance {}
787 807
788macro_rules! impl_instance { 808macro_rules! impl_instance {
@@ -819,7 +839,9 @@ macro_rules! impl_instance {
819impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33); 839impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33);
820impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35); 840impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35);
821 841
842/// SDA pin.
822pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {} 843pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {}
844/// SCL pin.
823pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {} 845pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {}
824 846
825macro_rules! impl_pin { 847macro_rules! impl_pin {
diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs
index 9271ede3a..721b7a1f6 100644
--- a/embassy-rp/src/i2c_slave.rs
+++ b/embassy-rp/src/i2c_slave.rs
@@ -1,3 +1,4 @@
1//! I2C slave driver.
1use core::future; 2use core::future;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::task::Poll; 4use core::task::Poll;
@@ -63,11 +64,13 @@ impl Default for Config {
63 } 64 }
64} 65}
65 66
67/// I2CSlave driver.
66pub struct I2cSlave<'d, T: Instance> { 68pub struct I2cSlave<'d, T: Instance> {
67 phantom: PhantomData<&'d mut T>, 69 phantom: PhantomData<&'d mut T>,
68} 70}
69 71
70impl<'d, T: Instance> I2cSlave<'d, T> { 72impl<'d, T: Instance> I2cSlave<'d, T> {
73 /// Create a new instance.
71 pub fn new( 74 pub fn new(
72 _peri: impl Peripheral<P = T> + 'd, 75 _peri: impl Peripheral<P = T> + 'd,
73 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 76 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index 2c49787df..004b94589 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -1,6 +1,7 @@
1#![no_std] 1#![no_std]
2#![allow(async_fn_in_trait)] 2#![allow(async_fn_in_trait)]
3#![doc = include_str!("../README.md")] 3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
4 5
5// This mod MUST go first, so that the others see its macros. 6// This mod MUST go first, so that the others see its macros.
6pub(crate) mod fmt; 7pub(crate) mod fmt;
diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs
index ae91d1e83..ca9795024 100644
--- a/embassy-rp/src/pio/mod.rs
+++ b/embassy-rp/src/pio/mod.rs
@@ -1,3 +1,4 @@
1//! PIO driver.
1use core::future::Future; 2use core::future::Future;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::pin::Pin as FuturePin; 4use core::pin::Pin as FuturePin;
diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs
index 5b96557a3..784a05f92 100644
--- a/embassy-rp/src/pwm.rs
+++ b/embassy-rp/src/pwm.rs
@@ -119,11 +119,13 @@ impl<'d, T: Channel> Pwm<'d, T> {
119 } 119 }
120 } 120 }
121 121
122 /// Create PWM driver without any configured pins.
122 #[inline] 123 #[inline]
123 pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self { 124 pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self {
124 Self::new_inner(inner, None, None, config, Divmode::DIV) 125 Self::new_inner(inner, None, None, config, Divmode::DIV)
125 } 126 }
126 127
128 /// Create PWM driver with a single 'a' as output.
127 #[inline] 129 #[inline]
128 pub fn new_output_a( 130 pub fn new_output_a(
129 inner: impl Peripheral<P = T> + 'd, 131 inner: impl Peripheral<P = T> + 'd,
@@ -134,6 +136,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
134 Self::new_inner(inner, Some(a.map_into()), None, config, Divmode::DIV) 136 Self::new_inner(inner, Some(a.map_into()), None, config, Divmode::DIV)
135 } 137 }
136 138
139 /// Create PWM driver with a single 'b' pin as output.
137 #[inline] 140 #[inline]
138 pub fn new_output_b( 141 pub fn new_output_b(
139 inner: impl Peripheral<P = T> + 'd, 142 inner: impl Peripheral<P = T> + 'd,
@@ -144,6 +147,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
144 Self::new_inner(inner, None, Some(b.map_into()), config, Divmode::DIV) 147 Self::new_inner(inner, None, Some(b.map_into()), config, Divmode::DIV)
145 } 148 }
146 149
150 /// Create PWM driver with a 'a' and 'b' pins as output.
147 #[inline] 151 #[inline]
148 pub fn new_output_ab( 152 pub fn new_output_ab(
149 inner: impl Peripheral<P = T> + 'd, 153 inner: impl Peripheral<P = T> + 'd,
@@ -155,6 +159,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
155 Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, Divmode::DIV) 159 Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, Divmode::DIV)
156 } 160 }
157 161
162 /// Create PWM driver with a single 'b' as input pin.
158 #[inline] 163 #[inline]
159 pub fn new_input( 164 pub fn new_input(
160 inner: impl Peripheral<P = T> + 'd, 165 inner: impl Peripheral<P = T> + 'd,
@@ -166,6 +171,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
166 Self::new_inner(inner, None, Some(b.map_into()), config, mode.into()) 171 Self::new_inner(inner, None, Some(b.map_into()), config, mode.into())
167 } 172 }
168 173
174 /// Create PWM driver with a 'a' and 'b' pins in the desired input mode.
169 #[inline] 175 #[inline]
170 pub fn new_output_input( 176 pub fn new_output_input(
171 inner: impl Peripheral<P = T> + 'd, 177 inner: impl Peripheral<P = T> + 'd,
@@ -178,6 +184,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
178 Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, mode.into()) 184 Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, mode.into())
179 } 185 }
180 186
187 /// Set the PWM config.
181 pub fn set_config(&mut self, config: &Config) { 188 pub fn set_config(&mut self, config: &Config) {
182 Self::configure(self.inner.regs(), config); 189 Self::configure(self.inner.regs(), config);
183 } 190 }
@@ -221,28 +228,33 @@ impl<'d, T: Channel> Pwm<'d, T> {
221 while p.csr().read().ph_ret() {} 228 while p.csr().read().ph_ret() {}
222 } 229 }
223 230
231 /// Read PWM counter.
224 #[inline] 232 #[inline]
225 pub fn counter(&self) -> u16 { 233 pub fn counter(&self) -> u16 {
226 self.inner.regs().ctr().read().ctr() 234 self.inner.regs().ctr().read().ctr()
227 } 235 }
228 236
237 /// Write PWM counter.
229 #[inline] 238 #[inline]
230 pub fn set_counter(&self, ctr: u16) { 239 pub fn set_counter(&self, ctr: u16) {
231 self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) 240 self.inner.regs().ctr().write(|w| w.set_ctr(ctr))
232 } 241 }
233 242
243 /// Wait for channel interrupt.
234 #[inline] 244 #[inline]
235 pub fn wait_for_wrap(&mut self) { 245 pub fn wait_for_wrap(&mut self) {
236 while !self.wrapped() {} 246 while !self.wrapped() {}
237 self.clear_wrapped(); 247 self.clear_wrapped();
238 } 248 }
239 249
250 /// Check if interrupt for channel is set.
240 #[inline] 251 #[inline]
241 pub fn wrapped(&mut self) -> bool { 252 pub fn wrapped(&mut self) -> bool {
242 pac::PWM.intr().read().0 & self.bit() != 0 253 pac::PWM.intr().read().0 & self.bit() != 0
243 } 254 }
244 255
245 #[inline] 256 #[inline]
257 /// Clear interrupt flag.
246 pub fn clear_wrapped(&mut self) { 258 pub fn clear_wrapped(&mut self) {
247 pac::PWM.intr().write_value(Intr(self.bit() as _)); 259 pac::PWM.intr().write_value(Intr(self.bit() as _));
248 } 260 }
@@ -253,15 +265,18 @@ impl<'d, T: Channel> Pwm<'d, T> {
253 } 265 }
254} 266}
255 267
268/// Batch representation of PWM channels.
256pub struct PwmBatch(u32); 269pub struct PwmBatch(u32);
257 270
258impl PwmBatch { 271impl PwmBatch {
259 #[inline] 272 #[inline]
273 /// Enable a PWM channel in this batch.
260 pub fn enable(&mut self, pwm: &Pwm<'_, impl Channel>) { 274 pub fn enable(&mut self, pwm: &Pwm<'_, impl Channel>) {
261 self.0 |= pwm.bit(); 275 self.0 |= pwm.bit();
262 } 276 }
263 277
264 #[inline] 278 #[inline]
279 /// Enable channels in this batch in a PWM.
265 pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) { 280 pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) {
266 let mut en = PwmBatch(0); 281 let mut en = PwmBatch(0);
267 batch(&mut en); 282 batch(&mut en);
@@ -289,9 +304,12 @@ mod sealed {
289 pub trait Channel {} 304 pub trait Channel {}
290} 305}
291 306
307/// PWM Channel.
292pub trait Channel: Peripheral<P = Self> + sealed::Channel + Sized + 'static { 308pub trait Channel: Peripheral<P = Self> + sealed::Channel + Sized + 'static {
309 /// Channel number.
293 fn number(&self) -> u8; 310 fn number(&self) -> u8;
294 311
312 /// Channel register block.
295 fn regs(&self) -> pac::pwm::Channel { 313 fn regs(&self) -> pac::pwm::Channel {
296 pac::PWM.ch(self.number() as _) 314 pac::PWM.ch(self.number() as _)
297 } 315 }
@@ -317,7 +335,9 @@ channel!(PWM_CH5, 5);
317channel!(PWM_CH6, 6); 335channel!(PWM_CH6, 6);
318channel!(PWM_CH7, 7); 336channel!(PWM_CH7, 7);
319 337
338/// PWM Pin A.
320pub trait PwmPinA<T: Channel>: GpioPin {} 339pub trait PwmPinA<T: Channel>: GpioPin {}
340/// PWM Pin B.
321pub trait PwmPinB<T: Channel>: GpioPin {} 341pub trait PwmPinB<T: Channel>: GpioPin {}
322 342
323macro_rules! impl_pin { 343macro_rules! impl_pin {
diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs
index c3df3ee57..b696989f5 100644
--- a/embassy-rp/src/rtc/mod.rs
+++ b/embassy-rp/src/rtc/mod.rs
@@ -1,3 +1,4 @@
1//! RTC driver.
1mod filter; 2mod filter;
2 3
3use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 4use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs
index faa8df037..69c0c85b1 100644
--- a/embassy-rp/src/timer.rs
+++ b/embassy-rp/src/timer.rs
@@ -1,3 +1,4 @@
1//! Timer driver.
1use core::cell::Cell; 2use core::cell::Cell;
2 3
3use atomic_polyfill::{AtomicU8, Ordering}; 4use atomic_polyfill::{AtomicU8, Ordering};
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index f14e08525..99c958129 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -1,3 +1,4 @@
1//! Buffered UART driver.
1use core::future::{poll_fn, Future}; 2use core::future::{poll_fn, Future};
2use core::slice; 3use core::slice;
3use core::task::Poll; 4use core::task::Poll;
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index 32be7661d..99fce0fc9 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -1,3 +1,4 @@
1//! UART driver.
1use core::future::poll_fn; 2use core::future::poll_fn;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::task::Poll; 4use core::task::Poll;
@@ -947,7 +948,7 @@ pub struct Async;
947impl_mode!(Blocking); 948impl_mode!(Blocking);
948impl_mode!(Async); 949impl_mode!(Async);
949 950
950/// UART instance trait. 951/// UART instance.
951pub trait Instance: sealed::Instance {} 952pub trait Instance: sealed::Instance {}
952 953
953macro_rules! impl_instance { 954macro_rules! impl_instance {
diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs
index bcd848222..905661d64 100644
--- a/embassy-rp/src/usb.rs
+++ b/embassy-rp/src/usb.rs
@@ -1,3 +1,4 @@
1//! USB driver.
1use core::future::poll_fn; 2use core::future::poll_fn;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::slice; 4use core::slice;