mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-10-17 02:45:05 +00:00
71 lines
2.4 KiB
C++
71 lines
2.4 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
#include <sdkconfig.h>
|
|
|
|
#ifdef CONFIG_ELF_LOADER_LOAD_PSRAM
|
|
|
|
#include <esp_ipc.h>
|
|
#include <freertos/FreeRTOS.h>
|
|
|
|
#include <atomic>
|
|
|
|
// elf_loader writes back the whole D-cache with the ROM's Cache_WriteBack_All(), which doesn't take
|
|
// esp_cache_msync()'s lock. A cache operation running at the same time on the other core (e.g. a display
|
|
// driver syncing a PSRAM framebuffer) then fails with "Dcache sync parameter configuration error".
|
|
// The write-back therefore runs in core 0's IPC task while core 1 is parked in its own IPC task. An IPC task
|
|
// only runs when its core is not in a critical section, which is where esp_cache_msync() does its work.
|
|
extern "C" {
|
|
|
|
void __real_esp_elf_arch_flush(void);
|
|
void Cache_WriteBack_All(void);
|
|
void spi_flash_disable_interrupts_caches_and_other_cpu(void);
|
|
void spi_flash_enable_interrupts_caches_and_other_cpu(void);
|
|
|
|
}
|
|
|
|
#if !CONFIG_FREERTOS_UNICORE && !CONFIG_IDF_TARGET_ESP32S31
|
|
|
|
namespace {
|
|
|
|
std::atomic<bool> other_core_parked { false };
|
|
std::atomic<bool> other_core_release { false };
|
|
|
|
void IRAM_ATTR park_core(void*) {
|
|
const uint32_t state = portSET_INTERRUPT_MASK_FROM_ISR();
|
|
other_core_parked.store(true, std::memory_order_release);
|
|
while (!other_core_release.load(std::memory_order_acquire)) {
|
|
}
|
|
portCLEAR_INTERRUPT_MASK_FROM_ISR(state);
|
|
}
|
|
|
|
void IRAM_ATTR write_back_with_core1_parked(void*) {
|
|
other_core_parked.store(false, std::memory_order_relaxed);
|
|
other_core_release.store(false, std::memory_order_relaxed);
|
|
esp_ipc_call(1, park_core, nullptr);
|
|
while (!other_core_parked.load(std::memory_order_acquire)) {
|
|
}
|
|
const uint32_t state = portSET_INTERRUPT_MASK_FROM_ISR();
|
|
Cache_WriteBack_All();
|
|
portCLEAR_INTERRUPT_MASK_FROM_ISR(state);
|
|
other_core_release.store(true, std::memory_order_release);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
// IRAM: spi_flash_disable_interrupts_caches_and_other_cpu() returns here with the caches disabled
|
|
extern "C" void IRAM_ATTR __wrap_esp_elf_arch_flush(void) {
|
|
esp_ipc_call_blocking(0, write_back_with_core1_parked, nullptr);
|
|
// Same as elf_loader's own esp_elf_arch_flush() after its write-back
|
|
spi_flash_disable_interrupts_caches_and_other_cpu();
|
|
spi_flash_enable_interrupts_caches_and_other_cpu();
|
|
}
|
|
|
|
#else
|
|
|
|
extern "C" void IRAM_ATTR __wrap_esp_elf_arch_flush(void) {
|
|
__real_esp_elf_arch_flush();
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif // CONFIG_ELF_LOADER_LOAD_PSRAM
|