diff --git a/arch/Kconfig b/arch/Kconfig index 7622620c317..ec355fffdf8 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -430,6 +430,18 @@ config ARCH_HAVE_TEXT_HEAP ---help--- Special memory region for dynamic code loading +config ARCH_TEXT_HEAP_SEPARATE_DATA_ADDRESS + bool + default n + ---help--- + Textheap might have separate instruction/data mappings + +config ARCH_TEXT_HEAP_WORD_ALIGNED_READ + bool + default n + ---help--- + Loads from the instruction mapping of textheap need to be word-aligned + config ARCH_HAVE_DATA_HEAP bool default n diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index c49349b6ec4..53dab1c2909 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -84,6 +84,8 @@ config ARCH_CHIP_ESP32S3 select ARCH_HAVE_MULTICPU select ARCH_HAVE_RESET select ARCH_HAVE_TEXT_HEAP + select ARCH_TEXT_HEAP_SEPARATE_DATA_ADDRESS + select ARCH_TEXT_HEAP_WORD_ALIGNED_READ select ARCH_HAVE_TESTSET select ARCH_VECNOTIRQ select LIBC_PREVENT_STRING_KERNEL diff --git a/arch/xtensa/src/esp32s3/esp32s3_textheap.c b/arch/xtensa/src/esp32s3/esp32s3_textheap.c index a7551ede73f..4ea19168e6b 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_textheap.c +++ b/arch/xtensa/src/esp32s3/esp32s3_textheap.c @@ -31,11 +31,13 @@ #include #include +#include "hal/cache_hal.h" #include "hardware/esp32s3_soc.h" #ifdef CONFIG_ESP32S3_RTC_HEAP # include "esp32s3_rtcheap.h" #endif +#include "esp32s3_spiram.h" /**************************************************************************** * Pre-processor Definitions @@ -45,6 +47,9 @@ #error "No suitable heap available. Enable ESP32S3_RTC_HEAP." #endif +#define EXTRAM_INSTRUCTION_BUS_LOW 0x42000000 +#define EXTRAM_INSTRUCTION_BUS_HIGH 0x44000000 + #define EXTRAM_D_I_BUS_OFFSET 0x6000000 /**************************************************************************** @@ -134,19 +139,7 @@ void up_textheap_free(void *p) else #endif { - uintptr_t addr = (uintptr_t)p; - if (SOC_DIRAM_IRAM_LOW <= addr && addr < SOC_DIRAM_IRAM_HIGH) - { - addr = MAP_IRAM_TO_DRAM(addr); - } - else - { - /* extram */ - - addr -= EXTRAM_D_I_BUS_OFFSET; - } - - p = (void *)addr; + p = up_textheap_data_address(p); kmm_free(p); } } @@ -180,18 +173,63 @@ bool up_textheap_heapmember(void *p) } #endif + p = up_textheap_data_address(p); + return kmm_heapmember(p); +} + +/**************************************************************************** + * Name: up_textheap_data_address + * + * Description: + * If an instruction bus address is specified, return the corresponding + * data bus address. Otherwise, return the given address as it is. + * + * For some platforms, up_textheap_memalign() might return memory regions + * with separate instruction/data bus mappings. In that case, + * up_textheap_memalign() returns the address of the instruction bus + * mapping. + * The instruction bus mapping might provide only limited data access. + * (For example, only read-only, word-aligned access.) + * You can use up_textheap_data_address() to query the corresponding data + * bus mapping. + * + ****************************************************************************/ + +FAR void *up_textheap_data_address(FAR void *p) +{ uintptr_t addr = (uintptr_t)p; if (SOC_DIRAM_IRAM_LOW <= addr && addr < SOC_DIRAM_IRAM_HIGH) { addr = MAP_IRAM_TO_DRAM(addr); } - else + else if (EXTRAM_INSTRUCTION_BUS_LOW <= addr && + addr < EXTRAM_INSTRUCTION_BUS_HIGH) { /* extram */ addr -= EXTRAM_D_I_BUS_OFFSET; } - p = (void *)addr; - return kmm_heapmember(p); + return (FAR void *)addr; +} + +/**************************************************************************** + * Name: up_textheap_data_sync + * + * Description: + * Ensure modifications made on the data bus addresses (the addresses + * returned by up_textheap_data_address) fully visible on the corresponding + * instruction bus addresses. + * + ****************************************************************************/ + +IRAM_ATTR void up_textheap_data_sync(void) +{ + irqstate_t flags = enter_critical_section(); + + esp_spiram_writeback_cache(); + cache_hal_disable(CACHE_TYPE_INSTRUCTION); + cache_hal_enable(CACHE_TYPE_INSTRUCTION); + + leave_critical_section(flags); } diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 385e9223b10..67e8034f70d 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -781,6 +781,50 @@ void up_textheap_free(FAR void *p); bool up_textheap_heapmember(FAR void *p); #endif +/**************************************************************************** + * Name: up_textheap_data_address + * + * Description: + * If an instruction bus address is specified, return the corresponding + * data bus address. Otherwise, return the given address as it is. + * + * For some platforms, up_textheap_memalign() might return memory regions + * with separate instruction/data bus mappings. In that case, + * up_textheap_memalign() returns the address of the instruction bus + * mapping. + * The instruction bus mapping might provide only limited data access. + * (For example, only read-only, word-aligned access.) + * You can use up_textheap_data_address() to query the corresponding data + * bus mapping. + * + ****************************************************************************/ + +#if defined(CONFIG_ARCH_USE_TEXT_HEAP) +#if defined(CONFIG_ARCH_TEXT_HEAP_SEPARATE_DATA_ADDRESS) +FAR void *up_textheap_data_address(FAR void *p); +#else +#define up_textheap_data_address(p) ((FAR void *)p) +#endif +#endif + +/**************************************************************************** + * Name: up_textheap_data_sync + * + * Description: + * Ensure modifications made on the data bus addresses (the addresses + * returned by up_textheap_data_address) fully visible on the corresponding + * instruction bus addresses. + * + ****************************************************************************/ + +#if defined(CONFIG_ARCH_USE_TEXT_HEAP) +#if defined(CONFIG_ARCH_TEXT_HEAP_SEPARATE_DATA_ADDRESS) +void up_textheap_data_sync(void); +#else +#define up_textheap_data_sync() do {} while (0) +#endif +#endif + /**************************************************************************** * Name: up_dataheap_memalign *