I've got a question regarding something specific I'm trying to implement on a PSoC5LP:
I have an I2C bus with a single slave device. The PSoC is the bus master, and the bus is entirely onboard with no access external to the PCB.
For testing purposes, I would like to (on reception of a RS232 command) switch it out to an external master using some free GPIO pins on the PSoC. Redirecting SDA and SCL away from the I2C component on the PSoC, and allowing the externally connected device to take over as master of the bus.
Here's what I came up with for the PSoC Schematic:
TW_SDA and TW_SCL are the internal i2c bus pins.
GPIO1 and GPIO2 are the pins that lead to a connector I want to use for our new I2C Master.
This appears to not work, and the external master seems unable to communicate with the slave device on the internal bus. We first thought maybe the GPIO pins needed their own pull-ups, as all these pins are Open Drain/Drive Low. I thought that maybe there is no direct hardware connection between GPIO/I2C pins when TW_I2C_BUS_SELECT is set to 1. If this is the case, GPIO1 and GPIO2 would need pull-up resistors. We added some pull-up resistors to GPIO1 and GPIO2 to see if anything would change but it didn't have any effect.
Is what I'm looking to do possible? Or am I misunderstanding how to go about this? Or 3rd option, this SHOULD work and I'm doing something else wrong?
Thanks for the input!
Solved! Go to Solution.
Let me see if I understand your question correctly.
You have a board with a PSoC CPU acting as the I2C master. On the board is an external I2C slave.
You want to place a connections on the board (at least temporarily) to allow an external I2C master to drive the I2C slave.
Is this correct?
If my assumption is correct, then the answer to your question is simple.
The I2C bus is open-drain output with external pull-ups. If you make a connection to SCL, SDA and GND to an external master, you should be able to directly talk to the I2C slave. This is because I2C by it design is a "Wired 'OR'" bus.
This only issue you should encounter is if the I2C master on the PSoC is trying to talk to the I2C slave at the same time.
To prevent this I provide two solutions.
The first solution is for testing purposes disable the I2C Master component from the TopDesign.
The second solution can use the UART command you indicated earlier and use the command activation to stop (or disable) the I2C component in SW.
Close, but not quite what I'm after. If I had a connection to the I2C bus leading off-board there would be no issue, and I would do exactly what you mentioned, just disabling the PSoC5LP MI2C component when I want to control externally.
The problem is that I don't have a connection to the bus from off-board. What I do have is spare GPIO connected to the PSoC I can access externally. What I want to do is have an external master able to drive the slave device through the PSoC.
I am set up like this in hardware:
I want to do this, using the PSoC to bridge SCL/SDA to the external master:
I basically created the same schematic for the pass-thru connection as you.
There is one possible difference. Since you don't define the connections outside the PSoC, I detail this in my schematic.
Both the I2C bus to the Slave has external pull-ups of 1K and the External Master I2C bus has 1K resistors.
Is this the case in your non-working implementation?
Yes we have pull-ups installed on both the internal I2C bus as well as the GPIO pins intended to be used for an external master.
The internal bus pull-ups are 1k, and the ones connected to the external bus are 2k (maybe different pull-up values is causing an issue?). The GPIO pins are configured for Open-Drain Drive Low like a typical I2C pin.
If we're pretty confident this should work as it is currently configured, I'll have to dig in a little deeper and have a look at the I2C lines with a scope/analyzer.
EDIT: Had a look on the scope and when i switch the muxes to point to the external bus for some reason both the internal and external lines are being held low. Not sure why that is but I will keep tinkering. Maybe there's some kind of issue with having 2 bidirectional pins connected to one another?
It seems is a simple solution to get the I2C lines passing through from one I2C bus to other, but it is not. You need to create a state machine to mimic a I2C Master on PSoC. Even a simple 1-to-1 (One Master, One Slave), both external to PSoC, requires a state machine.
Connecting the two buses internally would create a latch:
Long time ago, we created a component that implements 1-1 I2C Mux. This was designed for PSoC 3, but you can use it with PSoC 5LP as well.
If you add an I2C Master internally (which is your case), then you can use the internal muxes (in conjunction with the 1-1 I2C Mux) to select which master to connect to the slave (as proposed by Len).
Refer to the attached project to get the 1-1 I2C Mux component.
I'm not very savvy as a I2C user. I've never used this interface in my own projects. If I understand you correctly, the interface Kyle and I propose doesn't solve the the bidirectional control of the SDA signal without proper state logic.
There is a section in the I2C datasheet showing a i2C multiplexing scheme. Apparently you are suggesting this circuit would not apply here.
Is it possible to use the analog on the SDA and SCL pins as a pass-thru? Here is a suggested circuit:
The muxing you showed (an internal Master) works. The problem is when the I2C Master is external, where you need to do a pass-through, which is part the original statement of this post.
The problem with the analog route is that the internal resistance of the analog switches makes the total resistance of the analog connection too high for I2C applications.
So, just making sure I have a proper understanding:
In order to do bus multiplexing to pass through an external master onto an internal bus, I would have to essentially write an i2c state machine in firmware to act as the bridge.
For now It's looking like it would be easier if I just tack some wires onto the bus on our testing PCB and manually connect my other I2C master.
Since this is functionality is only needed for testing purposes, and would never need to be used in production, modifying our test board for this custom feature is not a huge deal.
Thank you for the clarification on this.
If it is an internal bus (the master or slave is on PSoC), you don't need a state machine. The problem is when you have two external buses, and you want to connect them through the PSoC. In this case, you need a state machine.
You don't need to implement the state machine in firmware. You can do it in hardware. That's what the I2CMUx component does.
I guess I'm slightly confused as to the distinction between "Internal" and "External" busses in this case.
A more detailed block diagram of what I want to do is below:
Mux selection 0 would be PSoC SDA/SCL to SDA/SCL
Mux selection 1 would be EXT SDA/SCL to SDA/SCL
When EXT SDA/SCL is connected with Mux Selection 1, the PSoC MI2C Component would be completely removed from the "active" bus, and the external master is in control of the slave device.
This is doable with only the I2CMux component? Or would a state machine be required?
Thanks again, I appreciate the help wrapping my head around this.
I'm incredibly close, that block diagram cleared alot up. Here's what I ended up with, and it's very close to working:
This almost works (and works perfectly when using the PSoC internal master TW_I2C), but I think something is messed up with maybe the internal state machine? It looks like ACK pulses from the slave device aren't making it back to the external bus. See this logic analyzer capture:
Possibly something with the I2C Mux state machine setting pin direction/drive?
Also, is there any recommendation of what to use for the CLOCK input of the I2C Mux component? Dependent on I2C clock speed maybe (I am only running the I2C at 100kHz) I tried the 1.6MHz shown in your posted example but no luck.
I'll keep messing around with it, maybe I'm missing something obvious with the pins or something.