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:
}
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>&’
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.
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: