Skip to content

Commit e8317c2

Browse files
committed
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
2 parents 5a36ece + db57bd6 commit e8317c2

File tree

12 files changed

+185
-28
lines changed

12 files changed

+185
-28
lines changed

Kconfig

+10-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ menu "Modbus configuration"
5858
config FMB_MASTER_TIMEOUT_MS_RESPOND
5959
int "Slave respond timeout (Milliseconds)"
6060
default 3000
61-
range 150 15000
61+
range 300 15000
6262
help
6363
If master sends a frame which is not broadcast, it has to wait sometime for slave response.
6464
if slave is not respond in this time, the master will process timeout error.
@@ -171,6 +171,15 @@ menu "Modbus configuration"
171171
Most significant byte of ID is used as short device ID and
172172
other three bytes used as long ID.
173173

174+
config FMB_CONTROLLER_SLAVE_ID_MAX_SIZE
175+
int "Modbus Slave ID maximum buffer size (bytes)"
176+
range 4 255
177+
default 32
178+
depends on FMB_CONTROLLER_SLAVE_ID_SUPPORT
179+
help
180+
Modbus slave ID buffer size used to store vendor specific ID information
181+
for the <Report Slave ID> command.
182+
174183
config FMB_CONTROLLER_NOTIFY_TIMEOUT
175184
int "Modbus controller notification timeout (ms)"
176185
range 0 200

freemodbus/common/esp_modbus_master.c

+24
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
#include <sys/param.h>
78
#include "esp_err.h" // for esp_err_t
89
#include "mbc_master.h" // for master interface define
910
#include "esp_modbus_master.h" // for public interface defines
@@ -237,6 +238,29 @@ eMBErrorCode eMBMasterRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress,
237238
return error;
238239
}
239240

241+
eMBErrorCode eMBMasterRegCommonCB(UCHAR * pucData, USHORT usAddress,
242+
USHORT usBytes)
243+
{
244+
MB_MASTER_CHECK((master_interface_ptr != NULL),
245+
MB_EILLSTATE,
246+
"Master interface is not correctly initialized.");
247+
MB_MASTER_CHECK((master_interface_ptr != NULL),
248+
MB_EILLSTATE,
249+
"Master interface uninitialized.");
250+
MB_MASTER_CHECK(pucData, MB_EINVAL,
251+
"Master stack processing error.");
252+
mb_master_options_t* popts = &master_interface_ptr->opts;
253+
USHORT usRegLen = (USHORT)popts->mbm_reg_buffer_size;
254+
UCHAR* pucParBuffer = (UCHAR*)popts->mbm_reg_buffer_ptr; // Get instance address
255+
eMBErrorCode eStatus = MB_ENOERR;
256+
if (pucParBuffer && !usAddress && (usBytes >= 1) && (((usRegLen << 1) >= usBytes))){
257+
memmove(pucParBuffer, pucData, MIN((usRegLen << 1), usBytes));
258+
} else {
259+
eStatus = MB_ENOREG;
260+
}
261+
return eStatus;
262+
}
263+
240264
/**
241265
* Helper function to get current transaction info
242266
*/

freemodbus/common/mbc_master.h

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "freertos/FreeRTOS.h" // for task creation and queue access
1212
#include "freertos/task.h" // for task api access
1313
#include "freertos/event_groups.h" // for event groups
14+
#include "freertos/semphr.h" // for semaphore
1415
#include "driver/uart.h" // for UART types
1516
#include "errno.h" // for errno
1617
#include "esp_log.h" // for log write
@@ -64,6 +65,7 @@ typedef struct {
6465
uint16_t mbm_reg_buffer_size; /*!< Modbus data buffer size */
6566
TaskHandle_t mbm_task_handle; /*!< Modbus task handle */
6667
EventGroupHandle_t mbm_event_group; /*!< Modbus controller event group */
68+
SemaphoreHandle_t mbm_sema; /*!< Modbus controller semaphore */
6769
const mb_parameter_descriptor_t* mbm_param_descriptor_table; /*!< Modbus controller parameter description table */
6870
size_t mbm_param_descriptor_size; /*!< Modbus controller parameter description table size*/
6971
#if MB_MASTER_TCP_ENABLED

freemodbus/modbus/functions/mbfuncother.c

+56-3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
/* ----------------------- Modbus includes ----------------------------------*/
4646
#include "mb.h"
47+
#include "mb_m.h"
4748
#include "mbframe.h"
4849
#include "mbproto.h"
4950
#include "mbconfig.h"
@@ -52,11 +53,61 @@
5253

5354
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
5455

56+
#define MB_PDU_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 )
57+
#define MB_PDU_FUNC_DATA_OFF ( MB_PDU_DATA_OFF + 1 )
58+
5559
/* ----------------------- Static variables ---------------------------------*/
56-
static UCHAR ucMBSlaveID[MB_FUNC_OTHER_REP_SLAVEID_BUF];
60+
static UCHAR ucMBSlaveID[MB_FUNC_OTHER_REP_SLAVEID_BUF] = {0};
5761
static USHORT usMBSlaveIDLen;
5862

5963
/* ----------------------- Start implementation -----------------------------*/
64+
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
65+
66+
eMBMasterReqErrCode
67+
eMBMasterReqReportSlaveID( UCHAR ucSndAddr, LONG lTimeOut )
68+
{
69+
UCHAR *ucMBFrame;
70+
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
71+
72+
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
73+
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
74+
else
75+
{
76+
vMBMasterGetPDUSndBuf(&ucMBFrame);
77+
vMBMasterSetDestAddress(ucSndAddr);
78+
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_OTHER_REPORT_SLAVEID;
79+
vMBMasterSetPDUSndLength( 1 );
80+
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
81+
eErrStatus = eMBMasterWaitRequestFinish( );
82+
}
83+
return eErrStatus;
84+
}
85+
86+
eMBException
87+
eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
88+
{
89+
UCHAR ucByteCount = 0;
90+
eMBException eStatus = MB_EX_NONE;
91+
eMBErrorCode eRegStatus;
92+
93+
if( *usLen <= ( MB_FUNC_OTHER_REP_SLAVEID_BUF - 2 ) )
94+
{
95+
ucByteCount = ( UCHAR )( pucFrame[MB_PDU_BYTECNT_OFF] );
96+
// Transfer data from command buffer.
97+
eRegStatus = eMBMasterRegCommonCB( &pucFrame[MB_PDU_FUNC_DATA_OFF], 0, ucByteCount);
98+
/* If an error occured convert it into a Modbus exception. */
99+
if( eRegStatus != MB_ENOERR )
100+
{
101+
eStatus = prveMBError2Exception( eRegStatus );
102+
}
103+
}
104+
else
105+
{
106+
/* Can't be a valid request because the length is incorrect. */
107+
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
108+
}
109+
return eStatus;
110+
}
60111

61112
eMBErrorCode
62113
eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,
@@ -86,11 +137,13 @@ eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,
86137
return eStatus;
87138
}
88139

140+
// pucFrame points to Modbus PDU
89141
eMBException
90142
eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
91143
{
92-
memcpy( &pucFrame[MB_PDU_DATA_OFF], &ucMBSlaveID[0], ( size_t )usMBSlaveIDLen );
93-
*usLen = ( USHORT )( MB_PDU_DATA_OFF + usMBSlaveIDLen );
144+
memcpy( &pucFrame[MB_PDU_FUNC_DATA_OFF], &ucMBSlaveID[0], ( size_t )usMBSlaveIDLen );
145+
*usLen = ( USHORT )( MB_PDU_FUNC_DATA_OFF + usMBSlaveIDLen );
146+
pucFrame[MB_PDU_BYTECNT_OFF] = usMBSlaveIDLen;
94147
return MB_EX_NONE;
95148
}
96149

freemodbus/modbus/include/mb_m.h

+23-3
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,24 @@ eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode,
258258
* to update the application register values.
259259
*/
260260

261+
/*! \ingroup modbus_registers
262+
* \brief The common callback function used to transfer common data as bytes
263+
* from command buffer in little endian format.
264+
*
265+
* \param pucData A pointer to data in command buffer to be transferred.
266+
* \param usAddress Unused for this function == 0.
267+
* \param usBytes Number of bytes the callback function must supply.
268+
*
269+
* \return The function must return one of the following error codes:
270+
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
271+
* Modbus response is sent.
272+
* - eMBErrorCode::MB_ENOREG if can not map the data of the registers
273+
* - eMBErrorCode::MB_EILLSTATE if can not procceed with data transfer due to critical error
274+
* - eMBErrorCode::MB_EINVAL if value data can not be transferred
275+
*/
276+
eMBErrorCode eMBMasterRegCommonCB( UCHAR * pucData, USHORT usAddress,
277+
USHORT usBytes );
278+
261279
/*! \ingroup modbus_registers
262280
* \brief Callback function used if the value of a <em>Input Register</em>
263281
* is required by the protocol stack. The starting register address is given
@@ -273,9 +291,9 @@ eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode,
273291
* \return The function must return one of the following error codes:
274292
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
275293
* Modbus response is sent.
276-
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
277-
* within the requested address range. In this case a
278-
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
294+
* - eMBErrorCode::MB_ENOREG if can not map the data of the registers
295+
* - eMBErrorCode::MB_EILLSTATE if can not procceed with data transfer due to critical error
296+
* - eMBErrorCode::MB_EINVAL if value data can not be transferred
279297
*/
280298
eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,
281299
USHORT usNRegs );
@@ -365,6 +383,8 @@ eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress,
365383
*\brief These Modbus functions are called for user when Modbus run in Master Mode.
366384
*/
367385
eMBMasterReqErrCode
386+
eMBMasterReqReportSlaveID( UCHAR ucSndAddr, LONG lTimeOut );
387+
eMBMasterReqErrCode
368388
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
369389
eMBMasterReqErrCode
370390
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut );

freemodbus/modbus/include/mbconfig.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ PR_BEGIN_EXTERN_C
144144
* how to set this value. It is only used if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
145145
* is set to <code>1</code>.
146146
*/
147-
#define MB_FUNC_OTHER_REP_SLAVEID_BUF ( 32 )
147+
#define MB_FUNC_OTHER_REP_SLAVEID_BUF ( CONFIG_FMB_CONTROLLER_SLAVE_ID_MAX_SIZE )
148148

149149
/*! \brief If the <em>Report Slave ID</em> function should be enabled. */
150150
#define MB_FUNC_OTHER_REP_SLAVEID_ENABLED ( CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT )

freemodbus/modbus/mb_m.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ BOOL( *pxMBMasterFrameCBTransmitFSMCur ) ( void );
129129
*/
130130
static xMBFunctionHandler xMasterFuncHandlers[MB_FUNC_HANDLERS_MAX] = {
131131
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0
132-
{MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID},
132+
{MB_FUNC_OTHER_REPORT_SLAVEID, eMBMasterFuncReportSlaveID},
133133
#endif
134134
#if MB_FUNC_READ_INPUT_ENABLED > 0
135135
{MB_FUNC_READ_INPUT_REGISTER, eMBMasterFuncReadInputRegister},

freemodbus/serial_master/modbus_controller/mbc_serial_master.c

+19-9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "freertos/task.h" // for task api access
1515
#include "freertos/event_groups.h" // for event groups
1616
#include "freertos/queue.h" // for queue api access
17+
#include "freertos/semphr.h" // for semaphore
1718
#include "mb_m.h" // for modbus stack master types definition
1819
#include "port.h" // for port callback functions
1920
#include "mbutils.h" // for mbutils functions definition for stack callback
@@ -28,7 +29,7 @@ extern BOOL xMBMasterPortSerialTxPoll(void);
2829

2930
/*-----------------------Master mode use these variables----------------------*/
3031
// Actual wait time depends on the response timer
31-
#define MB_SERIAL_API_RESP_TICS (pdMS_TO_TICKS(MB_MAX_RESPONSE_TIME_MS))
32+
#define MB_SERIAL_API_RESP_TICS (pdMS_TO_TICKS(MB_MAX_RESPONSE_TIME_MS))
3233

3334
static mb_master_interface_t* mbm_interface_ptr = NULL;
3435
static const char *TAG = "MB_CONTROLLER_MASTER";
@@ -127,6 +128,8 @@ static esp_err_t mbc_serial_master_destroy(void)
127128
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack disable failure.");
128129
(void)vTaskDelete(mbm_opts->mbm_task_handle);
129130
(void)vEventGroupDelete(mbm_opts->mbm_event_group);
131+
vSemaphoreDelete(mbm_opts->mbm_sema);
132+
mbm_opts->mbm_sema = NULL;
130133
mb_error = eMBMasterClose();
131134
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE,
132135
"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
176179
eMBMasterReqErrCode mb_error = MB_MRE_MASTER_BUSY;
177180
esp_err_t error = ESP_FAIL;
178181

179-
if (xMBMasterRunResTake(MB_SERIAL_API_RESP_TICS)) {
180-
182+
if (xSemaphoreTake(mbm_opts->mbm_sema, MB_SERIAL_API_RESP_TICS) == pdTRUE) {
181183
uint8_t mb_slave_addr = request->slave_addr;
182184
uint8_t mb_command = request->command;
183185
uint16_t mb_offset = request->reg_start;
184186
uint16_t mb_size = request->reg_size;
185-
187+
186188
// Set the buffer for callback function processing of received data
187189
mbm_opts->mbm_reg_buffer_ptr = (uint8_t*)data_ptr;
188190
mbm_opts->mbm_reg_buffer_size = mb_size;
189191

190-
vMBMasterRunResRelease();
191-
192192
// Calls appropriate request function to send request and waits response
193193
switch(mb_command)
194194
{
195+
case MB_FUNC_OTHER_REPORT_SLAVEID:
196+
mb_error = eMBMasterReqReportSlaveID((UCHAR)mb_slave_addr, (LONG)MB_SERIAL_API_RESP_TICS );
197+
break;
195198
case MB_FUNC_READ_COILS:
196199
mb_error = eMBMasterReqReadCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset,
197200
(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
216219
mb_error = eMBMasterReqWriteHoldingRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset,
217220
*(USHORT*)data_ptr, (LONG)MB_SERIAL_API_RESP_TICS );
218221
break;
219-
220222
case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
221223
mb_error = eMBMasterReqWriteMultipleHoldingRegister( (UCHAR)mb_slave_addr,
222224
(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
237239
mb_error = MB_MRE_NO_REG;
238240
break;
239241
}
242+
} else {
243+
ESP_LOGD(TAG, "%s:MBC semaphore take fail.", __func__);
240244
}
241245

242246
// 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
264268
break;
265269

266270
default:
267-
ESP_LOGE(TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, (int)mb_error);
271+
ESP_LOGE(TAG, "%s: Incorrect return code (0x%x) ", __FUNCTION__, (int)mb_error);
268272
error = ESP_FAIL;
269273
break;
270274
}
271275

276+
(void)xSemaphoreGive( mbm_opts->mbm_sema );
277+
272278
return error;
273279
}
274280

@@ -508,7 +514,7 @@ eMBErrorCode eMBRegInputCBSerialMaster(UCHAR * pucRegBuffer, USHORT usAddress,
508514
// If input or configuration parameters are incorrect then return an error to stack layer
509515
if ((pucInputBuffer != NULL)
510516
&& (usNRegs >= 1)
511-
&& (usRegInputNregs == usRegs)) {
517+
&& ((usRegInputNregs == usRegs) || (!usAddress))) {
512518
while (usRegs > 0) {
513519
_XFER_2_RD(pucInputBuffer, pucRegBuffer);
514520
usRegs -= 1;
@@ -698,6 +704,10 @@ esp_err_t mbc_serial_master_create(void** handler)
698704
mbm_opts->mbm_event_group = xEventGroupCreate();
699705
MB_MASTER_CHECK((mbm_opts->mbm_event_group != NULL),
700706
ESP_ERR_NO_MEM, "mb event group error.");
707+
mbm_opts->mbm_sema = xSemaphoreCreateBinary();
708+
MB_MASTER_CHECK((mbm_opts->mbm_sema != NULL), ESP_ERR_NO_MEM, "%s: mbm resource create error.", __func__);
709+
(void)xSemaphoreGive( mbm_opts->mbm_sema );
710+
701711
// Create modbus controller task
702712
status = xTaskCreatePinnedToCore((void*)&modbus_master_task,
703713
"modbus_matask",

0 commit comments

Comments
 (0)