Search code examples
embeddedinterruptmicrochippic18

Keeping time using timer interrupts an embedded microcontroller


This question is about programming small microcontrollers without an OS. In particular, I'm interested in PICs at the moment, but the question is general.

I've seen several times the following pattern for keeping time:

Timer interrupt code (say the timer fires every second):

...
if (sec_counter > 0)
  sec_counter--;
...

Mainline code (non-interrupt):

sec_counter = 500; // 500 seconds

while (sec_counter)
{
  // .. do stuff
}

The mainline code may repeat, set the counter to various values (not just seconds) and so on.

It seems to me there's a race condition here when the assignment to sec_counter in the mainline code isn't atomic. For example, in PIC18 the assignment is translated to 4 ASM statements (loading each byte at the time and selecting the right byte from the memory bank before that). If the interrupt code comes in the middle of this, the final value may be corrupted.

Curiously, if the value assigned is less than 256, the assignment is atomic, so there's no problem.

Am I right about this problem? What patterns do you use to implement such behavior correctly? I see several options:

  • Disable interrupts before each assignment to sec_counter and enable after - this isn't pretty
  • Don't use an interrupt, but a separate timer which is started and then polled. This is clean, but uses up a whole timer (in the previous case the 1-sec firing timer can be used for other purposes as well).

Any other ideas?


Solution

  • The PIC architecture is as atomic as it gets. It ensures that all read-modify-write operations to a memory file are 'atomic'. Although it takes 4-clocks to perform the entire read-modify-write, all 4-clocks are consumed in a single instruction and the next instruction uses the next 4-clock cycle. It is the way that the pipeline works. In 8-clocks, two instructions are in the pipeline.

    If the value is larger than 8-bit, it becomes an issue as the PIC is an 8-bit machine and larger operands are handled in multiple instructions. That will introduce atomic issues.