Files
root ca13734bf0 Add full automotive RTOS project
Add kernel (Cortex-M0/M3/M4, Tricore, S32K, RISC-V ports), drivers,
middleware (CAN stack, diagnostics, safety), applications, board
support, build/test tooling, and documentation.
2026-08-23 03:35:29 -04:00

213 lines
5.6 KiB
C

/**
* @file watchdog_manager.c
* @brief Watchdog Manager for safety-critical applications
*/
#include "kernel.h"
#include "task.h"
#include <string.h>
/* Watchdog Configuration */
#define WATCHDOG_MAX_TASKS 16
#define WATCHDOG_DEFAULT_TIMEOUT 100 /* ms */
#define WATCHDOG_MAX_ALIVE_COUNT 5
/* Watchdog Task Status */
typedef enum {
WATCHDOG_TASK_ALIVE = 0,
WATCHDOG_TASK_TIMEOUT = 1,
WATCHDOG_TASK_SUSPENDED = 2
} WatchdogTaskStatus_t;
/* Watchdog Task Entry */
typedef struct {
TaskHandle_t task;
char task_name[16];
uint32_t timeout_ms;
uint32_t last_alive_time;
uint32_t alive_count;
WatchdogTaskStatus_t status;
bool is_supervised;
} WatchdogTaskEntry_t;
/* Watchdog Manager State */
typedef struct {
bool initialized;
bool enabled;
WatchdogTaskEntry_t tasks[WATCHDOG_MAX_TASKS];
uint8_t task_count;
uint32_t global_timeout_ms;
uint32_t last_service_time;
Mutex_t mutex;
void (*system_reset_callback)(void);
void (*task_timeout_callback)(TaskHandle_t task);
} WatchdogManagerState_t;
static WatchdogManagerState_t watchdog_manager;
/* Initialize Watchdog Manager */
KernelStatus_t watchdog_manager_init(uint32_t global_timeout_ms) {
if (watchdog_manager.initialized) {
return KERNEL_ERROR;
}
memset(&watchdog_manager, 0, sizeof(WatchdogManagerState_t));
watchdog_manager.global_timeout_ms = global_timeout_ms;
watchdog_manager.enabled = false;
watchdog_manager.last_service_time = kernel_get_tick_count();
mutex_create(&watchdog_manager.mutex, false);
watchdog_manager.initialized = true;
return KERNEL_OK;
}
/* Register Task for Supervision */
KernelStatus_t watchdog_register_task(TaskHandle_t task, const char* name,
uint32_t timeout_ms) {
if (!watchdog_manager.initialized || task == NULL) {
return KERNEL_ERROR;
}
if (watchdog_manager.task_count >= WATCHDOG_MAX_TASKS) {
return KERNEL_OUT_OF_MEMORY;
}
mutex_lock(&watchdog_manager.mutex, 100);
WatchdogTaskEntry_t* entry = &watchdog_manager.tasks[watchdog_manager.task_count];
entry->task = task;
strncpy(entry->task_name, name, sizeof(entry->task_name) - 1);
entry->timeout_ms = timeout_ms;
entry->last_alive_time = kernel_get_tick_count();
entry->alive_count = 0;
entry->status = WATCHDOG_TASK_ALIVE;
entry->is_supervised = true;
watchdog_manager.task_count++;
mutex_unlock(&watchdog_manager.mutex);
return KERNEL_OK;
}
/* Task Alive Indication */
KernelStatus_t watchdog_task_alive(TaskHandle_t task) {
if (!watchdog_manager.initialized || task == NULL) {
return KERNEL_ERROR;
}
mutex_lock(&watchdog_manager.mutex, 100);
for (uint8_t i = 0; i < watchdog_manager.task_count; i++) {
if (watchdog_manager.tasks[i].task == task) {
watchdog_manager.tasks[i].last_alive_time = kernel_get_tick_count();
watchdog_manager.tasks[i].alive_count++;
watchdog_manager.tasks[i].status = WATCHDOG_TASK_ALIVE;
break;
}
}
mutex_unlock(&watchdog_manager.mutex);
return KERNEL_OK;
}
/* Enable Watchdog */
KernelStatus_t watchdog_enable(void) {
if (!watchdog_manager.initialized) {
return KERNEL_ERROR;
}
watchdog_manager.enabled = true;
watchdog_manager.last_service_time = kernel_get_tick_count();
/* Enable hardware watchdog */
hal_watchdog_enable(watchdog_manager.global_timeout_ms);
return KERNEL_OK;
}
/* Disable Watchdog */
KernelStatus_t watchdog_disable(void) {
if (!watchdog_manager.initialized) {
return KERNEL_ERROR;
}
watchdog_manager.enabled = false;
/* Disable hardware watchdog */
hal_watchdog_disable();
return KERNEL_OK;
}
/* Service Watchdog */
KernelStatus_t watchdog_service(void) {
if (!watchdog_manager.initialized || !watchdog_manager.enabled) {
return KERNEL_ERROR;
}
/* Check all supervised tasks */
uint32_t current_time = kernel_get_tick_count();
bool all_tasks_alive = true;
mutex_lock(&watchdog_manager.mutex, 100);
for (uint8_t i = 0; i < watchdog_manager.task_count; i++) {
WatchdogTaskEntry_t* entry = &watchdog_manager.tasks[i];
if (!entry->is_supervised) {
continue;
}
/* Check if task is alive */
if ((current_time - entry->last_alive_time) > entry->timeout_ms) {
entry->status = WATCHDOG_TASK_TIMEOUT;
all_tasks_alive = false;
/* Call task timeout callback */
if (watchdog_manager.task_timeout_callback != NULL) {
watchdog_manager.task_timeout_callback(entry->task);
}
}
}
mutex_unlock(&watchdog_manager.mutex);
if (all_tasks_alive) {
/* Service hardware watchdog */
hal_watchdog_service();
watchdog_manager.last_service_time = current_time;
return KERNEL_OK;
} else {
/* Don't service watchdog - will trigger reset */
return KERNEL_ERROR;
}
}
/* Register Callbacks */
KernelStatus_t watchdog_register_callbacks(
void (*system_reset_callback)(void),
void (*task_timeout_callback)(TaskHandle_t task)) {
if (!watchdog_manager.initialized) {
return KERNEL_ERROR;
}
watchdog_manager.system_reset_callback = system_reset_callback;
watchdog_manager.task_timeout_callback = task_timeout_callback;
return KERNEL_OK;
}
/* Watchdog Main Function */
void watchdog_manager_main_function(void) {
if (!watchdog_manager.initialized || !watchdog_manager.enabled) {
return;
}
/* Service watchdog periodically */
watchdog_service();
}