rp: Fix ROM cache ptr() returning the trampoline

Make sure that the ptr() function for ROM functions always returns
the actual ROM pointer.  This allows the use of flash I/O while the
function cache is enabled.
This commit is contained in:
Derek Hageman 2023-07-25 16:39:11 -06:00
parent 77e34c5e8a
commit a5f2152077

View File

@ -88,9 +88,8 @@ macro_rules! declare_rom_function {
#[doc = stringify!($name)] #[doc = stringify!($name)]
#[doc = r"` ROM function."] #[doc = r"` ROM function."]
pub mod $name { pub mod $name {
/// Retrieve a function pointer.
#[cfg(not(feature = "rom-func-cache"))] #[cfg(not(feature = "rom-func-cache"))]
pub fn ptr() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret { pub(crate) fn outer_call() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret {
let p: *const u32 = $lookup; let p: *const u32 = $lookup;
unsafe { unsafe {
let func : $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret let func : $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret
@ -99,6 +98,12 @@ macro_rules! declare_rom_function {
} }
} }
/// Retrieve a function pointer.
#[cfg(not(feature = "rom-func-cache"))]
pub fn ptr() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret {
outer_call()
}
#[cfg(feature = "rom-func-cache")] #[cfg(feature = "rom-func-cache")]
// unlike rp2040-hal we store a full word, containing the full function pointer. // unlike rp2040-hal we store a full word, containing the full function pointer.
// rp2040-hal saves two bytes by storing only the rom offset, at the cost of // rp2040-hal saves two bytes by storing only the rom offset, at the cost of
@ -119,9 +124,8 @@ macro_rules! declare_rom_function {
} }
} }
/// Retrieve a function pointer.
#[cfg(feature = "rom-func-cache")] #[cfg(feature = "rom-func-cache")]
pub fn ptr() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret { pub(crate) fn outer_call() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret {
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
// This is safe because the lookup will always resolve // This is safe because the lookup will always resolve
@ -138,11 +142,37 @@ macro_rules! declare_rom_function {
CACHE CACHE
} }
} }
/// Retrieve a function pointer.
#[cfg(feature = "rom-func-cache")]
pub fn ptr() -> $( $maybe_unsafe )? extern "C" fn( $($argname: $ty),* ) -> $ret {
use core::sync::atomic::{compiler_fence, Ordering};
// We can't just return the trampoline here because we need
// the actual resolved function address (e.x. flash operations
// can't reference a trampoline which itself is in flash). We
// can still utilize the cache, but we have to make sure it has
// been resolved already. Like the normal call path, we
// don't need anything stronger than fences because the
// final value always resolves to the same thing and SRAM
// itself is not cached.
compiler_fence(Ordering::Acquire);
#[allow(unused_unsafe)]
unsafe {
// ROM is 16kB in size at 0x0, so anything outside is cached
if CACHE as u32 >> 14 != 0 {
let p: *const u32 = $lookup;
CACHE = core::mem::transmute(p);
compiler_fence(Ordering::Release);
}
CACHE
}
}
} }
$(#[$outer])* $(#[$outer])*
pub $( $maybe_unsafe )? extern "C" fn $name( $($argname: $ty),* ) -> $ret { pub $( $maybe_unsafe )? extern "C" fn $name( $($argname: $ty),* ) -> $ret {
$name::ptr()($($argname),*) $name::outer_call()($($argname),*)
} }
}; };
} }