[En-Nut-Discussion] TWI and Lua problem
andre at riesberg-net.de
Mon Apr 11 18:06:22 CEST 2011
Bernd Walter schrieb:
> On Sun, Apr 10, 2011 at 11:20:49PM +0200, Ulrich Prinz wrote:
>> Good work!
>>> I'd make more test and found some interesting things. First, I use
>>> the function TwMasterTransact to send an address an two data bytes.
>>> The function TwMasterRegWrite should be the better one. But I am not
>>> sure if will fix this issue.
>> Normal chip sequence is addressing the chip, addressing something inside
>> the chip, then read or write something there.
>> TwMasterTransact is for doing anything else but this :)
>> It is mostly for I2C communication between several self made boards or so.
>> The routines you might like to use are TwMasterRegRead and -Write if you
>> address a real I2C chip.
>>> With an digital scope I see the start bit was send, then the address
>>> byte, next the first data byte. And next I see the stop bit, but this
>>> is wrong. Now I see the second data byte with the glitch.
>> Ok, with TwMasterRegRead/Write mostly all special functions of the SAM
>> hardware I2C are used, as it delivers automatic start/stop generation,
>> chip address and inside-chip address handling. So the driver fills in
>> all this information at once and then fires the first run.
>> With the first interrupt, the first data byte is fetched and written to
>> the bus. So the first interrupt after rolling the hardware is the one
>> that requests the first databyte. As the TWDR is empty at that point it
>> is the cause for the stop bit.
>> The driver needs a modification to write the first databyte too, before
>> or right after firing the system.
> Yes - you need to write the first data byte without waiting for TXRDY.
> That's a must to get the controller stable.
> Another point (maybe you've taken care in the driver, since it is more
> or less natural for I2C) is that for reading you need to setup NAK very
> You also need to wait for AT91C_TWI_TXCOMP before the TWI can be used
> again, which is also true after receiving an addressing NACK.
> I don't know the NutOS driver code, so don't be surprised if I write
> something, which is already done correctly...
>> What the SAM does is a clear violation of the I2C specification! As the
>> it does not know what to do next it clearly needs to halt and wait until
>> the next thing happens, either a stop request from the software (Abort)
>> or a databyte to send. It should never act alone and decide to break the
>> communication with a glitch like stop. The mechanism completely breaks
>> the Bit- and ACK-stretching what is used to slow down communication if
>> the system cannot react fast enough.
> Yes - this behavour is completely beyound imagination.
> I've first saw it on RM9200 when trying to debug something by adding
> debug printf, just to see the full stop/start crap on scope.
>>> In the data sheet under "Master Transmitter Mode" I found:
>>> "When an acknowledge is detected, the TXRDY bit is set until a new
>>> write in the TWI_THR. When no more data is written into the TWI_THR,
>>> the master generates a stop condition to end the transfer."
>> Looks like they tried to implement a auto-stop functionality... How
>> awful is that!
>>> The address byte and the first data byte are send in the function
>>> TwMasterTransact, the second data byte is put in the buffer to send
>>> it in the TwInterrupt function. Every thing is fine so long the
>>> interrupt will be handled fast enough. If the TWI_THR is not filled
>>> fast enough the stop bit is send. But the interrupt is handle and
>>> (too late) the byte is written to TWI_THR. I think this confuses the
>>> TWI hardware and produces the glicht(es).
>> The TwMasterTransact is just setting up the start condition. With that
>> sent out the mechanism gets another interrupt that then fetches the data
>> and everything else. If all data is sent, it checks if it needs to
>> receive some.
>>> Until now, I do not found a way to suppress the stop bit until the
>>> interrupt is handled.
>> If the chip is really that fast with the illegal stop condition, you
>> have no chance. Either you modify the TwMasterTransact and the other two
>> routines to prefetch one databyte or you switch to DMA mode.
> There is no DMA for TWI :-(
> It's hard to believe because it has alls the internal addressing support,
> but fails with simple data transport.
>>> I think this is a weakness in the TWI hardware. If you have high
>>> speed on the TWI bus or a complex system with disabled interrupts,
>>> the interrupt driven TWI handling will not work. The async TWI bus
>>> has now some synchron aspects and this is worse!
>> Weakness is really not the right word, its (beeeeep)... (SCNR)
> I'm also missing the words.
> I like the AT91 series, but the TWI is...
>>> This behavior fits good my application. If I send the data before
>>> all the threads are running, it works. If the Lua thread and all the
>>> other threads are running it fails.
>> The driver is a bit complex, but it should not be a problem to prefetch
>> the first databyte. I have to check the datasheets for the
>> double-buffering on TWI. If the SAM supports double buffer, you get an
>> interrupt if the TWDR is empty but the hardware is still sending the
>> previous byte. So you have the time of one byte to fetch again the next
the TwMasterRegWrite and TwMasterRegRead are the better functions.
TwMasterRegWrite can send up to 5 bytes, one address, up to three more
address (or data) bytes and another data byte. This is done without any
"byte sending" interrupt.
The function TwMasterTransact works reliable for only one data byte.
If we want to send more then 5 bytes, we have to write our own function
The automatic stop bit very bad.
But I hope there is a solution for this issue!
More information about the En-Nut-Discussion