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

Implement open drain output #263

Merged
merged 6 commits into from
May 9, 2022
Merged

Conversation

agausmann
Copy link
Contributor

@agausmann agausmann commented May 2, 2022

Based on #217 as it has been inactive. I've rebased it on the latest main and addressed the comments in the original pull request.

@Rahix Rahix added hal-api API design for the different components of avr-hal hal-generic Related to MCU generic parts of avr-hal labels May 2, 2022
Copy link
Owner

@Rahix Rahix left a comment

Choose a reason for hiding this comment

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

Hey, thanks for picking this back up! I've got two comments, apart from that it looks good to go.

avr-hal-generic/src/port.rs Outdated Show resolved Hide resolved
avr-hal-generic/src/port.rs Outdated Show resolved Hide resolved
@agausmann agausmann requested a review from Rahix May 2, 2022 21:09
Copy link
Owner

@Rahix Rahix left a comment

Choose a reason for hiding this comment

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

Looks good, thanks! Just to make sure: Did you test that it behaves correctly on real hardware? If not, I can take care of it in the coming days.

@agausmann
Copy link
Contributor Author

I haven't yet, but I can do a test sometime today

@agausmann
Copy link
Contributor Author

agausmann commented May 3, 2022

I tested it with this modified uno-blink example:
(Switched to d12 pin so there's no other circuitry going on, and also because it's the reverse current direction of the built-in LED)

Measured the resistance to ground and the voltage (with a pullup) and it seems to work as expected.

#![no_std]
#![no_main]

use panic_halt as _;

#[arduino_hal::entry]
fn main() -> ! {
    let dp = arduino_hal::Peripherals::take().unwrap();
    let pins = arduino_hal::pins!(dp);

    let mut led = pins.d12.into_opendrain_high();

    loop {
        led.set_high();
        arduino_hal::delay_ms(500);
        led.set_low();
        arduino_hal::delay_ms(500);
        led.set_high();
        arduino_hal::delay_ms(500);
        led.set_low();
        arduino_hal::delay_ms(1000);
    }
}

@agausmann
Copy link
Contributor Author

One thing I noticed is that there isn't a toggle method or an implementation of ToggleableOutputPin for Pin<OpenDrain> (in fact, there is no StatefulOutputPin or ToggleableOutputPin for Pin<Output> either 🤔 ). Is that something that we'd want?

@stappersg
Copy link
Contributor

One thing I noticed is that there isn't a toggle method or an implementation of ToggleableOutputPin for Pin<OpenDrain> (in fact, there is no StatefulOutputPin or ToggleableOutputPin for Pin<Output> either thinking ). Is that something that we'd want?

We should want that the hardware provides. If the open drain output can not be read back, don't do it, do not fake toggle for something that can not be toggled.

(My definition of toggle is an atomic read level and write invert level back, something that will work for a push-pull-output-pin. (But we are dealing with open drain outpt.))

@agausmann
Copy link
Contributor Author

agausmann commented May 3, 2022

@stappersg Glancing at the ATmega328P datasheet, the bits of DDRx registers are labeled R/W, so I'm pretty sure we can determine the state of open-drain pins, and I'd assume that's also a feature on other models. So that's some justification for a StatefulOutputPin impl. (EDIT: didn't even need to check that, we already have is_high and is_low methods for open-drain pins)

And there is precedent for a read-modify-write implementation for ToggleableOutputPin. (For example, the unproven toggleable::Default trait in embedded-hal, which was even used for push-pull outputs in avr-hal prior to #56 landing.

@Rahix
Copy link
Owner

Rahix commented May 9, 2022

One thing I noticed is that there isn't a toggle method or an implementation of ToggleableOutputPin for Pin (in fact, there is no StatefulOutputPin or ToggleableOutputPin for Pin either thinking ). Is that something that we'd want?

Sure, this would also be nice. But I suggest adding it in a separate MR...

didn't even need to check that, we already have is_high() and is_low() methods for open-drain pins

Careful! is_high()/is_low() have a different meaning than is_set_high()/is_set_low(). The former is meant to read the electrical state of the pin. Thus their return value can be influenced by outside circuitry. The latter must not read the electrical state but return what state the microcontroller last set the pin to. This means their return value must not be influenced by outside circuitry.

This is especially important for open-drain outputs. After a set_high(), the open-drain pin might still return true for is_low() when pulled to GND externally. But is_set_low() must not be true.

@Rahix Rahix merged commit d13d82d into Rahix:main May 9, 2022
@Rahix Rahix mentioned this pull request May 9, 2022
@agausmann
Copy link
Contributor Author

Careful! is_high()/is_low() have a different meaning than is_set_high()/is_set_low(). The former is meant to read the electrical state of the pin.

Oh, thanks, I should have looked more closely, it does use in_get().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hal-api API design for the different components of avr-hal hal-generic Related to MCU generic parts of avr-hal
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants