Timer keeps failing when trying to register ISR within an ISR

matthew798
Posts: 16
Joined: Mon Jun 01, 2020 2:31 am

Timer keeps failing when trying to register ISR within an ISR

Postby matthew798 » Fri Aug 07, 2020 3:25 am

Hi all,

I have a timer that I use to trigger 3 different ISRs. So:
ISR_1 must run every x uSec,
ISR_2 must run every x + 30 uSec,
ISR_3 must run every x + y uSec (where y > 30)

So I set it up like this:
ISR_1 does it's thing then registers ISR_2 on the timer. ISR_2 does the same for ISR_3, and 3 does the same for 1. The loop is infinite. If you need some context, I need to generate a 1kHz square wave, sample the amplitude of the wave 30uSec after it goes high, then return to LOW after a variable amount of time and start all over again.

Here are the 3 ISRs:

Code: Select all

void IRAM_ATTR ControlPilot::PulseLow(void* arg){
    digitalWrite(CP_PWM_PIN, HIGH);
    
    TIMERG0.int_clr_timers.t0 = 1;    
    SCHED_ACTION(CP_PWM_FREQ - highTime, PulseHigh);
}

void IRAM_ATTR ControlPilot::PulseHigh(void* arg){
    digitalWrite(CP_PWM_PIN, LOW);

    TIMERG0.int_clr_timers.t0 = 1;
    SCHED_ACTION(30, Sample);
}

void IRAM_ATTR ControlPilot::Sample(void* arg){
    digitalWrite(32, HIGH);
    adcStart(CP_READ_PIN);
    digitalWrite(32, LOW);

    TIMERG0.int_clr_timers.t0 = 1;
    SCHED_ACTION(highTime - 30, PulseLow);
}
Here is SCHED_ACTION:

Code: Select all

#define SCHED_ACTION(t, a)\
    ESP_ERROR_CHECK(timer_set_alarm_value(timer_group_t::TIMER_GROUP_0, timer_idx_t::TIMER_0, t));\
    ESP_ERROR_CHECK(timer_enable_intr(timer_group_t::TIMER_GROUP_0, timer_idx_t::TIMER_0));\
    ESP_ERROR_CHECK(timer_isr_register(timer_group_t::TIMER_GROUP_0, timer_idx_t::TIMER_0, a, (void *) timer_idx_t::TIMER_0, ESP_INTR_FLAG_IRAM, NULL));
And here is the timer setup:

Code: Select all

    //Set up our timer. We use IDF here because arduino makes too many assumptions
    timer_config_t tConfig = {
        .alarm_en = true,
        .counter_en = timer_start_t::TIMER_PAUSE,
        .intr_type = TIMER_INTR_LEVEL,
        .counter_dir = timer_count_dir_t::TIMER_COUNT_UP,
        .auto_reload = true,
        .divider = 80, //Prescaler of 80 gives us a resolution of 1uS
    };
    ESP_ERROR_CHECK(timer_init(timer_group_t::TIMER_GROUP_0, timer_idx_t::TIMER_0, &tConfig));
    ESP_ERROR_CHECK(timer_set_counter_value(timer_group_t::TIMER_GROUP_0, timer_idx_t::TIMER_0, 0x00000000ULL)); //Timer will reset to this value on alarm
Running this gives me:
ESP_ERROR_CHECK failed: esp_err_t 0x105 (ESP_ERR_NOT_FOUND) at 0x4008cf7c
file: "src/ControlPilot.cpp" line 62
func: static void ControlPilot::PulseHigh(void*)
expression: timer_isr_register(timer_group_t::TIMER_GROUP_0, timer_idx_t::TIMER_0, Sample, (void *) timer_idx_t::TIMER_0, ESP_INTR_FLAG_IRAM, NULL)

Backtrace: 0x4008ca98:0x3ffbe770 0x4008cf7f:0x3ffbe790 0x40081089:0x3ffbe7b0 0x40084dd5:0x3ffbe7d0 0x4000bfed:0x3ffb1e70 0x4008a34d:0x3ffb1e80 0x40128ac9:0x3ffb1ea0 0x400d193a:0x3ffb1ed0 0x400d123f:0x3ffb1ef0 0x400d1282:0x3ffb1f10 0x400d311b:0x3ffb1f30 0x400d122e:0x3ffb1f70 0x400d1d88:0x3ffb1f90 0x400d593d:0x3ffb1fb0 0x400891e1:0x3ffb1fd0
#0 0x4008ca98:0x3ffbe770 in invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:707
#1 0x4008cf7f:0x3ffbe790 in _esp_error_check_failed at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:713
#2 0x40081089:0x3ffbe7b0 in ControlPilot::PulseHigh(void*) at src/ControlPilot.cpp:132
#3 0x40084dd5:0x3ffbe7d0 in _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1154
#4 0x4000bfed:0x3ffb1e70 in ?? ??:0
#5 0x4008a34d:0x3ffb1e80 in vTaskExitCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c:3507
#6 0x40128ac9:0x3ffb1ea0 in timer_start at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/timer.c:268
#7 0x400d193a:0x3ffb1ed0 in ControlPilot::BeginPulse() at src/ControlPilot.cpp:132
#8 0x400d123f:0x3ffb1ef0 in ChargerAtm::EnterVehicleDetected() at src/ChargerAtm.cpp:34
#9 0x400d1282:0x3ffb1f10 in ChargerAtm::action(int) at src/ChargerAtm.cpp:69
#10 0x400d311b:0x3ffb1f30 in Machine::cycle(unsigned int) at lib/Automaton/src/Machine.cpp:230
#11 0x400d122e:0x3ffb1f70 in ChargerAtm::cycle() at src/ChargerAtm.cpp:26
#12 0x400d1d88:0x3ffb1f90 in loop() at src/main.cpp:109
#13 0x400d593d:0x3ffb1fb0 in loopTask(void*) at /home/matthew/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:19
#14 0x400891e1:0x3ffb1fd0 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)

ESP_Sprite
Posts: 9016
Joined: Thu Nov 26, 2015 4:08 am

Re: Timer keeps failing when trying to register ISR within an ISR

Postby ESP_Sprite » Fri Aug 07, 2020 7:39 am

There's a lot of stuff you cannot do in an ISR as it does not allow calls to an blocking function; registering an ISR is one of those. Suggest you use a single ISR instead, which checks a variable (either a plain enum or something fancy like a function pointer) to figure out the subroutine to call.

matthew798
Posts: 16
Joined: Mon Jun 01, 2020 2:31 am

Re: Timer keeps failing when trying to register ISR within an ISR

Postby matthew798 » Fri Aug 07, 2020 2:35 pm

Ah yes, after reading your post I re-read the docs and it is written plain as day. I figure I'll do what you said, have a single ISR with a persistent state between calls. Am I correct in assuming that to set the timer's alarm in an ISR I have to use TIMERG0.hw_timer[0].alarm_high/low?

Who is online

Users browsing this forum: No registered users and 142 guests