ATOMIC_BLOCK

2019. 5. 30. 16:03임베디드/ATmega128

avr-gcc에서 int 자료형은 2바이트 크기를 갖는다. 다만 ATmega128은 8비트 마이크로컨트롤러로 2바이트 자료형을 처리할 때는 2 클록에 처리할 수 있다. 따라서 한 클록 이후 인터럽트가 걸린다면 문제가 생길 수 있다.

 

예를 들어,

#include <avr/io.h>
#include <avr/interrupt.h>

volatile int value = 0;

ISR(외부 인터럽트) {
    value = (value + 1) % 2;
}

int main(void) {
    int local_value;
    setinterrpt();
 
    while(1) {
        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
            local_value = value;
        }
        if(local_value == 1) {
            do_something();
        }
    }
}

 

만일 ATOMIC_BLOCK이 걸려있지 않다면 value 한 클럭 읽어오고 나서 인터럽트 후 변경된 value의 나머지 부분을 읽어오게 되어서 잘못된 데이터 입력이 된다. 따라서 이렇게 인터럽트 내부에서 사용되는 data가 main 안에서도 영향을 끼친다면 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 옵션을 사용해 읽어오는 동안에는 인터럽트가 일어나지 않도록 하는 것이 옳은 방법이다

 

* ATOMIC_BLOCK(ATOMIC_FORCHEN) 옵션은 블록 내의 코드가 실행되는 도중 SREG 레지스터 값이 바뀔 수도 있다는 점이 있다. 하지만 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 옵션은 SREG 레지스터 값을 보장한다