When do you check for clock stretching i2c protocol ref master code

Started by TimB, Mar 21, 2023, 08:09 PM

Previous topic - Next topic

TimB

Hello all

As you can see from the number of posts I'm making I'm coding and getting a lot of issues.

This one is clock stretching and how to implement it properly.

Using the i2c slave interrupt code as a basis to understand what is happening. I see this :-
Note this is based on the fact the slave in hardware has clock stretching turned on.
Note before exiting the interrupt the slave software releases the clock via a hardware reg.

The Master sends a Start then the address.
The Slave on the right address generates an interrupt
Now depending if it is a read or a write some registers are set to give info for a state machine to interpret in the interrupt code

1 A Write the slave address is read from the i2cbuffer and then exits the interrupt. Basically do nothing
2 A Read in which case it zeros a pointer and loads the first element of an array into the i2cbuffer so that on the next read the first byte is transferred

Next packet that is written or Read by the master does this

1 A Write the data in the i2cBuffer is stuffed in an Master>Slave array
2 A Read and the next element in the Slave<Master Array is loaded into the i2cbuffer

This goes on until master sends a stop or another state (NACK?) that says please shut up I cannot help you anymore....

Amongst this there are ACKs being sent. I'm presuming its automatic by the Slave

Now to my question the clock stretching. Basically the clock stretching is automatic by th pic and released when the slave code says OK I'm done now carry on.
In the Master code I do not know where you should be checking for the clock stretching (looking that the CLK line is free eg high)

Is it

1 Before data is clocked one way or another
2 After data is clocked one way or another

Or some at other point

In the example Les posted it was in between every clock of data. I do not think that is right though. While it can be made to work I'm sure its just that its introducing a lot of delays rather than actually in the right place.

Since the Pic slave clock data is handled in hardware there is not need to slow the clocking of data. The slave code only gets involved once the packet has been sent. Its the processing of the data that is time consuming at you need to wait for that to be done before continuing.

Before you ask yes I have tried various methods but due to i2c being very finicky I only get it running using Busout etc with delays. I need to get the best speed and do the job properly.

Thanks

Tim







TimB


Perhaps answering my own question

From https://www.i2c-bus.org/clock-stretching/

Clock Stretching in High Speed Mode
Clock stretching in High-Speed-Mode is only allowed after the ACK bit (and before the 1st bit of the next byte). Stretching between bits 2-9 is illegal because the edges of these bits are boosted with an additional current source.

tumbleweed

I alluded to that here in the last post.

In the sample code in post 24, I don't see where I2C_WriteByte even checks for the slave to be clock stretching after the ACK cycle.

The only checks are done during the data phase of I2C_ReadByte, and that's not (usually) when the slave will be stretching the clock, at least if the slave is using the MSSP module.

TimB

After a lot of checking I think I'm 100% sure now the Clock stretching is done once the slave gets "something". That is the Pic will automatically hold the CLK line low until released in the code using SSP1CON1bits_CKP = 1 or what ever number the MSSP module is you are using.

Scenarios.
1 after the matching Address is seen
Sequence is:-
Start is seen
An address that matches what is in SSP1ADD either a read or write request
CLK is then held low while an interrupt is generated and it is up to the users code to release the CLK line when done

2 After the appropriate no of clocks have been seen to indicate 8bits were clocked into/out of the SSPBUFF before a NACK or Stop is seen.
CLC is held low before the ACK is sent if the slave is receiving data. When the user releases the clock the Pic will send the ACK. There is no code in the master to wait for an ACK though.


With that in mind the Master just needs to check the clock line before clocking anymore data in out

This all you need before the clocking in the Read byte/ Write byte sequence

    For bTimeout = $FF To 0 Step -1                             ' Create a loop if there is clock stretching
         If pSCL = 1 Then Break                                 ' Exit the loop when the SCL pin is high
    Next                                                        ' Until the timeout value times out

I'm going to post the code to act as a Slave and as the software master.

What I have found is that on a 64mhz master the issue is more the slew rate releasing the lines. It is faster than the lines can cope with. On my test boards with 12cm twisted lines I need 2.4k pullups or very long delays.

I also modified the code to have a user adjustable delay after releasing the lines to give them time to rise. Pulling them low is almost instantaneous.

Tim

tumbleweed

From what I recall, with SEN=1 the slave will clock stretch after the ACK cycle until you release it.

If you want it to stretch after the data byte but before the ACK then set AHEN and DHEN too.

The master MSSP will automatically wait if the clock is being stretched, so it's invisible to the master. You don't have to "wait for ack"... it occurs on the 9th cycle. If you're doing a software master thats a different story... you should check for stretching during the 9th cycle and after.

Check and make sure that the IO port slew rate setting isn't limiting you (if your device supports it).

TimB


I'm not fully aware of the aware of all the settings in the pic ref AHEN and DHEN I went of a 3rd party site site talking about clock stretching. Its not super relevant as the software ignores the ACK from the slave.

Yes MSSP modules will handle all the clock stretching but I need 2 i2c ports due to device issues and also a USART so MSSP modules are out of the question. Also there is no real speed advantage as far as I can see. Having software control over it I can just about remove any delays pulling the line low. Gaining a bit of speed.

Ref the slew rate its down to the capacitance of the line. Going from a low to an input, the rise is related to the pullup.

On my scope I checked I at least hit 5v but in reality I just need to be sure I made logic 1 long enough for the slave to see it.

Some devices will hard drive the lines high/low during data clocking. Just to get a speed increase.

Thanks

Tim