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

nrf52832 TWIM - ANACK and DNACK not working properly

Hello,

I am developing custom driver for TWIM. I am facing a problem with DNACK and ANACK which hangs my application. SCL and SDA lines are monitored through Saleale logic analyzer and an oscilloscope. The problem occures when no ACK appears after address byte (high level).

To simplify the problem I will describe the polling configuration. A code snipped is placed below:

i2c.TXD.MAXCNT = length + 1;
i2c.ADDRESS = (deviceAddress >> 1);
i2c.TXD.PTR = reinterpret_cast<uint32_t>(buffer);
eventClear(Event::LastTX);
eventClear(Event::Error);
taskTrigger(Task::StartTx);
do {
    if (eventCheck(Event::LastTX)) {
        eventClear(Event::LastTX);
        taskTrigger(Task::Stop);
    }

    if (eventCheck(Event::Error)) {
        eventClear(Event::Error);
        taskTrigger(Task::Stop);
        return getError();
    }

    if (eventCheck(Event::Stopped)) {
        eventClear(Event::Stopped);
        break;
    }

    if (getError() != I2C::Error::NoError) {
        taskTrigger(Task::Stop);
        return AcknowledgeFailure;
    }
} while (1);

return NoError;

After ANACK occures no events are reported, therefore getError conditional statement was added. getError function reads the i2c.ERRORSRC register and cleans it. Error is reported, but the next transmission on I2C does not starts. What's more - no event and no error is reported, above loop after next calling does not ends.

I will be grateful for any help.

  • You should clear the STOPPED event (eventClear(Event::Stopped)) before triggering StartTx task. As it is now you will not stop every second transmission since the stopped event is set when you enter the do-while loop.

    Alternatively you can wait for stopped event before returning when you get an error.

    You also should remove the if (getError() != I2C::Error::NoError) {..} block. As it is now it may be random if this block is executed or the block that checks error event.

  • Hi! Thank you for your reply. I implemented your suggestions in my code. I made some tests with my I2C device (PAC1710). This situation and unpredicted behaviour was primary caused by PAC1710. This device has no timeout mechanism so in some cases it held the SDA line down. Manually generated clock and start/stop condition on I2C lines helped with its strange behaviour. I forgot to mention that above behaviour was remarked after a dozen or so resets while the I2C transmission was going on.

Related