mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
esp_system: Fix esp_cpu_compare_and_set()
This commit fixes esp_cpu_compare_and_set() in the following ways - Removed call to esp_ptr_external_ram() as it incurred > 80 CPU cycles (due to multiple nested function calls, and those functions not being in IRAM). We now check manually if the pointer is in external RAM for increased speed. - Fixed infinite wait when attempting to get the external_ram_cas_lock. The function should return immediatley if any part of the compare and set call fails. - The preprocessor conditions of esp_cpu_compare_and_set() to depend on CONFIG_SPIRAM instead of SOC_SPIRAM_SUPPORTED. Even if the target supports SPIRAM, we only need the external RAM compare and set feature if SPIRAM is enabled. Also fixed incorrect inclusion of esp_intr_alloc.h in esp_cpu.h
This commit is contained in:
parent
36f49f361c
commit
64117a0c59
@ -620,7 +620,7 @@ esp_err_t esp_cpu_clear_watchpoint(int wp_num)
|
||||
*
|
||||
* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
#if __XTENSA__ && XCHAL_HAVE_S32C1I && SOC_SPIRAM_SUPPORTED
|
||||
#if __XTENSA__ && XCHAL_HAVE_S32C1I && CONFIG_SPIRAM
|
||||
static DRAM_ATTR uint32_t external_ram_cas_lock = 0;
|
||||
#endif
|
||||
|
||||
@ -628,35 +628,39 @@ bool esp_cpu_compare_and_set(volatile uint32_t *addr, uint32_t compare_value, ui
|
||||
{
|
||||
#if __XTENSA__
|
||||
bool ret;
|
||||
#if XCHAL_HAVE_S32C1I && SOC_SPIRAM_SUPPORTED
|
||||
if (esp_ptr_external_ram((const void *)addr)) {
|
||||
#if XCHAL_HAVE_S32C1I && CONFIG_SPIRAM
|
||||
// Check if the target address is in external RAM
|
||||
if ((uint32_t)addr >= SOC_EXTRAM_DATA_LOW && (uint32_t)addr < SOC_EXTRAM_DATA_HIGH) {
|
||||
/* The target address is in external RAM, thus the native CAS instruction cannot be used. Instead, we achieve
|
||||
atomicity by disabling interrupts and then acquiring an external RAM CAS lock. */
|
||||
uint32_t intr_level;
|
||||
// Atomicity is achieved by disabling interrupts then acquiring a an external RAM CAS lock
|
||||
__asm__ __volatile__ ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) "\n"
|
||||
: "=r"(intr_level));
|
||||
while (!xt_utils_compare_and_set(&external_ram_cas_lock, 0, 1)) {
|
||||
;
|
||||
if (!xt_utils_compare_and_set(&external_ram_cas_lock, 0, 1)) {
|
||||
// External RAM CAS lock already taken. Exit
|
||||
ret = false;
|
||||
goto exit;
|
||||
}
|
||||
// Now we compare and set the target address
|
||||
uint32_t old_value;
|
||||
old_value = *addr;
|
||||
if (old_value == compare_value) {
|
||||
ret = (*addr == compare_value);
|
||||
if (ret) {
|
||||
*addr = new_value;
|
||||
}
|
||||
// Release the external RAM CAS lock and reenable interrupts
|
||||
// Release the external RAM CAS lock
|
||||
external_ram_cas_lock = 0;
|
||||
exit:
|
||||
// Reenable interrupts
|
||||
__asm__ __volatile__ ("memw \n"
|
||||
"wsr %0, ps\n"
|
||||
:: "r"(intr_level));
|
||||
|
||||
ret = (old_value == compare_value);
|
||||
} else
|
||||
#endif //XCHAL_HAVE_S32C1I && SOC_SPIRAM_SUPPORTED
|
||||
#endif // XCHAL_HAVE_S32C1I && CONFIG_SPIRAM
|
||||
{
|
||||
// The target address is in internal RAM. Use the CPU's native CAS instruction
|
||||
ret = xt_utils_compare_and_set(addr, compare_value, new_value);
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
#else // __XTENSA__
|
||||
// Single core targets don't have atomic CAS instruction. So access method is the same for internal and external RAM
|
||||
return rv_utils_compare_and_set(addr, compare_value, new_value);
|
||||
#endif
|
||||
|
@ -17,6 +17,7 @@
|
||||
#elif __riscv
|
||||
#include "riscv/rv_utils.h"
|
||||
#endif
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
x
Reference in New Issue
Block a user