fix slave tcp skips response from multiple masters

This commit is contained in:
aleks
2025-07-23 12:12:04 +02:00
parent ff8b978fba
commit 32c670b71c
2 changed files with 28 additions and 25 deletions

View File

@@ -90,15 +90,15 @@ typedef struct _port_driver port_driver_t;
#define MB_EVENT_BASE(context) (__extension__( \
{ \
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(context); \
(pdrv_ctx->loop_name) ? (esp_event_base_t)(pdrv_ctx->loop_name) : "UNK_BASE"; \
port_driver_t *drv_obj = MB_GET_DRV_PTR(context); \
(drv_obj->loop_name) ? (esp_event_base_t)(drv_obj->loop_name) : "UNK_BASE"; \
} \
))
#define MB_ADD_FD(fd, max_fd, pfdset) do { \
#define MB_ADD_FD(fd, max_fd, fdset) do { \
if (fd) { \
(max_fd = (fd > max_fd) ? fd : max_fd); \
FD_SET(fd, pfdset); \
FD_SET(fd, fdset); \
} \
} while(0)
@@ -106,15 +106,15 @@ typedef struct _port_driver port_driver_t;
// Macro for atomic operations
#define MB_ATOMIC_LOAD(ctx, addr) (__extension__( \
{ \
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx); \
(CRITICAL_LOAD(pdrv_ctx->lock, addr)); \
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx); \
(CRITICAL_LOAD(drv_obj->lock, addr)); \
} \
))
#define MB_ATOMIC_STORE(ctx, addr, val) (__extension__( \
{ \
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx); \
CRITICAL_STORE(pdrv_ctx->lock, addr, val); \
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx); \
CRITICAL_STORE(drv_obj->lock, addr, val); \
} \
))
@@ -122,11 +122,11 @@ typedef struct _port_driver port_driver_t;
// So, the eventfd value keeps last event and its fd.
#define DRIVER_SEND_EVENT(ctx, event, fd) (__extension__( \
{ \
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx); \
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx); \
mb_event_info_t (event_info##__FUNCTION__##__LINE__); \
(event_info##__FUNCTION__##__LINE__).event_id = (int32_t)event; \
(event_info##__FUNCTION__##__LINE__).opt_fd = fd; \
((write_event((void *)pdrv_ctx, &(event_info##__FUNCTION__##__LINE__)) > 0) \
((write_event((void *)drv_obj, &(event_info##__FUNCTION__##__LINE__)) > 0) \
? ((event_info##__FUNCTION__##__LINE__)).event_id : UNDEF_FD); \
} \
))
@@ -203,7 +203,7 @@ typedef enum _mb_sync_event {
typedef enum _mb_status_flags {
MB_FLAG_BLANK = 0x0000,
MB_FLAG_TRANSACTION_DONE = 0x0001,
MB_FLAG_TRANSACTION_READY = 0x0001,
MB_FLAG_DISCONNECTED = 0x0002,
MB_FLAG_CONNECTED = 0x0004,
MB_FLAG_SUSPEND = 0x0008,
@@ -263,7 +263,7 @@ typedef struct _port_driver {
* @return esp_err_t
* - ESP_OK on success
*/
esp_err_t mb_drv_register(port_driver_t **config);
esp_err_t mb_drv_register(port_driver_t **ctx);
/**
* @brief Unregister modbus driver
@@ -317,7 +317,7 @@ ssize_t mb_drv_read(void *ctx, int fd, void *data, size_t size);
int mb_drv_close(void *ctx, int fd);
int32_t write_event(void *ctx, mb_event_info_t *pevent);
int32_t write_event(void *ctx, mb_event_info_t *event);
const char *driver_event_to_name_r(mb_driver_event_t event);
@@ -335,7 +335,7 @@ void mb_drv_lock(void *ctx);
void mb_drv_unlock(void *ctx);
mb_node_info_t *mb_drv_get_next_node_from_set(void *ctx, int *pfd, fd_set *pfdset);
mb_node_info_t *mb_drv_get_next_node_from_set(void *ctx, int *fd_ptr, fd_set *fdset);
mb_status_flags_t mb_drv_set_status_flag(void *ctx, mb_status_flags_t mask);

View File

@@ -360,6 +360,7 @@ MB_EVENT_HANDLER(mbs_on_ready)
pdrv_ctx->listen_sock_fd = listen_sock;
// so, all accepted sockets will inherit the keep-alive feature
(void)port_keep_alive(pdrv_ctx->listen_sock_fd);
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_READY);
mb_drv_unlock(ctx);
ESP_LOGI(TAG, "%s %s: fd: %d, bind is done", (char *)base, __func__, (int)pevent_info->opt_fd);
}
@@ -425,13 +426,21 @@ MB_EVENT_HANDLER(mbs_on_recv_data)
mb_drv_unlock(pdrv_ctx);
}
}
mb_drv_lock(pdrv_ctx);
item = transaction_get_first(port_obj->transaction);
if (item)
{
mb_status_flags_t flags = mb_drv_wait_status_flag(port_obj->pdriver, MB_FLAG_TRANSACTION_READY, TRANSACTION_TICKS);
if (transaction_item_get_state(item) == QUEUED)
{
if (MB_FLAG_TRANSACTION_READY == flags) {
(void)mb_drv_clear_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_READY);
} else {
// postpone the packet processing
DRIVER_SEND_EVENT(ctx, MB_EVENT_RECV_DATA, pnode->index);
return;
}
// send receive event to modbus object to get the new data
mb_drv_lock(pdrv_ctx);
uint16_t msg_id = 0;
uint64_t tick = 0;
(void)transaction_item_get_data(item, NULL, &msg_id, NULL);
@@ -443,25 +452,18 @@ MB_EVENT_HANDLER(mbs_on_recv_data)
pdrv_ctx, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, (unsigned)msg_id);
}
mb_drv_unlock(pdrv_ctx);
}
else
{
if (transaction_item_get_state(item) != TRANSMITTED) {
// Todo: for test removing expired item
// Transaction procesing is ongoing, just delete expired transactions
transaction_delete_expired(port_obj->transaction, port_get_timestamp(), 1000 * 1000);
}
if (MB_FLAG_TRANSACTION_DONE == mb_drv_wait_status_flag(port_obj->pdriver,
MB_FLAG_TRANSACTION_DONE,
TRANSACTION_TICKS)) {
(void)mb_drv_clear_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_DONE);
}
// postpone the packet processing
DRIVER_SEND_EVENT(ctx, MB_EVENT_RECV_DATA, pnode->index);
}
} else {
ESP_LOGE(TAG, "%p, no queued items found", ctx);
}
mb_drv_unlock(pdrv_ctx);
}
mb_drv_check_suspend_shutdown(ctx);
}
@@ -502,6 +504,7 @@ MB_EVENT_HANDLER(mbs_on_send_data)
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", send incorrect frame TID:0x%04" PRIx16 "!= 0x%04" PRIx16 ", %d (bytes), errno %d"),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, pnode->tid_counter, tid, (int)ret, (unsigned)errno);
pnode->tid_counter = tid; // update the TID to the current one
}
else
{
@@ -511,7 +514,7 @@ MB_EVENT_HANDLER(mbs_on_send_data)
}
ESP_LOG_BUFFER_HEX_LEVEL("SENT", frame_entry.pbuf, ret, ESP_LOG_DEBUG);
}
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_DONE);
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_READY);
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_SEND_OK);
mb_drv_lock(pdrv_ctx);
transaction_set_state(port_obj->transaction, tid, TRANSMITTED);