feat(shell): Add commands to configure Modbus
- Implement a new 'modbus' command in the shell. - Add sub-commands 'set_baud', 'set_id', and 'show'. - Add validation for baud rate and slave ID inputs. - The new parameters are applied to the Modbus server at runtime, allowing for live reconfiguration of the communication settings. - The shell backend is set to RTT.
This commit is contained in:
parent
b836f9a2f4
commit
6a9e4773ea
|
|
@ -6,4 +6,4 @@ list(APPEND BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
|
|||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(slave_node)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
target_sources(app PRIVATE src/main.c src/shell_modbus.c)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/ {
|
||||
chosen {
|
||||
zephyr,console = &rtt;
|
||||
zephyr,shell-uart = &rtt; // If using shell
|
||||
zephyr,shell = &rtt;
|
||||
};
|
||||
|
||||
rtt: rtt {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ CONFIG_UART_CONSOLE=n
|
|||
CONFIG_RTT_CONSOLE=y
|
||||
CONFIG_USE_SEGGER_RTT=y
|
||||
|
||||
# Enable Shell
|
||||
CONFIG_SHELL=y
|
||||
CONFIG_SHELL_BACKEND_RTT=y
|
||||
|
||||
# Config modbus
|
||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
CONFIG_MODBUS=y
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
#include <zephyr/usb/usb_device.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
#include "modbus_bridge.h"
|
||||
|
||||
LOG_MODULE_REGISTER(mbs_sample, LOG_LEVEL_INF);
|
||||
|
||||
#define APP_VERSION_MAJOR 1
|
||||
|
|
@ -32,6 +34,20 @@ enum {
|
|||
|
||||
|
||||
static uint16_t watchdog_timeout_s;
|
||||
static int modbus_iface;
|
||||
|
||||
static struct modbus_iface_param server_param = {
|
||||
.mode = MODBUS_MODE_RTU,
|
||||
.server = {
|
||||
.user_cb = NULL, // Will be set later
|
||||
.unit_id = 1,
|
||||
},
|
||||
.serial = {
|
||||
.baud = 19200,
|
||||
.parity = UART_CFG_PARITY_NONE,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static int coil_rd(uint16_t addr, bool *state)
|
||||
{
|
||||
|
|
@ -112,33 +128,56 @@ static struct modbus_user_callbacks mbs_cbs = {
|
|||
.input_reg_rd = input_reg_rd,
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
#define MODBUS_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_modbus_serial)
|
||||
|
||||
int modbus_reconfigure(uint32_t baudrate, uint8_t unit_id)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_INF("Reconfiguring Modbus: baudrate=%u, id=%u", baudrate, unit_id);
|
||||
|
||||
err = modbus_disable(modbus_iface);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to disable Modbus: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
server_param.serial.baud = baudrate;
|
||||
server_param.server.unit_id = unit_id;
|
||||
|
||||
err = modbus_init_server(modbus_iface, server_param);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to re-init Modbus server: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t modbus_get_baudrate(void)
|
||||
{
|
||||
return server_param.serial.baud;
|
||||
}
|
||||
|
||||
uint8_t modbus_get_unit_id(void)
|
||||
{
|
||||
return server_param.server.unit_id;
|
||||
}
|
||||
|
||||
|
||||
static int init_modbus_server(void)
|
||||
{
|
||||
const char iface_name[] = {DEVICE_DT_NAME(MODBUS_NODE)};
|
||||
int iface;
|
||||
|
||||
iface = modbus_iface_get_by_name(iface_name);
|
||||
|
||||
if (iface < 0) {
|
||||
modbus_iface = modbus_iface_get_by_name(iface_name);
|
||||
if (modbus_iface < 0) {
|
||||
LOG_ERR("Failed to get iface index for %s", iface_name);
|
||||
return iface;
|
||||
return modbus_iface;
|
||||
}
|
||||
|
||||
return modbus_init_server(iface, server_param);
|
||||
server_param.server.user_cb = &mbs_cbs;
|
||||
|
||||
return modbus_init_server(modbus_iface, server_param);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
|
@ -154,4 +193,4 @@ int main(void)
|
|||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef MODBUS_BRIDGE_H
|
||||
#define MODBUS_BRIDGE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Reconfigures the Modbus server with new parameters.
|
||||
*
|
||||
* @param baudrate New baudrate.
|
||||
* @param unit_id New slave unit ID.
|
||||
* @return 0 on success, negative error code on failure.
|
||||
*/
|
||||
int modbus_reconfigure(uint32_t baudrate, uint8_t unit_id);
|
||||
|
||||
/**
|
||||
* @brief Gets the currently active Modbus baudrate.
|
||||
* @return The current baudrate.
|
||||
*/
|
||||
uint32_t modbus_get_baudrate(void);
|
||||
|
||||
/**
|
||||
* @brief Gets the currently active Modbus slave unit ID.
|
||||
* @return The current slave unit ID.
|
||||
*/
|
||||
uint8_t modbus_get_unit_id(void);
|
||||
|
||||
#endif // MODBUS_BRIDGE_H
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
#include <zephyr/shell/shell.h>
|
||||
#include <stdlib.h>
|
||||
#include "modbus_bridge.h"
|
||||
|
||||
static int cmd_modbus_set_baud(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
shell_error(sh, "Usage: set_baud <baudrate>");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint32_t new_baud = (uint32_t)strtoul(argv[1], NULL, 10);
|
||||
const uint32_t valid_baud_rates[] = {1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200};
|
||||
bool is_valid = false;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(valid_baud_rates); i++) {
|
||||
if (new_baud == valid_baud_rates[i]) {
|
||||
is_valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
char error_msg[128];
|
||||
int offset = snprintf(error_msg, sizeof(error_msg), "Invalid baudrate. Valid rates are: ");
|
||||
for (int i = 0; i < ARRAY_SIZE(valid_baud_rates); i++) {
|
||||
offset += snprintf(error_msg + offset, sizeof(error_msg) - offset, "%u ", valid_baud_rates[i]);
|
||||
}
|
||||
shell_error(sh, "%s", error_msg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (modbus_reconfigure(new_baud, modbus_get_unit_id()) != 0) {
|
||||
shell_error(sh, "Failed to apply new baudrate");
|
||||
} else {
|
||||
shell_print(sh, "Modbus baudrate set to: %u", new_baud);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_modbus_set_id(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
shell_error(sh, "Usage: set_id <slave_id>");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint32_t new_id = (uint32_t)strtoul(argv[1], NULL, 10);
|
||||
if (new_id == 0 || new_id > 247) {
|
||||
shell_error(sh, "Invalid slave ID: %s. Must be between 1 and 247.", argv[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (modbus_reconfigure(modbus_get_baudrate(), (uint8_t)new_id) != 0) {
|
||||
shell_error(sh, "Failed to apply new slave ID");
|
||||
} else {
|
||||
shell_print(sh, "Modbus slave ID set to: %u", (uint8_t)new_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_modbus_show(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
shell_print(sh, "Current Modbus Configuration:");
|
||||
shell_print(sh, " Baudrate: %u", modbus_get_baudrate());
|
||||
shell_print(sh, " Slave ID: %u", modbus_get_unit_id());
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_STATIC_SUBCMD_SET_CREATE(sub_modbus_cmds,
|
||||
SHELL_CMD(set_baud, NULL, "Set Modbus baudrate", cmd_modbus_set_baud),
|
||||
SHELL_CMD(set_id, NULL, "Set Modbus slave ID", cmd_modbus_set_id),
|
||||
SHELL_CMD(show, NULL, "Show current Modbus configuration", cmd_modbus_show),
|
||||
SHELL_SUBCMD_SET_END
|
||||
);
|
||||
|
||||
SHELL_CMD_REGISTER(modbus, &sub_modbus_cmds, "Modbus configuration", NULL);
|
||||
Loading…
Reference in New Issue