Postpone deep-sleep timer wakeup from ULP
Posted: Mon Jan 20, 2025 5:18 am
Hello, I'm new to the ULP programming and I have the need to detect a lack of pulses on an input GPIO drawing the least current possible.
For now I've managed to achieve this by programming the ULP (RISCV) in order to periodically poll the GPIO for changes like so:
But while measuring the current drawn on my custom board I notice that doing this busy waits using "ulp_riscv_delay_cycles" is not the most efficient way.
I would like to change my code so that:
1. I specify a wakeup timer on my main code (say 500ms)
2. The ULP wakes up by the input GPIO when it is activated (let's say when level==1)
3. Each time the ULP code runs, it "postpones" the wakeup time specified by "esp_sleep_enable_timer_wakeup" (effectively detecting the lack of pulses)
I've already program steps 1 and 2, but I'm not sure how 3 could be done. Can this be achieved?
For now I've managed to achieve this by programming the ULP (RISCV) in order to periodically poll the GPIO for changes like so:
Code: Select all
#include "ulp_riscv_utils.h"
#include "ulp_riscv_gpio.h"
#include "soc/rtc_cntl_reg.h"
#include "ulp_riscv_register_ops.h"
/**
* @brief Read the lower 32 bits of the real time clock counter.
* @note At 150kHz, this value will overflow every ~7.95h.
*
* @return uint32_t
*/
static inline uint32_t ulp_riscv_get_rtc_32() {
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
return READ_PERI_REG(RTC_CNTL_TIME0_REG);
}
gpio_num_t trigger_pin; // GPIO pin to trigger the interrupt.
uint8_t trigger_level; // Trigger level for the interrupt.
uint32_t trigger_timeout_ticks; // Timeout to trigger the wakeup, expressed in RTC clock cycles.
uint32_t trigger_last_ticks; // Last time the trigger was activated, expressed in RTC clock cycles.
uint32_t rtc_ticks;
uint32_t trigger_diff_ticks;
int main(void) {
ulp_riscv_gpio_init(trigger_pin);
ulp_riscv_gpio_input_enable(trigger_pin);
while(1)
{
rtc_ticks = ulp_riscv_get_rtc_32();
// TODO rtc overflow
trigger_diff_ticks = rtc_ticks - trigger_last_ticks;
if ( ulp_riscv_gpio_get_level(trigger_pin) == trigger_level ) {
trigger_last_ticks = rtc_ticks;
}
else if ( trigger_diff_ticks > trigger_timeout_ticks ) {
ulp_riscv_wakeup_main_processor();
// ulp_riscv_timer_stop();
}
ulp_riscv_delay_cycles(50 * ULP_RISCV_CYCLES_PER_US);
}
return 0;
}
I would like to change my code so that:
1. I specify a wakeup timer on my main code (say 500ms)
2. The ULP wakes up by the input GPIO when it is activated (let's say when level==1)
3. Each time the ULP code runs, it "postpones" the wakeup time specified by "esp_sleep_enable_timer_wakeup" (effectively detecting the lack of pulses)
I've already program steps 1 and 2, but I'm not sure how 3 could be done. Can this be achieved?