[아두이노] 아두이노등의 임베디드 시스템의 변수 값 오버플로우 문제

아두이노등의 임베디드 시스템의 변수 값 오버플로우 문제(Variable overflow problem in embedded systems)

아두이노에서 10ms 마다 스위치 상태를 검사하는 코드를 작성한다고 해 보자.

void loop() {
  static unsigned long last = 0;
  static boolean swPrev = HIGH;
  unsigned long now;

  now = millis();
  if ((now-last)>=10) {
    digitalWrite(13,digitalRead(10));
    last = millis();
  }
}

Untitled.jpg





위와 같은 코드가 될텐데 동작시켜 보면 생각한대로 아무 문제 없이 동작한다. 하지만 이 코드의 경우 치명적인 버그가 숨어있다. millis() 함수는 unsigned long 타입의 값을 리턴해 준다. unsigned long 타입의 경우 0 ~ 4,294,967,295 까지의 숫자가 들어갈 수 있다. 4,294,967,295 ms면 엄청나게 긴 시간(대략 50일)임에는 틀림없다. 하지만 임베디드 시스템의 경우 한번 켜 놓으면 전원을 끄지 않고 몇년씩 계속 동작시키는 경우도 흔하다. 위의 코드를 사용하면 처음부터 약 50일간은 문제없이 동작하지만 약 50일 정도가 지나 4,294,967,295 -> 0으로 변한 이후부터는 동작하지 않는 문제가 발생한다.

예를 들어 마지막으로 스위치를 감지했을 때 시간값이 last 변수에 들어가게 되는데 그 값이 4,294,967,290이었다고 해 보자. 그 때 부터 5 ms 후에는 4,294,967,295가 되고 다시 1ms가 더 지나면 4,294,967,256이 아니고 0이 되어 버린다. 즉 now-last 값이 6이 아니고 -4,294,967,290이 되어 버리는 것이다. 즉 그때 부터는 (now-last) > 10 이라는 조건이 만족될 수가 없게 되어 버리기 때문에 스위치가 눌렸는지 검사를 하지 않게 된다. 

Untitled%2B2.jpg

이런 타입의 에러가 임베디드 시스템에서 아주 악성인 이유는 프로그램을 만들어 테스트 해 보면 정상적으로 잘 동작한다는 것이다. 그래서 제품을 출시해도 아무 문제가 없는데 출시 시작한지 약 두달 정도가 지나면 문제가 발견되기 시작한다는 것이다. 그리고 디버깅을 위해 버그를 재현하기 위해 개발실에서 다시 테스트 해 보면 전원을 넣은지 50일이 지나지 않았기 때문에 버그를 재현할 수 없다. 개발자가 버그를 재현할 수 없으면 버그의 원인을 찾기 힘들기 때문에 디버깅이 매우 어렵다. 

처음부터 이런 부분을 생각해 변수 값이 overflow 되는 경우에도 동작할 수 있도록 프로그램을 작성하는 연습을 해야만 한다.

위의 코드라면 이런식으로 수정해 주면 된다.

#define MAX 0xFFFFFFFF

boolean diff(unsigned long now, unsigned long prev, unsigned long d)
{
  if (now>prev) return ((now-prev)>=d);
  else return (((MAX-prev)+now+1)>=d);
}

void loop() {
  static unsigned long last = 0;
  static boolean swPrev = HIGH;
  unsigned long now;

  now = millis();
  if (diff(now, last, 10)) {
    digitalWrite(13,digitalRead(10));
    swPrev = LOW;
    last = millis();
  }

}

Untitled%2B3.jpg

이제 now 변수의 값이 overflow 되어 0으로 돌아가도 정상적으로 비교되어 위에서 이야기 한 버그가 발생하지 않는걸 확인할 수 있다. 
0
0
이 글을 페이스북으로 퍼가기 이 글을 트위터로 퍼가기 이 글을 카카오스토리로 퍼가기 이 글을 밴드로 퍼가기

임베디드 보드

번호 제목 글쓴이 날짜 조회수
14 마이크로비트 7 컬러 LED 모듈 (아두이노 센서 활용) icon HellMaker 08-08 16,511
13 마이크로비트 CDS 조도 센서 (아두이노 센서 활용) icon HellMaker 08-08 16,470
12 마이크로비트 매직라이트 컵 모듈 활용하기 (아두이노 센서 활용) icon HellMaker 08-08 22,659
11 마이크로비트 기울기 센서 활용 (아두이노 센서 활용) icon HellMaker 08-08 17,713
10 마이크로비트 노크 센서 활용 (아두이노 센서 활용) icon HellMaker 08-08 16,802
9 마이크로비트 수은 기울기 센서 활용 (아두이노 센서 활용) icon HellMaker 08-08 17,515
8 마이크로비트 써미스터 온도 센서 활용 (아두이노 센서 활용) icon HellMaker 08-08 16,997
7 마이크로비트 디지털 홀 센서 활용 (아두이노 센서 활용) icon HellMaker 08-08 19,175
6 마이크로비트 아날로그 홀 센서 활용 (아두이노 센서 활용) icon HellMaker 08-08 18,248
5 마이크로비트 마이크로비트로 가위바위보 게임 일산메이커 08-01 17,711
4 마이크로비트 마이크로 비트로 led 문자 출력하기 2 #microbit #마이크로비트 #led Wavy 07-31 17,352
3 마이크로비트 마이크로비트 - led로 문자출력하기 #마이크로비트 #led #문자 #microbit +1 Wavy 07-30 16,669
2 마이크로비트 마이크로 비트로 간단하게 led켜기 (microbit easy led) #microbit #LED #led Wavy 07-24 17,013
1 마이크로비트 마이크로비트 교육자료 - 반응속도 게임 +1 일산메이커 07-19 18,963