Improve heartbeat indication and docs
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include "uart_mux.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "dcdc_controller.h"
|
||||
#include "driver/gpio.h"
|
||||
@@ -18,6 +19,7 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "ws2812_status.h"
|
||||
|
||||
#ifndef CONFIG_WATCH_UART_MUX_CHANNELS
|
||||
#define CONFIG_WATCH_UART_MUX_CHANNELS 5
|
||||
@@ -43,6 +45,7 @@ static size_t s_active_channel = SIZE_MAX;
|
||||
static bool s_initialized;
|
||||
static int64_t s_last_heartbeat_us[UART_MUX_MAX_CHANNELS];
|
||||
static TaskHandle_t s_watchdog_task;
|
||||
static uint8_t s_consecutive_miss[UART_MUX_MAX_CHANNELS];
|
||||
|
||||
// Перемикає апаратний мультиплексор на вказаний канал під захистом мьютекса,
|
||||
// оновлюючи таймстемп останнього heartbeat для контролю watchdog.
|
||||
@@ -68,7 +71,7 @@ static esp_err_t uart_mux_select_locked(size_t channel)
|
||||
// якщо канал «мовчить» довше за CONFIG_WATCH_UART_HEARTBEAT_TIMEOUT_SEC.
|
||||
static void uart_mux_watchdog_task(void *arg)
|
||||
{
|
||||
const TickType_t poll_interval = pdMS_TO_TICKS(1000);
|
||||
const TickType_t poll_interval = pdMS_TO_TICKS(10000);
|
||||
const TickType_t read_timeout = pdMS_TO_TICKS(10);
|
||||
const int64_t timeout_us = (int64_t)CONFIG_WATCH_UART_HEARTBEAT_TIMEOUT_SEC * 1000000LL;
|
||||
uint8_t buffer[CONFIG_WATCH_UART_MUX_DEFAULT_READ_LEN];
|
||||
@@ -78,6 +81,7 @@ static void uart_mux_watchdog_task(void *arg)
|
||||
int64_t now = esp_timer_get_time();
|
||||
for (size_t ch = 0; ch < UART_MUX_MAX_CHANNELS; ++ch) {
|
||||
if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(20)) == pdTRUE) {
|
||||
ws2812_status_indicate_polling(ch, 2000);
|
||||
if (uart_mux_select_locked(ch) == ESP_OK) {
|
||||
int read = uart_read_bytes(CONFIG_WATCH_UART_PORT,
|
||||
buffer,
|
||||
@@ -85,16 +89,32 @@ static void uart_mux_watchdog_task(void *arg)
|
||||
read_timeout);
|
||||
if (read > 0) {
|
||||
s_last_heartbeat_us[ch] = now;
|
||||
s_consecutive_miss[ch] = 0;
|
||||
ws2812_status_set_ack_state(ch, true);
|
||||
} else if (s_consecutive_miss[ch] < UINT8_MAX) {
|
||||
s_consecutive_miss[ch]++;
|
||||
ws2812_status_set_ack_state(ch, false);
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(s_mutex);
|
||||
}
|
||||
|
||||
if (dcdc_get_state(ch) && s_consecutive_miss[ch] >= 3) {
|
||||
ESP_LOGW(TAG, "CH%u: немає відповіді 3 рази поспіль, перезапуск живлення", (unsigned)ch);
|
||||
ws2812_status_set_ack_state(ch, false);
|
||||
dcdc_disable(ch);
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
dcdc_enable(ch);
|
||||
s_consecutive_miss[ch] = 0;
|
||||
s_last_heartbeat_us[ch] = esp_timer_get_time();
|
||||
}
|
||||
|
||||
if (dcdc_get_state(ch) && s_last_heartbeat_us[ch] > 0 &&
|
||||
(now - s_last_heartbeat_us[ch]) > timeout_us) {
|
||||
ESP_LOGW(TAG, "Heartbeat каналу %u втрачено, перезавантаження...", (unsigned)ch);
|
||||
ws2812_status_set_ack_state(ch, false);
|
||||
dcdc_disable(ch);
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||
dcdc_enable(ch);
|
||||
s_last_heartbeat_us[ch] = esp_timer_get_time();
|
||||
}
|
||||
@@ -156,6 +176,7 @@ esp_err_t uart_mux_init(void)
|
||||
int64_t now = esp_timer_get_time();
|
||||
for (size_t ch = 0; ch < UART_MUX_MAX_CHANNELS; ++ch) {
|
||||
s_last_heartbeat_us[ch] = now;
|
||||
s_consecutive_miss[ch] = 0;
|
||||
}
|
||||
|
||||
if (xTaskCreate(uart_mux_watchdog_task, "uart_mux_wd", 4096, NULL, 5, &s_watchdog_task) != pdPASS) {
|
||||
@@ -208,6 +229,10 @@ esp_err_t uart_mux_write(size_t channel, const uint8_t *data, size_t length, Tic
|
||||
int written = uart_write_bytes(CONFIG_WATCH_UART_PORT, (const char *)data, length);
|
||||
if (written < 0 || (size_t)written != length) {
|
||||
err = ESP_FAIL;
|
||||
} else {
|
||||
if (uart_wait_tx_done(CONFIG_WATCH_UART_PORT, timeout) != ESP_OK) {
|
||||
err = ESP_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(s_mutex);
|
||||
|
||||
Reference in New Issue
Block a user