diff options
| author | Caleb Garrett <[email protected]> | 2024-02-04 17:19:15 -0500 |
|---|---|---|
| committer | Caleb Garrett <[email protected]> | 2024-02-04 17:19:15 -0500 |
| commit | 059d8a82228c0fa90f7709ce362d7629ca028f13 (patch) | |
| tree | 2f238a6f97d0da953e98e7f8573fdaff0528f855 /embassy-nrf/src | |
| parent | 66f44b95d70547be8e32daac1ab611eec5fbe28a (diff) | |
| parent | 1f940bf9e868438090ea126eb2267f5e9325fbd4 (diff) | |
Merge commit '1f940bf9e868438090ea126eb2267f5e9325fbd4' into hash
Diffstat (limited to 'embassy-nrf/src')
| -rw-r--r-- | embassy-nrf/src/chips/nrf51.rs | 169 | ||||
| -rw-r--r-- | embassy-nrf/src/gpio.rs | 10 | ||||
| -rw-r--r-- | embassy-nrf/src/lib.rs | 23 | ||||
| -rw-r--r-- | embassy-nrf/src/ppi/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-nrf/src/ppi/ppi.rs | 5 | ||||
| -rw-r--r-- | embassy-nrf/src/rng.rs | 126 | ||||
| -rw-r--r-- | embassy-nrf/src/time_driver.rs | 18 | ||||
| -rw-r--r-- | embassy-nrf/src/timer.rs | 20 | ||||
| -rw-r--r-- | embassy-nrf/src/util.rs | 1 |
9 files changed, 294 insertions, 79 deletions
diff --git a/embassy-nrf/src/chips/nrf51.rs b/embassy-nrf/src/chips/nrf51.rs new file mode 100644 index 000000000..016352fb8 --- /dev/null +++ b/embassy-nrf/src/chips/nrf51.rs | |||
| @@ -0,0 +1,169 @@ | |||
| 1 | pub use nrf51_pac as pac; | ||
| 2 | |||
| 3 | /// The maximum buffer size that the EasyDMA can send/recv in one operation. | ||
| 4 | pub const EASY_DMA_SIZE: usize = (1 << 14) - 1; | ||
| 5 | |||
| 6 | pub const FLASH_SIZE: usize = 128 * 1024; | ||
| 7 | |||
| 8 | embassy_hal_internal::peripherals! { | ||
| 9 | // RTC | ||
| 10 | RTC0, | ||
| 11 | RTC1, | ||
| 12 | |||
| 13 | // WDT | ||
| 14 | WDT, | ||
| 15 | |||
| 16 | // NVMC | ||
| 17 | NVMC, | ||
| 18 | |||
| 19 | // RNG | ||
| 20 | RNG, | ||
| 21 | |||
| 22 | // UARTE | ||
| 23 | UART0, | ||
| 24 | |||
| 25 | // SPI/TWI | ||
| 26 | TWI0, | ||
| 27 | SPI0, | ||
| 28 | |||
| 29 | // ADC | ||
| 30 | ADC, | ||
| 31 | |||
| 32 | // TIMER | ||
| 33 | TIMER0, | ||
| 34 | TIMER1, | ||
| 35 | TIMER2, | ||
| 36 | |||
| 37 | // GPIOTE | ||
| 38 | GPIOTE_CH0, | ||
| 39 | GPIOTE_CH1, | ||
| 40 | GPIOTE_CH2, | ||
| 41 | GPIOTE_CH3, | ||
| 42 | |||
| 43 | // PPI | ||
| 44 | PPI_CH0, | ||
| 45 | PPI_CH1, | ||
| 46 | PPI_CH2, | ||
| 47 | PPI_CH3, | ||
| 48 | PPI_CH4, | ||
| 49 | PPI_CH5, | ||
| 50 | PPI_CH6, | ||
| 51 | PPI_CH7, | ||
| 52 | PPI_CH8, | ||
| 53 | PPI_CH9, | ||
| 54 | PPI_CH10, | ||
| 55 | PPI_CH11, | ||
| 56 | PPI_CH12, | ||
| 57 | PPI_CH13, | ||
| 58 | PPI_CH14, | ||
| 59 | PPI_CH15, | ||
| 60 | |||
| 61 | PPI_GROUP0, | ||
| 62 | PPI_GROUP1, | ||
| 63 | PPI_GROUP2, | ||
| 64 | PPI_GROUP3, | ||
| 65 | |||
| 66 | // GPIO port 0 | ||
| 67 | P0_00, | ||
| 68 | P0_01, | ||
| 69 | P0_02, | ||
| 70 | P0_03, | ||
| 71 | P0_04, | ||
| 72 | P0_05, | ||
| 73 | P0_06, | ||
| 74 | P0_07, | ||
| 75 | P0_08, | ||
| 76 | P0_09, | ||
| 77 | P0_10, | ||
| 78 | P0_11, | ||
| 79 | P0_12, | ||
| 80 | P0_13, | ||
| 81 | P0_14, | ||
| 82 | P0_15, | ||
| 83 | P0_16, | ||
| 84 | P0_17, | ||
| 85 | P0_18, | ||
| 86 | P0_19, | ||
| 87 | P0_20, | ||
| 88 | P0_21, | ||
| 89 | P0_22, | ||
| 90 | P0_23, | ||
| 91 | P0_24, | ||
| 92 | P0_25, | ||
| 93 | P0_26, | ||
| 94 | P0_27, | ||
| 95 | P0_28, | ||
| 96 | P0_29, | ||
| 97 | P0_30, | ||
| 98 | P0_31, | ||
| 99 | |||
| 100 | // TEMP | ||
| 101 | TEMP, | ||
| 102 | } | ||
| 103 | |||
| 104 | impl_timer!(TIMER0, TIMER0, TIMER0); | ||
| 105 | impl_timer!(TIMER1, TIMER1, TIMER1); | ||
| 106 | impl_timer!(TIMER2, TIMER2, TIMER2); | ||
| 107 | |||
| 108 | impl_rng!(RNG, RNG, RNG); | ||
| 109 | |||
| 110 | impl_pin!(P0_00, 0, 0); | ||
| 111 | impl_pin!(P0_01, 0, 1); | ||
| 112 | impl_pin!(P0_02, 0, 2); | ||
| 113 | impl_pin!(P0_03, 0, 3); | ||
| 114 | impl_pin!(P0_04, 0, 4); | ||
| 115 | impl_pin!(P0_05, 0, 5); | ||
| 116 | impl_pin!(P0_06, 0, 6); | ||
| 117 | impl_pin!(P0_07, 0, 7); | ||
| 118 | impl_pin!(P0_08, 0, 8); | ||
| 119 | impl_pin!(P0_09, 0, 9); | ||
| 120 | impl_pin!(P0_10, 0, 10); | ||
| 121 | impl_pin!(P0_11, 0, 11); | ||
| 122 | impl_pin!(P0_12, 0, 12); | ||
| 123 | impl_pin!(P0_13, 0, 13); | ||
| 124 | impl_pin!(P0_14, 0, 14); | ||
| 125 | impl_pin!(P0_15, 0, 15); | ||
| 126 | impl_pin!(P0_16, 0, 16); | ||
| 127 | impl_pin!(P0_17, 0, 17); | ||
| 128 | impl_pin!(P0_18, 0, 18); | ||
| 129 | impl_pin!(P0_19, 0, 19); | ||
| 130 | impl_pin!(P0_20, 0, 20); | ||
| 131 | impl_pin!(P0_21, 0, 21); | ||
| 132 | impl_pin!(P0_22, 0, 22); | ||
| 133 | impl_pin!(P0_23, 0, 23); | ||
| 134 | impl_pin!(P0_24, 0, 24); | ||
| 135 | impl_pin!(P0_25, 0, 25); | ||
| 136 | impl_pin!(P0_26, 0, 26); | ||
| 137 | impl_pin!(P0_27, 0, 27); | ||
| 138 | impl_pin!(P0_28, 0, 28); | ||
| 139 | impl_pin!(P0_29, 0, 29); | ||
| 140 | impl_pin!(P0_30, 0, 30); | ||
| 141 | impl_pin!(P0_31, 0, 31); | ||
| 142 | |||
| 143 | embassy_hal_internal::interrupt_mod!( | ||
| 144 | POWER_CLOCK, | ||
| 145 | RADIO, | ||
| 146 | UART0, | ||
| 147 | SPI0_TWI0, | ||
| 148 | SPI1_TWI1, | ||
| 149 | GPIOTE, | ||
| 150 | ADC, | ||
| 151 | TIMER0, | ||
| 152 | TIMER1, | ||
| 153 | TIMER2, | ||
| 154 | RTC0, | ||
| 155 | TEMP, | ||
| 156 | RNG, | ||
| 157 | ECB, | ||
| 158 | CCM_AAR, | ||
| 159 | WDT, | ||
| 160 | RTC1, | ||
| 161 | QDEC, | ||
| 162 | LPCOMP, | ||
| 163 | SWI0, | ||
| 164 | SWI1, | ||
| 165 | SWI2, | ||
| 166 | SWI3, | ||
| 167 | SWI4, | ||
| 168 | SWI5, | ||
| 169 | ); | ||
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 287811e61..b2f987109 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs | |||
| @@ -8,7 +8,13 @@ use cfg_if::cfg_if; | |||
| 8 | use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; | 8 | use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; |
| 9 | 9 | ||
| 10 | use self::sealed::Pin as _; | 10 | use self::sealed::Pin as _; |
| 11 | #[cfg(feature = "nrf51")] | ||
| 12 | use crate::pac::gpio; | ||
| 13 | #[cfg(feature = "nrf51")] | ||
| 14 | use crate::pac::gpio::pin_cnf::{DRIVE_A, PULL_A}; | ||
| 15 | #[cfg(not(feature = "nrf51"))] | ||
| 11 | use crate::pac::p0 as gpio; | 16 | use crate::pac::p0 as gpio; |
| 17 | #[cfg(not(feature = "nrf51"))] | ||
| 12 | use crate::pac::p0::pin_cnf::{DRIVE_A, PULL_A}; | 18 | use crate::pac::p0::pin_cnf::{DRIVE_A, PULL_A}; |
| 13 | use crate::{pac, Peripheral}; | 19 | use crate::{pac, Peripheral}; |
| 14 | 20 | ||
| @@ -376,6 +382,9 @@ pub(crate) mod sealed { | |||
| 376 | fn block(&self) -> &gpio::RegisterBlock { | 382 | fn block(&self) -> &gpio::RegisterBlock { |
| 377 | unsafe { | 383 | unsafe { |
| 378 | match self.pin_port() / 32 { | 384 | match self.pin_port() / 32 { |
| 385 | #[cfg(feature = "nrf51")] | ||
| 386 | 0 => &*pac::GPIO::ptr(), | ||
| 387 | #[cfg(not(feature = "nrf51"))] | ||
| 379 | 0 => &*pac::P0::ptr(), | 388 | 0 => &*pac::P0::ptr(), |
| 380 | #[cfg(feature = "_gpio-p1")] | 389 | #[cfg(feature = "_gpio-p1")] |
| 381 | 1 => &*pac::P1::ptr(), | 390 | 1 => &*pac::P1::ptr(), |
| @@ -478,6 +487,7 @@ impl<'a, P: Pin> PselBits for Option<PeripheralRef<'a, P>> { | |||
| 478 | } | 487 | } |
| 479 | } | 488 | } |
| 480 | 489 | ||
| 490 | #[allow(dead_code)] | ||
| 481 | pub(crate) fn deconfigure_pin(psel_bits: u32) { | 491 | pub(crate) fn deconfigure_pin(psel_bits: u32) { |
| 482 | if psel_bits & 0x8000_0000 != 0 { | 492 | if psel_bits & 0x8000_0000 != 0 { |
| 483 | return; | 493 | return; |
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index d9c92a76d..358a7cc27 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs | |||
| @@ -40,6 +40,7 @@ pub(crate) mod util; | |||
| 40 | #[cfg(feature = "_time-driver")] | 40 | #[cfg(feature = "_time-driver")] |
| 41 | mod time_driver; | 41 | mod time_driver; |
| 42 | 42 | ||
| 43 | #[cfg(not(feature = "nrf51"))] | ||
| 43 | pub mod buffered_uarte; | 44 | pub mod buffered_uarte; |
| 44 | pub mod gpio; | 45 | pub mod gpio; |
| 45 | #[cfg(feature = "gpiote")] | 46 | #[cfg(feature = "gpiote")] |
| @@ -58,7 +59,12 @@ pub mod nvmc; | |||
| 58 | ))] | 59 | ))] |
| 59 | pub mod pdm; | 60 | pub mod pdm; |
| 60 | pub mod ppi; | 61 | pub mod ppi; |
| 61 | #[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))] | 62 | #[cfg(not(any( |
| 63 | feature = "nrf51", | ||
| 64 | feature = "nrf52805", | ||
| 65 | feature = "nrf52820", | ||
| 66 | feature = "_nrf5340-net" | ||
| 67 | )))] | ||
| 62 | pub mod pwm; | 68 | pub mod pwm; |
| 63 | #[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))] | 69 | #[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))] |
| 64 | pub mod qdec; | 70 | pub mod qdec; |
| @@ -66,15 +72,20 @@ pub mod qdec; | |||
| 66 | pub mod qspi; | 72 | pub mod qspi; |
| 67 | #[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))] | 73 | #[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))] |
| 68 | pub mod rng; | 74 | pub mod rng; |
| 69 | #[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))] | 75 | #[cfg(not(any(feature = "nrf51", feature = "nrf52820", feature = "_nrf5340-net")))] |
| 70 | pub mod saadc; | 76 | pub mod saadc; |
| 77 | #[cfg(not(feature = "nrf51"))] | ||
| 71 | pub mod spim; | 78 | pub mod spim; |
| 79 | #[cfg(not(feature = "nrf51"))] | ||
| 72 | pub mod spis; | 80 | pub mod spis; |
| 73 | #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] | 81 | #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] |
| 74 | pub mod temp; | 82 | pub mod temp; |
| 75 | pub mod timer; | 83 | pub mod timer; |
| 84 | #[cfg(not(feature = "nrf51"))] | ||
| 76 | pub mod twim; | 85 | pub mod twim; |
| 86 | #[cfg(not(feature = "nrf51"))] | ||
| 77 | pub mod twis; | 87 | pub mod twis; |
| 88 | #[cfg(not(feature = "nrf51"))] | ||
| 78 | pub mod uarte; | 89 | pub mod uarte; |
| 79 | #[cfg(any( | 90 | #[cfg(any( |
| 80 | feature = "_nrf5340-app", | 91 | feature = "_nrf5340-app", |
| @@ -87,6 +98,7 @@ pub mod usb; | |||
| 87 | pub mod wdt; | 98 | pub mod wdt; |
| 88 | 99 | ||
| 89 | // This mod MUST go last, so that it sees all the `impl_foo!` macros | 100 | // This mod MUST go last, so that it sees all the `impl_foo!` macros |
| 101 | #[cfg_attr(feature = "nrf51", path = "chips/nrf51.rs")] | ||
| 90 | #[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")] | 102 | #[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")] |
| 91 | #[cfg_attr(feature = "nrf52810", path = "chips/nrf52810.rs")] | 103 | #[cfg_attr(feature = "nrf52810", path = "chips/nrf52810.rs")] |
| 92 | #[cfg_attr(feature = "nrf52811", path = "chips/nrf52811.rs")] | 104 | #[cfg_attr(feature = "nrf52811", path = "chips/nrf52811.rs")] |
| @@ -324,6 +336,7 @@ mod consts { | |||
| 324 | pub const APPROTECT_DISABLED: u32 = 0x0000_005a; | 336 | pub const APPROTECT_DISABLED: u32 = 0x0000_005a; |
| 325 | } | 337 | } |
| 326 | 338 | ||
| 339 | #[cfg(not(feature = "nrf51"))] | ||
| 327 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | 340 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
| 328 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 341 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 329 | enum WriteResult { | 342 | enum WriteResult { |
| @@ -335,10 +348,12 @@ enum WriteResult { | |||
| 335 | Failed, | 348 | Failed, |
| 336 | } | 349 | } |
| 337 | 350 | ||
| 351 | #[cfg(not(feature = "nrf51"))] | ||
| 338 | unsafe fn uicr_write(address: *mut u32, value: u32) -> WriteResult { | 352 | unsafe fn uicr_write(address: *mut u32, value: u32) -> WriteResult { |
| 339 | uicr_write_masked(address, value, 0xFFFF_FFFF) | 353 | uicr_write_masked(address, value, 0xFFFF_FFFF) |
| 340 | } | 354 | } |
| 341 | 355 | ||
| 356 | #[cfg(not(feature = "nrf51"))] | ||
| 342 | unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteResult { | 357 | unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteResult { |
| 343 | let curr_val = address.read_volatile(); | 358 | let curr_val = address.read_volatile(); |
| 344 | if curr_val & mask == value & mask { | 359 | if curr_val & mask == value & mask { |
| @@ -371,9 +386,11 @@ pub fn init(config: config::Config) -> Peripherals { | |||
| 371 | // before doing anything important. | 386 | // before doing anything important. |
| 372 | let peripherals = Peripherals::take(); | 387 | let peripherals = Peripherals::take(); |
| 373 | 388 | ||
| 389 | #[allow(unused_mut)] | ||
| 374 | let mut needs_reset = false; | 390 | let mut needs_reset = false; |
| 375 | 391 | ||
| 376 | // Setup debug protection. | 392 | // Setup debug protection. |
| 393 | #[cfg(not(feature = "nrf51"))] | ||
| 377 | match config.debug { | 394 | match config.debug { |
| 378 | config::Debug::Allowed => { | 395 | config::Debug::Allowed => { |
| 379 | #[cfg(feature = "_nrf52")] | 396 | #[cfg(feature = "_nrf52")] |
| @@ -489,7 +506,7 @@ pub fn init(config: config::Config) -> Peripherals { | |||
| 489 | } | 506 | } |
| 490 | 507 | ||
| 491 | // Configure LFCLK. | 508 | // Configure LFCLK. |
| 492 | #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] | 509 | #[cfg(not(any(feature = "nrf51", feature = "_nrf5340", feature = "_nrf9160")))] |
| 493 | match config.lfclk_source { | 510 | match config.lfclk_source { |
| 494 | config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()), | 511 | config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()), |
| 495 | config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()), | 512 | config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()), |
diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs index 5b4a64388..f5764b8b7 100644 --- a/embassy-nrf/src/ppi/mod.rs +++ b/embassy-nrf/src/ppi/mod.rs | |||
| @@ -284,6 +284,7 @@ impl ConfigurableChannel for AnyConfigurableChannel { | |||
| 284 | } | 284 | } |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | #[cfg(not(feature = "nrf51"))] | ||
| 287 | macro_rules! impl_ppi_channel { | 288 | macro_rules! impl_ppi_channel { |
| 288 | ($type:ident, $number:expr) => { | 289 | ($type:ident, $number:expr) => { |
| 289 | impl crate::ppi::sealed::Channel for peripherals::$type {} | 290 | impl crate::ppi::sealed::Channel for peripherals::$type {} |
diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs index 3e9e9fc81..8ff52ece3 100644 --- a/embassy-nrf/src/ppi/ppi.rs +++ b/embassy-nrf/src/ppi/ppi.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | use embassy_hal_internal::into_ref; | 1 | use embassy_hal_internal::into_ref; |
| 2 | 2 | ||
| 3 | use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; | 3 | use super::{Channel, ConfigurableChannel, Event, Ppi, Task}; |
| 4 | use crate::{pac, Peripheral}; | 4 | use crate::{pac, Peripheral}; |
| 5 | 5 | ||
| 6 | impl<'d> Task<'d> { | 6 | impl<'d> Task<'d> { |
| @@ -19,7 +19,7 @@ pub(crate) fn regs() -> &'static pac::ppi::RegisterBlock { | |||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | #[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task | 21 | #[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task |
| 22 | impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> { | 22 | impl<'d, C: super::StaticChannel> Ppi<'d, C, 0, 1> { |
| 23 | /// Configure PPI channel to trigger `task`. | 23 | /// Configure PPI channel to trigger `task`. |
| 24 | pub fn new_zero_to_one(ch: impl Peripheral<P = C> + 'd, task: Task) -> Self { | 24 | pub fn new_zero_to_one(ch: impl Peripheral<P = C> + 'd, task: Task) -> Self { |
| 25 | into_ref!(ch); | 25 | into_ref!(ch); |
| @@ -84,6 +84,7 @@ impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Drop for | |||
| 84 | let n = self.ch.number(); | 84 | let n = self.ch.number(); |
| 85 | r.ch[n].eep.write(|w| unsafe { w.bits(0) }); | 85 | r.ch[n].eep.write(|w| unsafe { w.bits(0) }); |
| 86 | r.ch[n].tep.write(|w| unsafe { w.bits(0) }); | 86 | r.ch[n].tep.write(|w| unsafe { w.bits(0) }); |
| 87 | #[cfg(not(feature = "nrf51"))] | ||
| 87 | r.fork[n].tep.write(|w| unsafe { w.bits(0) }); | 88 | r.fork[n].tep.write(|w| unsafe { w.bits(0) }); |
| 88 | } | 89 | } |
| 89 | } | 90 | } |
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs index e2803f0d3..40b73231b 100644 --- a/embassy-nrf/src/rng.rs +++ b/embassy-nrf/src/rng.rs | |||
| @@ -5,12 +5,10 @@ | |||
| 5 | use core::future::poll_fn; | 5 | use core::future::poll_fn; |
| 6 | use core::marker::PhantomData; | 6 | use core::marker::PhantomData; |
| 7 | use core::ptr; | 7 | use core::ptr; |
| 8 | use core::sync::atomic::{AtomicPtr, Ordering}; | ||
| 9 | use core::task::Poll; | 8 | use core::task::Poll; |
| 10 | 9 | ||
| 11 | use embassy_hal_internal::drop::OnDrop; | 10 | use embassy_hal_internal::drop::OnDrop; |
| 12 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 11 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 13 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 14 | 12 | ||
| 15 | use crate::interrupt::typelevel::Interrupt; | 13 | use crate::interrupt::typelevel::Interrupt; |
| 16 | use crate::{interrupt, Peripheral}; | 14 | use crate::{interrupt, Peripheral}; |
| @@ -22,7 +20,6 @@ pub struct InterruptHandler<T: Instance> { | |||
| 22 | 20 | ||
| 23 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { | 21 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { |
| 24 | unsafe fn on_interrupt() { | 22 | unsafe fn on_interrupt() { |
| 25 | let s = T::state(); | ||
| 26 | let r = T::regs(); | 23 | let r = T::regs(); |
| 27 | 24 | ||
| 28 | // Clear the event. | 25 | // Clear the event. |
| @@ -30,46 +27,25 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 30 | 27 | ||
| 31 | // Mutate the slice within a critical section, | 28 | // Mutate the slice within a critical section, |
| 32 | // so that the future isn't dropped in between us loading the pointer and actually dereferencing it. | 29 | // so that the future isn't dropped in between us loading the pointer and actually dereferencing it. |
| 33 | let (ptr, end) = critical_section::with(|_| { | 30 | critical_section::with(|cs| { |
| 34 | let ptr = s.ptr.load(Ordering::Relaxed); | 31 | let mut state = T::state().borrow_mut(cs); |
| 35 | // We need to make sure we haven't already filled the whole slice, | 32 | // We need to make sure we haven't already filled the whole slice, |
| 36 | // in case the interrupt fired again before the executor got back to the future. | 33 | // in case the interrupt fired again before the executor got back to the future. |
| 37 | let end = s.end.load(Ordering::Relaxed); | 34 | if !state.ptr.is_null() && state.ptr != state.end { |
| 38 | if !ptr.is_null() && ptr != end { | ||
| 39 | // If the future was dropped, the pointer would have been set to null, | 35 | // If the future was dropped, the pointer would have been set to null, |
| 40 | // so we're still good to mutate the slice. | 36 | // so we're still good to mutate the slice. |
| 41 | // The safety contract of `Rng::new` means that the future can't have been dropped | 37 | // The safety contract of `Rng::new` means that the future can't have been dropped |
| 42 | // without calling its destructor. | 38 | // without calling its destructor. |
| 43 | unsafe { | 39 | unsafe { |
| 44 | *ptr = r.value.read().value().bits(); | 40 | *state.ptr = r.value.read().value().bits(); |
| 41 | state.ptr = state.ptr.add(1); | ||
| 45 | } | 42 | } |
| 46 | } | ||
| 47 | (ptr, end) | ||
| 48 | }); | ||
| 49 | |||
| 50 | if ptr.is_null() || ptr == end { | ||
| 51 | // If the future was dropped, there's nothing to do. | ||
| 52 | // If `ptr == end`, we were called by mistake, so return. | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | 43 | ||
| 56 | let new_ptr = unsafe { ptr.add(1) }; | 44 | if state.ptr == state.end { |
| 57 | match s | 45 | state.waker.wake(); |
| 58 | .ptr | ||
| 59 | .compare_exchange(ptr, new_ptr, Ordering::Relaxed, Ordering::Relaxed) | ||
| 60 | { | ||
| 61 | Ok(_) => { | ||
| 62 | let end = s.end.load(Ordering::Relaxed); | ||
| 63 | // It doesn't matter if `end` was changed under our feet, because then this will just be false. | ||
| 64 | if new_ptr == end { | ||
| 65 | s.waker.wake(); | ||
| 66 | } | 46 | } |
| 67 | } | 47 | } |
| 68 | Err(_) => { | 48 | }); |
| 69 | // If the future was dropped or finished, there's no point trying to wake it. | ||
| 70 | // It will have already stopped the RNG, so there's no need to do that either. | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | 49 | } |
| 74 | } | 50 | } |
| 75 | 51 | ||
| @@ -136,13 +112,14 @@ impl<'d, T: Instance> Rng<'d, T> { | |||
| 136 | return; // Nothing to fill | 112 | return; // Nothing to fill |
| 137 | } | 113 | } |
| 138 | 114 | ||
| 139 | let s = T::state(); | ||
| 140 | |||
| 141 | let range = dest.as_mut_ptr_range(); | 115 | let range = dest.as_mut_ptr_range(); |
| 142 | // Even if we've preempted the interrupt, it can't preempt us again, | 116 | // Even if we've preempted the interrupt, it can't preempt us again, |
| 143 | // so we don't need to worry about the order we write these in. | 117 | // so we don't need to worry about the order we write these in. |
| 144 | s.ptr.store(range.start, Ordering::Relaxed); | 118 | critical_section::with(|cs| { |
| 145 | s.end.store(range.end, Ordering::Relaxed); | 119 | let mut state = T::state().borrow_mut(cs); |
| 120 | state.ptr = range.start; | ||
| 121 | state.end = range.end; | ||
| 122 | }); | ||
| 146 | 123 | ||
| 147 | self.enable_irq(); | 124 | self.enable_irq(); |
| 148 | self.start(); | 125 | self.start(); |
| @@ -151,24 +128,24 @@ impl<'d, T: Instance> Rng<'d, T> { | |||
| 151 | self.stop(); | 128 | self.stop(); |
| 152 | self.disable_irq(); | 129 | self.disable_irq(); |
| 153 | 130 | ||
| 154 | // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here. | 131 | critical_section::with(|cs| { |
| 155 | s.ptr.store(ptr::null_mut(), Ordering::Relaxed); | 132 | let mut state = T::state().borrow_mut(cs); |
| 156 | s.end.store(ptr::null_mut(), Ordering::Relaxed); | 133 | state.ptr = ptr::null_mut(); |
| 134 | state.end = ptr::null_mut(); | ||
| 135 | }); | ||
| 157 | }); | 136 | }); |
| 158 | 137 | ||
| 159 | poll_fn(|cx| { | 138 | poll_fn(|cx| { |
| 160 | s.waker.register(cx.waker()); | 139 | critical_section::with(|cs| { |
| 161 | 140 | let mut s = T::state().borrow_mut(cs); | |
| 162 | // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`. | 141 | s.waker.register(cx.waker()); |
| 163 | let end = s.end.load(Ordering::Relaxed); | 142 | if s.ptr == s.end { |
| 164 | let ptr = s.ptr.load(Ordering::Relaxed); | 143 | // We're done. |
| 165 | 144 | Poll::Ready(()) | |
| 166 | if ptr == end { | 145 | } else { |
| 167 | // We're done. | 146 | Poll::Pending |
| 168 | Poll::Ready(()) | 147 | } |
| 169 | } else { | 148 | }) |
| 170 | Poll::Pending | ||
| 171 | } | ||
| 172 | }) | 149 | }) |
| 173 | .await; | 150 | .await; |
| 174 | 151 | ||
| @@ -194,9 +171,11 @@ impl<'d, T: Instance> Rng<'d, T> { | |||
| 194 | impl<'d, T: Instance> Drop for Rng<'d, T> { | 171 | impl<'d, T: Instance> Drop for Rng<'d, T> { |
| 195 | fn drop(&mut self) { | 172 | fn drop(&mut self) { |
| 196 | self.stop(); | 173 | self.stop(); |
| 197 | let s = T::state(); | 174 | critical_section::with(|cs| { |
| 198 | s.ptr.store(ptr::null_mut(), Ordering::Relaxed); | 175 | let mut state = T::state().borrow_mut(cs); |
| 199 | s.end.store(ptr::null_mut(), Ordering::Relaxed); | 176 | state.ptr = ptr::null_mut(); |
| 177 | state.end = ptr::null_mut(); | ||
| 178 | }); | ||
| 200 | } | 179 | } |
| 201 | } | 180 | } |
| 202 | 181 | ||
| @@ -227,21 +206,48 @@ impl<'d, T: Instance> rand_core::RngCore for Rng<'d, T> { | |||
| 227 | impl<'d, T: Instance> rand_core::CryptoRng for Rng<'d, T> {} | 206 | impl<'d, T: Instance> rand_core::CryptoRng for Rng<'d, T> {} |
| 228 | 207 | ||
| 229 | pub(crate) mod sealed { | 208 | pub(crate) mod sealed { |
| 209 | use core::cell::{Ref, RefCell, RefMut}; | ||
| 210 | |||
| 211 | use critical_section::{CriticalSection, Mutex}; | ||
| 212 | use embassy_sync::waitqueue::WakerRegistration; | ||
| 213 | |||
| 230 | use super::*; | 214 | use super::*; |
| 231 | 215 | ||
| 232 | /// Peripheral static state | 216 | /// Peripheral static state |
| 233 | pub struct State { | 217 | pub struct State { |
| 234 | pub ptr: AtomicPtr<u8>, | 218 | inner: Mutex<RefCell<InnerState>>, |
| 235 | pub end: AtomicPtr<u8>, | 219 | } |
| 236 | pub waker: AtomicWaker, | 220 | |
| 221 | pub struct InnerState { | ||
| 222 | pub ptr: *mut u8, | ||
| 223 | pub end: *mut u8, | ||
| 224 | pub waker: WakerRegistration, | ||
| 237 | } | 225 | } |
| 238 | 226 | ||
| 227 | unsafe impl Send for InnerState {} | ||
| 228 | |||
| 239 | impl State { | 229 | impl State { |
| 240 | pub const fn new() -> Self { | 230 | pub const fn new() -> Self { |
| 241 | Self { | 231 | Self { |
| 242 | ptr: AtomicPtr::new(ptr::null_mut()), | 232 | inner: Mutex::new(RefCell::new(InnerState::new())), |
| 243 | end: AtomicPtr::new(ptr::null_mut()), | 233 | } |
| 244 | waker: AtomicWaker::new(), | 234 | } |
| 235 | |||
| 236 | pub fn borrow<'cs>(&'cs self, cs: CriticalSection<'cs>) -> Ref<'cs, InnerState> { | ||
| 237 | self.inner.borrow(cs).borrow() | ||
| 238 | } | ||
| 239 | |||
| 240 | pub fn borrow_mut<'cs>(&'cs self, cs: CriticalSection<'cs>) -> RefMut<'cs, InnerState> { | ||
| 241 | self.inner.borrow(cs).borrow_mut() | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | impl InnerState { | ||
| 246 | pub const fn new() -> Self { | ||
| 247 | Self { | ||
| 248 | ptr: ptr::null_mut(), | ||
| 249 | end: ptr::null_mut(), | ||
| 250 | waker: WakerRegistration::new(), | ||
| 245 | } | 251 | } |
| 246 | } | 252 | } |
| 247 | } | 253 | } |
diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs index 042f7c5f7..3407c9504 100644 --- a/embassy-nrf/src/time_driver.rs +++ b/embassy-nrf/src/time_driver.rs | |||
| @@ -171,7 +171,8 @@ impl RtcDriver { | |||
| 171 | fn next_period(&self) { | 171 | fn next_period(&self) { |
| 172 | critical_section::with(|cs| { | 172 | critical_section::with(|cs| { |
| 173 | let r = rtc(); | 173 | let r = rtc(); |
| 174 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; | 174 | let period = self.period.load(Ordering::Relaxed) + 1; |
| 175 | self.period.store(period, Ordering::Relaxed); | ||
| 175 | let t = (period as u64) << 23; | 176 | let t = (period as u64) << 23; |
| 176 | 177 | ||
| 177 | for n in 0..ALARM_COUNT { | 178 | for n in 0..ALARM_COUNT { |
| @@ -219,18 +220,15 @@ impl Driver for RtcDriver { | |||
| 219 | } | 220 | } |
| 220 | 221 | ||
| 221 | unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> { | 222 | unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> { |
| 222 | let id = self.alarm_count.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| { | 223 | critical_section::with(|_| { |
| 223 | if x < ALARM_COUNT as u8 { | 224 | let id = self.alarm_count.load(Ordering::Relaxed); |
| 224 | Some(x + 1) | 225 | if id < ALARM_COUNT as u8 { |
| 226 | self.alarm_count.store(id + 1, Ordering::Relaxed); | ||
| 227 | Some(AlarmHandle::new(id)) | ||
| 225 | } else { | 228 | } else { |
| 226 | None | 229 | None |
| 227 | } | 230 | } |
| 228 | }); | 231 | }) |
| 229 | |||
| 230 | match id { | ||
| 231 | Ok(id) => Some(AlarmHandle::new(id)), | ||
| 232 | Err(_) => None, | ||
| 233 | } | ||
| 234 | } | 232 | } |
| 235 | 233 | ||
| 236 | fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) { | 234 | fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) { |
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index 3dbfdac42..3c35baee5 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs | |||
| @@ -111,7 +111,7 @@ impl<'d, T: Instance> Timer<'d, T> { | |||
| 111 | Self::new_inner(timer, true) | 111 | Self::new_inner(timer, true) |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | fn new_inner(timer: impl Peripheral<P = T> + 'd, is_counter: bool) -> Self { | 114 | fn new_inner(timer: impl Peripheral<P = T> + 'd, _is_counter: bool) -> Self { |
| 115 | into_ref!(timer); | 115 | into_ref!(timer); |
| 116 | 116 | ||
| 117 | let regs = T::regs(); | 117 | let regs = T::regs(); |
| @@ -122,12 +122,16 @@ impl<'d, T: Instance> Timer<'d, T> { | |||
| 122 | // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. | 122 | // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. |
| 123 | this.stop(); | 123 | this.stop(); |
| 124 | 124 | ||
| 125 | if is_counter { | 125 | #[cfg(not(feature = "nrf51"))] |
| 126 | if _is_counter { | ||
| 126 | regs.mode.write(|w| w.mode().low_power_counter()); | 127 | regs.mode.write(|w| w.mode().low_power_counter()); |
| 127 | } else { | 128 | } else { |
| 128 | regs.mode.write(|w| w.mode().timer()); | 129 | regs.mode.write(|w| w.mode().timer()); |
| 129 | } | 130 | } |
| 130 | 131 | ||
| 132 | #[cfg(feature = "nrf51")] | ||
| 133 | regs.mode.write(|w| w.mode().timer()); | ||
| 134 | |||
| 131 | // Make the counter's max value as high as possible. | 135 | // Make the counter's max value as high as possible. |
| 132 | // TODO: is there a reason someone would want to set this lower? | 136 | // TODO: is there a reason someone would want to set this lower? |
| 133 | regs.bitmode.write(|w| w.bitmode()._32bit()); | 137 | regs.bitmode.write(|w| w.bitmode()._32bit()); |
| @@ -238,7 +242,11 @@ pub struct Cc<'d, T: Instance> { | |||
| 238 | impl<'d, T: Instance> Cc<'d, T> { | 242 | impl<'d, T: Instance> Cc<'d, T> { |
| 239 | /// Get the current value stored in the register. | 243 | /// Get the current value stored in the register. |
| 240 | pub fn read(&self) -> u32 { | 244 | pub fn read(&self) -> u32 { |
| 241 | T::regs().cc[self.n].read().cc().bits() | 245 | #[cfg(not(feature = "nrf51"))] |
| 246 | return T::regs().cc[self.n].read().cc().bits(); | ||
| 247 | |||
| 248 | #[cfg(feature = "nrf51")] | ||
| 249 | return T::regs().cc[self.n].read().bits(); | ||
| 242 | } | 250 | } |
| 243 | 251 | ||
| 244 | /// Set the value stored in the register. | 252 | /// Set the value stored in the register. |
| @@ -246,7 +254,11 @@ impl<'d, T: Instance> Cc<'d, T> { | |||
| 246 | /// `event_compare` will fire when the timer's counter reaches this value. | 254 | /// `event_compare` will fire when the timer's counter reaches this value. |
| 247 | pub fn write(&self, value: u32) { | 255 | pub fn write(&self, value: u32) { |
| 248 | // SAFETY: there are no invalid values for the CC register. | 256 | // SAFETY: there are no invalid values for the CC register. |
| 249 | T::regs().cc[self.n].write(|w| unsafe { w.cc().bits(value) }) | 257 | #[cfg(not(feature = "nrf51"))] |
| 258 | T::regs().cc[self.n].write(|w| unsafe { w.cc().bits(value) }); | ||
| 259 | |||
| 260 | #[cfg(feature = "nrf51")] | ||
| 261 | T::regs().cc[self.n].write(|w| unsafe { w.bits(value) }); | ||
| 250 | } | 262 | } |
| 251 | 263 | ||
| 252 | /// Capture the current value of the timer's counter in this register, and return it. | 264 | /// Capture the current value of the timer's counter in this register, and return it. |
diff --git a/embassy-nrf/src/util.rs b/embassy-nrf/src/util.rs index cd0f59490..b408c517b 100644 --- a/embassy-nrf/src/util.rs +++ b/embassy-nrf/src/util.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | #![allow(dead_code)] | ||
| 1 | use core::mem; | 2 | use core::mem; |
| 2 | 3 | ||
| 3 | const SRAM_LOWER: usize = 0x2000_0000; | 4 | const SRAM_LOWER: usize = 0x2000_0000; |
