Brent, the I2C protocol has the "clock stretching" feature, where if the slave needs more time, it can pull the clock line down and hold it down until it is ready. When the master releases the clock line and it doesn't go up because the slave is stretching the clock, the host's only option is to wait. The 'while' you mentioned in the code is indeed just an empty loop and the braces around the following block are justisleading. Bad code but not much different than a lot around. What you can do is adding a timeout in the waiting for the clock to raise and perhaps resetting the slave if it takes too long. If you are using a hardware I2C interface, I suggest you to rewrite it using a bit-banging software implementation. Best regards, Isaac Em qui, 7 de mar de 2019 22:50, Brent Brown escreveu: > Hi list, > > I've been looking for the cause of an occasional software hang-up. Happen= s > very > rarely in practice, but have found I can re-produce it at will by shortin= g > I2C line(s) to > GND. This supports the observation that the problem has only exhibited > while I was > physically handling a PCB ~ so probably an ESD transient corrupting I2C > transfer. > > If it does ever happen in the field it wouldn't be great ~ it's a battery > powered device > with an LED (that the user probably can't see) that stays on causing > considerable > current draw when the problem manifests, with no way of resetting without > removing > the batteries which requires tools. I'd like to the make the program > recover from this > auto-magically. > > I went looking though the I2C code looking for places it could hang, e.g. > while > statements. The following section of MCC generated code stands out as odd= , > within > the function I2C1_MasterTRBInsert()... > > // for interrupt based > if (*pflag =3D=3D I2C1_MESSAGE_PENDING) > { > while(i2c1_state !=3D S_MASTER_IDLE); > { > // force the task to run since we know that the queue has > // something that needs to be sent > PIR1bits.SSP1IF =3D true; > } > } // block until request is complete > > The semi-colon after the while() terminates the while statement (if I'm > not mistaken). > That's strange, as the braces that follow, and comments, suggest the line > PIR1bits.SSP1IF =3D true was intended to be inside the while loop. As it > would be if > the semi-colon wasn't there, so perhaps it could be a simple typo. > > I've updated MPLAB IDE X and MCC to latest versions, but generated code > remains identical to above. > > Tried removing the semi-colon alone, program doesn't function properly at > all. So if > the semi-colon was a typo, then it is just fortuitous that the code works > better with it > than without it. > > Tried removing the semi-colon and added an extra PIR1bits.SSP1IF =3D true= ; > after > the while loop (closer to the what the code with the supposed typo would > do), and it > seems to work better now. The I2C now works normally, still crashes with > stimulus > as described previously but now in a way that no longer causes it to hang > at this > point. That's good - I can now work on making it recover fully from such = a > glitch. > > I'm not fluent in I2C, so hard to believe I might have found misbehaving > code in the > MCC routines. I could and probably should use the WDT to recover from thi= s > and/or > other errors in a brute force kind of way, just have avoided using WDT so > far as > device is battery powered and WDT would increase power consumption ~ > though > I'm using a PIC18LF46K22 and believe I can turn the WDT off during sleep. > > After sharing all this I feel more confident about solving the problem, > but still > appreciate comments, thanks for listening~! > > Brent. > > -- > http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist > --=20 http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .