You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, settings (on Linux) are changed using tcsetattr in write_settings, passing in TCSANOW for optional_actions. This causes the new settings to take effect immediately, here's the code in question:
The issue here is that TCSANOW is hardcoded, which prevents using some of the useful alternative options (from man tcsetattr(3)):
arg
meaning
TCSANOW
the change occurs immediately.
TCSADRAIN
the change occurs after all output written to fd has been transmitted. This option should be used when changing parameters that affect output.
TCSAFLUSH
the change occurs after all output written to the object referred by fd has been transmitted, and all input that has been received but not read will be discarded before the change is made.
This parameter cannot be specified with the TCSETS2, instead, different IOCTLS must be used. The old equivalents are documented in tty_ioctl(4):
TCSETS const struct termios *argp
Equivalent to tcsetattr(fd, TCSANOW, argp).
Set the current serial port settings.
TCSETSW const struct termios *argp
Equivalent to tcsetattr(fd, TCSADRAIN, argp).
Allow the output buffer to drain, and set the current serial
port settings.
TCSETSF const struct termios *argp
Equivalent to tcsetattr(fd, TCSAFLUSH, argp).
Allow the output buffer to drain, discard pending input, and
set the current serial port settings.
Note the missing 2. An equivalent TCSETS2, TCSETSW2 and TCSETSF2 exist (some information about these can be found here); they work pretty much the same, except that they require a struct termios2 * instead of a struct termios *.
A feature that is currently missing in serial-rs is the ability to specifiy when the settings changes should take effect. This API needs to be designed and added to the trait first, I'll happily implemented it on Linux, but I'd like to avoid introducing core API changes that may be rejected.
Currently, a workaround exists: Calling flush() on the SerialPort and only then writing new settings. This will cause an additional gap in transmisison for as long as it takes to setup and transfer these settings into the kernel.
A usecase for this is implementing DMX512 using an RS485 serial port. The DMX512 has a lenient but weird structure, it basically is just a regular UART serial port at 250,000 baud (hence the other pull request for non-standard bitrates).
However, to begin transmission of a frame a DMX master must send a long BREAK by pulling the line low for a fairly long amount of time, then releasing it. This can easily be emulated on any UART by setting the bitrate to 57,000 baud, writing a 0x00 byte (7 bit), which will result in a 138 us BREAK (the minimum is 92 us). Directly after (but not during) the port should be switched to 250,000 baud and transmission can begin. In Pseudo-code:
Set to low bitrate/7 bit.
Send BREAK
Set to high bitrate/8 bit
Send data
Drain
Repeat for next packet.
Step 3. could be improved by preparing the new settings in advanced through TCSETSW2, hopefully causing minimal delay when switching bitrates.
The text was updated successfully, but these errors were encountered:
An alternative that is less flexible would be adding support for the tcsendbreak syscall, which achieves the above without funky bitrate changing tricks (although the required pause MARK-AFTER-BREAK must then be done "by hand"). Adding support for this feature would almost be equivalent.
Edit: Unfortunately, the tc_sendbreak is fairly platform dependant:
The effect of a nonzero duration with tcsendbreak() varies. SunOS specifies a break of duration * N seconds, where N is at least 0.25, and not more than 0.5. Linux, AIX, DU, Tru64 send a break of duration milliseconds. FreeBSD and NetBSD and HP-UX and MacOS ignore the value of duration. Under Solaris and UnixWare, tcsendbreak() with nonzero duration behaves like tcdrain().
A millisecond is a long time, about 10x as much as needed for the usecase described above.
Currently, settings (on Linux) are changed using
tcsetattr
inwrite_settings
, passing inTCSANOW
foroptional_actions
. This causes the new settings to take effect immediately, here's the code in question:WIth the proposed pull request #42 , this (on Linux) changes to:
Instead of
tcsetattr
, theTCSETS2
ioctl is used.The issue here is that TCSANOW is hardcoded, which prevents using some of the useful alternative options (from man
tcsetattr(3)
):TCSANOW
TCSADRAIN
TCSAFLUSH
This parameter cannot be specified with the TCSETS2, instead, different IOCTLS must be used. The old equivalents are documented in
tty_ioctl(4)
:Note the missing
2
. An equivalentTCSETS2
,TCSETSW2
andTCSETSF2
exist (some information about these can be found here); they work pretty much the same, except that they require astruct termios2 *
instead of astruct termios *
.A feature that is currently missing in
serial-rs
is the ability to specifiy when the settings changes should take effect. This API needs to be designed and added to the trait first, I'll happily implemented it on Linux, but I'd like to avoid introducing core API changes that may be rejected.Currently, a workaround exists: Calling
flush()
on theSerialPort
and only then writing new settings. This will cause an additional gap in transmisison for as long as it takes to setup and transfer these settings into the kernel.A usecase for this is implementing DMX512 using an RS485 serial port. The DMX512 has a lenient but weird structure, it basically is just a regular UART serial port at 250,000 baud (hence the other pull request for non-standard bitrates).
However, to begin transmission of a frame a DMX master must send a long
BREAK
by pulling the line low for a fairly long amount of time, then releasing it. This can easily be emulated on any UART by setting the bitrate to 57,000 baud, writing a0x00
byte (7 bit), which will result in a 138 usBREAK
(the minimum is92
us). Directly after (but not during) the port should be switched to 250,000 baud and transmission can begin. In Pseudo-code:BREAK
Step 3. could be improved by preparing the new settings in advanced through
TCSETSW2
, hopefully causing minimal delay when switching bitrates.The text was updated successfully, but these errors were encountered: