SPI in ISR causes WDT timeout. Seachsing for other ways...

Moderators: grovkillen, Stuntteam, TD-er

Post Reply
Message
Author
supersjimmie
Normal user
Posts: 13
Joined: 09 Oct 2020, 15:19

SPI in ISR causes WDT timeout. Seachsing for other ways...

#1 Post by supersjimmie » 09 Oct 2020, 15:47

I am trying to get a plugin (_P145_Itho) working on an ESP32.
It is based on a cc1101, connected to the esp over SPI, with an SS(CS) pin and an additional pin from the cc1101 GDO2 to the esp to signal when data is received.

It works fine on esp8266, both for sending to the itho box and receiving from the itho remote.
With some slight modifications (use HSPI and add a working SS pin in the code), sending commands to the itho box works fine.

Also, receiving from the itho remote seemed to work... for a couple of seconds (sometimes minutes, depending on how many data passes by through the air).
Note, that the cc1101 triggers it's GDO2 pin on any traffic, not only itho specific, since it is just a 868MHz receiver.

Then a wdt timeout occurs.
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)
(which can be either CPU0 or CPU1)
I struggled on this and discovered that, at least on an esp32, you cannot use SPI transfer in an ISR routine.

Currently, the receiving process relies on that ISR:
1. When the cc1101 module receives (any) data, it pulls it's GDO2 pin high.
2. The cc1101 GDO2 pin is tied to any GPIO pin on the esp32 and triggers in interrupt (when RISING).
3. Once the interrupt is received, it takes about 5-10ms for the entire packet to come into the cc1101.
4. Only áfter that 5-10ms, a function is called to fetch the packet and inspect it.

Number 1. Is quite clear. 2/3/4 need some kind of adjustment.
What is being done in the plugin now, is that 2 uses a function via the attachInterrupt.
So function "PLUGIN_145_ITHOinterrupt()" is triggered when the cc1101 starts receiving data.
Because that already happens at the first bit of receiving data, we need to wait about 5-10ms for all data to come in, before reading it from the cc1101 queue into the esp code.
To accomplish that 5-10ms delay, the "PLUGIN_145_ITHOinterrupt()" only starts a Ticker: "PLUGIN_145_ITHOticker.once_ms(10, PLUGIN_145_ITHOcheck)"
Then the PLUGIN_145_ITHOcheck function, started 10ms later, is fetching the data from the cc1101 queue with a couple of SPI commands (including the SPI.tranfer() that causes a wdt timeout when used in the Ticker triggered function).

Long story short: I am searching for some other way to schedule the fetching of the data.
Does espeasy have some kind of queue, or some place where I can add code, that is run periodically and checks for a variable, where I can do the fetching?
I could then let the Ticker only set some variable and let the data fetch in that other place as soon as the variable is set (and then reset the variable).
That way, the SPI part can be part of the regular running code instead of an ISR.

I hope I explained this well enough...

supersjimmie
Normal user
Posts: 13
Joined: 09 Oct 2020, 15:19

Re: SPI in ISR causes WDT timeout. Seachsing for other ways...

#2 Post by supersjimmie » 09 Oct 2020, 16:27

For now I will experiment with the PLUGIN_TEN_PER_SECOND
Any better idea is very welcome.

TD-er
Core team member
Posts: 8749
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: SPI in ISR causes WDT timeout. Seachsing for other ways...

#3 Post by TD-er » 09 Oct 2020, 16:37

You can set a flag in the ISR code which stores the millis() in a volatile parameter.

In the 50/sec call you then check this parameter and reschedule the call to PLUGIN_READ using

Code: Select all

          Scheduler.schedule_task_device_timer(event->TaskIndex, xxx); // the volatile parameter + 5
See for some examples the code where schedule_task_device_timer is called.
Or just schedule it immediately (or even in the past) to make sure the PLUGIN_READ is called as soon as possible.

supersjimmie
Normal user
Posts: 13
Joined: 09 Oct 2020, 15:19

Re: SPI in ISR causes WDT timeout. Seachsing for other ways...

#4 Post by supersjimmie » 12 Oct 2020, 14:47

TD-er wrote: 09 Oct 2020, 16:37 You can set a flag in the ISR code which stores the millis() in a volatile parameter.

In the 50/sec call you then check this parameter and reschedule the call to PLUGIN_READ using

Code: Select all

          Scheduler.schedule_task_device_timer(event->TaskIndex, xxx); // the volatile parameter + 5
See for some examples the code where schedule_task_device_timer is called.
Or just schedule it immediately (or even in the past) to make sure the PLUGIN_READ is called as soon as possible.
Doesn't using that schedule cause the same issue? I think that is also conflicting with the SPI.transfer, same as when I use a scheduler like Ticker.

Also, what is the 50/sec? I was only able to find a 10 per sec?
Ah found it: PLUGIN_FIFTY_PER_SECOND was just a bit further in the .h file I was looking in.
But what can I do with the PLUGIN_READ then? Is that called as much as possible?

TD-er
Core team member
Posts: 8749
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: SPI in ISR causes WDT timeout. Seachsing for other ways...

#5 Post by TD-er » 12 Oct 2020, 15:08

PLUGIN_READ is the function that tells the connected controller whether or not there is new data to send.
If that function returns "success = true;" then any connected controller will receive the task data and also events are sent to be processed in rules.

So that PLUGIN_READ is typically called every N seconds (the "Interval" setting of a task)

supersjimmie
Normal user
Posts: 13
Joined: 09 Oct 2020, 15:19

Re: SPI in ISR causes WDT timeout. Seachsing for other ways...

#6 Post by supersjimmie » 12 Oct 2020, 16:23

TD-er wrote: 12 Oct 2020, 15:08 PLUGIN_READ is the function that tells the connected controller whether or not there is new data to send.
If that function returns "success = true;" then any connected controller will receive the task data and also events are sent to be processed in rules.

So that PLUGIN_READ is typically called every N seconds (the "Interval" setting of a task)
Ah I understand.
Since the PLUGIN_READ already contains some other code, I wouln't want to call that more often.
The 50/sec is nearly perfect, I will set a var based on millis on a new cc1101-packet and have the packet read in the 50/sec part only if there is data and only at least 10ms after it was received.
I tested it and seems to be working.

Code: Select all

		case PLUGIN_FIFTY_PER_SECOND: {
			if (PLUGIN_145_ITHOtimePacket != 0) {
				if ((PLUGIN_145_ITHOtimePacket+10) < millis()) {
					PLUGIN_145_ITHOcheck();
					PLUGIN_145_ITHOtimePacket = 0;
					PLUGIN_145_ITHOhasPacket = false;
				}
			}
			break;
		}

Code: Select all

inline static void ICACHE_RAM_ATTR  __attribute__((always_inline))  PLUGIN_145_ITHOinterrupt()
{
	PLUGIN_145_ITHOtimePacket = millis();
	PLUGIN_145_ITHOhasPacket = true;
}
I know that the PLUGIN_145_ITHOhasPacket is somewhat obsolete.

TD-er
Core team member
Posts: 8749
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: SPI in ISR causes WDT timeout. Seachsing for other ways...

#7 Post by TD-er » 12 Oct 2020, 18:38

You can even simplify it by just setting the millis() in the ISR call.
When reading you set it to 0 again.
So then in the 50/sec call you only need to compare it with 0 and if not, just copy the value for further processing and set to 0.

supersjimmie
Normal user
Posts: 13
Joined: 09 Oct 2020, 15:19

Re: SPI in ISR causes WDT timeout. Seachsing for other ways...

#8 Post by supersjimmie » 13 Oct 2020, 10:16

TD-er wrote: 12 Oct 2020, 18:38 You can even simplify it by just setting the millis() in the ISR call.
When reading you set it to 0 again.
So then in the 50/sec call you only need to compare it with 0 and if not, just copy the value for further processing and set to 0.
Sounds creative. :)
But I don't understand what you mean...
Isn't that what I do now? I set the PLUGIN_145_ITHOtimePacket to millis and check (+reset) it in the 50/sec.
(if you discard the extra PLUGIN_145_ITHOhasPacket, which I only have there for some other experiments).

TD-er
Core team member
Posts: 8749
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: SPI in ISR causes WDT timeout. Seachsing for other ways...

#9 Post by TD-er » 13 Oct 2020, 13:51

Well I noticed the extra bool flag, so assumed (I know that's something I must try to do less often...) you used it.
But I now see you set the millis in the ISR call and set to 0 when handling the call, then it is indeed exactly what I meant.

Post Reply

Who is online

Users browsing this forum: No registered users and 122 guests