aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/rom_data.rs40
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}