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:
Alex Lisitsyn
2024-12-06 19:25:23 +08:00
12 changed files with 185 additions and 28 deletions

11
Kconfig
View File

@ -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

View File

@ -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
*/ */

View File

@ -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

View File

@ -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;
} }

View File

@ -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 );

View File

@ -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 )

View File

@ -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},

View File

@ -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",

View File

@ -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",

View File

@ -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:

View File

@ -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++) {

View File

@ -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;) {