I2C Data needs an Open Drain IO Pad, but if this is to be Muxed then the OD needs to be controlled via CSRs not hardwired. i.e. the IOPad needs to be possible to switch between Open Drain and Push-Push under the control of GPIO CSRs. Staf, is this possible? i know you designed the original FlexLib IOPad to be general purpose, it was hardwired in alliance-check-toolkit iolib
It seems that Open Drain can be implemented by a constant zero output, and switching the tri-state/direction/oe control signal (1=tri-state, 0=push-pull to ground).
(In reply to Cesar Strauss from comment #1) > It seems that Open Drain can be implemented by a constant zero output, and > switching the tri-state/direction/oe control signal (1=tri-state, > 0=push-pull to ground). interesting. this would however need to be done by a mux, where "if the output is zero, also flip the IOpad out-enable to zero" which, now that i think about it, can be handled by the GPIO subsystem. my only concern is: timing. but, hey, Open Drain does not switch quickly anyway. I2C maxes out at 400 khz.
I don't see the problem. IC controller will deliver i, o, oe signals; if you want to MUX it with a signal that is only output you need to mux 1 on oe. If you want to mux it with only input signal you need to mux 0 on oe pin.
(In reply to Staf Verhaegen from comment #3) > I don't see the problem. IC controller will deliver i, o, oe signals; if you > want to MUX it with a signal that is only output you need to mux 1 on oe. If > you want to mux it with only input signal you need to mux 0 on oe pin. I2C is very strange, it is a shared cooperative bus. even when one master one slave the SDA data line is timeshared between them. however SDA it is not a push-push driven line: it is Open Drain with external pullup 2.2 kOhm resistors at each peripheral. so you are only allowed to pull it to GND, to signal a zero, and to indicate a 1 it must be put tristate, letting the 2.2k resistor bring the line HI. (actually that might be the other way round: to signal a *one* pull to GND, to signal a zero it must be tristated) the danger of multiple slaves going amok and accidentally getting into a current fight by one trying to push HI and the other push the line LO if ever they get out of sync is thus avoided. two push-push drivers would be a short circuit and would damage one or both IO Pads.
(In reply to Cesar Strauss from comment #1) > It seems that Open Drain can be implemented by a constant zero output, and > switching the tri-state/direction/oe control signal (1=tri-state, > 0=push-pull to ground). (edited, i got it hi not lo) # Open Drain Mode, made with a standard FlexLib IOlib cell with m.If(sda.oe): # Open Drain Output with m.If(sda.o == 1): # HI output is floating comb += pad.oe.eq(0) comb += pad.o.eq(0) with m.Else(): # LO output, drive output to GND. comb += pad.oe.eq(1) comb += pad.o.eq(0) with m.Else(): comb += pad.oe.eq(0) comb += sda.i.eq(pad.i) this will do the job, Staf: no need to change IOLib
(In reply to Luke Kenneth Casson Leighton from comment #5) > # Open Drain Mode, made with a standard FlexLib IOlib cell simplified: comb += pad.o.eq(0) comb += pad.oe.eq(sda.oe & ~sda.o) comb += sda.i.eq(pad.i) # i is always connected, allowing us to later add support for detecting when the i2c bus is being driven by two or more endpoints at once by checking that i matches what we were trying to transmit.
(In reply to Luke Kenneth Casson Leighton from comment #5) > (In reply to Cesar Strauss from comment #1) > > It seems that Open Drain can be implemented by a constant zero output, and > > switching the tri-state/direction/oe control signal (1=tri-state, > > 0=push-pull to ground). > > (edited, i got it hi not lo) > > # Open Drain Mode, made with a standard FlexLib IOlib cell > with m.If(sda.oe): > # Open Drain Output > with m.If(sda.o == 1): > # HI output is floating > comb += pad.oe.eq(0) > comb += pad.o.eq(0) > with m.Else(): > # LO output, drive output to GND. > comb += pad.oe.eq(1) > comb += pad.o.eq(0) > with m.Else(): > comb += pad.oe.eq(0) > comb += sda.i.eq(pad.i) > > this will do the job, Staf: no need to change IOLib This should not be needed, your I2C master should already make sure oe=0 when wanting 1 on output and oe=1 + o=0 when wanting 0 on output.
> This should not be needed, your I2C master should already make sure oe=0 > when wanting 1 on output and oe=1 + o=0 when wanting 0 on output. What I have seen is an I2C controller that puts always 0 on o and then control the output by only enabling or disabling oe.
(In reply to Staf Verhaegen from comment #7) > This should not be needed, your I2C master should already make sure oe=0 > when wanting 1 on output and oe=1 + o=0 when wanting 0 on output. this is for an I2C master. in STM32F Embedded Controllers, for convenience, it is the PHY that [automatically] does this OE/O trick for you, and to do so the pinmux GPIO settings must put the Pad into this "Open Drain" config mode. (the ability to set an OD Mode has been standard practice for the entire STM32F range since its inception) if bit-banging as a software-controlled pad, then yes absolutely it is perfectly fine to do - under software control - "rewrite GPIO to OE and switch O". ...HOWEVER... if there are separate CSR memory-mapped registers for OE as separate and distinct from O OR if, internally, the CSRs are split (wishbone bus 32-bit to 8-bit) internally such that OE is set on one clock cycle and O is set on another then you have a problem: glitching of the output. so, software bit-banging control to emulate I2C has two problems: 1) it's bit-banging. it takes up CPU cycles and requires great care in the design of the bit-banging. 2) very careful design of the GPIO CSR Banks is required compared to adding an Open Drain Mode in the GPIO CSR Bank, which is what all STM32F Series ECs do, the problems go away, both at the hardware level and the software level (even if bit-banging is used). (In reply to Staf Verhaegen from comment #8) > > This should not be needed, your I2C master should already make sure oe=0 > > when wanting 1 on output and oe=1 + o=0 when wanting 0 on output. > > What I have seen is an I2C controller that puts always 0 on o and then > control the output by only enabling or disabling oe. interesting! yes that would work. and would avoid output glitching in software-level bit-banging. Open Collector would be "always put a 1 on o". anyway: the main point of this bugreport was: "is any change needed to FlexLib IOPad Cell" and the answer is definitely "no". so i am closing this bugreport as resolved.
as an fyi: https://github.com/libopencm3/libopencm3/blob/ed2aada3e8c84d085f4f3451a9b9cdf36b893d62/include/libopencm3/stm32/common/gpio_common_f234.h#L192 /* --- GPIOx_OTYPER values ------------------------------------------------- */ /** @defgroup gpio_output_type GPIO Output Pin Driver Type @ingroup gpio_defines @{*/ /** Push Pull */ #define GPIO_OTYPE_PP 0x0 /** Open Drain */ #define GPIO_OTYPE_OD 0x1