![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
KTrenholm
Joined: 19 Dec 2012 Posts: 43 Location: Connecticut, USA
|
I2C Uneven SCL Pulses |
Posted: Tue Jul 01, 2014 8:09 am |
|
|
Hi all,
I'm seeing some odd behavior and was hoping I could get a solution or even just an explanation.
I'm using a PIC24FV32KA304 with PCWHD v4.132.
I'm using I2C to communicate with a RS232-I2C transceiver. I'm noticing that not all the time, but fairly often, the SCL signal is being held high for an abnormal amount of time (see below).
At first I thought it was clock stretching of some sort but if that's true shouldn't the line be held low by the slave device rather than the high I am seeing? Furthermore, I have I2C setup for no stretching:
#USE I2C (MASTER, FORCE_HW,sda=PIN_B9, scl=PIN_B8, STREAM=MCTL, NO_STRETCH)
Another theory I had was that perhaps the i2c_write() or i2c_read() function was getting interrupted somewhere. But disabling interrupts for the duration of the I2C transaction didn't cause any difference (and I shouldn't be spending that much time in these interrupts anyway. All they do is set a couple flags and increment counters).
Now functionally this doesn't seem to affect anything other than the amount of time a transaction takes. Data appears to come through and be read/written just fine. However I'd really like to know why I'm seeing what I'm seeing. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Tue Jul 01, 2014 9:28 am |
|
|
Get rid of the NO_STRETCH specification.
Use:
#USE I2C (MASTER, FORCE_HW,I2C1, STREAM=MCTL)
I think I found before, that specifying NO_STRETCH on a master, results in software I2C being used.....
Your behaviour looks as if this is happening. |
|
![](templates/subSilver/images/spacer.gif) |
KTrenholm
Joined: 19 Dec 2012 Posts: 43 Location: Connecticut, USA
|
|
Posted: Tue Jul 01, 2014 10:06 am |
|
|
Ttelmah wrote: | Get rid of the NO_STRETCH specification.
Use:
#USE I2C (MASTER, FORCE_HW,I2C1, STREAM=MCTL)
I think I found before, that specifying NO_STRETCH on a master, results in software I2C being used.....
Your behaviour looks as if this is happening. |
Thanks for the reply.
I gave that a shot and it didn't seem to change much.
The screenshot I posted was the longest high pulse I had seen but I'm still seeing it occasionally hold SCL high for up to 60uS. I will say that it does looks like big long pulses appear to be less frequent now. Is some stretching of the clock in this fashion to be expected?
This is legacy code I'm maintaining so I also have to wonder if maybe there's a reason why the dev that wrote this wasn't using hardware I2C. |
|
![](templates/subSilver/images/spacer.gif) |
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Tue Jul 01, 2014 11:32 am |
|
|
Consider the possibility of another interrupt going off during the sending and locking things up until serviced. Interrupts can solve lots of problems but they can also cause things to happen at apparent random times when they do go off.
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Tue Jul 01, 2014 11:32 am |
|
|
No.
If running software I2C, yes. If an interrupt occurs.
The hardware generates the clock, and you should see an irregularity at the start of the transaction (start), but the eight pulses for each character should be like 'clockwork' with the hardware.
I'd guess your old compiler, is not actually using the hardware I2C.....
Then I suspect either an interrupt is delaying longer than you think, or multiple interrupts occurred together. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
![](templates/subSilver/images/spacer.gif) |
KTrenholm
Joined: 19 Dec 2012 Posts: 43 Location: Connecticut, USA
|
|
Posted: Tue Jul 01, 2014 12:54 pm |
|
|
If I'm finding this correctly the I2C write function looks like this in the list file:
Code: |
.................... ack = i2c_write(packet.command);
0D32: MOV.B A79,W0L
0D34: MOV.B W0L,W1L
0D36: CALL CE6
0D3A: BCLR.B A7E.0
0D3C: BTSC.B 0.0
0D3E: BSET.B A7E.0
|
Looks like the call is to this?
Code: |
.................... #USE I2C (MASTER, FORCE_HW,I2C1, STREAM=MCTL)
*
0CE6: MOV #FFFF,W0
0CE8: BTSS.B 208.3
0CEA: BRA CF6
0CEC: BTSC.B 209.6
0CEE: BRA CEC
0CF0: MOV W1,202
0CF2: BTSC.B 209.6
0CF4: BRA CF2
0CF6: MOV #0,W0
0CF8: BTSC.B 209.7
0CFA: INC W0,W0
0CFC: RETURN
*
|
Unless I'm mistaken it looks like it's using hardware I2C. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 01, 2014 8:12 pm |
|
|
Remove the i2c slave and run a simple test loop that does continuous
i2c_write() operations, like this:
Code: |
while(1)
{
i2c_write(0x55);
delay_us(500);
}
|
Don't enable any interrupts. Then see if you still get the problem.
If you still get it, then it's caused by something in the Master.
Also, make sure it's not some anomaly caused by your logic analyzer.
Or pull-up values, bus capacitance, etc. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Wed Jul 02, 2014 1:25 am |
|
|
As some comments:
1) You are setting up streams in the I2C setup, but not then using this. Stick with either:
a) Use streams throughout - so the I2C write should also be using a stream name, or
b) Don't use streams at all.
Just safer.
2) Does your slave only support 100K?. 99% of I2C devices would now use 400KHz.
Stretch, only affects the clock low time, so shouldn't apply.
As far as I can see the only ways for the 'high' clock time to be changed 'mid byte', is first if the CPU clock rate changes. You can make a long break appear in the high time if (for instance) you start sending a byte, and then put the chip to sleep. The other way is if something tries to talk to the I2C peripheral in an interrupt, when I2C is already running.
However that being said, looking again, part may be an artefact with the logic analyser. The main byte transmissions are _nearly_ regular. If you look at the the start of the display, there is an I2C start, followed by the transmission of a byte with the clock showing one extra sample high after the fourth bit. looks at this point as if the actual sample period of the analyser is perhaps very low, and this is an artefact from this. The ninth clock is then stretched low (this is being done by the _slave_). Byte sent is 0xB2. Then there is the mysterious extra clock 3.6 divisions across the screen. If SDA had risen and dropped, I'd assume this was a repeated start. I'm actually wondering if in fact it is, and the sample rate of the analyser is low enough that the transition on SDA is not recorded. Then there is the huge gap till the next byte, which again has the clock nearly regular, but this time with the extra sample time after the second bit.
As such then if one assumes the analyser is only sampling perhaps 20* per main division across the screen, then part of the problem is that data is being missed, and the irregularity in the individual bytes is being created by the low sample rate. This would then explain how the hardware I2C could have an irregular clock....
Then the key is the long pause between the repeated start and the next byte. Since this is between bytes, it can be the result of an interrupt occurring at this point. Gpsmikey's comment then applies. |
|
![](templates/subSilver/images/spacer.gif) |
KTrenholm
Joined: 19 Dec 2012 Posts: 43 Location: Connecticut, USA
|
|
Posted: Wed Jul 02, 2014 7:22 am |
|
|
Ttelmah wrote: | As some comments:
1) You are setting up streams in the I2C setup, but not then using this. Stick with either:
a) Use streams throughout - so the I2C write should also be using a stream name, or
b) Don't use streams at all.
Just safer.
2) Does your slave only support 100K?. 99% of I2C devices would now use 400KHz.
Stretch, only affects the clock low time, so shouldn't apply.
As far as I can see the only ways for the 'high' clock time to be changed 'mid byte', is first if the CPU clock rate changes. You can make a long break appear in the high time if (for instance) you start sending a byte, and then put the chip to sleep. The other way is if something tries to talk to the I2C peripheral in an interrupt, when I2C is already running.
However that being said, looking again, part may be an artefact with the logic analyser. The main byte transmissions are _nearly_ regular. If you look at the the start of the display, there is an I2C start, followed by the transmission of a byte with the clock showing one extra sample high after the fourth bit. looks at this point as if the actual sample period of the analyser is perhaps very low, and this is an artefact from this. The ninth clock is then stretched low (this is being done by the _slave_). Byte sent is 0xB2. Then there is the mysterious extra clock 3.6 divisions across the screen. If SDA had risen and dropped, I'd assume this was a repeated start. I'm actually wondering if in fact it is, and the sample rate of the analyser is low enough that the transition on SDA is not recorded. Then there is the huge gap till the next byte, which again has the clock nearly regular, but this time with the extra sample time after the second bit.
As such then if one assumes the analyser is only sampling perhaps 20* per main division across the screen, then part of the problem is that data is being missed, and the irregularity in the individual bytes is being created by the low sample rate. This would then explain how the hardware I2C could have an irregular clock....
Then the key is the long pause between the repeated start and the next byte. Since this is between bytes, it can be the result of an interrupt occurring at this point. Gpsmikey's comment then applies. |
Thanks for the long and detailed explanation of your reasoning.
I took a look into my logic analyzer:
http://www.tech-tools.com/DV3100-logic-analyzer.htm
The sample rate should be at least 100MHz (10nS period). So I doubt it's slow enough to be causing any artifacts. I will probably hook up an oscilloscope to see if the signals actually match what I'm seeing on the analyzer.
I did look into interrupts perhaps doing something unintended but I saw the same behavior when disabling interrupts during I2C transactions.
The device I'm using is a MAX3107 I2C-RS232 UART. According to the datasheet, it supports 100kHz standard and 400Khz fast. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Wed Jul 02, 2014 8:42 am |
|
|
You are displaying 100uSec/division.
10 divisions across the screen. 1mSec.
At 10nSec/sample, the analyser would need to store 100000 samples, just for the screen. Most don't have anywhere near this storage. Though the analyser may well support 10nSec sampling, it'll normally only do this at it's shortest sample time. As you slow down the display, the sampling interval climbs. Even worse, most will store more than the displayed screen, so the resolution shoots downwards....
You might be surprised what you see, with the same settings on everything (zoom, sample interval, etc. etc..), if you feed (say) a 100KHz rectangular waveform at perhaps 25% duty cycle from a waveform generator into the analyser. If I'm right you are going to see the displayed graph is not a nice regular 25% duty cycle. If so, it just explains one small part of the oddity.
Since your chip supports 400K, use 400K. If the gaps remain the same, you are proving that these come from something else in the code. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|