H. Nikolaus Schaller
hns at goldelico.com
Sat Feb 13 16:33:53 CET 2021
> Am 13.02.2021 um 16:22 schrieb Paul Boddie <paul at boddie.org.uk>:
> On Saturday, 13 February 2021 15:11:14 CET H. Nikolaus Schaller wrote:
>> Now, there is a a problem. It appears that the next interrupt occurs before
>> the data byte has been sent. Well, FIFO behaviour...
>> This als means that the ACKF is not yet valid. And even worse, my test
>> i2cdetect -y 0 0x27 0x29 >/dev/null
>> sends out data packets with 0 bytes. So it should just send STA + address +
>> ACK + STO.
> This is indeed one of the annoying problems. What my code does is this...
> 1. Send start (STA)
> 2. Set address
> 3. Indicate data valid (DRF)
> 4. Wait for interrupt condition...
> 5. If transferring (STX), keep waiting (return to #4)
can you find out if this happens after submitting the first byte (address) or only after first data bytes?
> 6. Otherwise, if neither DRF or NACK are set, keep waiting (return to #4)
> As I noted before, waiting for an interrupt condition is just "handle an
> interrupt request" in the given context. Technically, I have a timeout, but
> this is hardly ever needed, and I don't do anything other than report it and
> keep testing for the flags if it does occur.
My state engine initially did work well, until I removed the printk :)
They essentially have the same effect as your waiting loops.
>> What I have not found is the IRQ mechanism to reset the IRQ if there is no
>> more data. The IRQ stays pending and is processed by the kernel right again
>> and my state engine immediately runs through to the end.
>> The flow charts in the data sheet unfortunately do not tell in any way how
>> to stop another IRQ after sending the last byte and how to properly switch
>> to read mode.
> I think that the mysterious STX flag might be the key here. Since DRF gets set
> in order to send the address, testing for it risks just sampling the condition
> that has just been set, making it seem that data has arrived when it is still
> being sent.
> When STX is also set, however, it appears to mean that the sending is still in
> progress. Here, the manual uses some incoherent language that doesn't
> communicate the purpose of the STX bit, so I am guessing to an extent.
> Once the above process is finished, the usual reading process occurs:
> 7. If NACK then send stop (STO) and exit
> 8. While data is expected...
> 9. Wait for interrupt condition...
> 10. If timeout then send stop and exit
> 11. If neither DRF or NACK are set, keep waiting (return to #9)
> This should have established that something has responded on the bus, and this
> is handled as follows:
> 12. If NACK then send stop (STO) and exit
> 13. Set NACK for the last byte if this will be next, or only one byte is read
> 14. Store the data
> 15. Clear DRF
> 16. Return to 8, sending stop and exiting if no more data is expected
>> What I know is that sending STO does end this, but that is brute force and
>> not the general case...
>> Do you have an idea what condition clears the data IRQ if there is no data
>> to send? We only can write AC to CR or DRF to SR. Both are 0.
> It is entirely possible that the IRQ occurs over and over in my routine above,
> and thus steps 4-6 are evaluated many times before the right exit conditions
> occur. I don't know how I would prevent this, however. All I can reasonably do
> is to prevent the IRQ from causing an advance through my code (and your state
> machine) by being misinterpreted.
This is currently my main issue that I get spurious interrupts. Which disappear
(or are merged) if I add printk at some locations.
> I think I may have sent a patch earlier that incorporated some of the above
> logic into the driver. It might be worth looking at parts of that,
> particularly the STX-related test, to see if it helps.
Well, my code has deviated from any published version now to simplify further
and reduce the issues to small locations.
At the moment I have two such critical points: one makes the NACK recognized
correctly. And the other makes the state engine stuck on write (not on read).
What I have also tried is to guess from the values I see in the I2CSR and
the ISR what boolean equation could describe an IRQ:
IRQ = !DRF & (STX | !TEND)
But that may not be correct. I remember from an earlier attempt to do the
same that I got both (IRQ=1 and IRQ=0) for the same values of the I2CSR.
So there may be some internal and invisible state involved.
And the problem with the above assumption is that we can only write the DRF
bit! So we must write it to 1 to stop any IRQ. Even after writing the
So I don't know how to switch to read mode...
More information about the Letux-kernel