Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
Watchdog Module - Architecture

Design Overview

Watchdog tracks liveness via timeout mechanism. Application periodically kicks to reset countdown. On timeout, registered recovery action fires (log, safe-state, reboot, custom callback, or failover). Framework manages global watchdog manager that coordinates all watchdog instances.

Core API

Creation

rte_watchdog_storage_t *storage,
const rte_watchdog_config_t *config,
rte_watchdog_t *out_handle
);
rte_status_t
Common result/status codes.
Definition rte_status.h:27
rte_status_t rte_watchdog_create(rte_watchdog_t *handle_out, const rte_watchdog_config_t *config)
Create a watchdog.
Watchdog configuration.

Caller provides storage; framework fills it with state. Config specifies type, timeout, and recovery action.

Lifecycle

rte_watchdog_start(handle) // Begin countdown
rte_watchdog_kick(handle) // Reset countdown
rte_watchdog_stop(handle) // Stop countdown
rte_watchdog_destroy(handle) // Release resources
rte_status_t rte_watchdog_start(rte_watchdog_t watchdog)
Start watchdog timer.
rte_status_t rte_watchdog_kick(rte_watchdog_t watchdog)
Kick (pet) watchdog - prove liveness.
rte_status_t rte_watchdog_destroy(rte_watchdog_t watchdog)
Destroy watchdog.
rte_status_t rte_watchdog_stop(rte_watchdog_t watchdog)
Stop watchdog timer.

Query

rte_watchdog_get_status(handle, &status);
rte_status_t rte_watchdog_get_status(rte_watchdog_t watchdog, rte_watchdog_status_t *status_out)
Get watchdog status.

Returns: kicks (total), fires (total timeouts), time_until_fire, active flag.

Watchdog Manager

Global singleton managing all watchdogs:

rte_watchdog_manager_initialize() // Call at startup
rte_watchdog_manager_shutdown() // Call at shutdown
rte_status_t rte_watchdog_manager_shutdown(void)
Shutdown watchdog manager (call once at shutdown).
rte_status_t rte_watchdog_manager_initialize(void)
Initialize watchdog manager (call once at startup).

Manager coordinates timeout callbacks and recovery actions.

State Per Watchdog

Countdown timer      - Current time until timeout
Last kick time      - When last kicked
Total kicks         - Diagnostic counter
Total fires         - Diagnostic counter
Is active           - Enabled/disabled state
Type/action/config  - Static configuration

Timeout Mechanics

On every tick (typically 1ms from system timer):

  1. Decrement countdown for each active watchdog
  2. If countdown reaches 0: a. Mark watchdog as fired b. Invoke recovery action c. Stop the watchdog

On kick:

  1. If not fired: reset countdown to timeout_ms
  2. If fired: return error (cannot kick)

Recovery Actions

Action on timeout depends on configuration:

LOG          - Log the event via rte_log
SAFESTATE    - Invoke RTE_SAFESTATE(SAFE, APP_REASON_WATCHDOG)
REBOOT       - Invoke RTE_REBOOT(APP_REASON_WATCHDOG)
FAILOVER     - Application-defined failover (distributed systems)
CUSTOM       - Call custom callback (application-provided)

Performance

Operation Time Notes
create() O(1) Initialize state
start() O(1) Set countdown
kick() O(1) Reset countdown
get_status() O(1) Read state
destroy() O(1) Clean up
Manager tick O(n) n = active watchdogs

System tick is the only O(n) operation; called once per millisecond.

Constraints

Max watchdog count      - No limit; all static
Min timeout            - Depends on timer resolution (typically 1ms)
Max timeout            - 2^32 - 1 milliseconds (~49 days)
Watchdog size          - 64 bytes (RTE_DECLARE_STORAGE)

Integration with Safe-State

Watchdog recovery action can trigger safe-state:

│
└─ On timeout:
└─ Enters safe-state as programmed
#define RTE_SAFESTATE(level, reason)
Explicitly enters the given safe-state level with a reason code, capturing the call site automaticall...
@ RTE_SAFESTATE_LEVEL_SAFE
@ RTE_WATCHDOG_ACTION_SAFESTATE

Unit Tests

Test 1: Timeout fires recovery action**

rte_watchdog_t wd;
rte_watchdog_create(&storage, &config, &wd);
// Wait for timeout without kicking
sleep_ms(config.timeout_ms + 10);
// Verify recovery action was triggered
ASSERT(action_was_fired == 1);

Test 2: Kick resets countdown**

sleep_ms(50); // Wait halfway to timeout
sleep_ms(50); // Half timeout again
// Should not have fired yet (total 100ms < timeout 200ms)
ASSERT(status.fires == 0);

See Also