2021-08-05 11:35:07 -04:00
|
|
|
/*
|
|
|
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2016-11-21 04:15:37 -05:00
|
|
|
|
|
|
|
#include "esp_attr.h"
|
|
|
|
#include "soc/cpu.h"
|
|
|
|
#include "soc/soc.h"
|
2020-01-18 21:47:20 -05:00
|
|
|
#include "soc/rtc_periph.h"
|
|
|
|
#include "sdkconfig.h"
|
|
|
|
|
|
|
|
#include "hal/cpu_hal.h"
|
|
|
|
#include "hal/cpu_types.h"
|
2020-11-05 23:00:07 -05:00
|
|
|
#include "hal/mpu_hal.h"
|
2020-01-18 21:47:20 -05:00
|
|
|
|
2021-02-19 07:23:32 -05:00
|
|
|
#include "esp_cpu.h"
|
|
|
|
|
2020-01-18 21:47:20 -05:00
|
|
|
#include "hal/soc_hal.h"
|
2020-02-03 01:58:19 -05:00
|
|
|
#include "soc/soc_caps.h"
|
2020-01-18 21:02:21 -05:00
|
|
|
|
2017-01-06 04:19:09 -05:00
|
|
|
#include "sdkconfig.h"
|
2016-11-21 04:15:37 -05:00
|
|
|
|
|
|
|
void IRAM_ATTR esp_cpu_stall(int cpu_id)
|
|
|
|
{
|
2020-02-03 01:58:19 -05:00
|
|
|
#if SOC_CPU_CORES_NUM > 1
|
2020-01-18 21:47:20 -05:00
|
|
|
soc_hal_stall_core(cpu_id);
|
2020-02-03 01:58:19 -05:00
|
|
|
#endif
|
2016-11-21 04:15:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void IRAM_ATTR esp_cpu_unstall(int cpu_id)
|
|
|
|
{
|
2020-02-03 01:58:19 -05:00
|
|
|
#if SOC_CPU_CORES_NUM > 1
|
2020-01-18 21:47:20 -05:00
|
|
|
soc_hal_unstall_core(cpu_id);
|
2020-02-03 01:58:19 -05:00
|
|
|
#endif
|
2016-11-21 04:15:37 -05:00
|
|
|
}
|
2016-12-06 19:33:24 -05:00
|
|
|
|
esp_restart: fix possible race while stalling other CPU, enable WDT early
Previously esp_restart would stall the other CPU before enabling RTC_WDT.
If the other CPU was executing an s32c1i instruction, the lock signal
from CPU to the arbiter would still be held after CPU was stalled. If
the CPU running esp_restart would then try to access the same locked
memory pool, it would be stuck, because lock signal would never be
released.
With this change, esp_restart resets the other CPU before stalling it.
Ideally, we would want to reset the CPU and keep it in reset, but the
hardware doesn't have such feature for PRO_CPU (it is possible to hold
APP_CPU in reset using DPORT register). Given that ROM code will not use
s32c1i in the first few hundred cycles, doing reset and then stall seems
to be safe.
In addition to than, RTC_WDT initialization is moved to the beginning of
the function, to prevent possible lock-up if CPU stalling still has any
issue.
2017-10-26 07:11:47 -04:00
|
|
|
void IRAM_ATTR esp_cpu_reset(int cpu_id)
|
|
|
|
{
|
2020-01-18 21:47:20 -05:00
|
|
|
soc_hal_reset_core(cpu_id);
|
esp_restart: fix possible race while stalling other CPU, enable WDT early
Previously esp_restart would stall the other CPU before enabling RTC_WDT.
If the other CPU was executing an s32c1i instruction, the lock signal
from CPU to the arbiter would still be held after CPU was stalled. If
the CPU running esp_restart would then try to access the same locked
memory pool, it would be stuck, because lock signal would never be
released.
With this change, esp_restart resets the other CPU before stalling it.
Ideally, we would want to reset the CPU and keep it in reset, but the
hardware doesn't have such feature for PRO_CPU (it is possible to hold
APP_CPU in reset using DPORT register). Given that ROM code will not use
s32c1i in the first few hundred cycles, doing reset and then stall seems
to be safe.
In addition to than, RTC_WDT initialization is moved to the beginning of
the function, to prevent possible lock-up if CPU stalling still has any
issue.
2017-10-26 07:11:47 -04:00
|
|
|
}
|
|
|
|
|
2021-02-19 07:23:32 -05:00
|
|
|
esp_err_t IRAM_ATTR esp_cpu_set_watchpoint(int no, void *adr, int size, int flags)
|
2016-12-06 19:33:24 -05:00
|
|
|
{
|
2020-01-18 21:47:20 -05:00
|
|
|
watchpoint_trigger_t trigger;
|
2020-01-18 21:02:21 -05:00
|
|
|
|
2023-11-30 02:47:22 -05:00
|
|
|
if (no < 0 || no >= SOC_CPU_WATCHPOINTS_NUM) {
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that the watched region's start address is naturally aligned to the size of the region
|
|
|
|
if ((uint32_t)adr % (uint32_t)size) {
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if size is 2^n, and size is in the range of [1 ... SOC_CPU_WATCHPOINT_SIZE]
|
|
|
|
if (size < 1 || size > SOC_CPU_WATCHPOINT_SIZE || (size & (size - 1)) != 0) {
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
2020-01-18 21:47:20 -05:00
|
|
|
switch (flags)
|
|
|
|
{
|
|
|
|
case ESP_WATCHPOINT_LOAD:
|
|
|
|
trigger = WATCHPOINT_TRIGGER_ON_RO;
|
|
|
|
break;
|
|
|
|
case ESP_WATCHPOINT_STORE:
|
|
|
|
trigger = WATCHPOINT_TRIGGER_ON_WO;
|
|
|
|
break;
|
|
|
|
case ESP_WATCHPOINT_ACCESS:
|
|
|
|
trigger = WATCHPOINT_TRIGGER_ON_RW;
|
|
|
|
break;
|
|
|
|
default:
|
2020-01-18 21:02:21 -05:00
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
2020-02-20 22:27:14 -05:00
|
|
|
cpu_hal_set_watchpoint(no, adr, size, trigger);
|
|
|
|
return ESP_OK;
|
2020-01-18 21:02:21 -05:00
|
|
|
}
|
|
|
|
|
2021-02-19 07:23:32 -05:00
|
|
|
void IRAM_ATTR esp_cpu_clear_watchpoint(int no)
|
2020-01-18 21:02:21 -05:00
|
|
|
{
|
2020-01-18 21:47:20 -05:00
|
|
|
cpu_hal_clear_watchpoint(no);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IRAM_ATTR esp_cpu_in_ocd_debug_mode(void)
|
|
|
|
{
|
2020-11-26 00:10:21 -05:00
|
|
|
#if CONFIG_ESP32_DEBUG_OCDAWARE || \
|
|
|
|
CONFIG_ESP32S2_DEBUG_OCDAWARE || \
|
|
|
|
CONFIG_ESP32S3_DEBUG_OCDAWARE || \
|
2021-06-10 03:22:43 -04:00
|
|
|
CONFIG_ESP32C3_DEBUG_OCDAWARE || \
|
|
|
|
CONFIG_ESP32H2_DEBUG_OCDAWARE
|
2020-01-18 21:47:20 -05:00
|
|
|
return cpu_ll_is_debugger_attached();
|
|
|
|
#else
|
|
|
|
return false; // Always return false if "OCD aware" is disabled
|
|
|
|
#endif
|
2020-01-18 21:02:21 -05:00
|
|
|
}
|
|
|
|
|
2020-11-05 23:00:07 -05:00
|
|
|
#if __XTENSA__
|
|
|
|
|
|
|
|
void esp_cpu_configure_region_protection(void)
|
|
|
|
{
|
|
|
|
/* Note: currently this is configured the same on all Xtensa targets
|
|
|
|
*
|
|
|
|
* Both chips have the address space divided into 8 regions, 512MB each.
|
|
|
|
*/
|
|
|
|
const int illegal_regions[] = {0, 4, 5, 6, 7}; // 0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000
|
2020-11-16 23:48:35 -05:00
|
|
|
for (size_t i = 0; i < sizeof(illegal_regions) / sizeof(illegal_regions[0]); ++i) {
|
2020-11-05 23:00:07 -05:00
|
|
|
mpu_hal_set_region_access(illegal_regions[i], MPU_REGION_ILLEGAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
mpu_hal_set_region_access(1, MPU_REGION_RW); // 0x20000000
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|