mirror of
https://github.com/espressif/esp-idf.git
synced 2024-09-19 14:26:01 -04:00
Merge branch 'feat/cache_msync_c2m_sliced_ops' into 'master'
cache: supported msync c2m sliced ops Closes IDF-10510 and IDF-10414 See merge request espressif/esp-idf!32155
This commit is contained in:
commit
23ee0b65ff
31
components/esp_mm/Kconfig
Normal file
31
components/esp_mm/Kconfig
Normal file
@ -0,0 +1,31 @@
|
||||
menu "ESP-MM: Memory Management Configurations"
|
||||
|
||||
config ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS
|
||||
depends on SOC_CACHE_WRITEBACK_SUPPORTED
|
||||
bool "Enable esp_cache_msync C2M chunked operation"
|
||||
help
|
||||
`esp_cache_msync` C2M direction takes critical sections, which means during
|
||||
the operation, the interrupts are disabled. Whereas Cache writebacks for
|
||||
large buffers could be especially time intensive, and might cause interrupts
|
||||
to be disabled for a significant amount of time.
|
||||
|
||||
Sometimes you want other ISRs to be responded during this C2M process.
|
||||
This option is to slice one C2M operation into multiple chunks,
|
||||
with CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS_MAX_LEN max len. This will give you
|
||||
a breath during the C2M process as sometimes the C2M process is quite long.
|
||||
|
||||
Note if the buffer processed by the `esp_cache_msync` (C2M sliced) is interrupted by an ISR,
|
||||
and this ISR also accesses this buffer, this may lead to data coherence issue.
|
||||
|
||||
config ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS_MAX_LEN
|
||||
hex "Max len in bytes per C2M chunk"
|
||||
depends on ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS
|
||||
range 0 0x80000
|
||||
default 0x20000 if IDF_TARGET_ESP32P4
|
||||
default 0x2000 if IDF_TARGET_ESP32S2
|
||||
default 0x8000 if IDF_TARGET_ESP32S3
|
||||
help
|
||||
Max len in bytes per C2M chunk, operations with size over the max len will be
|
||||
sliced into multiple chunks.
|
||||
|
||||
endmenu
|
@ -7,9 +7,11 @@
|
||||
#include <sys/param.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "sys/lock.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_rom_caps.h"
|
||||
#include "soc/soc_caps.h"
|
||||
@ -26,6 +28,58 @@ static const char *TAG = "cache";
|
||||
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
DEFINE_CRIT_SECTION_LOCK_STATIC(s_spinlock);
|
||||
#if CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS
|
||||
static _lock_t s_mutex;
|
||||
#endif
|
||||
|
||||
#if SOC_CACHE_WRITEBACK_SUPPORTED
|
||||
static void s_c2m_ops(uint32_t vaddr, size_t size)
|
||||
{
|
||||
#if CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS
|
||||
if (!xPortInIsrContext()) {
|
||||
bool valid = true;
|
||||
size_t offset = 0;
|
||||
while (offset < size) {
|
||||
size_t chunk_len = ((size - offset) > CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS_MAX_LEN) ? CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS_MAX_LEN : (size - offset);
|
||||
esp_os_enter_critical_safe(&s_spinlock);
|
||||
valid &= cache_hal_writeback_addr(vaddr + offset, chunk_len);
|
||||
esp_os_exit_critical_safe(&s_spinlock);
|
||||
offset += chunk_len;
|
||||
}
|
||||
assert(valid);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
bool valid = false;
|
||||
esp_os_enter_critical_safe(&s_spinlock);
|
||||
valid = cache_hal_writeback_addr(vaddr, size);
|
||||
esp_os_exit_critical_safe(&s_spinlock);
|
||||
assert(valid);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//no ops if ISR context or critical section context
|
||||
static void s_acquire_mutex_from_task_context(void)
|
||||
{
|
||||
#if CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS
|
||||
if (xPortCanYield()) {
|
||||
_lock_acquire(&s_mutex);
|
||||
ESP_LOGD(TAG, "mutex is taken");
|
||||
}
|
||||
#endif //#if CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS
|
||||
}
|
||||
|
||||
//no ops if ISR context or critical section context
|
||||
static void s_release_mutex_from_task_context(void)
|
||||
{
|
||||
#if CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS
|
||||
if (xPortCanYield()) {
|
||||
_lock_release(&s_mutex);
|
||||
ESP_LOGD(TAG, "mutex is free");
|
||||
}
|
||||
#endif //#if CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_msync(void *addr, size_t size, int flags)
|
||||
{
|
||||
@ -57,6 +111,7 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags)
|
||||
ESP_RETURN_ON_FALSE_ISR(aligned_addr, ESP_ERR_INVALID_ARG, TAG, "start address: 0x%" PRIx32 ", or the size: 0x%" PRIx32 " is(are) not aligned with cache line size (0x%" PRIx32 ")B", (uint32_t)addr, (uint32_t)size, cache_line_size);
|
||||
}
|
||||
|
||||
s_acquire_mutex_from_task_context();
|
||||
if (flags & ESP_CACHE_MSYNC_FLAG_DIR_M2C) {
|
||||
ESP_EARLY_LOGV(TAG, "M2C DIR");
|
||||
|
||||
@ -76,11 +131,7 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags)
|
||||
}
|
||||
|
||||
#if SOC_CACHE_WRITEBACK_SUPPORTED
|
||||
|
||||
esp_os_enter_critical_safe(&s_spinlock);
|
||||
valid = cache_hal_writeback_addr(vaddr, size);
|
||||
esp_os_exit_critical_safe(&s_spinlock);
|
||||
assert(valid);
|
||||
s_c2m_ops(vaddr, size);
|
||||
|
||||
if (flags & ESP_CACHE_MSYNC_FLAG_INVALIDATE) {
|
||||
esp_os_enter_critical_safe(&s_spinlock);
|
||||
@ -88,8 +139,9 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags)
|
||||
esp_os_exit_critical_safe(&s_spinlock);
|
||||
}
|
||||
assert(valid);
|
||||
#endif
|
||||
#endif //#if SOC_CACHE_WRITEBACK_SUPPORTED
|
||||
}
|
||||
s_release_mutex_from_task_context();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ const static char *TAG = "cache_utils";
|
||||
esp_err_t test_set_buffer_dirty(intptr_t vaddr_start, size_t size)
|
||||
{
|
||||
if (((vaddr_start % 32) != 0) || ((size % 32) != 0)) {
|
||||
ESP_LOGE(TAG, "addr not 4B aligned");
|
||||
ESP_LOGE(TAG, "addr or size not 4B aligned");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
@ -33,12 +33,14 @@ const static char *TAG = "CACHE_TEST";
|
||||
#define TEST_OFFSET 0x100000
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#define TEST_SYNC_START (SOC_DPORT_CACHE_ADDRESS_LOW + TEST_OFFSET)
|
||||
#define TEST_SYNC_SIZE CONFIG_ESP32S2_DATA_CACHE_SIZE
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define TEST_SYNC_START (SOC_DRAM0_CACHE_ADDRESS_LOW + TEST_OFFSET)
|
||||
#define TEST_SYNC_SIZE CONFIG_ESP32S3_DATA_CACHE_SIZE
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
#define TEST_SYNC_START (SOC_DRAM_PSRAM_ADDRESS_LOW + TEST_OFFSET)
|
||||
#define TEST_SYNC_SIZE CONFIG_CACHE_L2_CACHE_SIZE
|
||||
#endif
|
||||
#define TEST_SYNC_SIZE 0x8000
|
||||
|
||||
#define RECORD_TIME_PREPARE() uint32_t __t1, __t2
|
||||
#define RECORD_TIME_START() do {__t1 = esp_cpu_get_cycle_count();} while(0)
|
||||
|
@ -15,20 +15,6 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "ld.common"
|
||||
|
||||
#ifdef CONFIG_ESP32S2_INSTRUCTION_CACHE_8KB
|
||||
#define CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE 0x2000
|
||||
#else
|
||||
#define CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE 0x4000
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S2_DATA_CACHE_0KB
|
||||
#define CONFIG_ESP32S2_DATA_CACHE_SIZE 0
|
||||
#elif defined CONFIG_ESP32S2_DATA_CACHE_8KB
|
||||
#define CONFIG_ESP32S2_DATA_CACHE_SIZE 0x2000
|
||||
#else
|
||||
#define CONFIG_ESP32S2_DATA_CACHE_SIZE 0x4000
|
||||
#endif
|
||||
|
||||
#define RAM_IRAM_START 0x40020000
|
||||
#define RAM_DRAM_START 0x3FFB0000
|
||||
|
||||
|
@ -14,6 +14,11 @@ menu "Cache config"
|
||||
bool "16KB"
|
||||
endchoice
|
||||
|
||||
config ESP32S2_INSTRUCTION_CACHE_SIZE
|
||||
hex
|
||||
default 0x2000 if ESP32S2_INSTRUCTION_CACHE_8KB
|
||||
default 0x4000 if ESP32S2_INSTRUCTION_CACHE_16KB
|
||||
|
||||
choice ESP32S2_INSTRUCTION_CACHE_LINE_SIZE
|
||||
prompt "Instruction cache line size"
|
||||
default ESP32S2_INSTRUCTION_CACHE_LINE_32B
|
||||
@ -43,6 +48,12 @@ menu "Cache config"
|
||||
bool "16KB"
|
||||
endchoice
|
||||
|
||||
config ESP32S2_DATA_CACHE_SIZE
|
||||
hex
|
||||
default 0 if ESP32S2_DATA_CACHE_0KB
|
||||
default 0x2000 if ESP32S2_DATA_CACHE_8KB
|
||||
default 0x4000 if ESP32S2_DATA_CACHE_16KB
|
||||
|
||||
choice ESP32S2_DATA_CACHE_LINE_SIZE
|
||||
prompt "Data cache line size"
|
||||
default ESP32S2_DATA_CACHE_LINE_32B
|
||||
|
Loading…
Reference in New Issue
Block a user