임베디드 시스템과 펌웨어

위의 프로그램을 최적화를 켜고 컴파일하면 타이머 인터럽트가 발생해도 led_on()이 호출되지 않는 경우가 있습니다. 원인과 대책의 조합으로 올바른 것은 무엇입니까?

int flag = 0;
void timer_isr(void) { flag = 1; }
int main(void) {
    while (flag == 0) { }
    led_on();
}
  1. A컴파일러가 flag를 한 번만 읽고 루프 안에서 다시 읽지 않기 때문이다. flag에 volatile을 붙인다
  2. B인터럽트가 발생하면 flag가 0으로 돌아가기 때문이다. flag를 long으로 한다
  3. Cwhile의 내용이 비어 있으면 CPU가 멈추기 때문이다. 루프 안에 덧셈을 넣는다
정답과 해설 보기

정답: A. 컴파일러가 flag를 한 번만 읽고 루프 안에서 다시 읽지 않기 때문이다. flag에 volatile을 붙인다

컴파일러는 main 안만 보고 '루프 안에서 flag를 바꾸는 것은 없다'고 판단하여, flag를 한 번만 레지스터에 읽고 그 값으로 계속 도는 코드를 만들기도 합니다. 인터럽트 핸들러가 메모리 상의 flag를 바꿔도 루프는 그것을 보지 않습니다. volatile을 붙이면 접근할 때마다 메모리에서 읽고 쓰게 됩니다. 여러 바이트 변수에서는 읽기/쓰기 도중에 인터럽트되지 않도록 하는 추가적인 대책도 필요합니다.

이 분야 연습하기 분야로 돌아가기

임베디드 시스템과 펌웨어의 다른 문제

  1. 8비트 마이크로컨트롤러에서 타이머 인터럽트가 32비트 변수 ticks를 1씩 증가시키고, 메인 처리가 ticks를 읽어 경과 시간을 구하고 있습니다. 드물게 크게 어긋난 값이 읽히는 원인으로 올바른 것은 무엇입니까?
  2. UART를 이용한 시리얼 통신의 특징으로 올바른 것은 무엇입니까?
  3. 115200 bps UART에서 데이터 8비트, 패리티 없음, 스톱 비트 1(8N1) 형식으로 보낼 때, 1초 동안 보낼 수 있는 바이트 수에 가장 가까운 것은 무엇입니까?
  4. UART의 송신 측과 수신 측의 보 레이트가 조금 어긋나면 문자가 깨지는 경우가 있습니다. 어긋남의 허용 범위가 대략 몇 % 정도로 제한되는 이유로 올바른 것은 무엇입니까?
  5. SPI 통신의 특징으로 올바른 것은 무엇입니까?

이 분야의 비교