Interrupt array sync with main loop

Ok I’ve searched far and wide and either I’m missing something fundamental or perhaps my use case is just that unique.

I am processing a clock and data signal using an interrupt. The data signal is 6 bytes per message with 100ms between messages. I do the minimal processing in the ISR to create a message buffer that is an array of arrays of the 6 bytes.

In my main loop every few seconds I simple iterate through the array of messages and print them to screen. I’m using a queue data structure so pop the data off as I process it. If the ISR gets called while I’m doing this no problem because it pushes to the FIFO queue which is at the other end of the data structure. BUT if the ISR happens to get called in the middle of the pop function then things will go wrong because the internal queue indexes will be out of sync. I could do this with basic arrays but I’d have same problem because I’d need to share the current index of the front and back of the queue between ISR and loop and same out of sync problem. I can’t block interrupts during the loop pop becuase I would miss a bytes in the 6 byte message and I don’t have start and stop bytes and need to rely on the 6 bytes being there.

Ok so how about I use 2 buffers and a flag that the ISR controls to tell the loop which buffer to use. While the ISR works on one buffer the loop works on the other. The flag only changes in the ISR so no sync issue there. BUT this doesn’t work if the loop doesn’t clear its buffer before the ISR fills up the other buffer.

So what is the way to ensure I don’t lose any interrupts (data) and process a buffer of bytes in the main loop? I’ve got 100ms between messages and I can even skip some messages so I should have plenty of time in the main loop. Google brings up lots of people with same question but none seem to apply to my use case.

Without code, impossible to be sure, but the description indicates that in loop() you are not:

  1. turn off interrupts
  2. save the index that interrupt is using to a different variable
    3.turn the interrupts back on
  3. continue the code using the COPY of the index

Which Arduino board?

Yea but I can’t disable the interrupt during the loop processing because I would loose data. And since my messages are 6 bytes if I lose one byte I won’t be able to keep track of the 6 bytes that form a message. So I can’t disable ISR…

Esp32-wroover

The ESP32's built-in FreeRTOS operating system makes the solution trivial. Check out the functions:
xQueueCreate()
xQueueSendToBackFromISR()
xQueueReceive()

Why? The pending interrupt will run as soon as you enable interrupts!

So when you "disable" interrupts they queue up and fire once they are enabled? I was reading the word disable literally so if it means "pause processing" then that does solve my problem...

When a processor can have more than ONE interrupt possible, then they must have some type of priority since the processor can do only one thing at a time. There may be a separate interrupt processor that cycles through the signals looking for an interrupt indicator. The order of cycling give the priority. Your PC uses this method.
The "disable" just stops the cycling of the interrupt processing for the few cycles you have stopped them. If you NEVER enable interrupts, then there is no recovery possible until you reset the Arduino.

Devices can continue to queue interrupt requests if interrupts are disabled. Until you enable interrupts, none of those requests will be processed.

It is essential to disable interrupts when accessing shared variables in the main loop. Make a copy, re-enable interrupts, then use that copy in the loop code. If you don't, the interrupt will at times corrupt the data while it is being read.

For example:

volatile int count = 0; //global variable modified by interrupt routine
...

//in loop()

noInterrupts(); //disable
int count_copy = count; //make a copy of the shared variable
interrupts(); //re-enable
Serial.print(" Count: ");
Serial.println(count_copy);

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.