diff --git a/modbus/mb_ports/tcp/port_tcp_driver.h b/modbus/mb_ports/tcp/port_tcp_driver.h index b28c6a1..98692fa 100644 --- a/modbus/mb_ports/tcp/port_tcp_driver.h +++ b/modbus/mb_ports/tcp/port_tcp_driver.h @@ -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); diff --git a/modbus/mb_ports/tcp/port_tcp_slave.c b/modbus/mb_ports/tcp/port_tcp_slave.c index 5f7e67f..05e5fa5 100644 --- a/modbus/mb_ports/tcp/port_tcp_slave.c +++ b/modbus/mb_ports/tcp/port_tcp_slave.c @@ -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);