diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-05-27 00:11:13 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2024-05-27 00:14:44 +0200 |
| commit | d18a919ab9cfa1c07d339dd885d8268ab0abb7e6 (patch) | |
| tree | efa6e34cfbf8650080c4ed1d5e50125dd412afc1 | |
| parent | 33bdc9e85ff391da4ff4ff439abe86c2bae32986 (diff) | |
rp: wait until read matches for PSM accesses.
| -rw-r--r-- | embassy-rp/src/lib.rs | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 4602e66f4..507d42280 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs | |||
| @@ -383,25 +383,29 @@ unsafe fn pre_init() { | |||
| 383 | // | 383 | // |
| 384 | // The PSM order is SIO -> PROC0 -> PROC1. | 384 | // The PSM order is SIO -> PROC0 -> PROC1. |
| 385 | // So, we have to force-on PROC0 to prevent it from getting reset when resetting SIO. | 385 | // So, we have to force-on PROC0 to prevent it from getting reset when resetting SIO. |
| 386 | pac::PSM.frce_on().write(|w| { | 386 | pac::PSM.frce_on().write_and_wait(|w| { |
| 387 | w.set_proc0(true); | 387 | w.set_proc0(true); |
| 388 | }); | 388 | }); |
| 389 | // Then reset SIO and PROC1. | 389 | // Then reset SIO and PROC1. |
| 390 | pac::PSM.frce_off().write(|w| { | 390 | pac::PSM.frce_off().write_and_wait(|w| { |
| 391 | w.set_sio(true); | 391 | w.set_sio(true); |
| 392 | w.set_proc1(true); | 392 | w.set_proc1(true); |
| 393 | }); | 393 | }); |
| 394 | // clear force_off first, force_on second. The other way around would reset PROC0. | 394 | // clear force_off first, force_on second. The other way around would reset PROC0. |
| 395 | pac::PSM.frce_off().write(|_| {}); | 395 | pac::PSM.frce_off().write_and_wait(|_| {}); |
| 396 | pac::PSM.frce_on().write(|_| {}); | 396 | pac::PSM.frce_on().write_and_wait(|_| {}); |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | /// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes. | 399 | /// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes. |
| 400 | #[allow(unused)] | ||
| 400 | trait RegExt<T: Copy> { | 401 | trait RegExt<T: Copy> { |
| 401 | #[allow(unused)] | 402 | #[allow(unused)] |
| 402 | fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; | 403 | fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; |
| 403 | fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; | 404 | fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; |
| 404 | fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; | 405 | fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; |
| 406 | fn write_and_wait<R>(&self, f: impl FnOnce(&mut T) -> R) -> R | ||
| 407 | where | ||
| 408 | T: PartialEq; | ||
| 405 | } | 409 | } |
| 406 | 410 | ||
| 407 | impl<T: Default + Copy, A: pac::common::Write> RegExt<T> for pac::common::Reg<T, A> { | 411 | impl<T: Default + Copy, A: pac::common::Write> RegExt<T> for pac::common::Reg<T, A> { |
| @@ -434,4 +438,17 @@ impl<T: Default + Copy, A: pac::common::Write> RegExt<T> for pac::common::Reg<T, | |||
| 434 | } | 438 | } |
| 435 | res | 439 | res |
| 436 | } | 440 | } |
| 441 | |||
| 442 | fn write_and_wait<R>(&self, f: impl FnOnce(&mut T) -> R) -> R | ||
| 443 | where | ||
| 444 | T: PartialEq, | ||
| 445 | { | ||
| 446 | let mut val = Default::default(); | ||
| 447 | let res = f(&mut val); | ||
| 448 | unsafe { | ||
| 449 | self.as_ptr().write_volatile(val); | ||
| 450 | while self.as_ptr().read_volatile() != val {} | ||
| 451 | } | ||
| 452 | res | ||
| 453 | } | ||
| 437 | } | 454 | } |
