mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
ulp: refactor ulp component
This commit refactors the ulp component. Files are now divided based on type of ulp, viz., fsm or risc-v. Files common to both are maintained in the ulp_common folder. This commit also adds menuconfig options for ULP within the ulp component instead of presenting target specific configuations for ulp.
This commit is contained in:
parent
0ac6a105ef
commit
2fc9bd61bf
@ -500,28 +500,6 @@ menu "ESP32-specific"
|
|||||||
default 0x4000 if ESP32_MEMMAP_TRACEMEM && !ESP32_MEMMAP_TRACEMEM_TWOBANKS
|
default 0x4000 if ESP32_MEMMAP_TRACEMEM && !ESP32_MEMMAP_TRACEMEM_TWOBANKS
|
||||||
default 0x0
|
default 0x0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
config ESP32_ULP_COPROC_ENABLED
|
|
||||||
bool "Enable Ultra Low Power (ULP) Coprocessor"
|
|
||||||
default "n"
|
|
||||||
help
|
|
||||||
Set to 'y' if you plan to load a firmware for the coprocessor.
|
|
||||||
|
|
||||||
If this option is enabled, further coprocessor configuration will appear in the Components menu.
|
|
||||||
|
|
||||||
config ESP32_ULP_COPROC_RESERVE_MEM
|
|
||||||
int
|
|
||||||
prompt "RTC slow memory reserved for coprocessor" if ESP32_ULP_COPROC_ENABLED
|
|
||||||
default 512 if ESP32_ULP_COPROC_ENABLED
|
|
||||||
range 32 8176 if ESP32_ULP_COPROC_ENABLED
|
|
||||||
default 0 if !ESP32_ULP_COPROC_ENABLED
|
|
||||||
range 0 0 if !ESP32_ULP_COPROC_ENABLED
|
|
||||||
help
|
|
||||||
Bytes of memory to reserve for ULP coprocessor firmware & data.
|
|
||||||
|
|
||||||
Data is reserved at the beginning of RTC slow memory.
|
|
||||||
|
|
||||||
config ESP32_DEBUG_OCDAWARE
|
config ESP32_DEBUG_OCDAWARE
|
||||||
bool "Make exception and panic handlers JTAG/OCD aware"
|
bool "Make exception and panic handlers JTAG/OCD aware"
|
||||||
default y
|
default y
|
||||||
|
@ -15,8 +15,8 @@ CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 CONFIG_ESP32_RTC_CLK_SRC
|
|||||||
CONFIG_DISABLE_BASIC_ROM_CONSOLE CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE
|
CONFIG_DISABLE_BASIC_ROM_CONSOLE CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE
|
||||||
CONFIG_NO_BLOBS CONFIG_ESP32_NO_BLOBS
|
CONFIG_NO_BLOBS CONFIG_ESP32_NO_BLOBS
|
||||||
CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS
|
CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS
|
||||||
CONFIG_ULP_COPROC_ENABLED CONFIG_ESP32_ULP_COPROC_ENABLED
|
CONFIG_ESP32_ULP_COPROC_ENABLED CONFIG_ULP_COPROC_ENABLED
|
||||||
CONFIG_ULP_COPROC_RESERVE_MEM CONFIG_ESP32_ULP_COPROC_RESERVE_MEM
|
CONFIG_ESP32_ULP_COPROC_RESERVE_MEM CONFIG_ULP_COPROC_RESERVE_MEM
|
||||||
CONFIG_BROWNOUT_DET CONFIG_ESP32_BROWNOUT_DET
|
CONFIG_BROWNOUT_DET CONFIG_ESP32_BROWNOUT_DET
|
||||||
CONFIG_BROWNOUT_DET_LVL_SEL CONFIG_ESP32_BROWNOUT_DET_LVL_SEL
|
CONFIG_BROWNOUT_DET_LVL_SEL CONFIG_ESP32_BROWNOUT_DET_LVL_SEL
|
||||||
CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0
|
CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0
|
||||||
|
@ -220,34 +220,6 @@ menu "ESP32S2-specific"
|
|||||||
default 0x4000 if ESP32S2_MEMMAP_TRACEMEM && !ESP32S2_MEMMAP_TRACEMEM_TWOBANKS
|
default 0x4000 if ESP32S2_MEMMAP_TRACEMEM && !ESP32S2_MEMMAP_TRACEMEM_TWOBANKS
|
||||||
default 0x0
|
default 0x0
|
||||||
|
|
||||||
|
|
||||||
config ESP32S2_ULP_COPROC_ENABLED
|
|
||||||
bool "Enable Ultra Low Power (ULP) Coprocessor"
|
|
||||||
default "n"
|
|
||||||
help
|
|
||||||
Set to 'y' if you plan to load a firmware for the coprocessor.
|
|
||||||
|
|
||||||
If this option is enabled, further coprocessor configuration will appear in the Components menu.
|
|
||||||
|
|
||||||
config ESP32S2_ULP_COPROC_RESERVE_MEM
|
|
||||||
int
|
|
||||||
prompt "RTC slow memory reserved for coprocessor" if ESP32S2_ULP_COPROC_ENABLED
|
|
||||||
default 2048 if ESP32S2_ULP_COPROC_ENABLED
|
|
||||||
range 32 8176 if ESP32S2_ULP_COPROC_ENABLED
|
|
||||||
default 0 if !ESP32S2_ULP_COPROC_ENABLED
|
|
||||||
range 0 0 if !ESP32S2_ULP_COPROC_ENABLED
|
|
||||||
help
|
|
||||||
Bytes of memory to reserve for ULP coprocessor firmware & data.
|
|
||||||
|
|
||||||
Data is reserved at the beginning of RTC slow memory.
|
|
||||||
|
|
||||||
config ESP32S2_ULP_COPROC_RISCV
|
|
||||||
bool "Enable RISC-V as ULP coprocessor"
|
|
||||||
depends on ESP32S2_ULP_COPROC_ENABLED
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Set this to y to use the RISC-V coprocessor instead of the FSM-ULP.
|
|
||||||
|
|
||||||
config ESP32S2_DEBUG_OCDAWARE
|
config ESP32S2_DEBUG_OCDAWARE
|
||||||
bool "Make exception and panic handlers JTAG/OCD aware"
|
bool "Make exception and panic handlers JTAG/OCD aware"
|
||||||
default y
|
default y
|
||||||
|
7
components/esp32s2/sdkconfig.rename
Normal file
7
components/esp32s2/sdkconfig.rename
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# sdkconfig replacement configurations for deprecated options formatted as
|
||||||
|
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
|
||||||
|
|
||||||
|
# ESP32-S2 specific
|
||||||
|
CONFIG_ESP32S2_ULP_COPROC_ENABLED CONFIG_ULP_COPROC_ENABLED
|
||||||
|
CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM CONFIG_ULP_COPROC_RESERVE_MEM
|
||||||
|
CONFIG_ESP32S2_ULP_COPROC_RISCV CONFIG_ULP_COPROC_TYPE_RISCV
|
@ -306,34 +306,6 @@ menu "ESP32S3-Specific"
|
|||||||
default 0x4000 if ESP32S3_MEMMAP_TRACEMEM && !ESP32S3_MEMMAP_TRACEMEM_TWOBANKS
|
default 0x4000 if ESP32S3_MEMMAP_TRACEMEM && !ESP32S3_MEMMAP_TRACEMEM_TWOBANKS
|
||||||
default 0x0
|
default 0x0
|
||||||
|
|
||||||
|
|
||||||
config ESP32S3_ULP_COPROC_ENABLED
|
|
||||||
bool "Enable Ultra Low Power (ULP) Coprocessor"
|
|
||||||
default "n"
|
|
||||||
help
|
|
||||||
Set to 'y' if you plan to load a firmware for the coprocessor.
|
|
||||||
|
|
||||||
If this option is enabled, further coprocessor configuration will appear in the Components menu.
|
|
||||||
|
|
||||||
config ESP32S3_ULP_COPROC_RESERVE_MEM
|
|
||||||
int
|
|
||||||
prompt "RTC slow memory reserved for coprocessor" if ESP32S3_ULP_COPROC_ENABLED
|
|
||||||
default 512 if ESP32S3_ULP_COPROC_ENABLED
|
|
||||||
range 32 8176 if ESP32S3_ULP_COPROC_ENABLED
|
|
||||||
default 0 if !ESP32S3_ULP_COPROC_ENABLED
|
|
||||||
range 0 0 if !ESP32S3_ULP_COPROC_ENABLED
|
|
||||||
help
|
|
||||||
Bytes of memory to reserve for ULP coprocessor firmware & data.
|
|
||||||
|
|
||||||
Data is reserved at the beginning of RTC slow memory.
|
|
||||||
|
|
||||||
config ESP32S3_ULP_COPROC_RISCV
|
|
||||||
bool "Enable RISC-V as ULP coprocessor"
|
|
||||||
depends on ESP32S3_ULP_COPROC_ENABLED
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Set this to y to use the RISC-V coprocessor instead of the FSM-ULP.
|
|
||||||
|
|
||||||
config ESP32S3_DEBUG_OCDAWARE
|
config ESP32S3_DEBUG_OCDAWARE
|
||||||
bool "Make exception and panic handlers JTAG/OCD aware"
|
bool "Make exception and panic handlers JTAG/OCD aware"
|
||||||
default y
|
default y
|
||||||
|
@ -62,8 +62,8 @@
|
|||||||
#if __has_include("soc/esp32s2/esp_ds.h")
|
#if __has_include("soc/esp32s2/esp_ds.h")
|
||||||
#include "soc/esp32s2/esp_ds.h"
|
#include "soc/esp32s2/esp_ds.h"
|
||||||
#endif
|
#endif
|
||||||
#if __has_include("ulp_common.h")
|
#if __has_include("ulp_fsm_common.h")
|
||||||
#include "ulp_common.h"
|
#include "ulp_fsm_common.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
||||||
@ -221,7 +221,7 @@ static const esp_err_msg_t esp_err_msg_table[] = {
|
|||||||
forbidden since the NVS encryption works
|
forbidden since the NVS encryption works
|
||||||
differently. */
|
differently. */
|
||||||
# endif
|
# endif
|
||||||
// components/ulp/include/ulp_common.h
|
// components/ulp/ulp_fsm/include/ulp_fsm_common.h
|
||||||
# ifdef ESP_ERR_ULP_BASE
|
# ifdef ESP_ERR_ULP_BASE
|
||||||
ERR_TBL_IT(ESP_ERR_ULP_BASE), /* 4608 0x1200 Offset for ULP-related error codes */
|
ERR_TBL_IT(ESP_ERR_ULP_BASE), /* 4608 0x1200 Offset for ULP-related error codes */
|
||||||
# endif
|
# endif
|
||||||
|
@ -765,7 +765,7 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
|
|||||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) {
|
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) {
|
||||||
s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN);
|
s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN);
|
||||||
}
|
}
|
||||||
#if defined(CONFIG_ESP32_ULP_COPROC_ENABLED) || defined(CONFIG_ESP32S2_ULP_COPROC_ENABLED) || defined(CONFIG_ESP32S3_ULP_COPROC_ENABLED)
|
#if CONFIG_ULP_COPROC_ENABLED
|
||||||
else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) {
|
else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) {
|
||||||
s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN;
|
s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN;
|
||||||
}
|
}
|
||||||
@ -779,21 +779,21 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
|
|||||||
|
|
||||||
esp_err_t esp_sleep_enable_ulp_wakeup(void)
|
esp_err_t esp_sleep_enable_ulp_wakeup(void)
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_ULP_COPROC_ENABLED
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
#endif // CONFIG_ULP_COPROC_ENABLED
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
|
#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
|
||||||
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
|
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_ESP32_ULP_COPROC_ENABLED
|
|
||||||
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
|
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
|
||||||
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
|
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
|
||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
s_config.wakeup_triggers |= RTC_ULP_TRIG_EN;
|
s_config.wakeup_triggers |= RTC_ULP_TRIG_EN;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
#else // CONFIG_ESP32_ULP_COPROC_ENABLED
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
#endif // CONFIG_ESP32_ULP_COPROC_ENABLED
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||||
s_config.wakeup_triggers |= (RTC_ULP_TRIG_EN | RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN);
|
s_config.wakeup_triggers |= (RTC_ULP_TRIG_EN | RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#if CONFIG_ULP_COPROC_TYPE_FSM
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#include "esp32/ulp.h"
|
#include "esp32/ulp.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
@ -27,6 +28,7 @@
|
|||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/ulp.h"
|
#include "esp32s3/ulp.h"
|
||||||
#endif
|
#endif
|
||||||
|
#endif //CONFIG_ULP_COPROC_TYPE_FSM
|
||||||
|
|
||||||
TEST_CASE("Can dump power management lock stats", "[pm]")
|
TEST_CASE("Can dump power management lock stats", "[pm]")
|
||||||
{
|
{
|
||||||
@ -174,6 +176,7 @@ TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]")
|
|||||||
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_ULP_COPROC_TYPE_FSM
|
||||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
|
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
|
||||||
#if !DISABLED_FOR_TARGETS(ESP32C3)
|
#if !DISABLED_FOR_TARGETS(ESP32C3)
|
||||||
// No ULP on C3
|
// No ULP on C3
|
||||||
@ -181,13 +184,7 @@ TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]")
|
|||||||
// Fix failure on ESP32 when running alone; passes when the previous test is run before this one
|
// Fix failure on ESP32 when running alone; passes when the previous test is run before this one
|
||||||
TEST_CASE("Can wake up from automatic light sleep by GPIO", "[pm][ignore]")
|
TEST_CASE("Can wake up from automatic light sleep by GPIO", "[pm][ignore]")
|
||||||
{
|
{
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 16 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 16 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
assert(CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM >= 16 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
||||||
assert(CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM >= 16 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set up GPIO used to wake up RTC */
|
/* Set up GPIO used to wake up RTC */
|
||||||
const int ext1_wakeup_gpio = 25;
|
const int ext1_wakeup_gpio = 25;
|
||||||
@ -253,6 +250,7 @@ TEST_CASE("Can wake up from automatic light sleep by GPIO", "[pm][ignore]")
|
|||||||
}
|
}
|
||||||
#endif //!DISABLED_FOR_TARGETS(ESP32C3)
|
#endif //!DISABLED_FOR_TARGETS(ESP32C3)
|
||||||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
|
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
|
||||||
|
#endif //CONFIG_ULP_COPROC_TYPE_FSM
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int delay_us;
|
int delay_us;
|
||||||
|
@ -100,8 +100,12 @@ MEMORY
|
|||||||
|
|
||||||
Start of RTC slow memory is reserved for ULP co-processor code + data, if enabled.
|
Start of RTC slow memory is reserved for ULP co-processor code + data, if enabled.
|
||||||
*/
|
*/
|
||||||
rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ESP32_ULP_COPROC_RESERVE_MEM,
|
#if CONFIG_ULP_COPROC_ENABLED
|
||||||
len = 0x2000 - CONFIG_ESP32_ULP_COPROC_RESERVE_MEM
|
rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ULP_COPROC_RESERVE_MEM,
|
||||||
|
len = 0x2000 - CONFIG_ULP_COPROC_RESERVE_MEM
|
||||||
|
#else
|
||||||
|
rtc_slow_seg(RW) : org = 0x50000000, len = 0x2000
|
||||||
|
#endif // CONFIG_ULP_COPROC_ENABLED
|
||||||
|
|
||||||
/* external memory */
|
/* external memory */
|
||||||
extern_ram_seg(RWX) : org = 0x3F800000,
|
extern_ram_seg(RWX) : org = 0x3F800000,
|
||||||
|
@ -103,8 +103,12 @@ MEMORY
|
|||||||
|
|
||||||
Start of RTC slow memory is reserved for ULP co-processor code + data, if enabled.
|
Start of RTC slow memory is reserved for ULP co-processor code + data, if enabled.
|
||||||
*/
|
*/
|
||||||
rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM,
|
#if CONFIG_ULP_COPROC_ENABLED
|
||||||
len = 0x2000 - CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM
|
rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ULP_COPROC_RESERVE_MEM,
|
||||||
|
len = 0x2000 - CONFIG_ULP_COPROC_RESERVE_MEM
|
||||||
|
#else
|
||||||
|
rtc_slow_seg(RW) : org = 0x50000000, len = 0x2000
|
||||||
|
#endif // CONFIG_ULP_COPROC_ENABLED
|
||||||
|
|
||||||
/* RTC fast memory (same block as above), viewed from data bus */
|
/* RTC fast memory (same block as above), viewed from data bus */
|
||||||
rtc_data_seg(RW) : org = 0x3ff9e000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC
|
rtc_data_seg(RW) : org = 0x3ff9e000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC
|
||||||
|
@ -109,8 +109,12 @@ MEMORY
|
|||||||
* RTC slow memory (data accessible). Persists over deep sleep.
|
* RTC slow memory (data accessible). Persists over deep sleep.
|
||||||
* Start of RTC slow memory is reserved for ULP co-processor code + data, if enabled.
|
* Start of RTC slow memory is reserved for ULP co-processor code + data, if enabled.
|
||||||
*/
|
*/
|
||||||
rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM,
|
#if CONFIG_ULP_COPROC_ENABLED
|
||||||
len = 0x2000 - CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM
|
rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ULP_COPROC_RESERVE_MEM,
|
||||||
|
len = 0x2000 - CONFIG_ULP_COPROC_RESERVE_MEM
|
||||||
|
#else
|
||||||
|
rtc_slow_seg(RW) : org = 0x50000000 , len = 0x2000
|
||||||
|
#endif // CONFIG_ULP_COPROC_ENABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE
|
#if CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE
|
||||||
|
@ -1,16 +1,31 @@
|
|||||||
idf_build_get_property(target IDF_TARGET)
|
idf_build_get_property(target IDF_TARGET)
|
||||||
|
|
||||||
set(srcs "")
|
set(srcs "")
|
||||||
set(includes include)
|
set(includes "")
|
||||||
|
|
||||||
|
if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED)
|
||||||
|
|
||||||
if(CONFIG_SOC_ULP_SUPPORTED)
|
|
||||||
list(APPEND srcs
|
list(APPEND srcs
|
||||||
"ulp.c"
|
"ulp_common/ulp_common.c")
|
||||||
"ulp_macro.c")
|
|
||||||
|
|
||||||
if(CONFIG_SOC_RISCV_COPROC_SUPPORTED)
|
list(APPEND includes
|
||||||
|
ulp_common/include
|
||||||
|
ulp_common/include/${target})
|
||||||
|
|
||||||
|
if(CONFIG_ULP_COPROC_TYPE_FSM)
|
||||||
list(APPEND srcs
|
list(APPEND srcs
|
||||||
"ulp_riscv.c")
|
"ulp_fsm/ulp.c"
|
||||||
|
"ulp_fsm/ulp_macro.c")
|
||||||
|
|
||||||
|
list(APPEND includes
|
||||||
|
ulp_fsm/include)
|
||||||
|
|
||||||
|
elseif(CONFIG_ULP_COPROC_TYPE_RISCV)
|
||||||
|
list(APPEND srcs
|
||||||
|
"ulp_riscv/ulp_riscv.c")
|
||||||
|
|
||||||
|
list(APPEND includes
|
||||||
|
ulp_riscv/include)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
38
components/ulp/Kconfig
Normal file
38
components/ulp/Kconfig
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
menu "Ultra Low Power (ULP) Co-processor"
|
||||||
|
depends on (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED)
|
||||||
|
|
||||||
|
config ULP_COPROC_ENABLED
|
||||||
|
bool "Enable Ultra Low Power (ULP) Co-processor"
|
||||||
|
default "n"
|
||||||
|
help
|
||||||
|
Enable this feature if you plan to use the ULP Co-processor.
|
||||||
|
Once this option is enabled, further ULP co-processor configuration will appear in the menu.
|
||||||
|
|
||||||
|
choice ULP_COPROC_TYPE
|
||||||
|
prompt "ULP Co-processor type"
|
||||||
|
depends on ULP_COPROC_ENABLED
|
||||||
|
default ULP_COPROC_TYPE_FSM if IDF_TARGET_ESP32
|
||||||
|
default ULP_COPROC_TYPE_RISCV if (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
|
||||||
|
help
|
||||||
|
Choose the ULP Coprocessor type: ULP FSM (Finite State Machine) or ULP RISC-V.
|
||||||
|
Please note that ESP32 only supports ULP FSM.
|
||||||
|
|
||||||
|
config ULP_COPROC_TYPE_FSM
|
||||||
|
bool "ULP FSM (Finite State Machine)"
|
||||||
|
config ULP_COPROC_TYPE_RISCV
|
||||||
|
bool "ULP RISC-V"
|
||||||
|
depends on !IDF_TARGET_ESP32
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ULP_COPROC_RESERVE_MEM
|
||||||
|
int
|
||||||
|
prompt "RTC slow memory reserved for coprocessor"
|
||||||
|
depends on ULP_COPROC_ENABLED
|
||||||
|
default 512 if IDF_TARGET_ESP32
|
||||||
|
default 4096 if (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
|
||||||
|
range 32 8176
|
||||||
|
help
|
||||||
|
Bytes of memory to reserve for ULP Co-processor firmware & data.
|
||||||
|
Data is reserved at the beginning of RTC slow memory.
|
||||||
|
|
||||||
|
endmenu # Ultra Low Power (ULP) Co-processor
|
@ -1,5 +1,5 @@
|
|||||||
Programming ULP coprocessor using C macros (legacy)
|
Programming ULP FSM coprocessor using C macros (legacy)
|
||||||
===================================================
|
=======================================================
|
||||||
|
|
||||||
In addition to the existing binutils port for the ESP32 ULP coprocessor, it is possible to generate programs for the ULP by embedding assembly-like macros into an ESP32 application. Here is an example how this can be done::
|
In addition to the existing binutils port for the ESP32 ULP coprocessor, it is possible to generate programs for the ULP by embedding assembly-like macros into an ESP32 application. Here is an example how this can be done::
|
||||||
|
|
||||||
@ -65,9 +65,10 @@ Header File
|
|||||||
|
|
||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
:esp32: - :component_file:`ulp/include/esp32/ulp.h`
|
:component_file:`ulp/ulp_fsm/include/ulp_fsm_common.h`
|
||||||
:esp32s2: - :component_file:`ulp/include/esp32s2/ulp.h`
|
:esp32: - :component_file:`ulp/ulp_fsm/include/esp32/ulp.h`
|
||||||
:esp32s3: - :component_file:`ulp/include/esp32s3/ulp.h`
|
:esp32s2: - :component_file:`ulp/ulp_fsm/include/esp32s2/ulp.h`
|
||||||
|
:esp32s3: - :component_file:`ulp/ulp_fsm/include/esp32s3/ulp.h`
|
||||||
|
|
||||||
Functions
|
Functions
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
@ -17,10 +17,10 @@ string(REGEX MATCH "\\(GNU Binutils\\) (${version_pattern})" as_version ${as_out
|
|||||||
set(as_version ${CMAKE_MATCH_1})
|
set(as_version ${CMAKE_MATCH_1})
|
||||||
|
|
||||||
|
|
||||||
message(STATUS "Building ULP app ${ULP_APP_NAME} for ${IDF_TARGET}")
|
message(STATUS "Building ULP app ${ULP_APP_NAME}")
|
||||||
|
|
||||||
if(ULP_COCPU_IS_RISCV)
|
if(ULP_COCPU_IS_RISCV)
|
||||||
set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/${IDF_TARGET}.ulp.riscv.ld)
|
set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/ulp_riscv.ld)
|
||||||
else()
|
else()
|
||||||
message(STATUS "ULP assembler version: ${as_version}")
|
message(STATUS "ULP assembler version: ${as_version}")
|
||||||
|
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "ulp_common.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Run the program loaded into RTC memory
|
|
||||||
* @return ESP_OK on success
|
|
||||||
*/
|
|
||||||
esp_err_t ulp_riscv_run(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Load ULP-RISC-V program binary into RTC memory
|
|
||||||
*
|
|
||||||
* Different than ULP FSM, the binary program has no special format, it is the ELF
|
|
||||||
* file generated by RISC-V toolchain converted to binary format using objcopy.
|
|
||||||
*
|
|
||||||
* Linker script in components/ulp/ld/esp32s2.ulp.riscv.ld produces ELF files which
|
|
||||||
* correspond to this format. This linker script produces binaries with load_addr == 0.
|
|
||||||
*
|
|
||||||
* @param program_binary pointer to program binary
|
|
||||||
* @param program_size_bytes size of the program binary
|
|
||||||
* @return
|
|
||||||
* - ESP_OK on success
|
|
||||||
* - ESP_ERR_INVALID_SIZE if program_size_bytes is more than 8KiB
|
|
||||||
*/
|
|
||||||
esp_err_t ulp_riscv_load_binary(const uint8_t* program_binary, size_t program_size_bytes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Stop the ULP timer
|
|
||||||
*
|
|
||||||
* @note This will stop the ULP from waking up if halted, but will not abort any program
|
|
||||||
* currently executing on the ULP.
|
|
||||||
*/
|
|
||||||
void ulp_riscv_timer_stop(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Resumes the ULP timer
|
|
||||||
*
|
|
||||||
* @note This will resume an already configured timer, but does no other configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void ulp_riscv_timer_resume(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Halts the program currently running on the ULP-RISC-V
|
|
||||||
*
|
|
||||||
* @note Program will restart at the next ULP timer trigger if timer is still running.
|
|
||||||
* If you want to stop the ULP from waking up then call ulp_riscv_timer_stop() first.
|
|
||||||
*/
|
|
||||||
void ulp_riscv_halt(void);
|
|
@ -1,43 +0,0 @@
|
|||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
ENTRY(reset_vector)
|
|
||||||
|
|
||||||
MEMORY
|
|
||||||
{
|
|
||||||
ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = ORIGIN(ram);
|
|
||||||
.text :
|
|
||||||
{
|
|
||||||
*start.S.obj(.text.vectors) /* Default reset vector must link to offset 0x0 */
|
|
||||||
*(.text)
|
|
||||||
*(.text*)
|
|
||||||
} >ram
|
|
||||||
|
|
||||||
.rodata ALIGN(4):
|
|
||||||
{
|
|
||||||
*(.rodata)
|
|
||||||
*(.rodata*)
|
|
||||||
} > ram
|
|
||||||
|
|
||||||
.data ALIGN(4):
|
|
||||||
{
|
|
||||||
*(.data)
|
|
||||||
*(.data*)
|
|
||||||
*(.sdata)
|
|
||||||
*(.sdata*)
|
|
||||||
} > ram
|
|
||||||
|
|
||||||
.bss ALIGN(4) :
|
|
||||||
{
|
|
||||||
*(.bss)
|
|
||||||
*(.bss*)
|
|
||||||
*(.sbss)
|
|
||||||
*(.sbss*)
|
|
||||||
} >ram
|
|
||||||
|
|
||||||
__stack_top = ORIGIN(ram) + LENGTH(ram);
|
|
||||||
}
|
|
@ -5,19 +5,11 @@
|
|||||||
*/
|
*/
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#if CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM
|
|
||||||
#define LOCAL_ULP_COPROC_RESERVE_MEM CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM
|
|
||||||
#elif CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM
|
|
||||||
#define LOCAL_ULP_COPROC_RESERVE_MEM CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM
|
|
||||||
#else
|
|
||||||
#define LOCAL_ULP_COPROC_RESERVE_MEM CONFIG_ESP32_ULP_COPROC_RESERVE_MEM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ULP_BIN_MAGIC 0x00706c75
|
#define ULP_BIN_MAGIC 0x00706c75
|
||||||
#define HEADER_SIZE 12
|
#define HEADER_SIZE 12
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
ram(RW) : ORIGIN = 0, LENGTH = LOCAL_ULP_COPROC_RESERVE_MEM
|
ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ULP_COPROC_RESERVE_MEM
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
|
@ -9,7 +9,7 @@ ENTRY(reset_vector)
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM
|
ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ULP_COPROC_RESERVE_MEM
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
@ -39,7 +39,7 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs)
|
|||||||
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-${idf_target}-ulp.cmake)
|
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-${idf_target}-ulp.cmake)
|
||||||
set(ULP_IS_RISCV OFF)
|
set(ULP_IS_RISCV OFF)
|
||||||
elseif(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
|
elseif(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
|
||||||
if(CONFIG_ESP32S2_ULP_COPROC_RISCV STREQUAL "y" OR CONFIG_ESP32S3_ULP_COPROC_RISCV STREQUAL "y")
|
if(CONFIG_ULP_COPROC_TYPE_RISCV STREQUAL "y")
|
||||||
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-ulp-riscv.cmake)
|
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-ulp-riscv.cmake)
|
||||||
set(ULP_IS_RISCV ON)
|
set(ULP_IS_RISCV ON)
|
||||||
else()
|
else()
|
||||||
@ -59,7 +59,6 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs)
|
|||||||
-DCOMPONENT_DIR=${COMPONENT_DIR}
|
-DCOMPONENT_DIR=${COMPONENT_DIR}
|
||||||
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
|
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
-DIDF_PATH=${idf_path}
|
-DIDF_PATH=${idf_path}
|
||||||
-DIDF_TARGET=${idf_target}
|
|
||||||
-DSDKCONFIG_HEADER=${SDKCONFIG_HEADER}
|
-DSDKCONFIG_HEADER=${SDKCONFIG_HEADER}
|
||||||
-DPYTHON=${python}
|
-DPYTHON=${python}
|
||||||
-DULP_COCPU_IS_RISCV=${ULP_IS_RISCV}
|
-DULP_COCPU_IS_RISCV=${ULP_IS_RISCV}
|
||||||
|
@ -2,7 +2,7 @@ if(IDF_TARGET STREQUAL "esp32")
|
|||||||
set(src_dirs ${IDF_TARGET})
|
set(src_dirs ${IDF_TARGET})
|
||||||
set(ulp_sources "ulp/test_jumps_esp32.S")
|
set(ulp_sources "ulp/test_jumps_esp32.S")
|
||||||
elseif(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
|
elseif(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
|
||||||
if(CONFIG_ESP32S2_ULP_COPROC_RISCV STREQUAL "y" OR CONFIG_ESP32S3_ULP_COPROC_RISCV STREQUAL "y")
|
if(CONFIG_ULP_COPROC_TYPE_RISCV)
|
||||||
set(src_dirs "ulp_riscv")
|
set(src_dirs "ulp_riscv")
|
||||||
set(ulp_sources "ulp_riscv/ulp/test_main.c")
|
set(ulp_sources "ulp_riscv/ulp/test_main.c")
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -47,7 +39,7 @@ static void hexdump(const uint32_t* src, size_t count) {
|
|||||||
|
|
||||||
TEST_CASE("ulp add test", "[ulp]")
|
TEST_CASE("ulp add test", "[ulp]")
|
||||||
{
|
{
|
||||||
memset(RTC_SLOW_MEM, 0, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM);
|
memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
const ulp_insn_t program[] = {
|
const ulp_insn_t program[] = {
|
||||||
I_MOVI(R3, 16),
|
I_MOVI(R3, 16),
|
||||||
I_LD(R0, R3, 0),
|
I_LD(R0, R3, 0),
|
||||||
@ -62,14 +54,14 @@ TEST_CASE("ulp add test", "[ulp]")
|
|||||||
TEST_ASSERT_EQUAL(ESP_OK, ulp_process_macros_and_load(0, program, &size));
|
TEST_ASSERT_EQUAL(ESP_OK, ulp_process_macros_and_load(0, program, &size));
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, ulp_run(0));
|
TEST_ASSERT_EQUAL(ESP_OK, ulp_run(0));
|
||||||
esp_rom_delay_us(1000);
|
esp_rom_delay_us(1000);
|
||||||
hexdump(RTC_SLOW_MEM, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM / 4);
|
hexdump(RTC_SLOW_MEM, CONFIG_ULP_COPROC_RESERVE_MEM / 4);
|
||||||
TEST_ASSERT_EQUAL(10 + 11, RTC_SLOW_MEM[18] & 0xffff);
|
TEST_ASSERT_EQUAL(10 + 11, RTC_SLOW_MEM[18] & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ulp branch test", "[ulp]")
|
TEST_CASE("ulp branch test", "[ulp]")
|
||||||
{
|
{
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
memset(RTC_SLOW_MEM, 0, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM);
|
memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
const ulp_insn_t program[] = {
|
const ulp_insn_t program[] = {
|
||||||
I_MOVI(R0, 34), // r0 = dst
|
I_MOVI(R0, 34), // r0 = dst
|
||||||
M_LABEL(1),
|
M_LABEL(1),
|
||||||
@ -85,12 +77,12 @@ TEST_CASE("ulp branch test", "[ulp]")
|
|||||||
};
|
};
|
||||||
RTC_SLOW_MEM[32] = 42;
|
RTC_SLOW_MEM[32] = 42;
|
||||||
RTC_SLOW_MEM[33] = 18;
|
RTC_SLOW_MEM[33] = 18;
|
||||||
hexdump(RTC_SLOW_MEM, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM / 4);
|
hexdump(RTC_SLOW_MEM, CONFIG_ULP_COPROC_RESERVE_MEM / 4);
|
||||||
size_t size = sizeof(program)/sizeof(ulp_insn_t);
|
size_t size = sizeof(program)/sizeof(ulp_insn_t);
|
||||||
ulp_process_macros_and_load(0, program, &size);
|
ulp_process_macros_and_load(0, program, &size);
|
||||||
ulp_run(0);
|
ulp_run(0);
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
hexdump(RTC_SLOW_MEM, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM / 4);
|
hexdump(RTC_SLOW_MEM, CONFIG_ULP_COPROC_RESERVE_MEM / 4);
|
||||||
for (int i = 34; i < 64; ++i) {
|
for (int i = 34; i < 64; ++i) {
|
||||||
TEST_ASSERT_EQUAL(42 - 18, RTC_SLOW_MEM[i] & 0xffff);
|
TEST_ASSERT_EQUAL(42 - 18, RTC_SLOW_MEM[i] & 0xffff);
|
||||||
}
|
}
|
||||||
@ -99,8 +91,8 @@ TEST_CASE("ulp branch test", "[ulp]")
|
|||||||
|
|
||||||
TEST_CASE("ulp wakeup test", "[ulp][ignore]")
|
TEST_CASE("ulp wakeup test", "[ulp][ignore]")
|
||||||
{
|
{
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
memset(RTC_SLOW_MEM, 0, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM);
|
memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
const ulp_insn_t program[] = {
|
const ulp_insn_t program[] = {
|
||||||
I_MOVI(R1, 1024),
|
I_MOVI(R1, 1024),
|
||||||
M_LABEL(1),
|
M_LABEL(1),
|
||||||
@ -127,9 +119,9 @@ TEST_CASE("ulp wakeup test", "[ulp][ignore]")
|
|||||||
|
|
||||||
TEST_CASE("ulp can write and read peripheral registers", "[ulp]")
|
TEST_CASE("ulp can write and read peripheral registers", "[ulp]")
|
||||||
{
|
{
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
CLEAR_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);
|
CLEAR_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);
|
||||||
memset(RTC_SLOW_MEM, 0, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM);
|
memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
REG_WRITE(RTC_CNTL_STORE1_REG, 0x89abcdef);
|
REG_WRITE(RTC_CNTL_STORE1_REG, 0x89abcdef);
|
||||||
|
|
||||||
const ulp_insn_t program[] = {
|
const ulp_insn_t program[] = {
|
||||||
@ -167,8 +159,8 @@ TEST_CASE("ulp can write and read peripheral registers", "[ulp]")
|
|||||||
|
|
||||||
TEST_CASE("ULP I_WR_REG instruction test", "[ulp]")
|
TEST_CASE("ULP I_WR_REG instruction test", "[ulp]")
|
||||||
{
|
{
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
memset(RTC_SLOW_MEM, 0, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM);
|
memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int low;
|
int low;
|
||||||
int width;
|
int width;
|
||||||
@ -221,8 +213,8 @@ TEST_CASE("ULP I_WR_REG instruction test", "[ulp]")
|
|||||||
|
|
||||||
TEST_CASE("ulp controls RTC_IO", "[ulp][ignore]")
|
TEST_CASE("ulp controls RTC_IO", "[ulp][ignore]")
|
||||||
{
|
{
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
memset(RTC_SLOW_MEM, 0, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM);
|
memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
const ulp_insn_t program[] = {
|
const ulp_insn_t program[] = {
|
||||||
I_MOVI(R0, 0), // R0 is LED state
|
I_MOVI(R0, 0), // R0 is LED state
|
||||||
I_MOVI(R2, 16), // loop R2 from 16 down to 0
|
I_MOVI(R2, 16), // loop R2 from 16 down to 0
|
||||||
@ -270,7 +262,7 @@ TEST_CASE("ulp controls RTC_IO", "[ulp][ignore]")
|
|||||||
|
|
||||||
TEST_CASE("ulp power consumption in deep sleep", "[ulp][ignore]")
|
TEST_CASE("ulp power consumption in deep sleep", "[ulp][ignore]")
|
||||||
{
|
{
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 4 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 4 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
ulp_insn_t insn = I_HALT();
|
ulp_insn_t insn = I_HALT();
|
||||||
memcpy(&RTC_SLOW_MEM[0], &insn, sizeof(insn));
|
memcpy(&RTC_SLOW_MEM[0], &insn, sizeof(insn));
|
||||||
|
|
||||||
@ -290,8 +282,8 @@ TEST_CASE("ulp timer setting", "[ulp]")
|
|||||||
* Program calls I_HALT each time and gets restarted by the timer.
|
* Program calls I_HALT each time and gets restarted by the timer.
|
||||||
* Compare the expected number of times the program runs with the actual.
|
* Compare the expected number of times the program runs with the actual.
|
||||||
*/
|
*/
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 32 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 32 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
memset(RTC_SLOW_MEM, 0, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM);
|
memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
|
|
||||||
const int offset = 6;
|
const int offset = 6;
|
||||||
const ulp_insn_t program[] = {
|
const ulp_insn_t program[] = {
|
||||||
@ -333,11 +325,11 @@ TEST_CASE("ulp timer setting", "[ulp]")
|
|||||||
|
|
||||||
TEST_CASE("ulp can use TSENS in deep sleep", "[ulp][ignore]")
|
TEST_CASE("ulp can use TSENS in deep sleep", "[ulp][ignore]")
|
||||||
{
|
{
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
|
|
||||||
hexdump(RTC_SLOW_MEM, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM / 4);
|
hexdump(RTC_SLOW_MEM, CONFIG_ULP_COPROC_RESERVE_MEM / 4);
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
memset(RTC_SLOW_MEM, 0, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM);
|
memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
|
|
||||||
// Allow TSENS to be controlled by the ULP
|
// Allow TSENS to be controlled by the ULP
|
||||||
SET_PERI_REG_BITS(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_CLK_DIV, 10, SENS_TSENS_CLK_DIV_S);
|
SET_PERI_REG_BITS(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_CLK_DIV, 10, SENS_TSENS_CLK_DIV_S);
|
||||||
@ -349,7 +341,7 @@ TEST_CASE("ulp can use TSENS in deep sleep", "[ulp][ignore]")
|
|||||||
// data start offset
|
// data start offset
|
||||||
size_t offset = 20;
|
size_t offset = 20;
|
||||||
// number of samples to collect
|
// number of samples to collect
|
||||||
RTC_SLOW_MEM[offset] = (CONFIG_ESP32_ULP_COPROC_RESERVE_MEM) / 4 - offset - 8;
|
RTC_SLOW_MEM[offset] = (CONFIG_ULP_COPROC_RESERVE_MEM) / 4 - offset - 8;
|
||||||
// sample counter
|
// sample counter
|
||||||
RTC_SLOW_MEM[offset + 1] = 0;
|
RTC_SLOW_MEM[offset + 1] = 0;
|
||||||
|
|
||||||
@ -385,11 +377,11 @@ TEST_CASE("ulp can use TSENS in deep sleep", "[ulp][ignore]")
|
|||||||
|
|
||||||
TEST_CASE("can use ADC in deep sleep", "[ulp][ignore]")
|
TEST_CASE("can use ADC in deep sleep", "[ulp][ignore]")
|
||||||
{
|
{
|
||||||
assert(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ESP32_ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig");
|
||||||
|
|
||||||
hexdump(RTC_SLOW_MEM, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM / 4);
|
hexdump(RTC_SLOW_MEM, CONFIG_ULP_COPROC_RESERVE_MEM / 4);
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
memset(RTC_SLOW_MEM, 0, CONFIG_ESP32_ULP_COPROC_RESERVE_MEM);
|
memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH, 3, SENS_SAR1_BIT_WIDTH_S);
|
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH, 3, SENS_SAR1_BIT_WIDTH_S);
|
||||||
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR2_BIT_WIDTH, 3, SENS_SAR2_BIT_WIDTH_S);
|
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR2_BIT_WIDTH, 3, SENS_SAR2_BIT_WIDTH_S);
|
||||||
@ -429,7 +421,7 @@ TEST_CASE("can use ADC in deep sleep", "[ulp][ignore]")
|
|||||||
// data start offset
|
// data start offset
|
||||||
size_t offset = 20;
|
size_t offset = 20;
|
||||||
// number of samples to collect
|
// number of samples to collect
|
||||||
RTC_SLOW_MEM[offset] = (CONFIG_ESP32_ULP_COPROC_RESERVE_MEM) / 4 - offset - 8;
|
RTC_SLOW_MEM[offset] = (CONFIG_ULP_COPROC_RESERVE_MEM) / 4 - offset - 8;
|
||||||
// sample counter
|
// sample counter
|
||||||
RTC_SLOW_MEM[offset + 1] = 0;
|
RTC_SLOW_MEM[offset + 1] = 0;
|
||||||
|
|
||||||
|
@ -10,13 +10,7 @@
|
|||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "soc/sens_reg.h"
|
#include "soc/sens_reg.h"
|
||||||
#include "soc/rtc_periph.h"
|
#include "soc/rtc_periph.h"
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#include "ulp_riscv.h"
|
||||||
#include "esp32s2/ulp.h"
|
|
||||||
#include "esp32s2/ulp_riscv.h"
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
||||||
#include "esp32s3/ulp.h"
|
|
||||||
#include "esp32s3/ulp_riscv.h"
|
|
||||||
#endif
|
|
||||||
#include "ulp_test_app.h"
|
#include "ulp_test_app.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -129,22 +123,6 @@ TEST_CASE("ULP-RISC-V is able to wakeup main CPU from light sleep", "[ulp]")
|
|||||||
ulp_main_cpu_command = RISCV_NO_COMMAND;
|
ulp_main_cpu_command = RISCV_NO_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ULP-RISC-V is able to wakeup main CPU from deep sleep", "[ulp][reset=SW_CPU_RESET][ignore]")
|
|
||||||
{
|
|
||||||
/* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
|
|
||||||
load_and_start_ulp_firmware();
|
|
||||||
|
|
||||||
/* Setup wakeup triggers */
|
|
||||||
TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK);
|
|
||||||
|
|
||||||
/* Setup test data */
|
|
||||||
ulp_main_cpu_command = RISCV_DEEP_SLEEP_WAKEUP_TEST;
|
|
||||||
|
|
||||||
/* Enter Deep Sleep */
|
|
||||||
esp_deep_sleep_start();
|
|
||||||
UNITY_TEST_FAIL(__LINE__, "Should not get here!");
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ulp_riscv_is_running(void)
|
static bool ulp_riscv_is_running(void)
|
||||||
{
|
{
|
||||||
uint32_t start_cnt = ulp_riscv_counter;
|
uint32_t start_cnt = ulp_riscv_counter;
|
||||||
@ -205,3 +183,23 @@ TEST_CASE("ULP-RISC-V can stop itself and be resumed from the main CPU", "[ulp]"
|
|||||||
|
|
||||||
TEST_ASSERT(ulp_riscv_is_running());
|
TEST_ASSERT(ulp_riscv_is_running());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keep this test case as the last test case in this suite as a CPU reset occurs.
|
||||||
|
* Add new test cases above in order to ensure they run when all test cases are run together.
|
||||||
|
*/
|
||||||
|
TEST_CASE("ULP-RISC-V is able to wakeup main CPU from deep sleep", "[ulp][reset=SW_CPU_RESET][ignore]")
|
||||||
|
{
|
||||||
|
/* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
|
||||||
|
load_and_start_ulp_firmware();
|
||||||
|
|
||||||
|
/* Setup wakeup triggers */
|
||||||
|
TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK);
|
||||||
|
|
||||||
|
/* Setup test data */
|
||||||
|
ulp_main_cpu_command = RISCV_DEEP_SLEEP_WAKEUP_TEST;
|
||||||
|
|
||||||
|
/* Enter Deep Sleep */
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
UNITY_TEST_FAIL(__LINE__, "Should not get here!");
|
||||||
|
}
|
||||||
|
@ -7,9 +7,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "ulp_riscv/ulp_riscv.h"
|
#include "ulp_riscv_utils.h"
|
||||||
#include "ulp_riscv/ulp_riscv_utils.h"
|
#include "ulp_riscv_gpio.h"
|
||||||
#include "ulp_riscv/ulp_riscv_gpio.h"
|
|
||||||
|
|
||||||
typedef enum{
|
typedef enum{
|
||||||
RISCV_READ_WRITE_TEST = 1,
|
RISCV_READ_WRITE_TEST = 1,
|
||||||
|
19
components/ulp/ulp_common/include/esp32/ulp_common_defs.h
Normal file
19
components/ulp/ulp_common/include/esp32/ulp_common_defs.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __ULP_COMMON_DEFS_H__
|
||||||
|
#define __ULP_COMMON_DEFS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __ULP_COMMON_DEFS_H__
|
19
components/ulp/ulp_common/include/esp32s2/ulp_common_defs.h
Normal file
19
components/ulp/ulp_common/include/esp32s2/ulp_common_defs.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __ULP_COMMON_DEFS_H__
|
||||||
|
#define __ULP_COMMON_DEFS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __ULP_COMMON_DEFS_H__
|
19
components/ulp/ulp_common/include/esp32s3/ulp_common_defs.h
Normal file
19
components/ulp/ulp_common/include/esp32s3/ulp_common_defs.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __ULP_COMMON_DEFS_H__
|
||||||
|
#define __ULP_COMMON_DEFS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __ULP_COMMON_DEFS_H__
|
51
components/ulp/ulp_common/include/ulp_common.h
Normal file
51
components/ulp/ulp_common/include/ulp_common.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __ULP_COMMON_H__
|
||||||
|
#define __ULP_COMMON_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "ulp_common_defs.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set one of ULP wakeup period values
|
||||||
|
*
|
||||||
|
* ULP coprocessor starts running the program when the wakeup timer counts up
|
||||||
|
* to a given value (called period). There are 5 period values which can be
|
||||||
|
* programmed into SENS_ULP_CP_SLEEP_CYCx_REG registers, x = 0..4 for ESP32, and
|
||||||
|
* one period value which can be programmed into RTC_CNTL_ULP_CP_TIMER_1_REG register for ESP32-S2/S3.
|
||||||
|
* By default, for ESP32, wakeup timer will use the period set into SENS_ULP_CP_SLEEP_CYC0_REG,
|
||||||
|
* i.e. period number 0. ULP program code can use SLEEP instruction to select
|
||||||
|
* which of the SENS_ULP_CP_SLEEP_CYCx_REG should be used for subsequent wakeups.
|
||||||
|
*
|
||||||
|
* However, please note that SLEEP instruction issued (from ULP program) while the system
|
||||||
|
* is in deep sleep mode does not have effect, and sleep cycle count 0 is used.
|
||||||
|
*
|
||||||
|
* For ESP32-S2/S3 the SLEEP instruction not exist. Instead a WAKE instruction will be used.
|
||||||
|
*
|
||||||
|
* @param period_index wakeup period setting number (0 - 4)
|
||||||
|
* @param period_us wakeup period, us
|
||||||
|
* @note The ULP FSM requires two clock cycles to wakeup before being able to run the program.
|
||||||
|
* Then additional 16 cycles are reserved after wakeup waiting until the 8M clock is stable.
|
||||||
|
* The FSM also requires two more clock cycles to go to sleep after the program execution is halted.
|
||||||
|
* The minimum wakeup period that may be set up for the ULP
|
||||||
|
* is equal to the total number of cycles spent on the above internal tasks.
|
||||||
|
* For a default configuration of the ULP running at 150kHz it makes about 133us.
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_ARG if period_index is out of range
|
||||||
|
*/
|
||||||
|
esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __ULP_COMMON_H__
|
57
components/ulp/ulp_common/ulp_common.c
Normal file
57
components/ulp/ulp_common/ulp_common.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "ulp_common.h"
|
||||||
|
#include "esp_private/esp_clk.h"
|
||||||
|
#include "soc/rtc.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/sens_reg.h"
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
#define ULP_FSM_PREPARE_SLEEP_CYCLES 2 /*!< Cycles spent by FSM preparing ULP for sleep */
|
||||||
|
#define ULP_FSM_WAKEUP_SLEEP_CYCLES 2 /*!< Cycles spent by FSM waking up ULP from sleep */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us)
|
||||||
|
{
|
||||||
|
if (period_index > 4) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t period_us_64 = period_us;
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
uint64_t period_cycles = (period_us_64 << RTC_CLK_CAL_FRACT) / esp_clk_slowclk_cal_get();
|
||||||
|
uint64_t min_sleep_period_cycles = ULP_FSM_PREPARE_SLEEP_CYCLES
|
||||||
|
+ ULP_FSM_WAKEUP_SLEEP_CYCLES
|
||||||
|
+ REG_GET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT);
|
||||||
|
if (period_cycles < min_sleep_period_cycles) {
|
||||||
|
period_cycles = min_sleep_period_cycles;
|
||||||
|
ESP_LOGW("ulp", "Sleep period clipped to minimum of %d cycles", (uint32_t) min_sleep_period_cycles);
|
||||||
|
} else {
|
||||||
|
period_cycles -= min_sleep_period_cycles;
|
||||||
|
}
|
||||||
|
REG_SET_FIELD(SENS_ULP_CP_SLEEP_CYC0_REG + period_index * sizeof(uint32_t),
|
||||||
|
SENS_SLEEP_CYCLES_S0, (uint32_t) period_cycles);
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
rtc_slow_freq_t slow_clk_freq = rtc_clk_slow_freq_get();
|
||||||
|
rtc_slow_freq_t rtc_slow_freq_x32k = RTC_SLOW_FREQ_32K_XTAL;
|
||||||
|
rtc_slow_freq_t rtc_slow_freq_8MD256 = RTC_SLOW_FREQ_8MD256;
|
||||||
|
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
||||||
|
if (slow_clk_freq == (rtc_slow_freq_x32k)) {
|
||||||
|
cal_clk = RTC_CAL_32K_XTAL;
|
||||||
|
} else if (slow_clk_freq == rtc_slow_freq_8MD256) {
|
||||||
|
cal_clk = RTC_CAL_8MD256;
|
||||||
|
}
|
||||||
|
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
|
||||||
|
uint64_t period_cycles = rtc_time_us_to_slowclk(period_us_64, slow_clk_period);
|
||||||
|
|
||||||
|
REG_SET_FIELD(RTC_CNTL_ULP_CP_TIMER_1_REG, RTC_CNTL_ULP_CP_TIMER_SLP_CYCLE, ((uint32_t)period_cycles));
|
||||||
|
#endif
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
@ -10,15 +10,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "ulp_common.h"
|
#include "ulp_common.h"
|
||||||
|
#include "ulp_fsm_common.h"
|
||||||
#include "soc/reg_base.h"
|
#include "soc/reg_base.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ULP_FSM_PREPARE_SLEEP_CYCLES 2 /*!< Cycles spent by FSM preparing ULP for sleep */
|
|
||||||
#define ULP_FSM_WAKEUP_SLEEP_CYCLES 2 /*!< Cycles spent by FSM waking up ULP from sleep */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup ulp_registers ULP coprocessor registers
|
* @defgroup ulp_registers ULP coprocessor registers
|
||||||
* @{
|
* @{
|
||||||
@ -1031,9 +1029,6 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
|
|||||||
*/
|
*/
|
||||||
#define I_I2C_WRITE(slave_sel, sub_addr, val) I_I2C_RW(sub_addr, val, 0, 7, slave_sel, SUB_OPCODE_I2C_WR)
|
#define I_I2C_WRITE(slave_sel, sub_addr, val) I_I2C_RW(sub_addr, val, 0, 7, slave_sel, SUB_OPCODE_I2C_WR)
|
||||||
|
|
||||||
#define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -10,15 +10,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "ulp_common.h"
|
#include "ulp_common.h"
|
||||||
|
#include "ulp_fsm_common.h"
|
||||||
#include "soc/reg_base.h"
|
#include "soc/reg_base.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ULP_FSM_PREPARE_SLEEP_CYCLES 2 /*!< Cycles spent by FSM preparing ULP for sleep */
|
|
||||||
#define ULP_FSM_WAKEUP_SLEEP_CYCLES 2 /*!< Cycles spent by FSM waking up ULP from sleep */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup ulp_registers ULP coprocessor registers
|
* @defgroup ulp_registers ULP coprocessor registers
|
||||||
* @{
|
* @{
|
||||||
@ -823,10 +821,6 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
|
|||||||
M_BRANCH(label_num), \
|
M_BRANCH(label_num), \
|
||||||
I_BXFI(0)
|
I_BXFI(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -10,15 +10,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "ulp_common.h"
|
#include "ulp_common.h"
|
||||||
|
#include "ulp_fsm_common.h"
|
||||||
#include "soc/reg_base.h"
|
#include "soc/reg_base.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ULP_FSM_PREPARE_SLEEP_CYCLES 2 /*!< Cycles spent by FSM preparing ULP for sleep */
|
|
||||||
#define ULP_FSM_WAKEUP_SLEEP_CYCLES 2 /*!< Cycles spent by FSM waking up ULP from sleep */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup ulp_registers ULP coprocessor registers
|
* @defgroup ulp_registers ULP coprocessor registers
|
||||||
* @{
|
* @{
|
||||||
@ -823,10 +821,6 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg)
|
|||||||
M_BRANCH(label_num), \
|
M_BRANCH(label_num), \
|
||||||
I_BXFI(0)
|
I_BXFI(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -73,36 +73,6 @@ esp_err_t ulp_load_binary(uint32_t load_addr, const uint8_t* program_binary, siz
|
|||||||
*/
|
*/
|
||||||
esp_err_t ulp_run(uint32_t entry_point);
|
esp_err_t ulp_run(uint32_t entry_point);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set one of ULP wakeup period values
|
|
||||||
*
|
|
||||||
* ULP coprocessor starts running the program when the wakeup timer counts up
|
|
||||||
* to a given value (called period). There are 5 period values which can be
|
|
||||||
* programmed into SENS_ULP_CP_SLEEP_CYCx_REG registers, x = 0..4 for ESP32, and
|
|
||||||
* one period value which can be programmed into RTC_CNTL_ULP_CP_TIMER_1_REG register for ESP32-S2.
|
|
||||||
* By default, for ESP32, wakeup timer will use the period set into SENS_ULP_CP_SLEEP_CYC0_REG,
|
|
||||||
* i.e. period number 0. ULP program code can use SLEEP instruction to select
|
|
||||||
* which of the SENS_ULP_CP_SLEEP_CYCx_REG should be used for subsequent wakeups.
|
|
||||||
*
|
|
||||||
* However, please note that SLEEP instruction issued (from ULP program) while the system
|
|
||||||
* is in deep sleep mode does not have effect, and sleep cycle count 0 is used.
|
|
||||||
*
|
|
||||||
* For ESP32-s2 the SLEEP instruction not exist. Instead a WAKE instruction will be used.
|
|
||||||
*
|
|
||||||
* @param period_index wakeup period setting number (0 - 4)
|
|
||||||
* @param period_us wakeup period, us
|
|
||||||
* @note The ULP FSM requires two clock cycles to wakeup before being able to run the program.
|
|
||||||
* Then additional 16 cycles are reserved after wakeup waiting until the 8M clock is stable.
|
|
||||||
* The FSM also requires two more clock cycles to go to sleep after the program execution is halted.
|
|
||||||
* The minimum wakeup period that may be set up for the ULP
|
|
||||||
* is equal to the total number of cycles spent on the above internal tasks.
|
|
||||||
* For a default configuration of the ULP running at 150kHz it makes about 133us.
|
|
||||||
* @return
|
|
||||||
* - ESP_OK on success
|
|
||||||
* - ESP_ERR_INVALID_ARG if period_index is out of range
|
|
||||||
*/
|
|
||||||
esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -25,7 +25,7 @@
|
|||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "soc/sens_reg.h"
|
#include "soc/sens_reg.h"
|
||||||
|
|
||||||
#include "ulp_private.h"
|
#include "ulp_common.h"
|
||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -90,10 +90,10 @@ esp_err_t ulp_load_binary(uint32_t load_addr, const uint8_t* program_binary, siz
|
|||||||
if (program_size_bytes < sizeof(ulp_binary_header_t)) {
|
if (program_size_bytes < sizeof(ulp_binary_header_t)) {
|
||||||
return ESP_ERR_INVALID_SIZE;
|
return ESP_ERR_INVALID_SIZE;
|
||||||
}
|
}
|
||||||
if (load_addr_bytes > ULP_RESERVE_MEM) {
|
if (load_addr_bytes > CONFIG_ULP_COPROC_RESERVE_MEM) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
if (load_addr_bytes + program_size_bytes > ULP_RESERVE_MEM) {
|
if (load_addr_bytes + program_size_bytes > CONFIG_ULP_COPROC_RESERVE_MEM) {
|
||||||
return ESP_ERR_INVALID_SIZE;
|
return ESP_ERR_INVALID_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,46 +124,3 @@ esp_err_t ulp_load_binary(uint32_t load_addr, const uint8_t* program_binary, siz
|
|||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us)
|
|
||||||
{
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
if (period_index > 4) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
uint64_t period_us_64 = period_us;
|
|
||||||
uint64_t period_cycles = (period_us_64 << RTC_CLK_CAL_FRACT) / esp_clk_slowclk_cal_get();
|
|
||||||
uint64_t min_sleep_period_cycles = ULP_FSM_PREPARE_SLEEP_CYCLES
|
|
||||||
+ ULP_FSM_WAKEUP_SLEEP_CYCLES
|
|
||||||
+ REG_GET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT);
|
|
||||||
if (period_cycles < min_sleep_period_cycles) {
|
|
||||||
period_cycles = 0;
|
|
||||||
ESP_LOGW(TAG, "Sleep period clipped to minimum of %d cycles", (uint32_t) min_sleep_period_cycles);
|
|
||||||
} else {
|
|
||||||
period_cycles -= min_sleep_period_cycles;
|
|
||||||
}
|
|
||||||
REG_SET_FIELD(SENS_ULP_CP_SLEEP_CYC0_REG + period_index * sizeof(uint32_t),
|
|
||||||
SENS_SLEEP_CYCLES_S0, (uint32_t) period_cycles);
|
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
|
||||||
if (period_index > 4) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t period_us_64 = period_us;
|
|
||||||
|
|
||||||
rtc_slow_freq_t slow_clk_freq = rtc_clk_slow_freq_get();
|
|
||||||
rtc_slow_freq_t rtc_slow_freq_x32k = RTC_SLOW_FREQ_32K_XTAL;
|
|
||||||
rtc_slow_freq_t rtc_slow_freq_8MD256 = RTC_SLOW_FREQ_8MD256;
|
|
||||||
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
|
||||||
if (slow_clk_freq == (rtc_slow_freq_x32k)) {
|
|
||||||
cal_clk = RTC_CAL_32K_XTAL;
|
|
||||||
} else if (slow_clk_freq == rtc_slow_freq_8MD256) {
|
|
||||||
cal_clk = RTC_CAL_8MD256;
|
|
||||||
}
|
|
||||||
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
|
|
||||||
uint64_t period_cycles = rtc_time_us_to_slowclk(period_us_64, slow_clk_period);
|
|
||||||
|
|
||||||
REG_SET_FIELD(RTC_CNTL_ULP_CP_TIMER_1_REG, RTC_CNTL_ULP_CP_TIMER_SLP_CYCLE, ((uint32_t)period_cycles));
|
|
||||||
#endif
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -20,7 +12,7 @@
|
|||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp32/ulp.h"
|
#include "esp32/ulp.h"
|
||||||
#include "ulp_private.h"
|
#include "ulp_common.h"
|
||||||
|
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
@ -195,7 +187,7 @@ esp_err_t ulp_process_macros_and_load(uint32_t load_addr, const ulp_insn_t* prog
|
|||||||
++read_ptr;
|
++read_ptr;
|
||||||
}
|
}
|
||||||
size_t real_program_size = *psize - macro_count;
|
size_t real_program_size = *psize - macro_count;
|
||||||
const size_t ulp_mem_end = ULP_RESERVE_MEM / sizeof(ulp_insn_t);
|
const size_t ulp_mem_end = CONFIG_ULP_COPROC_RESERVE_MEM / sizeof(ulp_insn_t);
|
||||||
if (load_addr > ulp_mem_end) {
|
if (load_addr > ulp_mem_end) {
|
||||||
ESP_LOGW(TAG, "invalid load address %x, max is %x",
|
ESP_LOGW(TAG, "invalid load address %x, max is %x",
|
||||||
load_addr, ulp_mem_end);
|
load_addr, ulp_mem_end);
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32_ULP_COPROC_RESERVE_MEM
|
|
||||||
#define ULP_RESERVE_MEM CONFIG_ESP32_ULP_COPROC_RESERVE_MEM
|
|
||||||
#elif defined(CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM)
|
|
||||||
#define ULP_RESERVE_MEM CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM
|
|
||||||
#elif defined(CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM)
|
|
||||||
#define ULP_RESERVE_MEM CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM
|
|
||||||
#endif
|
|
8
components/ulp/ulp_riscv/include/esp32s2/ulp_riscv.h
Normal file
8
components/ulp/ulp_riscv/include/esp32s2/ulp_riscv.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#warning Contents of esp32s2/ulp_riscv.h have been merged with ulp_riscv.h. Please include the later to avoid the warning.
|
||||||
|
#include "ulp_riscv.h"
|
@ -27,7 +27,7 @@ esp_err_t ulp_riscv_run(void);
|
|||||||
* Different than ULP FSM, the binary program has no special format, it is the ELF
|
* Different than ULP FSM, the binary program has no special format, it is the ELF
|
||||||
* file generated by RISC-V toolchain converted to binary format using objcopy.
|
* file generated by RISC-V toolchain converted to binary format using objcopy.
|
||||||
*
|
*
|
||||||
* Linker script in components/ulp/ld/esp32s3.ulp.riscv.ld produces ELF files which
|
* Linker script in components/ulp/ld/ulp_riscv.ld produces ELF files which
|
||||||
* correspond to this format. This linker script produces binaries with load_addr == 0.
|
* correspond to this format. This linker script produces binaries with load_addr == 0.
|
||||||
*
|
*
|
||||||
* @param program_binary pointer to program binary
|
* @param program_binary pointer to program binary
|
@ -1,27 +1,8 @@
|
|||||||
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
|
|
||||||
#pragma once
|
#warning Contents of ulp_riscv/ulp_riscv.h have been merged with ulp_riscv_utils.Please include the later to avoid the warning.
|
||||||
|
#include "ulp_riscv_utils.h"
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "ulp_riscv_register_ops.h"
|
|
||||||
#include "soc/soc.h"
|
|
||||||
#include "soc/rtc_cntl_reg.h"
|
|
||||||
#include "soc/soc_ulp.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -4,122 +4,5 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#warning ulp_riscv_gpio.h has been moved one level up. Please include the file without the ulp_riscv prefix.
|
||||||
|
#include "ulp_riscv_gpio.h"
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "ulp_riscv/ulp_riscv.h"
|
|
||||||
#include "soc/rtc_io_reg.h"
|
|
||||||
#include "soc/sens_reg.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
GPIO_NUM_0 = 0, /*!< GPIO0, input and output */
|
|
||||||
GPIO_NUM_1 = 1, /*!< GPIO1, input and output */
|
|
||||||
GPIO_NUM_2 = 2, /*!< GPIO2, input and output */
|
|
||||||
GPIO_NUM_3 = 3, /*!< GPIO3, input and output */
|
|
||||||
GPIO_NUM_4 = 4, /*!< GPIO4, input and output */
|
|
||||||
GPIO_NUM_5 = 5, /*!< GPIO5, input and output */
|
|
||||||
GPIO_NUM_6 = 6, /*!< GPIO6, input and output */
|
|
||||||
GPIO_NUM_7 = 7, /*!< GPIO7, input and output */
|
|
||||||
GPIO_NUM_8 = 8, /*!< GPIO8, input and output */
|
|
||||||
GPIO_NUM_9 = 9, /*!< GPIO9, input and output */
|
|
||||||
GPIO_NUM_10 = 10, /*!< GPIO10, input and output */
|
|
||||||
GPIO_NUM_11 = 11, /*!< GPIO11, input and output */
|
|
||||||
GPIO_NUM_12 = 12, /*!< GPIO12, input and output */
|
|
||||||
GPIO_NUM_13 = 13, /*!< GPIO13, input and output */
|
|
||||||
GPIO_NUM_14 = 14, /*!< GPIO14, input and output */
|
|
||||||
GPIO_NUM_15 = 15, /*!< GPIO15, input and output */
|
|
||||||
GPIO_NUM_16 = 16, /*!< GPIO16, input and output */
|
|
||||||
GPIO_NUM_17 = 17, /*!< GPIO17, input and output */
|
|
||||||
GPIO_NUM_18 = 18, /*!< GPIO18, input and output */
|
|
||||||
GPIO_NUM_19 = 19, /*!< GPIO19, input and output */
|
|
||||||
GPIO_NUM_20 = 20,
|
|
||||||
GPIO_NUM_21 = 21, /*!< GPIO21, input and output */
|
|
||||||
} gpio_num_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
RTCIO_MODE_OUTPUT = 0,
|
|
||||||
RTCIO_MODE_OUTPUT_OD = 1,
|
|
||||||
} rtc_io_out_mode_t;
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_init(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_IO_MUX_CONF_REG, SENS_IOMUX_CLK_GATE_EN_M);
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_IOMUX_CLK_EN_M);
|
|
||||||
#endif
|
|
||||||
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_MUX_SEL);
|
|
||||||
REG_SET_FIELD(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_SEL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_deinit(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_MUX_SEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_output_enable(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
REG_SET_FIELD(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS, BIT(gpio_num));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_output_disable(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
REG_SET_FIELD(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC, BIT(gpio_num));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_input_enable(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_IE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_input_disable(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_IE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_output_level(gpio_num_t gpio_num, uint8_t level)
|
|
||||||
{
|
|
||||||
if (level) {
|
|
||||||
REG_SET_FIELD(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS, BIT(gpio_num));
|
|
||||||
} else {
|
|
||||||
REG_SET_FIELD(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TS, BIT(gpio_num));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint8_t ulp_riscv_gpio_get_level(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
return (uint8_t)((REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & BIT(gpio_num)) ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_set_output_mode(gpio_num_t gpio_num, rtc_io_out_mode_t mode)
|
|
||||||
{
|
|
||||||
REG_SET_FIELD(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_DRV, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_pullup(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_pullup_disable(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_pulldown(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_riscv_gpio_pulldown_disable(gpio_num_t gpio_num)
|
|
||||||
{
|
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,148 +1,8 @@
|
|||||||
// Copyright 2010-2018 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#define ULP_RISCV_REGISTER_OPS
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//Registers Operation {{
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When COCPU accesses the RTC register, it needs to convert the access address.
|
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
* When COCPU accesses the RTC memory, dont need to convert the access address.
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#define WRITE_RTC_MEM(addr, val) (*((volatile int*)(addr))) = (int) (val)
|
|
||||||
#define READ_RTC_MEM(addr) (*(volatile int*)(addr))
|
|
||||||
|
|
||||||
/*
|
#warning ulp_riscv_register_ops.h has been moved one level up. Please include the file without the ulp_riscv prefix.
|
||||||
* When COCPU accesses the RTC register, it needs to convert the access address.
|
#include "ulp_riscv_register_ops.h"
|
||||||
* When COCPU accesses the RTC memory, dont need to convert the access address.
|
|
||||||
*/
|
|
||||||
#define RISCV_REG_CONV(addr) (((addr&0xffff)<<3 & 0xe000) | (addr & 0x1fff) | 0x8000)
|
|
||||||
#define ETS_UNCACHED_ADDR(addr) (RISCV_REG_CONV(addr))
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
|
||||||
#define BIT(nr) (1UL << (nr))
|
|
||||||
#else
|
|
||||||
#define BIT(nr) (1 << (nr))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//write value to register
|
|
||||||
#define REG_WRITE(_r, _v) ({ \
|
|
||||||
(*(volatile uint32_t *)RISCV_REG_CONV(_r)) = (_v); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//read value from register
|
|
||||||
#define REG_READ(_r) ({ \
|
|
||||||
(*(volatile uint32_t *)RISCV_REG_CONV(_r)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//get bit or get bits from register
|
|
||||||
#define REG_GET_BIT(_r, _b) ({ \
|
|
||||||
(*(volatile uint32_t*)RISCV_REG_CONV(_r) & (_b)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//set bit or set bits to register
|
|
||||||
#define REG_SET_BIT(_r, _b) ({ \
|
|
||||||
(*(volatile uint32_t*)RISCV_REG_CONV(_r) |= (_b)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//clear bit or clear bits of register
|
|
||||||
#define REG_CLR_BIT(_r, _b) ({ \
|
|
||||||
(*(volatile uint32_t*)RISCV_REG_CONV(_r) &= ~(_b)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//set bits of register controlled by mask
|
|
||||||
#define REG_SET_BITS(_r, _b, _m) ({ \
|
|
||||||
(*(volatile uint32_t*)RISCV_REG_CONV(_r) = (*(volatile uint32_t*)RISCV_REG_CONV(_r) & ~(_m)) | ((_b) & (_m))); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//get field from register, uses field _S & _V to determine mask
|
|
||||||
#define REG_GET_FIELD(_r, _f) ({ \
|
|
||||||
((REG_READ(_r) >> (_f##_S)) & (_f##_V)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//set field of a register from variable, uses field _S & _V to determine mask
|
|
||||||
#define REG_SET_FIELD(_r, _f, _v) ({ \
|
|
||||||
(REG_WRITE((_r),((REG_READ(_r) & ~((_f##_V) << (_f##_S)))|(((_v) & (_f##_V))<<(_f##_S))))); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//get field value from a variable, used when _f is not left shifted by _f##_S
|
|
||||||
#define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f))
|
|
||||||
|
|
||||||
//get field value from a variable, used when _f is left shifted by _f##_S
|
|
||||||
#define VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S))
|
|
||||||
|
|
||||||
//set field value to a variable, used when _f is not left shifted by _f##_S
|
|
||||||
#define VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S))))
|
|
||||||
|
|
||||||
//set field value to a variable, used when _f is left shifted by _f##_S
|
|
||||||
#define VALUE_SET_FIELD2(_r, _f, _v) ((_r)=(((_r) & ~(_f))|((_v)<<(_f##_S))))
|
|
||||||
|
|
||||||
//generate a value from a field value, used when _f is not left shifted by _f##_S
|
|
||||||
#define FIELD_TO_VALUE(_f, _v) (((_v)&(_f))<<_f##_S)
|
|
||||||
|
|
||||||
//generate a value from a field value, used when _f is left shifted by _f##_S
|
|
||||||
#define FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f))
|
|
||||||
|
|
||||||
//read value from register
|
|
||||||
#define READ_PERI_REG(addr) ({ \
|
|
||||||
(*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//write value to register
|
|
||||||
#define WRITE_PERI_REG(addr, val) ({ \
|
|
||||||
(*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//clear bits of register controlled by mask
|
|
||||||
#define CLEAR_PERI_REG_MASK(reg, mask) ({ \
|
|
||||||
WRITE_PERI_REG((reg), (READ_PERI_REG(reg)&(~(mask)))); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//set bits of register controlled by mask
|
|
||||||
#define SET_PERI_REG_MASK(reg, mask) ({ \
|
|
||||||
WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask))); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//get bits of register controlled by mask
|
|
||||||
#define GET_PERI_REG_MASK(reg, mask) ({ \
|
|
||||||
(READ_PERI_REG(reg) & (mask)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//get bits of register controlled by highest bit and lowest bit
|
|
||||||
// #define GET_PERI_REG_BITS(reg, hipos,lowpos) ({
|
|
||||||
// ASSERT_IF_DPORT_REG((reg), GET_PERI_REG_BITS);
|
|
||||||
// ((READ_PERI_REG(reg)>>(lowpos))&((1UL<<((hipos)-(lowpos)+1))-1));
|
|
||||||
// })
|
|
||||||
#define GET_PERI_REG_BITS(reg, bit_map, shift) ((READ_PERI_REG(reg))&((bit_map)<<(shift)))>>shift
|
|
||||||
|
|
||||||
//set bits of register controlled by mask and shift
|
|
||||||
#define SET_PERI_REG_BITS(reg,bit_map,value,shift) ({ \
|
|
||||||
(WRITE_PERI_REG((reg),(READ_PERI_REG(reg)&(~((bit_map)<<(shift))))|(((value) & bit_map)<<(shift)) )); \
|
|
||||||
})
|
|
||||||
|
|
||||||
//get field of register
|
|
||||||
#define GET_PERI_REG_BITS2(reg, mask,shift) ({ \
|
|
||||||
((READ_PERI_REG(reg)>>(shift))&(mask)); \
|
|
||||||
})
|
|
||||||
//}}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -4,96 +4,5 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#warning ulp_riscv_utils.h has been moved one level up. Please include the file without the ulp_riscv prefix.
|
||||||
|
#include "ulp_riscv_utils.h"
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Wakeup main CPU from sleep or deep sleep.
|
|
||||||
*
|
|
||||||
* This raises a software interrupt signal, if the
|
|
||||||
* main CPU is configured the ULP as a wakeup source
|
|
||||||
* calling this function will make the main CPU to
|
|
||||||
* exit from sleep or deep sleep.
|
|
||||||
*/
|
|
||||||
void ulp_riscv_wakeup_main_processor(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Rescues the cpu from monitor mode
|
|
||||||
*
|
|
||||||
* This function cancels the low power mode
|
|
||||||
* of the ULP-RISC-V, should be called
|
|
||||||
* every time the co-processor starts.
|
|
||||||
*
|
|
||||||
* @note by convenience this function is
|
|
||||||
* automatically called in startup code.
|
|
||||||
*/
|
|
||||||
void ulp_riscv_rescue_from_monitor(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Finishes the ULP program and powers down the ULP
|
|
||||||
* until next wakeup.
|
|
||||||
*
|
|
||||||
* @note This function does not return. After called it will
|
|
||||||
* fully reset the ULP.
|
|
||||||
*
|
|
||||||
* @note Returning from main() in the ULP program results on
|
|
||||||
* calling this function.
|
|
||||||
*
|
|
||||||
* @note To stop the ULP from waking up, call ulp_riscv_timer_stop()
|
|
||||||
* before halting.
|
|
||||||
*
|
|
||||||
* This function should be called after the ULP program Finishes
|
|
||||||
* its processing, it will trigger the timer for the next wakeup,
|
|
||||||
* put the ULP in monitor mode and triggers a reset.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void __attribute__((noreturn)) ulp_riscv_halt(void);
|
|
||||||
|
|
||||||
#define ulp_riscv_shutdown ulp_riscv_halt
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Stop the ULP timer
|
|
||||||
*
|
|
||||||
* @note This will stop the ULP from waking up if halted, but will not abort any program
|
|
||||||
* currently executing on the ULP.
|
|
||||||
*/
|
|
||||||
void ulp_riscv_timer_stop(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Resumes the ULP timer
|
|
||||||
*
|
|
||||||
* @note This will resume an already configured timer, but does no other configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void ulp_riscv_timer_resume(void);
|
|
||||||
|
|
||||||
#define ULP_RISCV_GET_CCOUNT() ({ int __ccount; \
|
|
||||||
asm volatile("rdcycle %0;" : "=r"(__ccount)); \
|
|
||||||
__ccount; })
|
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
/* These are only approximate default numbers, the default frequency
|
|
||||||
of the 8M oscillator is 8.5MHz +/- 5%, at the default DCAP setting
|
|
||||||
*/
|
|
||||||
#define ULP_RISCV_CYCLES_PER_US 8.5
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
||||||
#define ULP_RISCV_CYCLES_PER_US 17.5
|
|
||||||
#endif
|
|
||||||
#define ULP_RISCV_CYCLES_PER_MS ULP_RISCV_CYCLES_PER_US*1000
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Makes the co-processor busy wait for a certain number of cycles
|
|
||||||
*
|
|
||||||
* @param cycles Number of cycles to busy wait
|
|
||||||
*/
|
|
||||||
void ulp_riscv_delay_cycles(uint32_t cycles);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
124
components/ulp/ulp_riscv/include/ulp_riscv_gpio.h
Normal file
124
components/ulp/ulp_riscv/include/ulp_riscv_gpio.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "soc/rtc_io_reg.h"
|
||||||
|
#include "soc/sens_reg.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GPIO_NUM_0 = 0, /*!< GPIO0, input and output */
|
||||||
|
GPIO_NUM_1 = 1, /*!< GPIO1, input and output */
|
||||||
|
GPIO_NUM_2 = 2, /*!< GPIO2, input and output */
|
||||||
|
GPIO_NUM_3 = 3, /*!< GPIO3, input and output */
|
||||||
|
GPIO_NUM_4 = 4, /*!< GPIO4, input and output */
|
||||||
|
GPIO_NUM_5 = 5, /*!< GPIO5, input and output */
|
||||||
|
GPIO_NUM_6 = 6, /*!< GPIO6, input and output */
|
||||||
|
GPIO_NUM_7 = 7, /*!< GPIO7, input and output */
|
||||||
|
GPIO_NUM_8 = 8, /*!< GPIO8, input and output */
|
||||||
|
GPIO_NUM_9 = 9, /*!< GPIO9, input and output */
|
||||||
|
GPIO_NUM_10 = 10, /*!< GPIO10, input and output */
|
||||||
|
GPIO_NUM_11 = 11, /*!< GPIO11, input and output */
|
||||||
|
GPIO_NUM_12 = 12, /*!< GPIO12, input and output */
|
||||||
|
GPIO_NUM_13 = 13, /*!< GPIO13, input and output */
|
||||||
|
GPIO_NUM_14 = 14, /*!< GPIO14, input and output */
|
||||||
|
GPIO_NUM_15 = 15, /*!< GPIO15, input and output */
|
||||||
|
GPIO_NUM_16 = 16, /*!< GPIO16, input and output */
|
||||||
|
GPIO_NUM_17 = 17, /*!< GPIO17, input and output */
|
||||||
|
GPIO_NUM_18 = 18, /*!< GPIO18, input and output */
|
||||||
|
GPIO_NUM_19 = 19, /*!< GPIO19, input and output */
|
||||||
|
GPIO_NUM_20 = 20,
|
||||||
|
GPIO_NUM_21 = 21, /*!< GPIO21, input and output */
|
||||||
|
} gpio_num_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RTCIO_MODE_OUTPUT = 0,
|
||||||
|
RTCIO_MODE_OUTPUT_OD = 1,
|
||||||
|
} rtc_io_out_mode_t;
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_init(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
SET_PERI_REG_MASK(SENS_SAR_IO_MUX_CONF_REG, SENS_IOMUX_CLK_GATE_EN_M);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
SET_PERI_REG_MASK(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_IOMUX_CLK_EN_M);
|
||||||
|
#endif
|
||||||
|
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_MUX_SEL);
|
||||||
|
REG_SET_FIELD(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_SEL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_deinit(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_MUX_SEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_output_enable(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS, BIT(gpio_num));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_output_disable(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC, BIT(gpio_num));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_input_enable(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_IE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_input_disable(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_IE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_output_level(gpio_num_t gpio_num, uint8_t level)
|
||||||
|
{
|
||||||
|
if (level) {
|
||||||
|
REG_SET_FIELD(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS, BIT(gpio_num));
|
||||||
|
} else {
|
||||||
|
REG_SET_FIELD(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TS, BIT(gpio_num));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t ulp_riscv_gpio_get_level(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
return (uint8_t)((REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & BIT(gpio_num)) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_set_output_mode(gpio_num_t gpio_num, rtc_io_out_mode_t mode)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_DRV, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_pullup(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_pullup_disable(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_pulldown(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_riscv_gpio_pulldown_disable(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
140
components/ulp/ulp_riscv/include/ulp_riscv_register_ops.h
Normal file
140
components/ulp/ulp_riscv/include/ulp_riscv_register_ops.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#define ULP_RISCV_REGISTER_OPS
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//Registers Operation {{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When COCPU accesses the RTC register, it needs to convert the access address.
|
||||||
|
* When COCPU accesses the RTC memory, dont need to convert the access address.
|
||||||
|
*/
|
||||||
|
#define WRITE_RTC_MEM(addr, val) (*((volatile int*)(addr))) = (int) (val)
|
||||||
|
#define READ_RTC_MEM(addr) (*(volatile int*)(addr))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When COCPU accesses the RTC register, it needs to convert the access address.
|
||||||
|
* When COCPU accesses the RTC memory, dont need to convert the access address.
|
||||||
|
*/
|
||||||
|
#define RISCV_REG_CONV(addr) (((addr&0xffff)<<3 & 0xe000) | (addr & 0x1fff) | 0x8000)
|
||||||
|
#define ETS_UNCACHED_ADDR(addr) (RISCV_REG_CONV(addr))
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
#define BIT(nr) (1UL << (nr))
|
||||||
|
#else
|
||||||
|
#define BIT(nr) (1 << (nr))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//write value to register
|
||||||
|
#define REG_WRITE(_r, _v) ({ \
|
||||||
|
(*(volatile uint32_t *)RISCV_REG_CONV(_r)) = (_v); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//read value from register
|
||||||
|
#define REG_READ(_r) ({ \
|
||||||
|
(*(volatile uint32_t *)RISCV_REG_CONV(_r)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//get bit or get bits from register
|
||||||
|
#define REG_GET_BIT(_r, _b) ({ \
|
||||||
|
(*(volatile uint32_t*)RISCV_REG_CONV(_r) & (_b)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//set bit or set bits to register
|
||||||
|
#define REG_SET_BIT(_r, _b) ({ \
|
||||||
|
(*(volatile uint32_t*)RISCV_REG_CONV(_r) |= (_b)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//clear bit or clear bits of register
|
||||||
|
#define REG_CLR_BIT(_r, _b) ({ \
|
||||||
|
(*(volatile uint32_t*)RISCV_REG_CONV(_r) &= ~(_b)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//set bits of register controlled by mask
|
||||||
|
#define REG_SET_BITS(_r, _b, _m) ({ \
|
||||||
|
(*(volatile uint32_t*)RISCV_REG_CONV(_r) = (*(volatile uint32_t*)RISCV_REG_CONV(_r) & ~(_m)) | ((_b) & (_m))); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//get field from register, uses field _S & _V to determine mask
|
||||||
|
#define REG_GET_FIELD(_r, _f) ({ \
|
||||||
|
((REG_READ(_r) >> (_f##_S)) & (_f##_V)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//set field of a register from variable, uses field _S & _V to determine mask
|
||||||
|
#define REG_SET_FIELD(_r, _f, _v) ({ \
|
||||||
|
(REG_WRITE((_r),((REG_READ(_r) & ~((_f##_V) << (_f##_S)))|(((_v) & (_f##_V))<<(_f##_S))))); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//get field value from a variable, used when _f is not left shifted by _f##_S
|
||||||
|
#define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f))
|
||||||
|
|
||||||
|
//get field value from a variable, used when _f is left shifted by _f##_S
|
||||||
|
#define VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S))
|
||||||
|
|
||||||
|
//set field value to a variable, used when _f is not left shifted by _f##_S
|
||||||
|
#define VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S))))
|
||||||
|
|
||||||
|
//set field value to a variable, used when _f is left shifted by _f##_S
|
||||||
|
#define VALUE_SET_FIELD2(_r, _f, _v) ((_r)=(((_r) & ~(_f))|((_v)<<(_f##_S))))
|
||||||
|
|
||||||
|
//generate a value from a field value, used when _f is not left shifted by _f##_S
|
||||||
|
#define FIELD_TO_VALUE(_f, _v) (((_v)&(_f))<<_f##_S)
|
||||||
|
|
||||||
|
//generate a value from a field value, used when _f is left shifted by _f##_S
|
||||||
|
#define FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f))
|
||||||
|
|
||||||
|
//read value from register
|
||||||
|
#define READ_PERI_REG(addr) ({ \
|
||||||
|
(*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//write value to register
|
||||||
|
#define WRITE_PERI_REG(addr, val) ({ \
|
||||||
|
(*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//clear bits of register controlled by mask
|
||||||
|
#define CLEAR_PERI_REG_MASK(reg, mask) ({ \
|
||||||
|
WRITE_PERI_REG((reg), (READ_PERI_REG(reg)&(~(mask)))); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//set bits of register controlled by mask
|
||||||
|
#define SET_PERI_REG_MASK(reg, mask) ({ \
|
||||||
|
WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask))); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//get bits of register controlled by mask
|
||||||
|
#define GET_PERI_REG_MASK(reg, mask) ({ \
|
||||||
|
(READ_PERI_REG(reg) & (mask)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//get bits of register controlled by highest bit and lowest bit
|
||||||
|
// #define GET_PERI_REG_BITS(reg, hipos,lowpos) ({
|
||||||
|
// ASSERT_IF_DPORT_REG((reg), GET_PERI_REG_BITS);
|
||||||
|
// ((READ_PERI_REG(reg)>>(lowpos))&((1UL<<((hipos)-(lowpos)+1))-1));
|
||||||
|
// })
|
||||||
|
#define GET_PERI_REG_BITS(reg, bit_map, shift) ((READ_PERI_REG(reg))&((bit_map)<<(shift)))>>shift
|
||||||
|
|
||||||
|
//set bits of register controlled by mask and shift
|
||||||
|
#define SET_PERI_REG_BITS(reg,bit_map,value,shift) ({ \
|
||||||
|
(WRITE_PERI_REG((reg),(READ_PERI_REG(reg)&(~((bit_map)<<(shift))))|(((value) & bit_map)<<(shift)) )); \
|
||||||
|
})
|
||||||
|
|
||||||
|
//get field of register
|
||||||
|
#define GET_PERI_REG_BITS2(reg, mask,shift) ({ \
|
||||||
|
((READ_PERI_REG(reg)>>(shift))&(mask)); \
|
||||||
|
})
|
||||||
|
//}}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
101
components/ulp/ulp_riscv/include/ulp_riscv_utils.h
Normal file
101
components/ulp/ulp_riscv/include/ulp_riscv_utils.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "ulp_riscv_register_ops.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wakeup main CPU from sleep or deep sleep.
|
||||||
|
*
|
||||||
|
* This raises a software interrupt signal, if the
|
||||||
|
* main CPU is configured the ULP as a wakeup source
|
||||||
|
* calling this function will make the main CPU to
|
||||||
|
* exit from sleep or deep sleep.
|
||||||
|
*/
|
||||||
|
void ulp_riscv_wakeup_main_processor(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Rescues the cpu from monitor mode
|
||||||
|
*
|
||||||
|
* This function cancels the low power mode
|
||||||
|
* of the ULP-RISC-V, should be called
|
||||||
|
* every time the co-processor starts.
|
||||||
|
*
|
||||||
|
* @note by convenience this function is
|
||||||
|
* automatically called in startup code.
|
||||||
|
*/
|
||||||
|
void ulp_riscv_rescue_from_monitor(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finishes the ULP program and powers down the ULP
|
||||||
|
* until next wakeup.
|
||||||
|
*
|
||||||
|
* @note This function does not return. After called it will
|
||||||
|
* fully reset the ULP.
|
||||||
|
*
|
||||||
|
* @note Returning from main() in the ULP program results on
|
||||||
|
* calling this function.
|
||||||
|
*
|
||||||
|
* @note To stop the ULP from waking up, call ulp_riscv_timer_stop()
|
||||||
|
* before halting.
|
||||||
|
*
|
||||||
|
* This function should be called after the ULP program Finishes
|
||||||
|
* its processing, it will trigger the timer for the next wakeup,
|
||||||
|
* put the ULP in monitor mode and triggers a reset.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void __attribute__((noreturn)) ulp_riscv_halt(void);
|
||||||
|
|
||||||
|
#define ulp_riscv_shutdown ulp_riscv_halt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop the ULP timer
|
||||||
|
*
|
||||||
|
* @note This will stop the ULP from waking up if halted, but will not abort any program
|
||||||
|
* currently executing on the ULP.
|
||||||
|
*/
|
||||||
|
void ulp_riscv_timer_stop(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resumes the ULP timer
|
||||||
|
*
|
||||||
|
* @note This will resume an already configured timer, but does no other configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ulp_riscv_timer_resume(void);
|
||||||
|
|
||||||
|
#define ULP_RISCV_GET_CCOUNT() ({ int __ccount; \
|
||||||
|
asm volatile("rdcycle %0;" : "=r"(__ccount)); \
|
||||||
|
__ccount; })
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
/* These are only approximate default numbers, the default frequency
|
||||||
|
of the 8M oscillator is 8.5MHz +/- 5%, at the default DCAP setting
|
||||||
|
*/
|
||||||
|
#define ULP_RISCV_CYCLES_PER_US 8.5
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
#define ULP_RISCV_CYCLES_PER_US 17.5
|
||||||
|
#endif
|
||||||
|
#define ULP_RISCV_CYCLES_PER_MS ULP_RISCV_CYCLES_PER_US*1000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Makes the co-processor busy wait for a certain number of cycles
|
||||||
|
*
|
||||||
|
* @param cycles Number of cycles to busy wait
|
||||||
|
*/
|
||||||
|
void ulp_riscv_delay_cycles(uint32_t cycles);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -12,18 +12,12 @@
|
|||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_private/esp_clk.h"
|
#include "esp_private/esp_clk.h"
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#include "ulp_riscv.h"
|
||||||
#include "esp32s2/ulp.h"
|
|
||||||
#include "esp32s2/ulp_riscv.h"
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
||||||
#include "esp32s3/ulp.h"
|
|
||||||
#include "esp32s3/ulp_riscv.h"
|
|
||||||
#endif
|
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "soc/sens_reg.h"
|
#include "soc/sens_reg.h"
|
||||||
#include "ulp_private.h"
|
#include "ulp_common.h"
|
||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
|
|
||||||
esp_err_t ulp_riscv_run(void)
|
esp_err_t ulp_riscv_run(void)
|
||||||
@ -123,14 +117,14 @@ esp_err_t ulp_riscv_load_binary(const uint8_t* program_binary, size_t program_si
|
|||||||
if (program_binary == NULL) {
|
if (program_binary == NULL) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
if (program_size_bytes > ULP_RESERVE_MEM) {
|
if (program_size_bytes > CONFIG_ULP_COPROC_RESERVE_MEM) {
|
||||||
return ESP_ERR_INVALID_SIZE;
|
return ESP_ERR_INVALID_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* base = (uint8_t*) RTC_SLOW_MEM;
|
uint8_t* base = (uint8_t*) RTC_SLOW_MEM;
|
||||||
|
|
||||||
//Start by clearing memory reserved with zeros, this will also will initialize the bss:
|
//Start by clearing memory reserved with zeros, this will also will initialize the bss:
|
||||||
memset(base, 0, ULP_RESERVE_MEM);
|
memset(base, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
memcpy(base, program_binary, program_size_bytes);
|
memcpy(base, program_binary, program_size_bytes);
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
@ -4,8 +4,11 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ulp_riscv/ulp_riscv.h"
|
#include "ulp_riscv_utils.h"
|
||||||
#include "ulp_riscv/ulp_riscv_utils.h"
|
#include "ulp_riscv_register_ops.h"
|
||||||
|
#include "soc/soc.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/soc_ulp.h"
|
||||||
|
|
||||||
void ulp_riscv_rescue_from_monitor(void)
|
void ulp_riscv_rescue_from_monitor(void)
|
||||||
{
|
{
|
||||||
|
@ -195,7 +195,10 @@ INPUT = \
|
|||||||
$(PROJECT_PATH)/components/esp_rom/include/esp_rom_sys.h \
|
$(PROJECT_PATH)/components/esp_rom/include/esp_rom_sys.h \
|
||||||
$(PROJECT_PATH)/components/esp_system/include/esp_system.h \
|
$(PROJECT_PATH)/components/esp_system/include/esp_system.h \
|
||||||
$(PROJECT_PATH)/components/esp_common/include/esp_idf_version.h \
|
$(PROJECT_PATH)/components/esp_common/include/esp_idf_version.h \
|
||||||
$(PROJECT_PATH)/components/ulp/include/ulp_common.h \
|
$(PROJECT_PATH)/components/ulp/ulp_common/include/ulp_common.h \
|
||||||
|
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/ulp_fsm_common.h \
|
||||||
|
$(PROJECT_PATH)/components/ulp/ulp_riscv/include/ulp_riscv.h \
|
||||||
|
$(PROJECT_PATH)/components/ulp/ulp_riscv/include/ulp_riscv_utils.h \
|
||||||
$(PROJECT_PATH)/components/app_trace/include/esp_app_trace.h \
|
$(PROJECT_PATH)/components/app_trace/include/esp_app_trace.h \
|
||||||
$(PROJECT_PATH)/components/app_trace/include/esp_sysview_trace.h \
|
$(PROJECT_PATH)/components/app_trace/include/esp_sysview_trace.h \
|
||||||
$(PROJECT_PATH)/components/esp_pm/include/esp_pm.h \
|
$(PROJECT_PATH)/components/esp_pm/include/esp_pm.h \
|
||||||
|
@ -9,6 +9,7 @@ INPUT += \
|
|||||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
|
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
|
||||||
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32/himem.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32/himem.h \
|
||||||
$(PROJECT_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \
|
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \
|
||||||
|
$(PROJECT_PATH)/components/ulp/ulp_common/include/$(IDF_TARGET)/ulp_common_defs.h \
|
||||||
$(PROJECT_PATH)/components/esp_system/include/esp_ipc.h \
|
$(PROJECT_PATH)/components/esp_system/include/esp_ipc.h \
|
||||||
$(PROJECT_PATH)/components/esp_system/include/esp_ipc_isr.h
|
$(PROJECT_PATH)/components/esp_system/include/esp_ipc_isr.h
|
||||||
|
@ -9,8 +9,8 @@ INPUT += \
|
|||||||
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_ds.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_ds.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_hmac.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_hmac.h \
|
||||||
$(PROJECT_PATH)/components/ulp/include/esp32s2/ulp_riscv.h \
|
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \
|
||||||
$(PROJECT_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \
|
$(PROJECT_PATH)/components/ulp/ulp_common/include/$(IDF_TARGET)/ulp_common_defs.h \
|
||||||
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_element.h \
|
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_element.h \
|
||||||
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_button.h \
|
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_button.h \
|
||||||
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_slider.h \
|
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_slider.h \
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
INPUT += \
|
INPUT += \
|
||||||
$(PROJECT_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \
|
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_hmac.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_hmac.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
||||||
$(PROJECT_PATH)/components/hal/include/hal/mcpwm_types.h \
|
$(PROJECT_PATH)/components/hal/include/hal/mcpwm_types.h \
|
||||||
@ -8,8 +7,8 @@ INPUT += \
|
|||||||
$(PROJECT_PATH)/components/driver/include/driver/pcnt.h \
|
$(PROJECT_PATH)/components/driver/include/driver/pcnt.h \
|
||||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
|
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
|
||||||
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
||||||
$(PROJECT_PATH)/components/ulp/include/esp32s3/ulp_riscv.h \
|
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \
|
||||||
$(PROJECT_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \
|
$(PROJECT_PATH)/components/ulp/ulp_common/include/$(IDF_TARGET)/ulp_common_defs.h \
|
||||||
$(PROJECT_PATH)/components/usb/include/usb/usb_helpers.h \
|
$(PROJECT_PATH)/components/usb/include/usb/usb_helpers.h \
|
||||||
$(PROJECT_PATH)/components/usb/include/usb/usb_host.h \
|
$(PROJECT_PATH)/components/usb/include/usb/usb_host.h \
|
||||||
$(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \
|
$(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \
|
||||||
|
@ -116,7 +116,7 @@ Starting the ULP-RISC-V Program
|
|||||||
|
|
||||||
To run a ULP-RISC-V program, the main application needs to load the ULP program into RTC memory using the :cpp:func:`ulp_riscv_load_binary` function, and then start it using the :cpp:func:`ulp_riscv_run` function.
|
To run a ULP-RISC-V program, the main application needs to load the ULP program into RTC memory using the :cpp:func:`ulp_riscv_load_binary` function, and then start it using the :cpp:func:`ulp_riscv_run` function.
|
||||||
|
|
||||||
Note that `CONFIG_ESP32S2_ULP_COPROC_ENABLED` and `CONFIG_ESP32S2_ULP_COPROC_RISCV` options must be enabled in menuconfig to reserve memory for the ULP. "RTC slow memory reserved for coprocessor" option must be set to a value sufficient to store ULP code and data. If the application components contain multiple ULP programs, then the size of the RTC memory must be sufficient to hold the largest one.
|
Note that `CONFIG_ULP_COPROC_ENABLED` and `CONFIG_ULP_COPROC_TYPE_RISCV` options must be enabled in menuconfig to reserve memory for the ULP. "RTC slow memory reserved for coprocessor" option must be set to a value sufficient to store ULP code and data. If the application components contain multiple ULP programs, then the size of the RTC memory must be sufficient to hold the largest one.
|
||||||
|
|
||||||
Each ULP-RISC-V program is embedded into the ESP-IDF application as a binary blob. The application can reference this blob and load it in the following way (suppose ULP_APP_NAME was defined to ``ulp_app_name``)
|
Each ULP-RISC-V program is embedded into the ESP-IDF application as a binary blob. The application can reference this blob and load it in the following way (suppose ULP_APP_NAME was defined to ``ulp_app_name``)
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ ULP-RISC-V 协处理器代码以 C 语言编写(也可能是汇编语言),
|
|||||||
|
|
||||||
要运行 ULP-RISC-V 程序,主程序需要调用 :cpp:func:`ulp_riscv_load_binary` 函数,将 ULP 程序加载到 RTC 内存中,然后调用 :cpp:func:`ulp_riscv_run` 函数,启动 ULP-RISC-V 程序。
|
要运行 ULP-RISC-V 程序,主程序需要调用 :cpp:func:`ulp_riscv_load_binary` 函数,将 ULP 程序加载到 RTC 内存中,然后调用 :cpp:func:`ulp_riscv_run` 函数,启动 ULP-RISC-V 程序。
|
||||||
|
|
||||||
注意,必须在 menuconfig 中启用 `CONFIG_ESP32S2_ULP_COPROC_ENABLED` 和 `CONFIG_ESP32S2_ULP_COPROC_RISCV` 选项,以便为 ULP 预留内存。"RTC slow memory reserved for coprocessor" 选项设置的值必须足够存储 ULP 代码和数据。如果应用程序组件包含多个 ULP 程序,RTC 内存必须足以容纳最大的程序。
|
注意,必须在 menuconfig 中启用 `CONFIG_ULP_COPROC_ENABLED` 和 `CONFIG_ULP_COPROC_TYPE_RISCV` 选项,以便为 ULP 预留内存。"RTC slow memory reserved for coprocessor" 选项设置的值必须足够存储 ULP 代码和数据。如果应用程序组件包含多个 ULP 程序,RTC 内存必须足以容纳最大的程序。
|
||||||
|
|
||||||
每个 ULP-RISC-V 程序均以二进制 BLOB 的形式嵌入到 ESP-IDF 应用程序中。应用程序可以引用此 BLOB,并以下面的方式加载此 BLOB(假设 ULP_APP_NAME 已被定义为 ``ulp_app_name``):
|
每个 ULP-RISC-V 程序均以二进制 BLOB 的形式嵌入到 ESP-IDF 应用程序中。应用程序可以引用此 BLOB,并以下面的方式加载此 BLOB(假设 ULP_APP_NAME 已被定义为 ``ulp_app_name``):
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# Enable ULP
|
# Enable ULP
|
||||||
CONFIG_ESP32_ULP_COPROC_ENABLED=y
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=1024
|
CONFIG_ULP_COPROC_TYPE_FSM=y
|
||||||
|
CONFIG_ULP_COPROC_RESERVE_MEM=1024
|
||||||
# Set log level to Warning to produce clean output
|
# Set log level to Warning to produce clean output
|
||||||
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||||
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# Enable ULP
|
# Enable ULP
|
||||||
CONFIG_ESP32_ULP_COPROC_ENABLED=y
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=1024
|
CONFIG_ULP_COPROC_TYPE_FSM=y
|
||||||
|
CONFIG_ULP_COPROC_RESERVE_MEM=1024
|
||||||
# Set log level to Warning to produce clean output
|
# Set log level to Warning to produce clean output
|
||||||
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||||
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "ulp_riscv/ulp_riscv.h"
|
#include "ulp_riscv.h"
|
||||||
#include "ulp_riscv/ulp_riscv_utils.h"
|
#include "ulp_riscv_utils.h"
|
||||||
#include "ulp_riscv/ulp_riscv_gpio.h"
|
#include "ulp_riscv_gpio.h"
|
||||||
|
|
||||||
#define EXAMPLE_1WIRE_GPIO GPIO_NUM_4
|
#define EXAMPLE_1WIRE_GPIO GPIO_NUM_4
|
||||||
|
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
#include "hal/rtc_io_ll.h"
|
#include "hal/rtc_io_ll.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "driver/rtc_io.h"
|
#include "driver/rtc_io.h"
|
||||||
#include "esp32s2/ulp.h"
|
#include "ulp_riscv.h"
|
||||||
#include "esp32s2/ulp_riscv.h"
|
|
||||||
#include "ulp_main.h"
|
#include "ulp_main.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
CONFIG_IDF_TARGET="esp32s2"
|
CONFIG_IDF_TARGET="esp32s2"
|
||||||
# Enable ULP
|
# Enable ULP
|
||||||
CONFIG_ESP32S2_ULP_COPROC_ENABLED=y
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
CONFIG_ESP32S2_ULP_COPROC_RISCV=y
|
CONFIG_ULP_COPROC_RISCV=y
|
||||||
CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=4096
|
CONFIG_ULP_COPROC_RESERVE_MEM=4096
|
||||||
# Set log level to Warning to produce clean output
|
# Set log level to Warning to produce clean output
|
||||||
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||||
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "ulp_riscv/ulp_riscv.h"
|
#include "ulp_riscv.h"
|
||||||
#include "ulp_riscv/ulp_riscv_utils.h"
|
#include "ulp_riscv_utils.h"
|
||||||
#include "ulp_riscv/ulp_riscv_gpio.h"
|
#include "ulp_riscv_gpio.h"
|
||||||
|
|
||||||
static bool gpio_level = false;
|
static bool gpio_level = false;
|
||||||
|
|
||||||
|
@ -14,8 +14,7 @@
|
|||||||
#include "soc/rtc_periph.h"
|
#include "soc/rtc_periph.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "driver/rtc_io.h"
|
#include "driver/rtc_io.h"
|
||||||
#include "esp32s2/ulp.h"
|
#include "ulp_riscv.h"
|
||||||
#include "esp32s2/ulp_riscv.h"
|
|
||||||
#include "ulp_main.h"
|
#include "ulp_main.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
CONFIG_IDF_TARGET="esp32s2"
|
CONFIG_IDF_TARGET="esp32s2"
|
||||||
# Enable ULP
|
# Enable ULP
|
||||||
CONFIG_ESP32S2_ULP_COPROC_ENABLED=y
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
CONFIG_ESP32S2_ULP_COPROC_RISCV=y
|
CONFIG_ULP_COPROC_RISCV=y
|
||||||
CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=4096
|
CONFIG_ULP_COPROC_RESERVE_MEM=4096
|
||||||
# Set log level to Warning to produce clean output
|
# Set log level to Warning to produce clean output
|
||||||
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||||
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||||
|
@ -2053,14 +2053,7 @@ components/touch_element/touch_element.c
|
|||||||
components/touch_element/touch_matrix.c
|
components/touch_element/touch_matrix.c
|
||||||
components/touch_element/touch_slider.c
|
components/touch_element/touch_slider.c
|
||||||
components/ulp/esp32ulp_mapgen.py
|
components/ulp/esp32ulp_mapgen.py
|
||||||
components/ulp/ld/esp32.ulp.ld
|
|
||||||
components/ulp/ld/esp32s2.ulp.riscv.ld
|
|
||||||
components/ulp/test/esp32/test_ulp.c
|
|
||||||
components/ulp/test/esp32/test_ulp_as.c
|
components/ulp/test/esp32/test_ulp_as.c
|
||||||
components/ulp/ulp_macro.c
|
|
||||||
components/ulp/ulp_private.h
|
|
||||||
components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv.h
|
|
||||||
components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_register_ops.h
|
|
||||||
components/unity/include/priv/setjmp.h
|
components/unity/include/priv/setjmp.h
|
||||||
components/unity/include/unity_config.h
|
components/unity/include/unity_config.h
|
||||||
components/unity/include/unity_fixture_extras.h
|
components/unity/include/unity_fixture_extras.h
|
||||||
|
@ -2,3 +2,4 @@ CONFIG_IDF_TARGET="esp32"
|
|||||||
TEST_COMPONENTS=esp_pm
|
TEST_COMPONENTS=esp_pm
|
||||||
CONFIG_PM_ENABLE=y
|
CONFIG_PM_ENABLE=y
|
||||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||||
|
CONFIG_ULP_COPROC_TYPE_FSM=y
|
||||||
|
@ -2,3 +2,4 @@ CONFIG_IDF_TARGET="esp32s2"
|
|||||||
TEST_COMPONENTS=esp_pm
|
TEST_COMPONENTS=esp_pm
|
||||||
CONFIG_PM_ENABLE=y
|
CONFIG_PM_ENABLE=y
|
||||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||||
|
CONFIG_ULP_COPROC_TYPE_FSM=y
|
||||||
|
@ -2,3 +2,4 @@ CONFIG_IDF_TARGET="esp32s3"
|
|||||||
TEST_COMPONENTS=esp_pm
|
TEST_COMPONENTS=esp_pm
|
||||||
CONFIG_PM_ENABLE=y
|
CONFIG_PM_ENABLE=y
|
||||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||||
|
CONFIG_ULP_COPROC_TYPE_FSM=y
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||||
CONFIG_ESP32_XTAL_FREQ_AUTO=y
|
CONFIG_ESP32_XTAL_FREQ_AUTO=y
|
||||||
CONFIG_ESP32_ULP_COPROC_ENABLED=y
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
|
CONFIG_ULP_COPROC_TYPE_FSM=y
|
||||||
|
CONFIG_ULP_COPROC_RESERVE_MEM=4096
|
||||||
CONFIG_SPI_FLASH_SHARE_SPI1_BUS=y
|
CONFIG_SPI_FLASH_SHARE_SPI1_BUS=y
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y
|
CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y
|
||||||
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
|
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
|
||||||
|
|
||||||
CONFIG_ESP32S2_ULP_COPROC_ENABLED=y
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
CONFIG_ESP32S2_ULP_COPROC_RISCV=y
|
CONFIG_ULP_COPROC_TYPE_RISCV=y
|
||||||
CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=4096
|
CONFIG_ULP_COPROC_RESERVE_MEM=4096
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
|
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
|
||||||
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
|
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
|
||||||
|
|
||||||
CONFIG_ESP32S3_ULP_COPROC_ENABLED=y
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
CONFIG_ESP32S3_ULP_COPROC_RISCV=y
|
CONFIG_ULP_COPROC_TYPE_RISCV=y
|
||||||
CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=4096
|
CONFIG_ULP_COPROC_RESERVE_MEM=4096
|
||||||
|
Loading…
Reference in New Issue
Block a user