diff options
| author | Ulf Lilleengen <[email protected]> | 2023-12-19 13:52:21 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-12-19 13:52:21 +0000 |
| commit | 5e76c8b41a05c89652a6c53061107482adc4125f (patch) | |
| tree | 102bbf8a892b830959fd87529c4e86f7f65c379d | |
| parent | ca2e3759ad31f511c239d30132a28714b0e402db (diff) | |
| parent | f4b77c967fec9edacc6818aa8d935fda60bc743f (diff) | |
Merge pull request #2317 from embassy-rs/embassy-rp-rustdoc-2
docs: document all embassy-rp public apis
| -rw-r--r-- | embassy-rp/src/adc.rs | 24 | ||||
| -rw-r--r-- | embassy-rp/src/clocks.rs | 97 | ||||
| -rw-r--r-- | embassy-rp/src/dma.rs | 20 | ||||
| -rw-r--r-- | embassy-rp/src/flash.rs | 42 | ||||
| -rw-r--r-- | embassy-rp/src/gpio.rs | 68 | ||||
| -rw-r--r-- | embassy-rp/src/i2c.rs | 22 | ||||
| -rw-r--r-- | embassy-rp/src/i2c_slave.rs | 3 | ||||
| -rw-r--r-- | embassy-rp/src/lib.rs | 1 | ||||
| -rw-r--r-- | embassy-rp/src/pio/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-rp/src/pwm.rs | 20 | ||||
| -rw-r--r-- | embassy-rp/src/rtc/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-rp/src/timer.rs | 1 | ||||
| -rw-r--r-- | embassy-rp/src/uart/buffered.rs | 1 | ||||
| -rw-r--r-- | embassy-rp/src/uart/mod.rs | 3 | ||||
| -rw-r--r-- | embassy-rp/src/usb.rs | 1 |
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. | ||
| 1 | use core::future::poll_fn; | 2 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use core::mem; | 4 | use core::mem; |
| @@ -16,6 +17,7 @@ use crate::{dma, interrupt, pac, peripherals, Peripheral, RegExt}; | |||
| 16 | 17 | ||
| 17 | static WAKER: AtomicWaker = AtomicWaker::new(); | 18 | static WAKER: AtomicWaker = AtomicWaker::new(); |
| 18 | 19 | ||
| 20 | /// ADC config. | ||
| 19 | #[non_exhaustive] | 21 | #[non_exhaustive] |
| 20 | pub struct Config {} | 22 | pub 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. | ||
| 33 | pub struct Channel<'p>(Source<'p>); | 36 | pub struct Channel<'p>(Source<'p>); |
| 34 | 37 | ||
| 35 | impl<'p> Channel<'p> { | 38 | impl<'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)] |
| 89 | pub struct Sample(u16); | 95 | pub struct Sample(u16); |
| 90 | 96 | ||
| 91 | impl Sample { | 97 | impl 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))] |
| 103 | pub enum Error { | 112 | pub enum Error { |
| 113 | /// Error converting value. | ||
| 104 | ConversionFailed, | 114 | ConversionFailed, |
| 105 | } | 115 | } |
| 106 | 116 | ||
| 117 | /// ADC mode. | ||
| 107 | pub trait Mode {} | 118 | pub trait Mode {} |
| 108 | 119 | ||
| 120 | /// ADC async mode. | ||
| 109 | pub struct Async; | 121 | pub struct Async; |
| 110 | impl Mode for Async {} | 122 | impl Mode for Async {} |
| 111 | 123 | ||
| 124 | /// ADC blocking mode. | ||
| 112 | pub struct Blocking; | 125 | pub struct Blocking; |
| 113 | impl Mode for Blocking {} | 126 | impl Mode for Blocking {} |
| 114 | 127 | ||
| 128 | /// ADC driver. | ||
| 115 | pub struct Adc<'d, M: Mode> { | 129 | pub 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 | ||
| 168 | impl<'d> Adc<'d, Async> { | 183 | impl<'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 | ||
| 301 | impl<'d> Adc<'d, Blocking> { | 320 | impl<'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. | ||
| 309 | pub struct InterruptHandler { | 330 | pub 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. | ||
| 327 | pub trait AdcSample: sealed::AdcSample {} | 349 | pub trait AdcSample: sealed::AdcSample {} |
| 328 | 350 | ||
| 329 | impl sealed::AdcSample for u16 {} | 351 | impl sealed::AdcSample for u16 {} |
| @@ -332,7 +354,9 @@ impl AdcSample for u16 {} | |||
| 332 | impl sealed::AdcSample for u8 {} | 354 | impl sealed::AdcSample for u8 {} |
| 333 | impl AdcSample for u8 {} | 355 | impl AdcSample for u8 {} |
| 334 | 356 | ||
| 357 | /// ADC channel. | ||
| 335 | pub trait AdcChannel: sealed::AdcChannel {} | 358 | pub trait AdcChannel: sealed::AdcChannel {} |
| 359 | /// ADC pin. | ||
| 336 | pub trait AdcPin: AdcChannel + gpio::Pin {} | 360 | pub trait AdcPin: AdcChannel + gpio::Pin {} |
| 337 | 361 | ||
| 338 | macro_rules! impl_pin { | 362 | macro_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)] |
| 52 | pub enum PeriClkSrc { | 52 | pub 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 | ||
| 85 | impl ClockConfig { | 90 | impl 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)] |
| 196 | pub enum RoscRange { | 204 | pub 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. |
| 243 | pub struct RefClkConfig { | 255 | pub 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)] |
| 250 | pub enum RefClkSrc { | 265 | pub 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)] |
| 262 | pub enum SysClkSrc { | 279 | pub 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. | ||
| 274 | pub struct SysClkConfig { | 295 | pub 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)] |
| 283 | pub enum UsbClkSrc { | 308 | pub 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. | ||
| 292 | pub struct UsbClkConfig { | 322 | pub 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)] |
| 301 | pub enum AdcClkSrc { | 335 | pub 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. | ||
| 310 | pub struct AdcClkConfig { | 349 | pub 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)] |
| 319 | pub enum RtcClkSrc { | 362 | pub 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. | ||
| 328 | pub struct RtcClkConfig { | 376 | pub 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. | ||
| 608 | pub fn rosc_freq() -> u32 { | 661 | pub fn rosc_freq() -> u32 { |
| 609 | CLOCKS.rosc.load(Ordering::Relaxed) | 662 | CLOCKS.rosc.load(Ordering::Relaxed) |
| 610 | } | 663 | } |
| 611 | 664 | ||
| 665 | /// XOSC clock frequency. | ||
| 612 | pub fn xosc_freq() -> u32 { | 666 | pub 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. | ||
| 623 | pub fn pll_sys_freq() -> u32 { | 678 | pub 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. | ||
| 627 | pub fn pll_usb_freq() -> u32 { | 683 | pub 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. | ||
| 631 | pub fn clk_sys_freq() -> u32 { | 688 | pub 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. | ||
| 635 | pub fn clk_ref_freq() -> u32 { | 693 | pub 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. | ||
| 639 | pub fn clk_peri_freq() -> u32 { | 698 | pub 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. | ||
| 643 | pub fn clk_usb_freq() -> u32 { | 703 | pub 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. | ||
| 647 | pub fn clk_adc_freq() -> u32 { | 708 | pub 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. | ||
| 651 | pub fn clk_rtc_freq() -> u16 { | 713 | pub 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. | ||
| 711 | pub trait GpinPin: crate::gpio::Pin { | 774 | pub 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 { | |||
| 723 | impl_gpinpin!(PIN_20, 20, 0); | 787 | impl_gpinpin!(PIN_20, 20, 0); |
| 724 | impl_gpinpin!(PIN_22, 22, 1); | 788 | impl_gpinpin!(PIN_22, 22, 1); |
| 725 | 789 | ||
| 790 | /// General purpose clock input driver. | ||
| 726 | pub struct Gpin<'d, T: Pin> { | 791 | pub 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 | ||
| 731 | impl<'d, T: Pin> Gpin<'d, T> { | 796 | impl<'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. | ||
| 757 | pub trait GpoutPin: crate::gpio::Pin { | 824 | pub 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); | |||
| 773 | impl_gpoutpin!(PIN_24, 2); | 841 | impl_gpoutpin!(PIN_24, 2); |
| 774 | impl_gpoutpin!(PIN_25, 3); | 842 | impl_gpoutpin!(PIN_25, 3); |
| 775 | 843 | ||
| 844 | /// Gpout clock source. | ||
| 776 | #[repr(u8)] | 845 | #[repr(u8)] |
| 777 | pub enum GpoutSrc { | 846 | pub 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. | ||
| 791 | pub struct Gpout<'d, T: GpoutPin> { | 870 | pub struct Gpout<'d, T: GpoutPin> { |
| 792 | gpout: PeripheralRef<'d, T>, | 871 | gpout: PeripheralRef<'d, T>, |
| 793 | } | 872 | } |
| 794 | 873 | ||
| 795 | impl<'d, T: GpoutPin> Gpout<'d, T> { | 874 | impl<'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. | ||
| 41 | pub unsafe fn read<'a, C: Channel, W: Word>( | 44 | pub 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. | ||
| 60 | pub unsafe fn write<'a, C: Channel, W: Word>( | 66 | pub 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. |
| 80 | static mut DUMMY: u32 = 0; | 86 | static mut DUMMY: u32 = 0; |
| 81 | 87 | ||
| 88 | /// DMA repeated write. | ||
| 89 | /// | ||
| 90 | /// SAFETY: Slice must point to a valid location reachable by DMA. | ||
| 82 | pub unsafe fn write_repeated<'a, C: Channel, W: Word>( | 91 | pub 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. | ||
| 100 | pub unsafe fn copy<'a, C: Channel, W: Word>( | 112 | pub 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"] |
| 156 | pub struct Transfer<'a, C: Channel> { | 169 | pub 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. | ||
| 204 | pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static { | 218 | pub 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. | ||
| 216 | pub trait Word: sealed::Word { | 234 | pub 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. | ||
| 241 | pub struct AnyChannel { | 261 | pub 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. | ||
| 1 | use core::future::Future; | 2 | use core::future::Future; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use core::pin::Pin; | 4 | use core::pin::Pin; |
| @@ -13,9 +14,10 @@ use crate::dma::{AnyChannel, Channel, Transfer}; | |||
| 13 | use crate::pac; | 14 | use crate::pac; |
| 14 | use crate::peripherals::FLASH; | 15 | use crate::peripherals::FLASH; |
| 15 | 16 | ||
| 17 | /// Flash base address. | ||
| 16 | pub const FLASH_BASE: *const u32 = 0x10000000 as _; | 18 | pub 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. |
| 20 | pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram"); | 22 | pub 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. | ||
| 27 | pub const PAGE_SIZE: usize = 256; | 30 | pub const PAGE_SIZE: usize = 256; |
| 31 | /// Flash write size. | ||
| 28 | pub const WRITE_SIZE: usize = 1; | 32 | pub const WRITE_SIZE: usize = 1; |
| 33 | /// Flash read size. | ||
| 29 | pub const READ_SIZE: usize = 1; | 34 | pub const READ_SIZE: usize = 1; |
| 35 | /// Flash erase size. | ||
| 30 | pub const ERASE_SIZE: usize = 4096; | 36 | pub const ERASE_SIZE: usize = 4096; |
| 37 | /// Flash DMA read size. | ||
| 31 | pub const ASYNC_READ_SIZE: usize = 4; | 38 | pub 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. | ||
| 99 | pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> { | 109 | pub 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 | ||
| 104 | impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> { | 114 | impl<'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 | ||
| 221 | impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> { | 245 | impl<'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 | ||
| 230 | impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> { | 255 | impl<'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. | ||
| 877 | pub trait Instance: sealed::Instance {} | 914 | pub trait Instance: sealed::Instance {} |
| 915 | /// Flash mode. | ||
| 878 | pub trait Mode: sealed::Mode {} | 916 | pub trait Mode: sealed::Mode {} |
| 879 | 917 | ||
| 880 | impl sealed::Instance for FLASH {} | 918 | impl sealed::Instance for FLASH {} |
| @@ -887,7 +925,9 @@ macro_rules! impl_mode { | |||
| 887 | }; | 925 | }; |
| 888 | } | 926 | } |
| 889 | 927 | ||
| 928 | /// Flash blocking mode. | ||
| 890 | pub struct Blocking; | 929 | pub struct Blocking; |
| 930 | /// Flash async mode. | ||
| 891 | pub struct Async; | 931 | pub struct Async; |
| 892 | 932 | ||
| 893 | impl_mode!(Blocking); | 933 | impl_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] |
| 2 | use core::convert::Infallible; | 3 | use core::convert::Infallible; |
| 3 | use core::future::Future; | 4 | use 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)] |
| 25 | pub enum Level { | 26 | pub 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)] |
| 50 | pub enum Pull { | 53 | pub 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)] |
| 58 | pub enum Drive { | 64 | pub 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)] |
| 66 | pub enum SlewRate { | 76 | pub 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)] |
| 73 | pub enum Bank { | 85 | pub 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))] |
| 81 | pub struct DormantWakeConfig { | 96 | pub 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. | ||
| 88 | pub struct Input<'d, T: Pin> { | 108 | pub struct Input<'d, T: Pin> { |
| 89 | pin: Flex<'d, T>, | 109 | pin: Flex<'d, T>, |
| 90 | } | 110 | } |
| 91 | 111 | ||
| 92 | impl<'d, T: Pin> Input<'d, T> { | 112 | impl<'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))] |
| 157 | pub enum InterruptTrigger { | 186 | pub 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 | ||
| 228 | impl<'d, T: Pin> InputFuture<'d, T> { | 262 | impl<'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. | ||
| 311 | pub struct Output<'d, T: Pin> { | 347 | pub struct Output<'d, T: Pin> { |
| 312 | pin: Flex<'d, T>, | 348 | pin: Flex<'d, T>, |
| 313 | } | 349 | } |
| 314 | 350 | ||
| 315 | impl<'d, T: Pin> Output<'d, T> { | 351 | impl<'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 | ||
| 388 | impl<'d, T: Pin> OutputOpenDrain<'d, T> { | 425 | impl<'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 | ||
| 510 | impl<'d, T: Pin> Flex<'d, T> { | 555 | impl<'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. | ||
| 740 | pub struct DormantWake<'w, T: Pin> { | 800 | pub 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]. | ||
| 821 | pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { | 882 | pub 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 | ||
| 842 | pub struct AnyPin { | 904 | pub 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. | ||
| 1 | use core::future; | 2 | use core::future; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use core::task::Poll; | 4 | use 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)] |
| 46 | pub struct Config { | 49 | pub 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. | ||
| 56 | pub const FIFO_SIZE: u8 = 16; | 61 | pub const FIFO_SIZE: u8 = 16; |
| 57 | 62 | ||
| 63 | /// I2C driver. | ||
| 58 | pub struct I2c<'d, T: Instance, M: Mode> { | 64 | pub 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 | ||
| 62 | impl<'d, T: Instance> I2c<'d, T, Blocking> { | 68 | impl<'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 | ||
| 74 | impl<'d, T: Instance> I2c<'d, T, Async> { | 81 | impl<'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. | ||
| 317 | pub struct InterruptHandler<T: Instance> { | 329 | pub 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. | ||
| 745 | pub fn i2c_reserved_addr(addr: u16) -> bool { | 761 | pub 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. | ||
| 771 | pub trait Mode: sealed::Mode {} | 788 | pub trait Mode: sealed::Mode {} |
| 772 | 789 | ||
| 773 | macro_rules! impl_mode { | 790 | macro_rules! impl_mode { |
| @@ -777,12 +794,15 @@ macro_rules! impl_mode { | |||
| 777 | }; | 794 | }; |
| 778 | } | 795 | } |
| 779 | 796 | ||
| 797 | /// Blocking mode. | ||
| 780 | pub struct Blocking; | 798 | pub struct Blocking; |
| 799 | /// Async mode. | ||
| 781 | pub struct Async; | 800 | pub struct Async; |
| 782 | 801 | ||
| 783 | impl_mode!(Blocking); | 802 | impl_mode!(Blocking); |
| 784 | impl_mode!(Async); | 803 | impl_mode!(Async); |
| 785 | 804 | ||
| 805 | /// I2C instance. | ||
| 786 | pub trait Instance: sealed::Instance {} | 806 | pub trait Instance: sealed::Instance {} |
| 787 | 807 | ||
| 788 | macro_rules! impl_instance { | 808 | macro_rules! impl_instance { |
| @@ -819,7 +839,9 @@ macro_rules! impl_instance { | |||
| 819 | impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33); | 839 | impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33); |
| 820 | impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35); | 840 | impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35); |
| 821 | 841 | ||
| 842 | /// SDA pin. | ||
| 822 | pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {} | 843 | pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {} |
| 844 | /// SCL pin. | ||
| 823 | pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {} | 845 | pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {} |
| 824 | 846 | ||
| 825 | macro_rules! impl_pin { | 847 | macro_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. | ||
| 1 | use core::future; | 2 | use core::future; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| @@ -63,11 +64,13 @@ impl Default for Config { | |||
| 63 | } | 64 | } |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 67 | /// I2CSlave driver. | ||
| 66 | pub struct I2cSlave<'d, T: Instance> { | 68 | pub struct I2cSlave<'d, T: Instance> { |
| 67 | phantom: PhantomData<&'d mut T>, | 69 | phantom: PhantomData<&'d mut T>, |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 70 | impl<'d, T: Instance> I2cSlave<'d, T> { | 72 | impl<'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. |
| 6 | pub(crate) mod fmt; | 7 | pub(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. | ||
| 1 | use core::future::Future; | 2 | use core::future::Future; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use core::pin::Pin as FuturePin; | 4 | use 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. | ||
| 256 | pub struct PwmBatch(u32); | 269 | pub struct PwmBatch(u32); |
| 257 | 270 | ||
| 258 | impl PwmBatch { | 271 | impl 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. | ||
| 292 | pub trait Channel: Peripheral<P = Self> + sealed::Channel + Sized + 'static { | 308 | pub 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); | |||
| 317 | channel!(PWM_CH6, 6); | 335 | channel!(PWM_CH6, 6); |
| 318 | channel!(PWM_CH7, 7); | 336 | channel!(PWM_CH7, 7); |
| 319 | 337 | ||
| 338 | /// PWM Pin A. | ||
| 320 | pub trait PwmPinA<T: Channel>: GpioPin {} | 339 | pub trait PwmPinA<T: Channel>: GpioPin {} |
| 340 | /// PWM Pin B. | ||
| 321 | pub trait PwmPinB<T: Channel>: GpioPin {} | 341 | pub trait PwmPinB<T: Channel>: GpioPin {} |
| 322 | 342 | ||
| 323 | macro_rules! impl_pin { | 343 | macro_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. | ||
| 1 | mod filter; | 2 | mod filter; |
| 2 | 3 | ||
| 3 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; | 4 | use 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. | ||
| 1 | use core::cell::Cell; | 2 | use core::cell::Cell; |
| 2 | 3 | ||
| 3 | use atomic_polyfill::{AtomicU8, Ordering}; | 4 | use 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. | ||
| 1 | use core::future::{poll_fn, Future}; | 2 | use core::future::{poll_fn, Future}; |
| 2 | use core::slice; | 3 | use core::slice; |
| 3 | use core::task::Poll; | 4 | use 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. | ||
| 1 | use core::future::poll_fn; | 2 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| @@ -947,7 +948,7 @@ pub struct Async; | |||
| 947 | impl_mode!(Blocking); | 948 | impl_mode!(Blocking); |
| 948 | impl_mode!(Async); | 949 | impl_mode!(Async); |
| 949 | 950 | ||
| 950 | /// UART instance trait. | 951 | /// UART instance. |
| 951 | pub trait Instance: sealed::Instance {} | 952 | pub trait Instance: sealed::Instance {} |
| 952 | 953 | ||
| 953 | macro_rules! impl_instance { | 954 | macro_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. | ||
| 1 | use core::future::poll_fn; | 2 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use core::slice; | 4 | use core::slice; |
