-
Notifications
You must be signed in to change notification settings - Fork 39
Conversation
need to read from idr instead from odr if MODE equals OpenDran to be able to use the OpenDrain mode properly (communicating with another chip via one line). |
Reading from IDR instead of ODR in OpenDrain mode allows one to implement protocols like OneWire using only the OutputPin trait (already implemented basic OneWire functionality that way in a local project). |
OneWire protocol implementation using an OpenDrain OutputPin. Crate also includes a ds18b20 (temperature sensor) implementation @therealprof @japaric Shall I open a ticket for the merge request? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
What if into_open_drain_output would return not only an OutputPin, but also an InputPin? This would be more clear than the specialization of the is_low() in OpenDrain mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR @kellerkindt. This basically looks good to me, but I had a question about is_low
.
src/gpio.rs
Outdated
// NOTE(unsafe) atomic write to a stateless register | ||
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) } | ||
} | ||
} | ||
|
||
/// In OpenDrain mode writing a high to the output causes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In OpenDrain mode writing a high to the output causes it to float.
So what happens if output (ODR) is set to low? Will this function do the right thing? Perhaps, this should check ODR first; if that's set to zero this returns true otherwise it returns the value stored in IDR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Writing low causes it to be pulled down to low. So if one writes high, the state depends on whether there is a pull-up resistor connected and on how other devices react, but if set to low, the output is pulled down to low by the chip.
So what happens if output (ODR) is set to low? Will this function do the right thing?
It does. I am currently communicating with ten OneWire devices through this OpenDrain implementation.
Perhaps, this should check ODR first; if that's set to zero this returns true otherwise it returns the value stored in IDR?
That should always return the same as reading directly from IDR, since the chip is trying its best to pull the pin down. I can only imagine it to return a wrong value, if one broke the output driver. I think adding a check for ODR would only cause unnecessary runtime costs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the HAL should work on every microcontroller architecture the same way.
I'm not sure that is_high(), is_low() is always available to read back output pins set state (so those could be removed from the Output trait).
I'm also not sure that an open drain out pin is always able to act the same time as input pin an read the voltage level.
On architectures, which support these, into_open_drain_output could return (OutputPin, InputPin) tuple based on the same pin, but maybe on other architectures you need to use 2 pins physically connected for the same purpose...
Unfortunately I can not tell examples for such a dumb architecture right now...
(If no one else does, then I'm perfectly fine with @kellerkindt's implementation.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the HAL should work on every microcontroller architecture the same way.
This crate is solely about the stm32f103xx family?
I'm not sure that is_high(), is_low() is always available to read back output pins set state (so those could be removed from the Output trait).
The current OutputPin trait already requires that tho. If I am not mistaken, all chips of the stm32f103xx family support the open-drain mode? Reference manual
I'm also not sure that an open drain out pin is always able to act the same time as input pin an read the voltage level.
Looking at the Reference manual (Figure 15/16/17), this shouldn't be an issue?
On architectures, which support these, into_open_drain_output could return (OutputPin, InputPin) tuple based on the same pin,
Returning a tuple would require huge refactoring, since it must be guaranteed to consume the correct two values on into_... function calls, and thus I think its not in the scope of this pull request.
But I could see one being interested to also impl InputPin for $PXi<Output<OpenDrain>>
- what do you think @japaric ?
but maybe on other architectures you need to use 2 pins physically connected for the same purpose...
For this crate, only interested in supporting the stm32f103xx family, this should be an issue?
(If no one else does, then I'm perfectly fine with @kellerkindt's implementation.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardware abstracion is about to use the same driver implementation on any microcontroller, which is valid target for rust. OutputPin trait is declared in hal::digital::OutputPin, which is not STM specific. that is why I'm not sure that is_high(), is_low() should be part of OutputPin...
But impl InputPin for $PXi<Output<OpenDrain>>
is not a bad idea on platforms which support it.
Soooo? 😁 @tib888 |
@kellerkindt
` |
This isn't possible without modifying the OutputPin trait |
I recommend modifying the names in OutputPin, because is_low has differnt meaning on OutputPin: it just reads back the previously set state, not the true level on the pin. |
…_drain_output for GPIO is not implemented yet follow: japaric/stm32f103xx-hal#51
…t<OpenDrain>>" This reverts commit da288c3. The longer I look at it, the less comfortable I feel with that implementation. The change did add no new functionality but only tried to make one thing more clear: that the pin returned by into_open_drain_output is also an InputPin. But what it also introduces was ambiguity. One cannot call is_low() is_high() on the returned pin, since InputPin and OutputPin overlap. One needs to call InputPin::is_low(&pin) or OutputPin::is_low(&pin), which raises the next question: Do these two functions behave differently? Should they? Currently they dont. My gut says they shouldn't behave differently, it would make things even more ambiguous. Since OutputPin already has is_low() and is_high(), I see no need anymore to also implement InputPin since the functions in OutputPin seem to be supposed to provide what would be gained by implementing InputPin - phew, what a sentence. Also I think, since @japaric kinda approved the state before this commit, one shouldn't make a change with such an impact afterwards. (And since a revert can be reverted easily, nothing is lost @tib888).
Since in every other method, the state should be as set by set_low / set_high. Otherwise a physical error is present (damaged output driver or short circuit - which would probably either destroy the output driver or cause the controller to be powered off). The only point I see in your argumentation is, that OutputPin::is_*(&pin) would always return the previously set state, while InputPin::is_*(&pin) reads back from the input. But as mentioned in 86842b3, I prefer to hear @japaric opinion first. (also in da288c3 was the removal of the specialization feature and default implementation missing, therefore incomplete) |
@kellerkindt, please find my proposal here, if that will be accepted it will solve this nicely. |
So, I updated this pull request to the latest changes. The Is this pull request now ready to be merged? If not, what further changes need to be made? |
Since #86 has been merged, there is no need to update the dependencies by this PR anymore. This is getting a bit frustrating with no replies in months... |
@kellerkindt, I reintroduced into_open_drain_output on my branch too. |
@tib8 Yeah, I updated this PR beginning of June to fit the the changes of the new OutputPin trait. |
I would not do that! |
The doc of The existing |
I implemented it only for $PXi<Output> because it makes sense. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
No description provided.