fix: address maximum api blocking time

This commit is contained in:
Alex Lisitsyn
2026-06-26 15:26:05 +01:00
parent db0cc168e9
commit 7473cf935a
4 changed files with 64 additions and 10 deletions
+10 -1
View File
@@ -71,12 +71,21 @@ menu "Modbus configuration"
config FMB_MASTER_TIMEOUT_MS_RESPOND
int "Slave respond timeout (Milliseconds)"
default 10000
default 5000
range 150 30000
help
If master sends a frame which is not broadcast, it has to wait some time for slave response.
if slave is not respond in this time, the master will process timeout error.
config FMB_MASTER_MAX_API_BLOCKING_TIME_MS
int "Modbus TCP master API blocking threshold (ms)"
range 3000 200000
default 6000
help
This option represents the maximum API blocking time used by controller API calls.
This API blocking time was intentionally separated from master timeout = CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND
to prevent possible misconfiguration and the value must be higher than the master timeout.
config FMB_MASTER_DELAY_MS_CONVERT
int "Slave conversion delay (Milliseconds)"
default 200
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2016-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -13,6 +13,8 @@
static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_MASTER";
#define API_BLOCKING_THRESHOLD 500
// This file implements public API for Modbus master controller.
/**
@@ -203,6 +205,20 @@ esp_err_t mbc_master_start(void *ctx)
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
"Master interface is not correctly initialized.");
mbm_controller_iface_t *mbm_controller = MB_MASTER_GET_IFACE(ctx);
uint32_t response_tout_ms = mbm_controller->opts.comm_opts.common_opts.response_tout_ms;
// Keep stack response timeout below API blocking threshold
if (!response_tout_ms || (response_tout_ms >= CONFIG_FMB_MASTER_MAX_API_BLOCKING_TIME_MS)) {
response_tout_ms = (CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND
<= (CONFIG_FMB_MASTER_MAX_API_BLOCKING_TIME_MS - API_BLOCKING_THRESHOLD))
? CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND
: (CONFIG_FMB_MASTER_MAX_API_BLOCKING_TIME_MS - API_BLOCKING_THRESHOLD);
ESP_LOGW(TAG,
"Master timeout option = (%u) exceeded the maximum API threshold or is uninitialized, will be set to configured value = %u.",
(unsigned)mbm_controller->opts.comm_opts.common_opts.response_tout_ms, (unsigned)response_tout_ms);
mbm_controller->opts.comm_opts.common_opts.response_tout_ms = response_tout_ms;
}
MB_RETURN_ON_FALSE(mbm_controller->start, ESP_ERR_INVALID_STATE, TAG,
"Master interface is not correctly initialized.");
error = mbm_controller->start(ctx);
+14 -4
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2016-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -22,16 +22,26 @@
#include "mb_utils.h"
#include "mb_master.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ----------------------- Defines ------------------------------------------*/
#define MB_MIN_RESP_DELAY_MS (300)
// Set the maximum resource waiting time, the actual time of resource release
// will be dependent on response time set by timer + conversion time if the command is received
#define MB_MAX_RESP_DELAY_MS (3000)
#define MB_MIN_RESP_DELAY_MS (300)
// will be dependent on response time set by timer + conversion time if the command is received.
#if defined(CONFIG_FMB_MASTER_MAX_API_BLOCKING_TIME_MS)
#define MB_MAX_RESP_DELAY_MS (CONFIG_FMB_MASTER_MAX_API_BLOCKING_TIME_MS)
_Static_assert(
(CONFIG_FMB_MASTER_MAX_API_BLOCKING_TIME_MS) >= (CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND),
"CONFIG_FMB_MASTER_MAX_API_BLOCKING_TIME_MS must be >= CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND"
);
#else
#define MB_MAX_RESP_DELAY_MS (CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND)
#endif
/**
* @brief Modbus controller handler structure
+23 -4
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -37,11 +37,15 @@ typedef enum mb_comm_mode_enum mb_mode_type_t;
#if (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)
#include <stddef.h>
#include "driver/uart.h"
struct port_serial_opts_s {
mb_mode_type_t mode; /*!< Modbus communication mode */
uart_port_t port; /*!< Modbus communication port (UART) number */
union {
uart_port_t port; /*!< UART driver port index (user API) */
uint32_t ser_port_align; /*!< Overlay for union with TCP/common \c port field */
};
uint8_t uid; /*!< Modbus slave address field (dummy for master) */
uint32_t response_tout_ms; /*!< Modbus slave response timeout */
uint64_t test_tout_us; /*!< Modbus test timeout (reserved) */
@@ -63,7 +67,7 @@ typedef enum addr_type_enum {
struct port_common_opts_s {
mb_mode_type_t mode; /*!< Modbus communication mode */
uint16_t port; /*!< Modbus communication port (UART) number */
uint32_t port; /*!< Modbus port number (TCP) or UART index (serial) */
uint8_t uid; /*!< Modbus slave address field (dummy for master) */
uint32_t response_tout_ms; /*!< Modbus slave response timeout */
uint64_t test_tout_us; /*!< Modbus test timeout (reserved) */
@@ -71,7 +75,10 @@ struct port_common_opts_s {
struct port_tcp_opts_s {
mb_mode_type_t mode; /*!< Modbus communication mode */
uint16_t port; /*!< Modbus communication port (UART) number */
struct {
uint16_t port; /*!< Modbus port number (TCP) */
uint16_t tcp_port_align; /*!< Overlay for union with SERIAL/common \c port field */
};
uint8_t uid; /*!< Modbus slave address field (dummy for master) */
uint32_t response_tout_ms; /*!< Modbus slave response timeout */
uint64_t test_tout_us; /*!< Modbus test timeout (reserved) */
@@ -84,6 +91,18 @@ struct port_tcp_opts_s {
typedef struct port_tcp_opts_s mb_tcp_opts_t;
#if (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)
_Static_assert(sizeof(uart_port_t) == sizeof(uint32_t),
"uart_port_t must match uint32_t width of common/tcp port for mb_communication_info_t union");
_Static_assert(offsetof(struct port_serial_opts_s, response_tout_ms) == offsetof(struct port_common_opts_s, response_tout_ms),
"serial/common Modbus opts: response_tout_ms offset must match (mb_communication_info_t union)");
#endif
#if (CONFIG_FMB_COMM_MODE_TCP_EN) && (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)
_Static_assert(offsetof(struct port_serial_opts_s, response_tout_ms) == offsetof(struct port_tcp_opts_s, response_tout_ms),
"serial/tcp Modbus opts: response_tout_ms offset must match (mb_communication_info_t union)");
#endif
// The common object descriptor structure (common for mb, transport, port objects)
struct obj_descr_s {
char *parent_name; /*!< Name of the parent (base) object */