Skip to content

Commit ddb7315

Browse files
committed
update documentation
1 parent 9246f74 commit ddb7315

File tree

4 files changed

+155
-11
lines changed

4 files changed

+155
-11
lines changed

docs/en/applications_and_references.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,19 @@ The examples below demonstrate the library port for serial, TCP slave and master
4040

4141
.. _example_mb_slave:
4242

43-
- `Modbus serial slave example <https://github.com/espressif/esp-modbus/tree/release/v2.0/examples/serial/mb_serial_slave>`__
43+
- `Modbus serial slave example <https://github.com/espressif/esp-modbus/tree/main/examples/serial/mb_serial_slave>`__
4444

4545
.. _example_mb_master:
4646

47-
- `Modbus serial master example <https://github.com/espressif/esp-modbus/tree/release/v2.0/examples/serial/mb_serial_master>`__
47+
- `Modbus serial master example <https://github.com/espressif/esp-modbus/tree/main/examples/serial/mb_serial_master>`__
4848

4949
.. _example_mb_tcp_master:
5050

51-
- `Modbus TCP master example <https://github.com/espressif/esp-modbus/tree/release/v2.0/examples/tcp/mb_tcp_slave>`__
51+
- `Modbus TCP master example <https://github.com/espressif/esp-modbus/tree/main/examples/tcp/mb_tcp_slave>`__
5252

5353
.. _example_mb_tcp_slave:
5454

55-
- `Modbus TCP slave example <https://github.com/espressif/esp-modbus/tree/release/v2.0/examples/tcp/mb_tcp_master>`__
55+
- `Modbus TCP slave example <https://github.com/espressif/esp-modbus/tree/main/examples/tcp/mb_tcp_master>`__
5656

5757
Please refer to the specific example README.md for details.
5858

docs/en/master_api_overview.rst

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ The following overview describes how to setup Modbus master communication. The o
77

88
1. :ref:`modbus_api_port_initialization` - Initialization of Modbus controller interface for the selected port.
99
2. :ref:`modbus_api_master_configure_descriptor` - Configure data descriptors to access slave parameters.
10-
3. :ref:`modbus_api_master_setup_communication_options` - Allows to setup communication options for selected port.
11-
4. :ref:`modbus_api_master_start_communication` - Start stack and sending / receiving data.
12-
5. :ref:`modbus_api_master_destroy` - Destroy Modbus controller and its resources.
10+
3. :ref:`modbus_api_master_handler_customization` - Customization of Modbus function handling.
11+
4. :ref:`modbus_api_master_setup_communication_options` - Allows to setup communication options for selected port.
12+
5. :ref:`modbus_api_master_start_communication` - Start stack and sending / receiving data.
13+
6. :ref:`modbus_api_master_destroy` - Destroy Modbus controller and its resources.
1314

1415
.. _modbus_api_master_configure_descriptor:
1516

@@ -305,6 +306,102 @@ Initialization of master descriptor. The descriptor represents an array of type
305306
The Data Dictionary can be initialized from SD card, MQTT or other source before start of stack. Once the initialization and setup is done, the Modbus controller allows the reading of complex parameters from any slave included in descriptor table using its CID.
306307
Refer to :ref:`example TCP master <example_mb_tcp_master>`, :ref:`example Serial master <example_mb_master>` for more information.
307308

309+
.. _modbus_api_master_handler_customization:
310+
311+
Master Customize Function Handlers
312+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
313+
314+
The Master object contains the command handling tables to define the specific handling functionality for each supported Modbus command. The default handling functions in this table support most common Modbus commands. However, the list of commands can be extended by adding the new command into handling table with its custom handling behavior. It is also possible overriding the function handler for the specific command. The below described API functions allow using this behavior for master objects.
315+
316+
:cpp:func:`mbc_master_set_handler`
317+
318+
:cpp:func:`mbc_master_get_handler`
319+
320+
The example code to overide the handler routine for command `0x04 - Read Input Registers`:
321+
322+
.. code:: c
323+
324+
static void *master_handle = NULL; // Pointer to allocated interface structure
325+
uint8_t override_command = 0x04;
326+
....
327+
// Define the custom function handler for the command.
328+
// The handler body must be short and don't use any unpredictable logic. The handler
329+
// is executed in the context of modbus controller event task.
330+
mb_exception_t my_custom_fc04_handler(void *pinst, uint8_t *frame_ptr, uint16_t *plen)
331+
{
332+
MB_RETURN_ON_FALSE(frame_ptr && plen, MB_EX_CRITICAL, TAG,
333+
"incorrect frame buffer length");
334+
// This error handler will be executed to check the request for the command 0x04
335+
// See the default handler in the file `esp-modbus//modbus/mb_objects/functions/mbfuncinput_master.c` for more information.
336+
// The pframe is pointer to command buffer, plen - is pointer to length of the buffer
337+
return MB_EX_CRITICAL;
338+
}
339+
....
340+
err = mbc_master_set_handler(master_handle, override_command, NULL);
341+
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
342+
"could not override handler, returned (0x%x).", (int)err);
343+
err = mbc_master_set_handler(master_handle, override_command, my_custom_fc04_handler);
344+
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
345+
"could not override handler, returned (0x%x).", (int)err);
346+
347+
.. note:: The custom handler set by the function :cpp:func:`mbc_master_set_handler` should be as short as possible and should contain simple and safe logic to not break the normal functionality of the stack. This is user application responsibility to handle the command appropriately.
348+
349+
The example code to handle custom vendor specific command is below. This example sends the 'Master' string to slave and gets the response from slave with the string being appended from slave. It is just a simple echo example to demonstrate the approach.
350+
351+
.. code:: c
352+
353+
#define MB_CUST_DATA_LEN 100
354+
static char my_custom_data[MB_CUST_DATA_LEN] = {0}; // custom data buffer for the request
355+
static void *master_handle = NULL; // Pointer to allocated interface structure
356+
357+
// This is the custom function handler to process incoming slave response.
358+
// Refer the function handler examples in `esp-modbus/modbus/mb_objects/functions/mbfuncinput_master.c` for more information.
359+
// Parameters: pframe: is pointer to incoming frame buffer, plen: is pointer to length including the function code
360+
// In spite of logging showed here, try to use just simple functionality here.
361+
mb_exception_t my_custom_fc_handler(void *pinst, uint8_t *frame_ptr, uint16_t *plen)
362+
{
363+
MB_RETURN_ON_FALSE((frame_ptr && plen && *plen && *plen < (MB_CUST_DATA_LEN - 1)), MB_EX_CRITICAL, TAG,
364+
"incorrect custom frame buffer");
365+
ESP_LOGW(TAG, "Custom handler, Frame ptr: %p, len: %u", frame_ptr, *plen);
366+
strncpy((char *)&my_custom_data[0], (char *)&frame_ptr[1], MB_CUST_DATA_LEN);
367+
ESP_LOG_BUFFER_HEXDUMP("CUSTOM_DATA", &my_custom_data[0], (*plen - 1), ESP_LOG_WARN);
368+
return MB_EX_NONE;
369+
}
370+
....
371+
// The setup of the master object is completed and the master_handle is already actual
372+
373+
// Add custom command handler
374+
uint8_t custom_command = 0x41; // the function code for the request
375+
// Reset the handler for the command if already set
376+
err = mbc_master_set_handler(master_handle, custom_command, NULL);
377+
MB_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_INVALID_STATE), ESP_ERR_INVALID_STATE, TAG,
378+
"could not override handler, returned (0x%x).", (int)err);
379+
err = mbc_master_set_handler(master_handle, custom_command, my_custom_fc_handler);
380+
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
381+
"could not override handler, returned (0x%x).", (int)err);
382+
mb_fn_handler_fp phandler = NULL;
383+
// Make sure the handler is updated correctly
384+
err = mbc_master_get_handler(master_handle, custom_command, &phandler);
385+
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_fc_handler), ESP_ERR_INVALID_STATE, TAG,
386+
"could not get handler for command %d, returned (0x%x).", (int)custom_command, (int)err);
387+
388+
char *pcustom_string = "Master"; // The custom request string that will be sent to the slave
389+
mb_param_request_t req = {
390+
.slave_addr = MB_DEVICE_ADDR1, // the slave UID to send the request
391+
.command = 0x41, // the custom function code,
392+
.reg_start = 0, // unused,
393+
.reg_size = (strlen(pcustom_string) >> 1) // length of the data to send (registers)
394+
};
395+
396+
// Send the request with custom command (vendor speciic)
397+
err = mbc_master_send_request(master_handle, &req, pcustom_string);
398+
if (err != ESP_OK) {
399+
ESP_LOGE("CUSTOM_DATA", "Send custom request fail.");
400+
} else {
401+
// The request is processed correctly and the `my_custom_data[]` contains the sent string with appended slave string
402+
...
403+
}
404+
308405
.. _modbus_api_master_start_communication:
309406

310407
Master Communication

docs/en/overview_messaging_and_mapping.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ The below diagrams show how the extended data types appear on network layer.
276276

277277
The approach showed above can be used to pack the data into MBAP frames used by Modbus TCP as well as for other types with similar size.
278278

279-
The following sections give an overview of how to use the ESP_Modbus component found under `components/freemodbus`. The sections cover initialization of a Modbus port, and the setup a master or slave device accordingly:
279+
The following sections give an overview of how to use the ESP_Modbus component found under `components/esp-modbus`. The sections cover initialization of a Modbus port, and the setup a master or slave device accordingly:
280280

281281
- :ref:`modbus_api_port_initialization`
282282
- :ref:`modbus_api_slave_overview`

docs/en/slave_api_overview.rst

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ The sections below represent typical programming workflow for the slave API whic
77

88
1. :ref:`modbus_api_port_initialization` - Initialization of Modbus controller interface using communication options.
99
2. :ref:`modbus_api_slave_configure_descriptor` - Configure data descriptors to access slave parameters.
10-
3. :ref:`modbus_api_slave_setup_communication_options` - Allows to setup communication options for selected port.
11-
4. :ref:`modbus_api_slave_communication` - Start stack and sending / receiving data. Filter events when master accesses the register areas.
12-
5. :ref:`modbus_api_slave_destroy` - Destroy Modbus controller and its resources.
10+
3. :ref:`modbus_api_slave_handler_customization` - Customization of Modbus function handling in slave object.
11+
4. :ref:`modbus_api_slave_setup_communication_options` - Allows to setup communication options for selected port.
12+
5. :ref:`modbus_api_slave_communication` - Start stack and sending / receiving data. Filter events when master accesses the register areas.
13+
6. :ref:`modbus_api_slave_destroy` - Destroy Modbus controller and its resources.
1314

1415
.. _modbus_api_slave_configure_descriptor:
1516

@@ -161,6 +162,52 @@ Example to get the actual slave identificator:
161162
}
162163
...
163164
165+
.. _modbus_api_slave_handler_customization:
166+
167+
Slave Customize Function Handlers
168+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
169+
170+
The Slave object contains the command handling tables to define the specific handling functionality for each supported Modbus command. The default handling functions in this table support most useful Modbus commands. However, the list of commands can be extended by adding the new command into handling table with its custom handling behavior. It is also possible overriding the function handler for the specific command. The below described API functions allow using this behavior slave objects.
171+
172+
:cpp:func:`mbc_slave_set_handler`
173+
174+
:cpp:func:`mbc_slave_get_handler`
175+
176+
The following example allows to override the standard command to read input registers. Refer to examples for more information on how to handle custom commands.
177+
178+
.. code:: c
179+
180+
static void *slave_handle = NULL; // Pointer to allocated interface structure (must be actual)
181+
....
182+
// The custom function handler for the function returns exception code for now
183+
// Please place your custom handling behavior here.
184+
// This error handler will be executed to check the request for the command 0x04
185+
// See the default handler in the file `esp-modbus//modbus/mb_objects/functions/mbfuncinput_slave.c` for more information.
186+
// The pframe is pointer to command buffer, plen - is pointer to the variable with the length of the buffer
187+
mb_exception_t my_custom_fc04_handler(void *pinst, uint8_t *frame_ptr, uint16_t *plen)
188+
{
189+
MB_RETURN_ON_FALSE(frame_ptr && plen, MB_EX_CRITICAL, TAG,
190+
"incorrect frame buffer length");
191+
return MB_EX_CRITICAL;
192+
}
193+
...
194+
uint8_t override_command = 0x04;
195+
// Reset the existing handler for the command
196+
esp_err_t err = mbc_slave_set_handler(slave_handle, override_command, NULL);
197+
MB_RETURN_ON_FALSE((err == ESP_OK), ;, TAG,
198+
"could not reset handler, returned (0x%x).", (int)err);
199+
// Set the custom handler function for the command
200+
err = mbc_slave_set_handler(slave_handle, override_command, my_custom_fc04_handler);
201+
MB_RETURN_ON_FALSE((err == ESP_OK), ;, TAG,
202+
"could not override handler, returned (0x%x).", (int)err);
203+
mb_fn_handler_fp phandler = NULL;
204+
// Get the actual handler for the command
205+
err = mbc_slave_get_handler(slave_handle, override_command, &phandler);
206+
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_fc04_handler), ;, TAG,
207+
"could not get handler, returned (0x%x).", (int)err);
208+
209+
.. note:: The custom handlers set by the function :cpp:func:`mbc_slave_set_handler` should be as short as possible and should contain simple logic to not break the normal functionality of the stack. This is user application responsibility to handle the command appropriately.
210+
164211
.. _modbus_api_slave_communication:
165212

166213
Slave Communication

0 commit comments

Comments
 (0)