But when I try to control GPIO, I ran into problems. In short: the GPIO output works from ULP when main processor is running but stops when main processor goes to sleep.
The documentation about what can and cannot be done in ULP is non-existing. Have anyone tried to write GPIO in ULP code?
The ULP code below writes 0 for 10 seconds, 1 for 10 seconds and then again 0 for 10 seconds. Simple voltage meter can be used to check that it is working. If I delay the main processor going into sleep for 30 seconds, ULP code works fine. But If the main goes to sleep immediately, the output pin seems to be floating for whole 30 seconds.
Then I thought that I have to enable peripheral power with esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); It actually seemed to work, couple of times. But the I started to get random ULP Traps, code 11.
Below is the main without headers, the headers are unmodified from riscv sample.
I changed he ULP timer to happen once a second.
Code: Select all
void app_main(void) {
rtc_gpio_init(GPIO_NUM_2);
rtc_gpio_set_direction(GPIO_NUM_2, RTC_GPIO_MODE_OUTPUT_ONLY);
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
if (cause != ESP_SLEEP_WAKEUP_ULP) {
printf("Not a ULP-RISC-V wakeup, cause = %d, initializing it! \n", cause);
init_ulp_program();
// Uncommenting following makes the ULP code work while the main processor is up
// vTaskDelay(30000 / portTICK_PERIOD_MS);
}
if (cause == ESP_SLEEP_WAKEUP_ULP) {
printf("ULP-RISC-V woke up the main CPU! \n");
}
printf("Entering in deep sleep\n\n");
vTaskDelay(100);
// Uncommenting following causes random ULP traps (cause == 11)
// esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
ESP_ERROR_CHECK(esp_sleep_enable_ulp_wakeup());
esp_deep_sleep_start();
}
static void init_ulp_program(void) {
ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start));
ulp_set_wakeup_period(0, 1000000); // one second !
ulp_riscv_run();
}
Code: Select all
#define pin GPIO_NUM_2
int main(void) {
static int count = 0;
if (count == 0) {
// do nothing, main process is not yet in sleep
} else if (count > 0 && count <= 10) {
example_ulp_gpio_output_level(pin, 0);
} else if (count > 10 && count <= 20) {
example_ulp_gpio_output_level(pin, 1);
} else if (count > 20 && count < 30) {
example_ulp_gpio_output_level(pin, 0);
} else if (count >= 30) {
count = 0;
ulp_riscv_wakeup_main_processor();
}
count++;
return 0;
}