Skip to content

Commit

Permalink
Merge branch 'feature/support_utilities_in_cpu' into 'master'
Browse files Browse the repository at this point in the history
feat(esp_hw_support): Support utilities in cpu.c

Closes IDF-7848

See merge request espressif/esp-idf!29661
  • Loading branch information
KonstantinKondrashov committed Apr 12, 2024
2 parents 7639933 + 06c28f0 commit e6d153f
Show file tree
Hide file tree
Showing 21 changed files with 437 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .codespellrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[codespell]
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling
write-changes = true
104 changes: 9 additions & 95 deletions components/esp_hw_support/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,142 +9,56 @@
#include <assert.h>
#include "soc/soc.h"
#include "soc/soc_caps.h"

// TODO: IDF-5645
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61
#include "soc/lp_aon_reg.h"
#include "soc/pcr_reg.h"
#define SYSTEM_CPU_PER_CONF_REG PCR_CPU_WAITI_CONF_REG
#define SYSTEM_CPU_WAIT_MODE_FORCE_ON PCR_CPU_WAIT_MODE_FORCE_ON
#elif CONFIG_IDF_TARGET_ESP32P4
#include "soc/lp_clkrst_reg.h"
#include "soc/pmu_reg.h"
#else
#include "soc/rtc_cntl_reg.h"
#endif

#include "hal/soc_hal.h"
#include "hal/cpu_utility_ll.h"
#include "esp_bit_defs.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_cpu.h"
#if __XTENSA__
#include "xtensa/config/core-isa.h"
#else
#include "soc/system_reg.h" // For SYSTEM_CPU_PER_CONF_REG
#include "soc/dport_access.h" // For Dport access
#else // __riscv
#include "riscv/semihosting.h"
#endif
#if SOC_CPU_HAS_FLEXIBLE_INTC
#include "riscv/instruction_decode.h"
#endif

#endif // __riscv

/* --------------------------------------------------- CPU Control -----------------------------------------------------
*
* ------------------------------------------------------------------------------------------------------------------ */

void esp_cpu_stall(int core_id)
{
assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
#if SOC_CPU_CORES_NUM > 1 // We don't allow stalling of the current core
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7848
if (core_id == 0) {
REG_SET_FIELD(PMU_CPU_SW_STALL_REG, PMU_HPCORE0_SW_STALL_CODE, 0x86);
} else {
REG_SET_FIELD(PMU_CPU_SW_STALL_REG, PMU_HPCORE1_SW_STALL_CODE, 0x86);
}
#else
/*
We need to write the value "0x86" to stall a particular core. The write location is split into two separate
bit fields named "c0" and "c1", and the two fields are located in different registers. Each core has its own pair of
"c0" and "c1" bit fields.
Note: This function can be called when the cache is disabled. We use "ternary if" instead of an array so that the
"rodata" of the register masks/shifts will be stored in this function's "rodata" section, instead of the source
file's "rodata" section (see IDF-5214).
*/
int rtc_cntl_c0_m = (core_id == 0) ? RTC_CNTL_SW_STALL_PROCPU_C0_M : RTC_CNTL_SW_STALL_APPCPU_C0_M;
int rtc_cntl_c0_s = (core_id == 0) ? RTC_CNTL_SW_STALL_PROCPU_C0_S : RTC_CNTL_SW_STALL_APPCPU_C0_S;
int rtc_cntl_c1_m = (core_id == 0) ? RTC_CNTL_SW_STALL_PROCPU_C1_M : RTC_CNTL_SW_STALL_APPCPU_C1_M;
int rtc_cntl_c1_s = (core_id == 0) ? RTC_CNTL_SW_STALL_PROCPU_C1_S : RTC_CNTL_SW_STALL_APPCPU_C1_S;
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_c0_m);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2 << rtc_cntl_c0_s);
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1_m);
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21 << rtc_cntl_c1_s);
#endif // CONFIG_IDF_TARGET_ESP32P4
assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
cpu_utility_ll_stall_cpu(core_id);
#endif // SOC_CPU_CORES_NUM > 1
}

void esp_cpu_unstall(int core_id)
{
assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
#if SOC_CPU_CORES_NUM > 1 // We don't allow stalling of the current core
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7848
int pmu_core_stall_mask = (core_id == 0) ? PMU_HPCORE0_SW_STALL_CODE_M : PMU_HPCORE1_SW_STALL_CODE_M;
CLEAR_PERI_REG_MASK(PMU_CPU_SW_STALL_REG, pmu_core_stall_mask);
#else
/*
We need to write clear the value "0x86" to uninstall a particular core. The location of this value is split into
two separate bit fields named "c0" and "c1", and the two fields are located in different registers. Each core has
its own pair of "c0" and "c1" bit fields.
Note: This function can be called when the cache is disabled. We use "ternary if" instead of an array so that the
"rodata" of the register masks/shifts will be stored in this function's "rodata" section, instead of the source
file's "rodata" section (see IDF-5214).
*/
int rtc_cntl_c0_m = (core_id == 0) ? RTC_CNTL_SW_STALL_PROCPU_C0_M : RTC_CNTL_SW_STALL_APPCPU_C0_M;
int rtc_cntl_c1_m = (core_id == 0) ? RTC_CNTL_SW_STALL_PROCPU_C1_M : RTC_CNTL_SW_STALL_APPCPU_C1_M;
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_c0_m);
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1_m);
#endif // CONFIG_IDF_TARGET_ESP32P4
assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
cpu_utility_ll_unstall_cpu(core_id);
#endif // SOC_CPU_CORES_NUM > 1
}

void esp_cpu_reset(int core_id)
{
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7848
if (core_id == 0)
REG_SET_BIT(LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE0_SW_RESET);
else
REG_SET_BIT(LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE1_SW_RESET);
#else
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 // TODO: IDF-5645
SET_PERI_REG_MASK(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET);
#else
assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
#if SOC_CPU_CORES_NUM > 1
/*
Note: This function can be called when the cache is disabled. We use "ternary if" instead of an array so that the
"rodata" of the register masks/shifts will be stored in this function's "rodata" section, instead of the source
file's "rodata" section (see IDF-5214).
*/
int rtc_cntl_rst_m = (core_id == 0) ? RTC_CNTL_SW_PROCPU_RST_M : RTC_CNTL_SW_APPCPU_RST_M;
#else // SOC_CPU_CORES_NUM > 1
int rtc_cntl_rst_m = RTC_CNTL_SW_PROCPU_RST_M;
#endif // SOC_CPU_CORES_NUM > 1
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_rst_m);
#endif
#endif // CONFIG_IDF_TARGET_ESP32P4
cpu_utility_ll_reset_cpu(core_id);
}

void esp_cpu_wait_for_intr(void)
{
#if __XTENSA__
xt_utils_wait_for_intr();
#else
//TODO: IDF-7848
#if !CONFIG_IDF_TARGET_ESP32P4
// TODO: IDF-5645 (better to implement with ll) C6 register names converted in the #include section at the top
if (esp_cpu_dbgr_is_attached() && DPORT_REG_GET_BIT(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPU_WAIT_MODE_FORCE_ON) == 0) {
if (esp_cpu_dbgr_is_attached() && cpu_utility_ll_wait_mode() == 0) {
/* when SYSTEM_CPU_WAIT_MODE_FORCE_ON is disabled in WFI mode SBA access to memory does not work for debugger,
so do not enter that mode when debugger is connected */
return;
}
#endif
rv_utils_wait_for_intr();
#endif // __XTENSA__
}
Expand Down
70 changes: 70 additions & 0 deletions components/hal/esp32/include/hal/cpu_utility_ll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_attr.h"

#ifdef __cplusplus
extern "C" {
#endif

FORCE_INLINE_ATTR void cpu_utility_ll_reset_cpu(uint32_t cpu_no)
{
/*
Note: This function can be called when the cache is disabled. We use "ternary if" instead of an array so that the
"rodata" of the register masks/shifts will be stored in this function's "rodata" section, instead of the source
file's "rodata" section (see IDF-5214).
*/
uint32_t rtc_cntl_rst = (cpu_no == 0) ? RTC_CNTL_SW_PROCPU_RST_M : RTC_CNTL_SW_APPCPU_RST_M;
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_rst);
}

#if SOC_CPU_CORES_NUM > 1 // We only allow stalling/unstalling of other cores
FORCE_INLINE_ATTR void cpu_utility_ll_stall_cpu(uint32_t cpu_no)
{
/*
We need to write the value "0x86" to stall a particular core. The write location is split into two separate
bit fields named "c0" and "c1", and the two fields are located in different registers. Each core has its own pair of
"c0" and "c1" bit fields.
Note: This function can be called when the cache is disabled. We use "ternary if" instead of an array so that the
"rodata" of the register masks/shifts will be stored in this function's "rodata" section, instead of the source
file's "rodata" section (see IDF-5214).
*/
uint32_t rtc_cntl_c0_m = (cpu_no == 0) ? RTC_CNTL_SW_STALL_PROCPU_C0_M : RTC_CNTL_SW_STALL_APPCPU_C0_M;
uint32_t rtc_cntl_c0_s = (cpu_no == 0) ? RTC_CNTL_SW_STALL_PROCPU_C0_S : RTC_CNTL_SW_STALL_APPCPU_C0_S;
uint32_t rtc_cntl_c1_m = (cpu_no == 0) ? RTC_CNTL_SW_STALL_PROCPU_C1_M : RTC_CNTL_SW_STALL_APPCPU_C1_M;
uint32_t rtc_cntl_c1_s = (cpu_no == 0) ? RTC_CNTL_SW_STALL_PROCPU_C1_S : RTC_CNTL_SW_STALL_APPCPU_C1_S;
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_c0_m);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2 << rtc_cntl_c0_s);
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1_m);
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21 << rtc_cntl_c1_s);
}

FORCE_INLINE_ATTR void cpu_utility_ll_unstall_cpu(uint32_t cpu_no)
{
/*
We need to write clear the value "0x86" to unstall a particular core. The location of this value is split into
two separate bit fields named "c0" and "c1", and the two fields are located in different registers. Each core has
its own pair of "c0" and "c1" bit fields.
Note: This function can be called when the cache is disabled. We use "ternary if" instead of an array so that the
"rodata" of the register masks/shifts will be stored in this function's "rodata" section, instead of the source
file's "rodata" section (see IDF-5214).
*/
uint32_t rtc_cntl_c0 = (cpu_no == 0) ? RTC_CNTL_SW_STALL_PROCPU_C0_M : RTC_CNTL_SW_STALL_APPCPU_C0_M;
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_c0);
int rtc_cntl_c1 = (cpu_no == 0) ? RTC_CNTL_SW_STALL_PROCPU_C1_M : RTC_CNTL_SW_STALL_APPCPU_C1_M;
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1);
}
#endif // SOC_CPU_CORES_NUM > 1

#ifdef __cplusplus
}
#endif
30 changes: 30 additions & 0 deletions components/hal/esp32c2/include/hal/cpu_utility_ll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/system_reg.h"
#include "esp_attr.h"

#ifdef __cplusplus
extern "C" {
#endif

FORCE_INLINE_ATTR void cpu_utility_ll_reset_cpu(uint32_t cpu_no)
{
(void) cpu_no;
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST);
}

FORCE_INLINE_ATTR uint32_t cpu_utility_ll_wait_mode(void)
{
return REG_GET_BIT(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPU_WAIT_MODE_FORCE_ON);
}

#ifdef __cplusplus
}
#endif
30 changes: 30 additions & 0 deletions components/hal/esp32c3/include/hal/cpu_utility_ll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/system_reg.h"
#include "esp_attr.h"

#ifdef __cplusplus
extern "C" {
#endif

FORCE_INLINE_ATTR void cpu_utility_ll_reset_cpu(uint32_t cpu_no)
{
(void) cpu_no;
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST);
}

FORCE_INLINE_ATTR uint32_t cpu_utility_ll_wait_mode(void)
{
return REG_GET_BIT(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPU_WAIT_MODE_FORCE_ON);
}

#ifdef __cplusplus
}
#endif
30 changes: 30 additions & 0 deletions components/hal/esp32c5/include/hal/cpu_utility_ll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once
#include "soc/soc.h"
#include "soc/lp_aon_reg.h"
#include "soc/pcr_reg.h"
#include "esp_attr.h"

#ifdef __cplusplus
extern "C" {
#endif

FORCE_INLINE_ATTR void cpu_utility_ll_reset_cpu(uint32_t cpu_no)
{
(void) cpu_no;
SET_PERI_REG_MASK(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET);
}

FORCE_INLINE_ATTR uint32_t cpu_utility_ll_wait_mode(void)
{
return REG_GET_BIT(PCR_CPU_WAITI_CONF_REG, PCR_CPU_WAIT_MODE_FORCE_ON);
}

#ifdef __cplusplus
}
#endif
30 changes: 30 additions & 0 deletions components/hal/esp32c6/include/hal/cpu_utility_ll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once
#include "soc/soc.h"
#include "soc/lp_aon_reg.h"
#include "soc/pcr_reg.h"
#include "esp_attr.h"

#ifdef __cplusplus
extern "C" {
#endif

FORCE_INLINE_ATTR void cpu_utility_ll_reset_cpu(uint32_t cpu_no)
{
(void) cpu_no;
SET_PERI_REG_MASK(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET);
}

FORCE_INLINE_ATTR uint32_t cpu_utility_ll_wait_mode(void)
{
return REG_GET_BIT(PCR_CPU_WAITI_CONF_REG, PCR_CPU_WAIT_MODE_FORCE_ON);
}

#ifdef __cplusplus
}
#endif
30 changes: 30 additions & 0 deletions components/hal/esp32c61/include/hal/cpu_utility_ll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once
#include "soc/soc.h"
#include "soc/lp_aon_reg.h"
#include "soc/pcr_reg.h"
#include "esp_attr.h"

#ifdef __cplusplus
extern "C" {
#endif

FORCE_INLINE_ATTR void cpu_utility_ll_reset_cpu(uint32_t cpu_no)
{
(void) cpu_no;
SET_PERI_REG_MASK(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET);
}

FORCE_INLINE_ATTR uint32_t cpu_utility_ll_wait_mode(void)
{
return REG_GET_BIT(PCR_CPU_WAITI_CONF_REG, PCR_CPU_WAIT_MODE_FORCE_ON);
}

#ifdef __cplusplus
}
#endif
Loading

0 comments on commit e6d153f

Please sign in to comment.