RIOT
RIOT copied to clipboard
drivers: modbus_rtu: add initial support (v2)
Contribution description
This PR is a reboot of https://github.com/RIOT-OS/RIOT/pull/13913 that got stale. I cloned it, rebased it onto master, adapted it to latest standards (hopefully) and proposed https://github.com/RIOT-OS/RIOT/pull/19819. But after some actual testing, I decided that both PRs were not really useful, and made a lot of assumptions. For more flexibility, I rewrote most of the code. Some notable improvements:
- No more hard-coded addresses. If you request address 1000, the slave does not need to allocate a buffer to hold 1000 registers.
- Slave implementation uses a request callback, which makes it much simpler to implement dynamic behavior.
- Support for exceptions.
- Better documented, consistent naming with Modbus specification.
Contrary to the original PR, I removed a lot of #ifdefs that limited which Modbus functions would be supported. It was hard to manage IMHO.
I also extended the test application to test using a single or multiple devices. An example application that provides a Modbus slave implementation is also provided.
Testing procedure
A test application is provided in tests/drivers/modbus.
There are multiple ways to test this. The easiest is to connect RX/TX of one UART to TX/RX of another UART. That way, Modbus runs over RS-232, which should be sufficient to test majority of the implementation. If you take a board with two additional UARTs, then you can use the loopback mode, which will perform additional assertions by comparing data directly.
Alternatively, connect two or more boards via a RS-485 network. Let one run as master and the other as slaves.
See here for more information.
Issues/PRs references
Fixes #13869.
Murdock results
:heavy_check_mark: PASSED
6f6f606e3b8f3105b985d15dc416cf788aa33bd5 fixup! tests/drivers/modbus: add test application
| Success | Failures | Total | Runtime |
|---|---|---|---|
| 10067 | 0 | 10067 | 09m:34s |
Artifacts
I made some additional changes to the implementation.
- I removed message validation when using
modbus_rtu_send_request. It is up to the caller to provide a valid message. - I also removed message validation in
modbus_rtu_recv_request. Validation should now happen in the callback, because it checks 'application level' properties. - I removed the
MODBUS_ERR_EXCEPTIONerror code: exceptions are a valid responses, so leave it up to the application to handle it. - I added support for zero-copy read requests: in this case, the message will directly point to the internal buffer, which does not need copying.
- I added support for multi-slave implementations. Sounds like a lot, but I basically allow the request callback to handle any request message, so it is up to the callback to decide whether or not to send a response. This also allows for broadcasted requests (slave identifier == 0). It does require some additional checks in the callback, but I think its worth the flexibility.
@derMihai since you worked with modbus would you please take a short look