Reading a variable that is manipulated by ISR

Hi,

My ISR is incrementing a variable "count" and 1kHz.
I need to read this variable inside my "loop()".
Is there going to be a problem if at the moment I am reading this variable, the ISR kicks in and corrupt my variable?
is there some safety measures I can do for protection against data corruption?

Thanks

declare the variable as volatile, the compiler knows that the variable has to be read each time it is accessed.

volatile int count;

Thanks...

I had it declared as volatile... just wanted to make sure...

Is the variable one byte (short) or two bytes (integer)? If you are unlucky, your number is say 00FF, you read the FF and then the next read is interrupted by your timer and the high byte becomes 01 then your read resumes and the result you get is 01FF, instead of 0100. To prevent this you will have to disable interrupt before you read your first byte. But if you only have one byte to read, then never mind. If your main code is fast enough to catch an unsigned short from overflowing twice, i.e. 00->FF->00->FF->00, then use a one byte variable in interrupt and handle overflow in your main code so you only read one byte. The problem is thus solved.

then, if the variable is more than one byte long, it should be ok to disable interrupts just before reading the variable, and enable them immediately after the reading ?

alnath:
then, if the variable is more than one byte long, it should be ok to disable interrupts just before reading the variable, and enable them immediately after the reading ?

Correct. The typically pattern involves a temporary / local variable.

In addition to the failure case described by @liudr, there is another case that applies regardless of the data size. In other words, interrupts should always be disabled when accessing shared data.

Is the variable one byte (short) or two bytes (integer)?

I don't understand the use of "short" here - a short is typically a signed sixteen bit integer, whereas a byte is typically an eight bit unsigned integer.

What you are describing is known as a Critical Section and using them is central to any multi-threaded system. Interrupts constitute a multi-threaded system as the code in the interrupt is run in a different context (in another thread if you like) to the main code.

Protecting any variables or other resources accessed in both the main thread and the interrupt thread from corruption is pretty important.

In full multi-threaded systems this is done through the use of "mutex locks" which stop one thread from accessing the resource while another thread is using it. For interrupts disabling interrupts for a short time while you access the resource outside the interrupt is usually sufficient - as long as you keep that access as short as possible.

One example might be:

volatile int sharedVariable; // variable that gets updated in the interrupt routine

// Grab a copy of the variable
cli();
int localVariable = sharedVariable;
sei();

// Do something that takes time with that data
doSomethingWithData(localVariable);

alnath:
declare the variable as volatile, the compiler knows that the variable has to be read each time it is accessed.

volatile int count;

That will only work if the cpu can load the value in one clock cycle. That would work on a Due, which uses the Arm processor. However, on AVR's the chance exists that your ISR might interrupt after the first byte has been loaded, but not the second byte. I would suggest using uint8_t (aka unsigned char) and making sure your code only counts from 0..255.

A handy macro:

// Critical section copy FROM (x) TO (y)
#define COPY_PROTECTED(x,y) cli(); y = (x); sei();

volaile int sharedVariable;
int localVariable;

// Copy FROM shared TO local variable
COPY_PROTECTED(sharedVariable, localVariable)

And yes, using that you can do small operations, like:

COPY_PROTECTED(sharedVariable + 1, sharedVariable)