Daniel
Daniel

Reputation: 2592

AVR interrupt's variable updated in main

Using a 8-bit AVR micro, I arrived to a simple situation which might not be that easy to solve.

Consider the following snippet:

static volatile uint8_t counter;

//fires often and I need all the values of the counter.
void isr(void) {
  counter++;
}

int main (void) {

  while(1) {
    send_uart(counter);
    counter = 0;
    delay_ms(1000); //1 sec pause
  }  

  return 0;
}

1.) It can happen that send_uart is followed by an isr which increases the counter, and then the next statement zeroes it out. Therefore I'll miss one data from the counter.

2.) If I use ATOMIC_BLOCK(ATOMIC_RESTORESTATE) in the main fn, I can avoid the problems declared in (1), but it can happen that I miss an ISR because in this case INTs are disabled for a short time.

Is there a better way to pass information from the main fn to ISR?

Upvotes: 0

Views: 822

Answers (1)

vega8
vega8

Reputation: 542

If the counter is sampled rather than reset, there won't be any timing issues. Increments happening while sending will be accounted for in the next iteration. The unsigned data type of the counter variables will guarantee well-defined overflow behavior.

uint8_t cs = 0;                  // counter sample at time of sending
uint8_t n = 0;                   // counter as last reported

while (1) {
  cs = counter;                  // sample the counter
  send_uart((uint8_t)(cs - n));  // report difference between sample and last time
  n = cs;                        // update last reported value
  delay_ms(1000);
}

Upvotes: 1

Related Questions