paul at boddie.org.uk
Sat Feb 13 16:58:37 CET 2021
On Saturday, 13 February 2021 16:33:53 CET H. Nikolaus Schaller wrote:
> > Am 13.02.2021 um 16:22 schrieb Paul Boddie <paul at boddie.org.uk>:
> > 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?
This is after the first byte (address). I don't bother testing STX once I
start reading the data because DRF will be cleared to indicate that more data
is expected, and so there isn't a risk of testing DRF and finding it set
because of something I just did.
It is possible that STX is a distraction, but it happens to be a useful one
for my code. I imagine that I could also use the same logic when reading data,
though. In other words:
while (STX || (!DRF && !NACK));
But with DRF and NACK initially unset, and with the peripheral the only thing
likely to set them, it doesn't seem worthwhile to involve STX as well.
> > 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.
Yes, I don't know how these interrupts could be prevented.
> > 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
In terms of address (write) to read transitions, it does seem to involve a
safe transition that does not get confused by DRF. I haven't looked at
situations where actual writing and reading are mixed within a single
transaction, and I don't think the manual is much help with that, either.
> 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.
This is presumably only for read-related interrupts, or does the involvement
of TEND suggest more general consideration of both read and write interrupts?
It seems to me that read-related interrupts will (or should) occur when DRF or
NACK are set by the peripheral:
IRQread = DRF || NACK
It might be no more complicated than that. We would really want some kind of
condition involved that prevents the IRQ from occurring if we set DRF
ourselves. This might involve ignoring the address setting operation which
cannot avoid setting DRF. Here I could imagine a flag being set to indicate
the transition from driver control of DRF to peripheral control, and I manage
to use STX for that, regardless of whatever it really means.
> So there may be some internal and invisible state involved.
I could imagine the read/write status of the address byte being used to
control the IRQ logic internally.
> 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
> last byte.
> So I don't know how to switch to read mode...
I hope I have given you some ideas, at least.
More information about the Letux-kernel