feat(gateway): add KNX TP UART startup timeout configuration and enhance initialization logic

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-05-16 03:40:45 +08:00
parent 277379abd7
commit 323ff24c04
6 changed files with 40 additions and 1 deletions
+11
View File
@@ -831,6 +831,17 @@ config GATEWAY_KNX_TP_BAUDRATE
range 1200 921600 range 1200 921600
default 19200 default 19200
config GATEWAY_KNX_TP_STARTUP_TIMEOUT_MS
int "KNX TP UART startup timeout (ms)"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range 0 10000
default 2000
help
How long the gateway should keep retrying TP-UART startup before
giving up. This covers transient UART/GPIO ownership races that can
happen immediately after an ETS-triggered reboot. Set to 0 to keep the
previous single-shot startup behavior.
config GATEWAY_KNX_TP_UART_9BIT_MODE config GATEWAY_KNX_TP_UART_9BIT_MODE
bool "KNX TP UART 9-bit mode" bool "KNX TP UART 9-bit mode"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED depends on GATEWAY_KNX_BRIDGE_SUPPORTED
+6
View File
@@ -107,6 +107,10 @@
#define CONFIG_GATEWAY_485_CONTROL_TASK_PRIORITY 4 #define CONFIG_GATEWAY_485_CONTROL_TASK_PRIORITY 4
#endif #endif
#ifndef CONFIG_GATEWAY_KNX_TP_STARTUP_TIMEOUT_MS
#define CONFIG_GATEWAY_KNX_TP_STARTUP_TIMEOUT_MS 2000
#endif
#ifndef CONFIG_GATEWAY_SMARTCONFIG_TIMEOUT_SEC #ifndef CONFIG_GATEWAY_SMARTCONFIG_TIMEOUT_SEC
#define CONFIG_GATEWAY_SMARTCONFIG_TIMEOUT_SEC 60 #define CONFIG_GATEWAY_SMARTCONFIG_TIMEOUT_SEC 60
#endif #endif
@@ -907,6 +911,8 @@ extern "C" void app_main(void) {
default_knx.tp_uart.tx_pin = CONFIG_GATEWAY_KNX_TP_TX_PIN; default_knx.tp_uart.tx_pin = CONFIG_GATEWAY_KNX_TP_TX_PIN;
default_knx.tp_uart.rx_pin = CONFIG_GATEWAY_KNX_TP_RX_PIN; default_knx.tp_uart.rx_pin = CONFIG_GATEWAY_KNX_TP_RX_PIN;
default_knx.tp_uart.baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_KNX_TP_BAUDRATE); default_knx.tp_uart.baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_KNX_TP_BAUDRATE);
default_knx.tp_uart.startup_timeout_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_KNX_TP_STARTUP_TIMEOUT_MS);
#ifdef CONFIG_GATEWAY_KNX_TP_UART_9BIT_MODE #ifdef CONFIG_GATEWAY_KNX_TP_UART_9BIT_MODE
default_knx.tp_uart.nine_bit_mode = true; default_knx.tp_uart.nine_bit_mode = true;
#else #else
+1
View File
@@ -697,6 +697,7 @@ CONFIG_GATEWAY_KNX_TP_UART_PORT=0
CONFIG_GATEWAY_KNX_TP_TX_PIN=-1 CONFIG_GATEWAY_KNX_TP_TX_PIN=-1
CONFIG_GATEWAY_KNX_TP_RX_PIN=-1 CONFIG_GATEWAY_KNX_TP_RX_PIN=-1
CONFIG_GATEWAY_KNX_TP_BAUDRATE=19200 CONFIG_GATEWAY_KNX_TP_BAUDRATE=19200
CONFIG_GATEWAY_KNX_TP_STARTUP_TIMEOUT_MS=2000
CONFIG_GATEWAY_KNX_TP_UART_9BIT_MODE=y CONFIG_GATEWAY_KNX_TP_UART_9BIT_MODE=y
CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE=12288 CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE=12288
CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY=5 CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY=5
@@ -33,6 +33,7 @@ class TpuartUartInterface;
constexpr uint16_t kGatewayKnxDefaultUdpPort = 3671; constexpr uint16_t kGatewayKnxDefaultUdpPort = 3671;
constexpr const char* kGatewayKnxDefaultMulticastAddress = "224.0.23.12"; constexpr const char* kGatewayKnxDefaultMulticastAddress = "224.0.23.12";
constexpr uint32_t kGatewayKnxDefaultTpBaudrate = 19200; constexpr uint32_t kGatewayKnxDefaultTpBaudrate = 19200;
constexpr uint32_t kGatewayKnxDefaultTpStartupTimeoutMs = 2000;
struct GatewayKnxTpUartConfig { struct GatewayKnxTpUartConfig {
int uart_port{1}; int uart_port{1};
@@ -41,6 +42,7 @@ struct GatewayKnxTpUartConfig {
uint32_t baudrate{kGatewayKnxDefaultTpBaudrate}; uint32_t baudrate{kGatewayKnxDefaultTpBaudrate};
size_t rx_buffer_size{1024}; size_t rx_buffer_size{1024};
size_t tx_buffer_size{1024}; size_t tx_buffer_size{1024};
uint32_t startup_timeout_ms{kGatewayKnxDefaultTpStartupTimeoutMs};
uint32_t read_timeout_ms{20}; uint32_t read_timeout_ms{20};
bool nine_bit_mode{true}; bool nine_bit_mode{true};
}; };
@@ -804,6 +804,9 @@ std::optional<GatewayKnxConfig> GatewayKnxConfigFromValue(const DaliValue* value
config.tp_uart.tx_buffer_size = static_cast<size_t>(std::max( config.tp_uart.tx_buffer_size = static_cast<size_t>(std::max(
128, ObjectIntAny(serial, {"txBufferSize", "tx_buffer_size"}) 128, ObjectIntAny(serial, {"txBufferSize", "tx_buffer_size"})
.value_or(static_cast<int>(config.tp_uart.tx_buffer_size)))); .value_or(static_cast<int>(config.tp_uart.tx_buffer_size))));
config.tp_uart.startup_timeout_ms = static_cast<uint32_t>(std::max(
0, ObjectIntAny(serial, {"startupTimeoutMs", "startup_timeout_ms"})
.value_or(static_cast<int>(config.tp_uart.startup_timeout_ms))));
config.tp_uart.read_timeout_ms = static_cast<uint32_t>(std::max( config.tp_uart.read_timeout_ms = static_cast<uint32_t>(std::max(
1, ObjectIntAny(serial, {"readTimeoutMs", "read_timeout_ms"}) 1, ObjectIntAny(serial, {"readTimeoutMs", "read_timeout_ms"})
.value_or(static_cast<int>(config.tp_uart.read_timeout_ms)))); .value_or(static_cast<int>(config.tp_uart.read_timeout_ms))));
@@ -840,6 +843,7 @@ DaliValue GatewayKnxConfigToValue(const GatewayKnxConfig& config) {
serial["baudrate"] = static_cast<int>(config.tp_uart.baudrate); serial["baudrate"] = static_cast<int>(config.tp_uart.baudrate);
serial["rxBufferSize"] = static_cast<int>(config.tp_uart.rx_buffer_size); serial["rxBufferSize"] = static_cast<int>(config.tp_uart.rx_buffer_size);
serial["txBufferSize"] = static_cast<int>(config.tp_uart.tx_buffer_size); serial["txBufferSize"] = static_cast<int>(config.tp_uart.tx_buffer_size);
serial["startupTimeoutMs"] = static_cast<int>(config.tp_uart.startup_timeout_ms);
serial["readTimeoutMs"] = static_cast<int>(config.tp_uart.read_timeout_ms); serial["readTimeoutMs"] = static_cast<int>(config.tp_uart.read_timeout_ms);
serial["nineBitMode"] = config.tp_uart.nine_bit_mode; serial["nineBitMode"] = config.tp_uart.nine_bit_mode;
out["tpUart"] = std::move(serial); out["tpUart"] = std::move(serial);
@@ -2447,7 +2451,17 @@ bool GatewayKnxTpIpRouter::configureTpUart() {
ESP_LOGE(kTag, "%s", last_error_.c_str()); ESP_LOGE(kTag, "%s", last_error_.c_str());
return false; return false;
} }
const TickType_t startup_timeout_ticks =
pdMS_TO_TICKS(config_.tp_uart.startup_timeout_ms);
const TickType_t retry_poll_ticks = std::max<TickType_t>(1, pdMS_TO_TICKS(20));
const TickType_t startup_begin_tick = xTaskGetTickCount();
tp_uart_online_ = ets_device_->enableTpUart(true); tp_uart_online_ = ets_device_->enableTpUart(true);
while (!tp_uart_online_ && startup_timeout_ticks > 0 &&
(xTaskGetTickCount() - startup_begin_tick) < startup_timeout_ticks) {
vTaskDelay(retry_poll_ticks);
ets_device_->loop();
tp_uart_online_ = ets_device_->tpUartOnline();
}
if (!tp_uart_online_) { if (!tp_uart_online_) {
last_error_ = "OpenKNX failed to initialize KNX TP-UART uart=" + last_error_ = "OpenKNX failed to initialize KNX TP-UART uart=" +
std::to_string(config_.tp_uart.uart_port) + " tx=" + std::to_string(config_.tp_uart.uart_port) + " tx=" +
@@ -2465,6 +2479,11 @@ bool GatewayKnxTpIpRouter::configureTpUart() {
ESP_LOGE(kTag, "%s", last_error_.c_str()); ESP_LOGE(kTag, "%s", last_error_.c_str());
return false; return false;
} }
const TickType_t startup_elapsed_ticks = xTaskGetTickCount() - startup_begin_tick;
if (startup_elapsed_ticks > 0) {
ESP_LOGI(kTag, "KNX TP-UART startup settled after %lu ms",
static_cast<unsigned long>(pdTICKS_TO_MS(startup_elapsed_ticks)));
}
ESP_LOGI(kTag, "KNX TP-UART online uart=%d tx=%s rx=%s baud=%u nineBit=%d", ESP_LOGI(kTag, "KNX TP-UART online uart=%d tx=%s rx=%s baud=%u nineBit=%d",
config_.tp_uart.uart_port, config_.tp_uart.uart_port,
UartPinDescription(config_.tp_uart.tx_pin, tp_uart_tx_pin_).c_str(), UartPinDescription(config_.tp_uart.tx_pin, tp_uart_tx_pin_).c_str(),
+1 -1
Submodule tpuart updated: d95248f994...0dd32a4246