modbus: serial: Add non-compliant mode with custom stop-bit settings

The mode is activated by the CONFIG_MODBUS_NONCOMPLIANT_SERIAL_MODE option
and allows any stop-bit setting for the serial port.

Signed-off-by: Maksim Salau <msalau@iotecha.com>
This commit is contained in:
Maksim Salau 2025-03-21 16:47:27 +01:00 committed by Anas Nashif
parent 6e0d0f5879
commit bdd94261a5
7 changed files with 14 additions and 13 deletions

View File

@ -10,6 +10,7 @@ config PZEM004T
depends on MODBUS
depends on MODBUS_SERIAL
depends on MODBUS_RAW_ADU
select MODBUS_NONCOMPLIANT_SERIAL_MODE
help
Enable the driver for the Peacefair PZEM004T Multifunction AC Meter.

View File

@ -325,7 +325,7 @@ static const struct pzem004t_config pzem004t_config_##inst = {
{ \
.baud = 9600, \
.parity = UART_CFG_PARITY_NONE, \
.stop_bits_client = UART_CFG_STOP_BITS_1, \
.stop_bits = UART_CFG_STOP_BITS_1, \
}, \
}, \
}; \

View File

@ -484,13 +484,13 @@ struct modbus_serial_param {
* UART_CFG_PARITY_ODD
*/
enum uart_config_parity parity;
/** stop_bits_client UART's stop bits setting if in client mode:
/** stop_bits UART's stop bits setting in non-compliant mode:
* UART_CFG_STOP_BITS_0_5,
* UART_CFG_STOP_BITS_1,
* UART_CFG_STOP_BITS_1_5,
* UART_CFG_STOP_BITS_2,
*/
enum uart_config_stop_bits stop_bits_client;
enum uart_config_stop_bits stop_bits;
};
/**

View File

@ -19,7 +19,6 @@ const static struct modbus_iface_param client_param = {
.serial = {
.baud = 19200,
.parity = UART_CFG_PARITY_NONE,
.stop_bits_client = UART_CFG_STOP_BITS_2,
},
};

View File

@ -79,6 +79,12 @@ config MODBUS_FC08_DIAGNOSTIC
help
Enable function code 08 Diagnostic support
config MODBUS_NONCOMPLIANT_SERIAL_MODE
bool "Non-compliant serial mode"
depends on MODBUS_SERIAL
help
Allow non-compliant stop and parity bit settings.
module = MODBUS
module-str = Modbus Support
module-help = Sets log level for Modbus support

View File

@ -477,14 +477,14 @@ static inline int configure_uart(struct modbus_context *ctx,
return -EINVAL;
}
if (ctx->client) {
/* Allow custom stop bit settings only in client mode */
switch (param->serial.stop_bits_client) {
if (IS_ENABLED(CONFIG_MODBUS_NONCOMPLIANT_SERIAL_MODE)) {
/* Allow custom stop bit settings only in non-compliant mode */
switch (param->serial.stop_bits) {
case UART_CFG_STOP_BITS_0_5:
case UART_CFG_STOP_BITS_1:
case UART_CFG_STOP_BITS_1_5:
case UART_CFG_STOP_BITS_2:
uart_cfg.stop_bits = param->serial.stop_bits_client;
uart_cfg.stop_bits = param->serial.stop_bits;
break;
default:
return -EINVAL;

View File

@ -216,7 +216,6 @@ static struct modbus_iface_param client_param = {
.serial = {
.baud = MB_TEST_BAUDRATE_LOW,
.parity = UART_CFG_PARITY_ODD,
.stop_bits_client = UART_CFG_STOP_BITS_1,
},
};
@ -241,7 +240,6 @@ void test_client_setup_low_none(void)
client_param.mode = MODBUS_MODE_RTU;
client_param.serial.baud = MB_TEST_BAUDRATE_LOW;
client_param.serial.parity = UART_CFG_PARITY_NONE;
client_param.serial.stop_bits_client = UART_CFG_STOP_BITS_2;
err = modbus_init_client(client_iface, client_param);
zassert_equal(err, 0, "Failed to configure RTU client");
@ -255,7 +253,6 @@ void test_client_setup_low_odd(void)
client_param.mode = MODBUS_MODE_RTU;
client_param.serial.baud = MB_TEST_BAUDRATE_LOW;
client_param.serial.parity = UART_CFG_PARITY_ODD;
client_param.serial.stop_bits_client = UART_CFG_STOP_BITS_1;
err = modbus_init_client(client_iface, client_param);
zassert_equal(err, 0, "Failed to configure RTU client");
@ -269,7 +266,6 @@ void test_client_setup_high_even(void)
client_param.mode = MODBUS_MODE_RTU;
client_param.serial.baud = MB_TEST_BAUDRATE_HIGH;
client_param.serial.parity = UART_CFG_PARITY_EVEN;
client_param.serial.stop_bits_client = UART_CFG_STOP_BITS_1;
err = modbus_init_client(client_iface, client_param);
zassert_equal(err, 0, "Failed to configure RTU client");
@ -283,7 +279,6 @@ void test_client_setup_ascii(void)
client_param.mode = MODBUS_MODE_ASCII;
client_param.serial.baud = MB_TEST_BAUDRATE_HIGH;
client_param.serial.parity = UART_CFG_PARITY_EVEN;
client_param.serial.stop_bits_client = UART_CFG_STOP_BITS_1;
err = modbus_init_client(client_iface, client_param);