- Thu Jan 10, 2019 3:30 pm
#79998
McChubby007 wrote:There are three strategies you can use :
1. Use a read/write operation which cannot be interrupted. This is the best option but in the case of esp8266 is not available.
2. Turn off interrupts in main code when modifying shared variable. This is fine because interrupts are not missed they are just not 'serviced' by the system until re-enabled. It is not my preferred option but I think you could do this and many many other code does this. It would be a bad option if interrupts were off for long periods but this is not the case for your example code. EDIT 1 : However, if interrupts are disabled for longer than the interrupt frequency then interrupts will be lost as you would get one isr call even though multiple interrupts have occurred. CPUs such as ARM have an NVIC (nested interrupt controller) which handles this for the user and is a fantastic piece of hardware!
3. Only write in one place, read from the other place into a temporary/other variable. This is what I tend to use when it is a simple data type like an int, which is what you use. The ISR will do the 'var++'. The main code reads this value and compares to a local copy to determine the interrupt count, eg
Code: Select all===
ISR:
===
isrCount++;
=======
non-ISR:
=======
//--------------------------------------
// globals:
uint32_t isrCount = 0;
//--------------------------------------
// code body in regular periodic loop etc...
static uint32_t copyOfCount = 0; // local copy of isr counter
uint32_t newCount = isrCount; // atomic read of isr counter
// note using unsigned ints means count still works after isrCount rolls back to 0, it would not work for signed values
uint32_t numInterrupts = newCount - copyOfCount; // get number of interrupts since last checked
copyOfCount = newCount; // update local copy of isr counter
if (numInterrupts > 0) {
// process ...
}
Very interesting!
I am evaluating whether to use option 2 or 3.
I was a bit confused in your explanation of option 3.
Exactly in this part:
uint32_t newCount = isrCount; // atomic read of isr counter
At the moment I am copying a variable that is being incremented in the interrupt to another global variable, can not there be an interruption between the assignment operations? since they are 2 32bit variables, and when copying from one register to the other of 8 bits, generate several instructions. Between these instructions could there be no interruption and cause me problems?
But if this works fine, I can copy the variable that increment the interrupt to a temporary variable, without errors, my problem has been solved! So it will be better to use the third option, it's simple and I do not need to stop the interruptions !!
I would like to comment on something else:
The test I told you would do up.
Increment a variable and not use anywhere.
That solved the problem! Do not worry anymore!
However, if I reset manually while there is a frequency above 10hz the equipment goes into a resets loop. It keeps resetting until I take out the pulses or decrease the frequency to 1hz or less.
I'll now investigate why this reset occurs, I believe I'll handle the interrupts very early and come into conflict with loading something else.