ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
esp32_ulp.cpp
Go to the documentation of this file.
1#include "esp32_ulp.h"
2
3#if defined(USE_ESP32) && (SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)
4
5#include "esphome/core/log.h"
6
7#include <esp_attr.h>
8#include <esp_sleep.h>
9#include <esp_system.h>
10#if SOC_RISCV_COPROC_SUPPORTED
11#include <ulp_riscv.h>
12#endif
13
14extern const uint8_t ULP_MAIN_BIN_START[] asm("_binary_ulp_main_bin_start");
15extern const size_t ULP_MAIN_BIN_LENGTH asm("ulp_main_bin_length");
16
18
19ESPHOME_LOG_TAG(TAG, "esp32_ulp");
20
21// Survives deep sleep (RTC memory) so a program loaded before sleeping is known
22// to still be running on wake, however it was started.
23// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
24static RTC_DATA_ATTR bool s_program_loaded = false;
25
26#if SOC_RISCV_COPROC_SUPPORTED
27static constexpr const char *BACKEND = "ULP RISC-V";
28#else
29static constexpr const char *BACKEND = "LP core";
30#endif
31
33 if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_ULP) {
34 ESP_LOGI(TAG, "Woken from deep sleep by the %s", BACKEND);
35 }
36#if SOC_RISCV_COPROC_SUPPORTED
37 if (this->wakeup_period_us_ > 0) {
38 esp_err_t err = ulp_set_wakeup_period(0, this->wakeup_period_us_);
39 if (err != ESP_OK) {
40 ESP_LOGE(TAG, "ulp_set_wakeup_period failed: %s", esp_err_to_name(err));
41 this->mark_failed();
42 return;
43 }
44 }
45#endif
46 // After a deep sleep the program is still running in RTC memory; reloading
47 // it would discard its state.
48 if (esp_reset_reason() == ESP_RST_DEEPSLEEP && s_program_loaded) {
49 this->loaded_ = true;
50 } else if (this->run_on_boot_ && !this->load_and_run()) {
51 this->mark_failed();
52 return;
53 }
54 if (this->wakeup_from_sleep_) {
55 esp_err_t err = esp_sleep_enable_ulp_wakeup();
56 if (err != ESP_OK) {
57 ESP_LOGW(TAG, "esp_sleep_enable_ulp_wakeup failed: %s", esp_err_to_name(err));
58 }
59 }
60}
61
63 ESP_LOGCONFIG(TAG,
64 "ESP32 ULP:\n"
65 " Coprocessor: %s\n"
66 " Program size: %u bytes\n"
67 " Wakeup period: %" PRIu32 " us\n"
68 " Run on boot: %s\n"
69 " Wakeup from sleep: %s\n"
70 " Loaded: %s",
71 BACKEND, static_cast<unsigned>(ULP_MAIN_BIN_LENGTH), this->wakeup_period_us_, YESNO(this->run_on_boot_),
72 YESNO(this->wakeup_from_sleep_), YESNO(this->loaded_));
73}
74
76 const size_t size = ULP_MAIN_BIN_LENGTH;
77#if SOC_RISCV_COPROC_SUPPORTED
78 // ulp_riscv_load_binary() overwrites RTC memory without stopping a running
79 // program; the LP core variant stops the core itself.
80 ulp_riscv_halt();
81 esp_err_t err = ulp_riscv_load_binary(ULP_MAIN_BIN_START, size);
82#else
83 esp_err_t err = ulp_lp_core_load_binary(ULP_MAIN_BIN_START, size);
84#endif
85 if (err != ESP_OK) {
86 ESP_LOGE(TAG, "Loading the program failed: %s", esp_err_to_name(err));
87 return false;
88 }
89 if (!this->run_()) {
90 return false;
91 }
92 this->loaded_ = true;
93 s_program_loaded = true;
94 ESP_LOGD(TAG, "Loaded and started %u byte program", static_cast<unsigned>(size));
95 return true;
96}
97
99#if SOC_RISCV_COPROC_SUPPORTED
100 esp_err_t err = ulp_riscv_run();
101#else
102 ulp_lp_core_cfg_t cfg = {};
103 cfg.wakeup_source = this->wakeup_sources_;
104 cfg.lp_timer_sleep_duration_us = this->wakeup_period_us_;
105 esp_err_t err = ulp_lp_core_run(&cfg);
106#endif
107 if (err != ESP_OK) {
108 ESP_LOGE(TAG, "Starting the program failed: %s", esp_err_to_name(err));
109 return false;
110 }
111 return true;
112}
113
115#if SOC_RISCV_COPROC_SUPPORTED
116 ulp_riscv_timer_stop();
117#else
118 ulp_lp_core_stop();
119#endif
120}
121
123 if (!this->loaded_) {
124 return;
125 }
126#if SOC_RISCV_COPROC_SUPPORTED
127 ulp_riscv_timer_resume();
128#else
129 this->run_();
130#endif
131}
132
133} // namespace esphome::esp32_ulp
134
135#endif // USE_ESP32 && (SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)
void mark_failed()
Mark this component as failed.
void timer_resume()
Resume the coprocessor timer.
bool load_and_run()
Load the embedded program into the coprocessor memory and start it.
Definition esp32_ulp.cpp:75
void timer_stop()
Stop the coprocessor timer so the program is not started again.
void dump_config() override
Definition esp32_ulp.cpp:62
ESPHOME_LOG_TAG(TAG, "esp32_ulp")
uint16_t size
Definition helpers.cpp:34