본문 바로가기
myCortex

watchdog 타이머

by irmus 2011. 10. 8.
MCU에서 watchdog 타이머는 주로 fail-over 목적으로 사용됩니다. 뭔가 이유를 알 수 없는, 혹은 도저히 대응 불가능한 오류가 발생했을 때 꺼낼 수 있는 최후의 수단으로 시스템을 리셋시키는 용도입니다. watchdog = 경비견 이란 이름이 붙은 이유죠. 

컴퓨터로 프로그램들 사용하다 보면 [응답없음]이라 뜨면서 프로그램이 아무런 반응도 하지 않는 경우를 가끔 볼 수 있는데요, 임베디드 환경에서 이런 상황에 빠져 아무런 응답도 하지 않고 전기만 먹고 있으면 안되겠죠. 기본적으로 모든 가능한 경우를 따져가며 프로그램을 작성하고, 갖가지 상황에서 복구할 수 있는 수단을 마련해 두는데, watchdog timer는 이러한 복구 수단 중 최후의 보루로 주로 쓰입니다.

MCU 마다 다양한 형식의 watchdog timer가 있을 수 있는데요, myCortex 시리즈에서 쓰인 LM3S 칩셋의 watchdog timer는 아주 심플한 구성입니다.
watchdog 전용 타이머 카운터가 1개 있습니다. 이 카운터는 down counter이고, auto-reload 기능이 있습니다. 기본적인 설정을 마치고 watchdog 카운터를 활성화 시키면 auto-reload 레지스터에서 카운터로 읽어오고, 그때부터 1씩 감소시켜 나갑니다. 그러다가 0이 되면~ 인터럽트가 뜨고, 카운터는 다시 auto-reload 레지스터의 값을 읽어오고 카운팅을 계속해 나갑니다. 여기까지는 일반 타이머/카운터랑 동일합니다. LM3S의 watchdog 카운터가 일반 타이머와 다른 차이점은 한번 underflow interrupt가 발생한 다음 다음 underflow interrupt가 발생하기 전 까지 먼저 발생한 interrupt 가 clear 되지 않는다면 뒤도돌아보지 않고 시스템을 리셋시켜버린다는 점입니다.
한번 경고 날리고 그다음엔 바로 아웃~


myCortex 시리즈에서 사용하는 예를 살펴보겠습니다.
위 코드는 watchdog timer를 초기화하는 코드입니다. (WATCHDOG_TIMEOUT_SEC / 2) 만큼 시간이 경과한 후 watchdog interrupt가 발생합니다. 위에서 설명한 바와 같이 두번 연속 인터럽트가 발생하면 리셋됩니다. 즉 WATCHDOG_TIMEOUT_SEC 만큼 시간이 경과하면 리셋이 발생하겠죠. 이처럼 리셋이 발생하지 않도록 하기 위해서는 틈틈이 "나 살아있소~"라고 알려줘야 합니다. 즉 두번째 인터럽트가 발생하기 전에 먼저 발생한 인터럽트를 클리어 해 주면 됩니다.
위 코드가 인터럽트 클리어 해 주는 코드입니다. 이런 코드를 watchdog timer를 kick 해준다 라고 표현하는데요, 꼭 개를 발로 차서 깨운다는 것 같기도 하고;;;
꼭 인터럽트가 뜬 상황에서만 클리어 할  수 있는 것은 아닙니다. 첫번째 인터럽트가 안떴더라도 그냥 클리어 하는 코드를 호출하더라도 아무 일 없이 그냥 지나갑니다. 그러니 시간주기 따지지 말고 틈틈이 한번씩 호출해 주면 됩니다.

작성한 펌웨어가 10초동안 반응이 없다면 강제로 리셋되도록 만들고 싶다면 WATCHDOG_TIMEOUT_SEC에 10을 넣어주면 됩니다. 그리고 종종 인터럽트를 클리어 해 주는 것입니다. 그러다 어딘가 문제가 생겨 무한루프에 빠졌거나 fault가 발생한 경우 등에는 더이상 인터럽트 클리어 함수가 호출될 수 없으니 10초 지난 후에 시스템 리셋!


watchdog timer는 최후의 수단입니다. 기본적으로 watchdog timer에 호소해야 하는 경우는 그리 많지 않습니다. 네트워크 통신 펌웨어를 만드는데 peer와의 hand shake가 엉망이 되었다거나 sub system이 반응이 없다거나 등 주로 외부 요인을 수반하는 아주 한정적인 케이스입니다. 자신이 만든 시스템이 이유없이 자꾸 죽는다거나 반응이 없다거나 한다면 watchdog timer를 써야겠다고 생각하기 전에 디버깅부터 먼저 해야 합니다. 이유없이 죽는 것은 없습니다. 다 이유가 있죠. 그리고 그 이유의 99.99%는 개발자 실수입니다. 컴파일러 버그, 칩 버그 같은 이유는 0.01%도 안됩니다. 이바닥에서 구르면서 터득한 진리 중 하나죠. 기계를 의심하기 전에 자기 머리를 탓해라;;;



참. watchdog timer쓸 때 주의사항 하나. JTAG 디버거로 step-by-step 디버깅 할때 watchdog timer 꺼두세요. 안그럼 마구마구 리셋되어버리겠죠.
디버깅할동안에는 자동으로 watchdog time를 정지시키는 함수가 있습니다. 위의 코드 조각 중 초기화 부분에 아래 코드 한줄만 넣어주면 됩니다.

이렇게 하면 별도로 신경쓸 필요 없이 watchdog 타이머와 디버거를 함께 사용할 수 있습니다.