Skip to content

File syn_watchdog.c

File List > sched > syn_watchdog.c

Go to the documentation of this file

#if __has_include("syn_config.h")
#include "syn_config.h"
#endif

#if !defined(SYN_USE_WATCHDOG) || SYN_USE_WATCHDOG

#include "../system/syn_errlog.h"
#include "../util/syn_assert.h"
#include "syn_watchdog.h"

#include <string.h>

#define SYN_WDT_ERR_TIMEOUT 0x0200 
void syn_watchdog_init(SYN_Watchdog *wdt, SYN_WDT_Entry *entries, uint8_t capacity,
                       SYN_WDT_TimeoutCallback callback, void *ctx)
{
    SYN_ASSERT(wdt != NULL);
    SYN_ASSERT(entries != NULL);
    SYN_ASSERT(capacity > 0);

    memset(entries, 0, sizeof(*entries) * capacity);
    wdt->entries = entries;
    wdt->capacity = capacity;
    wdt->count = 0;
    wdt->callback = callback;
    wdt->ctx = ctx;
    wdt->errlog = NULL;
}

int8_t syn_watchdog_register(SYN_Watchdog *wdt, const char *name, uint32_t timeout_ms)
{
    SYN_ASSERT(wdt != NULL);

    if (wdt->count >= wdt->capacity)
        return -1;

    /* Find free slot */
    for (uint8_t i = 0; i < wdt->capacity; i++) {
        if (!wdt->entries[i].active) {
            wdt->entries[i].name = name;
            wdt->entries[i].timeout_ms = timeout_ms;
            wdt->entries[i].last_checkin = syn_port_get_tick_ms();
            wdt->entries[i].active = true;
            wdt->count++;
            return (int8_t)i;
        }
    }
    return -1;
}

void syn_watchdog_checkin(SYN_Watchdog *wdt, int8_t id)
{
    SYN_ASSERT(wdt != NULL);
    SYN_ASSERT(id >= 0 && (uint8_t)id < wdt->capacity);
    SYN_ASSERT(wdt->entries[id].active);

    wdt->entries[id].last_checkin = syn_port_get_tick_ms();
}

void syn_watchdog_unregister(SYN_Watchdog *wdt, int8_t id)
{
    SYN_ASSERT(wdt != NULL);
    SYN_ASSERT(id >= 0 && (uint8_t)id < wdt->capacity);

    wdt->entries[id].active = false;
    wdt->count--;
}

void syn_watchdog_update(SYN_Watchdog *wdt)
{
    SYN_ASSERT(wdt != NULL);

    uint32_t now = syn_port_get_tick_ms();

    for (uint8_t i = 0; i < wdt->capacity; i++) {
        if (!wdt->entries[i].active)
            continue;

        uint32_t elapsed = now - wdt->entries[i].last_checkin;
        if (elapsed >= wdt->entries[i].timeout_ms) {
            if (wdt->errlog != NULL) {
                syn_errlog_record(wdt->errlog, SYN_WDT_ERR_TIMEOUT, SYN_ERR_ERROR, (uint32_t)i);
            }
            if (wdt->callback != NULL) {
                wdt->callback(wdt, &wdt->entries[i], wdt->ctx);
            }
            /* Reset check-in to avoid repeated callbacks */
            wdt->entries[i].last_checkin = now;
        }
    }
}

#endif /* SYN_USE_WATCHDOG */