From 4ff616b647ac33d543b639142e466622de0a866e Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Wed, 10 Mar 2021 19:19:12 +0100 Subject: [PATCH] modbus: rework interface configuration Use commot parameter structure to configure server or client interfaces. Signed-off-by: Johann Fischer --- include/modbus/modbus.h | 98 +++++++---- samples/subsys/modbus/rtu_client/src/main.c | 35 ++-- samples/subsys/modbus/rtu_server/src/main.c | 15 +- subsys/modbus/modbus_core.c | 166 ++++++++++--------- subsys/modbus/modbus_internal.h | 16 +- subsys/modbus/modbus_serial.c | 32 ++-- tests/subsys/modbus/src/test_modbus_client.c | 111 ++++++++----- tests/subsys/modbus/src/test_modbus_server.c | 69 ++++++-- 8 files changed, 338 insertions(+), 204 deletions(-) diff --git a/include/modbus/modbus.h b/include/modbus/modbus.h index 42e3f2536e7..6a8be81fcba 100644 --- a/include/modbus/modbus.h +++ b/include/modbus/modbus.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 PHYTEC Messtechnik GmbH + * Copyright (c) 2021 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -347,44 +348,79 @@ struct modbus_user_callbacks { int modbus_iface_get_by_name(const char *iface_name); /** - * @brief Configure Modbus Interface as server - * - * @param iface Modbus interface index - * @param unit_id Modbus unit ID of the server - * @param baud Baudrate of the serial line - * @param parity UART's parity setting: - * UART_CFG_PARITY_NONE, - * UART_CFG_PARITY_EVEN, - * UART_CFG_PARITY_ODD - * @param cb Pointer to the User Callback structure - * @param ascii_mode Enable ASCII Transfer Mode - * - * @retval 0 If the function was successful + * @brief Modbus interface mode */ -int modbus_init_server(const uint8_t iface, const uint8_t unit_id, - const uint32_t baud, enum uart_config_parity parity, - struct modbus_user_callbacks *const cb, - bool ascii_mode); +enum modbus_mode { + /** Modbus over serial line RTU mode */ + MODBUS_MODE_RTU, + /** Modbus over serial line ASCII mode */ + MODBUS_MODE_ASCII, +}; /** - * @brief Configure Modbus Interface as client + * @brief Modbus serial line parameter + */ +struct modbus_serial_param { + /** Baudrate of the serial line */ + uint32_t baud; + /** parity UART's parity setting: + * UART_CFG_PARITY_NONE, + * UART_CFG_PARITY_EVEN, + * UART_CFG_PARITY_ODD + */ + enum uart_config_parity parity; +}; + +/** + * @brief Modbus server parameter + */ +struct modbus_server_param { + /** Pointer to the User Callback structure */ + struct modbus_user_callbacks *user_cb; + /** Modbus unit ID of the server */ + uint8_t unit_id; +}; + +/** + * @brief User parameter structure to configure Modbus interfase + * as client or server. + */ +struct modbus_iface_param { + /** Mode of the interface */ + enum modbus_mode mode; + union { + struct modbus_server_param server; + /** Amount of time client will wait for + * a response from the server. + */ + uint32_t rx_timeout; + }; + union { + /** Serial support parameter of the interface */ + struct modbus_serial_param serial; + }; +}; + +/** + * @brief Configure Modbus Interface as raw ADU server * - * @param iface Modbus interface index - * @param baud Baudrate of the serial line - * @param parity UART's parity setting: - * UART_CFG_PARITY_NONE, - * UART_CFG_PARITY_EVEN, - * UART_CFG_PARITY_ODD - * @param rx_timeout Amount of time client will wait for a response - * from the server. - * @param ascii_mode Enable ASCII Transfer Mode + * @param iface Modbus RTU interface index + * @param param Configuration parameter of the server interface * * @retval 0 If the function was successful */ -int modbus_init_client(const uint8_t iface, - const uint32_t baud, enum uart_config_parity parity, - uint32_t rx_timeout, - bool ascii_mode); +int modbus_init_server(const int iface, struct modbus_iface_param param); + +/** + * @brief Configure Modbus Interface as raw ADU client + * + * @param iface Modbus RTU interface index + * @param param Configuration parameter of the client interface + * + * @retval 0 If the function was successful + */ +int modbus_init_client(const int iface, struct modbus_iface_param param); + /** * @brief Disable Modbus Interface * diff --git a/samples/subsys/modbus/rtu_client/src/main.c b/samples/subsys/modbus/rtu_client/src/main.c index 23b38720175..e06238e6351 100644 --- a/samples/subsys/modbus/rtu_client/src/main.c +++ b/samples/subsys/modbus/rtu_client/src/main.c @@ -12,15 +12,24 @@ #include LOG_MODULE_REGISTER(mbc_sample, LOG_LEVEL_INF); -#define RTU_IFACE 0 +static int client_iface; + +const static struct modbus_iface_param client_param = { + .mode = MODBUS_MODE_RTU, + .rx_timeout = 50000, + .serial = { + .baud = 19200, + .parity = UART_CFG_PARITY_NONE, + }, +}; static int init_modbus_client(void) { - const uint32_t mb_rtu_br = 19200; - const uint32_t rsp_timeout = 50000; + const char iface_name[] = {DT_PROP(DT_INST(0, zephyr_modbus_serial), label)}; - return modbus_init_client(RTU_IFACE, mb_rtu_br, UART_CFG_PARITY_NONE, - rsp_timeout, false); + client_iface = modbus_iface_get_by_name(iface_name); + + return modbus_init_client(client_iface, client_param); } void main(void) @@ -38,14 +47,14 @@ void main(void) return; } - err = modbus_write_holding_regs(RTU_IFACE, node, 0, holding_reg, + err = modbus_write_holding_regs(client_iface, node, 0, holding_reg, ARRAY_SIZE(holding_reg)); if (err != 0) { LOG_ERR("FC16 failed"); return; } - err = modbus_read_holding_regs(RTU_IFACE, node, 0, holding_reg, + err = modbus_read_holding_regs(client_iface, node, 0, holding_reg, ARRAY_SIZE(holding_reg)); if (err != 0) { LOG_ERR("FC03 failed with %d", err); @@ -58,7 +67,7 @@ void main(void) while (true) { uint16_t addr = 0; - err = modbus_read_coils(RTU_IFACE, node, 0, coil, coil_qty); + err = modbus_read_coils(client_iface, node, 0, coil, coil_qty); if (err != 0) { LOG_ERR("FC01 failed with %d", err); return; @@ -66,28 +75,28 @@ void main(void) LOG_INF("Coils state 0x%02x", coil[0]); - err = modbus_write_coil(RTU_IFACE, node, addr++, true); + err = modbus_write_coil(client_iface, node, addr++, true); if (err != 0) { LOG_ERR("FC05 failed with %d", err); return; } k_msleep(sleep); - err = modbus_write_coil(RTU_IFACE, node, addr++, true); + err = modbus_write_coil(client_iface, node, addr++, true); if (err != 0) { LOG_ERR("FC05 failed with %d", err); return; } k_msleep(sleep); - err = modbus_write_coil(RTU_IFACE, node, addr++, true); + err = modbus_write_coil(client_iface, node, addr++, true); if (err != 0) { LOG_ERR("FC05 failed with %d", err); return; } k_msleep(sleep); - err = modbus_read_coils(RTU_IFACE, node, 0, coil, coil_qty); + err = modbus_read_coils(client_iface, node, 0, coil, coil_qty); if (err != 0) { LOG_ERR("FC01 failed with %d", err); return; @@ -96,7 +105,7 @@ void main(void) LOG_INF("Coils state 0x%02x", coil[0]); coil[0] = 0; - err = modbus_write_coils(RTU_IFACE, node, 0, coil, coil_qty); + err = modbus_write_coils(client_iface, node, 0, coil, coil_qty); if (err != 0) { LOG_ERR("FC15 failed with %d", err); return; diff --git a/samples/subsys/modbus/rtu_server/src/main.c b/samples/subsys/modbus/rtu_server/src/main.c index eb51f98b6d0..3ec9636d155 100644 --- a/samples/subsys/modbus/rtu_server/src/main.c +++ b/samples/subsys/modbus/rtu_server/src/main.c @@ -100,6 +100,18 @@ static struct modbus_user_callbacks mbs_cbs = { .holding_reg_wr = holding_reg_wr, }; +const static struct modbus_iface_param server_param = { + .mode = MODBUS_MODE_RTU, + .server = { + .user_cb = &mbs_cbs, + .unit_id = 1, + }, + .serial = { + .baud = 19200, + .parity = UART_CFG_PARITY_NONE, + }, +}; + static int init_modbus_server(void) { const uint32_t mb_rtu_br = 19200; @@ -113,8 +125,7 @@ static int init_modbus_server(void) return iface; } - return modbus_init_server(iface, 1, mb_rtu_br, UART_CFG_PARITY_NONE, - &mbs_cbs, false); + return modbus_init_server(iface, server_param); } void main(void) diff --git a/subsys/modbus/modbus_core.c b/subsys/modbus/modbus_core.c index 41afe3fe17e..ee3abb514e5 100644 --- a/subsys/modbus/modbus_core.c +++ b/subsys/modbus/modbus_core.c @@ -149,13 +149,18 @@ struct modbus_context *modbus_get_context(const uint8_t iface) return ctx; } -static struct modbus_context *mb_cfg_iface(const uint8_t iface, - const uint8_t unit_id, - const uint32_t baud, - const enum uart_config_parity parity, - const uint32_t rx_timeout, - const bool client, - const bool ascii_mode) +int modbus_iface_get_by_name(const char *iface_name) +{ + for (int i = 0; i < ARRAY_SIZE(mb_ctx_tbl); i++) { + if (strcmp(iface_name, mb_ctx_tbl[i].iface_name) == 0) { + return i; + } + } + + return -ENODEV; +} + +static struct modbus_context *modbus_init_iface(const uint8_t iface) { struct modbus_context *ctx; @@ -171,118 +176,129 @@ static struct modbus_context *mb_cfg_iface(const uint8_t iface, return NULL; } - if ((client == true) && - !IS_ENABLED(CONFIG_MODBUS_CLIENT)) { - LOG_ERR("Modbus client support is not enabled"); - ctx->client = false; - return NULL; - } - - ctx->rxwait_to = rx_timeout; - ctx->unit_id = unit_id; - ctx->client = client; - ctx->mbs_user_cb = NULL; k_mutex_init(&ctx->iface_lock); - k_sem_init(&ctx->client_wait_sem, 0, 1); k_work_init(&ctx->server_work, modbus_rx_handler); - if (IS_ENABLED(CONFIG_MODBUS_FC08_DIAGNOSTIC)) { - modbus_reset_stats(ctx); - } - - switch (ctx->mode) { - case MODBUS_MODE_RTU: - case MODBUS_MODE_ASCII: - if (IS_ENABLED(CONFIG_MODBUS_SERIAL) && - modbus_serial_init(ctx, baud, parity, ascii_mode) != 0) { - LOG_ERR("Failed to init MODBUS over serial line"); - return NULL; - } - break; - default: - LOG_ERR("Unknown MODBUS mode"); - return NULL; - } - - LOG_DBG("Modbus interface %s initialized", ctx->iface_name); - return ctx; } -int modbus_init_server(const uint8_t iface, const uint8_t unit_id, - const uint32_t baud, const enum uart_config_parity parity, - struct modbus_user_callbacks *const cb, - const bool ascii_mode) +int modbus_init_server(const int iface, struct modbus_iface_param param) { - struct modbus_context *ctx; + struct modbus_context *ctx = NULL; + int rc = 0; if (!IS_ENABLED(CONFIG_MODBUS_SERVER)) { LOG_ERR("Modbus server support is not enabled"); - return -ENOTSUP; + rc = -ENOTSUP; + goto init_server_error; } - if (cb == NULL) { + if (param.server.user_cb == NULL) { LOG_ERR("User callbacks should be available"); - return -EINVAL; + rc = -EINVAL; + goto init_server_error; } - ctx = mb_cfg_iface(iface, unit_id, baud, - parity, 0, false, ascii_mode); - + ctx = modbus_init_iface(iface); if (ctx == NULL) { - return -EINVAL; + rc = -EINVAL; + goto init_server_error; } - ctx->mbs_user_cb = cb; + switch (param.mode) { + case MODBUS_MODE_RTU: + case MODBUS_MODE_ASCII: + if (IS_ENABLED(CONFIG_MODBUS_SERIAL) && + modbus_serial_init(ctx, param) != 0) { + LOG_ERR("Failed to init MODBUS over serial line"); + rc = -EINVAL; + goto init_server_error; + } + break; + default: + LOG_ERR("Unknown MODBUS mode"); + rc = -ENOTSUP; + goto init_server_error; + } + + ctx->client = false; + ctx->unit_id = param.server.unit_id; + ctx->mbs_user_cb = param.server.user_cb; + if (IS_ENABLED(CONFIG_MODBUS_FC08_DIAGNOSTIC)) { + modbus_reset_stats(ctx); + } + + LOG_DBG("Modbus interface %s initialized", ctx->iface_name); return 0; -} -int modbus_iface_get_by_name(const char *iface_name) -{ - for (int i = 0; i < ARRAY_SIZE(mb_ctx_tbl); i++) { - if (strcmp(iface_name, mb_ctx_tbl[i].iface_name) == 0) { - return i; - } +init_server_error: + if (ctx != NULL) { + atomic_clear_bit(&ctx->state, MODBUS_STATE_CONFIGURED); } - return -ENODEV; + return rc; } -int modbus_init_client(const uint8_t iface, - const uint32_t baud, const enum uart_config_parity parity, - const uint32_t rx_timeout, - const bool ascii_mode) +int modbus_init_client(const int iface, struct modbus_iface_param param) { - struct modbus_context *ctx; + struct modbus_context *ctx = NULL; + int rc = 0; if (!IS_ENABLED(CONFIG_MODBUS_CLIENT)) { LOG_ERR("Modbus client support is not enabled"); - return -ENOTSUP; + rc = -ENOTSUP; + goto init_client_error; } - ctx = mb_cfg_iface(iface, 0, baud, - parity, rx_timeout, true, ascii_mode); - + ctx = modbus_init_iface(iface); if (ctx == NULL) { - return -EINVAL; + rc = -EINVAL; + goto init_client_error; } + switch (param.mode) { + case MODBUS_MODE_RTU: + case MODBUS_MODE_ASCII: + if (IS_ENABLED(CONFIG_MODBUS_SERIAL) && + modbus_serial_init(ctx, param) != 0) { + LOG_ERR("Failed to init MODBUS over serial line"); + rc = -EINVAL; + goto init_client_error; + } + break; + default: + LOG_ERR("Unknown MODBUS mode"); + rc = -ENOTSUP; + goto init_client_error; + } + + ctx->client = true; + ctx->unit_id = 0; + ctx->mbs_user_cb = NULL; + ctx->rxwait_to = param.rx_timeout; + return 0; + +init_client_error: + if (ctx != NULL) { + atomic_clear_bit(&ctx->state, MODBUS_STATE_CONFIGURED); + } + + return rc; } int modbus_disable(const uint8_t iface) { struct modbus_context *ctx; - if (iface >= ARRAY_SIZE(mb_ctx_tbl)) { - LOG_ERR("Interface %u not available", iface); + ctx = modbus_get_context(iface); + if (ctx == NULL) { + LOG_ERR("Interface %u not initialized", iface); return -EINVAL; } - ctx = &mb_ctx_tbl[iface]; - switch (ctx->mode) { case MODBUS_MODE_RTU: case MODBUS_MODE_ASCII: @@ -300,7 +316,7 @@ int modbus_disable(const uint8_t iface) ctx->mbs_user_cb = NULL; atomic_clear_bit(&ctx->state, MODBUS_STATE_CONFIGURED); - LOG_INF("Disable Modbus interface"); + LOG_INF("Modbus interface %u disabled", iface); return 0; } diff --git a/subsys/modbus/modbus_internal.h b/subsys/modbus/modbus_internal.h index ea89d4b3878..12a607c6cc1 100644 --- a/subsys/modbus/modbus_internal.h +++ b/subsys/modbus/modbus_internal.h @@ -87,11 +87,6 @@ struct mb_rtu_gpio_config { gpio_dt_flags_t flags; }; -enum modbus_mode { - MODBUS_MODE_RTU, - MODBUS_MODE_ASCII, -}; - struct modbus_serial_config { /* UART device name */ const char *dev_name; @@ -244,19 +239,12 @@ int modbus_serial_tx_adu(struct modbus_context *ctx); * @brief Initialize serial line support. * * @param ctx Modbus interface context - * @param baudrate Baudrate of the serial line - * @param parity UART's parity setting: - * UART_CFG_PARITY_NONE, - * UART_CFG_PARITY_EVEN, - * UART_CFG_PARITY_ODD - * @param ascii_mode Enable ASCII Transfer Mode + * @param param Configuration parameter of the interface * * @retval 0 If the function was successful. */ int modbus_serial_init(struct modbus_context *ctx, - uint32_t baudrate, - enum uart_config_parity parity, - const bool ascii_mode); + struct modbus_iface_param param); /** * @brief Disable serial line support. diff --git a/subsys/modbus/modbus_serial.c b/subsys/modbus/modbus_serial.c index a9eda812ef1..f713ec27e56 100644 --- a/subsys/modbus/modbus_serial.c +++ b/subsys/modbus/modbus_serial.c @@ -526,15 +526,22 @@ int modbus_serial_tx_adu(struct modbus_context *ctx) } int modbus_serial_init(struct modbus_context *ctx, - uint32_t baudrate, - enum uart_config_parity parity, - const bool ascii_mode) + struct modbus_iface_param param) { struct modbus_serial_config *cfg = ctx->cfg; const uint32_t if_delay_max = 3500000; const uint32_t numof_bits = 11; struct uart_config uart_cfg; + switch (param.mode) { + case MODBUS_MODE_RTU: + case MODBUS_MODE_ASCII: + ctx->mode = param.mode; + break; + default: + return -ENOTSUP; + } + cfg->dev = device_get_binding(cfg->dev_name); if (cfg->dev == NULL) { LOG_ERR("Failed to get UART device %s", @@ -542,7 +549,7 @@ int modbus_serial_init(struct modbus_context *ctx, return -ENODEV; } - uart_cfg.baudrate = baudrate, + uart_cfg.baudrate = param.serial.baud, uart_cfg.flow_ctrl = UART_CFG_FLOW_CTRL_NONE; if (ctx->mode == MODBUS_MODE_ASCII) { @@ -551,15 +558,15 @@ int modbus_serial_init(struct modbus_context *ctx, uart_cfg.data_bits = UART_CFG_DATA_BITS_8; } - switch (parity) { + switch (param.serial.parity) { case UART_CFG_PARITY_ODD: case UART_CFG_PARITY_EVEN: - uart_cfg.parity = parity; + uart_cfg.parity = param.serial.parity; uart_cfg.stop_bits = UART_CFG_STOP_BITS_1; break; case UART_CFG_PARITY_NONE: /* Use of no parity requires 2 stop bits */ - uart_cfg.parity = parity; + uart_cfg.parity = param.serial.parity; uart_cfg.stop_bits = UART_CFG_STOP_BITS_2; break; default: @@ -571,8 +578,9 @@ int modbus_serial_init(struct modbus_context *ctx, return -EINVAL; } - if (baudrate <= 38400) { - cfg->rtu_timeout = (numof_bits * if_delay_max) / baudrate; + if (param.serial.baud <= 38400) { + cfg->rtu_timeout = (numof_bits * if_delay_max) / + param.serial.baud; } else { cfg->rtu_timeout = (numof_bits * if_delay_max) / 38400; } @@ -583,12 +591,12 @@ int modbus_serial_init(struct modbus_context *ctx, cfg->uart_buf_ctr = 0; cfg->uart_buf_ptr = &cfg->uart_buf[0]; - uart_irq_callback_user_data_set(cfg->dev, uart_cb_handler, ctx); - modbus_serial_rx_on(ctx); - ctx->mode = ascii_mode ? MODBUS_MODE_ASCII : MODBUS_MODE_RTU; + uart_irq_callback_user_data_set(cfg->dev, uart_cb_handler, ctx); k_timer_init(&cfg->rtu_timer, rtu_tmr_handler, NULL); k_timer_user_data_set(&cfg->rtu_timer, ctx); + + modbus_serial_rx_on(ctx); LOG_INF("RTU timeout %u us", cfg->rtu_timeout); return 0; diff --git a/tests/subsys/modbus/src/test_modbus_client.c b/tests/subsys/modbus/src/test_modbus_client.c index 649f27dbba0..6f583dc6394 100644 --- a/tests/subsys/modbus/src/test_modbus_client.c +++ b/tests/subsys/modbus/src/test_modbus_client.c @@ -11,11 +11,12 @@ LOG_MODULE_REGISTER(mbc_test, LOG_LEVEL_INF); #ifdef CONFIG_MODBUS_CLIENT const static uint16_t fp_offset = MB_TEST_FP_OFFSET; -const static uint8_t iface = MB_TEST_IFACE_CLIENT; const static uint8_t node = MB_TEST_NODE_ADDR; const static uint16_t offset_oor = 32; const static uint16_t fp_offset_oor = fp_offset + offset_oor; +static uint8_t client_iface; + void test_coil_wr_rd(void) { const uint8_t coil_qty = 16; @@ -23,35 +24,35 @@ void test_coil_wr_rd(void) int err; for (uint16_t idx = 0; idx < coil_qty; idx++) { - err = modbus_write_coil(iface, node, idx, true); + err = modbus_write_coil(client_iface, node, idx, true); zassert_equal(err, 0, "FC05 request failed"); } - err = modbus_read_coils(iface, node, 0, coil, coil_qty); + err = modbus_read_coils(client_iface, node, 0, coil, coil_qty); zassert_equal(err, 0, "FC01 request failed"); zassert_equal(coil[0], 0xff, "FC05 verify coil 0-7 failed"); zassert_equal(coil[1], 0xff, "FC05 verify coil 8-15 failed"); for (uint16_t numof = 1; numof <= coil_qty; numof++) { - err = modbus_write_coils(iface, node, 0, coil, numof); + err = modbus_write_coils(client_iface, node, 0, coil, numof); zassert_equal(err, 0, "FC15 request failed"); } coil[0] = 0xaa; coil[1] = 0xbb; - err = modbus_write_coils(iface, node, 0, coil, coil_qty); + err = modbus_write_coils(client_iface, node, 0, coil, coil_qty); zassert_equal(err, 0, "FC15 request failed"); - err = modbus_read_coils(iface, node, 0, coil, coil_qty); + err = modbus_read_coils(client_iface, node, 0, coil, coil_qty); zassert_equal(err, 0, "FC01 request failed"); zassert_equal(coil[0], 0xaa, "FC15 verify coil 0-7 failed"); zassert_equal(coil[1], 0xbb, "FC15 verify coil 8-15 failed"); - err = modbus_write_coil(iface, node, offset_oor, true); + err = modbus_write_coil(client_iface, node, offset_oor, true); zassert_not_equal(err, 0, "FC05 out of range request not failed"); - err = modbus_write_coils(iface, node, offset_oor, coil, coil_qty); + err = modbus_write_coils(client_iface, node, offset_oor, coil, coil_qty); zassert_not_equal(err, 0, "FC15 out of range request not failed"); } @@ -61,16 +62,16 @@ void test_di_rd(void) uint8_t di[4] = {0}; int err; - err = modbus_read_dinputs(iface, node, 0, di, di_qty); + err = modbus_read_dinputs(client_iface, node, 0, di, di_qty); zassert_equal(err, 0, "FC02 request failed"); zassert_equal(di[0], 0xaa, "FC02 verify di 0-7 failed"); zassert_equal(di[1], 0xbb, "FC02 verify di 8-15 failed"); - err = modbus_read_dinputs(iface, node, 0, di, di_qty + 1); + err = modbus_read_dinputs(client_iface, node, 0, di, di_qty + 1); zassert_not_equal(err, 0, "FC02 out of range request not failed"); - err = modbus_read_dinputs(iface, node, offset_oor, di, di_qty); + err = modbus_read_dinputs(client_iface, node, offset_oor, di, di_qty); zassert_not_equal(err, 0, "FC02 out of range request not failed"); } @@ -79,15 +80,15 @@ void test_input_reg(void) uint16_t ir[8] = {0}; int err; - err = modbus_write_holding_reg(iface, node, 0, 0xcafe); + err = modbus_write_holding_reg(client_iface, node, 0, 0xcafe); zassert_equal(err, 0, "FC06 write request for FC04 failed"); - err = modbus_read_input_regs(iface, node, 0, ir, ARRAY_SIZE(ir)); + err = modbus_read_input_regs(client_iface, node, 0, ir, ARRAY_SIZE(ir)); zassert_equal(err, 0, "FC04 request failed"); zassert_equal(ir[0], 0xcafe, "FC04 verify failed"); - err = modbus_read_input_regs(iface, + err = modbus_read_input_regs(client_iface, node, offset_oor, ir, @@ -105,14 +106,14 @@ void test_holding_reg(void) /* Test FC06 | FC03 */ for (uint16_t idx = 0; idx < ARRAY_SIZE(hr_wr); idx++) { - err = modbus_write_holding_reg(iface, node, idx, hr_wr[idx]); + err = modbus_write_holding_reg(client_iface, node, idx, hr_wr[idx]); zassert_equal(err, 0, "FC06 write request failed"); } - err = modbus_write_holding_reg(iface, node, offset_oor, 0xcafe); + err = modbus_write_holding_reg(client_iface, node, offset_oor, 0xcafe); zassert_not_equal(err, 0, "FC06 out of range request not failed"); - err = modbus_read_holding_regs(iface, node, 0, + err = modbus_read_holding_regs(client_iface, node, 0, hr_rd, ARRAY_SIZE(hr_rd)); zassert_equal(err, 0, "FC03 read request failed"); @@ -120,7 +121,7 @@ void test_holding_reg(void) zassert_equal(memcmp(hr_wr, hr_rd, sizeof(hr_wr)), 0, "FC06 verify failed"); - err = modbus_read_holding_regs(iface, + err = modbus_read_holding_regs(client_iface, node, offset_oor, hr_rd, @@ -128,11 +129,11 @@ void test_holding_reg(void) zassert_not_equal(err, 0, "FC03 out of range request not failed"); /* Test FC16 | FC03 */ - err = modbus_write_holding_regs(iface, node, 0, + err = modbus_write_holding_regs(client_iface, node, 0, hr_wr, ARRAY_SIZE(hr_wr)); zassert_equal(err, 0, "FC16 write request failed"); - err = modbus_read_holding_regs(iface, node, 0, + err = modbus_read_holding_regs(client_iface, node, 0, hr_rd, ARRAY_SIZE(hr_rd)); zassert_equal(err, 0, "FC03 read request failed"); @@ -142,35 +143,35 @@ void test_holding_reg(void) /* Test FC16 | FC03 */ for (uint16_t idx = 0; idx < ARRAY_SIZE(fhr_wr); idx++) { - err = modbus_write_holding_regs_fp(iface, + err = modbus_write_holding_regs_fp(client_iface, node, fp_offset + idx, &fhr_wr[0], 1); zassert_equal(err, 0, "FC16 write request failed"); } - err = modbus_write_holding_regs_fp(iface, + err = modbus_write_holding_regs_fp(client_iface, node, fp_offset, fhr_wr, ARRAY_SIZE(fhr_wr)); zassert_equal(err, 0, "FC16 FP request failed"); - err = modbus_write_holding_regs_fp(iface, + err = modbus_write_holding_regs_fp(client_iface, node, fp_offset_oor, fhr_wr, ARRAY_SIZE(fhr_wr)); zassert_not_equal(err, 0, "FC16 FP out of range request not failed"); - err = modbus_read_holding_regs_fp(iface, + err = modbus_read_holding_regs_fp(client_iface, node, fp_offset_oor, fhr_wr, ARRAY_SIZE(fhr_wr)); zassert_not_equal(err, 0, "FC16 FP out of range request not failed"); - err = modbus_read_holding_regs_fp(iface, + err = modbus_read_holding_regs_fp(client_iface, node, fp_offset, fhr_rd, @@ -188,51 +189,81 @@ void test_diagnostic(void) int err; for (uint16_t sf = 0x0A; sf < 0x0F; sf++) { - err = modbus_request_diagnostic(iface, node, sf, 0, &data); + err = modbus_request_diagnostic(client_iface, node, sf, 0, &data); zassert_equal(err, 0, "FC08:0x%04x request failed", sf); } - err = modbus_request_diagnostic(iface, node, 0xFF, 0, &data); + err = modbus_request_diagnostic(client_iface, node, 0xFF, 0, &data); zassert_not_equal(err, 0, "FC08 not supported request not failed"); } +static struct modbus_iface_param client_param = { + .mode = MODBUS_MODE_RTU, + .rx_timeout = MB_TEST_RESPONSE_TO, + .serial = { + .baud = MB_TEST_BAUDRATE_LOW, + .parity = UART_CFG_PARITY_ODD, + }, +}; + void test_client_setup_low_none(void) { int err; + const char iface_name[] = {DT_PROP_OR(DT_INST(0, zephyr_modbus_serial), + label, "")}; - err = modbus_init_client(iface, MB_TEST_BAUDRATE_LOW, - UART_CFG_PARITY_NONE, - MB_TEST_RESPONSE_TO, false); + client_iface = modbus_iface_get_by_name(iface_name); + client_param.mode = MODBUS_MODE_RTU; + client_param.serial.baud = MB_TEST_BAUDRATE_LOW; + client_param.serial.parity = UART_CFG_PARITY_NONE; + + err = modbus_init_client(client_iface, client_param); zassert_equal(err, 0, "Failed to configure RTU client"); } void test_client_setup_low_odd(void) { int err; + const char iface_name[] = {DT_PROP_OR(DT_INST(0, zephyr_modbus_serial), + label, "")}; - err = modbus_init_client(iface, MB_TEST_BAUDRATE_LOW, - UART_CFG_PARITY_ODD, - MB_TEST_RESPONSE_TO, false); + client_iface = modbus_iface_get_by_name(iface_name); + client_param.mode = MODBUS_MODE_RTU; + client_param.serial.baud = MB_TEST_BAUDRATE_LOW; + client_param.serial.parity = UART_CFG_PARITY_ODD; + + err = modbus_init_client(client_iface, client_param); zassert_equal(err, 0, "Failed to configure RTU client"); } void test_client_setup_high_even(void) { int err; + const char iface_name[] = {DT_PROP_OR(DT_INST(0, zephyr_modbus_serial), + label, "")}; - err = modbus_init_client(iface, MB_TEST_BAUDRATE_HIGH, - UART_CFG_PARITY_EVEN, - MB_TEST_RESPONSE_TO, false); + client_iface = modbus_iface_get_by_name(iface_name); + client_param.mode = MODBUS_MODE_RTU; + client_param.serial.baud = MB_TEST_BAUDRATE_HIGH; + client_param.serial.parity = UART_CFG_PARITY_EVEN; + + err = modbus_init_client(client_iface, client_param); zassert_equal(err, 0, "Failed to configure RTU client"); } void test_client_setup_ascii(void) { int err; + const char iface_name[] = {DT_PROP_OR(DT_INST(0, zephyr_modbus_serial), + label, "")}; + + client_iface = modbus_iface_get_by_name(iface_name); + client_param.mode = MODBUS_MODE_ASCII; + client_param.serial.baud = MB_TEST_BAUDRATE_HIGH; + client_param.serial.parity = UART_CFG_PARITY_EVEN; + + err = modbus_init_client(client_iface, client_param); - err = modbus_init_client(iface, MB_TEST_BAUDRATE_HIGH, - UART_CFG_PARITY_EVEN, - MB_TEST_RESPONSE_TO, true); zassert_equal(err, 0, "Failed to configure RTU client"); } @@ -240,7 +271,7 @@ void test_client_disable(void) { int err; - err = modbus_disable(iface); + err = modbus_disable(client_iface); zassert_equal(err, 0, "Failed to disable RTU client"); } diff --git a/tests/subsys/modbus/src/test_modbus_server.c b/tests/subsys/modbus/src/test_modbus_server.c index 85f9784fe40..2e681d01693 100644 --- a/tests/subsys/modbus/src/test_modbus_server.c +++ b/tests/subsys/modbus/src/test_modbus_server.c @@ -14,6 +14,13 @@ static uint16_t coils; static uint16_t holding_reg[8]; static float holding_fp[4]; +uint8_t server_iface; + +uint8_t test_get_server_iface(void) +{ + return server_iface; +} + static int coil_rd(uint16_t addr, bool *state) { if (addr >= (sizeof(coils) * 8)) { @@ -164,15 +171,31 @@ static struct modbus_user_callbacks mbs_cbs = { .holding_reg_wr_fp = holding_reg_wr_fp, }; +static struct modbus_iface_param server_param = { + .mode = MODBUS_MODE_RTU, + .server = { + .user_cb = &mbs_cbs, + .unit_id = MB_TEST_NODE_ADDR, + }, + .serial = { + .baud = MB_TEST_BAUDRATE_LOW, + .parity = UART_CFG_PARITY_ODD, + }, +}; + void test_server_setup_low_odd(void) { int err; + const char iface_name[] = {DT_PROP_OR(DT_INST(1, zephyr_modbus_serial), + label, "")}; + + server_iface = modbus_iface_get_by_name(iface_name); + server_param.mode = MODBUS_MODE_RTU; + server_param.serial.baud = MB_TEST_BAUDRATE_LOW; + server_param.serial.parity = UART_CFG_PARITY_ODD; if (IS_ENABLED(CONFIG_MODBUS_SERVER)) { - err = modbus_init_server(MB_TEST_IFACE_SERVER, MB_TEST_NODE_ADDR, - MB_TEST_BAUDRATE_LOW, - UART_CFG_PARITY_ODD, - &mbs_cbs, false); + err = modbus_init_server(server_iface, server_param); zassert_equal(err, 0, "Failed to configure RTU server"); } else { ztest_test_skip(); @@ -182,12 +205,16 @@ void test_server_setup_low_odd(void) void test_server_setup_low_none(void) { int err; + const char iface_name[] = {DT_PROP_OR(DT_INST(1, zephyr_modbus_serial), + label, "")}; + + server_iface = modbus_iface_get_by_name(iface_name); + server_param.mode = MODBUS_MODE_RTU; + server_param.serial.baud = MB_TEST_BAUDRATE_LOW; + server_param.serial.parity = UART_CFG_PARITY_NONE; if (IS_ENABLED(CONFIG_MODBUS_SERVER)) { - err = modbus_init_server(MB_TEST_IFACE_SERVER, MB_TEST_NODE_ADDR, - MB_TEST_BAUDRATE_LOW, - UART_CFG_PARITY_NONE, - &mbs_cbs, false); + err = modbus_init_server(server_iface, server_param); zassert_equal(err, 0, "Failed to configure RTU server"); } else { ztest_test_skip(); @@ -197,12 +224,16 @@ void test_server_setup_low_none(void) void test_server_setup_high_even(void) { int err; + const char iface_name[] = {DT_PROP_OR(DT_INST(1, zephyr_modbus_serial), + label, "")}; + + server_iface = modbus_iface_get_by_name(iface_name); + server_param.mode = MODBUS_MODE_RTU; + server_param.serial.baud = MB_TEST_BAUDRATE_HIGH; + server_param.serial.parity = UART_CFG_PARITY_EVEN; if (IS_ENABLED(CONFIG_MODBUS_SERVER)) { - err = modbus_init_server(MB_TEST_IFACE_SERVER, MB_TEST_NODE_ADDR, - MB_TEST_BAUDRATE_HIGH, - UART_CFG_PARITY_EVEN, - &mbs_cbs, false); + err = modbus_init_server(server_iface, server_param); zassert_equal(err, 0, "Failed to configure RTU server"); } else { ztest_test_skip(); @@ -212,12 +243,16 @@ void test_server_setup_high_even(void) void test_server_setup_ascii(void) { int err; + const char iface_name[] = {DT_PROP_OR(DT_INST(1, zephyr_modbus_serial), + label, "")}; + + server_iface = modbus_iface_get_by_name(iface_name); + server_param.mode = MODBUS_MODE_ASCII; + server_param.serial.baud = MB_TEST_BAUDRATE_HIGH; + server_param.serial.parity = UART_CFG_PARITY_EVEN; if (IS_ENABLED(CONFIG_MODBUS_SERVER)) { - err = modbus_init_server(MB_TEST_IFACE_SERVER, MB_TEST_NODE_ADDR, - MB_TEST_BAUDRATE_HIGH, - UART_CFG_PARITY_EVEN, - &mbs_cbs, true); + err = modbus_init_server(server_iface, server_param); zassert_equal(err, 0, "Failed to configure RTU server"); } else { ztest_test_skip(); @@ -229,7 +264,7 @@ void test_server_disable(void) int err; if (IS_ENABLED(CONFIG_MODBUS_SERVER)) { - err = modbus_disable(MB_TEST_IFACE_SERVER); + err = modbus_disable(server_iface); zassert_equal(err, 0, "Failed to disable RTU server"); } else { ztest_test_skip();