Skip to content

Commit

Permalink
add agile_modbus_compute_response_length_from_request API
Browse files Browse the repository at this point in the history
  • Loading branch information
loogg committed Jan 28, 2024
1 parent c2af9ac commit de77c82
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 66 deletions.
10 changes: 10 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,13 @@
2022-11-22: Ma Longwei

* Writing a single register in `agile_modbus_slave_handle` will point the `slave_info.buf` pointer to the local variable address. This address will be used by other variables after turning on compiler optimization. Modify it to point to the global variable address within the function.

## Agile Modbus 1.1.4 released

### Revise

* fixed some warnings for some compiltion IDE such as ses

### New function

* Add API `agile_modbus_compute_response_length_from_request`: Obtain the length of the response from the slave based on the request
Binary file modified doc/doxygen/Agile_Modbus.chm
Binary file not shown.
2 changes: 1 addition & 1 deletion doc/doxygen/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = "Agile Modbus"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 1.1.3
PROJECT_NUMBER = 1.1.4

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
32 changes: 16 additions & 16 deletions doc/doxygen/output/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">Agile Modbus<span id="projectnumber">&#160;1.1.3</span>
<div id="projectname">Agile Modbus<span id="projectnumber">&#160;1.1.4</span>
</div>
<div id="projectbrief">Lightweight modbus protocol stack.</div>
</td>
Expand Down Expand Up @@ -86,8 +86,8 @@
<div class="headertitle"><div class="title">Agile Modbus </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p ><a class="anchor" id="md_C__Users_25440_Desktop_agile_modbus_README"></a> </p>
<h1><a class="anchor" id="autotoc_md20"></a>
<div class="textblock"><p ><a class="anchor" id="md_D__AgilePackages_agile_modbus_README"></a> </p>
<h1><a class="anchor" id="autotoc_md23"></a>
1. Introduction</h1>
<p >Agile Modbus is a lightweight modbus protocol stack that meets the needs of users in any scenario.</p>
<p ><img src="./figures/ModbusProtocol.jpg" alt="ModbusProtocol" class="inline"/></p>
Expand All @@ -98,7 +98,7 @@ <h1><a class="anchor" id="autotoc_md20"></a>
<li>Bootloader based on RT-Thread on AT32F437 that supports Modbus firmware upgrade: <a href="https://github.com/loogg/AT32F437_Boot">AT32F437_Boot</a></li>
<li>Bootloader based on RT-Thread on HPM6750 that supports Modbus firmware upgrade: <a href="https://github.com/loogg/HPM6750_Boot">HPM6750_Boot</a></li>
</ul>
<h2><a class="anchor" id="autotoc_md21"></a>
<h2><a class="anchor" id="autotoc_md24"></a>
1.1. Features</h2>
<ol type="1">
<li>Supports rtu and tcp protocols, is developed using pure C, does not involve any hardware interface, and can be used directly on any form of hardware.</li>
Expand All @@ -107,7 +107,7 @@ <h2><a class="anchor" id="autotoc_md21"></a>
<li>Supports multiple masters and multiple slaves at the same time.</li>
<li>It is easy to use. You only need to initialize the rtu or tcp handle and call the corresponding API to package and unpack.</li>
</ol>
<h2><a class="anchor" id="autotoc_md22"></a>
<h2><a class="anchor" id="autotoc_md25"></a>
1.2. Directory structure</h2>
<table class="markdownTable">
<tr class="markdownTableHead">
Expand All @@ -125,13 +125,13 @@ <h2><a class="anchor" id="autotoc_md22"></a>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">util </td><td class="markdownTableBodyNone">Provides simple and practical components </td></tr>
</table>
<h2><a class="anchor" id="autotoc_md23"></a>
<h2><a class="anchor" id="autotoc_md26"></a>
1.3. License</h2>
<p >Agile Modbus complies with the <code>Apache-2.0</code> license, see the <code>LICENSE</code> file for details.</p>
<h1><a class="anchor" id="autotoc_md24"></a>
<h1><a class="anchor" id="autotoc_md27"></a>
2. Use Agile Modbus</h1>
<p >Please view the help document <a href="./doc/doxygen/Agile_Modbus.chm">doc/doxygen/Agile_Modbus.chm</a></p>
<h2><a class="anchor" id="autotoc_md25"></a>
<h2><a class="anchor" id="autotoc_md28"></a>
2.1. Transplantation</h2>
<ul>
<li><p class="startli">Users need to implement the <code>send data</code>, <code>wait for data reception to end</code> and <code>clear the receive buffer</code> functions of the hardware interface</p>
Expand Down Expand Up @@ -186,12 +186,12 @@ <h2><a class="anchor" id="autotoc_md25"></a>
<p class="startli">Receive buffer setting: If the <code>message length requested by the host</code> is greater than the <code>set receive buffer size</code>, an exception will be returned. This is reasonable. When a small memory MCU is used as a slave, certain function codes must be restricted.</p>
</li>
</ul>
<h2><a class="anchor" id="autotoc_md26"></a>
<h2><a class="anchor" id="autotoc_md29"></a>
2.2. Host</h2>
<p >See <code>2.1. Transplantation</code>.</p>
<h2><a class="anchor" id="autotoc_md27"></a>
<h2><a class="anchor" id="autotoc_md30"></a>
2.3. Slave machine</h2>
<h3><a class="anchor" id="autotoc_md28"></a>
<h3><a class="anchor" id="autotoc_md31"></a>
2.3.1. Interface description</h3>
<ul>
<li><p class="startli">Introduction to <code>agile_modbus_slave_handle</code></p>
Expand Down Expand Up @@ -254,7 +254,7 @@ <h3><a class="anchor" id="autotoc_md28"></a>
</ul>
</li>
</ul>
<h3><a class="anchor" id="autotoc_md29"></a>
<h3><a class="anchor" id="autotoc_md32"></a>
2.3.2. Simple slave access interface</h3>
<p >Agile Modbus provides an implementation of <code>agile_modbus_slave_callback_t</code>, allowing users to access it simply and conveniently.</p>
<p >See <a href="./examples/slave">examples/slave</a> for examples of usage.</p>
Expand Down Expand Up @@ -348,7 +348,7 @@ <h3><a class="anchor" id="autotoc_md29"></a>
</ul>
</li>
</ul>
<h2><a class="anchor" id="autotoc_md30"></a>
<h2><a class="anchor" id="autotoc_md33"></a>
2.4. Example</h2>
<ul>
<li>Examples on PC are provided in the <a href="./examples">examples</a> folder, which can be compiled and run under <code>WSL</code> or <code>Linux</code>.<ul>
Expand All @@ -363,18 +363,18 @@ <h2><a class="anchor" id="autotoc_md30"></a>
<li><a href="https://github.com/loogg/AT32F437_Boot">AT32F437_Boot</a> A Bootloader based on RT-Thread implemented on AT32F437 that supports Modbus firmware upgrade.</li>
<li><a href="https://github.com/loogg/HPM6750_Boot">HPM6750_Boot</a> A Bootloader based on RT-Thread implemented on HPM6750 that supports Modbus firmware upgrade.</li>
</ul>
<h2><a class="anchor" id="autotoc_md31"></a>
<h2><a class="anchor" id="autotoc_md34"></a>
2.5. Doxygen document generation</h2>
<ul>
<li>Use <code>Doxywizard</code> to open <a href="./doc/doxygen/Doxyfile">Doxyfile</a> and run it. The generated file will be under <a href="./doc/doxygen/output">doxygen/output</a>.</li>
<li><code>Graphviz</code> path needs to be changed.</li>
<li><code>HTML</code> is generated without using <code>chm</code> format. If it is enabled, you need to change the <code>hhc.exe</code> path.</li>
</ul>
<h1><a class="anchor" id="autotoc_md32"></a>
<h1><a class="anchor" id="autotoc_md35"></a>
3. Support</h1>
<p ><img src="./figures/zanshang.jpg" alt="zanshang" class="inline"/></p>
<p >If Agile Modbus solves your problem, you might as well scan the QR code above and invite me for a <b>cup of coffee</b> ~</p>
<h1><a class="anchor" id="autotoc_md33"></a>
<h1><a class="anchor" id="autotoc_md36"></a>
4. Contact information &amp; thanks</h1>
<ul>
<li>Maintenance: Ma Longwei</li>
Expand Down
3 changes: 2 additions & 1 deletion inc/agile_modbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ extern "C" {
/** @defgroup Modbus_Constants Modbus Constants
* @{
*/
#define AGILE_MODBUS_VERSION_STRING "AMB_1.1.3" /**< Agile Modbus version number */
#define AGILE_MODBUS_VERSION_STRING "AMB_1.1.4" /**< Agile Modbus version number */

#define AGILE_MODBUS_BROADCAST_ADDRESS 0 /**< Modbus broadcast address */

Expand Down Expand Up @@ -327,6 +327,7 @@ int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length
/** @addtogroup Master_Raw_Operation_Functions
* @{
*/
int agile_modbus_compute_response_length_from_request(agile_modbus_t *ctx, uint8_t *req);
int agile_modbus_serialize_raw_request(agile_modbus_t *ctx, const uint8_t *raw_req, int raw_req_length);
int agile_modbus_deserialize_raw_response(agile_modbus_t *ctx, int msg_length);
/**
Expand Down
96 changes: 48 additions & 48 deletions src/agile_modbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,54 +331,6 @@ int agile_modbus_receive_judge(agile_modbus_t *ctx, int msg_length, agile_modbus
* @{
*/

/**
* @brief Calculate the expected response data length
* @note If it is a special function code, AGILE_MODBUS_MSG_LENGTH_UNDEFINED is returned, but this does not mean an exception.
* When agile_modbus_check_confirmation calls this API processing, it is considered that the return value of AGILE_MODBUS_MSG_LENGTH_UNDEFINED is also valid.
* @param ctx modbus handle
* @param req request data pointer
* @return expected response data length
*/
static int agile_modbus_compute_response_length_from_request(agile_modbus_t *ctx, uint8_t *req)
{
int length;
const int offset = ctx->backend->header_length;

switch (req[offset]) {
case AGILE_MODBUS_FC_READ_COILS:
case AGILE_MODBUS_FC_READ_DISCRETE_INPUTS: {
/* Header + nb values (code from write_bits) */
int nb = (req[offset + 3] << 8) | req[offset + 4];
length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);
} break;

case AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS:
case AGILE_MODBUS_FC_READ_HOLDING_REGISTERS:
case AGILE_MODBUS_FC_READ_INPUT_REGISTERS:
/* Header + 2 * nb values */
length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]);
break;

case AGILE_MODBUS_FC_WRITE_SINGLE_COIL:
case AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER:
case AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS:
case AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
length = 5;
break;

case AGILE_MODBUS_FC_MASK_WRITE_REGISTER:
length = 7;
break;

default:
/* The response is device specific (the header provides the
length) */
return AGILE_MODBUS_MSG_LENGTH_UNDEFINED;
}

return offset + length + ctx->backend->checksum_length;
}

/**
* @brief Check and confirm the slave response data
* @param ctx modbus handle
Expand Down Expand Up @@ -1021,6 +973,54 @@ int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length
* @{
*/

/**
* @brief Calculate the expected response data length
* @note If it is a special function code, AGILE_MODBUS_MSG_LENGTH_UNDEFINED is returned, but this does not mean an exception.
* When agile_modbus_check_confirmation calls this API processing, it is considered that the return value of AGILE_MODBUS_MSG_LENGTH_UNDEFINED is also valid.
* @param ctx modbus handle
* @param req request data pointer
* @return expected response data length
*/
int agile_modbus_compute_response_length_from_request(agile_modbus_t *ctx, uint8_t *req)
{
int length;
const int offset = ctx->backend->header_length;

switch (req[offset]) {
case AGILE_MODBUS_FC_READ_COILS:
case AGILE_MODBUS_FC_READ_DISCRETE_INPUTS: {
/* Header + nb values (code from write_bits) */
int nb = (req[offset + 3] << 8) | req[offset + 4];
length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);
} break;

case AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS:
case AGILE_MODBUS_FC_READ_HOLDING_REGISTERS:
case AGILE_MODBUS_FC_READ_INPUT_REGISTERS:
/* Header + 2 * nb values */
length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]);
break;

case AGILE_MODBUS_FC_WRITE_SINGLE_COIL:
case AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER:
case AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS:
case AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
length = 5;
break;

case AGILE_MODBUS_FC_MASK_WRITE_REGISTER:
length = 7;
break;

default:
/* The response is device specific (the header provides the
length) */
return AGILE_MODBUS_MSG_LENGTH_UNDEFINED;
}

return offset + length + ctx->backend->checksum_length;
}

/**
* @brief Pack the original data into a request message
* @param ctx modbus handle
Expand Down

0 comments on commit de77c82

Please sign in to comment.