From 9d017f9f8da4f61219eb0d55ac394d8d639e076a Mon Sep 17 00:00:00 2001 From: Eduard Iten Date: Mon, 16 Jun 2025 13:09:27 +0200 Subject: [PATCH] Zwischenspeichern --- software/.vscode/settings.json | 16 +- .../boards/iten/valve_node/Kconfig.valve_node | 8 + .../boards/iten/valve_node/valve_node.dts | 10 +- software/lib/canbus.c | 140 +++++++++++++----- software/lib/canbus.h | 22 ++- software/lib/config.c | 62 ++++++++ software/lib/config.h | 11 ++ software/lib/settings.h | 17 --- software/test_canbus/CMakeLists.txt | 1 + software/test_canbus/prj.conf | 3 +- software/test_canbus/src/main.c | 32 +++- 11 files changed, 258 insertions(+), 64 deletions(-) create mode 100644 software/lib/config.c create mode 100644 software/lib/config.h delete mode 100644 software/lib/settings.h diff --git a/software/.vscode/settings.json b/software/.vscode/settings.json index 15b66f3..c595456 100644 --- a/software/.vscode/settings.json +++ b/software/.vscode/settings.json @@ -1,7 +1,4 @@ { - "nrf-connect.applications": [ - "${workspaceFolder}\\modbus_test" - ], "files.associations": { "log.h": "c", "modbus.h": "c", @@ -10,6 +7,15 @@ "string_view": "c", "canbus.h": "c", "kernel.h": "c", - "settings.h": "c" - } + "settings.h": "c", + "can.h": "c" + }, + "C_Cpp.default.compileCommands": [ + "build/compile_commands.json", + "../build/compile_commands.json" + ], + "cmake.sourceDirectory": "/home/edi/zephyrproject/projects/irrigation_system/software/test_canbus", + "nrf-connect.applications": [ + "${workspaceFolder}/test_canbus" + ], } \ No newline at end of file diff --git a/software/boards/iten/valve_node/Kconfig.valve_node b/software/boards/iten/valve_node/Kconfig.valve_node index a52f9b8..e155e80 100644 --- a/software/boards/iten/valve_node/Kconfig.valve_node +++ b/software/boards/iten/valve_node/Kconfig.valve_node @@ -13,6 +13,14 @@ config LOG_CAN_LEVEL int "Log level for CAN" default 3 range 0 7 + help + Set the log level for CAN messages. + 0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug, 5 = Trace, 6 = Debug2, 7 = Debug3 + +config LOG_SETTINGS_LEVEL + int "Log level for settings" + default 3 + range 0 7 help Set the log level for CAN messages. 0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug, 5 = Trace, 6 = Debug2, 7 = Debug3 \ No newline at end of file diff --git a/software/boards/iten/valve_node/valve_node.dts b/software/boards/iten/valve_node/valve_node.dts index bd39f4a..76ace88 100644 --- a/software/boards/iten/valve_node/valve_node.dts +++ b/software/boards/iten/valve_node/valve_node.dts @@ -13,12 +13,18 @@ model = "Iten engineering Valve Node"; compatible = "iten,valve-node", "st,stm32f103rb"; + can_loopback0: can_loopback0 { + status = "okay"; + compatible = "zephyr,can-loopback"; + }; + chosen { zephyr,console = &usart1; zephyr,shell-uart = &usart1; zephyr,sram = &sram0; zephyr,flash = &flash0; - zephyr,canbus = &can1; + //zephyr,canbus = &can1; + zephyr,canbus = &can_loopback0; }; leds: leds { @@ -174,7 +180,7 @@ pinctrl-0 = <&can_rx_pa11 &can_tx_pa12>; pinctrl-names = "default"; status= "okay"; - bus-speed = < 125000 >; + bus-speed = <500000>; }; &exti { diff --git a/software/lib/canbus.c b/software/lib/canbus.c index 55442a3..23d12c1 100644 --- a/software/lib/canbus.c +++ b/software/lib/canbus.c @@ -1,53 +1,80 @@ #include "canbus.h" #include #include -#include "settings.h" +#include +#include "config.h" + +int canbus_node_id = 1; // Default node ID for CAN bus const struct device *const can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); -K_THREAD_STACK_DEFINE(rx_thread_stack, RX_THREAD_STACK_SIZE); +struct k_thread rx_thread_data; -static uint8_t node_id = 12; // Default node ID +K_THREAD_STACK_DEFINE(rx_thread_stack, CANBUS_RX_THREAD_STACK_SIZE); +CAN_MSGQ_DEFINE(commands_msq, 2); LOG_MODULE_REGISTER(canbus, CONFIG_LOG_CAN_LEVEL); -static int canbus_set(const char *key, size_t len, settings_read_cb read_cb, void *cb_arg) +static void rx_thread(void *arg1, void *arg2, void *arg3) { - const char *next; - int rc; + ARG_UNUSED(arg1); + ARG_UNUSED(arg2); + ARG_UNUSED(arg3); + const struct can_filter filter = { + .flags = CAN_FILTER_IDE, + .id = (canbus_node_id << 8) | 0x00, // Standard ID with node ID in the first byte + .mask = CAN_STD_ID_MASK & 0xFFFFFF00U // Mask for standard ID, ignoring the last byte + }; - // Handle setting values for CAN bus configuration - LOG_DBG("Setting CAN bus configuration: key=%s, len=%zu", key, len); - if (settings_name_steq(key, "node_id", &next) && next != NULL) + struct can_frame frame; + int filter_id; + + filter_id = can_add_rx_filter_msgq(can_dev, &commands_msq, &filter); + LOG_DBG("RX thread started. Filter ID: %d, flags: 0x%02x, id: 0x%08x, mask: 0x%08x", filter_id, filter.flags, filter.id, filter.mask); + + while (1) { - if (len != sizeof(node_id)) + k_msgq_get(&commands_msq, &frame, K_FOREVER); + LOG_DBG("Received CAN frame: ID=0x%08x, DLC=%u, Flags=0x%02x", + frame.id, frame.dlc, frame.flags); + if (IS_ENABLED(CONFIG_CAN_ACCEPT_RTR) && (frame.flags & CAN_FRAME_RTR) != 0U) { - LOG_ERR("Invalid length for node_id setting: %zu", len); - return -EINVAL; // Invalid argument + continue; } - int rc = read_cb(cb_arg, &node_id, sizeof(node_id)); - if (rc < 0) + uint8_t target_node = (frame.id >> 8) & 0xFF; // Extract the target node from the ID + if (target_node != canbus_node_id) { - LOG_ERR("Failed to read node_id setting: %d", rc); - return rc; // Read error + LOG_WRN("Received frame for different node ID: %d, expected: %d", target_node, canbus_node_id); + continue; // Ignore frames not meant for this node } - LOG_DBG("Set CAN bus node ID to: %d", node_id); + uint8_t target_register = frame.id & 0xFF; // Extract the register address from the ID + + // Log the received frame details + LOG_DBG("Received CAN frame: ID=0x%08x, DLC=%u, Flags=0x%02x, Target Node=%d, Register Address=%d", + frame.id, frame.dlc, frame.flags, target_node, target_register); + LOG_HEXDUMP_DBG(frame.data, sizeof(frame.data) * sizeof(frame.data[0]), "Frame data:"); } - return 0; // Return 0 on success } -struct settings_handler canbus_settings_handler = { - .name = "canbus", - .h_set = canbus_set, // No settings set handler -}; +static void canbus_tx_callback(const struct device *dev, int error, void *user_data) +{ + ARG_UNUSED(dev); + ARG_UNUSED(user_data); + if (error != 0) + { + LOG_ERR("CAN transmission error: %d", error); + } + else + { + LOG_DBG("CAN message sent successfully"); + } +} int canbus_init(void) { + k_tid_t rx_tid; int rc; - settings_subsys_init(); - settings_register(&canbus_settings_handler); - settings_load(); rc = settings_get_val_len("canbus/node_id"); if (rc < 0) @@ -58,8 +85,8 @@ int canbus_init(void) else if (rc == 0) { - LOG_WRN("No CAN bus node id found in settings, using default default (%d)", node_id); - settings_save_one("canbus/node_id", &node_id, sizeof(node_id)); + LOG_WRN("No CAN bus node id found in settings, using default (%d)", canbus_node_id); + settings_save_one("canbus/node_id", &canbus_node_id, sizeof(canbus_node_id)); if (rc < 0) { LOG_ERR("Failed to save default CAN bus node id: %d", rc); @@ -68,13 +95,7 @@ int canbus_init(void) } else { - rc = settings_load_one("canbus/node_id", &node_id, sizeof(node_id)); - if (rc < 0) - { - LOG_ERR("Failed to load CAN bus node id from settings: %d", rc); - return rc; - } - LOG_DBG("Loaded CAN bus node id: %d", node_id); + LOG_DBG("CAN bus node ID found in settings: %d", canbus_node_id); } if (!device_is_ready(can_dev)) @@ -91,5 +112,54 @@ int canbus_init(void) return rc; } #endif + rc = can_start(can_dev); + if (rc != 0) { + printf("Error starting CAN controller [%d]", rc); + return 0; + } + LOG_DBG("CAN device %s is ready", can_dev->name); + + LOG_DBG("Trying to start rx thread"); + + // Create the RX thread for handling incoming CAN messages + rx_tid = k_thread_create(&rx_thread_data, rx_thread_stack, + K_THREAD_STACK_SIZEOF(rx_thread_stack), + rx_thread, NULL, NULL, NULL, + CANBUS_RX_THREAD_PRIORITY, 0, K_NO_WAIT); + + if (rx_tid == NULL) + { + LOG_ERR("Failed to create CAN RX thread"); + return -ENOMEM; // Not enough memory to create thread + } + + LOG_INF("CAN bus initialized with node ID: %d,", canbus_node_id); + return 0; // Return 0 on success +} + +int canbus_send_message(uint8_t destination_node, uint8_t register_address, uint8_t *data, size_t data_length) +{ + struct can_frame frame; + if (data_length > sizeof(frame.data)) + { + LOG_ERR("Data length exceeds maximum CAN frame size"); + return -EINVAL; // Invalid argument + } + + frame.id = (destination_node << 8) | register_address; // Standard ID with node ID in the first byte + frame.dlc = data_length; + frame.flags = 0; // No special flags + + // Copy data into the frame + memcpy(frame.data, data, data_length); + + // Send the CAN frame + int rc = can_send(can_dev, &frame, K_MSEC(100), canbus_tx_callback, NULL); + if (rc < 0) { + LOG_ERR("Failed to send CAN message: %d", rc); + return rc; // Return error code + } + + LOG_DBG("CAN message sent: ID=0x%08x, DLC=%u", frame.id, frame.dlc); return 0; -} \ No newline at end of file +} diff --git a/software/lib/canbus.h b/software/lib/canbus.h index c58a404..0d4266d 100644 --- a/software/lib/canbus.h +++ b/software/lib/canbus.h @@ -4,10 +4,26 @@ #include #include -#define RX_THREAD_STACK_SIZE 512 -#define RX_THREAD_PRIORITY 2 +#define CANBUS_RX_THREAD_STACK_SIZE (512) +#define CANBUS_RX_THREAD_PRIORITY (-2) + +typedef struct { + /** Standard (11-bit) or extended (29-bit) CAN identifier. */ + uint32_t id; + /** Data Length Code (DLC) indicating data length in bytes. */ + uint8_t dlc; + /** Flags. */ + uint8_t flags; + /** The frame payload data. */ + union { + /** Payload data accessed as unsigned 8 bit values. */ + uint8_t data[8]; + uint16_t data_16[4]; + uint32_t data_32[2]; + } data; +} can_frame_t; int canbus_init(void); -int canbus_send_message(const struct can_frame *frame); +int canbus_send_message(uint8_t destination_node, uint8_t register_address, uint8_t *data, size_t data_length); #endif // __CANBUS_H__ \ No newline at end of file diff --git a/software/lib/config.c b/software/lib/config.c new file mode 100644 index 0000000..54155aa --- /dev/null +++ b/software/lib/config.c @@ -0,0 +1,62 @@ +#include "config.h" +#include + +LOG_MODULE_REGISTER(config, CONFIG_LOG_SETTINGS_LEVEL); + + +extern int canbus_node_id; // Default node ID for CAN bus + +static int settings_canbus(const char *key, size_t len, settings_read_cb read_cb, void *cb_arg) +{ + const char *next; + int rc; + + // Handle setting values for CAN bus configuration + LOG_DBG("Trying to read CAN bus configuration: key=%s, len=%zu", key, len); + if (settings_name_steq(key, "node_id", &next) && next == NULL) + { + if (len != sizeof(canbus_node_id)) + { + LOG_ERR("Invalid length for node_id setting: %zu", len); + return -EINVAL; // Invalid argument + } + + rc = read_cb(cb_arg, &canbus_node_id, sizeof(canbus_node_id)); + if (rc < 0) + { + LOG_ERR("Failed to read node_id setting: %d", rc); + return rc; // Read error + } + LOG_INF("Set CAN bus node ID to <%d> from settings", canbus_node_id); + } + return 0; // Return 0 on success +} + +static struct settings_handler settings_handler_canbus = { + .name = "canbus", + .h_set = settings_canbus, // No settings set handler +}; + +int config_init(void) +{ + int rc; + rc=settings_subsys_init(); + if (rc < 0) + { + LOG_ERR("Failed to initialize settings subsystem: %d", rc); + return rc; // Initialization error + } + rc = settings_register(&settings_handler_canbus); + if (rc < 0) + { + LOG_ERR("Failed to register settings handler: %d", rc); + return rc; // Registration error + } + rc = settings_load(); + if (rc < 0) + { + LOG_ERR("Failed to load settings: %d", rc); + return rc; // Load error + } + return 0; // Return 0 on success +} \ No newline at end of file diff --git a/software/lib/config.h b/software/lib/config.h new file mode 100644 index 0000000..78ab7dc --- /dev/null +++ b/software/lib/config.h @@ -0,0 +1,11 @@ +#ifndef __SETTINGS_H__ +#define __SETTINGS_H__ + +#include + +#include +#include + +int config_init(void); + +#endif // __SETTINGS_H__ \ No newline at end of file diff --git a/software/lib/settings.h b/software/lib/settings.h deleted file mode 100644 index 523df6f..0000000 --- a/software/lib/settings.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __SETTINGS_H__ -#define __SETTINGS_H__ - -#include - -#include -#include - -#if defined(CONFIG_SETTINGS_FILE) -#include -#include -#endif - -#define STORAGE_PARTITION storage_partition -#define STORAGE_PARTITION_ID FIXED_PARTITION_ID(STORAGE_PARTITION) - -#endif // __SETTINGS_H__ \ No newline at end of file diff --git a/software/test_canbus/CMakeLists.txt b/software/test_canbus/CMakeLists.txt index 3989c64..17330ae 100644 --- a/software/test_canbus/CMakeLists.txt +++ b/software/test_canbus/CMakeLists.txt @@ -9,6 +9,7 @@ project(hello_world) target_sources(app PRIVATE src/main.c) target_sources(app PRIVATE ../lib/canbus.c) +target_sources(app PRIVATE ../lib/config.c) target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../lib ) diff --git a/software/test_canbus/prj.conf b/software/test_canbus/prj.conf index b95fd27..ae29397 100644 --- a/software/test_canbus/prj.conf +++ b/software/test_canbus/prj.conf @@ -1,5 +1,7 @@ CONFIG_LOG=y CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_SETTINGS_LEVEL=4 +CONFIG_LOG_CAN_LEVEL=4 CONFIG_CBPRINTF_FP_SUPPORT=y CONFIG_UART_CONSOLE=y # Console on USART1 @@ -7,4 +9,3 @@ CONFIG_UART_CONSOLE=y # Console on USART1 #CONFIG_USE_SEGGER_RTT=y CONFIG_LOOPBACK_MODE=y -CONFIG_LOG_CAN_LEVEL=4 \ No newline at end of file diff --git a/software/test_canbus/src/main.c b/software/test_canbus/src/main.c index eec6388..1c8b85c 100644 --- a/software/test_canbus/src/main.c +++ b/software/test_canbus/src/main.c @@ -6,15 +6,25 @@ #include #include -#include +#include #include "canbus.h" +#include "config.h" LOG_MODULE_REGISTER(main, CONFIG_LOG_DEFAULT_LEVEL); int main(void) { int rc; + LOG_INF("Starting CAN bus initialization..."); + + // Initialize the configuration and CAN bus + rc = config_init(); + if (rc != 0) + { + LOG_ERR("Failed to initialize configuration: %d", rc); + return rc; + } rc = canbus_init(); if (rc != 0) { @@ -22,5 +32,25 @@ int main(void) return rc; } LOG_INF("CAN bus initialized successfully"); + uint16_t counter = 0; + k_sleep(K_SECONDS(1)); // Sleep for 1 second before starting the loop + + while (1) + { + uint8_t data[2] = {0x00}; + UNALIGNED_PUT(sys_cpu_to_be16(counter), (uint16_t *)&data[0]); + canbus_send_message(1, 0x01, data, sizeof(data)); // Example message sending + LOG_DBG("Sent message with counter: %d", counter); + canbus_send_message(2, 0x01, data, sizeof(data)); // Example message sending + LOG_DBG("Sent message with counter: %d", counter); + counter++; + if (counter > 1000) // Reset counter after 1000 + { + counter = 0; + } + k_sleep(K_SECONDS(5)); // Sleep for 5 second before next iteration + return 0; // Exit the loop after one iteration for testing purposes + // In a real application, you would likely not return here and continue the loop indefinitely + } return 0; }