forked from espressif/esp-modbus
feature add custom fc handlers for master and slave v2
This commit is contained in:
1 parent
439c767aed
commit
8215e3d0d2
51 files changed
+1345
-300
No files matched your search
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "esp_err.h"
|
||||
#include "mbc_master.h" // for master interface define
|
||||
#include "mbc_slave.h" // for slave interface define
|
||||
#include "esp_modbus_common.h" // for public interface defines
|
||||
|
||||
static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_COMMON";
|
||||
|
||||
/**
|
||||
* Register or override command handler for the command in object command handler table
|
||||
*/
|
||||
esp_err_t mbc_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp phandler)
|
||||
{
|
||||
MB_RETURN_ON_FALSE((ctx && phandler && func_code), ESP_ERR_INVALID_STATE, TAG,
|
||||
"Incorrect arguments for the function.");
|
||||
mb_err_enum_t ret = MB_EINVAL;
|
||||
mb_controller_common_t *mb_controller = (mb_controller_common_t *)(ctx);
|
||||
mb_base_t *pmb_obj = (mb_base_t *)mb_controller->mb_base;
|
||||
MB_RETURN_ON_FALSE(pmb_obj, ESP_ERR_INVALID_STATE, TAG,
|
||||
"Controller interface is not correctly initialized.");
|
||||
if (pmb_obj->descr.is_master) {
|
||||
ret = mbm_set_handler(mb_controller->mb_base, func_code, phandler);
|
||||
} else {
|
||||
ret = mbs_set_handler(mb_controller->mb_base, func_code, phandler);
|
||||
}
|
||||
return MB_ERR_TO_ESP_ERR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get command handler from the command handler table of the object
|
||||
*/
|
||||
esp_err_t mbc_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *phandler)
|
||||
{
|
||||
MB_RETURN_ON_FALSE((ctx && func_code && phandler), ESP_ERR_INVALID_STATE, TAG,
|
||||
"Incorrect arguments for the function.");
|
||||
mb_err_enum_t ret = MB_EINVAL;
|
||||
mb_controller_common_t *mb_controller = (mb_controller_common_t *)(ctx);
|
||||
mb_base_t *pmb_obj = (mb_base_t *)mb_controller->mb_base;
|
||||
MB_RETURN_ON_FALSE(pmb_obj, ESP_ERR_INVALID_STATE, TAG,
|
||||
"Controller interface is not correctly initialized.");
|
||||
if (pmb_obj->descr.is_master) {
|
||||
ret = mbm_get_handler(mb_controller->mb_base, func_code, phandler);
|
||||
} else {
|
||||
ret = mbs_get_handler(mb_controller->mb_base, func_code, phandler);
|
||||
}
|
||||
return MB_ERR_TO_ESP_ERR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete command handler from the command handler table of the object
|
||||
*/
|
||||
esp_err_t mbc_delete_handler(void *ctx, uint8_t func_code)
|
||||
{
|
||||
MB_RETURN_ON_FALSE((ctx && func_code), ESP_ERR_INVALID_STATE, TAG,
|
||||
"Incorrect arguments for the function.");
|
||||
mb_err_enum_t ret = MB_EINVAL;
|
||||
mb_controller_common_t *mb_controller = (mb_controller_common_t *)(ctx);
|
||||
mb_base_t *pmb_obj = (mb_base_t *)mb_controller->mb_base;
|
||||
MB_RETURN_ON_FALSE(pmb_obj, ESP_ERR_INVALID_STATE, TAG,
|
||||
"Controller interface is not correctly initialized.");
|
||||
if (pmb_obj->descr.is_master) {
|
||||
ret = mbm_delete_handler(mb_controller->mb_base, func_code);
|
||||
} else {
|
||||
ret = mbs_delete_handler(mb_controller->mb_base, func_code);
|
||||
}
|
||||
return MB_ERR_TO_ESP_ERR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of registered command handlers for the object
|
||||
*/
|
||||
esp_err_t mbc_get_handler_count(void *ctx, uint16_t *pcount)
|
||||
{
|
||||
MB_RETURN_ON_FALSE((ctx && pcount), ESP_ERR_INVALID_STATE, TAG,
|
||||
"Controller interface is not correctly initialized.");
|
||||
mb_err_enum_t ret = MB_EINVAL;
|
||||
mb_controller_common_t *mb_controller = (mb_controller_common_t *)(ctx);
|
||||
mb_base_t *pmb_obj = (mb_base_t *)mb_controller->mb_base;
|
||||
MB_RETURN_ON_FALSE(pmb_obj, ESP_ERR_INVALID_STATE, TAG,
|
||||
"Controller interface is not correctly initialized.");
|
||||
if (pmb_obj->descr.is_master) {
|
||||
ret = mbm_get_handler_count(mb_controller->mb_base, pcount);
|
||||
} else {
|
||||
ret = mbs_get_handler_count(mb_controller->mb_base, pcount);
|
||||
}
|
||||
return MB_ERR_TO_ESP_ERR(ret);
|
||||
}
|
||||
@@ -732,3 +732,4 @@ esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -76,6 +76,47 @@ extern "C" {
|
||||
*(uint8_t *)(dst + 0) = *(uint8_t *)(src)++; \
|
||||
}
|
||||
|
||||
#define mb_err_var esp_err##__func__##__line__
|
||||
#define esp_err_var mb_error##__func__##__line__
|
||||
#define MB_ERR_TO_ESP_ERR(error_code) (__extension__( \
|
||||
{ \
|
||||
mb_err_enum_t mb_err_var = (mb_err_enum_t)error_code; \
|
||||
esp_err_t esp_err_var = ESP_FAIL; \
|
||||
switch(mb_err_var) { \
|
||||
case MB_ENOERR: \
|
||||
esp_err_var = ESP_OK; \
|
||||
break; \
|
||||
case MB_ENOREG: \
|
||||
esp_err_var = ESP_ERR_NOT_SUPPORTED; \
|
||||
break; \
|
||||
case MB_ETIMEDOUT: \
|
||||
esp_err_var = ESP_ERR_TIMEOUT; \
|
||||
break; \
|
||||
case MB_EINVAL: \
|
||||
esp_err_var = ESP_ERR_INVALID_ARG; \
|
||||
break; \
|
||||
case MB_EILLFUNC: \
|
||||
esp_err_var = ESP_ERR_INVALID_RESPONSE; \
|
||||
break; \
|
||||
case MB_ERECVDATA: \
|
||||
esp_err_var = ESP_ERR_INVALID_RESPONSE; \
|
||||
break; \
|
||||
case MB_EBUSY: \
|
||||
case MB_EILLSTATE: \
|
||||
case MB_EPORTERR: \
|
||||
case MB_ENORES: \
|
||||
case MB_ENOCONN: \
|
||||
esp_err_var = ESP_ERR_INVALID_STATE; \
|
||||
break; \
|
||||
default: \
|
||||
ESP_LOGE(TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, (int)mb_err_var); \
|
||||
esp_err_var = ESP_FAIL; \
|
||||
break; \
|
||||
} \
|
||||
(esp_err_var); \
|
||||
} \
|
||||
))
|
||||
|
||||
/**
|
||||
* @brief Types of actual Modbus implementation
|
||||
*/
|
||||
@@ -117,45 +158,6 @@ typedef enum {
|
||||
MB_PARAM_UNKNOWN = 0xFF
|
||||
} mb_param_type_t;
|
||||
|
||||
#define mb_err_var esp_err##__func__##__line__
|
||||
#define esp_err_var mb_error##__func__##__line__
|
||||
#define MB_ERR_TO_ESP_ERR(error_code) (__extension__( \
|
||||
{ \
|
||||
mb_err_enum_t mb_err_var = (mb_err_enum_t)error_code; \
|
||||
esp_err_t esp_err_var = ESP_FAIL; \
|
||||
switch(mb_err_var) { \
|
||||
case MB_ENOERR: \
|
||||
esp_err_var = ESP_OK; \
|
||||
break; \
|
||||
case MB_ENOREG: \
|
||||
esp_err_var = ESP_ERR_NOT_SUPPORTED; \
|
||||
break; \
|
||||
case MB_ETIMEDOUT: \
|
||||
esp_err_var = ESP_ERR_TIMEOUT; \
|
||||
break; \
|
||||
case MB_EILLFUNC: \
|
||||
case MB_EINVAL: \
|
||||
esp_err_var = ESP_ERR_INVALID_RESPONSE; \
|
||||
break; \
|
||||
case MB_ERECVDATA: \
|
||||
esp_err_var = ESP_ERR_INVALID_RESPONSE; \
|
||||
break; \
|
||||
case MB_EBUSY: \
|
||||
case MB_EILLSTATE: \
|
||||
case MB_EPORTERR: \
|
||||
case MB_ENORES: \
|
||||
case MB_ENOCONN: \
|
||||
esp_err_var = ESP_ERR_INVALID_STATE; \
|
||||
break; \
|
||||
default: \
|
||||
ESP_LOGE(TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, (int)mb_err_var); \
|
||||
esp_err_var = ESP_FAIL; \
|
||||
break; \
|
||||
} \
|
||||
(esp_err_var); \
|
||||
} \
|
||||
))
|
||||
|
||||
typedef enum _mb_comm_mode mb_mode_type_t;
|
||||
|
||||
typedef struct mb_base_t mb_base_t;
|
||||
@@ -168,17 +170,17 @@ typedef enum _addr_type_enum mb_tcp_addr_type_t;
|
||||
/*!
|
||||
* \brief Modbus TCP communication options structure.
|
||||
*/
|
||||
typedef struct _port_tcp_opts mb_tcp_opts_t;
|
||||
typedef struct port_tcp_opts_s mb_tcp_opts_t;
|
||||
|
||||
/*!
|
||||
* \brief Modbus serial communication options structure.
|
||||
*/
|
||||
typedef struct _port_serial_opts mb_serial_opts_t;
|
||||
typedef struct port_serial_opts_s mb_serial_opts_t;
|
||||
|
||||
/*!
|
||||
* \brief Modbus common communication options structure.
|
||||
*/
|
||||
typedef struct _port_common_opts mb_common_opts_t;
|
||||
typedef struct port_common_opts_s mb_common_opts_t;
|
||||
|
||||
/**
|
||||
* @brief Device communication structure to setup Modbus controller
|
||||
@@ -199,7 +201,70 @@ typedef union
|
||||
* common interface method types
|
||||
*/
|
||||
typedef esp_err_t (*iface_create_fp)(mb_communication_info_t*, void **); /*!< Interface method create */
|
||||
typedef esp_err_t (*iface_method_default_fp)(void *ctx); /*!< Interface method default prototype */
|
||||
typedef esp_err_t (*iface_method_default_fp)(void *ctx); /*!< Interface method default prototype */
|
||||
|
||||
/**
|
||||
* @brief Modbus controller common interface structure
|
||||
*/
|
||||
typedef struct {
|
||||
mb_base_t *mb_base; /*!< base object pointer */
|
||||
} mb_controller_common_t;
|
||||
|
||||
/**
|
||||
* @brief The function registers the new function handler for specified command
|
||||
* and allows to override the existing handler for the the controller object.
|
||||
*
|
||||
* @param[in] ctx context pointer to the controller object (master or slave)
|
||||
* @param[in] func_code the function code for the handler
|
||||
* @param[in] phandler the pointer to function handler being used for command
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t ESP_OK - the function handler is correctly set the handler
|
||||
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
|
||||
* - esp_err_t ESP_ERR_INVALID_STATE - can not register non-existent handler or can not
|
||||
* - esp_err_t ESP_ERR_NOT_FOUND - the requested slave is not found (not connected or not configured)
|
||||
*/
|
||||
esp_err_t mbc_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp phandler);
|
||||
|
||||
/**
|
||||
* @brief The function gets function handler for specified command from the controller object handler table.
|
||||
*
|
||||
* @param[in] ctx context pointer to the controller object (master or slave)
|
||||
* @param[in] func_code the function code for the handler
|
||||
* @param[out] phandler the pointer to function handler being returned
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t ESP_OK - the function handler is returned
|
||||
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
|
||||
* esp_err_t ESP_ERR_INVALID_STATE - can not register non-existent handler or incorrect configuration
|
||||
*/
|
||||
esp_err_t mbc_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *phandler);
|
||||
|
||||
/**
|
||||
* @brief The function deletes function handler for specified command from the controller object command handler table.
|
||||
*
|
||||
* @param[in] ctx context pointer to the controller object (master or slave)
|
||||
* @param[in] func_code the function code for the handler
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t ESP_OK - the function handler is deleted
|
||||
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
|
||||
* esp_err_t ESP_ERR_INVALID_STATE - can not register non-existent handler or incorrect configuration
|
||||
*/
|
||||
esp_err_t mbc_delete_handler(void *ctx, uint8_t func_code);
|
||||
|
||||
/**
|
||||
* @brief The function gets the number of registered function handlers for the controller object.
|
||||
*
|
||||
* @param[in] ctx context pointer to the controller object (master or slave)
|
||||
* @param[out] pcount the pointer to returned counter
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t ESP_OK - the function handler is returned in the
|
||||
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
|
||||
* esp_err_t ESP_ERR_INVALID_STATE - can not register non-existent handler or incorrect configuration
|
||||
*/
|
||||
esp_err_t mbc_get_handler_count(void *ctx, uint16_t *pcount);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
#include "driver/uart.h" // for uart port number defines
|
||||
#include "sdkconfig.h" // for KConfig options
|
||||
|
||||
#include "esp_modbus_common.h"
|
||||
#include "esp_modbus_master.h"
|
||||
#include "esp_modbus_slave.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ extern "C" {
|
||||
|
||||
#include "mb_common.h" // for mb_base_t
|
||||
#include "esp_modbus_slave.h" // for public type defines
|
||||
#include "mb_slave.h"
|
||||
|
||||
/* ----------------------- Defines ------------------------------------------*/
|
||||
#define MB_INST_MIN_SIZE (1) // The minimal size of Modbus registers area in bytes
|
||||
|
||||
@@ -256,9 +256,20 @@ static esp_err_t mbc_serial_master_send_request(void *ctx, mb_param_request_t *r
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ESP_LOGE(TAG, "%s: Incorrect or unsupported function in request (%u) ",
|
||||
__FUNCTION__, mb_command);
|
||||
mb_error = MB_ENOREG;
|
||||
mb_fn_handler_fp phandler = NULL;
|
||||
// check registered function handler
|
||||
mb_error = mbm_get_handler(mbm_controller_iface->mb_base, mb_command, &phandler);
|
||||
if (mb_error == MB_ENOERR) {
|
||||
// send the request for custom command
|
||||
mb_error = mbm_rq_custom(mbm_controller_iface->mb_base, mb_slave_addr, mb_command,
|
||||
data_ptr, (uint16_t)(mb_size << 1),
|
||||
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
|
||||
ESP_LOGD(TAG, "%s: Send custom request (%u)", __FUNCTION__, mb_command);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "%s: Incorrect or unsupported function in request (%u), error = (0x%x)",
|
||||
__FUNCTION__, mb_command, (int)mb_error);
|
||||
mb_error = MB_ENOREG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -255,9 +255,19 @@ static esp_err_t mbc_tcp_master_send_request(void *ctx, mb_param_request_t *requ
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ESP_LOGE(TAG, "%s: Incorrect or unsupported function in request (%u) ",
|
||||
__FUNCTION__, (unsigned)mb_command);
|
||||
mb_error = MB_ENOREG;
|
||||
mb_fn_handler_fp phandler = NULL;
|
||||
// check registered function handler
|
||||
mb_error = mbm_get_handler(mbm_controller_iface->mb_base, mb_command, &phandler);
|
||||
if (mb_error == MB_ENOERR) {
|
||||
// send the request for custom command
|
||||
mb_error = mbm_rq_custom(mbm_controller_iface->mb_base, mb_slave_addr, mb_command,
|
||||
data_ptr, (uint16_t)(mb_size << 1),
|
||||
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
|
||||
ESP_LOGD(TAG, "%s: Send custom request (%u)", __FUNCTION__, mb_command);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "%s: Incorrect or unsupported function in request (%u), error = (0x%x) ", __FUNCTION__, mb_command, (int)mb_error);
|
||||
mb_error = MB_ENOREG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -588,7 +598,6 @@ static esp_err_t mbc_tcp_master_delete(void *ctx)
|
||||
MB_RETURN_ON_FALSE((mbc_tcp_master_stop(ctx) == ESP_OK),
|
||||
ESP_ERR_INVALID_STATE, TAG, "mb stack stop failure.");
|
||||
}
|
||||
|
||||
mbm_iface->is_active = false;
|
||||
vTaskDelete(mbm_opts->task_handle);
|
||||
mbm_opts->task_handle = NULL;
|
||||
|
||||
Reference in new issue
Block a user