_modbus_rtu_flush() does not clear the COM-port buffer (in Windows) #144

Closed
AlexMaz opened this Issue Oct 7, 2013 · 5 comments

Comments

Projects
None yet
3 participants
@AlexMaz

AlexMaz commented Oct 7, 2013

Function "_modbus_rtu_flush()" does not clear the COM-port buffer when it is filled with random data.
It cause the processing halt (for some time) of slave device response until all previous random data in the buffer will not be processed as normal slave response data.
My solution:
Instead of using (in "_modbus_rtu_flush()"):

return (FlushFileBuffers(ctx_rtu->w_ser.fd) == FALSE);

I use:

return (PurgeComm(ctx_rtu->w_ser.fd, PURGE_RXCLEAR) == FALSE);

and it clears the COM-port buffer in practice.

@AlexMaz

This comment has been minimized.

Show comment
Hide comment
@AlexMaz

AlexMaz Oct 7, 2013

I am not Windows programmer, but as I understand from MSDN (for a case of COM-port):
"PurgeComm()" simply clears the COM-port buffer and the deleted characters are not transmitted. Whereas "FlushFileBuffers()" ensures that the contents of buffer must be transmitted for processing.

AlexMaz commented Oct 7, 2013

I am not Windows programmer, but as I understand from MSDN (for a case of COM-port):
"PurgeComm()" simply clears the COM-port buffer and the deleted characters are not transmitted. Whereas "FlushFileBuffers()" ensures that the contents of buffer must be transmitted for processing.

@stephane stephane closed this in 8dc4e2e Nov 12, 2013

@stephane

This comment has been minimized.

Show comment
Hide comment
@stephane

stephane Nov 12, 2013

Owner

The role of modbus_flush is to discard any data in the buffer (cleaning) so your proposal seems legit and nobody replied on mailing list...

Owner

stephane commented Nov 12, 2013

The role of modbus_flush is to discard any data in the buffer (cleaning) so your proposal seems legit and nobody replied on mailing list...

mk8 added a commit to mk8/libmodbus that referenced this issue Jan 29, 2014

@bartoli

This comment has been minimized.

Show comment
Hide comment
@bartoli

bartoli Mar 8, 2016

Sorry to bring this back up after so long, but :

  • Will this never be integrated in 3.0.x?
  • I actually encountered a use case on Windows where modbus was stuck because the flush would not flush what was already in the receive buffer. And this change was not enough to make it disappear. I also had to add the option PURGE_RXABORT (Terminates all outstanding overlapped read operations and returns immediately, even if the read operations have not been completed) to the PurgeComm() call. With only PURGE_RXCLEAR, i believe PurgeComm is not any better than FlushFileBuffers()

bartoli commented Mar 8, 2016

Sorry to bring this back up after so long, but :

  • Will this never be integrated in 3.0.x?
  • I actually encountered a use case on Windows where modbus was stuck because the flush would not flush what was already in the receive buffer. And this change was not enough to make it disappear. I also had to add the option PURGE_RXABORT (Terminates all outstanding overlapped read operations and returns immediately, even if the read operations have not been completed) to the PurgeComm() call. With only PURGE_RXCLEAR, i believe PurgeComm is not any better than FlushFileBuffers()
@stephane

This comment has been minimized.

Show comment
Hide comment
@stephane

stephane Mar 8, 2016

Owner
  • This change won't be integrated in 3.0.X
  • If the current code (in v3.1.2 and master) needs some tweaks, feel free to submit a patch.
Owner

stephane commented Mar 8, 2016

  • This change won't be integrated in 3.0.X
  • If the current code (in v3.1.2 and master) needs some tweaks, feel free to submit a patch.
@bartoli

This comment has been minimized.

Show comment
Hide comment
@bartoli

bartoli Mar 8, 2016

I just remembered there is also an issue of return values

I think modbus_rtu_flush() is supposed to return like tcflush. 0 on success, and -1 on failure.
FlushFileBuffer()/PurgeComm() returned a BOOL, non-zero for success. and (PurgeComm()==0) is returned from modbus_rtu_flush(). That means a 1 failure code for windows.
So if some code, instead of testing if it succeeded, tests if _modbus_rtu_flush() failed with either linux of windows failure code, there will be some portability issues.

The code i am actually using is
int ret = PurgeComm(ctx_rtu->w_ser.fd, PURGE_RXCLEAR|PURGE_RXABORT); if(ret==0 && ctx->debug){ printf("Input Buffer emptying error : %d\n",GetLastError()); return -1; } return (ret);

bartoli commented Mar 8, 2016

I just remembered there is also an issue of return values

I think modbus_rtu_flush() is supposed to return like tcflush. 0 on success, and -1 on failure.
FlushFileBuffer()/PurgeComm() returned a BOOL, non-zero for success. and (PurgeComm()==0) is returned from modbus_rtu_flush(). That means a 1 failure code for windows.
So if some code, instead of testing if it succeeded, tests if _modbus_rtu_flush() failed with either linux of windows failure code, there will be some portability issues.

The code i am actually using is
int ret = PurgeComm(ctx_rtu->w_ser.fd, PURGE_RXCLEAR|PURGE_RXABORT); if(ret==0 && ctx->debug){ printf("Input Buffer emptying error : %d\n",GetLastError()); return -1; } return (ret);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment