Author Topic: PIC I2C deadlock and recovery  (Read 4388 times)

0 Members and 1 Guest are viewing this topic.

Offline MSOTopic starter

  • Contributor
  • Posts: 42
  • Country: us
PIC I2C deadlock and recovery
« on: March 23, 2016, 06:01:00 pm »
I’m writing an I2C slave on PIC16F1454. My slave uses a slave defined packet exchange algorithm with an unknown master (Command, Data Length, Data). My problem is deciding upon a decent deadlock detection and recovery scheme.

For instance:
 
--Master sends address with Read command
--Slave decodes address; sends ACK
   -- slave loads SSPBUF with response data byte
-- Master fails to send any more clocks

In this deadlock situation, my slave is holding SDA low (can only change SDA on SCL low following falling edge of SCL), so even if the master can recover from whatever problem it had, it’s only possible chance at recovery is send enough clocks to clear my slave.

But (there’s always a but, isn’t there?), I can’t count on the master to do that, so my slave with its ACK  holding the SDA low, will effectively lock up the I2C bus in perpetuity.  My solution is to detect the deadlock and return the I2C bus to its idle state.

My thinking is to time each exchange between my slave and whatever master happens to be controlling the bus.  If the exchange doesn’t complete within the allotted time, my slave should abandon the exchange and return the bus to its idle state.

That seems reasonable to me, but that leaves two questions: 1) What is a reasonable time to wait before abandoning the exchange and 2) what’s the best way to ‘reset’ the MSSP to return the I2C bus to its idle state?

I would think that a timeout period could be as low as tens of milliseconds up to a couple of seconds?  Any suggestions and thoughts on this are welcome.  Remember, I’m dealing with a potentially unknown master.

Second, what is a reliable method to ‘reset’ an MSSP slave?  Is toggling SSPEN (low then back to high) good enough or is there a better way to do this?

Thanks for any help, ideas or thoughts you might have.
 

Offline ade

  • Supporter
  • ****
  • Posts: 231
  • Country: ca
Re: PIC I2C deadlock and recovery
« Reply #1 on: March 23, 2016, 07:01:59 pm »
If the master has truly "gone away" then clearing the bus has no effect anyway.  It takes two to tango.

If the master has not gone away, then let the master eventually clear the deadlock (if it needs to) by running the clock then sending a stop or start.

The exception maybe is if you're in a multi-master scenario, but unless all of the masters cooperate then this won't work anyway.

In any case, SMBus has a 35ms timeout (on a 100 kHz bus) so that might be a reasonable value to use?
 

Offline Sal Ammoniac

  • Super Contributor
  • ***
  • Posts: 1668
  • Country: us
Re: PIC I2C deadlock and recovery
« Reply #2 on: March 23, 2016, 07:54:48 pm »
This may not be relevant to your circumstances, but it's one of the few app notes I've seen for dealing with I2C hangs: http://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf
Complexity is the number-one enemy of high-quality code.
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3238
  • Country: gb
Re: PIC I2C deadlock and recovery
« Reply #3 on: March 23, 2016, 10:30:44 pm »
I had to deal with this on a PIC based product many years back.  IIRC I used one of the hardware timers and reset it after every byte was received from the master, up until a stop had been sent.  If the timer rolled over the interrupt would reset the MSSP peripheral.  If the master finally woke and and sent more data it wouldn't be acknowledged so everything sorted itself out.

The optimal timeout period is really going to depend on the master device.  If you have no control over the master maybe you could make the timeout period configurable?
 

Offline MSOTopic starter

  • Contributor
  • Posts: 42
  • Country: us
Re: PIC I2C deadlock and recovery
« Reply #4 on: March 24, 2016, 02:41:56 am »
mikerj,

"I used one of the hardware timers and reset it after every byte was received from the master, up until a stop had been sent.  If the timer rolled over the interrupt would reset the MSSP peripheral."

I'm currently using a timer with a prescaler to generate a 'heartbeat' every 10msec. This heartbeat is then pushed to any registered code that wants it. My timer code increments a local variable until it gets whatever multiple of 10msec. it wants.  If it turns out that I need more flexibility, I can change the timer accordingly.

I'm interested in how you reset the MSSP; my own inclination is simply to toggle the SSPEN bit off then on again, but I don't know if that is a reliable solution.  Thanks for you help.

ade,

"In any case, SMBus has a 35ms timeout (on a 100 kHz bus) so that might be a reasonable value to use?"

Exactly the information I'm looking for. I've done I2C masters in on the MSP430, but there my master was in charge, so whatever value I picked was pretty arbitrary.  Thank you.

Sal Ammoniac,

Thanks for the link; that app note describes my problem to a 'T'. Now I know that I'm not drifting off into never-never land.  Thanks for your help.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf