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

Added support for 1.5 stop bits when reading current port settings #195

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

robdobsn
Copy link

@robdobsn robdobsn commented Jun 6, 2024

On Windows 11 an Espressif ESP32-S3 module connected via USB defaults to 1.5 stop bits when in JTAG/CDC mode
Currently serialport-rs fails to open a port when it is in this state as the stop bits setting of 1.5 is not supported
This change does not allow 1.5 stop bits to be set but avoids failure to open when the port is already set to 1.5 stop bits

This does not allow 1.5 stop bits to be set but avoids failure to open when the port is already set to 1.5 stop bits
@@ -198,6 +198,7 @@ pub(crate) fn set_data_bits(termios: &mut Termios, data_bits: DataBits) {
pub(crate) fn set_stop_bits(termios: &mut Termios, stop_bits: StopBits) {
match stop_bits {
StopBits::One => termios.c_cflag &= !libc::CSTOPB,
StopBits::OnePointFive => termios.c_cflag &= !libc::CSTOPB,
Copy link

@Skgland Skgland Jun 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is ideal to implicitly treat 1.5 as 1 here.
This might work for reading as we get a longer stop bit than we require, but for writing we would send a too short stop bit, causing the symbol to not be properly recognized by the receiver.

Based on this stack overflow answer in some circumstances treating 1.5 as 2 might even be expected.

I don't think adding such a special case here is reasonably possible, so my suggestion would be to make this failable (i.e. return a Result) and return an Err for 1.5 on posix.

Copy link

@Skgland Skgland Jun 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note on how this is treated elsewhere

  • pyserial treats 1.5 stop bits as 2 doc link
  • in some support forum it is suggested to use 2 as a replacement for 1.5 forum link

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the case I'm interested in I don't think it makes any difference what value is selected as the connection is actually implemented on the device as a USB CDC profile. There is no physical layer transmission of serial data in this situation. The issue is that the serialport library fails to connect to the device based on the state that it is in when the connection attempt is made. Further, I would have thought that the job of the library is to define the stop bits setting (along with other communications parameters) rather than declaring them. As I see it this is not a question of what stop bits setting to choose when the user requests 1.5 stop bits but of ensuring the library doesn't fail to connect to a device which is currently reporting that it is configured for 1.5 stop bits.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, if you specify that you want to open a serial port with 2 stop bits (or 1 stop bit for that matter) and the port is currently set to have 1.5 stop bits then the open fails. That makes the library unusable on devices that default to 1.5 stop bits. All I am trying to do is to stop this scenario from failing. I am not trying to add support for 1.5 stop bits and I don't think that would be possible (or desirable) without significant changes that probably go beyond this library.

Copy link

@Skgland Skgland Jul 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not arguing against adding 1.5 stop bits. I just wanted to argue that treating 1.5 as 2 rather than 1 appears to be more consistent with other sources.
As such I would propose to either change the code to treat 1.5 as 2.0 or reject 1.5 (i.e. panic) for set_stop_bits on unix and <u8 as From<StopBits>>::from in general. Either way I am not a maintainer of this project and the final decision lies in their not my purview.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't care what happens when you try to set 1.5 stop bits. It could reject or treat as 1 or 2. That doesn't matter to me. What does matter is what happens when the port is already set to 1.5 stop bits. In this case currently you cannot do anything with the port. When you try to open the port (with 1 or 2 stop bits) it fails. That is what I am trying to get fixed.

Copy link

@Skgland Skgland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is effectively the change to this PR I am proposing.

@@ -242,6 +246,7 @@ impl From<StopBits> for u8 {
fn from(value: StopBits) -> Self {
match value {
StopBits::One => 1,
StopBits::OnePointFive => 1,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
StopBits::OnePointFive => 1,
StopBits::OnePointFive |

@@ -198,6 +198,7 @@ pub(crate) fn set_data_bits(termios: &mut Termios, data_bits: DataBits) {
pub(crate) fn set_stop_bits(termios: &mut Termios, stop_bits: StopBits) {
match stop_bits {
StopBits::One => termios.c_cflag &= !libc::CSTOPB,
StopBits::OnePointFive => termios.c_cflag &= !libc::CSTOPB,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
StopBits::OnePointFive => termios.c_cflag &= !libc::CSTOPB,
StopBits::OnePointFive |

@sirhcel
Copy link
Contributor

sirhcel commented Jul 19, 2024

Thank you for the PR @robdobsn! Thank you for the first review @Skgland! I've looked into how to deal with the API part of this change but I'm still indecisive whether to provide the fractional stop bits for all platforms or just the ones supporting it. Other serial port crates seem to ignore this issue.

In every case rounding up fractional stop bits as suggested by @Skgland looks like the right thing to do to me. The cited examples are making a good case for it.

As changing StopBits is a breaking change for the API, what about splitting this PR and tackling the issue in two steps:

  1. Reporting 1.5 stop bits as 2 when set to resolve the actual issue with the ESP32-S3
  2. Deciding on the how and adding support for 1.5 stop bits with the next major release

@sirhcel
Copy link
Contributor

sirhcel commented Jul 29, 2024

Currently serialport-rs fails to open a port when it is in this state as the stop bits setting of 1.5 is not supported This change does not allow 1.5 stop bits to be set but avoids failure to open when the port is already set to 1.5 stop bits

Looking further into this issue, I can't find the path where opening a serial port (and starting to read some data) triggers interpreting the ports current stop bits configuration. Running examples/receive_data.rs with the interpretation of any stop bit setting disabled gets to the point of waiting for incoming data:

>cargo run --example receive_data com8 115200
[...]
Receiving data on com8 at 115200 baud:

It looks like opening the port always changes the ports stop bit setting and this likely breaks communication with the ESP32-S3. But I don't see where not supporting 1.5 stop bits makes opening the port fail (like in "with an error").

How are you attempting to open the port @robdobsn and which error are you getting in this case? Could you provide an example for reproducing this issue at best?

As changing StopBits is a breaking change for the API, what about splitting this PR and tackling the issue in two steps:

  1. Reporting 1.5 stop bits as 2 when set to resolve the actual issue with the ESP32-S3

I'm asking because just adding support for interpreting the 1.5 stop bit case would not make an issue with opening the port go away.

@sirhcel sirhcel added this to the 5.0.0 milestone Jul 29, 2024
@RossSmyth
Copy link
Contributor

I did see this while reviewing other projects that does the opposite of moving to one stop bit
https://github.com/microsoft/AirSim/blob/6688d27d3712c2a9c824ababec7a2703475b6628/MavLinkCom/src/serial_com/SerialPort.cpp#L143-L145

But I think two makes more sense.

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.

4 participants