Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes float encoding/decoding for both big and little endian (fixes #665). #694

Merged
merged 4 commits into from
Jul 17, 2024
Merged

Conversation

ghorwin
Copy link
Contributor

@ghorwin ghorwin commented Apr 5, 2023

Fixes float encoding/decoding for both big and little endian (fixes #665).
Also removes useless memcpy calls and no longer used swap32 and swap16 macros.

This pullrequest modifies a single file. As explained in issue #665, the byte positions in target modbus buffer must be explicitely set according to the modbus protocol specs.

Both for encoding/decoding a cross-platform way working for both big and little endian systems is the use of 32-bit integers. That means, we interpret the memory of the 32-bit float as 32-bit integer, then extract the byte via shift operations. Hereby, the compiler takes care of the big/little endian memory layout of our float/integer.

The new code is way faster than the previous, as the memcpy operations are no longer needed. The type casts may look ugly at first glance, but really describe what we want to achive:

float f;
float * f_ptr = &f;  // pointer to float
uint32_t * i_ptr = (uint32_*)f_ptr; // interpret as pointer to uint32
uint32_t i = *i_ptr; // get the integer value at this memory location

putting this all together:

*(uint32_t*)(&f) = integer number

).

Also removes useless memcpy calls and no longer used swap32 and swap16 macros.
@cla-bot
Copy link

cla-bot bot commented Apr 5, 2023

We require contributors to sign our Contributor License Agreement. In order for us to review and merge your code, please fill https://forms.gle/5635zjphDo5JEJQSA to get added. Your document will be manually checked by the maintainer. Be patient...

@ghorwin ghorwin closed this Apr 6, 2023
@ghorwin
Copy link
Contributor Author

ghorwin commented Apr 6, 2023

Sorry, need to revise patch first, as src 16-bit registers already match endianess of host architecture

@ghorwin ghorwin reopened this Apr 6, 2023
@cla-bot
Copy link

cla-bot bot commented Apr 6, 2023

We require contributors to sign our Contributor License Agreement. In order for us to review and merge your code, please fill https://forms.gle/5635zjphDo5JEJQSA to get added. Your document will be manually checked by the maintainer. Be patient...

@ghorwin
Copy link
Contributor Author

ghorwin commented Apr 6, 2023

Finished revision of encoding/decoding functions. Actually, the encoding functions are now almost identical to the original code (except for the useless memcpy). Also, instead of altering positions of a,b,c,d in assembling the int32, I chose to alter the positions when retrieving a,b,c,d from source int16. The result is the same, yet better readable (I hope).

@cshabee
Copy link

cshabee commented Jan 22, 2024

Could someone please provide an answer to the question whether this is going to be merge anytime soon?
Thanks in advance!

@ghorwin
Copy link
Contributor Author

ghorwin commented Jan 22, 2024

Hi there,
I'm using the patched version of libmodbus for several projects with different devices and 32-bit encodings. I'm also aware of several projects reporting errors or implementing manual workarounds as the buggy libmodbus-version is already present in the apt repository of ubuntu-like distros. Hence, I would be happy if this bugfix would be merged soon.

As for the cla - I have signed it already last year but I can sign it again, to be on the safe side. Just a moment...

@ghorwin
Copy link
Contributor Author

ghorwin commented Jan 22, 2024

So, I have completed the contributor license agreement form (again). Should be all clear now.

@ghorwin
Copy link
Contributor Author

ghorwin commented Feb 9, 2024

Ok, the CLA bot seems broken... I'm giving up. I've completed the CLA sign procedure now three times, and still get the same error. Bummer...

@stephane
Copy link
Owner

Thank you @ghorwin I've updated the CLA file (manual operation is required).

@stephane
Copy link
Owner

You seem to have spend enough time on the subject to propose a good patch. This subject is full of traps and I don't want to spend more time on it these days so I'll trust your code and apply it (almost) blindly!

@stephane stephane merged commit 13bd584 into stephane:master Jul 17, 2024
@stephane
Copy link
Owner

stephane commented Jul 17, 2024

The CI fails so who is right?

TEST FLOATS
1/4 Set/get float ABCD:
Line 327: assertion error for 'is_memory_equal(tab_rp_registers, UT_IREAL_ABCD_SET, 4)': FAILED Set float ABCD

The gcc warnings are not acceptable:

../../../src/modbus-data.c:105:6: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  105 |     *(uint32_t *)&f = (a << 24) | (b << 16) | (c << 8) | (d << 0);

stephane added a commit that referenced this pull request Jul 17, 2024
@stephane
Copy link
Owner

Don't know how to reopen this PR...

@ghorwin
Copy link
Contributor Author

ghorwin commented Jul 17, 2024

Hi Stephane,
thanks for looking into this. I need to check the CI to see if the assumption/definition is wrong or my code.

@stephane
Copy link
Owner

BTW I'm sure the mask and shift approach w/o memcpy or useless bswap of your PR is the right way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

modbus_get/set_float_xxxx() mixing bytes
3 participants