Discussion:
[PIC] PIC32 I2C crashes
Neil
2018-10-15 18:38:30 UTC
Permalink
Anyone here used the PIC32 peripheral library for I2C? I'm having a
hard time with this, and can't find my ICD3 to help diagnose what's
happening.
I'm continuously reading data from a slave I2C device (PIC18F25K42
based), and the master (PIC32MX320F128H) crashes (reboots) regularly.
I'm posting about the maser here...

Flags on reboot only have the POR and BOR flags set. Adding a bit of
bulk capacitance (10uf) does not help. And this is happening with both
Pickit3 power or LiPo w/5V DC-DC power. I also don't see a way to
change BOR threshold voltage as with other PIC series.
Logic analyzer says that it's happening at different points, but always
between I2C start and stop.

I'm at a loss as to what to test next, but perhaps someone can identify
something I'm doing wrong? This is my master code to read data. The
delays were put in earlier when testing w/o error-checking, and seems to
still help to reduce crashes.
HandleI2CErrors() is just a quick function to check and clear
arbitration, TX overflow, and RX overflow errors, and also sets an LED
to alert me, but that LED stays off.

signed int ReadAFEValue(void)
{
signed int result, inVal, retVal;


retVal = 1;

if (PLIB_I2C_BusIsIdle(I2C_ID_1))
{
PLIB_I2C_MasterStart(I2C_ID_1);

// Tell AFE to restart result counter and be ready to send data...
// delay_us(100);
DelayMs(1);
if (PLIB_I2C_TransmitterIsReady(I2C_ID_1))
{

PLIB_I2C_TransmitterByteSend(I2C_ID_1,0x54); //
Slave addr 0x2A in bits 7:1. 1 in LSB = read request, or 0 = write req..
if (PLIB_I2C_TransmitterByteWasAcknowledged(I2C_ID_1))
{
// delay_us(100);
DelayMs(1);
if (PLIB_I2C_TransmitterIsReady(I2C_ID_1))
{
PLIB_I2C_TransmitterByteSend(I2C_ID_1,0xB0);
// Command for set mode to read_data mode
if (PLIB_I2C_TransmitterByteWasAcknowledged(I2C_ID_1))
{
HandleI2CErrors();

// Restart...
// delay_us(200);
DelayMs(1);
if (PLIB_I2C_BusIsIdle(I2C_ID_1))
{
PLIB_I2C_MasterStartRepeat(I2C_ID_1);

HandleI2CErrors();

// Tell AFE we want to read data now...
// delay_us(200);
DelayMs(1);
if (PLIB_I2C_TransmitterIsReady(I2C_ID_1))
{
PLIB_I2C_TransmitterByteSend(I2C_ID_1,0x55); // Slave addr 0x2A in bits
7:1. 1 in LSB = read request, or 0 = write req..
if
(PLIB_I2C_TransmitterByteWasAcknowledged(I2C_ID_1))
{
HandleI2CErrors();

// delay_us(200);
DelayMs(1);
PLIB_I2C_MasterReceiverClock1Byte(I2C_ID_1); // Get first byte back from
AFE.

// delay_us(100);
DelayMs(1);
if
(PLIB_I2C_ReceivedByteIsAvailable(I2C_ID_1))
{
if
(PLIB_I2C_MasterReceiverReadyToAcknowledge(I2C_ID_1))
{
result =
PLIB_I2C_ReceivedByteGet(I2C_ID_1); // TODO -- store this
somewhere
PLIB_I2C_ReceivedByteAcknowledge(I2C_ID_1, true);
// while
(!PLIB_I2C_ReceiverByteAcknowledgeHasCompleted(I2C_ID_1));
}
}

HandleI2CErrors();

// delay_us(200);
DelayMs(1);
PLIB_I2C_MasterReceiverClock1Byte(I2C_ID_1); // Get second byte back
from AFE.

// delay_us(200);
DelayMs(1);
if
(PLIB_I2C_ReceivedByteIsAvailable(I2C_ID_1))
{
if
(PLIB_I2C_MasterReceiverReadyToAcknowledge(I2C_ID_1))
{
inVal =
PLIB_I2C_ReceivedByteGet(I2C_ID_1); // TODO -- store
this somewhere
PLIB_I2C_ReceivedByteAcknowledge(I2C_ID_1, false); // NAK
here is required for last byte
result = result | (inVal
<< 8);
retVal = result;
}
}

HandleI2CErrors();

// DelayMs(1);
// delay_us(200);
DelayMs(1);
while
(PLIB_I2C_TransmitterIsReady(I2C_ID_1) == 0); // TODO
-- countdown and timeout here?
}
else
retVal = -8;
}
else
retVal = -7;
}
else
retVal = -6;
}
else
retVal = -5;
}
else
retVal = -4;
}
else
retVal = -3;
}
else
retVal = -2;

PLIB_I2C_MasterStop(I2C_ID_1);
}

return retVal;
} // ReadAFEValue()



Cheers,
-Neil
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
Harold Hallikainen
2018-10-15 19:49:45 UTC
Permalink
I have always talked directly to the I2C port instead of using the
library. Also, for me to get I2C to work, I generally need a logic
analyzer to watch the bus and a debugger for the PIC. It's very difficult
for me to get I2C working without the debugger and logic analyzer (may be
impossible... never tried!).

Not much help...

Good luck!

Harold
--
FCC Rules Updated Daily at http://www.hallikainen.com
Not sent from an iPhone.
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
Neil
2018-10-15 20:33:41 UTC
Permalink
I'm still also unclear if I'm doing something wrong on the slave
(PIC1825K42) side, but that's MCC-generated code, which is very
undocumented. I was told that I pretty much need to figure that out
from the header file comments.
Either way, nothing that the slave does should cause the master to
crash/reset.

My local FAE has tried to convince me that the MCC/harmony/libraries
would save me time and aggravation, but I'm far from convinced at this
point. At least with my own code, I know where to look for issues.

Cheers,
-Neil.
Post by Harold Hallikainen
I have always talked directly to the I2C port instead of using the
library. Also, for me to get I2C to work, I generally need a logic
analyzer to watch the bus and a debugger for the PIC. It's very difficult
for me to get I2C working without the debugger and logic analyzer (may be
impossible... never tried!).
Not much help...
Good luck!
Harold
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
John J. McDonough
2018-10-15 20:38:01 UTC
Permalink
Post by Harold Hallikainen
I have always talked directly to the I2C port instead of using the
library. Also, for me to get I2C to work, I generally need a logic
analyzer to watch the bus and a debugger for the PIC. It's very difficult
for me to get I2C working without the debugger and logic analyzer (may be
impossible... never tried!).
Interesting. I have never used I2C on a PIC32, but on a dsPIC, it has
never been much of a problem. I never was able to make it work on a
16F, however. But then, I tend to avoid Microchip libraries.

--McD
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
AB Pearce - UKRI STFC
2018-10-15 21:41:33 UTC
Permalink
I never was able to make it work on a 16F, however. But then, I tend to avoid Microchip libraries.
I had no problem getting both master and slave code running on 16F876 chips. I used the Microchip AN74x? code, but was alerted to a missing line of code in one of them by someone on this list who had also used it. Because of that I had it working more or less straight out of the box. The code in the app notes doesn't use interrupts but I modified to do so. Didn't take a lot of effort to change.
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
Manu Abraham
2018-10-15 20:09:19 UTC
Permalink
Very hard to read your code, but:
Does your slave support REPEATED START ? Not all slaves do support it.

Cheers,
Manu
Post by Neil
Anyone here used the PIC32 peripheral library for I2C? I'm having a
hard time with this, and can't find my ICD3 to help diagnose what's
happening.
I'm continuously reading data from a slave I2C device (PIC18F25K42
based), and the master (PIC32MX320F128H) crashes (reboots) regularly.
I'm posting about the maser here...
Flags on reboot only have the POR and BOR flags set. Adding a bit of
bulk capacitance (10uf) does not help. And this is happening with both
Pickit3 power or LiPo w/5V DC-DC power. I also don't see a way to
change BOR threshold voltage as with other PIC series.
Logic analyzer says that it's happening at different points, but always
between I2C start and stop.
I'm at a loss as to what to test next, but perhaps someone can identify
something I'm doing wrong? This is my master code to read data. The
delays were put in earlier when testing w/o error-checking, and seems to
still help to reduce crashes.
HandleI2CErrors() is just a quick function to check and clear
arbitration, TX overflow, and RX overflow errors, and also sets an LED
to alert me, but that LED stays off.
signed int ReadAFEValue(void)
{
signed int result, inVal, retVal;
retVal = 1;
if (PLIB_I2C_BusIsIdle(I2C_ID_1))
{
PLIB_I2C_MasterStart(I2C_ID_1);
// Tell AFE to restart result counter and be ready to send data...
// delay_us(100);
DelayMs(1);
if (PLIB_I2C_TransmitterIsReady(I2C_ID_1))
{
PLIB_I2C_TransmitterByteSend(I2C_ID_1,0x54); //
Slave addr 0x2A in bits 7:1. 1 in LSB = read request, or 0 = write req..
if (PLIB_I2C_TransmitterByteWasAcknowledged(I2C_ID_1))
{
// delay_us(100);
DelayMs(1);
if (PLIB_I2C_TransmitterIsReady(I2C_ID_1))
{
PLIB_I2C_TransmitterByteSend(I2C_ID_1,0xB0);
// Command for set mode to read_data mode
if (PLIB_I2C_TransmitterByteWasAcknowledged(I2C_ID_1))
{
HandleI2CErrors();
// Restart...
// delay_us(200);
DelayMs(1);
if (PLIB_I2C_BusIsIdle(I2C_ID_1))
{
PLIB_I2C_MasterStartRepeat(I2C_ID_1);
HandleI2CErrors();
// Tell AFE we want to read data now...
// delay_us(200);
DelayMs(1);
if (PLIB_I2C_TransmitterIsReady(I2C_ID_1))
{
PLIB_I2C_TransmitterByteSend(I2C_ID_1,0x55); // Slave addr 0x2A in bits
7:1. 1 in LSB = read request, or 0 = write req..
if
(PLIB_I2C_TransmitterByteWasAcknowledged(I2C_ID_1))
{
HandleI2CErrors();
// delay_us(200);
DelayMs(1);
PLIB_I2C_MasterReceiverClock1Byte(I2C_ID_1); // Get first byte back from
AFE.
// delay_us(100);
DelayMs(1);
if
(PLIB_I2C_ReceivedByteIsAvailable(I2C_ID_1))
{
if
(PLIB_I2C_MasterReceiverReadyToAcknowledge(I2C_ID_1))
{
result =
PLIB_I2C_ReceivedByteGet(I2C_ID_1); // TODO -- store this
somewhere
PLIB_I2C_ReceivedByteAcknowledge(I2C_ID_1, true);
// while
(!PLIB_I2C_ReceiverByteAcknowledgeHasCompleted(I2C_ID_1));
}
}
HandleI2CErrors();
// delay_us(200);
DelayMs(1);
PLIB_I2C_MasterReceiverClock1Byte(I2C_ID_1); // Get second byte back
from AFE.
// delay_us(200);
DelayMs(1);
if
(PLIB_I2C_ReceivedByteIsAvailable(I2C_ID_1))
{
if
(PLIB_I2C_MasterReceiverReadyToAcknowledge(I2C_ID_1))
{
inVal =
PLIB_I2C_ReceivedByteGet(I2C_ID_1); // TODO -- store
this somewhere
PLIB_I2C_ReceivedByteAcknowledge(I2C_ID_1, false); // NAK
here is required for last byte
result = result | (inVal
<< 8);
retVal = result;
}
}
HandleI2CErrors();
// DelayMs(1);
// delay_us(200);
DelayMs(1);
while
(PLIB_I2C_TransmitterIsReady(I2C_ID_1) == 0); // TODO
-- countdown and timeout here?
}
else
retVal = -8;
}
else
retVal = -7;
}
else
retVal = -6;
}
else
retVal = -5;
}
else
retVal = -4;
}
else
retVal = -3;
}
else
retVal = -2;
PLIB_I2C_MasterStop(I2C_ID_1);
}
return retVal;
} // ReadAFEValue()
Cheers,
-Neil
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
Neil
2018-10-15 20:39:24 UTC
Permalink
Not aware of this, but I'll check. Slave is a PIC18F25K42 running
MCC-generated code structure. I've used this to try and isolate myself
from the nit-picky details, but it's more and more looking like I should
be setting registers manually like I always do.

Cheers,
-Neil.
Post by Manu Abraham
Does your slave support REPEATED START ? Not all slaves do support it.
Cheers,
Manu
Post by Neil
Anyone here used the PIC32 peripheral library for I2C? I'm having a
hard time with this, and can't find my ICD3 to help diagnose what's
happening.
I'm continuously reading data from a slave I2C device (PIC18F25K42
based), and the master (PIC32MX320F128H) crashes (reboots) regularly.
I'm posting about the maser here...
Flags on reboot only have the POR and BOR flags set. Adding a bit of
bulk capacitance (10uf) does not help. And this is happening with both
Pickit3 power or LiPo w/5V DC-DC power. I also don't see a way to
change BOR threshold voltage as with other PIC series.
Logic analyzer says that it's happening at different points, but always
between I2C start and stop.
I'm at a loss as to what to test next, but perhaps someone can identify
something I'm doing wrong? This is my master code to read data. The
delays were put in earlier when testing w/o error-checking, and seems to
still help to reduce crashes.
HandleI2CErrors() is just a quick function to check and clear
arbitration, TX overflow, and RX overflow errors, and also sets an LED
to alert me, but that LED stays off.
signed int ReadAFEValue(void)
{
signed int result, inVal, retVal;
retVal = 1;
if (PLIB_I2C_BusIsIdle(I2C_ID_1))
{
PLIB_I2C_MasterStart(I2C_ID_1);
// Tell AFE to restart result counter and be ready to send data...
// delay_us(100);
DelayMs(1);
if (PLIB_I2C_TransmitterIsReady(I2C_ID_1))
{
PLIB_I2C_TransmitterByteSend(I2C_ID_1,0x54); //
Slave addr 0x2A in bits 7:1. 1 in LSB = read request, or 0 = write req..
if (PLIB_I2C_TransmitterByteWasAcknowledged(I2C_ID_1))
{
// delay_us(100);
DelayMs(1);
if (PLIB_I2C_TransmitterIsReady(I2C_ID_1))
{
PLIB_I2C_TransmitterByteSend(I2C_ID_1,0xB0);
// Command for set mode to read_data mode
if (PLIB_I2C_TransmitterByteWasAcknowledged(I2C_ID_1))
{
HandleI2CErrors();
// Restart...
// delay_us(200);
DelayMs(1);
if (PLIB_I2C_BusIsIdle(I2C_ID_1))
{
PLIB_I2C_MasterStartRepeat(I2C_ID_1);
HandleI2CErrors();
// Tell AFE we want to read data now...
// delay_us(200);
DelayMs(1);
if (PLIB_I2C_TransmitterIsReady(I2C_ID_1))
{
PLIB_I2C_TransmitterByteSend(I2C_ID_1,0x55); // Slave addr 0x2A in bits
7:1. 1 in LSB = read request, or 0 = write req..
if
(PLIB_I2C_TransmitterByteWasAcknowledged(I2C_ID_1))
{
HandleI2CErrors();
// delay_us(200);
DelayMs(1);
PLIB_I2C_MasterReceiverClock1Byte(I2C_ID_1); // Get first byte back from
AFE.
// delay_us(100);
DelayMs(1);
if
(PLIB_I2C_ReceivedByteIsAvailable(I2C_ID_1))
{
if
(PLIB_I2C_MasterReceiverReadyToAcknowledge(I2C_ID_1))
{
result =
PLIB_I2C_ReceivedByteGet(I2C_ID_1); // TODO -- store this
somewhere
PLIB_I2C_ReceivedByteAcknowledge(I2C_ID_1, true);
// while
(!PLIB_I2C_ReceiverByteAcknowledgeHasCompleted(I2C_ID_1));
}
}
HandleI2CErrors();
// delay_us(200);
DelayMs(1);
PLIB_I2C_MasterReceiverClock1Byte(I2C_ID_1); // Get second byte back
from AFE.
// delay_us(200);
DelayMs(1);
if
(PLIB_I2C_ReceivedByteIsAvailable(I2C_ID_1))
{
if
(PLIB_I2C_MasterReceiverReadyToAcknowledge(I2C_ID_1))
{
inVal =
PLIB_I2C_ReceivedByteGet(I2C_ID_1); // TODO -- store
this somewhere
PLIB_I2C_ReceivedByteAcknowledge(I2C_ID_1, false); // NAK
here is required for last byte
result = result | (inVal
<< 8);
retVal = result;
}
}
HandleI2CErrors();
// DelayMs(1);
// delay_us(200);
DelayMs(1);
while
(PLIB_I2C_TransmitterIsReady(I2C_ID_1) == 0); // TODO
-- countdown and timeout here?
}
else
retVal = -8;
}
else
retVal = -7;
}
else
retVal = -6;
}
else
retVal = -5;
}
else
retVal = -4;
}
else
retVal = -3;
}
else
retVal = -2;
PLIB_I2C_MasterStop(I2C_ID_1);
}
return retVal;
} // ReadAFEValue()
Cheers,
-Neil
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
Loading...