de-vri-es / serial2-rs

Cross platform serial ports for Rust
Other
47 stars 11 forks source link

Error when opening USB-to-Serial adapter #41

Closed hlima closed 22 hours ago

hlima commented 2 weeks ago

I am running this code on an RPI4b. It used to work and all of a sudden became very unstable. The code is the following:

let port_name="/dev/ttyUSB0";
let baud_rate=115200;
match SerialPort::open(&port_name, |mut settings: Settings| {
        Settings::set_raw(&mut settings);
        settings.set_baud_rate(baud_rate);
        settings.set_char_size(serial2::CharSize::Bits8);
        settings.set_stop_bits(serial2::StopBits::One);
        settings.set_parity(serial2::Parity::None);
        settings.set_flow_control(serial2::FlowControl::None);
        Ok(settings)
    }) {
        Ok(p) => {

        }
        Err(e) => {
            println!("Error opening serial port {} {}", port_name, e);
        }
    }

I am getting this error printed when the code above is executed:

Error opening serial port /dev/ttyUSB0 failed to apply some or all settings

I am using an usb FTDI usb to serial adapter. I tried with many different brands with the same result.

de-vri-es commented 2 weeks ago

Thanks for reporting the issue!

Can you open the serial port with KeepSettings and then print the settings, then try to adjust the settings, and then print the settings again?

Also, do you know if anything changed in between? Maybe an OS update?

hlima commented 2 weeks ago

settings the configuration after opening the port worked fine. As per your recommendation, I changed the code to look like this:

let port_name="/dev/ttyUSB0";
let baud_rate=115200;
match  SerialPort::open(&port_name,KeepSettings) {
        Ok(mut p) => {
            let mut settings = p.get_configuration();
            settings.set_baud_rate(baud_rate);
            settings.set_char_size(serial2::CharSize::Bits8);
            settings.set_stop_bits(serial2::StopBits::One);
            settings.set_parity(serial2::Parity::None);
            settings.set_flow_control(serial2::FlowControl::None);
            p.set_configuration(&settings);
            ...
            // everythings else worked fine
        }
        Err(e) => {
            println!("Error opening serial port {} {}", port_name, e);
        }
}

and now it works. Not sure why :-)

de-vri-es commented 2 weeks ago

Hmm, interesting. One difference is that now you don't call settings.set_raw() at the top. Does it break if you add that back?

hlima commented 2 weeks ago

One thing I noticed is that I am ignoring any error returned by set_configuration. If I change the code to:

    p.set_configuration(&settings).unwrap();

I have the same problem as before:

called `Result::unwrap()` on an `Err` value: Custom { kind: Other, error: "failed to apply some or all settings" }

If I ignore the error things work as expected.

hlima commented 2 weeks ago

One more thing. Printing the settings after the error I get the following:

setting baud rate to: 115200
Ok(Settings { baud_rate: Ok(115384), char_size: Ok(Bits8), stop_bits: Ok(One), parity: Ok(None), flow_control: Ok(None) })

The baud rate returned after setting is not the one requested 115200 != 115384

de-vri-es commented 2 weeks ago

Ah, that must be the problem. The OS selected 115384 as "close enough". But because tcsetattr on a serial port reports success if any setting has been applied (rather than if all settings have been applied), serial2 checks each setting again.

So, maybe we need to add a similar "good enough" comparison for the baud rate too.

Thanks for the extra details. I will see what kind of deviation from the baud rate is still considered acceptable normally, and adjust the check if tcattr succeeded accordingly.

de-vri-es commented 2 weeks ago

I've merged #42 into main, which should fix this issue. Could you test it before I make a new release?

When I get home after work I might also test it myself. We'll see who can test it first ;)

de-vri-es commented 22 hours ago

Releases as v0.2.27 :rocket: !

Thanks for reporting the issue!