GPIO ISR improperly called - "SOLVED" (worked around)

Posts: 11
Joined: Mon Dec 14, 2020 4:42 pm

GPIO ISR improperly called - "SOLVED" (worked around)

Postby sraposo » Fri Jan 15, 2021 7:51 pm

In january, 23rd 2021, title was changed from "Random timer miscount" to "GPIO ISR improperly called"

Check post dated Jan 22, 2021 8:51 pm

"ESP32 DEVKITV1" board


I´m about to develop an application that is time-critical and demand a reasonable precision on timer count.

It´s a simple code that should register how many timer counts occur between two positive edges on square wave signal. I´m using a pretty stable 1KHz square wave generator.

Considering a divider with value 40, it´s expected something around 2000 counts, but I´ve detected a random timer count variation around half of the correct average value.

timer_config_t config0 = {
.alarm_en = false,
.counter_en = false,
.intr_type = TIMER_INTR_LEVEL,
.counter_dir = TIMER_COUNT_UP,
.auto_reload = false,
.divider = 40

Interrupt routine for a certain GPIO on positive transition works perfectly. It never miss a rising edge, never is called when it should not be. When the GPIO interrupt occurs, timer is paused, its value is read and spared and finally timer is started.

Can somebody give me some clue?
Last edited by sraposo on Sun Jan 24, 2021 10:25 am, edited 2 times in total.

Posts: 211
Joined: Fri Jun 02, 2017 6:50 am

Re: Random timer miscount (TIMER_GROUP_0 TIMER_0)

Postby ESP_Dazz » Fri Jan 22, 2021 8:24 pm

There is some delay and variation to when your interrupt will run. Usually when an interrupt occurs, it takes 2 or 3 microseconds to get into the interrupt. However, you can't assume that this means your interrupt will run 2 to 3 us after an edge as there are other factors that can prevent your interrupt from occurring such as:
  • Critical sections which disable interrupts. Critical sections are used pretty much everywhere and its hard to say what the max interrupt delay will be due to a critical sections.
  • Other higher priority interrupts or other interrupt service routines that run before your timer ISR/
IMO there's probably a better approach to timing the period between two edges than using an ISR to start a timer.

- If there's little variation between the period of two edges, and all you need is a rough average of frequency, consider using the pulse counter peripheral instead
- If you need an exact time between two edges and cannot use an average, I suggest writing a high level interrupt in assembly (see docs). The latency of high level interrupts is much short and much more deterministic. However, the downside is that you'll need to write the routine in assembly.

Posts: 11
Joined: Mon Dec 14, 2020 4:42 pm

Re: Random timer miscount (TIMER_GROUP_0 TIMER_0)

Postby sraposo » Fri Jan 22, 2021 11:51 pm

ESP_Dazz, thanx for your reply.

An average 2..3 us delay is ok and I can cope with this.
I need an time as exact as possible between two edges and cannot use an average, since signal frequency is variable.

Initially, I intended to fully code in Assembly to get the most effective program I could since I have to deal with very fast repetitive events, but I've a lot of difficulties trying to learn about. Presently, products of my company use Assembly to control hardware based on other platform and ESP32 seemed to be an interesting option to replace current one with advantages, but specific documentation was not found. I'll take a look on that documentation you've referred.

Anyway, since I've posted here another issues have emerged and a solution for "Random timer miscount", as stated on the topic title, has been found: it was specified that GPIO isr should be call on GPIO_INTR_POSEDGE and randomly a negative edge invoked this isr, resulting in a count error. I am saving your time not detailing code internals 'cause I think it's not relevant, but I can present that if you want.
How did I've got rid of this problem? Including a boolean test at the ISR beginning: if current state of GPIO is high, then execute ISR code, otherwise, get out ISR at that very point. From that moment on, no more improper negative edges being hooked by ISR.

Well, it seems GPIO_INTR_POSEDGE parameter defines a ISR that will be called "ALWAYS" and "ONLY" on a GPIO positive transition, but it is partially true. In my experience, it means "ALWAYS" and "most of time ONLY", eventually on negative transitions.
No, there was never any abrupt voltage variation on the signal that could be interpreted as a (undesirable) positive transition in a negative edge. Considering an eventual so short in time glitch that could be taken as a positive transition, maybe not detectable by my 100MHz 1GSa/s oscilloscope, low-pass RC filter with ceramic capacitor was added to prevent it, but all I've got was a distorted square wave signal when capacitance was very increased, eventually disturbing system operation. Low-pass filter was useless because there was no high frequency noise to eliminate.

Posts: 11
Joined: Mon Dec 14, 2020 4:42 pm

Re: Random timer miscount (TIMER_GROUP_0 TIMER_0)

Postby sraposo » Sat Jan 23, 2021 8:37 pm

It's needed to update title from "Random timer miscount" to "GPIO ISR improperly called", since the real cause of the "Random timer miscount" was an error on GPIO interrupt, as explained in my previous post.

Not explained yet why GPIO ISR behaves that way.

Who is online

Users browsing this forum: No registered users and 20 guests