Closed davidlattimore closed 2 years ago
I'm happy to make this a non-breaking change if you'd prefer. Restoring the pin mode in the release method would be the most complicated part. I think I'd need to create a new trait that reinitializes the current mode of the pin then implement that for Analog and Output
I think we can easily allow such breaking change. @dotcypress?
This is a breaking change, but I'm inclined to merge this anyway, cause this level glitch on i2c initialization phase is something that we need to remove asap.
Ok, now I'm 99% sure that using OpenDrain
mode for i2c was my design mistake. I'll mention that breaking change on release notes for the next release.
Looks like i2c stop working after merging this PR, I will dive in to find a root cause.
@davidlattimore @andresv I rolled back this commit until I found a solution.
No problem. I just updated our application to use the HAL with this commit and it seems to be working for me. I'll be interested in what you find.
@davidlattimore I just try to run https://github.com/dotcypress/minesweeper with that change and display stop working.
I believe we still need to switch mode to OpenDrainOutput
before changing alt function.
The mistake I've made: forcing user to switch pin mode to OpenDrainOutput
. Instead we need to use DefaultMode
and change mode to OpenDrainOutput
internally, with High
level by default. It will take some changes on i2c macro, I will try couple of ideas and ping you.
It looks like into_open_drain_output is enabling the internal pull-up resistors for the pin. I couldn't tell from looking at minesweeper whether you had external pull-ups or not. The internal pull-ups are fairly weak, so not sufficient for many applications (by my limited understanding of this stuff), but perhaps they're enough for your application depending on the I2C speed and timing settings.
We're using 2.2K resistors on our I2C bus, which perhaps explains why it still works for us.
Assuming that is the problem, do you think it should be left up to the user code whether to enable the internal pull-ups or not? Perhaps a config option, then passing an argument to SDAPin::setup.
I've tried with resistors(2.2K) and without: not working on both cases.
I think this happens because pin was switched to open_drain_output with default value is LOW
, pulling pins down, then after set_alt_mode
was called, i2c engine start controlling pins output.
Putting pins into open-drain mode causes them to be pulled low, which can confuse other devices on the bus.
This is a breaking change. Calling code can be fixed by not calling
into_open_drain_output()
on pins when setting up I2C.Fixes #87