Preventing your I2C device from jamming up the works...
Oldbitcollector (Jeff)
Posts: 8,091
Recently I ran into an issue using the I2C objects with Wii Controllers.
Seems that if the controller wasn't plugged in, things wouldn't just continue on gracefully, the whole program would freeze.
Some investigation of the I2C code reveals some code that works like this..
Apparently this is done to stretch the clock out a bit in case the device is lagging behind the code.
I've started switching that code with something that looks like this..
This problem doesn't seem to affect other I2C scenarios, and seems to fix the issues with missing controllers.
Now things carry on without getting stuck. The official version of MIGS will also be updated soon as the I2C object there suffered from the same kinds of issues.
OBC
Seems that if the controller wasn't plugged in, things wouldn't just continue on gracefully, the whole program would freeze.
Some investigation of the I2C code reveals some code that works like this..
repeat until ina[i2cSCL] == _pinHigh
Apparently this is done to stretch the clock out a bit in case the device is lagging behind the code.
I've started switching that code with something that looks like this..
repeat 20 if ina[i2cSCL] == _pinHigh quit
This problem doesn't seem to affect other I2C scenarios, and seems to fix the issues with missing controllers.
Now things carry on without getting stuck. The official version of MIGS will also be updated soon as the I2C object there suffered from the same kinds of issues.
OBC
Comments
I'm also curious because generally clock stretching is performed by holding the clock line LOW, and given that there should be pull-ups on the I2C bus, how would the missing controller be pulling the clock line low ???
-Phil
Mostly I've seen this come up with I2C slaves that are not "hard" chips (e.g. EEPROM, RTCs, etc) but micros themselves, where the setup time for prepping bytes to the master might be much longer then the next clock pulse following addressing from the master.
-Phil
OBC
-Phil
The SDA line as well as the SCL line should be investigated during this 'hang' scenario.
http://www.esacademy.com/en/library/technical-articles-and-documents/miscellaneous/i2c-bus/i2c-bus-events/start-and-stop-conditions.html
Many Propeller-based designs (e.g. Prop Demo Board) do not include a pull-up on SCL. In cases where the I2C master drives the line both high and low, it's not necessary; but it's not a very good practice to do it that way, since it doesn't accommodate slaves that use clock stretching. Some I2C objects, instead of driving SCL both high and low with outa, use dira to toggle SCL, relying on a pull-up to take care of the logic high. This is the way it should be done, since it can accommodate clock stretching. Due to the the line of code that OBC cites, I suspect that he's using such a driver. But such drivers are not compatible with circuits that do not include the pull-up on SCL. So my guess is that OBC is using a board without the pull-up but that the Wii Controller has one built-in. This would cause the hang that he reports without the controller connected, but normal operation with it plugged in. While it's all very well to include a time-out in the code (which should be there anyway), it would be better still to add a pull-up resistor to SCL.
-Phil
Nick and I opted to remove the "optional" Wii Controller pull-up's from the last run of Quickplayer. I suspect I may include them in the next run, however I did in fact add the pull-up resistor to the board I'm running here without it making a difference in any of the original drivers. As for determining if the controller has an internal pull-up, I'm actually testing with four different controllers; Wii Classic, ClassicPro, Wii Nunchuck, and clone Nunchuck. They have all respond universally to the issue. The biggest issue that I seem to have found is that of having software "lockup" when the controller isn't present. I've re-written MIGS to skip past when the I2C device doesn't communicate in time, then return 0's on all controls when queried.
OBC
-Phil
You know Phil, I've been scratching my head over the same question.. Hence the final software solution..
If you've got a clue here, I'd love to know.
OBC
Is the line really comming up low at boot? Is the initial state of the output register somehow set to output a low in some other cog and pulling it down? That's a head scratcher for sure.
In general I like to include escape timeouts from code like that, especially when the goal involves other tasks that should continue even when one part fails. In field wiring there are all sorts of things that can go bump in the night. A device simply fails, or it falls into a vat of salt water, or a rat needs the cable jacket for its nest, or somebody fiddles with the wiring, or somebody makes a firmware change that sets the pin low from another cog, etc etc.
OBC, which i2c driver are you using? Mike's basic_i2c_driver does not support clock stretching, so it would not exhibit the problem. The only device I've used that depended on clock stretching was an ADC, the MAX1239.
The details are sparse, here.
Is this a power removal, or a complete disconnect from the pins. Is the bus shared with ANY other devices ?
Is this a removal while running scenario, or a cold power up, with no remotes plugged in ?
Clearly something, somewhere has to be pulling the pin low, (or the polled pin is moving ?).
A small series resistor will let you check the current magnitude and direction with a reasonable multimeter