views:

35

answers:

1

First of all I'd welcome edits to the title of this question, I couldn't think how to word it better but I'm not too happy with what I came up with.

This is a question about concurrency, my application is on a microcontroller in C but I don't think that matters a great deal.

I have an interrupt routine which can change the values of two global variables. I have some main code which can read those variables. But it must get get consistent values from both which means I can't read one and then read the other because the interrupt might occur between the two and change them both, leaving me having read one from one set and one from the other.

Normally I would just disable the interrupt for the tiny part of code that reads both variables but I can't do this because the interrupt needs to be called at exactly the right time with no "jitter" in calls. 4 or 5 instructions to read and store the variables will lead to too much jitter in interrupt timing. (I'm generating PAL video in the interrupt so any jitter in timing will lead to visible movement of pixels on the screen).

I could rearrange the code to do this in a different way so that the same interrupt isn't responsible for the two things, and long term I'll probably do this, but it's significant work to do so. The question has become interesting to me anyway now as a 'puzzle' even if I recode it later to avoid the situation.

So what I'm asking is, is there any way I can read both variables and ensure they are in a consistent state without disabling interrupts?

It doesn't matter if I get the value before or after the interrupt occurs as long as both values come from the same place.

I've thought about having a separate "version number" count to read to ensure that each variable is the same version that is read, but that just makes the problem worse as now I have 4 variables to read.

+3  A: 

What microcontroller are you using. What kind of variables are we talking about? If you need less then 4 bytes and using 32bit MCU, you can solve this problem by putting the two variables into one 32bit variable.

EDIT:

If you are using 8 bit MCU, I think that the best way to you can do is to put variables to structure, create array of this structures (2 elements) and have one variable which indicates which structure is currently used for read. Then your interrupt changes the unused structure, and after that changes the value of indicator.

mack369
It's an Cortex-M3 (LPC1343).Ah yes I see what you mean, combine the two into one word and then write that out in a single instruction.... That would work, they are both single byte counts.it's easy now you've said that, why didn't I think of that :)
John Burton
Although I must add the warning: *assuming said data-size is accessible atomically*. A single byte is normally atomic. But 16-bit (or 32-bit) access might not be atomic -- consider systems where the data-bus is only 8-bit (or 16-bit), respectively.
pst
For Cortex-M3 it is going to be atomic operation, but the most portable way is to do it in the second way.
mack369
Ah I see, swap between two copies of the structure. That makes sense too. This is basic stuff, clearly I'm not awake this morning and a little ashamed I didn't think of it.
John Burton
The second proposal is called double buffering, it is the standard solution for this kind of problem.
starblue