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

TWI hanging in nrf_twim_event_check

I am using TWI 0 to communicate with an external EEPROM.  99% of the time this is going succesfully.  For reasons best known to itself, my eeprom will sometimes fail to acknowledge read requests properly, leaving the SDA line in an abnormal state.

I can identify that this has happened via a timeout and would have been able to recover, but the TWI interface is hanging in         while (!nrf_twim_event_check(p_twim, evt_to_wait))  within twim_xfer() from SDK 15.3.0

Rather than ensure my slave device never does anything unexpected, I'd prefer to make my code able to withstand these faults, simply providing back a read error.

Are there any recommended methods for adding a timeout within this loop or for clearing flags externally so that this loop breaks out with a fault instead of continuing to hang?

  • Hello,

    Yes, the TWI might get stuck if the acknowledge is missed - this can for example be caused by an interrupt with higher priority triggering at an unfortunate time and/or taking a longer time to handle than anticipated. 

    Either way, there are things you could do to remedy this. Have you taken a look at the documentation for our TWI API reference? The nrfx_twi_bus_recover might be what you are looking for in this case.
    You can call this function after noticing that the bus is stuck.

    Is this what you were looking for?

    Best regards,
    Karl

  • Thanks Karl,

    Reading the notes on the nrfx_twi_bus_recover routine suggests that the final stage in that may solve the issues I am facing.

    I don't expect the toggling of the SCL line to help in this case as it is not the slave that is locked up, it is the NRF52 that has got stuck awaiting a particular I2C event that is not forthcoming.

    Unfortunately all our code is built upon SDK V15.3 rather than 16.0  so I don't believe this feature is available to us.  I'll investigate what is involved in the V16 recovery and see if it is something I can retrospectively add to 15.3.

    Failing that we might need to upgrade our SDK, though with everything else working faultlessly I'm wary about a wholesale change such as that.

    Cheers

    Andy

  • Andrew said:
    Thanks Karl,

    No problem at all Andy!

    Andrew said:

    Unfortunately all our code is built upon SDK V15.3 rather than 16.0  so I don't believe this feature is available to us.  I'll investigate what is involved in the V16 recovery and see if it is something I can retrospectively add to 15.3.
    Failing that we might need to upgrade our SDK, though with everything else working faultlessly I'm wary about a wholesale change such as that.

    I am terribly sorry, it seems I missed that part in my initial reply.
    Have you seen the twi_master_with_twis_slave example? It is from the SDK 15.3, and demonstrates TWI_master communication with a simulated EEPROM.
    In this example, the bus is cleared using the twi_clear_bus function from the nrf_drv_twi.c source file. You may use that instead of the previously mentioned, unavailable, function.

    Could you clarify what you are referring to when you say "failing that"? -To add the recovery option to the SDK v15.3, or to escape the twi acknowledgement on the nRF52?
    None of the aforementioned should cause you to have to migrate your SDK, do not worry!

    Andrew said:
    I don't expect the toggling of the SCL line to help in this case as it is not the slave that is locked up, it is the NRF52 that has got stuck awaiting a particular I2C event that is not forthcoming.

    You are absolutely correct, this is a fix to a twi slave locking the bus. I apologize for my misunderstanding.

    To escape the waiting loop on the nRF52, I would suggest using a timer interrupt to check if the processor has been waiting for the acknowledgement for a reasonably long time, before clearing the wait event and continuing on. Are you familiar with using timed interrupts? If the timer interrupt has higher priority than the twi transmission, the interrupt service routine will execute when the timer indicates it. The interrupt service routine could then clear the waiting condition, and set some transmission error flag instead.
    You could see a demonstration of a timer in the timer example, or read about the timer API directly here.
    From your description I am assuming that the EEPROM is the only other slave on the bus?
    Please get back to me with what you think of this proposed solution.

    Could you also please specify which nRF52 SoC you are developing on? That would be of great help in our future discussion.

    Best regards,
    Karl  

  • I'll have a look at that example Karl, thanks.

    To answer your questions:

    I'm using SDK 15.3.0 with softdevice S132

    I am familiar with the timers functionality and have a couple running already.  I've added one that proceses a timeout and catches this situation where I2C has taken too long to complete, so I'll look at the example you cited and see how this works.

    My "failing that" reference was that if I cannot ensure the nrf52 main loop does not get blocked by unexpected twi acknowledgement or stop bits, then I'd have to think about using the V16 TWI routines.

    I'll go and have a look at those examples and see what looks relevant to the way we are operating here.

    Thanks

    Andy

  • Andrew said:
    I'll have a look at that example Karl, thanks.

    Great, I am happy to help, Andy!

    Andrew said:
    I'm using SDK 15.3.0 with softdevice S132

    I understand, but could you also tell me which specific board/chip you are using? For example, are you developing on a nRF52832 DK, or a third party board with a Nordic SoC?

    Andrew said:
    My "failing that" reference was that if I cannot ensure the nrf52 main loop does not get blocked by unexpected twi acknowledgement or stop bits, then I'd have to think about using the V16 TWI routines.

    We will figure out this issue, do not worry. Even if you are unable to achieve satisfactory performance with my previous feedback, we will make this work without having you change the SDK version, I am sure of it.
    A timer sounds like a great way to counter this and escape the waiting loop after a given waiting period. This should not cause any problems so long as my assumption that the EEPROM is the only slave on the TWI bus holds.

    Andrew said:
    I am familiar with the timers functionality and have a couple running already.  I've added one that proceses a timeout and catches this situation where I2C has taken too long to complete, so I'll look at the example you cited and see how this works.

    The examples I suggested was mainly to demonstrate TWI communication with EEPROM, and how to recover the bus in the case that a slave is forcing it low.
    I do not think that the examples I mention implement a fix for a missed acknowledgement from the EEPROM - they both only concern TWI communication in general, and as such they are not prone to interruption from other tasks.
    However, the solution with setting a timer interrupt for the ack_wait loop sounds like a good solution to your problem.

    I look forward to hearing if this implementation solves your problem!

    Best regards,
    Karl

Related