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:
parent
0d3696bf93
commit
6f81e84541
|
|
@ -0,0 +1,7 @@
|
||||||
|
&usart1 {
|
||||||
|
modbus0 {
|
||||||
|
compatible = "zephyr,modbus-serial";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Enable Console and printk for logging
|
# Enable Console and printk for logging
|
||||||
CONFIG_CONSOLE=y
|
CONFIG_CONSOLE=y
|
||||||
CONFIG_PRINTK=y
|
CONFIG_LOG=y
|
||||||
|
|
||||||
# Disable UART console
|
# Disable UART console
|
||||||
CONFIG_UART_CONSOLE=n
|
CONFIG_UART_CONSOLE=n
|
||||||
|
|
@ -8,3 +8,8 @@ CONFIG_UART_CONSOLE=n
|
||||||
# Enable RTT console
|
# Enable RTT console
|
||||||
CONFIG_RTT_CONSOLE=y
|
CONFIG_RTT_CONSOLE=y
|
||||||
CONFIG_USE_SEGGER_RTT=y
|
CONFIG_USE_SEGGER_RTT=y
|
||||||
|
|
||||||
|
# Config modbus
|
||||||
|
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||||
|
CONFIG_MODBUS=y
|
||||||
|
CONFIG_MODBUS_ROLE_SERVER=y
|
||||||
|
|
|
||||||
|
|
@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <zephyr/kernel.h>
|
#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)
|
int main(void)
|
||||||
{
|
{
|
||||||
while (1) {
|
LOG_INF("Starting APP");
|
||||||
printk("Hello from the updated Slave Node! Version 2.0\n");
|
if (init_modbus_server()) {
|
||||||
k_msleep(1000);
|
LOG_ERR("Modbus RTU server initialization failed");
|
||||||
}
|
}
|
||||||
|
LOG_INF("APP started");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue