/* * Copyright (c) 2020 PHYTEC Messtechnik GmbH * Copyright (c) 2022 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include LOG_MODULE_REGISTER(mbs_sample, LOG_LEVEL_INF); static uint16_t holding_reg[8]; static uint8_t coils_state; static const struct gpio_dt_spec led_dev[] = { GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios), GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios), GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios), }; static int coil_rd(uint16_t addr, bool *state) { if (addr >= ARRAY_SIZE(led_dev)) { return -ENOTSUP; } if (coils_state & BIT(addr)) { *state = true; } else { *state = false; } LOG_INF("Coil read, addr %u, %d", addr, (int)*state); return 0; } static int coil_wr(uint16_t addr, bool state) { bool on; if (addr >= ARRAY_SIZE(led_dev)) { return -ENOTSUP; } if (state == true) { coils_state |= BIT(addr); on = true; } else { coils_state &= ~BIT(addr); on = false; } gpio_pin_set(led_dev[addr].port, led_dev[addr].pin, (int)on); LOG_INF("Coil write, addr %u, %d", addr, (int)state); return 0; } static int holding_reg_rd(uint16_t addr, uint16_t *reg) { if (addr >= ARRAY_SIZE(holding_reg)) { return -ENOTSUP; } *reg = holding_reg[addr]; LOG_INF("Holding register read, addr %u", addr); return 0; } static int holding_reg_wr(uint16_t addr, uint16_t reg) { if (addr >= ARRAY_SIZE(holding_reg)) { return -ENOTSUP; } holding_reg[addr] = reg; LOG_INF("Holding register write, addr %u", addr); return 0; } static struct modbus_user_callbacks mbs_cbs = { .coil_rd = coil_rd, .coil_wr = coil_wr, .holding_reg_rd = holding_reg_rd, .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, }, }; #define MODBUS_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_modbus_serial) 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) { LOG_ERR("Failed to get iface index for %s", iface_name); return iface; } return modbus_init_server(iface, server_param); } int main(void) { int err; for (int i = 0; i < ARRAY_SIZE(led_dev); i++) { if (!gpio_is_ready_dt(&led_dev[i])) { LOG_ERR("LED%u GPIO device not ready", i); return 0; } err = gpio_pin_configure_dt(&led_dev[i], GPIO_OUTPUT_INACTIVE); if (err != 0) { LOG_ERR("Failed to configure LED%u pin", i); return 0; } } #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; 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)); } LOG_INF("Client connected to server on %s", dev->name); #endif if (init_modbus_server()) { LOG_ERR("Modbus RTU server initialization failed"); } return 0; }