This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Meaning of TWI overrun flag in master mode

What is the purpose of the TWI overrun flag given that the TWI peripheral only supports master mode?

I have the following code in an ISR for my TWI acting as master.

if(0 != I2C_TWIX->EVENTS_ERROR)
{
    /* An error has occurred. Clear all the flags because the hardware
     * can set multiple flags when an error occurs (for instance
     * TXDSENT and ERROR if an error occurs during transmit) but we
     * only want to handle this once. */
    I2C_TWIX->EVENTS_ERROR = 0;
    I2C_TWIX->EVENTS_TXDSENT = 0;
    I2C_TWIX->EVENTS_RXDREADY = 0;

    /* What type of error? */
    if(I2C_TWIX->ERRORSRC & ((TWI_ERRORSRC_ANACK_Present <<
                              TWI_ERRORSRC_ANACK_Pos) |
                             (TWI_ERRORSRC_DNACK_Present <<
                              TWI_ERRORSRC_DNACK_Pos)))
    {
        /* Handle missing ACK. */
    }
    else
    {
        /* The datasheet lists an over-run error too; we don't check
         * for this since it should only apply to slaves. */
        FAIL("TWI error from unknown source.");
    }
}

The driver will happily perform thousands of readings from the slave (a pressure sensor). Very rarely, however, the FAIL line is being hit, suggesting that the overrun flag is being set. In what circumstances can this flag be set? The datasheet says the following:

Overrun error
A start condition is received while the previous data still lies in
RXD (Previous data is lost)

But a start condition should never be received on a single-master bus when this device is the master. Could this be caused by a transient low pulse on the line between transmissions? Or bad slave behaviour?

I'm using S110 v7.1.0 on nRF51822QFAB.

Thanks, Carl

Parents
  • Are you using the shortcut BB->SUSPEND shown in the manual (and I assume used in the reference code)?

    Your question reminded me of one I asked a while ago where I decided the manual wasn't totally accurate about 'stretching the clock until RXD is read', that's here, see if that matches what you're seeing at all.

    devzone.nordicsemi.com/.../

    If you're not suspending the read on a byte boundary, or you're not doing it with a shortcut but in code, you may occasionally fail to stretch the clock after an ACK and the next byte will be clocked in causing an overrun.

Reply
  • Are you using the shortcut BB->SUSPEND shown in the manual (and I assume used in the reference code)?

    Your question reminded me of one I asked a while ago where I decided the manual wasn't totally accurate about 'stretching the clock until RXD is read', that's here, see if that matches what you're seeing at all.

    devzone.nordicsemi.com/.../

    If you're not suspending the read on a byte boundary, or you're not doing it with a shortcut but in code, you may occasionally fail to stretch the clock after an ACK and the next byte will be clocked in causing an overrun.

Children
  • Hi RK, thanks for the idea. I think I saw your question before when I first designed the driver; it made things much clearer than the manual. I'm already using the SUSPEND shortcut. I set the shortcut before each byte except the last one of a transaction, where I set the STOP shortcut instead. In any case, according to the manual the "overrun" condition should be set when a start condition occurs. The situation you describe should not result in a new start condition. Your question doesn't mention the overrun flag; are you seeing the overrun flag in the situation you describe?

  • It was a while ago but I did some abusive testing of the peripheral and yes got the overrun if I didn't use the shortcut and didn't service the RXD event. The overrun came when one byte had been read in, there was no shortcut to suspend the peripheral and (despite the manual saying otherwise) it just continued on with another start and clocked in more data from the peripheral, as soon as that happened there was an overrun as the byte hadn't been read from RXD.

    If you're using the shortcuts and suspending the peripheral and reading RXD before you restart the read, then I too cannot come up with a way you get an overrun. I certainly haven't seen one since I put that code in.

  • So from what you describe I think the manual is wrong in its description and the overrun flag is set if a byte would enter the receive buffer before the previous is read (which does not require a start condition). This makes sense, although it is particularly confusing because this flag would not be necessary at all if the clock was stretched automatically as stated in the manual. What I'm left wondering is whether the flag can also be set for some other reason (e.g. a transient low pulse on SDA or SCL when the master is not clocking), or whether this behaviour means I've got a bug where I'm occasionally not setting SUSPEND properly. I'll have another look and see if I can spot something, and otherwise hope to hear from someone at Nordic about the flag. Thanks again for your help.

Related