problem with volatile declaration

Hi everyone. I'm a totally new Arduino uno owner. I ran into a declaration problem.

I am attempting to decode a pulse train with the help of a ISR. I get wierd results and realized that the variables in the ISR should probably be volatile. However since I basically have used volatile once or twice before I have no idea how to declare this with structs.

How do I get this to compile? (Stupid looking code, but made it for example only)

typedef struct{
      int time;
      int state;
} volatile state_t;
typedef struct{
      int i;
      state_t data[1];
} volatile fifo_t;

 fifo_t fifo;
 state_t state;

void isr(){
 fifo.data[0]=state; 
  
}
void setup() {
  // put your setup code here, to run once:
    
}

void loop() {
  // put your main code here, to run repeatedly: 
  
}

Thanks in advance, and have a nice day/evning.

Declare the variables to be volatile, not the types

typedef struct{
      int time;
      int state;
} state_t;
typedef struct{
      int i;
      state_t data[1];
}fifo_t;

 volatile fifo_t fifo;
 volatile state_t state;

Yeah, tried that. Does not compile. gcc linux.

The hint from gcc:
note: no known conversion for argument 1 from ‘volatile state_t’ to ‘const state_t&’

It looks as if the error is caused by passing a volatile variable in place of a const function argument, but I don't see anywhere in your code that does that. Could you post some code that actually demonstrates the problem, and the complete output from compiling it?

Sure, Peter. Thanks for helping out. That is the actual code I'm compiling.

Edit: Sorry, that output is from RoyKs suggestion.

Output:

BareMinimum.ino: In function ‘void isr()’:
BareMinimum.ino:15:15: error: no match for ‘operator=’ in ‘fifo.fifo_t::data[0] = state’
BareMinimum.ino:15:15: note: candidate is:
BareMinimum.ino:5:4: note: state_t& state_t::operator=(const state_t&)
BareMinimum.ino:5:4: note:   no known conversion for argument 1 from ‘volatile state_t’ to ‘const state_t&’

My initial demo code gives:

BareMinimum.ino: In function ‘void isr()’:
BareMinimum.ino:15:15: error: no match for ‘operator=’ in ‘fifo.<anonymous struct>::data[0] = state’
BareMinimum.ino:15:15: note: candidate is:
BareMinimum.ino:2:24: note: <anonymous struct>&<anonymous struct>::operator=(const<anonymous struct>&)
BareMinimum.ino:2:24: note:   no known conversion for argument 1 from ‘state_t {aka volatile<anonymous struct>}’ to ‘const<anonymous struct>&’

avr-gcc-4.7.2
Arduino IDE 1:1.0.5+dfsg2-1

Thanks.
//Peter

Why do you think you need to declare the struct to be volatile? The members of the struct may, or may not, need to be volatile. The struct does not.

Well, I have tried everyting I could think of. Declaring members volatile, and stucts not gives me this error:

typedef  struct{
      volatile int time;
      volatile int state;
}  state_t;
typedef  struct{
      volatile int i;
      volatile state_t data[1];
}  fifo_t;

  fifo_t  fifo;
  state_t  state;

void isr(){
 fifo.data[0]=state; 
  
}

BareMinimum.ino: In function ‘void isr()’:
BareMinimum.ino:15:15: error: passing ‘volatile state_t’ as ‘this’ argument of ‘state_t& state_t::operator=(const state_t&)’ discards qualifiers [-fpermissive]

There is something with structs and volatile I am missing.

here is something with structs and volatile I am missing.

state_t is a struct. You are trying to declare the struct volatile. Don't do that. The members of the struct are volatile, and are all that should be volatile.

Aaaaw, man, doh! How did I not see that?

Thanks.

You should also be aware of critical sections. Any non-atomic variable accessed by both your ISR and your main code should be protected in your main code to prevent the ISR from interrupting operations on the variable and changing it mid operation.

For example, the following scenario (count1 and coun2 are ints that are updated by ISRs):

int result = (count1 + count2) / 2;

That takes a number of assembly instructions to calculate - at any point during that the ISR could fire and modify count1 or count2. As they are all integers, and the Arduino is only 8-bit, just reading the value takes multiple operations, so it is possible that the ISR could trigger midway through reading the two bytes of count1 say.

You should prevent interrupts from running while you're accessing those variables, but at the same time you want to spend as little time as possible without interrupts. cli() and sei() turn off and on interrupts respectively, so you could do something like:

cli();
int localCount1 = count1;
sei();
// Give the ISR a chance to fire
cli();
int localCount2 = count2;
sei();
int result = (localCount1 + localCount2) / 2;

Or to make things nicer, you could make a little macro:

#define CRITICAL(X) cli(); X; sei();

CRITICAL(int localCount1 = count1);
CRITICAL(int localCount2 = count2);
int result = (localCount1 + localCount2) / 2;