mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(cache): supported msync c2m sliced ops
This commit adds sliced C2M ops, when the msync is called in task. This way it gives a breath of the critical section, so that a long C2M operation will not disable interrupts for a long time
This commit is contained in:
parent
42bcb84013
commit
3bfc134a23
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
|
@ -10,6 +10,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "esp_rom_caps.h"
|
#include "esp_rom_caps.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
@ -26,6 +27,36 @@ static const char *TAG = "cache";
|
|||||||
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||||
|
|
||||||
DEFINE_CRIT_SECTION_LOCK_STATIC(s_spinlock);
|
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
|
||||||
|
|
||||||
esp_err_t esp_cache_msync(void *addr, size_t size, int flags)
|
esp_err_t esp_cache_msync(void *addr, size_t size, int flags)
|
||||||
{
|
{
|
||||||
@ -76,11 +107,7 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if SOC_CACHE_WRITEBACK_SUPPORTED
|
#if SOC_CACHE_WRITEBACK_SUPPORTED
|
||||||
|
s_c2m_ops(vaddr, size);
|
||||||
esp_os_enter_critical_safe(&s_spinlock);
|
|
||||||
valid = cache_hal_writeback_addr(vaddr, size);
|
|
||||||
esp_os_exit_critical_safe(&s_spinlock);
|
|
||||||
assert(valid);
|
|
||||||
|
|
||||||
if (flags & ESP_CACHE_MSYNC_FLAG_INVALIDATE) {
|
if (flags & ESP_CACHE_MSYNC_FLAG_INVALIDATE) {
|
||||||
esp_os_enter_critical_safe(&s_spinlock);
|
esp_os_enter_critical_safe(&s_spinlock);
|
||||||
@ -88,7 +115,7 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags)
|
|||||||
esp_os_exit_critical_safe(&s_spinlock);
|
esp_os_exit_critical_safe(&s_spinlock);
|
||||||
}
|
}
|
||||||
assert(valid);
|
assert(valid);
|
||||||
#endif
|
#endif //#if SOC_CACHE_WRITEBACK_SUPPORTED
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
Loading…
Reference in New Issue
Block a user