diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-07-31 17:26:59 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-07-31 17:26:59 +0000 |
| commit | 4da97433173fcab5196e7c2a69c295edff3588eb (patch) | |
| tree | 929d20c7cb388f008dffeaee5ae5b4a2efb9a0ef | |
| parent | 4a9df60a7bcc1c52d82107382ed10ceaefc483ef (diff) | |
| parent | a5f21520771270984e7c2af1a3f78c79cc91c4fd (diff) | |
Merge pull request #1690 from Sizurka/rp-flash-ptr-fix
rp: Fix ROM cache ptr() returning the trampoline
| -rw-r--r-- | embassy-rp/src/rom_data.rs | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/embassy-rp/src/rom_data.rs b/embassy-rp/src/rom_data.rs index 805c1f09f..baebe5b6c 100644 --- a/embassy-rp/src/rom_data.rs +++ b/embassy-rp/src/rom_data.rs | |||
| @@ -88,9 +88,8 @@ macro_rules! declare_rom_function { | |||
| 88 | #[doc = stringify!($name)] | 88 | #[doc = stringify!($name)] |
| 89 | #[doc = r"` ROM function."] | 89 | #[doc = r"` ROM function."] |
| 90 | pub mod $name { | 90 | pub mod $name { |
| 91 | /// Retrieve a function pointer. | ||
| 92 | #[cfg(not(feature = "rom-func-cache"))] | 91 | #[cfg(not(feature = "rom-func-cache"))] |
| 93 | pub fn ptr() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret { | 92 | pub(crate) fn outer_call() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret { |
| 94 | let p: *const u32 = $lookup; | 93 | let p: *const u32 = $lookup; |
| 95 | unsafe { | 94 | unsafe { |
| 96 | let func : $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret | 95 | let func : $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret |
| @@ -99,6 +98,12 @@ macro_rules! declare_rom_function { | |||
| 99 | } | 98 | } |
| 100 | } | 99 | } |
| 101 | 100 | ||
| 101 | /// Retrieve a function pointer. | ||
| 102 | #[cfg(not(feature = "rom-func-cache"))] | ||
| 103 | pub fn ptr() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret { | ||
| 104 | outer_call() | ||
| 105 | } | ||
| 106 | |||
| 102 | #[cfg(feature = "rom-func-cache")] | 107 | #[cfg(feature = "rom-func-cache")] |
| 103 | // unlike rp2040-hal we store a full word, containing the full function pointer. | 108 | // unlike rp2040-hal we store a full word, containing the full function pointer. |
| 104 | // rp2040-hal saves two bytes by storing only the rom offset, at the cost of | 109 | // rp2040-hal saves two bytes by storing only the rom offset, at the cost of |
| @@ -119,9 +124,8 @@ macro_rules! declare_rom_function { | |||
| 119 | } | 124 | } |
| 120 | } | 125 | } |
| 121 | 126 | ||
| 122 | /// Retrieve a function pointer. | ||
| 123 | #[cfg(feature = "rom-func-cache")] | 127 | #[cfg(feature = "rom-func-cache")] |
| 124 | pub fn ptr() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret { | 128 | pub(crate) fn outer_call() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret { |
| 125 | use core::sync::atomic::{compiler_fence, Ordering}; | 129 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 126 | 130 | ||
| 127 | // This is safe because the lookup will always resolve | 131 | // This is safe because the lookup will always resolve |
| @@ -138,11 +142,37 @@ macro_rules! declare_rom_function { | |||
| 138 | CACHE | 142 | CACHE |
| 139 | } | 143 | } |
| 140 | } | 144 | } |
| 145 | |||
| 146 | /// Retrieve a function pointer. | ||
| 147 | #[cfg(feature = "rom-func-cache")] | ||
| 148 | pub fn ptr() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret { | ||
| 149 | use core::sync::atomic::{compiler_fence, Ordering}; | ||
| 150 | |||
| 151 | // We can't just return the trampoline here because we need | ||
| 152 | // the actual resolved function address (e.x. flash operations | ||
| 153 | // can't reference a trampoline which itself is in flash). We | ||
| 154 | // can still utilize the cache, but we have to make sure it has | ||
| 155 | // been resolved already. Like the normal call path, we | ||
| 156 | // don't need anything stronger than fences because the | ||
| 157 | // final value always resolves to the same thing and SRAM | ||
| 158 | // itself is not cached. | ||
| 159 | compiler_fence(Ordering::Acquire); | ||
| 160 | #[allow(unused_unsafe)] | ||
| 161 | unsafe { | ||
| 162 | // ROM is 16kB in size at 0x0, so anything outside is cached | ||
| 163 | if CACHE as u32 >> 14 != 0 { | ||
| 164 | let p: *const u32 = $lookup; | ||
| 165 | CACHE = core::mem::transmute(p); | ||
| 166 | compiler_fence(Ordering::Release); | ||
| 167 | } | ||
| 168 | CACHE | ||
| 169 | } | ||
| 170 | } | ||
| 141 | } | 171 | } |
| 142 | 172 | ||
| 143 | $(#[$outer])* | 173 | $(#[$outer])* |
| 144 | pub $( $maybe_unsafe )? extern "C" fn $name( $($argname: $ty),* ) -> $ret { | 174 | pub $( $maybe_unsafe )? extern "C" fn $name( $($argname: $ty),* ) -> $ret { |
| 145 | $name::ptr()($($argname),*) | 175 | $name::outer_call()($($argname),*) |
| 146 | } | 176 | } |
| 147 | }; | 177 | }; |
| 148 | } | 178 | } |
