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

Add open-drain output implementation #552

Closed
bartweber opened this issue Feb 17, 2023 · 5 comments · Fixed by #585
Closed

Add open-drain output implementation #552

bartweber opened this issue Feb 17, 2023 · 5 comments · Fixed by #585

Comments

@bartweber
Copy link

For convenience, please add an open-drain output implementation. I experimented with the implementation InOutPin used in the example rp2040-hal/examples/dht11.rs for communication with the 1-wire protocol (i.c.w. a DS18B20), but it seems to be unreliable. (Or more accurately: not working at all.)

As stated in the example, it is not possible to drive the pin low before changing the pin mode to output to emulate the open-drain output low state.

// In theory, we should set the pin to low first, to make sure we never actively
// pull it up. But if we try it on the input pin, we get Err(Gpio(InvalidPinType)).

It seems to me this cannot be solved by a custom DynPin implementation (as is done in the example) and should be solved in the rp2040-hal itself. Hence this ticket.

In another hals - e.g. https://github.com/stm32-rs/stm32f3xx-hal - this pin mode is implemented.
I would suggest a method like into_open_drain_output() as used in:

let mut one_wire_pin = pins.gpio0.into_open_drain_output();

To sum up the requirements (please correct me if I am wrong):

  • the open-drain output Pin should implement the HAL traits OuputPin and InputPin;
  • when the Pin's method set_low is called, the pin should be set to low and switch its internal mode by using the following ModeFields values: funcsel=SIO_FUNCSEL, sio_outen = true, inen = true and all other fields set to false;
  • when the Pin's method set_high is called, the pin should switch its internal mode by using the following ModeFields values: funcsel = SIO_FUNCSEL, sio_outen = false, inen = true and all other fields set to false;
  • switch from low to high and visa versa should be fast.
@ithinuel
Copy link
Member

The main reason for not implementing this so far is that the hardware does not support it. It has to be emulated with controling OE.

The difference with the st hal (and lots of other silicon) is that they do have support for it in hardware (see stm32f3xx reference manual page 228/1141 – 11.3 GPIO Functional description).

@bartweber
Copy link
Author

bartweber commented Feb 18, 2023

Ai, I should have RTFM first. Somehow I got the idea that all modern micro-controllers have no other option than to emulate the open-drain output. (I'm a software developer for many years but a beginner/hobbyist in embedded programming and electronics.)

In this case I might be better of with an I2C to 1-wire bridge (like the DS2482). No any hassle with the 1-wire protocol. (One disadvantage of this option is though, there no lib written in Rust yet for this device.)

@jannic
Copy link
Member

jannic commented Feb 18, 2023

Well, that's an opportunity to write a driver for the weekly driver initiative :-)

Seriously: @ithinuel correctly explained why there is no open-drain output implementation. But that doesn't mean that the rp2040 is unable to speak the 1-wire protocol. If the emulated InOutPin doesn't work, we should find out why.

@anall
Copy link
Contributor

anall commented Feb 19, 2023

I actually considered adding support for open drain/open collector [by fiddling OE] when doing the conversion to the type-based GPIO, but didn't want the added complexity when the original code didn't support it.

I don't think it would be that hard to add.

@jannic
Copy link
Member

jannic commented Feb 19, 2023

I probably wouldn't call it open drain/open collector. It works similar, but electrically, it's something different. I'm not knowledgeable enough about electrical circuits to tell if it actually makes a difference, so I'd just be cautious and give it some neutral name. That's why I just called it InOutPin in the dht11 example.
And yes, it shouldn't be hard to add. Hardest thing would be to find a good API (ie. as flexible as possible without becoming difficult to use).

@jannic jannic linked a pull request May 20, 2023 that will close this issue
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 a pull request may close this issue.

4 participants