디지털 시스템의 안정성을 보장하기 위한 독견 타이머(Watchdog Timer)는 임베디드 시스템에서 매우 중요한 구성 요소입니다. STM32F103 마이크로컨트롤러는 두 가지 유형의 독견 타이머를 제공하며, 각각 다른 목적과 동작 방식을 가지고 있습니다.
독견 타이머의 기본 개념
독견 타이머는 시스템의 비정상 동작을 감지하고 복구하는 장치입니다. 마치 집을 지키는 개처럼, 시스템이 예상치 못한 상황(예: 소프트웨어 결함, 무한 루프, 외부 간섭으로 인한 프로그램 비정상 종료)에 빠졌을 때 시스템을 재시작하여 안정성을 유지합니다.
공식 데이터시트에 명시된 바와 같이, 독견 타이머의 주요 역할은 소프트웨어 장애를 감지하고 해결하며, 카운터가 특정 시간 초과 값에 도달했을 때 시스템 리셋 또는 인터럽트(윈도우 독견 타이머의 경우)를 트리거하는 것입니다.
독립형 독견 타이머(IWDG)
독립형 독견 타이머(IWDG)는 이름에서 알 수 있듯이 독립적인 클럭 소스를 가지고 있습니다. 이는 주 클럭 소스에 문제가 발생해도 IWDG는 계속 작동할 수 있음을 의미합니다. 이 독립 클럭은 내부 RC 클럭으로 제공되는 40KHz 저속 클럭(LSI)입니다.
동작 원리
IWDG의 동작은 다음과 같은 단계로 이루어집니다:
- 40KHz LSI 클럭이 8비트 프리스케일러를 통과합니다
- 프리스케일링된 클럭이 12비트 감소 카운터로 공급됩니다
- 카운터 값이 0에 도달하면 IWDG 리셋 신호가 발생합니다
주요 레지스터
- 키 레지스터(IWDG_KR): 독견 "먹이주기" 작업은 이 레지스터에 0xAAAA 값을 쓰는 것으로 수행됩니다
- 프리스케일러 레지스터(IWDG_PR): 카운터에 적용될 분주 비율을 설정합니다
- 재로드 레지스터(IWDG_RLR): 카운터의 초기값을 설정합니다
- 상태 레지스터(IWDG_SR): 현재 레지스터 쓰기 상태를 나타냅니다
소프트웨어 구현
IWDG 사용을 위한 기본 계산 공식은 다음과 같습니다:
Tout = ((4 × 2prer) × rlr) / 40
여기서 Tout는 타이머 오버플로 시간(ms), prer는 프리스케일 값(0-7), rlr는 재로드 값입니다.
// 독립형 독견 타이머 핸들러
Watchdog_TypeDef g_stm32_watchdog;
/**
* @brief 독립형 독견 타이머 초기화
* @param prescaler: 분주 비율 (4~256)
* @param reload_val: 재로드 값 (0~4095)
* @note 시간 계산: Tout = ((4 * 2^prescaler) * reload_val) / 40 (ms)
*/
void watchdog_initialize(uint8_t prescaler, uint16_t reload_val)
{
g_stm32_watchdog.Instance = IWDG;
g_stm32_watchdog.Init.Prescaler = prescaler;
g_stm32_watchdog.Init.Reload = reload_val;
HAL_IWDG_Init(&g_stm32_watchdog);
}
/**
* @brief 독견 타이머 "먹이주기" 작업
*/
void watchdog_refresh(void)
{
HAL_IWDG_Refresh(&g_stm32_watchdog);
}
윈도우 독견 타이머(WWDG)
윈도우 독견 타이머(WWDG)는 IWDG와 다른 방식으로 동작합니다. WWDG는 "윈도우"라는 개념을 도입하여 타이밍 제어를 더 세밀하게 할 수 있습니다.
동작 원리
WWDG는 두 가지 조건에서 리셋을 트리거합니다:
- 윈도우 상한값 외부에서 "먹이주기" 작업을 수행할 때
- 카운터가 윈도우 하한값에 도달했을 때
이는 "먹이주기" 작업이 특정 시간 창(window) 내에서 수행되어야 함을 의미합니다.
주요 레지스터
- 제어 레지스터(WWDG_CR): 7비트 카운터 값을 포함하며, 값이 0x3F에서 0x40로 감소할 때 리셋이 발생합니다
- 구성 레지스터(WWDG_CFR): 윈도우 상한값(W6)과 프리스케일 값을 설정합니다
- 상태 레지스터(WWDG_SR): 인터럽트 플래그를 포함합니다
소프트웨어 구현
WWDG 시간 계산 공식은 다음과 같습니다:
TWWDG = (4096 × 2WDGTB × (T[5:0] + 1)) / FPCLK1
여기서 TWWDG는 WWDG 타임아웃 시간(ms), FPCLK1은 APB1 클럭频率(KHz), WDGTB는 프리스케일 값, T[5:0]는 카운터의 하위 6비트 값입니다.
// 윈도우 독견 타이머 핸들러
WindowWatchdog_TypeDef g_window_watchdog;
/**
* @brief 윈도우 독견 타이머 초기화
* @param counter: 카운터 값 (T[6:0])
* @param window_val: 윈도우 값 (W[6:0])
* @param prescaler: 분주 비율 (WDGTB)
* @note fprer: 분주 계수 (WWDG_PRESCALER_1~WWDG_PRESCALER_8)
* Fwwdg = PCLK1/(4096*2^fprer). 일반적으로 PCLK1=36Mhz
*/
void window_watchdog_init(uint8_t counter, uint8_t window_val, uint32_t prescaler)
{
g_window_watchdog.Instance = WWDG;
g_window_watchdog.Init.Prescaler = prescaler;
g_window_watchdog.Init.Window = window_val;
g_window_watchdog.Init.Counter = counter;
g_window_watchdog.Init.EWIMode = WWDG_EWI_ENABLE;
HAL_WWDG_Init(&g_window_watchdog);
}
/**
* @brief WWDG MSP 콜백 함수
* @param hwwdg: WWDG 핸들러
*/
void HAL_WWDG_MspInit(WindowWatchdog_TypeDef *hwwdg)
{
__HAL_RCC_WWDG_CLK_ENABLE();
HAL_NVIC_SetPriority(WWDG_IRQn, 2, 3);
HAL_NVIC_EnableIRQ(WWDG_IRQn);
}
/**
* @brief 윈도우 독견 타이머 인터럽트 서비스 루틴
*/
void WWDG_IRQHandler(void)
{
HAL_WWDG_IRQHandler(&g_window_watchdog);
}
/**
* @brief 윈도우 독견 타이머 조기 인터럽트 콜백 함수
* @param hwwdg: WWDG 핸들러
*/
void HAL_WWDG_EarlyWakeupCallback(WindowWatchdog_TypeDef *hwwdg)
{
HAL_WWDG_Refresh(&g_window_watchdog);
}
주요 적용 분야
- 산업 제어 시스템: 프로그램 데드락으로 인한 생산 사고 방지. 예정된 시간 내에 핵심 작업이 완료되는지 감시하여 시스템 완전 중단 방지
- 의료 장비: 심박 모니터링과 같은 핵심 작업의 실시간 응답 보장
- 스마트 홈 기기: 장기간 운영 안정성 향상 및 유지보수 요구 감소