mirror of
https://github.com/espressif/esp-modbus.git
synced 2025-07-31 02:47:16 +02:00
Merge branch 'feature/add_slave_id_command' into 'master'
add the command 0x11 - get slave info Closes IDFGH-13856 See merge request idf/esp-modbus!82
This commit is contained in:
11
Kconfig
11
Kconfig
@ -58,7 +58,7 @@ menu "Modbus configuration"
|
|||||||
config FMB_MASTER_TIMEOUT_MS_RESPOND
|
config FMB_MASTER_TIMEOUT_MS_RESPOND
|
||||||
int "Slave respond timeout (Milliseconds)"
|
int "Slave respond timeout (Milliseconds)"
|
||||||
default 3000
|
default 3000
|
||||||
range 150 15000
|
range 300 15000
|
||||||
help
|
help
|
||||||
If master sends a frame which is not broadcast, it has to wait sometime for slave response.
|
If master sends a frame which is not broadcast, it has to wait sometime for slave response.
|
||||||
if slave is not respond in this time, the master will process timeout error.
|
if slave is not respond in this time, the master will process timeout error.
|
||||||
@ -171,6 +171,15 @@ menu "Modbus configuration"
|
|||||||
Most significant byte of ID is used as short device ID and
|
Most significant byte of ID is used as short device ID and
|
||||||
other three bytes used as long ID.
|
other three bytes used as long ID.
|
||||||
|
|
||||||
|
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_CONTROLLER_NOTIFY_TIMEOUT
|
config FMB_CONTROLLER_NOTIFY_TIMEOUT
|
||||||
int "Modbus controller notification timeout (ms)"
|
int "Modbus controller notification timeout (ms)"
|
||||||
range 0 200
|
range 0 200
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
#include "esp_err.h" // for esp_err_t
|
#include "esp_err.h" // for esp_err_t
|
||||||
#include "mbc_master.h" // for master interface define
|
#include "mbc_master.h" // for master interface define
|
||||||
#include "esp_modbus_master.h" // for public interface defines
|
#include "esp_modbus_master.h" // for public interface defines
|
||||||
@ -237,6 +238,29 @@ eMBErrorCode eMBMasterRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eMBErrorCode eMBMasterRegCommonCB(UCHAR * pucData, USHORT usAddress,
|
||||||
|
USHORT usBytes)
|
||||||
|
{
|
||||||
|
MB_MASTER_CHECK((master_interface_ptr != NULL),
|
||||||
|
MB_EILLSTATE,
|
||||||
|
"Master interface is not correctly initialized.");
|
||||||
|
MB_MASTER_CHECK((master_interface_ptr != NULL),
|
||||||
|
MB_EILLSTATE,
|
||||||
|
"Master interface uninitialized.");
|
||||||
|
MB_MASTER_CHECK(pucData, MB_EINVAL,
|
||||||
|
"Master stack processing error.");
|
||||||
|
mb_master_options_t* popts = &master_interface_ptr->opts;
|
||||||
|
USHORT usRegLen = (USHORT)popts->mbm_reg_buffer_size;
|
||||||
|
UCHAR* pucParBuffer = (UCHAR*)popts->mbm_reg_buffer_ptr; // Get instance address
|
||||||
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
if (pucParBuffer && !usAddress && (usBytes >= 1) && (((usRegLen << 1) >= usBytes))){
|
||||||
|
memmove(pucParBuffer, pucData, MIN((usRegLen << 1), usBytes));
|
||||||
|
} else {
|
||||||
|
eStatus = MB_ENOREG;
|
||||||
|
}
|
||||||
|
return eStatus;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to get current transaction info
|
* Helper function to get current transaction info
|
||||||
*/
|
*/
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "freertos/FreeRTOS.h" // for task creation and queue access
|
#include "freertos/FreeRTOS.h" // for task creation and queue access
|
||||||
#include "freertos/task.h" // for task api access
|
#include "freertos/task.h" // for task api access
|
||||||
#include "freertos/event_groups.h" // for event groups
|
#include "freertos/event_groups.h" // for event groups
|
||||||
|
#include "freertos/semphr.h" // for semaphore
|
||||||
#include "driver/uart.h" // for UART types
|
#include "driver/uart.h" // for UART types
|
||||||
#include "errno.h" // for errno
|
#include "errno.h" // for errno
|
||||||
#include "esp_log.h" // for log write
|
#include "esp_log.h" // for log write
|
||||||
@ -64,6 +65,7 @@ typedef struct {
|
|||||||
uint16_t mbm_reg_buffer_size; /*!< Modbus data buffer size */
|
uint16_t mbm_reg_buffer_size; /*!< Modbus data buffer size */
|
||||||
TaskHandle_t mbm_task_handle; /*!< Modbus task handle */
|
TaskHandle_t mbm_task_handle; /*!< Modbus task handle */
|
||||||
EventGroupHandle_t mbm_event_group; /*!< Modbus controller event group */
|
EventGroupHandle_t mbm_event_group; /*!< Modbus controller event group */
|
||||||
|
SemaphoreHandle_t mbm_sema; /*!< Modbus controller semaphore */
|
||||||
const mb_parameter_descriptor_t* mbm_param_descriptor_table; /*!< Modbus controller parameter description table */
|
const mb_parameter_descriptor_t* mbm_param_descriptor_table; /*!< Modbus controller parameter description table */
|
||||||
size_t mbm_param_descriptor_size; /*!< Modbus controller parameter description table size*/
|
size_t mbm_param_descriptor_size; /*!< Modbus controller parameter description table size*/
|
||||||
#if MB_MASTER_TCP_ENABLED
|
#if MB_MASTER_TCP_ENABLED
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
/* ----------------------- Modbus includes ----------------------------------*/
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
#include "mb.h"
|
#include "mb.h"
|
||||||
|
#include "mb_m.h"
|
||||||
#include "mbframe.h"
|
#include "mbframe.h"
|
||||||
#include "mbproto.h"
|
#include "mbproto.h"
|
||||||
#include "mbconfig.h"
|
#include "mbconfig.h"
|
||||||
@ -52,11 +53,61 @@
|
|||||||
|
|
||||||
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
|
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
|
||||||
|
|
||||||
|
#define MB_PDU_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 )
|
||||||
|
#define MB_PDU_FUNC_DATA_OFF ( MB_PDU_DATA_OFF + 1 )
|
||||||
|
|
||||||
/* ----------------------- Static variables ---------------------------------*/
|
/* ----------------------- Static variables ---------------------------------*/
|
||||||
static UCHAR ucMBSlaveID[MB_FUNC_OTHER_REP_SLAVEID_BUF];
|
static UCHAR ucMBSlaveID[MB_FUNC_OTHER_REP_SLAVEID_BUF] = {0};
|
||||||
static USHORT usMBSlaveIDLen;
|
static USHORT usMBSlaveIDLen;
|
||||||
|
|
||||||
/* ----------------------- Start implementation -----------------------------*/
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
|
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
|
||||||
|
|
||||||
|
eMBMasterReqErrCode
|
||||||
|
eMBMasterReqReportSlaveID( UCHAR ucSndAddr, LONG lTimeOut )
|
||||||
|
{
|
||||||
|
UCHAR *ucMBFrame;
|
||||||
|
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
|
||||||
|
|
||||||
|
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
|
||||||
|
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vMBMasterGetPDUSndBuf(&ucMBFrame);
|
||||||
|
vMBMasterSetDestAddress(ucSndAddr);
|
||||||
|
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_OTHER_REPORT_SLAVEID;
|
||||||
|
vMBMasterSetPDUSndLength( 1 );
|
||||||
|
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
|
||||||
|
eErrStatus = eMBMasterWaitRequestFinish( );
|
||||||
|
}
|
||||||
|
return eErrStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
eMBException
|
||||||
|
eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
|
||||||
|
{
|
||||||
|
UCHAR ucByteCount = 0;
|
||||||
|
eMBException eStatus = MB_EX_NONE;
|
||||||
|
eMBErrorCode eRegStatus;
|
||||||
|
|
||||||
|
if( *usLen <= ( MB_FUNC_OTHER_REP_SLAVEID_BUF - 2 ) )
|
||||||
|
{
|
||||||
|
ucByteCount = ( UCHAR )( pucFrame[MB_PDU_BYTECNT_OFF] );
|
||||||
|
// Transfer data from command buffer.
|
||||||
|
eRegStatus = eMBMasterRegCommonCB( &pucFrame[MB_PDU_FUNC_DATA_OFF], 0, ucByteCount);
|
||||||
|
/* If an error occured convert it into a Modbus exception. */
|
||||||
|
if( eRegStatus != MB_ENOERR )
|
||||||
|
{
|
||||||
|
eStatus = prveMBError2Exception( eRegStatus );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Can't be a valid request because the length is incorrect. */
|
||||||
|
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
|
||||||
|
}
|
||||||
|
return eStatus;
|
||||||
|
}
|
||||||
|
|
||||||
eMBErrorCode
|
eMBErrorCode
|
||||||
eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,
|
eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,
|
||||||
@ -86,11 +137,13 @@ eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,
|
|||||||
return eStatus;
|
return eStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pucFrame points to Modbus PDU
|
||||||
eMBException
|
eMBException
|
||||||
eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
|
eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
|
||||||
{
|
{
|
||||||
memcpy( &pucFrame[MB_PDU_DATA_OFF], &ucMBSlaveID[0], ( size_t )usMBSlaveIDLen );
|
memcpy( &pucFrame[MB_PDU_FUNC_DATA_OFF], &ucMBSlaveID[0], ( size_t )usMBSlaveIDLen );
|
||||||
*usLen = ( USHORT )( MB_PDU_DATA_OFF + usMBSlaveIDLen );
|
*usLen = ( USHORT )( MB_PDU_FUNC_DATA_OFF + usMBSlaveIDLen );
|
||||||
|
pucFrame[MB_PDU_BYTECNT_OFF] = usMBSlaveIDLen;
|
||||||
return MB_EX_NONE;
|
return MB_EX_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +258,24 @@ eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode,
|
|||||||
* to update the application register values.
|
* to update the application register values.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*! \ingroup modbus_registers
|
||||||
|
* \brief The common callback function used to transfer common data as bytes
|
||||||
|
* from command buffer in little endian format.
|
||||||
|
*
|
||||||
|
* \param pucData A pointer to data in command buffer to be transferred.
|
||||||
|
* \param usAddress Unused for this function == 0.
|
||||||
|
* \param usBytes Number of bytes the callback function must supply.
|
||||||
|
*
|
||||||
|
* \return The function must return one of the following error codes:
|
||||||
|
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
|
||||||
|
* Modbus response is sent.
|
||||||
|
* - eMBErrorCode::MB_ENOREG if can not map the data of the registers
|
||||||
|
* - eMBErrorCode::MB_EILLSTATE if can not procceed with data transfer due to critical error
|
||||||
|
* - eMBErrorCode::MB_EINVAL if value data can not be transferred
|
||||||
|
*/
|
||||||
|
eMBErrorCode eMBMasterRegCommonCB( UCHAR * pucData, USHORT usAddress,
|
||||||
|
USHORT usBytes );
|
||||||
|
|
||||||
/*! \ingroup modbus_registers
|
/*! \ingroup modbus_registers
|
||||||
* \brief Callback function used if the value of a <em>Input Register</em>
|
* \brief Callback function used if the value of a <em>Input Register</em>
|
||||||
* is required by the protocol stack. The starting register address is given
|
* is required by the protocol stack. The starting register address is given
|
||||||
@ -273,9 +291,9 @@ eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode,
|
|||||||
* \return The function must return one of the following error codes:
|
* \return The function must return one of the following error codes:
|
||||||
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
|
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
|
||||||
* Modbus response is sent.
|
* Modbus response is sent.
|
||||||
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
|
* - eMBErrorCode::MB_ENOREG if can not map the data of the registers
|
||||||
* within the requested address range. In this case a
|
* - eMBErrorCode::MB_EILLSTATE if can not procceed with data transfer due to critical error
|
||||||
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
|
* - eMBErrorCode::MB_EINVAL if value data can not be transferred
|
||||||
*/
|
*/
|
||||||
eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,
|
eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,
|
||||||
USHORT usNRegs );
|
USHORT usNRegs );
|
||||||
@ -365,6 +383,8 @@ eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress,
|
|||||||
*\brief These Modbus functions are called for user when Modbus run in Master Mode.
|
*\brief These Modbus functions are called for user when Modbus run in Master Mode.
|
||||||
*/
|
*/
|
||||||
eMBMasterReqErrCode
|
eMBMasterReqErrCode
|
||||||
|
eMBMasterReqReportSlaveID( UCHAR ucSndAddr, LONG lTimeOut );
|
||||||
|
eMBMasterReqErrCode
|
||||||
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
|
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
|
||||||
eMBMasterReqErrCode
|
eMBMasterReqErrCode
|
||||||
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut );
|
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut );
|
||||||
|
@ -144,7 +144,7 @@ PR_BEGIN_EXTERN_C
|
|||||||
* how to set this value. It is only used if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
|
* how to set this value. It is only used if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
|
||||||
* is set to <code>1</code>.
|
* is set to <code>1</code>.
|
||||||
*/
|
*/
|
||||||
#define MB_FUNC_OTHER_REP_SLAVEID_BUF ( 32 )
|
#define MB_FUNC_OTHER_REP_SLAVEID_BUF ( CONFIG_FMB_CONTROLLER_SLAVE_ID_MAX_SIZE )
|
||||||
|
|
||||||
/*! \brief If the <em>Report Slave ID</em> function should be enabled. */
|
/*! \brief If the <em>Report Slave ID</em> function should be enabled. */
|
||||||
#define MB_FUNC_OTHER_REP_SLAVEID_ENABLED ( CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT )
|
#define MB_FUNC_OTHER_REP_SLAVEID_ENABLED ( CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT )
|
||||||
|
@ -129,7 +129,7 @@ BOOL( *pxMBMasterFrameCBTransmitFSMCur ) ( void );
|
|||||||
*/
|
*/
|
||||||
static xMBFunctionHandler xMasterFuncHandlers[MB_FUNC_HANDLERS_MAX] = {
|
static xMBFunctionHandler xMasterFuncHandlers[MB_FUNC_HANDLERS_MAX] = {
|
||||||
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0
|
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0
|
||||||
{MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID},
|
{MB_FUNC_OTHER_REPORT_SLAVEID, eMBMasterFuncReportSlaveID},
|
||||||
#endif
|
#endif
|
||||||
#if MB_FUNC_READ_INPUT_ENABLED > 0
|
#if MB_FUNC_READ_INPUT_ENABLED > 0
|
||||||
{MB_FUNC_READ_INPUT_REGISTER, eMBMasterFuncReadInputRegister},
|
{MB_FUNC_READ_INPUT_REGISTER, eMBMasterFuncReadInputRegister},
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "freertos/task.h" // for task api access
|
#include "freertos/task.h" // for task api access
|
||||||
#include "freertos/event_groups.h" // for event groups
|
#include "freertos/event_groups.h" // for event groups
|
||||||
#include "freertos/queue.h" // for queue api access
|
#include "freertos/queue.h" // for queue api access
|
||||||
|
#include "freertos/semphr.h" // for semaphore
|
||||||
#include "mb_m.h" // for modbus stack master types definition
|
#include "mb_m.h" // for modbus stack master types definition
|
||||||
#include "port.h" // for port callback functions
|
#include "port.h" // for port callback functions
|
||||||
#include "mbutils.h" // for mbutils functions definition for stack callback
|
#include "mbutils.h" // for mbutils functions definition for stack callback
|
||||||
@ -28,7 +29,7 @@ extern BOOL xMBMasterPortSerialTxPoll(void);
|
|||||||
|
|
||||||
/*-----------------------Master mode use these variables----------------------*/
|
/*-----------------------Master mode use these variables----------------------*/
|
||||||
// Actual wait time depends on the response timer
|
// Actual wait time depends on the response timer
|
||||||
#define MB_SERIAL_API_RESP_TICS (pdMS_TO_TICKS(MB_MAX_RESPONSE_TIME_MS))
|
#define MB_SERIAL_API_RESP_TICS (pdMS_TO_TICKS(MB_MAX_RESPONSE_TIME_MS))
|
||||||
|
|
||||||
static mb_master_interface_t* mbm_interface_ptr = NULL;
|
static mb_master_interface_t* mbm_interface_ptr = NULL;
|
||||||
static const char *TAG = "MB_CONTROLLER_MASTER";
|
static const char *TAG = "MB_CONTROLLER_MASTER";
|
||||||
@ -127,6 +128,8 @@ static esp_err_t mbc_serial_master_destroy(void)
|
|||||||
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack disable failure.");
|
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack disable failure.");
|
||||||
(void)vTaskDelete(mbm_opts->mbm_task_handle);
|
(void)vTaskDelete(mbm_opts->mbm_task_handle);
|
||||||
(void)vEventGroupDelete(mbm_opts->mbm_event_group);
|
(void)vEventGroupDelete(mbm_opts->mbm_event_group);
|
||||||
|
vSemaphoreDelete(mbm_opts->mbm_sema);
|
||||||
|
mbm_opts->mbm_sema = NULL;
|
||||||
mb_error = eMBMasterClose();
|
mb_error = eMBMasterClose();
|
||||||
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
||||||
"mb stack close failure returned (0x%x).", (int)mb_error);
|
"mb stack close failure returned (0x%x).", (int)mb_error);
|
||||||
@ -176,22 +179,22 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi
|
|||||||
eMBMasterReqErrCode mb_error = MB_MRE_MASTER_BUSY;
|
eMBMasterReqErrCode mb_error = MB_MRE_MASTER_BUSY;
|
||||||
esp_err_t error = ESP_FAIL;
|
esp_err_t error = ESP_FAIL;
|
||||||
|
|
||||||
if (xMBMasterRunResTake(MB_SERIAL_API_RESP_TICS)) {
|
if (xSemaphoreTake(mbm_opts->mbm_sema, MB_SERIAL_API_RESP_TICS) == pdTRUE) {
|
||||||
|
|
||||||
uint8_t mb_slave_addr = request->slave_addr;
|
uint8_t mb_slave_addr = request->slave_addr;
|
||||||
uint8_t mb_command = request->command;
|
uint8_t mb_command = request->command;
|
||||||
uint16_t mb_offset = request->reg_start;
|
uint16_t mb_offset = request->reg_start;
|
||||||
uint16_t mb_size = request->reg_size;
|
uint16_t mb_size = request->reg_size;
|
||||||
|
|
||||||
// Set the buffer for callback function processing of received data
|
// Set the buffer for callback function processing of received data
|
||||||
mbm_opts->mbm_reg_buffer_ptr = (uint8_t*)data_ptr;
|
mbm_opts->mbm_reg_buffer_ptr = (uint8_t*)data_ptr;
|
||||||
mbm_opts->mbm_reg_buffer_size = mb_size;
|
mbm_opts->mbm_reg_buffer_size = mb_size;
|
||||||
|
|
||||||
vMBMasterRunResRelease();
|
|
||||||
|
|
||||||
// Calls appropriate request function to send request and waits response
|
// Calls appropriate request function to send request and waits response
|
||||||
switch(mb_command)
|
switch(mb_command)
|
||||||
{
|
{
|
||||||
|
case MB_FUNC_OTHER_REPORT_SLAVEID:
|
||||||
|
mb_error = eMBMasterReqReportSlaveID((UCHAR)mb_slave_addr, (LONG)MB_SERIAL_API_RESP_TICS );
|
||||||
|
break;
|
||||||
case MB_FUNC_READ_COILS:
|
case MB_FUNC_READ_COILS:
|
||||||
mb_error = eMBMasterReqReadCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset,
|
mb_error = eMBMasterReqReadCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset,
|
||||||
(USHORT)mb_size , (LONG)MB_SERIAL_API_RESP_TICS );
|
(USHORT)mb_size , (LONG)MB_SERIAL_API_RESP_TICS );
|
||||||
@ -216,7 +219,6 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi
|
|||||||
mb_error = eMBMasterReqWriteHoldingRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset,
|
mb_error = eMBMasterReqWriteHoldingRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset,
|
||||||
*(USHORT*)data_ptr, (LONG)MB_SERIAL_API_RESP_TICS );
|
*(USHORT*)data_ptr, (LONG)MB_SERIAL_API_RESP_TICS );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
|
case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
|
||||||
mb_error = eMBMasterReqWriteMultipleHoldingRegister( (UCHAR)mb_slave_addr,
|
mb_error = eMBMasterReqWriteMultipleHoldingRegister( (UCHAR)mb_slave_addr,
|
||||||
(USHORT)mb_offset, (USHORT)mb_size,
|
(USHORT)mb_offset, (USHORT)mb_size,
|
||||||
@ -237,6 +239,8 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi
|
|||||||
mb_error = MB_MRE_NO_REG;
|
mb_error = MB_MRE_NO_REG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "%s:MBC semaphore take fail.", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propagate the Modbus errors to higher level
|
// Propagate the Modbus errors to higher level
|
||||||
@ -264,11 +268,13 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ESP_LOGE(TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, (int)mb_error);
|
ESP_LOGE(TAG, "%s: Incorrect return code (0x%x) ", __FUNCTION__, (int)mb_error);
|
||||||
error = ESP_FAIL;
|
error = ESP_FAIL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(void)xSemaphoreGive( mbm_opts->mbm_sema );
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +514,7 @@ eMBErrorCode eMBRegInputCBSerialMaster(UCHAR * pucRegBuffer, USHORT usAddress,
|
|||||||
// If input or configuration parameters are incorrect then return an error to stack layer
|
// If input or configuration parameters are incorrect then return an error to stack layer
|
||||||
if ((pucInputBuffer != NULL)
|
if ((pucInputBuffer != NULL)
|
||||||
&& (usNRegs >= 1)
|
&& (usNRegs >= 1)
|
||||||
&& (usRegInputNregs == usRegs)) {
|
&& ((usRegInputNregs == usRegs) || (!usAddress))) {
|
||||||
while (usRegs > 0) {
|
while (usRegs > 0) {
|
||||||
_XFER_2_RD(pucInputBuffer, pucRegBuffer);
|
_XFER_2_RD(pucInputBuffer, pucRegBuffer);
|
||||||
usRegs -= 1;
|
usRegs -= 1;
|
||||||
@ -698,6 +704,10 @@ esp_err_t mbc_serial_master_create(void** handler)
|
|||||||
mbm_opts->mbm_event_group = xEventGroupCreate();
|
mbm_opts->mbm_event_group = xEventGroupCreate();
|
||||||
MB_MASTER_CHECK((mbm_opts->mbm_event_group != NULL),
|
MB_MASTER_CHECK((mbm_opts->mbm_event_group != NULL),
|
||||||
ESP_ERR_NO_MEM, "mb event group error.");
|
ESP_ERR_NO_MEM, "mb event group error.");
|
||||||
|
mbm_opts->mbm_sema = xSemaphoreCreateBinary();
|
||||||
|
MB_MASTER_CHECK((mbm_opts->mbm_sema != NULL), ESP_ERR_NO_MEM, "%s: mbm resource create error.", __func__);
|
||||||
|
(void)xSemaphoreGive( mbm_opts->mbm_sema );
|
||||||
|
|
||||||
// Create modbus controller task
|
// Create modbus controller task
|
||||||
status = xTaskCreatePinnedToCore((void*)&modbus_master_task,
|
status = xTaskCreatePinnedToCore((void*)&modbus_master_task,
|
||||||
"modbus_matask",
|
"modbus_matask",
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "freertos/task.h" // for task api access
|
#include "freertos/task.h" // for task api access
|
||||||
#include "freertos/event_groups.h" // for event groups
|
#include "freertos/event_groups.h" // for event groups
|
||||||
#include "freertos/queue.h" // for queue api access
|
#include "freertos/queue.h" // for queue api access
|
||||||
|
#include "freertos/semphr.h" // for semaphore
|
||||||
#include "mb_m.h" // for modbus stack master types definition
|
#include "mb_m.h" // for modbus stack master types definition
|
||||||
#include "port.h" // for port callback functions and defines
|
#include "port.h" // for port callback functions and defines
|
||||||
#include "mbutils.h" // for mbutils functions definition for stack callback
|
#include "mbutils.h" // for mbutils functions definition for stack callback
|
||||||
@ -28,7 +29,6 @@
|
|||||||
#if MB_MASTER_TCP_ENABLED
|
#if MB_MASTER_TCP_ENABLED
|
||||||
|
|
||||||
/*-----------------------Master mode use these variables----------------------*/
|
/*-----------------------Master mode use these variables----------------------*/
|
||||||
|
|
||||||
#define MB_TCP_CONNECTION_TOUT (pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000))
|
#define MB_TCP_CONNECTION_TOUT (pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000))
|
||||||
|
|
||||||
// Actual wait time depends on the response timer
|
// Actual wait time depends on the response timer
|
||||||
@ -197,7 +197,9 @@ static esp_err_t mbc_tcp_master_destroy(void)
|
|||||||
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack disable failure.");
|
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack disable failure.");
|
||||||
|
|
||||||
(void)vTaskDelete(mbm_opts->mbm_task_handle);
|
(void)vTaskDelete(mbm_opts->mbm_task_handle);
|
||||||
mbm_opts->mbm_task_handle = NULL;
|
mbm_opts->mbm_task_handle = NULL;
|
||||||
|
vSemaphoreDelete(mbm_opts->mbm_sema);
|
||||||
|
mbm_opts->mbm_sema = NULL;
|
||||||
|
|
||||||
mb_error = eMBMasterClose();
|
mb_error = eMBMasterClose();
|
||||||
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
||||||
@ -261,19 +263,16 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void*
|
|||||||
eMBMasterReqErrCode mb_error = MB_MRE_MASTER_BUSY;
|
eMBMasterReqErrCode mb_error = MB_MRE_MASTER_BUSY;
|
||||||
esp_err_t error = ESP_FAIL;
|
esp_err_t error = ESP_FAIL;
|
||||||
|
|
||||||
if (xMBMasterRunResTake(MB_TCP_API_RESP_TICS)) {
|
if (xSemaphoreTake(mbm_opts->mbm_sema, MB_TCP_API_RESP_TICS) == pdTRUE) {
|
||||||
|
|
||||||
uint8_t mb_slave_addr = request->slave_addr;
|
uint8_t mb_slave_addr = request->slave_addr;
|
||||||
uint8_t mb_command = request->command;
|
uint8_t mb_command = request->command;
|
||||||
uint16_t mb_offset = request->reg_start;
|
uint16_t mb_offset = request->reg_start;
|
||||||
uint16_t mb_size = request->reg_size;
|
uint16_t mb_size = request->reg_size;
|
||||||
|
|
||||||
// Set the buffer for callback function processing of received data
|
// Set the buffer for callback function processing of received data
|
||||||
mbm_opts->mbm_reg_buffer_ptr = (uint8_t*)data_ptr;
|
mbm_opts->mbm_reg_buffer_ptr = (uint8_t*)data_ptr;
|
||||||
mbm_opts->mbm_reg_buffer_size = mb_size;
|
mbm_opts->mbm_reg_buffer_size = mb_size;
|
||||||
|
|
||||||
vMBMasterRunResRelease();
|
|
||||||
|
|
||||||
// Calls appropriate request function to send request and waits response
|
// Calls appropriate request function to send request and waits response
|
||||||
switch(mb_command)
|
switch(mb_command)
|
||||||
{
|
{
|
||||||
@ -323,7 +322,9 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void*
|
|||||||
mb_error = MB_MRE_NO_REG;
|
mb_error = MB_MRE_NO_REG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
ESP_LOGD(TAG, "%s:MBC semaphore take fail.", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
// Propagate the Modbus errors to higher level
|
// Propagate the Modbus errors to higher level
|
||||||
switch(mb_error)
|
switch(mb_error)
|
||||||
@ -350,10 +351,11 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void*
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ESP_LOGE(TAG, "%s: Incorrect return code (0x%x) ", __FUNCTION__, (unsigned)mb_error);
|
ESP_LOGE(TAG, "%s: Incorrect return code (0x%x) ", __FUNCTION__, (int)mb_error);
|
||||||
error = ESP_FAIL;
|
error = ESP_FAIL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
xSemaphoreGive( mbm_opts->mbm_sema );
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -744,6 +746,10 @@ esp_err_t mbc_tcp_master_create(void** handler)
|
|||||||
// Parameter change notification queue
|
// Parameter change notification queue
|
||||||
mbm_opts->mbm_event_group = xEventGroupCreate();
|
mbm_opts->mbm_event_group = xEventGroupCreate();
|
||||||
MB_MASTER_CHECK((mbm_opts->mbm_event_group != NULL), ESP_ERR_NO_MEM, "mb event group error.");
|
MB_MASTER_CHECK((mbm_opts->mbm_event_group != NULL), ESP_ERR_NO_MEM, "mb event group error.");
|
||||||
|
mbm_opts->mbm_sema = xSemaphoreCreateBinary();
|
||||||
|
MB_MASTER_CHECK((mbm_opts->mbm_sema), ESP_ERR_NO_MEM, "%s: mbm resource create error.", __func__);
|
||||||
|
(void)xSemaphoreGive( mbm_opts->mbm_sema );
|
||||||
|
|
||||||
// Create modbus controller task
|
// Create modbus controller task
|
||||||
status = xTaskCreate((void*)&modbus_tcp_master_task,
|
status = xTaskCreate((void*)&modbus_tcp_master_task,
|
||||||
"modbus_tcp_master_task",
|
"modbus_tcp_master_task",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: "1.0.16"
|
version: "1.0.17"
|
||||||
description: ESP-MODBUS is the official Modbus library for Espressif SoCs.
|
description: ESP-MODBUS is the official Modbus library for Espressif SoCs.
|
||||||
url: https://github.com/espressif/esp-modbus
|
url: https://github.com/espressif/esp-modbus
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -305,6 +305,26 @@ static void master_operation_func(void *arg)
|
|||||||
|
|
||||||
ESP_LOGI(TAG, "Start modbus test...");
|
ESP_LOGI(TAG, "Start modbus test...");
|
||||||
|
|
||||||
|
// Command - 17 (0x11) Report Slave ID (Serial Line only)
|
||||||
|
// The command contains vendor specific data and should be interpreted accordingly.
|
||||||
|
// This version of command handler needs to define the maximum number
|
||||||
|
// of registers that can be returned from concrete slave (buffer size).
|
||||||
|
// The returned slave info data will be stored into the `info_buf`.
|
||||||
|
// Request fields: slave_addr - the UID of slave, reg_start - not used,
|
||||||
|
// reg_size = max size of buffer (registers).
|
||||||
|
mb_param_request_t req = {.slave_addr = 1, .command = 0x11,
|
||||||
|
.reg_start = 0, .reg_size = (CONFIG_FMB_CONTROLLER_SLAVE_ID_MAX_SIZE >> 1)};
|
||||||
|
|
||||||
|
uint8_t info_buf[CONFIG_FMB_CONTROLLER_SLAVE_ID_MAX_SIZE] = {0};
|
||||||
|
|
||||||
|
// This is the way to retrieve slave ID information from slave (vendor specific command = 0x11).
|
||||||
|
err = mbc_master_send_request(&req, &info_buf[0]);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE("SLAVE_INFO", "Read slave info fail.");
|
||||||
|
} else {
|
||||||
|
ESP_LOG_BUFFER_HEX_LEVEL("SLAVE_INFO", (void*)info_buf, sizeof(info_buf), ESP_LOG_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) {
|
for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) {
|
||||||
// Read all found characteristics from slave(s)
|
// Read all found characteristics from slave(s)
|
||||||
for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < MASTER_MAX_CIDS; cid++) {
|
for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < MASTER_MAX_CIDS; cid++) {
|
||||||
|
@ -126,6 +126,10 @@ static void setup_reg_data(void)
|
|||||||
input_reg_params.input_data7 = 4.78;
|
input_reg_params.input_data7 = 4.78;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the way to expose the funcion to set slave ID .
|
||||||
|
// The related function is vendor specific and stack by default hides this functionality from user.
|
||||||
|
extern int eMBSetSlaveID(uint8_t slave_id, bool is_running, uint8_t const *pdata, uint16_t data_len);
|
||||||
|
|
||||||
// An example application of Modbus slave. It is based on freemodbus stack.
|
// An example application of Modbus slave. It is based on freemodbus stack.
|
||||||
// See deviceparams.h file for more information about assigned Modbus parameters.
|
// See deviceparams.h file for more information about assigned Modbus parameters.
|
||||||
// These parameters can be accessed from main application and also can be changed
|
// These parameters can be accessed from main application and also can be changed
|
||||||
@ -226,6 +230,15 @@ void app_main(void)
|
|||||||
ESP_LOGI(TAG, "Modbus slave stack initialized.");
|
ESP_LOGI(TAG, "Modbus slave stack initialized.");
|
||||||
ESP_LOGI(TAG, "Start modbus test...");
|
ESP_LOGI(TAG, "Start modbus test...");
|
||||||
|
|
||||||
|
uint8_t ext_data[] = {0x11, 0x22, 0x33, 0x44, 0x55};
|
||||||
|
// This is the way to set Slave ID fields to retrieve it by master using report slave ID command.
|
||||||
|
int err = eMBSetSlaveID(comm_info.slave_addr, true, (uint8_t *)&ext_data, sizeof(ext_data));
|
||||||
|
if (!err) {
|
||||||
|
ESP_LOG_BUFFER_HEX_LEVEL("SET_SLAVE_ID", (void*)ext_data, sizeof(ext_data), ESP_LOG_WARN);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE("SET_SLAVE_ID", "Set slave ID fail, err=%d.", err);
|
||||||
|
}
|
||||||
|
|
||||||
// The cycle below will be terminated when parameter holdingRegParams.dataChan0
|
// The cycle below will be terminated when parameter holdingRegParams.dataChan0
|
||||||
// incremented each access cycle reaches the CHAN_DATA_MAX_VAL value.
|
// incremented each access cycle reaches the CHAN_DATA_MAX_VAL value.
|
||||||
for(;holding_reg_params.holding_data0 < MB_CHAN_DATA_MAX_VAL;) {
|
for(;holding_reg_params.holding_data0 < MB_CHAN_DATA_MAX_VAL;) {
|
||||||
|
Reference in New Issue
Block a user