mb master, slave add custom fc handlers

This commit is contained in:
aleks
2025-03-10 16:09:03 +01:00
parent a54f11355c
commit fc8fc06fc5
23 changed files with 438 additions and 84 deletions
+7 -1
View File
@@ -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);
+1 -1
View File
@@ -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.
+2
View File
@@ -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
+8 -1
View File
@@ -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
-125
View File
@@ -1,125 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "mb_config.h"
#include "mb_types.h"
#if __has_include("esp_idf_version.h")
#include "esp_idf_version.h"
#endif
// Workaround for atomics incompatibility issue under CPP.
#if defined(__cplusplus) && (IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 0, 0))
#include <atomic>
#define _Atomic(T) std::atomic<T>
#define atomic_int int
#else
#include <stdatomic.h>
#endif
#if defined(__cplusplus)
extern "C" {
#else
// This is to verify the atomic int types for C compilation unit have the same layout as int type.
static_assert(
(sizeof(_Atomic(int)) == sizeof(int) && sizeof(_Atomic int) == sizeof(int)),
"the _Atomic int types are not layout compatible with int type"
);
#endif
#define MB_ATTR_WEAK __attribute__ ((weak))
typedef enum _mb_comm_mode mb_mode_type_t;
#if (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)
#include "driver/uart.h"
struct _port_serial_opts {
mb_mode_type_t mode; /*!< Modbus communication mode */
uart_port_t port; /*!< Modbus communication port (UART) number */
uint8_t uid; /*!< Modbus slave address field (dummy for master) */
uint32_t response_tout_ms; /*!< Modbus slave response timeout */
uint64_t test_tout_us; /*!< Modbus test timeout (reserved) */
uint32_t baudrate; /*!< Modbus baudrate */
uart_word_length_t data_bits; /*!< Modbus number of data bits */
uart_stop_bits_t stop_bits; /*!< Modbus number of stop bits */
uart_parity_t parity; /*!< Modbus UART parity settings */
} __attribute__((__packed__));
typedef struct _port_serial_opts mb_serial_opts_t;
#endif
typedef enum _addr_type_enum {
MB_NOIP = 0,
MB_IPV4 = 1, /*!< TCP IPV4 addressing */
MB_IPV6 = 2 /*!< TCP IPV6 addressing */
} mb_addr_type_t;
struct _port_common_opts {
mb_mode_type_t mode; /*!< Modbus communication mode */
uint16_t port; /*!< Modbus communication port (UART) number */
uint8_t uid; /*!< Modbus slave address field (dummy for master) */
uint32_t response_tout_ms; /*!< Modbus slave response timeout */
uint64_t test_tout_us; /*!< Modbus test timeout (reserved) */
} __attribute__((__packed__));
struct _port_tcp_opts {
mb_mode_type_t mode; /*!< Modbus communication mode */
uint16_t port; /*!< Modbus communication port (UART) number */
uint8_t uid; /*!< Modbus slave address field (dummy for master) */
uint32_t response_tout_ms; /*!< Modbus slave response timeout */
uint64_t test_tout_us; /*!< Modbus test timeout (reserved) */
mb_addr_type_t addr_type; /*!< Modbus address type */
void *ip_addr_table; /*!< Modbus address or table for connection */
void *ip_netif_ptr; /*!< Modbus network interface */
char *dns_name; /*!< Modbus node DNS name */
bool start_disconnected; /*!< (Master only option) do not wait for connection to all nodes before polling */
} __attribute__((__packed__));
typedef struct _port_tcp_opts mb_tcp_opts_t;
// The common object descriptor struture (common for mb, transport, port objects)
struct _obj_descr {
char *parent_name; /*!< Name of the parent (base) object */
char *obj_name; /*!< Name of the object */
void *parent; /*!< Pointer to the parent (base) object */
uint32_t inst_index; /*!< The consicutive index of the object instance */
bool is_master; /*!< The current object is master or slave (false) */
};
typedef struct _obj_descr obj_descr_t;
typedef enum _mb_sock_state {
MB_SOCK_STATE_UNDEF = 0x0000, /*!< Default init state */
MB_SOCK_STATE_CLOSED, /*!< Node is closed */
MB_SOCK_STATE_READY, /*!< Node is ready for communication */
MB_SOCK_STATE_OPENED, /*!< Node is opened */
MB_SOCK_STATE_RESOLVED, /*!< Node address is resolved */
MB_SOCK_STATE_CONNECTING, /*!< Node connection is in progress */
MB_SOCK_STATE_CONNECTED, /*!< Node is connected */
MB_SOCK_STATE_ACCEPTED /*!< Slave node accepted the connection */
} mb_sock_state_t;
typedef struct _uid_info {
uint16_t index; /*!< index of the address info */
int fd; /*!< node global FD for VFS (reserved) */
char *node_name_str; /*!< node name string (host name of node to resolve) */
char *ip_addr_str; /*!< represents the IP address of the node */
mb_addr_type_t addr_type; /*!< type of IP address */
uint16_t uid; /*!< node unit ID (UID) field for MBAP frame */
uint16_t port; /*!< node port number */
mb_comm_mode_t proto; /*!< protocol type */
_Atomic(int) state; /*!< node state */
void *inst; /*!< pointer to linked instance */
} mb_uid_info_t;
#ifdef __cplusplus
}
#endif
-16
View File
@@ -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;
+4
View File
@@ -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
-141
View File
@@ -1,141 +0,0 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "stdbool.h"
#include "stdint.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ----------------------- Type definitions ---------------------------------*/
/*! \ingroup modbus
* \brief Modbus serial transmission modes (RTU/ASCII/TCP/UDP).
*
* Modbus serial supports two transmission modes. Either ASCII or RTU. RTU
* is faster but has more hardware requirements and requires a network with
* a low jitter. ASCII is slower and more reliable on slower links (E.g. modems)
* The TCP or UDP mode is used for communication over ethernet.
*/
typedef enum _mb_comm_mode
{
MB_RTU, /*!< RTU transmission mode. */
MB_ASCII, /*!< ASCII transmission mode. */
MB_TCP, /*!< TCP mode. */
MB_UDP /*!< UDP mode. */
} mb_comm_mode_t;
/*! \ingroup modbus
* \brief If register should be written or read.
*
* This value is passed to the callback functions which support either
* reading or writing register values. Writing means that the application
* registers should be updated and reading means that the modbus protocol
* stack needs to know the current register values.
*
* \see mbs_reg_holding_cb(), mbs_reg_coils_cb(), mbs_reg_holding_cb() and
* mbs_reg_input_cb().
*/
typedef enum
{
MB_REG_READ = 0x0001, /*!< Read register values and pass to protocol stack. */
MB_REG_WRITE = 0x0002, /*!< Update register values. */
} mb_reg_mode_enum_t;
/*! \ingroup modbus
* \brief Event types used by all function in the protocol stack.
*/
typedef enum _mb_event_enum {
EV_TRANS_START = 0x0001, /*!< Start of transaction. */
EV_READY = 0x0002, /*!< Startup finished. */
EV_FRAME_RECEIVED = 0x0004, /*!< Frame received. */
EV_EXECUTE = 0x0008, /*!< Execute function. */
EV_FRAME_TRANSMIT = 0x0010, /*!< Transmission started . */
EV_FRAME_SENT = 0x0020, /*!< Frame sent. */
EV_ERROR_PROCESS = 0x0040, /*!< Error process state. */
EV_MASTER_ERROR_RESPOND_TIMEOUT = 0x0080, /*!< Request respond timeout. */
EV_MASTER_ERROR_RECEIVE_DATA = 0x0100, /*!< Request receive data error. */
EV_MASTER_ERROR_EXECUTE_FUNCTION = 0x0200, /*!< Request execute function error. */
EV_MASTER_PROCESS_SUCCESS = 0x0400 /*!< Master error process. */
} mb_event_enum_t;
/*! \ingroup modbus
* \brief Error event type
*/
typedef enum _mb_err_event_enum {
EV_ERROR_INIT, /*!< No error, initial state. */
EV_ERROR_RESPOND_TIMEOUT, /*!< Slave respond timeout. */
EV_ERROR_RECEIVE_DATA, /*!< Receive frame data error. */
EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */
EV_ERROR_OK /*!< No error, processing completed. */
} mb_err_event_t;
typedef struct _mb_event_t {
mb_event_enum_t event; /*!< event itself. */
uint64_t trans_id; /*!< unique transaction id */
uint16_t length; /*!< length of data accociated with the event */
void *pdata; /*!< data accociated with the event */
mb_err_event_t type; /*!< error type accociated with the event */
uint64_t post_ts; /*!< timestamp of event posted */
uint64_t get_ts; /*!< timestamp of event receved */
} mb_event_t;
/*! \ingroup modbus
* \brief Errorcodes used by all function in the protocol stack.
*/
typedef enum
{
MB_ENOERR, /*!< no error. */
MB_ENOREG, /*!< illegal register address. */
MB_EINVAL, /*!< illegal argument. */
MB_EPORTERR, /*!< porting layer error. */
MB_ENORES, /*!< insufficient resources. */
MB_EIO, /*!< I/O error. */
MB_EILLSTATE, /*!< protocol stack in illegal state. */
MB_ERECVDATA, /*!< receive data error. */
MB_ETIMEDOUT, /*!< timeout error occurred. */
MB_EILLFUNC, /*!< illegal MB function. */
MB_EBUSY, /*!< master is busy now. */
MB_ENOCONN /*!< peer is not connected. */
} mb_err_enum_t;
/*! \ingroup modbus
* \brief TimerMode is Master 3 kind of Timer modes.
*/
typedef enum
{
MB_TMODE_T35, /*!< Master receive frame T3.5 timeout. */
MB_TMODE_RESPOND_TIMEOUT, /*!< Master wait respond for slave. */
MB_TMODE_CONVERT_DELAY /*!< Master sent broadcast , then delay sometime.*/
} mb_timer_mode_enum_t;
#ifdef __cplusplus
}
#endif