gpio isr on both cpu question

jesseb
Posts: 29
Joined: Tue Jan 10, 2017 5:36 pm

gpio isr on both cpu question

Postby jesseb » Mon May 01, 2017 8:33 pm

Can I set two ISRs for gpios running on both CPUs simultaneously?

jesseb
Posts: 29
Joined: Tue Jan 10, 2017 5:36 pm

Re: gpio isr on both cpu question

Postby jesseb » Mon May 01, 2017 8:43 pm

It seems I can from all of the docs and .h files. I'll try it out and let you know how it goes.

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

Re: gpio isr on both cpu question

Postby ESP_Sprite » Tue May 02, 2017 1:18 am

You can, but it probably wouldn't do what you want... the GPIO peripheral only has one interrupt source, so if anything, each GPIO that gets changed would ostensibly call the ISR on both CPUs. ISRs in general are not witten to be run concurrently, so my guess would be that you'd then get a crash in the worst case and interrupts being ignored in the best case. If anything, Espressif does not recommend this.

Is there a reason you need the two interrupts?

jesseb
Posts: 29
Joined: Tue Jan 10, 2017 5:36 pm

Re: gpio isr on both cpu question

Postby jesseb » Wed May 03, 2017 6:04 pm

I'm trying to get an accurate measurement for pulse width but couldn't get the remote control peripheral to work for me, see viewtopic.php?f=2&t=1772#p8256.

I did have a bit of problems calling xQueueSendFromISR from interrupt on app cpu. I changed my code to use flags and got two gpio ISRs working. This allowed me to do some stuff that was messing with latency in ISR on pro cpu and the fast stuff on the ISR on app cpu. A single gpio only has interrupts enabled on one cpu. Here's an Idea of how I did it:

Code: Select all

static void IRAM_ATTR gpioIsr_appCpu(void* arg)
{
    //Low latency needed here
    uint32_t gpioIntStatusL = GPIO.acpu_int; // read status to get interrupt status for GPIO0-31
    uint32_t gpioIntStatusH = GPIO.acpu_int1.intr; // read status1 to get interrupt status for GPIO32-39

    if( shortCircuitDetectMask & gpioIntStatusH )
    {
        //reload timer and alarm
        TIMERG1.hw_timer[0].load_high = 0;
        TIMERG1.hw_timer[0].load_low = 0;
        TIMERG1.hw_timer[0].reload = 1;
        TIMERG1.hw_timer[0].alarm_high = 0;
        TIMERG1.hw_timer[0].alarm_low = shortCircuitDetect_firstPulseWidthThresh_us;

        //enable if pin is low (negative edge occurred), disable if high (positive edge occurred)
        bool enable = !(shortCircuitDetectMask & GPIO.in1.val);
        TIMERG1.hw_timer[0].config.alarm_en = enable;
        TIMERG1.int_ena.t0 = enable;
        TIMERG1.hw_timer[0].config.enable = enable;
    }

    GPIO.status_w1tc = gpioIntStatusL; // Clear intr for gpio0-gpio31
    GPIO.status1_w1tc.intr_st = gpioIntStatusH; // Clear intr for gpio32-39
}

static void IRAM_ATTR gpioIsr_proCpu(void* arg)
{
        uint32_t gpioIntStatusL = GPIO.pcpu_int; // read status to get interrupt status for GPIO0-31
        uint32_t gpioIntStatusH = GPIO.pcpu_int1.intr; // read status1 to get interrupt status for GPIO32-39

        if( (buttonsMaskL & gpioIntStatusL) || (buttonsMaskH & gpioIntStatusH) )
        {
            buttonPressed(true);
        }

        if( encoderMaskA & gpioIntStatusL )
        {
            encoderATriggered();
        }

        if( encoderMaskB & gpioIntStatusL )
        {
            encoderBTriggered();
        }

        if( rtcTickMask & gpioIntStatusL )
        {
            POST_EVENT(state_event_rtcTick);
        }

        GPIO.status_w1tc = gpioIntStatusL; // Clear intr for gpio0-gpio31
        GPIO.status1_w1tc.intr_st = gpioIntStatusH; // Clear intr for gpio32-39
}
I initialized these interrupts from tasks on their respective cpus.

Code: Select all

gpio_isr_register(gpioIsr_proCpu, NULL, ESP_INTR_FLAG_LEVEL1, NULL)
gpio_isr_register(gpioIsr_appCpu, NULL, ESP_INTR_FLAG_LEVEL2, NULL)
The only thing I think I'm missing is protection for clearing the interrupt status since those write to the same registers. It's possible that this will still cause problems as, ESP_Sprite has said, but it seems to be working and I've tried to press it to its limits with a few tests. So far it's the best way that I can answer my pulse width measurement question referenced above even though it's not the ideal solution.

Who is online

Users browsing this forum: No registered users and 95 guests