diff --git a/subsys/modbus/modbus_internal.h b/subsys/modbus/modbus_internal.h index 080da58ea09..8b40f7c6476 100644 --- a/subsys/modbus/modbus_internal.h +++ b/subsys/modbus/modbus_internal.h @@ -88,6 +88,7 @@ struct modbus_serial_config { }; #define MODBUS_STATE_CONFIGURED 0 +#define MODBUS_STATE_RX_ENABLED 1 struct modbus_context { /* Interface name */ diff --git a/subsys/modbus/modbus_serial.c b/subsys/modbus/modbus_serial.c index d76ebff4cd9..2a96ac37b6a 100644 --- a/subsys/modbus/modbus_serial.c +++ b/subsys/modbus/modbus_serial.c @@ -50,6 +50,17 @@ static void modbus_serial_tx_off(struct modbus_context *ctx) } } +static void modbus_serial_rx_fifo_drain(struct modbus_context *ctx) +{ + struct modbus_serial_config *cfg = ctx->cfg; + uint8_t buf[8]; + int n; + + do { + n = uart_fifo_read(cfg->dev, buf, sizeof(buf)); + } while (n == sizeof(buf)); +} + static void modbus_serial_rx_on(struct modbus_context *ctx) { struct modbus_serial_config *cfg = ctx->cfg; @@ -58,6 +69,7 @@ static void modbus_serial_rx_on(struct modbus_context *ctx) gpio_pin_set(cfg->re->port, cfg->re->pin, 1); } + atomic_set_bit(&ctx->state, MODBUS_STATE_RX_ENABLED); uart_irq_rx_enable(cfg->dev); } @@ -66,6 +78,8 @@ static void modbus_serial_rx_off(struct modbus_context *ctx) struct modbus_serial_config *cfg = ctx->cfg; uart_irq_rx_disable(cfg->dev); + atomic_clear_bit(&ctx->state, MODBUS_STATE_RX_ENABLED); + if (cfg->re != NULL) { gpio_pin_set(cfg->re->port, cfg->re->pin, 0); } @@ -312,6 +326,11 @@ static void cb_handler_rx(struct modbus_context *ctx) { struct modbus_serial_config *cfg = ctx->cfg; + if (!atomic_test_bit(&ctx->state, MODBUS_STATE_RX_ENABLED)) { + modbus_serial_rx_fifo_drain(ctx); + return; + } + if ((ctx->mode == MODBUS_MODE_ASCII) && IS_ENABLED(CONFIG_MODBUS_ASCII_MODE)) { uint8_t c; @@ -379,6 +398,7 @@ static void cb_handler_tx(struct modbus_context *ctx) /* Disable transmission */ cfg->uart_buf_ptr = &cfg->uart_buf[0]; modbus_serial_tx_off(ctx); + modbus_serial_rx_fifo_drain(ctx); modbus_serial_rx_on(ctx); } }