mirror of
https://github.com/espressif/esp-modbus.git
synced 2025-08-03 12:24:27 +02:00
fix slave tcp skips response from multiple masters
This commit is contained in:
@@ -90,15 +90,15 @@ typedef struct _port_driver port_driver_t;
|
|||||||
|
|
||||||
#define MB_EVENT_BASE(context) (__extension__( \
|
#define MB_EVENT_BASE(context) (__extension__( \
|
||||||
{ \
|
{ \
|
||||||
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(context); \
|
port_driver_t *drv_obj = MB_GET_DRV_PTR(context); \
|
||||||
(pdrv_ctx->loop_name) ? (esp_event_base_t)(pdrv_ctx->loop_name) : "UNK_BASE"; \
|
(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) { \
|
if (fd) { \
|
||||||
(max_fd = (fd > max_fd) ? fd : max_fd); \
|
(max_fd = (fd > max_fd) ? fd : max_fd); \
|
||||||
FD_SET(fd, pfdset); \
|
FD_SET(fd, fdset); \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
@@ -106,15 +106,15 @@ typedef struct _port_driver port_driver_t;
|
|||||||
// Macro for atomic operations
|
// Macro for atomic operations
|
||||||
#define MB_ATOMIC_LOAD(ctx, addr) (__extension__( \
|
#define MB_ATOMIC_LOAD(ctx, addr) (__extension__( \
|
||||||
{ \
|
{ \
|
||||||
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx); \
|
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx); \
|
||||||
(CRITICAL_LOAD(pdrv_ctx->lock, addr)); \
|
(CRITICAL_LOAD(drv_obj->lock, addr)); \
|
||||||
} \
|
} \
|
||||||
))
|
))
|
||||||
|
|
||||||
#define MB_ATOMIC_STORE(ctx, addr, val) (__extension__( \
|
#define MB_ATOMIC_STORE(ctx, addr, val) (__extension__( \
|
||||||
{ \
|
{ \
|
||||||
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx); \
|
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx); \
|
||||||
CRITICAL_STORE(pdrv_ctx->lock, addr, val); \
|
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.
|
// So, the eventfd value keeps last event and its fd.
|
||||||
#define DRIVER_SEND_EVENT(ctx, event, fd) (__extension__( \
|
#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__); \
|
mb_event_info_t (event_info##__FUNCTION__##__LINE__); \
|
||||||
(event_info##__FUNCTION__##__LINE__).event_id = (int32_t)event; \
|
(event_info##__FUNCTION__##__LINE__).event_id = (int32_t)event; \
|
||||||
(event_info##__FUNCTION__##__LINE__).opt_fd = fd; \
|
(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); \
|
? ((event_info##__FUNCTION__##__LINE__)).event_id : UNDEF_FD); \
|
||||||
} \
|
} \
|
||||||
))
|
))
|
||||||
@@ -203,7 +203,7 @@ typedef enum _mb_sync_event {
|
|||||||
|
|
||||||
typedef enum _mb_status_flags {
|
typedef enum _mb_status_flags {
|
||||||
MB_FLAG_BLANK = 0x0000,
|
MB_FLAG_BLANK = 0x0000,
|
||||||
MB_FLAG_TRANSACTION_DONE = 0x0001,
|
MB_FLAG_TRANSACTION_READY = 0x0001,
|
||||||
MB_FLAG_DISCONNECTED = 0x0002,
|
MB_FLAG_DISCONNECTED = 0x0002,
|
||||||
MB_FLAG_CONNECTED = 0x0004,
|
MB_FLAG_CONNECTED = 0x0004,
|
||||||
MB_FLAG_SUSPEND = 0x0008,
|
MB_FLAG_SUSPEND = 0x0008,
|
||||||
@@ -263,7 +263,7 @@ typedef struct _port_driver {
|
|||||||
* @return esp_err_t
|
* @return esp_err_t
|
||||||
* - ESP_OK on success
|
* - 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
|
* @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);
|
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);
|
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);
|
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);
|
mb_status_flags_t mb_drv_set_status_flag(void *ctx, mb_status_flags_t mask);
|
||||||
|
|
||||||
|
@@ -360,6 +360,7 @@ MB_EVENT_HANDLER(mbs_on_ready)
|
|||||||
pdrv_ctx->listen_sock_fd = listen_sock;
|
pdrv_ctx->listen_sock_fd = listen_sock;
|
||||||
// so, all accepted sockets will inherit the keep-alive feature
|
// so, all accepted sockets will inherit the keep-alive feature
|
||||||
(void)port_keep_alive(pdrv_ctx->listen_sock_fd);
|
(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);
|
mb_drv_unlock(ctx);
|
||||||
ESP_LOGI(TAG, "%s %s: fd: %d, bind is done", (char *)base, __func__, (int)pevent_info->opt_fd);
|
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_unlock(pdrv_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mb_drv_lock(pdrv_ctx);
|
|
||||||
item = transaction_get_first(port_obj->transaction);
|
item = transaction_get_first(port_obj->transaction);
|
||||||
if (item)
|
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 (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
|
// send receive event to modbus object to get the new data
|
||||||
|
mb_drv_lock(pdrv_ctx);
|
||||||
uint16_t msg_id = 0;
|
uint16_t msg_id = 0;
|
||||||
uint64_t tick = 0;
|
uint64_t tick = 0;
|
||||||
(void)transaction_item_get_data(item, NULL, &msg_id, NULL);
|
(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,
|
pdrv_ctx, pnode->index, pnode->sock_id,
|
||||||
pnode->addr_info.ip_addr_str, (unsigned)msg_id);
|
pnode->addr_info.ip_addr_str, (unsigned)msg_id);
|
||||||
}
|
}
|
||||||
|
mb_drv_unlock(pdrv_ctx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (transaction_item_get_state(item) != TRANSMITTED) {
|
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);
|
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 {
|
} else {
|
||||||
ESP_LOGE(TAG, "%p, no queued items found", ctx);
|
ESP_LOGE(TAG, "%p, no queued items found", ctx);
|
||||||
}
|
}
|
||||||
mb_drv_unlock(pdrv_ctx);
|
|
||||||
}
|
}
|
||||||
mb_drv_check_suspend_shutdown(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"),
|
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,
|
ctx, (int)pnode->index, (int)pnode->sock_id,
|
||||||
pnode->addr_info.ip_addr_str, pnode->tid_counter, tid, (int)ret, (unsigned)errno);
|
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
|
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);
|
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);
|
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_SEND_OK);
|
||||||
mb_drv_lock(pdrv_ctx);
|
mb_drv_lock(pdrv_ctx);
|
||||||
transaction_set_state(port_obj->transaction, tid, TRANSMITTED);
|
transaction_set_state(port_obj->transaction, tid, TRANSMITTED);
|
||||||
|
Reference in New Issue
Block a user