From 9b7159d5a49b9264d5241c593be7bf62d3278bf6 Mon Sep 17 00:00:00 2001 From: Eduard Iten Date: Tue, 8 Jul 2025 16:06:11 +0200 Subject: [PATCH] added formatting --- setup-format-hook.sh | 56 +++ software/.clang-format | 5 + software/.vscode/settings.json | 21 +- software/.vscode/tasks.json | 40 +- software/apps/firmware_node/CMakeLists.txt | 0 software/apps/firmware_node/README.md | 0 .../boards/flash_partitions_128kb.dtsi | 0 .../boards/weact_stm32g431_core.conf | 0 .../boards/weact_stm32g431_core.overlay | 0 .../weact_stm32g431_core_mcuboot.overlay | 0 software/apps/firmware_node/pm.yml | 0 software/apps/firmware_node/prj.conf | 0 software/apps/firmware_node/src/main.c | 0 software/apps/firmware_node/sysbuild.cmake | 0 software/apps/firmware_node/sysbuild.conf | 0 .../sysbuild/firmware_node.overlay | 0 .../apps/firmware_node/sysbuild/mcuboot.conf | 0 .../firmware_node/sysbuild/mcuboot.overlay | 0 .../boards/weact_stm32g431_core.overlay | 0 software/apps/gateway/src/main.c | 7 +- .../slave_node/.vscode/c_cpp_properties.json | 12 + software/apps/slave_node/VERSION | 5 + software/apps/slave_node/src/main.c | 42 +- software/include/lib/adc_sensor.h | 6 +- software/include/lib/fwu.h | 2 +- software/include/lib/modbus_server.h | 207 +++++----- software/include/lib/valve.h | 34 +- software/lib/adc_sensor/adc_sensor.c | 83 ++-- software/lib/fwu/fwu.c | 71 ++-- software/lib/modbus_server/modbus_server.c | 379 ++++++++---------- software/lib/shell_modbus/shell_modbus.c | 183 +++++---- software/lib/shell_system/shell_system.c | 11 +- software/lib/valve/valve.c | 136 ++++--- 33 files changed, 685 insertions(+), 615 deletions(-) create mode 100755 setup-format-hook.sh create mode 100644 software/.clang-format create mode 100644 software/apps/firmware_node/CMakeLists.txt create mode 100644 software/apps/firmware_node/README.md create mode 100644 software/apps/firmware_node/boards/flash_partitions_128kb.dtsi create mode 100644 software/apps/firmware_node/boards/weact_stm32g431_core.conf create mode 100644 software/apps/firmware_node/boards/weact_stm32g431_core.overlay create mode 100644 software/apps/firmware_node/boards/weact_stm32g431_core_mcuboot.overlay create mode 100644 software/apps/firmware_node/pm.yml create mode 100644 software/apps/firmware_node/prj.conf create mode 100644 software/apps/firmware_node/src/main.c create mode 100644 software/apps/firmware_node/sysbuild.cmake create mode 100644 software/apps/firmware_node/sysbuild.conf create mode 100644 software/apps/firmware_node/sysbuild/firmware_node.overlay create mode 100644 software/apps/firmware_node/sysbuild/mcuboot.conf create mode 100644 software/apps/firmware_node/sysbuild/mcuboot.overlay create mode 100644 software/apps/firmware_node/sysbuild/mcuboot/boards/weact_stm32g431_core.overlay create mode 100644 software/apps/slave_node/.vscode/c_cpp_properties.json create mode 100644 software/apps/slave_node/VERSION diff --git a/setup-format-hook.sh b/setup-format-hook.sh new file mode 100755 index 0000000..80ea847 --- /dev/null +++ b/setup-format-hook.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +# This script sets up a Git pre-commit hook to automatically format C/C++ files +# in the 'software/' subdirectory using clang-format. + +# Define the path for the pre-commit hook +HOOK_DIR=".git/hooks" +HOOK_FILE="$HOOK_DIR/pre-commit" + +# Create the hooks directory if it doesn't exist +mkdir -p "$HOOK_DIR" + +# Create the pre-commit hook script using a 'here document' +cat > "$HOOK_FILE" << 'EOF' +#!/bin/sh + +# --- Pre-commit hook for clang-format --- +# +# This hook formats staged C, C++, and Objective-C files in the 'software/' +# subdirectory before a commit is made. +# It automatically finds the .clang-format file in the software/ directory. +# + +# Directory to be formatted +TARGET_DIR="software/" + +# Use git diff to find staged files that are Added (A), Copied (C), or Modified (M). +# We filter for files only within the TARGET_DIR. +# The grep regex matches common C/C++ and Objective-C file extensions. +FILES_TO_FORMAT=$(git diff --cached --name-only --diff-filter=ACM "$TARGET_DIR" | grep -E '\.(c|h|cpp|hpp|cxx|hxx|cc|hh|m|mm)$') + +if [ -z "$FILES_TO_FORMAT" ]; then + # No relevant files to format, exit successfully. + exit 0 +fi + +echo "› Running clang-format on staged files in '$TARGET_DIR'..." + +# Run clang-format in-place on the identified files. +# clang-format will automatically find the .clang-format file in the software/ directory +# or any of its parent directories. +echo "$FILES_TO_FORMAT" | xargs clang-format -i + +# Since clang-format may have changed the files, we need to re-stage them. +echo "$FILES_TO_FORMAT" | xargs git add + +echo "› Formatting complete." + +exit 0 +EOF + +# Make the hook executable +chmod +x "$HOOK_FILE" + +echo "✅ Git pre-commit hook has been set up successfully." +echo " It will now automatically format files in the '$PWD/software' directory before each commit." diff --git a/software/.clang-format b/software/.clang-format new file mode 100644 index 0000000..bc7d8cc --- /dev/null +++ b/software/.clang-format @@ -0,0 +1,5 @@ +# .clang-format +BasedOnStyle: Google +#IndentWidth: 4 +#ColumnLimit: 100 +#AllowShortFunctionsOnASingleLine: None diff --git a/software/.vscode/settings.json b/software/.vscode/settings.json index 148d807..8d96b49 100644 --- a/software/.vscode/settings.json +++ b/software/.vscode/settings.json @@ -1,13 +1,12 @@ { - // Hush CMake - "cmake.configureOnOpen": false, - - // IntelliSense - "C_Cpp.default.compilerPath": "${userHome}/zephyr-sdk-0.17.1/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc.exe", - "C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json", - - // File Associations - "files.associations": { - "app_version.h": "c" - } + // Hush CMake + "cmake.configureOnOpen": false, + // IntelliSense + "C_Cpp.default.compilerPath": "${userHome}/zephyr-sdk-0.17.1/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc.exe", + "C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json", + // File Associations + "files.associations": { + "app_version.h": "c" + }, + "C_Cpp.clang_format_style": "file", } \ No newline at end of file diff --git a/software/.vscode/tasks.json b/software/.vscode/tasks.json index 89ed6b2..9aa5e19 100644 --- a/software/.vscode/tasks.json +++ b/software/.vscode/tasks.json @@ -2,32 +2,20 @@ "version": "2.0.0", "tasks": [ { - "label": "West Build", - "type": "shell", - "group": { - "kind": "build", - "isDefault": true - }, - "linux": { - "command": "${userHome}/zephyrproject/.venv/bin/west" - }, - "windows": { - "command": "${userHome}/zephyrproject/.venv/Scripts/west.exe" - }, - "osx": { - "command": "${userHome}/zephyrproject/.venv/bin/west" - }, - "args": [ - "build", - "-p", - "auto", - "-b", - "valve_node" - ], - "problemMatcher": [ - "$gcc" - ] - }, + "label": "Format All C/C++ Files", + "type": "shell", + "command": "find . -name \"*.c\" -o -name \"*.h\" | xargs clang-format -i", + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "reveal": "silent", + "clear": true, + "panel": "shared" + } + }, { "label": "West Configurable Build", "type": "shell", diff --git a/software/apps/firmware_node/CMakeLists.txt b/software/apps/firmware_node/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/README.md b/software/apps/firmware_node/README.md new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/boards/flash_partitions_128kb.dtsi b/software/apps/firmware_node/boards/flash_partitions_128kb.dtsi new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/boards/weact_stm32g431_core.conf b/software/apps/firmware_node/boards/weact_stm32g431_core.conf new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/boards/weact_stm32g431_core.overlay b/software/apps/firmware_node/boards/weact_stm32g431_core.overlay new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/boards/weact_stm32g431_core_mcuboot.overlay b/software/apps/firmware_node/boards/weact_stm32g431_core_mcuboot.overlay new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/pm.yml b/software/apps/firmware_node/pm.yml new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/prj.conf b/software/apps/firmware_node/prj.conf new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/src/main.c b/software/apps/firmware_node/src/main.c new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/sysbuild.cmake b/software/apps/firmware_node/sysbuild.cmake new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/sysbuild.conf b/software/apps/firmware_node/sysbuild.conf new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/sysbuild/firmware_node.overlay b/software/apps/firmware_node/sysbuild/firmware_node.overlay new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/sysbuild/mcuboot.conf b/software/apps/firmware_node/sysbuild/mcuboot.conf new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/sysbuild/mcuboot.overlay b/software/apps/firmware_node/sysbuild/mcuboot.overlay new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/firmware_node/sysbuild/mcuboot/boards/weact_stm32g431_core.overlay b/software/apps/firmware_node/sysbuild/mcuboot/boards/weact_stm32g431_core.overlay new file mode 100644 index 0000000..e69de29 diff --git a/software/apps/gateway/src/main.c b/software/apps/gateway/src/main.c index 1707ef4..38f2611 100644 --- a/software/apps/gateway/src/main.c +++ b/software/apps/gateway/src/main.c @@ -6,8 +6,7 @@ #include -int main(void) -{ - printk("Hello from Gateway!\n"); - return 0; +int main(void) { + printk("Hello from Gateway!\n"); + return 0; } diff --git a/software/apps/slave_node/.vscode/c_cpp_properties.json b/software/apps/slave_node/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..ac35bee --- /dev/null +++ b/software/apps/slave_node/.vscode/c_cpp_properties.json @@ -0,0 +1,12 @@ +{ + "configurations": [ + { + "name": "Linux", + "compileCommands": "${workspaceFolder}/build/compile_commands.json", + "cStandard": "c99", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-gcc-arm" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/software/apps/slave_node/VERSION b/software/apps/slave_node/VERSION new file mode 100644 index 0000000..2bdb1ca --- /dev/null +++ b/software/apps/slave_node/VERSION @@ -0,0 +1,5 @@ +VERSION_MAJOR = 0 +VERSION_MINOR = 0 +PATCHLEVEL = 1 +VERSION_TWEAK = 1 +EXTRAVERSION = devel \ No newline at end of file diff --git a/software/apps/slave_node/src/main.c b/software/apps/slave_node/src/main.c index 3191bec..d9d2e08 100644 --- a/software/apps/slave_node/src/main.c +++ b/software/apps/slave_node/src/main.c @@ -1,29 +1,31 @@ -#include -#include -#include +#include +#include #include #include -#include -#include +#include +#include +#include LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); -int main(void) -{ - LOG_INF("Starting Irrigation System Slave Node version %s (Build version %s)", APP_VERSION_STRING, STRINGIFY(APP_BUILD_VERSION)); +int main(void) { + int rc; + LOG_INF("Starting Irrigation System Slave Node version %s (Build version %s)", + APP_VERSION_STRING, STRINGIFY(APP_BUILD_VERSION)); - if (settings_subsys_init() || settings_load()) { - LOG_ERR("Settings initialization or loading failed"); - } + if (settings_subsys_init() || settings_load()) { + LOG_ERR("Settings initialization or loading failed"); + } - valve_init(); - fwu_init(); + valve_init(); + fwu_init(); - if (modbus_server_init()) { - LOG_ERR("Modbus RTU server initialization failed"); - return 0; - } - - LOG_INF("Irrigation System Slave Node started successfully"); - return 0; + rc = modbus_server_init(); + if (rc < 0) { + LOG_ERR("Modbus RTU server initialization failed"); + return 0; + } + + LOG_INF("Irrigation System Slave Node started successfully"); + return 0; } diff --git a/software/include/lib/adc_sensor.h b/software/include/lib/adc_sensor.h index 5bfff80..67e895b 100644 --- a/software/include/lib/adc_sensor.h +++ b/software/include/lib/adc_sensor.h @@ -18,7 +18,7 @@ * This function sets up the necessary ADC channels and configurations. * It should be called once before any other function in this library. * In simulated mode, it logs the simulated values. - * + * * @return 0 on success, or a negative error code on failure. */ int adc_sensor_init(void); @@ -28,7 +28,7 @@ int adc_sensor_init(void); * * This function reads the value from the corresponding ADC channel and converts * it to millivolts. - * + * * @return The supply voltage in millivolts (mV). */ uint16_t adc_sensor_get_voltage_mv(void); @@ -38,7 +38,7 @@ uint16_t adc_sensor_get_voltage_mv(void); * * This function reads the value from the motor driver's sense pin via ADC * and converts it to milliamps. This is used for end-stop detection. - * + * * @return The motor current in milliamps (mA). */ uint16_t adc_sensor_get_current_ma(void); diff --git a/software/include/lib/fwu.h b/software/include/lib/fwu.h index 673a962..8de4697 100644 --- a/software/include/lib/fwu.h +++ b/software/include/lib/fwu.h @@ -44,4 +44,4 @@ void fwu_handler(uint16_t addr, uint16_t reg); */ uint16_t fwu_get_last_chunk_crc(void); -#endif // FWU_H +#endif // FWU_H diff --git a/software/include/lib/modbus_server.h b/software/include/lib/modbus_server.h index d2091d4..f20016c 100644 --- a/software/include/lib/modbus_server.h +++ b/software/include/lib/modbus_server.h @@ -7,116 +7,120 @@ * @file modbus_server.h * @brief API for the Modbus server implementation. * - * This file defines the Modbus register map and provides functions to initialize - * and manage the Modbus server. + * This file defines the Modbus register map and provides functions to + * initialize and manage the Modbus server. */ /** * @brief Modbus Input Register Addresses (Read-Only). * @see docs/modbus-registers.de.md */ -enum -{ - /** - * @brief Kombiniertes Status-Register für das Ventil. - * High-Byte: Bewegung (0=Idle, 1=Öffnet, 2=Schliesst, 3=Fehler). - * Low-Byte: Zustand (0=Geschlossen, 1=Geöffnet). - */ - REG_INPUT_VALVE_STATE_MOVEMENT = 0x0000, - /** - * @brief Aktueller Motorstrom in Milliampere (mA). - */ - REG_INPUT_MOTOR_CURRENT_MA = 0x0001, - /** - * @brief Bitmaske der digitalen Eingänge. Bit 0: Eingang 1, Bit 1: Eingang 2. 1=Aktiv. - */ - REG_INPUT_DIGITAL_INPUTS_STATE = 0x0020, - /** - * @brief Event-Flags für Taster (Clear-on-Read). Bit 0: Taster 1 gedrückt. Bit 1: Taster 2 gedrückt. - */ - REG_INPUT_BUTTON_EVENTS = 0x0021, - /** - * @brief Firmware-Version, z.B. 0x0102 für v1.2. - */ - REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR = 0x00F0, - /** - * @brief Firmware-Version Patch-Level, z.B. 3 für v1.2.3. - */ - REG_INPUT_FIRMWARE_VERSION_PATCH = 0x00F1, - /** - * @brief Gerätestatus (0=OK, 1=Allgemeiner Fehler). - */ - REG_INPUT_DEVICE_STATUS = 0x00F2, - /** - * @brief Untere 16 Bit der Uptime in Sekunden. - */ - REG_INPUT_UPTIME_SECONDS_LOW = 0x00F3, - /** - * @brief Obere 16 Bit der Uptime in Sekunden. - */ - REG_INPUT_UPTIME_SECONDS_HIGH = 0x00F4, - /** - * @brief Aktuelle Versorgungsspannung in Millivolt (mV). - */ - REG_INPUT_SUPPLY_VOLTAGE_MV = 0x00F5, - /** - * @brief CRC16 des zuletzt im Puffer empfangenen Daten-Chunks für das Firmware-Update. - */ - REG_INPUT_FWU_LAST_CHUNK_CRC = 0x0100 +enum { + /** + * @brief Kombiniertes Status-Register für das Ventil. + * High-Byte: Bewegung (0=Idle, 1=Öffnet, 2=Schliesst, 3=Fehler). + * Low-Byte: Zustand (0=Geschlossen, 1=Geöffnet). + */ + REG_INPUT_VALVE_STATE_MOVEMENT = 0x0000, + /** + * @brief Aktueller Motorstrom in Milliampere (mA). + */ + REG_INPUT_MOTOR_CURRENT_MA = 0x0001, + /** + * @brief Bitmaske der digitalen Eingänge. Bit 0: Eingang 1, Bit 1: Eingang 2. + * 1=Aktiv. + */ + REG_INPUT_DIGITAL_INPUTS_STATE = 0x0020, + /** + * @brief Event-Flags für Taster (Clear-on-Read). Bit 0: Taster 1 gedrückt. + * Bit 1: Taster 2 gedrückt. + */ + REG_INPUT_BUTTON_EVENTS = 0x0021, + /** + * @brief Firmware-Version, z.B. 0x0102 für v1.2. + */ + REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR = 0x00F0, + /** + * @brief Firmware-Version Patch-Level, z.B. 3 für v1.2.3. + */ + REG_INPUT_FIRMWARE_VERSION_PATCH = 0x00F1, + /** + * @brief Gerätestatus (0=OK, 1=Allgemeiner Fehler). + */ + REG_INPUT_DEVICE_STATUS = 0x00F2, + /** + * @brief Untere 16 Bit der Uptime in Sekunden. + */ + REG_INPUT_UPTIME_SECONDS_LOW = 0x00F3, + /** + * @brief Obere 16 Bit der Uptime in Sekunden. + */ + REG_INPUT_UPTIME_SECONDS_HIGH = 0x00F4, + /** + * @brief Aktuelle Versorgungsspannung in Millivolt (mV). + */ + REG_INPUT_SUPPLY_VOLTAGE_MV = 0x00F5, + /** + * @brief CRC16 des zuletzt im Puffer empfangenen Daten-Chunks für das + * Firmware-Update. + */ + REG_INPUT_FWU_LAST_CHUNK_CRC = 0x0100 }; /** * @brief Modbus Holding Register Addresses (Read/Write). * @see docs/modbus-registers.de.md */ -enum -{ - /** - * @brief Ventilsteuerungsbefehl (1=Öffnen, 2=Schliessen, 0=Bewegung stoppen). - */ - REG_HOLDING_VALVE_COMMAND = 0x0000, - /** - * @brief Sicherheits-Timeout in Sekunden für den Öffnen-Vorgang. - */ - REG_HOLDING_MAX_OPENING_TIME_S = 0x0001, - /** - * @brief Sicherheits-Timeout in Sekunden für den Schliessen-Vorgang. - */ - REG_HOLDING_MAX_CLOSING_TIME_S = 0x0002, - /** - * @brief Bitmaske zum Lesen und Schreiben der digitalen Ausgänge. Bit 0: Ausgang 1, Bit 1: Ausgang 2. 1=AN, 0=AUS. - */ - REG_HOLDING_DIGITAL_OUTPUTS_STATE = 0x0010, - /** - * @brief Timeout des Fail-Safe-Watchdogs in Sekunden. 0=Deaktiviert. - */ - REG_HOLDING_WATCHDOG_TIMEOUT_S = 0x00F0, - /** - * @brief Schreiben von 1 startet das Gerät neu. - */ - REG_HOLDING_DEVICE_RESET = 0x00F1, - /** - * @brief Befehl für das Firmware-Update. - * 1: Verify Chunk - Slave schreibt den letzten Chunk ins Flash. - * 2: Finalize Update - Installation abschliessen und neu starten. - */ - REG_HOLDING_FWU_COMMAND = 0x0100, - /** - * @brief Untere 16 Bit des 32-Bit-Offsets für den nächsten Firmware-Update-Chunk. - */ - REG_HOLDING_FWU_CHUNK_OFFSET_LOW = 0x0101, - /** - * @brief Obere 16 Bit des 32-Bit-Offsets für den nächsten Firmware-Update-Chunk. - */ - REG_HOLDING_FWU_CHUNK_OFFSET_HIGH = 0x0102, - /** - * @brief Grösse des nächsten Firmware-Update-Chunks in Bytes (max. 256). - */ - REG_HOLDING_FWU_CHUNK_SIZE = 0x0103, - /** - * @brief Startadresse des 256-Byte-Puffers für Firmware-Update-Daten. - */ - REG_HOLDING_FWU_DATA_BUFFER = 0x0180, +enum { + /** + * @brief Ventilsteuerungsbefehl (1=Öffnen, 2=Schliessen, 0=Bewegung stoppen). + */ + REG_HOLDING_VALVE_COMMAND = 0x0000, + /** + * @brief Sicherheits-Timeout in Sekunden für den Öffnen-Vorgang. + */ + REG_HOLDING_MAX_OPENING_TIME_S = 0x0001, + /** + * @brief Sicherheits-Timeout in Sekunden für den Schliessen-Vorgang. + */ + REG_HOLDING_MAX_CLOSING_TIME_S = 0x0002, + /** + * @brief Bitmaske zum Lesen und Schreiben der digitalen Ausgänge. Bit 0: + * Ausgang 1, Bit 1: Ausgang 2. 1=AN, 0=AUS. + */ + REG_HOLDING_DIGITAL_OUTPUTS_STATE = 0x0010, + /** + * @brief Timeout des Fail-Safe-Watchdogs in Sekunden. 0=Deaktiviert. + */ + REG_HOLDING_WATCHDOG_TIMEOUT_S = 0x00F0, + /** + * @brief Schreiben von 1 startet das Gerät neu. + */ + REG_HOLDING_DEVICE_RESET = 0x00F1, + /** + * @brief Befehl für das Firmware-Update. + * 1: Verify Chunk - Slave schreibt den letzten Chunk ins Flash. + * 2: Finalize Update - Installation abschliessen und neu starten. + */ + REG_HOLDING_FWU_COMMAND = 0x0100, + /** + * @brief Untere 16 Bit des 32-Bit-Offsets für den nächsten + * Firmware-Update-Chunk. + */ + REG_HOLDING_FWU_CHUNK_OFFSET_LOW = 0x0101, + /** + * @brief Obere 16 Bit des 32-Bit-Offsets für den nächsten + * Firmware-Update-Chunk. + */ + REG_HOLDING_FWU_CHUNK_OFFSET_HIGH = 0x0102, + /** + * @brief Grösse des nächsten Firmware-Update-Chunks in Bytes (max. 256). + */ + REG_HOLDING_FWU_CHUNK_SIZE = 0x0103, + /** + * @brief Startadresse des 256-Byte-Puffers für Firmware-Update-Daten. + */ + REG_HOLDING_FWU_DATA_BUFFER = 0x0180, }; /** @@ -137,8 +141,9 @@ int modbus_server_init(void); * * @param baudrate The new baudrate to set. * @param unit_id The new Modbus unit ID (slave address). - * @return 0 on success, or a negative error code if immediate reconfiguration fails. - * Returns 0 even on failure if settings could be saved for the next boot. + * @return 0 on success, or a negative error code if immediate reconfiguration + * fails. Returns 0 even on failure if settings could be saved for the next + * boot. */ int modbus_reconfigure(uint32_t baudrate, uint8_t unit_id); @@ -156,4 +161,4 @@ uint32_t modbus_get_baudrate(void); */ uint8_t modbus_get_unit_id(void); -#endif // MODBUS_SERVER_H +#endif // MODBUS_SERVER_H diff --git a/software/include/lib/valve.h b/software/include/lib/valve.h index 17f6b56..9808355 100644 --- a/software/include/lib/valve.h +++ b/software/include/lib/valve.h @@ -8,39 +8,41 @@ * @file valve.h * @brief API for controlling the motorized valve. * - * This library provides functions to initialize, open, close, and stop the valve. - * It also allows getting the valve's state and movement status, and configuring - * the maximum opening and closing times. + * This library provides functions to initialize, open, close, and stop the + * valve. It also allows getting the valve's state and movement status, and + * configuring the maximum opening and closing times. */ /** * @brief Defines the GPIO pins used for the valve controller. */ struct valve_gpios { - const struct gpio_dt_spec in0; /**< Control input 0 for the VND7050AJ driver. */ - const struct gpio_dt_spec in1; /**< Control input 1 for the VND7050AJ driver. */ - const struct gpio_dt_spec rst; /**< Reset pin for the VND7050AJ driver. */ - const struct gpio_dt_spec sen; /**< Sense (current measurement) pin. */ - const struct gpio_dt_spec s0; /**< S0 select pin. */ - const struct gpio_dt_spec s1; /**< S1 select pin. */ + const struct gpio_dt_spec + in0; /**< Control input 0 for the VND7050AJ driver. */ + const struct gpio_dt_spec + in1; /**< Control input 1 for the VND7050AJ driver. */ + const struct gpio_dt_spec rst; /**< Reset pin for the VND7050AJ driver. */ + const struct gpio_dt_spec sen; /**< Sense (current measurement) pin. */ + const struct gpio_dt_spec s0; /**< S0 select pin. */ + const struct gpio_dt_spec s1; /**< S1 select pin. */ }; /** * @brief Represents the static state of the valve (open or closed). */ enum valve_state { - VALVE_STATE_CLOSED, /**< The valve is fully closed. */ - VALVE_STATE_OPEN, /**< The valve is fully open. */ + VALVE_STATE_CLOSED, /**< The valve is fully closed. */ + VALVE_STATE_OPEN, /**< The valve is fully open. */ }; /** * @brief Represents the dynamic movement status of the valve. */ enum valve_movement { - VALVE_MOVEMENT_IDLE, /**< The valve is not moving. */ - VALVE_MOVEMENT_OPENING, /**< The valve is currently opening. */ - VALVE_MOVEMENT_CLOSING, /**< The valve is currently closing. */ - VALVE_MOVEMENT_ERROR /**< An error occurred during movement. */ + VALVE_MOVEMENT_IDLE, /**< The valve is not moving. */ + VALVE_MOVEMENT_OPENING, /**< The valve is currently opening. */ + VALVE_MOVEMENT_CLOSING, /**< The valve is currently closing. */ + VALVE_MOVEMENT_ERROR /**< An error occurred during movement. */ }; /** @@ -118,4 +120,4 @@ uint16_t valve_get_max_open_time(void); */ uint16_t valve_get_max_close_time(void); -#endif // VALVE_H +#endif // VALVE_H diff --git a/software/lib/adc_sensor/adc_sensor.c b/software/lib/adc_sensor/adc_sensor.c index 48e8c39..6ec6104 100644 --- a/software/lib/adc_sensor/adc_sensor.c +++ b/software/lib/adc_sensor/adc_sensor.c @@ -2,14 +2,14 @@ * @file adc_sensor.c * @brief Implementation of the ADC sensor library. * - * This file contains the implementation for initializing and reading from ADC sensors. - * It currently provides simulated values for voltage and current, with placeholders - * for real hardware ADC implementation. + * This file contains the implementation for initializing and reading from ADC + * sensors. It currently provides simulated values for voltage and current, with + * placeholders for real hardware ADC implementation. */ +#include #include #include -#include LOG_MODULE_REGISTER(adc_sensor, LOG_LEVEL_INF); @@ -17,54 +17,53 @@ LOG_MODULE_REGISTER(adc_sensor, LOG_LEVEL_INF); #define SIMULATED_VOLTAGE_MV 12000 #define SIMULATED_CURRENT_MA 45 -static bool initialized = false; // Flag to indicate if the ADC sensor is initialized +static bool initialized = + false; // Flag to indicate if the ADC sensor is initialized -int adc_sensor_init(void) -{ - if (initialized) { - return 0; - } - -#ifdef CONFIG_ADC_SENSOR_SIMULATED - LOG_INF("ADC sensor initialized (simulated mode)"); - LOG_INF("Simulated values: %dmV, %dmA", SIMULATED_VOLTAGE_MV, SIMULATED_CURRENT_MA); -#else - // TODO: Initialize real ADC hardware - LOG_INF("ADC sensor initialized (real ADC mode - not yet implemented)"); -#endif - - initialized = true; +int adc_sensor_init(void) { + if (initialized) { return 0; -} - -uint16_t adc_sensor_get_voltage_mv(void) -{ - if (!initialized) { - LOG_WRN("ADC sensor not initialized, calling adc_sensor_init()"); - adc_sensor_init(); - } + } #ifdef CONFIG_ADC_SENSOR_SIMULATED - return SIMULATED_VOLTAGE_MV; + LOG_INF("ADC sensor initialized (simulated mode)"); + LOG_INF("Simulated values: %dmV, %dmA", SIMULATED_VOLTAGE_MV, + SIMULATED_CURRENT_MA); #else - // TODO: Read real ADC value for voltage - // For now return simulated value - return SIMULATED_VOLTAGE_MV; + // TODO: Initialize real ADC hardware + LOG_INF("ADC sensor initialized (real ADC mode - not yet implemented)"); +#endif + + initialized = true; + return 0; +} + +uint16_t adc_sensor_get_voltage_mv(void) { + if (!initialized) { + LOG_WRN("ADC sensor not initialized, calling adc_sensor_init()"); + adc_sensor_init(); + } + +#ifdef CONFIG_ADC_SENSOR_SIMULATED + return SIMULATED_VOLTAGE_MV; +#else + // TODO: Read real ADC value for voltage + // For now return simulated value + return SIMULATED_VOLTAGE_MV; #endif } -uint16_t adc_sensor_get_current_ma(void) -{ - if (!initialized) { - LOG_WRN("ADC sensor not initialized, calling adc_sensor_init()"); - adc_sensor_init(); - } +uint16_t adc_sensor_get_current_ma(void) { + if (!initialized) { + LOG_WRN("ADC sensor not initialized, calling adc_sensor_init()"); + adc_sensor_init(); + } #ifdef CONFIG_ADC_SENSOR_SIMULATED - return SIMULATED_CURRENT_MA; + return SIMULATED_CURRENT_MA; #else - // TODO: Read real ADC value for current - // For now return simulated value - return SIMULATED_CURRENT_MA; + // TODO: Read real ADC value for current + // For now return simulated value + return SIMULATED_CURRENT_MA; #endif } diff --git a/software/lib/fwu/fwu.c b/software/lib/fwu/fwu.c index fd7d7e4..e04196a 100644 --- a/software/lib/fwu/fwu.c +++ b/software/lib/fwu/fwu.c @@ -8,48 +8,51 @@ * the update process. The actual writing to flash is simulated. */ -#include -#include -#include -#include #include +#include +#include +#include +#include LOG_MODULE_REGISTER(fwu, LOG_LEVEL_INF); #define FWU_BUFFER_SIZE 256 -static uint8_t fwu_buffer[FWU_BUFFER_SIZE]; // Buffer to store incoming firmware data chunks -static uint32_t fwu_chunk_offset = 0; // Offset for the current firmware chunk in the overall image -static uint16_t fwu_chunk_size = 0; // Size of the current firmware chunk -static uint16_t fwu_last_chunk_crc = 0; // CRC16 of the last received firmware chunk +static uint8_t fwu_buffer[FWU_BUFFER_SIZE]; // Buffer to store incoming + // firmware data chunks +static uint32_t fwu_chunk_offset = + 0; // Offset for the current firmware chunk in the overall image +static uint16_t fwu_chunk_size = 0; // Size of the current firmware chunk +static uint16_t fwu_last_chunk_crc = + 0; // CRC16 of the last received firmware chunk void fwu_init(void) {} -void fwu_handler(uint16_t addr, uint16_t reg) -{ - // This is a simplified handler. In a real scenario, you would have a proper mapping - // between register addresses and actions. - if (addr == 0x0100) { // FWU_COMMAND - if (reg == 1) { LOG_INF("FWU: Chunk at offset %u (size %u) verified.", fwu_chunk_offset, fwu_chunk_size); } - else if (reg == 2) { LOG_INF("FWU: Finalize command received. Rebooting (simulated)."); } - } else if (addr == 0x0101) { // FWU_CHUNK_OFFSET_LOW - fwu_chunk_offset = (fwu_chunk_offset & 0xFFFF0000) | reg; - } else if (addr == 0x0102) { // FWU_CHUNK_OFFSET_HIGH - fwu_chunk_offset = (fwu_chunk_offset & 0x0000FFFF) | ((uint32_t)reg << 16); - } else if (addr == 0x0103) { // FWU_CHUNK_SIZE - fwu_chunk_size = (reg > FWU_BUFFER_SIZE) ? FWU_BUFFER_SIZE : reg; - } else if (addr >= 0x0180 && addr < (0x0180 + (FWU_BUFFER_SIZE / 2))) { - uint16_t index = (addr - 0x0180) * 2; - if (index < sizeof(fwu_buffer)) { - sys_put_be16(reg, &fwu_buffer[index]); - if (index + 2 >= fwu_chunk_size) { - fwu_last_chunk_crc = crc16_ccitt(0xffff, fwu_buffer, fwu_chunk_size); - LOG_INF("FWU: Chunk received, CRC is 0x%04X", fwu_last_chunk_crc); - } - } +void fwu_handler(uint16_t addr, uint16_t reg) { + // This is a simplified handler. In a real scenario, you would have a proper + // mapping between register addresses and actions. + if (addr == 0x0100) { // FWU_COMMAND + if (reg == 1) { + LOG_INF("FWU: Chunk at offset %u (size %u) verified.", fwu_chunk_offset, + fwu_chunk_size); + } else if (reg == 2) { + LOG_INF("FWU: Finalize command received. Rebooting (simulated)."); } + } else if (addr == 0x0101) { // FWU_CHUNK_OFFSET_LOW + fwu_chunk_offset = (fwu_chunk_offset & 0xFFFF0000) | reg; + } else if (addr == 0x0102) { // FWU_CHUNK_OFFSET_HIGH + fwu_chunk_offset = (fwu_chunk_offset & 0x0000FFFF) | ((uint32_t)reg << 16); + } else if (addr == 0x0103) { // FWU_CHUNK_SIZE + fwu_chunk_size = (reg > FWU_BUFFER_SIZE) ? FWU_BUFFER_SIZE : reg; + } else if (addr >= 0x0180 && addr < (0x0180 + (FWU_BUFFER_SIZE / 2))) { + uint16_t index = (addr - 0x0180) * 2; + if (index < sizeof(fwu_buffer)) { + sys_put_be16(reg, &fwu_buffer[index]); + if (index + 2 >= fwu_chunk_size) { + fwu_last_chunk_crc = crc16_ccitt(0xffff, fwu_buffer, fwu_chunk_size); + LOG_INF("FWU: Chunk received, CRC is 0x%04X", fwu_last_chunk_crc); + } + } + } } -uint16_t fwu_get_last_chunk_crc(void) -{ - return fwu_last_chunk_crc; -} +uint16_t fwu_get_last_chunk_crc(void) { return fwu_last_chunk_crc; } diff --git a/software/lib/modbus_server/modbus_server.c b/software/lib/modbus_server/modbus_server.c index ca1fc5c..ab5e3f4 100644 --- a/software/lib/modbus_server/modbus_server.c +++ b/software/lib/modbus_server/modbus_server.c @@ -7,28 +7,27 @@ * libraries like valve control, ADC sensors, and firmware updates. */ -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include #include #include -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include #include LOG_MODULE_REGISTER(modbus_server, LOG_LEVEL_INF); static int modbus_iface; static struct modbus_iface_param server_param = { - .mode = MODBUS_MODE_RTU, - .server = {.user_cb = NULL, .unit_id = 1}, - .serial = {.baud = 19200, .parity = UART_CFG_PARITY_NONE}, + .mode = MODBUS_MODE_RTU, + .server = {.user_cb = NULL, .unit_id = 1}, + .serial = {.baud = 19200, .parity = UART_CFG_PARITY_NONE}, }; static uint16_t watchdog_timeout_s = 0; @@ -43,10 +42,9 @@ static struct k_timer watchdog_timer; * * @param timer_id Pointer to the timer instance. */ -static void watchdog_timer_handler(struct k_timer *timer_id) -{ - LOG_WRN("Modbus watchdog expired! Closing valve as a fail-safe."); - valve_close(); +static void watchdog_timer_handler(struct k_timer *timer_id) { + LOG_WRN("Modbus watchdog expired! Closing valve as a fail-safe."); + valve_close(); } /** @@ -55,12 +53,10 @@ static void watchdog_timer_handler(struct k_timer *timer_id) * This function should be called upon receiving any valid Modbus request * to prevent the watchdog from expiring. */ -static inline void reset_watchdog(void) -{ - if (watchdog_timeout_s > 0) - { - k_timer_start(&watchdog_timer, K_SECONDS(watchdog_timeout_s), K_NO_WAIT); - } +static inline void reset_watchdog(void) { + if (watchdog_timeout_s > 0) { + k_timer_start(&watchdog_timer, K_SECONDS(watchdog_timeout_s), K_NO_WAIT); + } } /** @@ -70,25 +66,23 @@ static inline void reset_watchdog(void) * @param reg Pointer to store the read value. * @return 0 on success. */ -static int holding_reg_rd(uint16_t addr, uint16_t *reg) -{ - reset_watchdog(); - switch (addr) - { - case REG_HOLDING_MAX_OPENING_TIME_S: - *reg = valve_get_max_open_time(); - break; - case REG_HOLDING_MAX_CLOSING_TIME_S: - *reg = valve_get_max_close_time(); - break; - case REG_HOLDING_WATCHDOG_TIMEOUT_S: - *reg = watchdog_timeout_s; - break; - default: - *reg = 0; - break; - } - return 0; +static int holding_reg_rd(uint16_t addr, uint16_t *reg) { + reset_watchdog(); + switch (addr) { + case REG_HOLDING_MAX_OPENING_TIME_S: + *reg = valve_get_max_open_time(); + break; + case REG_HOLDING_MAX_CLOSING_TIME_S: + *reg = valve_get_max_close_time(); + break; + case REG_HOLDING_WATCHDOG_TIMEOUT_S: + *reg = watchdog_timeout_s; + break; + default: + *reg = 0; + break; + } + return 0; } /** @@ -98,56 +92,45 @@ static int holding_reg_rd(uint16_t addr, uint16_t *reg) * @param reg Value to write. * @return 0 on success. */ -static int holding_reg_wr(uint16_t addr, uint16_t reg) -{ - reset_watchdog(); - switch (addr) - { - case REG_HOLDING_VALVE_COMMAND: - if (reg == 1) - { - valve_open(); - } - else if (reg == 2) - { - valve_close(); - } - else if (reg == 0) - { - valve_stop(); - } - break; - case REG_HOLDING_MAX_OPENING_TIME_S: - valve_set_max_open_time(reg); - break; - case REG_HOLDING_MAX_CLOSING_TIME_S: - valve_set_max_close_time(reg); - break; - case REG_HOLDING_WATCHDOG_TIMEOUT_S: - watchdog_timeout_s = reg; - if (watchdog_timeout_s > 0) - { - LOG_INF("Watchdog enabled with %u s timeout.", watchdog_timeout_s); - reset_watchdog(); - } - else - { - LOG_INF("Watchdog disabled."); - k_timer_stop(&watchdog_timer); - } - break; - case REG_HOLDING_DEVICE_RESET: - if (reg == 1) - { - LOG_WRN("Modbus reset command received. Rebooting..."); - sys_reboot(SYS_REBOOT_WARM); - } - break; - default: - fwu_handler(addr, reg); - break; - } - return 0; +static int holding_reg_wr(uint16_t addr, uint16_t reg) { + reset_watchdog(); + switch (addr) { + case REG_HOLDING_VALVE_COMMAND: + if (reg == 1) { + valve_open(); + } else if (reg == 2) { + valve_close(); + } else if (reg == 0) { + valve_stop(); + } + break; + case REG_HOLDING_MAX_OPENING_TIME_S: + valve_set_max_open_time(reg); + break; + case REG_HOLDING_MAX_CLOSING_TIME_S: + valve_set_max_close_time(reg); + break; + case REG_HOLDING_WATCHDOG_TIMEOUT_S: + watchdog_timeout_s = reg; + if (watchdog_timeout_s > 0) { + LOG_INF("Watchdog enabled with %u s timeout.", watchdog_timeout_s); + reset_watchdog(); + } else { + LOG_INF("Watchdog disabled."); + k_timer_stop(&watchdog_timer); + } + break; + case REG_HOLDING_DEVICE_RESET: + if (reg == 1) { + LOG_WRN("Modbus reset command received. Rebooting..."); + sys_reboot(SYS_REBOOT_WARM); + } + break; + default: + fwu_handler(addr, reg); + break; + } + return 0; } /** @@ -157,130 +140,124 @@ static int holding_reg_wr(uint16_t addr, uint16_t reg) * @param reg Pointer to store the read value. * @return 0 on success. */ -static int input_reg_rd(uint16_t addr, uint16_t *reg) -{ - reset_watchdog(); - uint32_t uptime_s = k_uptime_get_32() / 1000; - switch (addr) - { - case REG_INPUT_VALVE_STATE_MOVEMENT: - *reg = (valve_get_movement() << 8) | (valve_get_state() & 0xFF); - break; - case REG_INPUT_MOTOR_CURRENT_MA: - *reg = adc_sensor_get_current_ma(); - break; - case REG_INPUT_UPTIME_SECONDS_LOW: - *reg = (uint16_t)(uptime_s & 0xFFFF); - break; - case REG_INPUT_UPTIME_SECONDS_HIGH: - *reg = (uint16_t)(uptime_s >> 16); - break; - case REG_INPUT_SUPPLY_VOLTAGE_MV: - *reg = adc_sensor_get_voltage_mv(); - break; - case REG_INPUT_FWU_LAST_CHUNK_CRC: - *reg = fwu_get_last_chunk_crc(); - break; - case REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR: - *reg = (APP_VERSION_MAJOR << 8) | APP_VERSION_MINOR; - break; - case REG_INPUT_FIRMWARE_VERSION_PATCH: - *reg = APP_PATCHLEVEL; - break; - default: - *reg = 0; - break; - } - return 0; +static int input_reg_rd(uint16_t addr, uint16_t *reg) { + reset_watchdog(); + uint32_t uptime_s = k_uptime_get_32() / 1000; + switch (addr) { + case REG_INPUT_VALVE_STATE_MOVEMENT: + *reg = (valve_get_movement() << 8) | (valve_get_state() & 0xFF); + break; + case REG_INPUT_MOTOR_CURRENT_MA: + *reg = adc_sensor_get_current_ma(); + break; + case REG_INPUT_UPTIME_SECONDS_LOW: + *reg = (uint16_t)(uptime_s & 0xFFFF); + break; + case REG_INPUT_UPTIME_SECONDS_HIGH: + *reg = (uint16_t)(uptime_s >> 16); + break; + case REG_INPUT_SUPPLY_VOLTAGE_MV: + *reg = adc_sensor_get_voltage_mv(); + break; + case REG_INPUT_FWU_LAST_CHUNK_CRC: + *reg = fwu_get_last_chunk_crc(); + break; + case REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR: + *reg = (APP_VERSION_MAJOR << 8) | APP_VERSION_MINOR; + break; + case REG_INPUT_FIRMWARE_VERSION_PATCH: + *reg = APP_PATCHLEVEL; + break; + default: + *reg = 0; + break; + } + return 0; } -static struct modbus_user_callbacks mbs_cbs = { // Modbus server callback functions - .holding_reg_rd = holding_reg_rd, - .holding_reg_wr = holding_reg_wr, - .input_reg_rd = input_reg_rd, +static struct modbus_user_callbacks mbs_cbs = { + // Modbus server callback functions + .holding_reg_rd = holding_reg_rd, + .holding_reg_wr = holding_reg_wr, + .input_reg_rd = input_reg_rd, }; #define MODBUS_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_modbus_serial) -int modbus_server_init(void) -{ - k_timer_init(&watchdog_timer, watchdog_timer_handler, NULL); - - // Initialize ADC sensor - int ret = adc_sensor_init(); - if (ret < 0) { - LOG_ERR("Failed to initialize ADC sensor: %d", ret); - return ret; - } - - // Load saved settings - uint32_t saved_baudrate = 19200; - uint8_t saved_unit_id = 1; - settings_load_one("modbus/baudrate", &saved_baudrate, sizeof(saved_baudrate)); - settings_load_one("modbus/unit_id", &saved_unit_id, sizeof(saved_unit_id)); - - // Apply loaded settings - server_param.serial.baud = saved_baudrate; - server_param.server.unit_id = saved_unit_id; - - const char iface_name[] = {DEVICE_DT_NAME(MODBUS_NODE)}; +int modbus_server_init(void) { + k_timer_init(&watchdog_timer, watchdog_timer_handler, NULL); + + // Initialize ADC sensor + int ret = adc_sensor_init(); + if (ret < 0) { + LOG_ERR("Failed to initialize ADC sensor: %d", ret); + return ret; + } + + // Load saved settings + uint32_t saved_baudrate = 19200; + uint8_t saved_unit_id = 1; + settings_load_one("modbus/baudrate", &saved_baudrate, sizeof(saved_baudrate)); + settings_load_one("modbus/unit_id", &saved_unit_id, sizeof(saved_unit_id)); + + // Apply loaded settings + server_param.serial.baud = saved_baudrate; + server_param.server.unit_id = saved_unit_id; + + const char iface_name[] = {DEVICE_DT_NAME(MODBUS_NODE)}; #if DT_NODE_HAS_COMPAT(DT_PARENT(MODBUS_NODE), zephyr_cdc_acm_uart) - const struct device *const dev = DEVICE_DT_GET(DT_PARENT(MODBUS_NODE)); - uint32_t dtr = 0; + const struct device *const dev = DEVICE_DT_GET(DT_PARENT(MODBUS_NODE)); + uint32_t dtr = 0; - if (!device_is_ready(dev) || usb_enable(NULL)) - { - return 0; - } + if (!device_is_ready(dev) || usb_enable(NULL)) { + return 0; + } - while (!dtr) - { - uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr); - k_sleep(K_MSEC(100)); - } + while (!dtr) { + uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr); + k_sleep(K_MSEC(100)); + } - LOG_INF("Client connected to server on %s", dev->name); + LOG_INF("Client connected to server on %s", dev->name); #endif - modbus_iface = modbus_iface_get_by_name(iface_name); - if (modbus_iface < 0) - { - return modbus_iface; - } - server_param.server.user_cb = &mbs_cbs; - - LOG_INF("Starting Modbus server: baudrate=%u, unit_id=%u", saved_baudrate, saved_unit_id); - return modbus_init_server(modbus_iface, server_param); + modbus_iface = modbus_iface_get_by_name(iface_name); + if (modbus_iface < 0) { + return modbus_iface; + } + server_param.server.user_cb = &mbs_cbs; + + LOG_INF("Starting Modbus server: baudrate=%u, unit_id=%u", saved_baudrate, + saved_unit_id); + return modbus_init_server(modbus_iface, server_param); } -int modbus_reconfigure(uint32_t baudrate, uint8_t unit_id) -{ - // Update parameters - server_param.serial.baud = baudrate; - server_param.server.unit_id = unit_id; +int modbus_reconfigure(uint32_t baudrate, uint8_t unit_id) { + // Update parameters + server_param.serial.baud = baudrate; + server_param.server.unit_id = unit_id; - // Try to reinitialize - this should work for most cases - int ret = modbus_init_server(modbus_iface, server_param); + // Try to reinitialize - this should work for most cases + int ret = modbus_init_server(modbus_iface, server_param); - if (ret == 0) - { - settings_save_one("modbus/baudrate", &baudrate, sizeof(baudrate)); - settings_save_one("modbus/unit_id", &unit_id, sizeof(unit_id)); - LOG_INF("Modbus reconfigured: baudrate=%u, unit_id=%u", baudrate, unit_id); - } - else - { - LOG_ERR("Failed to reconfigure Modbus: %d", ret); - LOG_INF("Modbus reconfiguration requires restart to take effect"); - - // Save settings for next boot - settings_save_one("modbus/baudrate", &baudrate, sizeof(baudrate)); - settings_save_one("modbus/unit_id", &unit_id, sizeof(unit_id)); - - LOG_INF("Settings saved. Type 'reset' to restart the device and apply the change."); - return 0; // Return success since settings are saved - } + if (ret == 0) { + settings_save_one("modbus/baudrate", &baudrate, sizeof(baudrate)); + settings_save_one("modbus/unit_id", &unit_id, sizeof(unit_id)); + LOG_INF("Modbus reconfigured: baudrate=%u, unit_id=%u", baudrate, unit_id); + } else { + LOG_ERR("Failed to reconfigure Modbus: %d", ret); + LOG_INF("Modbus reconfiguration requires restart to take effect"); - return ret; + // Save settings for next boot + settings_save_one("modbus/baudrate", &baudrate, sizeof(baudrate)); + settings_save_one("modbus/unit_id", &unit_id, sizeof(unit_id)); + + LOG_INF( + "Settings saved. Type 'reset' to restart the device and apply the " + "change."); + return 0; // Return success since settings are saved + } + + return ret; } uint32_t modbus_get_baudrate(void) { return server_param.serial.baud; } diff --git a/software/lib/shell_modbus/shell_modbus.c b/software/lib/shell_modbus/shell_modbus.c index d377da3..78f0995 100644 --- a/software/lib/shell_modbus/shell_modbus.c +++ b/software/lib/shell_modbus/shell_modbus.c @@ -8,10 +8,10 @@ * storage. */ -#include -#include #include #include +#include +#include /** * @brief Shell command to set the Modbus baudrate. @@ -21,41 +21,44 @@ * @param argv Argument values. * @return 0 on success, -EINVAL on error. */ -static int cmd_modbus_set_baud(const struct shell *sh, size_t argc, char **argv) -{ - if (argc != 2) { - shell_error(sh, "Usage: set_baud "); - return -EINVAL; - } +static int cmd_modbus_set_baud(const struct shell *sh, size_t argc, + char **argv) { + if (argc != 2) { + shell_error(sh, "Usage: set_baud "); + 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; + 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; - } - } + 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 (!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 (and saved)", new_baud); - } + 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 (and saved)", new_baud); + } - return 0; + return 0; } /** @@ -66,27 +69,27 @@ static int cmd_modbus_set_baud(const struct shell *sh, size_t argc, char **argv) * @param argv Argument values. * @return 0 on success, -EINVAL on error. */ -static int cmd_modbus_set_id(const struct shell *sh, size_t argc, char **argv) -{ - if (argc != 2) { - shell_error(sh, "Usage: set_id "); - return -EINVAL; - } +static int cmd_modbus_set_id(const struct shell *sh, size_t argc, char **argv) { + if (argc != 2) { + shell_error(sh, "Usage: set_id "); + return -EINVAL; + } - uint32_t new_id_u32 = (uint32_t)strtoul(argv[1], NULL, 10); - if (new_id_u32 == 0 || new_id_u32 > 247) { - shell_error(sh, "Invalid slave ID: %s. Must be between 1 and 247.", argv[1]); - return -EINVAL; - } - uint8_t new_id = (uint8_t)new_id_u32; + uint32_t new_id_u32 = (uint32_t)strtoul(argv[1], NULL, 10); + if (new_id_u32 == 0 || new_id_u32 > 247) { + shell_error(sh, "Invalid slave ID: %s. Must be between 1 and 247.", + argv[1]); + return -EINVAL; + } + uint8_t new_id = (uint8_t)new_id_u32; - if (modbus_reconfigure(modbus_get_baudrate(), new_id) != 0) { - shell_error(sh, "Failed to apply new slave ID"); - } else { - shell_print(sh, "Modbus slave ID set to: %u (and saved)", new_id); - } + if (modbus_reconfigure(modbus_get_baudrate(), new_id) != 0) { + shell_error(sh, "Failed to apply new slave ID"); + } else { + shell_print(sh, "Modbus slave ID set to: %u (and saved)", new_id); + } - return 0; + return 0; } /** @@ -97,18 +100,18 @@ static int cmd_modbus_set_id(const struct shell *sh, size_t argc, char **argv) * @param argv Argument values. * @return 0 on success, -EINVAL on error. */ -static int cmd_valve_set_open_time(const struct shell *sh, size_t argc, char **argv) -{ - if (argc != 2) { - shell_error(sh, "Usage: set_open_time "); - return -EINVAL; - } +static int cmd_valve_set_open_time(const struct shell *sh, size_t argc, + char **argv) { + if (argc != 2) { + shell_error(sh, "Usage: set_open_time "); + return -EINVAL; + } - uint16_t seconds = (uint16_t)strtoul(argv[1], NULL, 10); - valve_set_max_open_time(seconds); - shell_print(sh, "Max opening time set to: %u seconds (and saved)", seconds); + uint16_t seconds = (uint16_t)strtoul(argv[1], NULL, 10); + valve_set_max_open_time(seconds); + shell_print(sh, "Max opening time set to: %u seconds (and saved)", seconds); - return 0; + return 0; } /** @@ -119,18 +122,18 @@ static int cmd_valve_set_open_time(const struct shell *sh, size_t argc, char **a * @param argv Argument values. * @return 0 on success, -EINVAL on error. */ -static int cmd_valve_set_close_time(const struct shell *sh, size_t argc, char **argv) -{ - if (argc != 2) { - shell_error(sh, "Usage: set_close_time "); - return -EINVAL; - } +static int cmd_valve_set_close_time(const struct shell *sh, size_t argc, + char **argv) { + if (argc != 2) { + shell_error(sh, "Usage: set_close_time "); + return -EINVAL; + } - uint16_t seconds = (uint16_t)strtoul(argv[1], NULL, 10); - valve_set_max_close_time(seconds); - shell_print(sh, "Max closing time set to: %u seconds (and saved)", seconds); + uint16_t seconds = (uint16_t)strtoul(argv[1], NULL, 10); + valve_set_max_close_time(seconds); + shell_print(sh, "Max closing time set to: %u seconds (and saved)", seconds); - return 0; + return 0; } /** @@ -141,29 +144,33 @@ static int cmd_valve_set_close_time(const struct shell *sh, size_t argc, char ** * @param argv Argument values. * @return 0 on success. */ -static int cmd_config_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()); - shell_print(sh, "Current Valve Configuration:"); - shell_print(sh, " Max Opening Time: %u s", valve_get_max_open_time()); - shell_print(sh, " Max Closing Time: %u s", valve_get_max_close_time()); - return 0; +static int cmd_config_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()); + shell_print(sh, "Current Valve Configuration:"); + shell_print(sh, " Max Opening Time: %u s", valve_get_max_open_time()); + shell_print(sh, " Max Closing Time: %u s", valve_get_max_close_time()); + 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_SUBCMD_SET_END -); + 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_SUBCMD_SET_END); SHELL_STATIC_SUBCMD_SET_CREATE(sub_valve_cmds, - SHELL_CMD(set_open_time, NULL, "Set max valve opening time", cmd_valve_set_open_time), - SHELL_CMD(set_close_time, NULL, "Set max valve closing time", cmd_valve_set_close_time), - SHELL_SUBCMD_SET_END -); + SHELL_CMD(set_open_time, NULL, + "Set max valve opening time", + cmd_valve_set_open_time), + SHELL_CMD(set_close_time, NULL, + "Set max valve closing time", + cmd_valve_set_close_time), + SHELL_SUBCMD_SET_END); SHELL_CMD_REGISTER(modbus, &sub_modbus_cmds, "Modbus configuration", NULL); SHELL_CMD_REGISTER(valve, &sub_valve_cmds, "Valve configuration", NULL); -SHELL_CMD_REGISTER(show_config, NULL, "Show all configurations", cmd_config_show); \ No newline at end of file +SHELL_CMD_REGISTER(show_config, NULL, "Show all configurations", + cmd_config_show); \ No newline at end of file diff --git a/software/lib/shell_system/shell_system.c b/software/lib/shell_system/shell_system.c index e339079..c55dbef 100644 --- a/software/lib/shell_system/shell_system.c +++ b/software/lib/shell_system/shell_system.c @@ -20,12 +20,11 @@ * @param argv Argument values. * @return 0 on success. */ -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; +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); diff --git a/software/lib/valve/valve.c b/software/lib/valve/valve.c index f281bb3..3b2e14f 100644 --- a/software/lib/valve/valve.c +++ b/software/lib/valve/valve.c @@ -7,12 +7,12 @@ * safety timeouts for opening and closing operations. */ -#include -#include -#include +#include #include #include -#include +#include +#include +#include LOG_MODULE_REGISTER(valve, LOG_LEVEL_INF); @@ -29,81 +29,93 @@ static enum valve_state current_state = VALVE_STATE_CLOSED; static enum valve_movement current_movement = VALVE_MOVEMENT_IDLE; static uint16_t max_opening_time_s = 60; static uint16_t max_closing_time_s = 60; -static struct k_work_delayable valve_work; // Work item for scheduling valve movement timeouts +static struct k_work_delayable + valve_work; // Work item for scheduling valve movement timeouts /** * @brief Work handler for valve movement timeouts. * * This function is executed when the valve's movement timer expires. * It stops the motor to prevent damage and updates the valve's state. - * + * * @param work Pointer to the k_work item. */ -static void valve_work_handler(struct k_work *work) -{ - gpio_pin_set_dt(&valve_gpios.in0, 0); +static void valve_work_handler(struct k_work *work) { + gpio_pin_set_dt(&valve_gpios.in0, 0); + gpio_pin_set_dt(&valve_gpios.in1, 0); + gpio_pin_set_dt(&valve_gpios.rst, 0); + + if (current_movement == VALVE_MOVEMENT_OPENING) { + LOG_INF("Valve finished opening"); + } else if (current_movement == VALVE_MOVEMENT_CLOSING) { + current_state = VALVE_STATE_CLOSED; + LOG_INF("Valve finished closing"); + } + current_movement = VALVE_MOVEMENT_IDLE; +} + +void valve_init(void) { + k_work_init_delayable(&valve_work, valve_work_handler); + settings_load_one("valve/max_open_time", &max_opening_time_s, + sizeof(max_opening_time_s)); + settings_load_one("valve/max_close_time", &max_closing_time_s, + sizeof(max_closing_time_s)); + + gpio_pin_configure_dt(&valve_gpios.in0, GPIO_OUTPUT_INACTIVE); + gpio_pin_configure_dt(&valve_gpios.in1, GPIO_OUTPUT_INACTIVE); + gpio_pin_configure_dt(&valve_gpios.rst, + GPIO_OUTPUT_ACTIVE); // Keep VND7050AJ out of reset + gpio_pin_configure_dt(&valve_gpios.sen, GPIO_OUTPUT_INACTIVE); + gpio_pin_configure_dt(&valve_gpios.s0, + GPIO_OUTPUT_INACTIVE); // S0 select pin - output + gpio_pin_configure_dt(&valve_gpios.s1, + GPIO_OUTPUT_INACTIVE); // S1 select pin - output + + LOG_INF("Valve initialized: max_open=%us, max_close=%us", max_opening_time_s, + max_closing_time_s); +} + +void valve_open(void) { + if (current_state == VALVE_STATE_CLOSED) { + gpio_pin_set_dt(&valve_gpios.rst, 1); gpio_pin_set_dt(&valve_gpios.in1, 0); - gpio_pin_set_dt(&valve_gpios.rst, 0); - - if (current_movement == VALVE_MOVEMENT_OPENING) { - LOG_INF("Valve finished opening"); - } else if (current_movement == VALVE_MOVEMENT_CLOSING) { - current_state = VALVE_STATE_CLOSED; - LOG_INF("Valve finished closing"); - } - current_movement = VALVE_MOVEMENT_IDLE; + gpio_pin_set_dt(&valve_gpios.in0, 1); + current_state = VALVE_STATE_OPEN; + current_movement = VALVE_MOVEMENT_OPENING; + k_work_schedule(&valve_work, K_MSEC(max_opening_time_s * 1000 * 0.9)); + } } -void valve_init(void) -{ - k_work_init_delayable(&valve_work, valve_work_handler); - settings_load_one("valve/max_open_time", &max_opening_time_s, sizeof(max_opening_time_s)); - settings_load_one("valve/max_close_time", &max_closing_time_s, sizeof(max_closing_time_s)); - - gpio_pin_configure_dt(&valve_gpios.in0, GPIO_OUTPUT_INACTIVE); - gpio_pin_configure_dt(&valve_gpios.in1, GPIO_OUTPUT_INACTIVE); - gpio_pin_configure_dt(&valve_gpios.rst, GPIO_OUTPUT_ACTIVE); // Keep VND7050AJ out of reset - gpio_pin_configure_dt(&valve_gpios.sen, GPIO_OUTPUT_INACTIVE); - gpio_pin_configure_dt(&valve_gpios.s0, GPIO_OUTPUT_INACTIVE); // S0 select pin - output - gpio_pin_configure_dt(&valve_gpios.s1, GPIO_OUTPUT_INACTIVE); // S1 select pin - output - - LOG_INF("Valve initialized: max_open=%us, max_close=%us", max_opening_time_s, max_closing_time_s); +void valve_close(void) { + if (current_state == VALVE_STATE_OPEN) { + gpio_pin_set_dt(&valve_gpios.rst, 1); + gpio_pin_set_dt(&valve_gpios.in0, 0); + gpio_pin_set_dt(&valve_gpios.in1, 1); + current_movement = VALVE_MOVEMENT_CLOSING; + k_work_schedule(&valve_work, K_MSEC(max_closing_time_s * 1000 * 0.9)); + } } -void valve_open(void) -{ - if (current_state == VALVE_STATE_CLOSED) { - gpio_pin_set_dt(&valve_gpios.rst, 1); - gpio_pin_set_dt(&valve_gpios.in1, 0); - gpio_pin_set_dt(&valve_gpios.in0, 1); - current_state = VALVE_STATE_OPEN; - current_movement = VALVE_MOVEMENT_OPENING; - k_work_schedule(&valve_work, K_MSEC(max_opening_time_s * 1000 * 0.9)); - } -} - -void valve_close(void) -{ - if (current_state == VALVE_STATE_OPEN) { - gpio_pin_set_dt(&valve_gpios.rst, 1); - gpio_pin_set_dt(&valve_gpios.in0, 0); - gpio_pin_set_dt(&valve_gpios.in1, 1); - current_movement = VALVE_MOVEMENT_CLOSING; - k_work_schedule(&valve_work, K_MSEC(max_closing_time_s * 1000 * 0.9)); - } -} - -void valve_stop(void) -{ - k_work_cancel_delayable(&valve_work); - current_movement = VALVE_MOVEMENT_IDLE; +void valve_stop(void) { + k_work_cancel_delayable(&valve_work); + current_movement = VALVE_MOVEMENT_IDLE; } enum valve_state valve_get_state(void) { return current_state; } enum valve_movement valve_get_movement(void) { return current_movement; } -uint16_t valve_get_motor_current(void) { return (current_movement != VALVE_MOVEMENT_IDLE) ? 150 : 10; } +uint16_t valve_get_motor_current(void) { + return (current_movement != VALVE_MOVEMENT_IDLE) ? 150 : 10; +} -void valve_set_max_open_time(uint16_t seconds) { max_opening_time_s = seconds; settings_save_one("valve/max_open_time", &max_opening_time_s, sizeof(max_opening_time_s)); } -void valve_set_max_close_time(uint16_t seconds) { max_closing_time_s = seconds; settings_save_one("valve/max_close_time", &max_closing_time_s, sizeof(max_closing_time_s)); } +void valve_set_max_open_time(uint16_t seconds) { + max_opening_time_s = seconds; + settings_save_one("valve/max_open_time", &max_opening_time_s, + sizeof(max_opening_time_s)); +} +void valve_set_max_close_time(uint16_t seconds) { + max_closing_time_s = seconds; + settings_save_one("valve/max_close_time", &max_closing_time_s, + sizeof(max_closing_time_s)); +} uint16_t valve_get_max_open_time(void) { return max_opening_time_s; } uint16_t valve_get_max_close_time(void) { return max_closing_time_s; }