embedded-hal
embedded-hal copied to clipboard
[Discussion] `digital` marker traits, such as `digital::StronglyDriven`, `digital::OpenDrain`, `digital::OpenCollector`, etc.
Many MCUs (the STM32s especially) implement a plethora of different output options for their GPIO pins. A driver generally has specific output requirements for its pins -- but enforcing these with API traits will mean there will be many traits available, all implementing similar or identical APIs -- i.e. OutputStronglyDrivenPin
, OutputOpenDrainPin
, OutputOpenDrainPullupPin
, etc.
Advantages
- One API for high-level pin mode (
IoPin
,InputPin
,OutputPin
), with additional traits providing fine-grained configurability - Unusual combinations easy to express (
OutputPin + OpenDrain + PullUp
)
Disadvantages
- Possible huge proliferation of implementer types
- The actual pin driving code will likely look similar for all, but initialization will be different. Does this force too much duplication/boilerplate?
- Could this be handled by a builder-like pattern? i.e. pin init functions which consume a type with/without the marker trait, change the config, and return a type without/with the trait?
- Possibility of expressing impossible bounds (i.e.
OutputPin + StronglyDriven + OpenDrain
).- Mostly a problem from the driver writer's standpoint, and it will become quickly clear that no available HAL provides the type needed
Example driver usage
pub struct BitBangedI2c<D, C> {
sda: D,
scl: C,
}
impl<D, C> BitBangedI2c<D, C> {
pub fn new<D, C>(sda: D, scl: C) -> BitBangedI2c<D, C>
where
D: digital::IoPin + digital::OpenDrain,
C: digital::IoPin + digital::OpenDrain,
{
BitBangedI2c { sda, scl }
}
}
Please find a related discssion here: https://github.com/japaric/stm32f103xx-hal/pull/51