Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modbus: Add locking API #87485

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions include/zephyr/modbus/modbus.h
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@
#ifndef ZEPHYR_INCLUDE_MODBUS_H_
#define ZEPHYR_INCLUDE_MODBUS_H_

#include <zephyr/sys_clock.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/sys/slist.h>
#ifdef __cplusplus
@@ -561,6 +562,38 @@ int modbus_init_client(const int iface, struct modbus_iface_param param);
*/
int modbus_disable(const uint8_t iface);

#if IS_ENABLED(CONFIG_MODBUS_LOCKING)
/**
* @brief Lock Modbus Interface
*
* The lock ensures that no new requests are handled while the inetraface is locked.asm
* May be used to ensure atomic update of register values in server role.
*
* @param iface Modbus interface index
* @param timeout Waiting period to lock the interface,
* or one of the special values K_NO_WAIT and
* K_FOREVER.
*
* @retval 0 Interface locked.
* @retval -ENODEV Invalid interface index
* @retval -EBUSY Returned without waiting.
* @retval -EAGAIN Waiting period timed out.
*/
int modbus_lock(const int iface, k_timeout_t timeout);

/**
* @brief Unlock Modbus Interface
*
* @param iface Modbus interface index
*
* @retval 0 Interface unlocked.
* @retval -ENODEV Invalid interface index
* @retval -EPERM The current thread does not own the lock
* @retval -EINVAL The interface is not locked
*/
int modbus_unlock(const int iface);
#endif

/**
* @brief Submit raw ADU
*
14 changes: 14 additions & 0 deletions subsys/modbus/Kconfig
Original file line number Diff line number Diff line change
@@ -79,6 +79,20 @@ config MODBUS_FC08_DIAGNOSTIC
help
Enable function code 08 Diagnostic support

config MODBUS_LOCKING
bool "Interface locking support"
default n
help
Enable interface locking API

config MODBUS_SERVER_LOCKING
bool "Server locking support"
depends on MODBUS_SERVER
select MODBUS_LOCKING
default n
help
Enable server locking to allow for atomic request handling

module = MODBUS
module-str = Modbus Support
module-help = Sets log level for Modbus support
34 changes: 34 additions & 0 deletions subsys/modbus/modbus_core.c
Original file line number Diff line number Diff line change
@@ -92,8 +92,16 @@ static void modbus_rx_handler(struct k_work *item)
if (ctx->client == true) {
k_sem_give(&ctx->client_wait_sem);
} else if (IS_ENABLED(CONFIG_MODBUS_SERVER)) {
if (IS_ENABLED(CONFIG_MODBUS_SERVER_LOCKING)) {
k_mutex_lock(&ctx->iface_lock, K_FOREVER);
}

bool respond = modbus_server_handler(ctx);

if (IS_ENABLED(CONFIG_MODBUS_SERVER_LOCKING)) {
k_mutex_unlock(&ctx->iface_lock);
}

if (respond) {
modbus_tx_adu(ctx);
} else {
@@ -407,3 +415,29 @@ int modbus_disable(const uint8_t iface)

return 0;
}

#if IS_ENABLED(CONFIG_MODBUS_LOCKING)

int modbus_lock(const int iface, k_timeout_t timeout)
{
struct modbus_context *ctx = modbus_get_context(iface);

if (ctx == NULL) {
return -ENODEV;
}

return k_mutex_lock(&ctx->iface_lock, timeout);
}

int modbus_unlock(const int iface)
{
struct modbus_context *ctx = modbus_get_context(iface);

if (ctx == NULL) {
return -ENODEV;
}

return k_mutex_unlock(&ctx->iface_lock);
}

#endif
2 changes: 1 addition & 1 deletion subsys/modbus/modbus_internal.h
Original file line number Diff line number Diff line change
@@ -109,7 +109,7 @@ struct modbus_context {
/* Interface state */
atomic_t state;

/* Client's mutually exclusive access */
/* Interface lock */
struct k_mutex iface_lock;
/* Wait for response semaphore */
struct k_sem client_wait_sem;