From 0fa58ed21928e4175e598c9300e4fde019d10a60 Mon Sep 17 00:00:00 2001 From: Graham Sanderson Date: Fri, 8 Oct 2021 09:02:19 -0500 Subject: [PATCH] Adding/propage macros/signature typedefs for ROM functions. Make rom_func_lookup non-flash safe for flash functions (#586) * add typedef signatures and ROM code defines for bootrom functions. Propogate uses thru SDK code. Add _inline version of rom_func_lookup --- src/rp2_common/hardware_flash/flash.c | 26 ++++--- src/rp2_common/pico_bootrom/bootrom.c | 4 +- .../pico_bootrom/include/pico/bootrom.h | 72 ++++++++++++++++++- src/rp2_common/pico_double/double_init_rom.c | 2 +- src/rp2_common/pico_float/float_init_rom.c | 2 +- 5 files changed, 84 insertions(+), 22 deletions(-) diff --git a/src/rp2_common/hardware_flash/flash.c b/src/rp2_common/hardware_flash/flash.c index dc9d833..5699302 100644 --- a/src/rp2_common/hardware_flash/flash.c +++ b/src/rp2_common/hardware_flash/flash.c @@ -50,7 +50,7 @@ static void __no_inline_not_in_flash_func(flash_init_boot2_copyout)(void) {} static void __no_inline_not_in_flash_func(flash_enable_xip_via_boot2)(void) { // Set up XIP for 03h read on bus access (slow but generic) - void (*flash_enter_cmd_xip)(void) = (void(*)(void))rom_func_lookup(rom_table_code('C', 'X')); + rom_flash_enter_cmd_xip_fn flash_enter_cmd_xip = (rom_flash_enter_cmd_xip_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_ENTER_CMD_XIP); assert(flash_enter_cmd_xip); flash_enter_cmd_xip(); } @@ -66,11 +66,10 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_ #endif invalid_params_if(FLASH, flash_offs & (FLASH_SECTOR_SIZE - 1)); invalid_params_if(FLASH, count & (FLASH_SECTOR_SIZE - 1)); - void (*connect_internal_flash)(void) = (void(*)(void))rom_func_lookup(rom_table_code('I', 'F')); - void (*flash_exit_xip)(void) = (void(*)(void))rom_func_lookup(rom_table_code('E', 'X')); - void (*flash_range_erase)(uint32_t, size_t, uint32_t, uint8_t) = - (void(*)(uint32_t, size_t, uint32_t, uint8_t))rom_func_lookup(rom_table_code('R', 'E')); - void (*flash_flush_cache)(void) = (void(*)(void))rom_func_lookup(rom_table_code('F', 'C')); + rom_connect_internal_flash_fn connect_internal_flash = (rom_connect_internal_flash_fn)rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH); + rom_flash_exit_xip_fn flash_exit_xip = (rom_flash_exit_xip_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP); + rom_flash_range_erase_fn flash_range_erase = (rom_flash_range_erase_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_RANGE_ERASE); + rom_flash_flush_cache_fn flash_flush_cache = (rom_flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE); assert(connect_internal_flash && flash_exit_xip && flash_range_erase && flash_flush_cache); flash_init_boot2_copyout(); @@ -90,11 +89,10 @@ void __no_inline_not_in_flash_func(flash_range_program)(uint32_t flash_offs, con #endif invalid_params_if(FLASH, flash_offs & (FLASH_PAGE_SIZE - 1)); invalid_params_if(FLASH, count & (FLASH_PAGE_SIZE - 1)); - void (*connect_internal_flash)(void) = (void(*)(void))rom_func_lookup(rom_table_code('I', 'F')); - void (*flash_exit_xip)(void) = (void(*)(void))rom_func_lookup(rom_table_code('E', 'X')); - void (*flash_range_program)(uint32_t, const uint8_t*, size_t) = - (void(*)(uint32_t, const uint8_t*, size_t))rom_func_lookup(rom_table_code('R', 'P')); - void (*flash_flush_cache)(void) = (void(*)(void))rom_func_lookup(rom_table_code('F', 'C')); + rom_connect_internal_flash_fn connect_internal_flash = (rom_connect_internal_flash_fn)rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH); + rom_flash_exit_xip_fn flash_exit_xip = (rom_flash_exit_xip_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP); + rom_flash_range_program_fn flash_range_program = (rom_flash_range_program_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_RANGE_PROGRAM); + rom_flash_flush_cache_fn flash_flush_cache = (rom_flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE); assert(connect_internal_flash && flash_exit_xip && flash_range_program && flash_flush_cache); flash_init_boot2_copyout(); @@ -124,9 +122,9 @@ static void __no_inline_not_in_flash_func(flash_cs_force)(bool high) { } void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *rxbuf, size_t count) { - void (*connect_internal_flash)(void) = (void(*)(void))rom_func_lookup(rom_table_code('I', 'F')); - void (*flash_exit_xip)(void) = (void(*)(void))rom_func_lookup(rom_table_code('E', 'X')); - void (*flash_flush_cache)(void) = (void(*)(void))rom_func_lookup(rom_table_code('F', 'C')); + rom_connect_internal_flash_fn connect_internal_flash = (rom_connect_internal_flash_fn)rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH); + rom_flash_exit_xip_fn flash_exit_xip = (rom_flash_exit_xip_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP); + rom_flash_flush_cache_fn flash_flush_cache = (rom_flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE); assert(connect_internal_flash && flash_exit_xip && flash_flush_cache); flash_init_boot2_copyout(); __compiler_memory_barrier(); diff --git a/src/rp2_common/pico_bootrom/bootrom.c b/src/rp2_common/pico_bootrom/bootrom.c index 08cdb33..af7d091 100644 --- a/src/rp2_common/pico_bootrom/bootrom.c +++ b/src/rp2_common/pico_bootrom/bootrom.c @@ -16,9 +16,7 @@ typedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code); #define rom_hword_as_ptr(rom_address) (void *)(uintptr_t)(*(uint16_t *)rom_address) void *rom_func_lookup(uint32_t code) { - rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) rom_hword_as_ptr(0x18); - uint16_t *func_table = (uint16_t *) rom_hword_as_ptr(0x14); - return rom_table_lookup(func_table, code); + return rom_func_lookup_inline(code); } void *rom_data_lookup(uint32_t code) { diff --git a/src/rp2_common/pico_bootrom/include/pico/bootrom.h b/src/rp2_common/pico_bootrom/include/pico/bootrom.h index 7d42926..cd9b155 100644 --- a/src/rp2_common/pico_bootrom/include/pico/bootrom.h +++ b/src/rp2_common/pico_bootrom/include/pico/bootrom.h @@ -22,7 +22,7 @@ extern "C" { * \ingroup pico_bootrom * * These codes are uses to lookup data or function addresses in the bootrom - * + * * \param c1 the first character * \param c2 the second character * \return the 'code' to use in rom_func_lookup() or rom_data_lookup() @@ -31,6 +31,7 @@ static inline uint32_t rom_table_code(uint8_t c1, uint8_t c2) { return (((uint)c2) << 8u) | (uint)c1; } + /*! * \brief Lookup a bootrom function by code * \ingroup pico_bootrom @@ -60,7 +61,72 @@ void *rom_data_lookup(uint32_t code); */ bool rom_funcs_lookup(uint32_t *table, unsigned int count); -typedef void __attribute__((noreturn)) (*reset_usb_boot_fn)(uint32_t, uint32_t); +// The following is a list of bootrom functions available via rom_func_lookup and their signature + +typedef uint32_t (*rom_popcount32_fn)(uint32_t); +#define ROM_FUNC_POPCOUNT32 rom_table_code('P', '3') + +typedef uint32_t (*rom_reverse32_fn)(uint32_t); +#define ROM_FUNC_REVERSE32 rom_table_code('R', '3') + +typedef uint32_t (*rom_clz32_fn)(uint32_t); +#define ROM_FUNC_CLZ32 rom_table_code('L', '3') + +typedef uint32_t (*rom_ctz32_fn)(uint32_t); +#define ROM_FUNC_CTZ32 rom_table_code('T', '3') + +typedef uint8_t *(*rom_memset_fn)(uint8_t *, uint8_t, uint32_t); +#define ROM_FUNC_MEMSET rom_table_code('M', 'S') + +typedef uint32_t *(*rom_memset4_fn)(uint32_t *, uint8_t, uint32_t); +#define ROM_FUNC_MEMSET4 rom_table_code('S', '4') + +typedef uint32_t *(*rom_memcpy_fn)(uint8_t *, const uint8_t *, uint32_t); +#define ROM_FUNC_MEMCPY rom_table_code('M', 'C') + +typedef uint32_t *(*rom_memcpy44_fn)(uint32_t *, const uint32_t *, uint32_t); +#define ROM_FUNC_MEMCPY44 rom_table_code('C', '4') + +typedef void __attribute__((noreturn)) (*rom_reset_usb_boot_fn)(uint32_t, uint32_t); +typedef rom_reset_usb_boot_fn reset_usb_boot_fn; // kept for backwards compatibility +#define ROM_FUNC_RESET_USB_BOOT rom_table_code('U', 'B') + +typedef void (*rom_connect_internal_flash_fn)(void); +#define ROM_FUNC_CONNECT_INTERNAL_FLASH rom_table_code('I', 'F') + +typedef void (*rom_flash_exit_xip_fn)(void); +#define ROM_FUNC_FLASH_EXIT_XIP rom_table_code('E', 'X') + +typedef void (*rom_flash_range_erase_fn)(uint32_t, size_t, uint32_t, uint8_t); +#define ROM_FUNC_FLASH_RANGE_ERASE rom_table_code('R', 'E') + +typedef void (*rom_flash_range_program_fn)(uint32_t, const uint8_t*, size_t); +#define ROM_FUNC_FLASH_RANGE_PROGRAM rom_table_code('R', 'P') + +typedef void (*rom_flash_flush_cache_fn)(void); +#define ROM_FUNC_FLASH_FLUSH_CACHE rom_table_code('F', 'C') + +typedef void (*rom_flash_enter_cmd_xip_fn)(void); +#define ROM_FUNC_FLASH_ENTER_CMD_XIP rom_table_code('C', 'X') + +// Bootrom function: rom_table_lookup +// Returns the 32 bit pointer into the ROM if found or NULL otherwise. +typedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code); + +// Convert a 16 bit pointer stored at the given rom address into a 32 bit pointer +#define rom_hword_as_ptr(rom_address) (void *)(uintptr_t)(*(uint16_t *)rom_address) + +/*! + * \brief Lookup a bootrom function by code. This method is forceably inlined into the caller for FLASH/RAM sensitive code usage + * \ingroup pico_bootrom + * \param code the code + * \return a pointer to the function, or NULL if the code does not match any bootrom function + */ +static __force_inline void *rom_func_lookup_inline(uint32_t code) { + rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) rom_hword_as_ptr(0x18); + uint16_t *func_table = (uint16_t *) rom_hword_as_ptr(0x14); + return rom_table_lookup(func_table, code); +} /*! * \brief Reboot the device into BOOTSEL mode @@ -81,7 +147,7 @@ typedef void __attribute__((noreturn)) (*reset_usb_boot_fn)(uint32_t, uint32_t); */ static inline void __attribute__((noreturn)) reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interface_mask) { - reset_usb_boot_fn func = (reset_usb_boot_fn) rom_func_lookup(rom_table_code('U', 'B')); + rom_reset_usb_boot_fn func = (rom_reset_usb_boot_fn) rom_func_lookup(ROM_FUNC_RESET_USB_BOOT); func(usb_activity_gpio_pin_mask, disable_interface_mask); } diff --git a/src/rp2_common/pico_double/double_init_rom.c b/src/rp2_common/pico_double/double_init_rom.c index 2255939..79ecff6 100644 --- a/src/rp2_common/pico_double/double_init_rom.c +++ b/src/rp2_common/pico_double/double_init_rom.c @@ -66,5 +66,5 @@ void __aeabi_double_init(void) { sd_table[SF_TABLE_V3_FSINCOS / 4] = (uintptr_t) double_table_shim_on_use_helper; } - sf_clz_func = rom_func_lookup(rom_table_code('L', '3')); + sf_clz_func = rom_func_lookup(ROM_FUNC_CLZ32); } diff --git a/src/rp2_common/pico_float/float_init_rom.c b/src/rp2_common/pico_float/float_init_rom.c index c7a52c2..b9a350a 100644 --- a/src/rp2_common/pico_float/float_init_rom.c +++ b/src/rp2_common/pico_float/float_init_rom.c @@ -66,5 +66,5 @@ void __aeabi_float_init(void) { assert(*((uint8_t *)(rom_table-2)) * 4 >= SF_TABLE_V2_SIZE); memcpy(&sf_table, rom_table, SF_TABLE_V2_SIZE); } - sf_clz_func = rom_func_lookup(rom_table_code('L', '3')); + sf_clz_func = rom_func_lookup(ROM_FUNC_CLZ32); }