feat(slave_node): Implement system registers

- Add read support for system-level input registers:
  - FIRMWARE_VERSION_MAJOR_MINOR (0xF0)
  - FIRMWARE_VERSION_PATCH (0xF1)
  - DEVICE_STATUS (0xF2)
- Use enums for register addresses to improve readability.
- Implement a workaround for a Kconfig issue by hardcoding the firmware version.
- Stabilize multi-register reads by returning 0 for unhandled input registers instead of an exception.
- NOTE: Writing to holding registers is currently unstable with mbpoll and will be addressed separately.
This commit is contained in:
Eduard Iten 2025-07-01 14:48:03 +02:00
parent 032ddf2cc0
commit e6dc9f9136
1 changed files with 47 additions and 30 deletions

View File

@ -14,57 +14,66 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(mbs_sample, LOG_LEVEL_INF);
static uint16_t holding_reg[8];
static uint8_t coils_state;
#define APP_VERSION_MAJOR 1
#define APP_VERSION_MINOR 0
#define APP_VERSION_PATCH 0
enum {
REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR = 0x00F0,
REG_INPUT_FIRMWARE_VERSION_PATCH = 0x00F1,
REG_INPUT_DEVICE_STATUS = 0x00F2,
REG_INPUT_UPTIME_SECONDS_LOW = 0x00F3,
REG_INPUT_UPTIME_SECONDS_HIGH = 0x00F4,
};
enum {
REG_HOLDING_WATCHDOG_TIMEOUT_S = 0x00F0,
};
static uint16_t watchdog_timeout_s;
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;
switch (addr) {
case REG_HOLDING_WATCHDOG_TIMEOUT_S:
*reg = watchdog_timeout_s;
break;
default:
*reg = 0;
break;
}
*reg = 0xDEAD;
LOG_INF("Holding register read, addr %u", addr);
LOG_INF("Holding register read, addr %u, value %u", addr, *reg);
return 0;
}
static int holding_reg_wr(uint16_t addr, uint16_t reg)
{
if (addr >= ARRAY_SIZE(holding_reg)) {
return -ENOTSUP;
switch (addr) {
case REG_HOLDING_WATCHDOG_TIMEOUT_S:
watchdog_timeout_s = reg;
break;
default:
/* Do nothing for unsupported registers */
break;
}
holding_reg[addr] = reg;
LOG_INF("Holding register write, addr %u", addr);
LOG_INF("Holding register write, addr %u, value %u", addr, reg);
return 0;
}
@ -73,10 +82,19 @@ static int input_reg_rd(uint16_t addr, uint16_t *reg)
uint32_t uptime_s = k_uptime_get_32() / 1000;
switch (addr) {
case 0x00F3:
case REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR:
*reg = (APP_VERSION_MAJOR << 8) | (APP_VERSION_MINOR & 0xFF);
break;
case REG_INPUT_FIRMWARE_VERSION_PATCH:
*reg = APP_VERSION_PATCH;
break;
case REG_INPUT_DEVICE_STATUS:
*reg = 0; /* 0 = OK */
break;
case REG_INPUT_UPTIME_SECONDS_LOW:
*reg = (uint16_t)(uptime_s & 0xFFFF);
break;
case 0x00F4:
case REG_INPUT_UPTIME_SECONDS_HIGH:
*reg = (uint16_t)(uptime_s >> 16);
break;
default:
@ -85,7 +103,6 @@ static int input_reg_rd(uint16_t addr, uint16_t *reg)
}
LOG_INF("Input register read, addr %u, value %u", addr, *reg);
return 0;
}
@ -139,4 +156,4 @@ int main(void)
}
return 0;
}
}