k_timer 사용법이나 workqueue의 작업 제출·취소는 별도 주제다. 숫자 시간선은 설명용이고 특정 보드의 스케줄링·하드웨어 watchdog 응답 시간을 측정한 값이 아니다. 그림과 표는 이 글을 위해 새로 그렸다.1. 채널 여러 개, 소프트웨어 타이머 하나, 선택적 하드웨어 장치 하나
Task Watchdog은 전역 API로 채널을 추가·삭제하며 여러 인스턴스를 만들지 않는다. 각 채널에는 자체 reload_period와 만료 절대 시각이 있다. v3.7.0 구현은 현재 tick에 k_ms_to_ticks_ceil64(reload_period)를 더해 채널 마감을 계산한다. 활성 채널의 가장 빠른 마감에 하나의 k_timer를 맞추지만, 하드웨어 fallback이 빌드되면 CONFIG_TASK_WDT_MIN_TIMEOUT을 tick으로 올림 변환한 배경 시각이 더 빠를 수도 있다. 이때는 배경 시각을 고른다. task_wdt_feed(id)는 해당 채널의 마감을 다시 계산하고 타이머를 재설정한다. 이 타이머는 작업을 주기적으로 실행하기 위한 사용자의 timer/workqueue가 아니라 만료·배경 갱신을 판정하는 내부 시계다.
↔ 오른쪽으로 이동하며 작업별 채널, 내부 타이머, 배경 갱신과 만료 처리의 역할을 확인하세요.
작업 B · 채널 1각 작업의 성공적 진전이 자기 채널을 feed한다.
k_timer타이머 하나가 다음 사건을 기다린다.| 요소 | 목적 | 진전이 없을 때 |
|---|---|---|
| Task Watchdog 채널 | 특정 작업의 feed 간격 감시 | 그 채널의 callback 또는 기본 재부팅 경로 |
내부 k_timer | 가장 이른 채널 마감 또는 fallback 빌드의 배경 시각 예약 | 채널 만료 ISR 처리 또는 배경 재예약·조건부 HW feed |
| 하드웨어 WDT fallback | 스케줄러·소프트웨어 감시 체계 정지에 대비 | 장치·설정에 따른 하드웨어 재설정 시도 |
| 일반 timer/workqueue | 시간 후 콜백 또는 작업 실행 | 작업의 성공적 진전을 자동으로 판정하지 않음 |
근거: 3.7.0 다중 채널·전역 인스턴스·커널 타이머, v3.7.0 schedule_next_timeout 구현.
2. init → add → feed → delete 순서와 자원 한도를 지킨다
task_wdt_init(hw_wdt)를 먼저 부르고, fallback 장치가 필요 없으면 NULL을 전달한다. task_wdt_add(period_ms, callback, user_data)는 성공하면 0 이상의 채널 ID를, 실패하면 음수 오류값을 돌려준다. 채널 수 상한은 CONFIG_TASK_WDT_CHANNELS에서 정한다. 얻은 ID로 task_wdt_feed()하고, 감시가 필요 없어질 때 task_wdt_delete()한다. v3.7.0 구현은 채널을 추가할 때 그 채널을 한 번 feed해 첫 마감을 잡는다.
| API | 성공 결과 | 호출자 책임 |
|---|---|---|
task_wdt_init(hw_wdt) | 0 | add/feed 전에 호출. 하드웨어 장치를 넘기면 지원 여부와 timeout 설치 오류를 확인. |
task_wdt_add(ms, cb, data) | 0 이상 채널 ID | 0이 아닌 기간, 채널 수 상한, 콜백 ISR 제약을 고려. |
task_wdt_feed(id) | 0 | 실제 작업 진전 후 해당 ID를 feed. 음수 오류값을 확인. |
task_wdt_delete(id) | 0 | 더 감시하지 않을 채널을 정리하고 이후 stale ID를 쓰지 않음. |
채널 수는 스레드 수와 자동으로 같아지지 않는다. 애플리케이션이 어떤 작업의 어떤 진전 지점을 감시할지 고른 뒤 채널을 등록한다. 하나의 스레드에서 여러 독립 진행 단계를 감시할 수도 있고, 감시하지 않는 스레드에는 채널이 없다.
근거: 3.7.0 init/add/feed/delete 계약, CONFIG_TASK_WDT_CHANNELS.
3. 주기적 feed보다 “무엇을 마쳤는가”가 중요하다
작업이 멈췄는데 별도 타이머가 계속 task_wdt_feed()하면 watchdog은 살아 있는 것으로 판단한다. 감시하려는 단계가 정상적으로 끝난 뒤 해당 작업이 직접 feed하도록 두어야 의미가 있다. 기간은 정상적인 가장 긴 처리 시간, 스케줄링 지연, 전원 모드의 영향을 고려해 정한다. 너무 짧으면 정상 작업도 만료되고, 너무 길면 장애 탐지가 늦다.
↔ 예시 시간선에서 성공적 진전, feed, 정지, 만료를 순서대로 보세요.
task_wdt_add(1000, …)첫 채널 마감이 설정된다.
task_wdt_feed(id)로 새 마감 설정.정기 타이머가 대신 feed하지 않는다.
ISR callback 또는 기본 재부팅 경로.
| feed 위치 | 보이는 상태 | 판단 |
|---|---|---|
| 검증된 작업 단계 직후 | 그 단계가 끝난 사실 | 감시 목표와 일치한다. |
| 독립 주기 타이머 | 타이머만 동작한 사실 | 원래 작업이 멈춰도 계속 feed할 위험이 있다. |
| 긴 I/O가 시작되기 직전 | 작업을 시작한 사실 | 완료를 감시하려면 기간과 다음 feed 지점을 다시 설계한다. |
| 채널 등록 안 함 | 아무 감시 정보 없음 | 다른 채널이 살아 있어도 그 작업의 상태는 알 수 없다. |
근거: 3.7.0 채널 목적·feed 개념, 각 채널의 절대 마감 재계산. feed 위치에 대한 권고는 이 계약에서 도출한 설계 판단이다.
4. 소프트웨어 감시만 쓰는 최소 API 순서
다음은 프로젝트 코드에 통합할 뼈대다. progress_step()은 애플리케이션이 정의하는 실제 작업이며, 성공을 확인한 뒤에만 feed한다. callback = NULL이면 v3.7.0 구현의 기본 시스템 재부팅 경로를 택한다. 실제 제품에서는 오류·재시작 정책과 정상 최장 실행 시간을 먼저 정해야 한다.
#include <zephyr/task_wdt/task_wdt.h>
int start_progress_watch(void)
{
int rc = task_wdt_init(NULL); /* HW fallback 없이 시작 */
if (rc != 0) {
return rc;
}
int channel = task_wdt_add(1000, NULL, NULL); /* ms, 기본 reset */
if (channel < 0) {
return channel;
}
return channel; /* 호출자가 ID를 보관 */
}
/* 감시 대상 작업 안에서, 실제 단위 작업이 성공한 뒤: */
/* if (progress_step() == 0) { task_wdt_feed(channel); } */
1000 ms는 실습용 숫자다. 이 뼈대는 채널 정리, 종료, 재부팅, 전원 모드, 전체 오류 처리를 생략했으며 그대로 완성된 애플리케이션이 되지 않는다. 공식 샘플은 주 작업과 제어 작업에 채널을 두고 제어 작업이 멈췄을 때 해당 채널 콜백이 나타나는 흐름을 보여 준다.
5. 만료 콜백은 타이머 ISR의 문맥을 따른다
v3.7.0 task_wdt.c는 k_timer 만료 함수에서 채널의 callback(channel_id, user_data)를 직접 호출한다. 즉 사용자 콜백에는 ISR 제약이 그대로 적용된다. 잠들기, 오래 블로킹하기, 일반 스레드 전용 API 호출을 콜백 안에 넣지 않는다. 복구에 복잡한 작업이 필요하면 ISR에서 가능한 신호만 남기고 그 작업의 실행 문맥을 별도로 설계한다. 콜백을 NULL로 등록하면 구현은 sys_reboot(SYS_REBOOT_COLD)를 호출한다.
| 상황 | 실행 위치 | 기대할 동작 |
|---|---|---|
정상적인 task_wdt_feed | feed를 부른 작업 문맥 | 채널 마감 갱신, 다음 내부 타이머 선택 |
| 사용자 timeout callback | k_timer 만료 ISR | 짧은 ISR 안전 처리만 수행; 복구 정책은 별도 설계 |
callback = NULL | 만료 처리 경로 | v3.7.0 구현의 기본 cold reboot 호출 |
Callback이 곧 성공한 복구는 아니다. ISR 제약, 인터럽트 마스킹, 전원·하드웨어 상태에 따라 수행 가능성이 달라진다. timeout callback을 오래 돌려서 하드웨어 fallback까지 늦추는 구조로 만들지 않는다.
6. HW fallback은 소프트웨어 감시의 다음 단계다
CONFIG_TASK_WDT_HW_FALLBACK이 켜져 있고 사용 가능한 하드웨어 watchdog 장치를 task_wdt_init(device)에 넘겨야 fallback 경로를 요청할 수 있다. NULL이면 소프트웨어 채널만 쓰는 선택이다. v3.7.0 구현은 하드웨어 timeout을 CONFIG_TASK_WDT_MIN_TIMEOUT + CONFIG_TASK_WDT_HW_FALLBACK_DELAY로 설치하고, 첫 채널을 추가할 때 wdt_setup()을 호출한다. 내부 스케줄링 경로에서 하드웨어를 feed하므로, 스케줄러·타이머 경로 자체가 멈추면 하드웨어 장치가 만료할 수 있다.
↔ 두 실패가 어떤 감시층에서 관측되는지 오른쪽으로 비교하세요.
| 설정 | 의미 | 맞출 기준 |
|---|---|---|
CONFIG_TASK_WDT_CHANNELS | 동시에 설치할 채널 상한 | 감시할 작업 수와 RAM 사용량 |
CONFIG_TASK_WDT_MIN_TIMEOUT | HW fallback과 내부 배경 feed의 기준 | 실제 채널 중 가장 짧은 기간에 맞춰 불필요한 배경 타이머를 줄임 |
CONFIG_TASK_WDT_HW_FALLBACK_DELAY | 하드웨어 timeout에 더하는 여유 | 콜백 조치 시간·서로 다른 시계의 편차 |
CONFIG_TASK_WDT_HW_FALLBACK | 하드웨어 장치 사용 지원 | 빌드 설정과 실제 장치 포인터가 모두 필요 |
구현 주석은 모든 채널의 기간이 MIN_TIMEOUT보다 길면 하드웨어를 feed하기 위해 배경 타이머가 주기적으로 깨어날 수 있다고 설명한다. 설정값을 실제 최소 채널 기간에 맞추는 이유다. v3.7.0 구현은 첫 task_wdt_add()의 wdt_setup() 반환값을 검사하지 않고 시작 상태를 표시한다. task_wdt_init()의 성공만으로 하드웨어 fallback이 실제 작동한다고 단정하지 말고, 보드·드라이버의 재설정 동작과 debug pause 정책을 시험한다.
7. 리셋이 일어난 뒤에는 feed 주체와 감시층을 분리한다
| 관측 | 먼저 볼 경계 | 다음 확인 |
|---|---|---|
task_wdt_add 실패 | 기간·채널 수 | 0 ms 요청, CONFIG_TASK_WDT_CHANNELS 한도 |
| 예상보다 빠른 callback | 작업 시간·스케줄링 | 정상 최장 시간, feed 위치, tick 환산 |
| 작업이 멈췄는데 timeout이 없다 | feed 주체 | 독립 timer/다른 스레드가 대신 feed하는지 |
| 소프트웨어 callback 없이 reset | HW fallback 또는 다른 reset 원인 | 장치 reset reason·watchdog 설정과 로그 기록 |
| callback 안에서 더 멈춤 | ISR 문맥 | 블로킹 API·긴 작업·잠금 사용 여부 |
재부팅 사실 하나만으로 어느 층이 동작했는지 단정할 수 없다. 보드가 제공하는 reset reason과 callback 진입 관측, 채널 ID, feed 시점을 함께 남겨야 한다. 공식 샘플도 한 제어 작업이 멈추는 동안 main 작업은 살아 있고, 제어 채널 콜백 뒤 재부팅하는 차이를 보여 준다.
근거: 3.7.0 샘플 출력, API 오류값.
8. 소스와 재현 범위
Zephyr 릴리스 v3.7.0의 공식 Task Watchdog 문서, 같은 태그의 구현·Kconfig, 공식 샘플 설명을 기준으로 썼다. 시간선과 실패 도식은 원본 소스의 관계를 재구성한 자체 그림이다. 실제 보드의 하드웨어 WDT, sleep·debug pause, 타임아웃 여유를 측정하거나 인증했다는 뜻은 아니다.
| 고정 근거 | 확인할 부분 |
|---|---|
| Task Watchdog 공식 문서 | 다중 채널·단일 인스턴스·공개 API 계약 |
| v3.7.0 구현 | 최소 마감, ISR callback, HW fallback 설정·feed |
| v3.7.0 Kconfig | 채널 수·최소 기간·fallback 여유 |
| 공식 샘플 | 한 작업 정지와 해당 채널 callback 관측 |