forked from espressif/esp-modbus
mb master, slave add custom fc handlers
This commit is contained in:
@@ -43,9 +43,9 @@ set(srcs
|
||||
"mb_transports/tcp/tcp_slave.c"
|
||||
)
|
||||
|
||||
set(include_dirs mb_transports mb_controller/common/include mb_objects/include mb_ports/common mb_ports/serial mb_ports/tcp)
|
||||
set(include_dirs mb_transports mb_controller/common/include mb_objects/common mb_ports/common mb_ports/serial mb_ports/tcp)
|
||||
|
||||
set(priv_include_dirs mb_controller/serial mb_controller/tcp mb_controller/common mb_transports/rtu mb_transports/ascii mb_transports/tcp)
|
||||
set(priv_include_dirs mb_controller/serial mb_controller/tcp mb_controller/common mb_objects/include mb_transports/rtu mb_transports/ascii mb_transports/tcp)
|
||||
|
||||
if(CONFIG_FMB_EXT_TYPE_SUPPORT)
|
||||
list(APPEND srcs "mb_controller/common/mb_endianness_utils.c")
|
||||
|
17
Kconfig
17
Kconfig
@@ -224,4 +224,21 @@ menu "Modbus configuration"
|
||||
otherwise the only legacy types are supported. The extended types include
|
||||
integer, float, double types with different endianness and size.
|
||||
|
||||
config FMB_CONTROLLER_SLAVE_ID_MAX_SIZE
|
||||
int "Modbus Slave ID maximum buffer size (bytes)"
|
||||
range 4 255
|
||||
default 32
|
||||
depends on FMB_CONTROLLER_SLAVE_ID_SUPPORT
|
||||
help
|
||||
Modbus slave ID buffer size used to store vendor specific ID information
|
||||
for the <Report Slave ID> command.
|
||||
|
||||
config FMB_FUNC_HANDLERS_MAX
|
||||
int "Maximum number of Modbus function handlers"
|
||||
range 16 64
|
||||
default 16
|
||||
help
|
||||
This option defines the maximum number of Modbus command handlers for Modbus master and slave.
|
||||
The option can be useful to register additional commands and its handlers.
|
||||
|
||||
endmenu
|
||||
|
@@ -732,3 +732,33 @@ esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register or override command handler for the command in master command handler table
|
||||
*/
|
||||
esp_err_t mbc_master_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp phandler)
|
||||
{
|
||||
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
|
||||
"Master interface is not correctly initialized.");
|
||||
mbm_controller_iface_t *mbm_controller = MB_MASTER_GET_IFACE(ctx);
|
||||
mb_base_t *pmb_obj = (mb_base_t *)mbm_controller->mb_base;
|
||||
MB_RETURN_ON_FALSE((pmb_obj && pmb_obj->descr.is_master), ESP_ERR_INVALID_STATE, TAG,
|
||||
"Master interface is not correctly initialized.");
|
||||
mb_err_enum_t ret = mbm_set_handler(func_code, phandler);
|
||||
return MB_ERR_TO_ESP_ERR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get command master command handler from the slave command handler table
|
||||
*/
|
||||
esp_err_t mbc_master_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *phandler)
|
||||
{
|
||||
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
|
||||
"Master interface is not correctly initialized.");
|
||||
mbm_controller_iface_t *mbm_controller = MB_MASTER_GET_IFACE(ctx);
|
||||
mb_base_t *pmb_obj = (mb_base_t *)mbm_controller->mb_base;
|
||||
MB_RETURN_ON_FALSE((pmb_obj && pmb_obj->descr.is_master), ESP_ERR_INVALID_STATE, TAG,
|
||||
"Master interface is not correctly initialized.");
|
||||
mb_err_enum_t ret = mbm_get_handler(func_code, phandler);
|
||||
return MB_ERR_TO_ESP_ERR(ret);
|
||||
}
|
@@ -547,3 +547,33 @@ mb_err_enum_t mbc_reg_discrete_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, ui
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register or override command handler for the command in slave command handler table
|
||||
*/
|
||||
esp_err_t mbc_slave_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp phandler)
|
||||
{
|
||||
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
|
||||
"Slave interface is not correctly initialized.");
|
||||
mbs_controller_iface_t *mbs_controller = MB_SLAVE_GET_IFACE(ctx);
|
||||
mb_base_t *pmb_obj = (mb_base_t *)mbs_controller->mb_base;
|
||||
MB_RETURN_ON_FALSE((pmb_obj && !pmb_obj->descr.is_master), ESP_ERR_INVALID_STATE, TAG,
|
||||
"Slave interface is not correctly initialized.");
|
||||
mb_err_enum_t ret = mbs_set_handler(func_code, phandler);
|
||||
return MB_ERR_TO_ESP_ERR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get slave command handler from the slave command handler table
|
||||
*/
|
||||
esp_err_t mbc_slave_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *phandler)
|
||||
{
|
||||
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
|
||||
"Slave interface is not correctly initialized.");
|
||||
mbs_controller_iface_t *mbs_controller = MB_SLAVE_GET_IFACE(ctx);
|
||||
mb_base_t *pmb_obj = (mb_base_t *)mbs_controller->mb_base;
|
||||
MB_RETURN_ON_FALSE((pmb_obj && !pmb_obj->descr.is_master), ESP_ERR_INVALID_STATE, TAG,
|
||||
"Slave interface is not correctly initialized.");
|
||||
mb_err_enum_t ret = mbs_get_handler(func_code, phandler);
|
||||
return MB_ERR_TO_ESP_ERR(ret);
|
||||
}
|
@@ -201,6 +201,27 @@ typedef union
|
||||
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 */
|
||||
|
||||
/**
|
||||
* @brief The function registers the new function handler for specified command and
|
||||
* allows to override the existing one for the communication object.
|
||||
* If the phandler == 0, the function allows to clear the actual function handler for the `func_code` parameter.
|
||||
*
|
||||
* @param[in] ctx context pointer to the communication object
|
||||
* @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
|
||||
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
|
||||
* - esp_err_t ESP_ERR_INVALID_RESPONSE - an invalid response from slave during processing of parameter
|
||||
* - esp_err_t ESP_ERR_INVALID_STATE - invalid state during data processing or allocation failure
|
||||
* - esp_err_t ESP_ERR_NOT_FOUND - the requested slave is not found (not connected or not configured)
|
||||
* - esp_err_t ESP_ERR_TIMEOUT - operation timed out and no response from slave
|
||||
* - esp_err_t ESP_ERR_NOT_SUPPORTED - the request command is not supported by slave
|
||||
* - esp_err_t ESP_FAIL - slave returned an exception or other failure
|
||||
*/
|
||||
esp_err_t mbc_register_cb(void *ctx, uint8_t func_code, mb_fn_handler_fp phandler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -466,6 +466,38 @@ mb_err_enum_t mbc_reg_coils_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint
|
||||
*/
|
||||
esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param_type, size_t param_size);
|
||||
|
||||
/**
|
||||
* @brief The function registers the new function handler for specified command
|
||||
* and allows to override the existing one for the master object.
|
||||
* If the phandler == NULL, the function allows to reset the actual function handler
|
||||
* for the `func_code` parameter.
|
||||
*
|
||||
* @param[in] ctx context pointer to the master controller object
|
||||
* @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
|
||||
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
|
||||
* - esp_err_t ESP_ERR_INVALID_RESPONSE - an invalid response from slave during processing of parameter
|
||||
* - esp_err_t ESP_ERR_INVALID_STATE - invalid state during data processing or allocation failure
|
||||
* - esp_err_t ESP_ERR_NOT_FOUND - the requested slave is not found (not connected or not configured)
|
||||
*/
|
||||
esp_err_t mbc_master_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp phandler);
|
||||
|
||||
/**
|
||||
* @brief The function gets function handler for specified command from master command handler table.
|
||||
*
|
||||
* @param[in] ctx context pointer to the master controller object
|
||||
* @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 in the
|
||||
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
|
||||
*/
|
||||
esp_err_t mbc_master_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *phandler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -292,6 +292,37 @@ mb_err_enum_t mbc_reg_discrete_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, ui
|
||||
*/
|
||||
mb_err_enum_t mbc_reg_coils_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t address, uint16_t n_coils, mb_reg_mode_enum_t mode) __attribute__ ((weak));
|
||||
|
||||
/**
|
||||
* @brief The function registers the new function handler for specified command
|
||||
* and allows to override the existing one for the slave object.
|
||||
* If the phandler == NULL, the function allows to reset the actual function handler
|
||||
* for the `func_code` parameter.
|
||||
*
|
||||
* @param[in] ctx context pointer to the slave controller object
|
||||
* @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
|
||||
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
|
||||
* - esp_err_t ESP_ERR_INVALID_RESPONSE - an invalid response from slave during processing of parameter
|
||||
* - esp_err_t ESP_ERR_INVALID_STATE - invalid state during data processing or allocation failure
|
||||
*/
|
||||
esp_err_t mbc_slave_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp phandler);
|
||||
|
||||
/**
|
||||
* @brief The function gets function handler for specified command from slave command handler table.
|
||||
*
|
||||
* @param[in] ctx context pointer to the slave controller object
|
||||
* @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 in the
|
||||
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
|
||||
*/
|
||||
esp_err_t mbc_slave_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *phandler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -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,19 @@ 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(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), error = (0x%d) ", __FUNCTION__, mb_command, (int)mb_error);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "%s: Incorrect or unsupported function in request (%u) ", __FUNCTION__, mb_command);
|
||||
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(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), error = (0x%d) ", __FUNCTION__, mb_command, (int)mb_error);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "%s: Incorrect or unsupported function in request (%u) ", __FUNCTION__, mb_command);
|
||||
mb_error = MB_ENOREG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@@ -5,8 +5,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "mb_config.h"
|
||||
#include "mb_types.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if __has_include("esp_idf_version.h")
|
||||
#include "esp_idf_version.h"
|
@@ -85,6 +85,26 @@ typedef enum _mb_event_enum {
|
||||
EV_MASTER_PROCESS_SUCCESS = 0x0400 /*!< Master error process. */
|
||||
} mb_event_enum_t;
|
||||
|
||||
/*! \ingroup modbus
|
||||
* \brief Modbus exception types used in the stack.
|
||||
*/
|
||||
typedef enum _mb_exception_enum
|
||||
{
|
||||
MB_EX_NONE = 0x00,
|
||||
MB_EX_ILLEGAL_FUNCTION = 0x01,
|
||||
MB_EX_ILLEGAL_DATA_ADDRESS = 0x02,
|
||||
MB_EX_ILLEGAL_DATA_VALUE = 0x03,
|
||||
MB_EX_SLAVE_DEVICE_FAILURE = 0x04,
|
||||
MB_EX_ACKNOWLEDGE = 0x05,
|
||||
MB_EX_SLAVE_BUSY = 0x06,
|
||||
MB_EX_MEMORY_PARITY_ERROR = 0x08,
|
||||
MB_EX_GATEWAY_PATH_FAILED = 0x0A,
|
||||
MB_EX_GATEWAY_TGT_FAILED = 0x0B,
|
||||
MB_EX_CRITICAL = 0xFF
|
||||
} mb_exception_t;
|
||||
|
||||
typedef mb_exception_t (*mb_fn_handler_fp)(void *, uint8_t *frame_ptr, uint16_t *len_buf);
|
||||
|
||||
/*! \ingroup modbus
|
||||
* \brief Error event type
|
||||
*/
|
@@ -44,6 +44,39 @@
|
||||
/* ----------------------- Start implementation -----------------------------*/
|
||||
mb_exception_t mb_error_to_exception(mb_err_enum_t error_code);
|
||||
|
||||
/**
|
||||
* This function will request read coil.
|
||||
*
|
||||
* @param uid slave address
|
||||
* @param fc custom function code
|
||||
* @param buf additional data to send
|
||||
* @param buf_size size of data to send
|
||||
* @param timeout timeout (-1 will waiting forever)
|
||||
*
|
||||
* @return error code (mb_err_enum_t)
|
||||
*/
|
||||
mb_err_enum_t mbm_rq_custom(mb_base_t *inst, uint8_t uid, uint8_t fc, uint8_t *buf, uint16_t buf_size, uint32_t tout)
|
||||
{
|
||||
uint8_t *mb_frame_ptr;
|
||||
if (!buf || (uid > MB_ADDRESS_MAX) || (buf_size >= (MB_BUFFER_SIZE - 2))) {
|
||||
return MB_EINVAL;
|
||||
}
|
||||
if (!mb_port_event_res_take(inst->port_obj, tout)) {
|
||||
return MB_EBUSY;
|
||||
}
|
||||
inst->get_send_buf(inst, &mb_frame_ptr);
|
||||
inst->set_dest_addr(inst, uid);
|
||||
|
||||
mb_frame_ptr[MB_PDU_FUNC_OFF] = fc;
|
||||
|
||||
memcpy(&mb_frame_ptr[MB_PDU_DATA_OFF], buf, buf_size);
|
||||
|
||||
inst->set_send_len(inst, MB_PDU_SIZE_MIN + buf_size);
|
||||
|
||||
(void)mb_port_event_post(inst->port_obj, EVENT(EV_FRAME_TRANSMIT | EV_TRANS_START));
|
||||
return mb_port_event_wait_req_finish(inst->port_obj);
|
||||
}
|
||||
|
||||
mb_err_enum_t mbm_rq_report_slave_id(mb_base_t *inst, uint8_t slave_addr, uint32_t timeout)
|
||||
{
|
||||
uint8_t *mb_frame_ptr = NULL;
|
||||
|
@@ -126,4 +126,52 @@ mb_exception_t mb_error_to_exception(mb_err_enum_t error_code)
|
||||
return status;
|
||||
}
|
||||
|
||||
mb_err_enum_t mb_set_handler(mb_fn_handler_t *pfh_table, uint8_t func_code, mb_fn_handler_fp phandler)
|
||||
{
|
||||
int index;
|
||||
mb_err_enum_t status = MB_EILLSTATE;
|
||||
if ((0 < func_code) && (func_code <= MB_FUNC_CODE_MAX)) {
|
||||
if (phandler != NULL) {
|
||||
for(index = 0; index < MB_FUNC_HANDLERS_MAX; index++) {
|
||||
if ((pfh_table[index].handler == NULL) ||
|
||||
(pfh_table[index].handler == phandler)) {
|
||||
pfh_table[index].func_code = func_code;
|
||||
pfh_table[index].handler = phandler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
status = (index != MB_FUNC_HANDLERS_MAX) ? MB_ENOERR : MB_ENORES;
|
||||
} else {
|
||||
for (index = 0; index < MB_FUNC_HANDLERS_MAX; index++) {
|
||||
if (pfh_table[index].func_code == func_code) {
|
||||
pfh_table[index].func_code = 0;
|
||||
pfh_table[index].handler = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
status = (index < MB_FUNC_HANDLERS_MAX) ? MB_ENOERR : MB_ENORES;
|
||||
}
|
||||
} else {
|
||||
status = MB_EINVAL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
mb_err_enum_t mb_get_handler(mb_fn_handler_t *pfh_table, uint8_t func_code, mb_fn_handler_fp *phandler)
|
||||
{
|
||||
int index;
|
||||
mb_err_enum_t status = MB_EILLSTATE;
|
||||
if (pfh_table && phandler && (0 < func_code) && (func_code <= MB_FUNC_CODE_MAX)) {
|
||||
for(index = 0; index < MB_FUNC_HANDLERS_MAX; index++) {
|
||||
if (func_code == pfh_table[index].func_code) {
|
||||
*phandler = pfh_table[index].handler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
status = (index < MB_FUNC_HANDLERS_MAX) ? MB_ENOERR : MB_ENORES;
|
||||
} else {
|
||||
status = MB_EINVAL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@@ -152,7 +152,8 @@ struct mb_base_t
|
||||
mb_rw_callbacks_t rw_cbs;
|
||||
};
|
||||
|
||||
typedef struct _port_tcp_opts mb_tcp_opts_t;
|
||||
mb_err_enum_t mb_set_handler(mb_fn_handler_t *pfh_table, uint8_t func_code, mb_fn_handler_fp phandler);
|
||||
mb_err_enum_t mb_get_handler(mb_fn_handler_t *pfh_table, uint8_t func_code, mb_fn_handler_fp *phandler);
|
||||
|
||||
#if (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)
|
||||
|
||||
@@ -163,8 +164,13 @@ mb_err_enum_t mbs_ascii_create(mb_serial_opts_t *ser_opts, void **in_out_obj);
|
||||
|
||||
#endif
|
||||
|
||||
#if (CONFIG_FMB_COMM_MODE_TCP_EN)
|
||||
|
||||
typedef struct _port_tcp_opts mb_tcp_opts_t;
|
||||
mb_err_enum_t mbs_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj);
|
||||
|
||||
#endif
|
||||
|
||||
mb_err_enum_t mbs_delete(mb_base_t *inst);
|
||||
mb_err_enum_t mbs_enable(mb_base_t *inst);
|
||||
mb_err_enum_t mbs_disable(mb_base_t *inst);
|
||||
|
@@ -115,7 +115,7 @@ extern "C" {
|
||||
* the sum of all enabled functions in this file and custom function
|
||||
* handlers. If set to small adding more functions will fail.
|
||||
*/
|
||||
#define MB_FUNC_HANDLERS_MAX (16)
|
||||
#define MB_FUNC_HANDLERS_MAX (CONFIG_FMB_FUNC_HANDLERS_MAX)
|
||||
|
||||
/*! \brief Number of bytes which should be allocated for the <em>Report Slave ID
|
||||
* </em>command.
|
||||
|
@@ -12,6 +12,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MB_FUNC_CODE_MAX 127
|
||||
|
||||
typedef struct mb_base_t mb_base_t;
|
||||
|
||||
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
|
||||
|
@@ -10,7 +10,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct mb_base_t mb_base_t; /*!< Type of moddus object */
|
||||
typedef struct mb_base_t mb_base_t; /*!< Type of modbus object */
|
||||
|
||||
mb_err_enum_t mbm_rq_read_inp_reg(mb_base_t *inst, uint8_t snd_addr, uint16_t reg_addr, uint16_t reg_num, uint32_t tout);
|
||||
mb_err_enum_t mbm_rq_write_holding_reg(mb_base_t *inst, uint8_t snd_addr, uint16_t reg_addr, uint16_t reg_data, uint32_t tout);
|
||||
@@ -26,6 +26,7 @@ mb_err_enum_t mbm_rq_write_multi_coils(mb_base_t *inst, uint8_t snd_addr, uint16
|
||||
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
|
||||
mb_err_enum_t mbm_rq_report_slave_id(mb_base_t *inst, uint8_t slave_addr, uint32_t timeout);
|
||||
mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t * pframe, uint16_t *usLen);
|
||||
mb_err_enum_t mbm_rq_custom(mb_base_t *inst, uint8_t uid, uint8_t fc, uint8_t *buf, uint16_t buf_size, uint32_t tout);
|
||||
|
||||
/*! \ingroup modbus_registers
|
||||
* \brief The common callback function used to transfer common data as bytes from command buffer in little endian format.
|
||||
@@ -44,6 +45,12 @@ mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t * pframe, uint16_
|
||||
mb_err_enum_t mbc_reg_common_cb(mb_base_t *inst, uint8_t *pdata, uint16_t address, uint16_t bytes);
|
||||
#endif
|
||||
|
||||
// The function to register custom function handler for master
|
||||
mb_err_enum_t mbm_set_handler(uint8_t func_code, mb_fn_handler_fp phandler);
|
||||
|
||||
// The helper function to get custom function handler for master
|
||||
mb_err_enum_t mbm_get_handler(uint8_t fc, mb_fn_handler_fp *phandler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -38,22 +38,6 @@ typedef enum _mb_commands_enum
|
||||
|
||||
/* ----------------------- Type definitions ---------------------------------*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MB_EX_NONE = 0x00,
|
||||
MB_EX_ILLEGAL_FUNCTION = 0x01,
|
||||
MB_EX_ILLEGAL_DATA_ADDRESS = 0x02,
|
||||
MB_EX_ILLEGAL_DATA_VALUE = 0x03,
|
||||
MB_EX_SLAVE_DEVICE_FAILURE = 0x04,
|
||||
MB_EX_ACKNOWLEDGE = 0x05,
|
||||
MB_EX_SLAVE_BUSY = 0x06,
|
||||
MB_EX_MEMORY_PARITY_ERROR = 0x08,
|
||||
MB_EX_GATEWAY_PATH_FAILED = 0x0A,
|
||||
MB_EX_GATEWAY_TGT_FAILED = 0x0B
|
||||
} mb_exception_t;
|
||||
|
||||
typedef mb_exception_t (*mb_fn_handler_fp)(void *, uint8_t *frame_ptr, uint16_t *len_buf);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t func_code;
|
||||
|
@@ -15,6 +15,10 @@ extern "C" {
|
||||
mb_exception_t mbs_fn_report_slave_id(mb_base_t *inst, uint8_t *frame_ptr, uint16_t *plen_buf);
|
||||
#endif
|
||||
|
||||
// The helper function to register custom function handler for slave
|
||||
mb_err_enum_t mbs_set_handler(uint8_t func_code, mb_fn_handler_fp phandler);
|
||||
mb_err_enum_t mbs_get_handler(uint8_t func_code, mb_fn_handler_fp *phandler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -16,9 +16,15 @@
|
||||
|
||||
static const char *TAG = "mb_object.master";
|
||||
|
||||
#if (MB_MASTER_ASCII_ENABLED || MB_MASTER_RTU_ENABLED)
|
||||
|
||||
typedef struct _port_serial_opts mb_serial_opts_t;
|
||||
|
||||
#endif
|
||||
|
||||
#if (MB_MASTER_ASCII_ENABLED || MB_MASTER_RTU_ENABLED || MB_MASTER_TCP_ENABLED)
|
||||
|
||||
static const mb_fn_handler_t master_handlers[MB_FUNC_HANDLERS_MAX] =
|
||||
static mb_fn_handler_t master_handlers[MB_FUNC_HANDLERS_MAX] =
|
||||
{
|
||||
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
|
||||
{MB_FUNC_OTHER_REPORT_SLAVEID, (void *)mbm_fn_report_slave_id},
|
||||
@@ -57,7 +63,6 @@ typedef struct
|
||||
mb_base_t base;
|
||||
mb_comm_mode_t cur_mode;
|
||||
mb_state_enum_t cur_state;
|
||||
const mb_fn_handler_t *func_handlers;
|
||||
uint8_t *rcv_frame;
|
||||
uint8_t *snd_frame;
|
||||
uint16_t pdu_snd_len;
|
||||
@@ -82,7 +87,55 @@ static void mbm_set_dest_addr(mb_base_t *inst, uint8_t dest_addr);
|
||||
static uint8_t mbm_get_dest_addr(mb_base_t *inst);
|
||||
static void mbm_get_pdu_send_buf(mb_base_t *inst, uint8_t **pbuf);
|
||||
|
||||
typedef struct _port_serial_opts mb_serial_opts_t;
|
||||
static _lock_t s_mbm_lock; // lock section for command handlers
|
||||
|
||||
mb_err_enum_t mbm_set_handler(uint8_t func_code, mb_fn_handler_fp phandler)
|
||||
{
|
||||
mb_err_enum_t status = MB_EILLSTATE;
|
||||
CRITICAL_SECTION(s_mbm_lock) {
|
||||
status = mb_set_handler(&master_handlers[0], func_code, phandler);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// The helper function to register custom function handler for master
|
||||
mb_err_enum_t mbm_get_handler(uint8_t fc, mb_fn_handler_fp *phandler)
|
||||
{
|
||||
mb_err_enum_t status = MB_EINVAL;
|
||||
if (phandler) {
|
||||
CRITICAL_SECTION(s_mbm_lock) {
|
||||
status = mb_get_handler(&master_handlers[0], fc, phandler);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static mb_err_enum_t mbm_check_invoke_handler(mb_base_t *inst, uint8_t fc, uint8_t *pbuf, uint16_t *plen)
|
||||
{
|
||||
mb_exception_t exception = MB_EX_ILLEGAL_FUNCTION;
|
||||
if (!fc) {
|
||||
return MB_EX_ILLEGAL_FUNCTION;
|
||||
}
|
||||
if (fc & MB_FUNC_ERROR) {
|
||||
exception = (mb_exception_t)pbuf[MB_PDU_DATA_OFF];
|
||||
return exception;
|
||||
}
|
||||
CRITICAL_SECTION(s_mbm_lock) {
|
||||
for (int i = 0; i < MB_FUNC_HANDLERS_MAX; i++) {
|
||||
/* No more function handlers registered. Abort. */
|
||||
if (master_handlers[i].func_code == 0) {
|
||||
ESP_LOGE(TAG, MB_OBJ_FMT": function (0x%x), handler is missing.", MB_OBJ_PARENT(inst), (int)fc);
|
||||
break;
|
||||
}
|
||||
if (master_handlers[i].func_code == fc) {
|
||||
exception = master_handlers[i].handler(inst, pbuf, plen);
|
||||
ESP_LOGD(__func__, MB_OBJ_FMT": function (0x%x), invoke handler.", MB_OBJ_PARENT(inst), (int)fc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return exception;
|
||||
}
|
||||
|
||||
#if (MB_MASTER_RTU_ENABLED)
|
||||
|
||||
@@ -121,7 +174,6 @@ mb_err_enum_t mbm_rtu_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
|
||||
ret = mbm_rtu_transp_create(ser_opts, (void **)&transp_obj);
|
||||
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
|
||||
TAG, "transport creation, err: %d", (int)ret);
|
||||
mbm_obj->func_handlers = master_handlers;
|
||||
mbm_obj->cur_mode = ser_opts->mode;
|
||||
mbm_obj->cur_state = STATE_DISABLED;
|
||||
transp_obj->get_tx_frm(transp_obj, (uint8_t **)&mbm_obj->snd_frame);
|
||||
@@ -183,7 +235,6 @@ mb_err_enum_t mbm_ascii_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
|
||||
ret = mbm_ascii_transp_create(ser_opts, (void **)&transp_obj);
|
||||
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
|
||||
TAG, "transport creation, err: %d", (int)ret);
|
||||
mbm_obj->func_handlers = master_handlers;
|
||||
mbm_obj->cur_mode = ser_opts->mode;
|
||||
mbm_obj->cur_state = STATE_DISABLED;
|
||||
transp_obj->get_tx_frm(transp_obj, (uint8_t **)&mbm_obj->snd_frame);
|
||||
@@ -245,7 +296,6 @@ mb_err_enum_t mbm_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj)
|
||||
ret = mbm_tcp_transp_create(tcp_opts, (void **)&transp_obj);
|
||||
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
|
||||
TAG, "transport creation, err: %d", (int)ret);
|
||||
mbm_obj->func_handlers = master_handlers;
|
||||
mbm_obj->cur_mode = tcp_opts->mode;
|
||||
mbm_obj->cur_state = STATE_DISABLED;
|
||||
transp_obj->get_tx_frm(transp_obj, (uint8_t **)&mbm_obj->snd_frame);
|
||||
@@ -271,7 +321,7 @@ error:
|
||||
|
||||
mb_err_enum_t mbm_delete(mb_base_t *inst)
|
||||
{
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);;
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
|
||||
mb_err_enum_t status = MB_ENOERR;
|
||||
if (mbm_obj->cur_state == STATE_DISABLED) {
|
||||
if (MB_OBJ(mbm_obj->base.transp_obj)->frm_delete) {
|
||||
@@ -303,7 +353,7 @@ mb_err_enum_t mbm_delete(mb_base_t *inst)
|
||||
|
||||
mb_err_enum_t mbm_enable(mb_base_t *inst)
|
||||
{
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);;
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
|
||||
mb_err_enum_t status = MB_ENOERR;
|
||||
CRITICAL_SECTION(inst->lock)
|
||||
{
|
||||
@@ -322,7 +372,7 @@ mb_err_enum_t mbm_enable(mb_base_t *inst)
|
||||
mb_err_enum_t mbm_disable(mb_base_t *inst)
|
||||
{
|
||||
mb_err_enum_t status = MB_ENOERR;
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);;
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
|
||||
CRITICAL_SECTION(inst->lock)
|
||||
{
|
||||
if (mbm_obj->cur_state == STATE_ENABLED) {
|
||||
@@ -340,7 +390,7 @@ mb_err_enum_t mbm_disable(mb_base_t *inst)
|
||||
|
||||
static void mbm_get_pdu_send_buf(mb_base_t *inst, uint8_t **pbuf)
|
||||
{
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);;
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
|
||||
MB_OBJ(mbm_obj->base.transp_obj)->get_tx_frm(mbm_obj->base.transp_obj, pbuf);
|
||||
}
|
||||
|
||||
@@ -353,7 +403,7 @@ static void mbm_get_pdu_recv_buf(mb_base_t *inst, uint8_t **pbuf)
|
||||
|
||||
static void mbm_set_pdu_send_length(mb_base_t *inst, uint16_t length)
|
||||
{
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);;
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
|
||||
CRITICAL_SECTION(inst->lock)
|
||||
{
|
||||
mbm_obj->pdu_snd_len = length;
|
||||
@@ -362,13 +412,13 @@ static void mbm_set_pdu_send_length(mb_base_t *inst, uint16_t length)
|
||||
|
||||
static uint16_t mbm_get_pdu_send_length(mb_base_t *inst)
|
||||
{
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);;
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
|
||||
return mbm_obj->pdu_snd_len;
|
||||
}
|
||||
|
||||
static void mbm_set_dest_addr(mb_base_t *inst, uint8_t dest_addr)
|
||||
{
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);;
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
|
||||
CRITICAL_SECTION(inst->lock)
|
||||
{
|
||||
mbm_obj->master_dst_addr = dest_addr;
|
||||
@@ -377,7 +427,7 @@ static void mbm_set_dest_addr(mb_base_t *inst, uint8_t dest_addr)
|
||||
|
||||
static uint8_t mbm_get_dest_addr(mb_base_t *inst)
|
||||
{
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);;
|
||||
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
|
||||
return mbm_obj->master_dst_addr;
|
||||
}
|
||||
|
||||
@@ -496,31 +546,18 @@ mb_err_enum_t mbm_poll(mb_base_t *inst)
|
||||
ESP_LOGD(TAG, MB_OBJ_FMT":EV_EXECUTE", MB_OBJ_PARENT(inst));
|
||||
mbm_obj->func_code = mbm_obj->rcv_frame[MB_PDU_FUNC_OFF];
|
||||
exception = MB_EX_ILLEGAL_FUNCTION;
|
||||
/* If receive frame has exception. The receive function code highest bit is 1.*/
|
||||
if (mbm_obj->func_code & MB_FUNC_ERROR) {
|
||||
exception = (mb_exception_t)mbm_obj->rcv_frame[MB_PDU_DATA_OFF];
|
||||
} else {
|
||||
for (int i = 0; i < MB_FUNC_HANDLERS_MAX; i++) {
|
||||
/* No more function handlers registered. Abort. */
|
||||
if (mbm_obj->func_handlers[i].func_code == 0) {
|
||||
break;
|
||||
}
|
||||
if (mbm_obj->func_handlers[i].func_code == mbm_obj->func_code) {
|
||||
/* If master request is broadcast,
|
||||
* the master need execute function for all slave.
|
||||
*/
|
||||
if (MB_OBJ(inst->transp_obj)->frm_is_bcast(inst->transp_obj)) {
|
||||
length = mbm_obj->pdu_snd_len;
|
||||
for (int j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++) {
|
||||
mbm_set_dest_addr(inst, j);
|
||||
exception = mbm_obj->func_handlers[i].handler(inst, mbm_obj->rcv_frame, &length);
|
||||
}
|
||||
} else {
|
||||
exception = mbm_obj->func_handlers[i].handler(inst, mbm_obj->rcv_frame, &mbm_obj->pdu_rcv_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* If master request is broadcast,
|
||||
* the master need to execute function for all slaves.
|
||||
*/
|
||||
if (MB_OBJ(inst->transp_obj)->frm_is_bcast(inst->transp_obj)) {
|
||||
length = mbm_obj->pdu_snd_len;
|
||||
for (int j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++) {
|
||||
mbm_set_dest_addr(inst, j);
|
||||
exception = mbm_check_invoke_handler(inst, mbm_obj->func_code, mbm_obj->rcv_frame, &length);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGD(__func__, MB_OBJ_FMT": function (0x%x), invoke handler.", MB_OBJ_PARENT(inst), (int)mbm_obj->func_code);
|
||||
exception = mbm_check_invoke_handler(inst, mbm_obj->func_code, mbm_obj->rcv_frame, &mbm_obj->pdu_rcv_len);
|
||||
}
|
||||
/* If master has exception, will send error process event. Otherwise the master is idle.*/
|
||||
if (exception != MB_EX_NONE) {
|
||||
|
@@ -30,7 +30,6 @@ typedef struct
|
||||
// here are slave object properties and methods
|
||||
uint8_t mb_address;
|
||||
mb_comm_mode_t cur_mode;
|
||||
const mb_fn_handler_t *func_handlers;
|
||||
mb_state_enum_t cur_state;
|
||||
uint8_t *frame;
|
||||
uint16_t length;
|
||||
@@ -74,11 +73,58 @@ static mb_fn_handler_t slave_handlers[MB_FUNC_HANDLERS_MAX] =
|
||||
#endif
|
||||
};
|
||||
|
||||
static _lock_t s_mbs_lock;
|
||||
|
||||
mb_err_enum_t mbs_delete(mb_base_t *inst);
|
||||
mb_err_enum_t mbs_enable(mb_base_t *inst);
|
||||
mb_err_enum_t mbs_disable(mb_base_t *inst);
|
||||
mb_err_enum_t mbs_poll(mb_base_t *inst);
|
||||
|
||||
// The helper function to register custom function handler for slave
|
||||
mb_err_enum_t mbs_set_handler(uint8_t fc, mb_fn_handler_fp phandler)
|
||||
{
|
||||
mb_err_enum_t status = MB_EINVAL;
|
||||
CRITICAL_SECTION(s_mbs_lock) {
|
||||
status = mb_set_handler(&slave_handlers[0], fc, phandler);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// The helper function to register custom function handler for slave
|
||||
mb_err_enum_t mbs_get_handler(uint8_t fc, mb_fn_handler_fp *phandler)
|
||||
{
|
||||
mb_err_enum_t status = MB_EINVAL;
|
||||
if (phandler) {
|
||||
CRITICAL_SECTION(s_mbs_lock) {
|
||||
status = mb_get_handler(&slave_handlers[0], fc, phandler);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static mb_err_enum_t mbs_check_invoke_handler(mb_base_t *inst, uint8_t fc, uint8_t *pbuf, uint16_t *plen)
|
||||
{
|
||||
mb_exception_t exception = MB_EX_ILLEGAL_FUNCTION;
|
||||
if (!fc || (fc & MB_FUNC_ERROR)) {
|
||||
return MB_EX_ILLEGAL_FUNCTION;
|
||||
}
|
||||
CRITICAL_SECTION(s_mbs_lock) {
|
||||
for (int i = 0; i < MB_FUNC_HANDLERS_MAX; i++) {
|
||||
/* No more function handlers registered. Abort. */
|
||||
if (slave_handlers[i].func_code == 0) {
|
||||
ESP_LOGD(TAG, MB_OBJ_FMT": function (0x%x), handler is missing.", MB_OBJ_PARENT(inst), (int)fc);
|
||||
break;
|
||||
}
|
||||
if (slave_handlers[i].func_code == fc) {
|
||||
exception = slave_handlers[i].handler(inst, pbuf, plen);
|
||||
ESP_LOGD(TAG, MB_OBJ_FMT": function (0x%x), invoke handler.", MB_OBJ_PARENT(inst), (int)fc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return exception;
|
||||
}
|
||||
|
||||
#if (MB_SLAVE_RTU_ENABLED)
|
||||
|
||||
mb_err_enum_t mbs_rtu_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
|
||||
@@ -111,7 +157,6 @@ mb_err_enum_t mbs_rtu_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
|
||||
ret = mbs_rtu_transp_create(ser_opts, (void **)&transp_obj);
|
||||
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
|
||||
TAG, "transport creation, err: %d", (int)ret);
|
||||
mbs_obj->func_handlers = slave_handlers;
|
||||
mbs_obj->cur_mode = ser_opts->mode;
|
||||
mbs_obj->mb_address = ser_opts->uid;
|
||||
mbs_obj->cur_state = STATE_DISABLED;
|
||||
@@ -166,7 +211,6 @@ mb_err_enum_t mbs_ascii_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
|
||||
ret = mbs_ascii_transp_create(ser_opts, (void **)&transp_obj);
|
||||
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
|
||||
TAG, "transport creation, err: %d", (int)ret);
|
||||
mbs_obj->func_handlers = slave_handlers;
|
||||
mbs_obj->cur_mode = ser_opts->mode;
|
||||
mbs_obj->mb_address = ser_opts->uid;
|
||||
mbs_obj->cur_state = STATE_DISABLED;
|
||||
@@ -222,7 +266,6 @@ mb_err_enum_t mbs_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj)
|
||||
ret = mbs_tcp_transp_create(tcp_opts, (void **)&transp_obj);
|
||||
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
|
||||
TAG, "transport creation, err: %d", (int)ret);
|
||||
mbs_obj->func_handlers = slave_handlers;
|
||||
mbs_obj->cur_mode = tcp_opts->mode;
|
||||
mbs_obj->mb_address = tcp_opts->uid;
|
||||
mbs_obj->cur_state = STATE_DISABLED;
|
||||
@@ -358,20 +401,7 @@ mb_err_enum_t mbs_poll(mb_base_t *inst)
|
||||
MB_RETURN_ON_FALSE(mbs_obj->frame, MB_EILLSTATE, TAG, "receive buffer fail.");
|
||||
ESP_LOGD(TAG, MB_OBJ_FMT":EV_EXECUTE", MB_OBJ_PARENT(inst));
|
||||
mbs_obj->func_code = mbs_obj->frame[MB_PDU_FUNC_OFF];
|
||||
exception = MB_EX_ILLEGAL_FUNCTION;
|
||||
// If receive frame has exception. The receive function code highest bit is 1.
|
||||
for (int i = 0; (i < MB_FUNC_HANDLERS_MAX); i++) {
|
||||
// No more function handlers registered. Abort.
|
||||
if (mbs_obj->func_handlers[i].func_code == 0) {
|
||||
ESP_LOGD(TAG, MB_OBJ_FMT": function (0x%x), handler is not found.", MB_OBJ_PARENT(inst), (int)mbs_obj->func_code);
|
||||
break;
|
||||
}
|
||||
if ((mbs_obj->func_handlers[i].func_code) == mbs_obj->func_code) {
|
||||
ESP_LOGD(TAG, MB_OBJ_FMT": function (0x%x), start handler.", MB_OBJ_PARENT(inst), (int)mbs_obj->func_code);
|
||||
exception = mbs_obj->func_handlers[i].handler(inst, mbs_obj->frame, &mbs_obj->length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
exception = mbs_check_invoke_handler(inst, mbs_obj->func_code, mbs_obj->frame, &mbs_obj->length);
|
||||
// If the request was not sent to the broadcast address, return a reply.
|
||||
if ((mbs_obj->rcv_addr != MB_ADDRESS_BROADCAST) || (mbs_obj->cur_mode == MB_TCP)) {
|
||||
if (exception != MB_EX_NONE) {
|
||||
|
@@ -29,6 +29,7 @@ extern "C"
|
||||
#define MB_EVENT_QUEUE_TIMEOUT_MAX_MS (3000)
|
||||
#define MB_EVENT_QUEUE_TIMEOUT (pdMS_TO_TICKS(CONFIG_FMB_EVENT_QUEUE_TIMEOUT))
|
||||
#define MB_EVENT_QUEUE_TIMEOUT_MAX (pdMS_TO_TICKS(MB_EVENT_QUEUE_TIMEOUT_MAX_MS))
|
||||
#define MB_MS_TO_TICKS(time_ms) ((TickType_t)(((time_ms)/portTICK_PERIOD_MS)))
|
||||
|
||||
int lock_obj(_lock_t *plock);
|
||||
void unlock_obj(_lock_t *plock);
|
||||
|
Reference in New Issue
Block a user