feat(settings): Implement persistent Modbus configuration
- Integrate the Zephyr Settings subsystem to persist Modbus parameters. - Use NVS (Non-Volatile Storage) as the backend with a dedicated flash partition. - Modbus baudrate and slave ID are now loaded at startup. - Changes made via the shell are saved to flash and survive a reboot. - Add a 'reset' command to the shell for easier testing. - Fix all compiler and devicetree warnings for a clean build.
This commit is contained in:
parent
6a9e4773ea
commit
8cab3eecc1
|
|
@ -6,4 +6,4 @@ list(APPEND BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
|
||||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
project(slave_node)
|
project(slave_node)
|
||||||
|
|
||||||
target_sources(app PRIVATE src/main.c src/shell_modbus.c)
|
target_sources(app PRIVATE src/main.c src/shell_modbus.c src/shell_system.c)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,console = &rtt;
|
zephyr,console = &rtt;
|
||||||
zephyr,shell = &rtt;
|
zephyr,shell = &rtt;
|
||||||
|
zephyr,settings-partition = &storage_partition;
|
||||||
};
|
};
|
||||||
|
|
||||||
rtt: rtt {
|
rtt: rtt {
|
||||||
|
|
@ -12,6 +13,27 @@
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&flash0 {
|
||||||
|
partitions {
|
||||||
|
compatible = "fixed-partitions";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
/* Application partition starts at the beginning of flash */
|
||||||
|
slot0_partition: partition@0 {
|
||||||
|
label = "image-0";
|
||||||
|
reg = <0x00000000 DT_SIZE_K(120)>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Use the last 8K for settings */
|
||||||
|
storage_partition: partition@1E000 {
|
||||||
|
label = "storage";
|
||||||
|
reg = <0x0001E000 DT_SIZE_K(8)>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
&usart1 {
|
&usart1 {
|
||||||
modbus0 {
|
modbus0 {
|
||||||
compatible = "zephyr,modbus-serial";
|
compatible = "zephyr,modbus-serial";
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,16 @@ CONFIG_USE_SEGGER_RTT=y
|
||||||
# Enable Shell
|
# Enable Shell
|
||||||
CONFIG_SHELL=y
|
CONFIG_SHELL=y
|
||||||
CONFIG_SHELL_BACKEND_RTT=y
|
CONFIG_SHELL_BACKEND_RTT=y
|
||||||
|
CONFIG_REBOOT=y
|
||||||
|
|
||||||
|
# Enable Settings Subsystem
|
||||||
|
CONFIG_SETTINGS=y
|
||||||
|
CONFIG_SETTINGS_NVS=y
|
||||||
|
CONFIG_NVS=y
|
||||||
|
CONFIG_FLASH=y
|
||||||
|
CONFIG_FLASH_MAP=y
|
||||||
|
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||||
|
CONFIG_SETTINGS_LOG_LEVEL_DBG=y
|
||||||
|
|
||||||
# Config modbus
|
# Config modbus
|
||||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <zephyr/drivers/gpio.h>
|
#include <zephyr/drivers/gpio.h>
|
||||||
#include <zephyr/modbus/modbus.h>
|
#include <zephyr/modbus/modbus.h>
|
||||||
#include <zephyr/usb/usb_device.h>
|
#include <zephyr/usb/usb_device.h>
|
||||||
|
#include <zephyr/settings/settings.h>
|
||||||
|
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
#include "modbus_bridge.h"
|
#include "modbus_bridge.h"
|
||||||
|
|
@ -164,6 +165,35 @@ uint8_t modbus_get_unit_id(void)
|
||||||
return server_param.server.unit_id;
|
return server_param.server.unit_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int settings_modbus_load(const char *name, size_t len,
|
||||||
|
settings_read_cb read_cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
const char *next;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (settings_name_steq(name, "baudrate", &next) && !next) {
|
||||||
|
rc = read_cb(cb_arg, &server_param.serial.baud, sizeof(server_param.serial.baud));
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
LOG_INF("Loaded modbus/baudrate: %u", server_param.serial.baud);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings_name_steq(name, "unit_id", &next) && !next) {
|
||||||
|
rc = read_cb(cb_arg, &server_param.server.unit_id, sizeof(server_param.server.unit_id));
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
LOG_INF("Loaded modbus/unit_id: %u", server_param.server.unit_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
SETTINGS_STATIC_HANDLER_DEFINE(modbus, "modbus", NULL, settings_modbus_load, NULL, NULL);
|
||||||
|
|
||||||
|
|
||||||
static int init_modbus_server(void)
|
static int init_modbus_server(void)
|
||||||
{
|
{
|
||||||
|
|
@ -183,6 +213,16 @@ static int init_modbus_server(void)
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
LOG_INF("Starting APP");
|
LOG_INF("Starting APP");
|
||||||
|
|
||||||
|
if (settings_subsys_init()) {
|
||||||
|
LOG_ERR("Failed to initialize settings subsystem");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings_load()) {
|
||||||
|
LOG_ERR("Failed to load settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (init_modbus_server()) {
|
if (init_modbus_server()) {
|
||||||
LOG_ERR("Modbus RTU server initialization failed");
|
LOG_ERR("Modbus RTU server initialization failed");
|
||||||
}
|
}
|
||||||
|
|
@ -193,4 +233,4 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <zephyr/shell/shell.h>
|
#include <zephyr/shell/shell.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <zephyr/settings/settings.h>
|
||||||
#include "modbus_bridge.h"
|
#include "modbus_bridge.h"
|
||||||
|
|
||||||
static int cmd_modbus_set_baud(const struct shell *sh, size_t argc, char **argv)
|
static int cmd_modbus_set_baud(const struct shell *sh, size_t argc, char **argv)
|
||||||
|
|
@ -32,10 +33,12 @@ static int cmd_modbus_set_baud(const struct shell *sh, size_t argc, char **argv)
|
||||||
|
|
||||||
if (modbus_reconfigure(new_baud, modbus_get_unit_id()) != 0) {
|
if (modbus_reconfigure(new_baud, modbus_get_unit_id()) != 0) {
|
||||||
shell_error(sh, "Failed to apply new baudrate");
|
shell_error(sh, "Failed to apply new baudrate");
|
||||||
} else {
|
return -1;
|
||||||
shell_print(sh, "Modbus baudrate set to: %u", new_baud);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settings_save_one("modbus/baudrate", &new_baud, sizeof(new_baud));
|
||||||
|
shell_print(sh, "Modbus baudrate set to: %u (and saved)", new_baud);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,18 +49,21 @@ static int cmd_modbus_set_id(const struct shell *sh, size_t argc, char **argv)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t new_id = (uint32_t)strtoul(argv[1], NULL, 10);
|
uint32_t new_id_u32 = (uint32_t)strtoul(argv[1], NULL, 10);
|
||||||
if (new_id == 0 || new_id > 247) {
|
if (new_id_u32 == 0 || new_id_u32 > 247) {
|
||||||
shell_error(sh, "Invalid slave ID: %s. Must be between 1 and 247.", argv[1]);
|
shell_error(sh, "Invalid slave ID: %s. Must be between 1 and 247.", argv[1]);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
uint8_t new_id = (uint8_t)new_id_u32;
|
||||||
|
|
||||||
if (modbus_reconfigure(modbus_get_baudrate(), (uint8_t)new_id) != 0) {
|
if (modbus_reconfigure(modbus_get_baudrate(), new_id) != 0) {
|
||||||
shell_error(sh, "Failed to apply new slave ID");
|
shell_error(sh, "Failed to apply new slave ID");
|
||||||
} else {
|
return -1;
|
||||||
shell_print(sh, "Modbus slave ID set to: %u", (uint8_t)new_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settings_save_one("modbus/unit_id", &new_id, sizeof(new_id));
|
||||||
|
shell_print(sh, "Modbus slave ID set to: %u (and saved)", new_id);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,4 +82,4 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_modbus_cmds,
|
||||||
SHELL_SUBCMD_SET_END
|
SHELL_SUBCMD_SET_END
|
||||||
);
|
);
|
||||||
|
|
||||||
SHELL_CMD_REGISTER(modbus, &sub_modbus_cmds, "Modbus configuration", NULL);
|
SHELL_CMD_REGISTER(modbus, &sub_modbus_cmds, "Modbus configuration", NULL);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include <zephyr/shell/shell.h>
|
||||||
|
#include <zephyr/sys/reboot.h>
|
||||||
|
|
||||||
|
static int cmd_reset(const struct shell *sh, size_t argc, char **argv)
|
||||||
|
{
|
||||||
|
shell_print(sh, "Rebooting system...");
|
||||||
|
k_sleep(K_MSEC(100)); // Allow the shell to print the message
|
||||||
|
sys_reboot(SYS_REBOOT_WARM);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHELL_CMD_REGISTER(reset, NULL, "Reboot the system", cmd_reset);
|
||||||
Loading…
Reference in New Issue