feat(slave_node): Implement initial Modbus RTU server

- Add a basic Modbus RTU server implementation based on Zephyr samples.
- Configure usart1 for Modbus via a board overlay.
- The server initializes and runs, but polling with mbpoll results in a timeout.
- This commit captures a functional but non-working state for further debugging.
This commit is contained in:
Eduard Iten 2025-07-01 13:41:22 +02:00
parent 0d3696bf93
commit 6f81e84541
3 changed files with 116 additions and 5 deletions

View File

@ -0,0 +1,7 @@
&usart1 {
modbus0 {
compatible = "zephyr,modbus-serial";
status = "okay";
};
status = "okay";
};

View File

@ -1,6 +1,6 @@
# Enable Console and printk for logging
CONFIG_CONSOLE=y
CONFIG_PRINTK=y
CONFIG_LOG=y
# Disable UART console
CONFIG_UART_CONSOLE=n
@ -8,3 +8,8 @@ CONFIG_UART_CONSOLE=n
# Enable RTT console
CONFIG_RTT_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y
# Config modbus
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_MODBUS=y
CONFIG_MODBUS_ROLE_SERVER=y

View File

@ -1,16 +1,115 @@
/*
* Copyright (c) 2025 Eduard Iten
* Copyright (c) 2020 PHYTEC Messtechnik GmbH
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/sys/util.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/modbus/modbus.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(mbs_sample, LOG_LEVEL_INF);
static uint16_t holding_reg[8];
static uint8_t coils_state;
static int coil_rd(uint16_t addr, bool *state)
{
*state = true;
LOG_INF("Coil read, addr %u, %d", addr, (int)*state);
return 0;
}
static int coil_wr(uint16_t addr, bool state)
{
bool on;
if (state == true) {
coils_state |= BIT(addr);
on = true;
} else {
coils_state &= ~BIT(addr);
on = false;
}
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 = 0xDEAD;
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)
{
while (1) {
printk("Hello from the updated Slave Node! Version 2.0\n");
k_msleep(1000);
LOG_INF("Starting APP");
if (init_modbus_server()) {
LOG_ERR("Modbus RTU server initialization failed");
}
LOG_INF("APP started");
return 0;
}