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

Does anyone have a more robust TWI_handler than that given in the TWI examples?

The current example TWI_handler will hang forever is it exits with anything other than NRF_DRV_TWI_EVT_DONE.  This can occur if a TWI slave fails to acknowledge the address or data phase. I am looking for how to gracefully exit a nrf_drv_twi_tx() or nrf_drv_twi_rx() call if an error occurs.  Would it be best to poll for m_xfer_done before the call to nrf_drv_twi_tx() or nrf_drv_twi_rx()?  In that manner, if an error occurred from a previous call, the firmware can handle the exception gracefully.  I am using SDK 15.2 and a nrf52832 device.

It appears that back-to-back calls to either of the TWI driver calls can cause erroneous behavior if one doesn't wait for the first transfer to finish. Does the TWI driver have the ability to determine if it is busy (in process of a previous transfer)?

Parents
  • I am using the TWI master to communicate to several slave devices.

    My TWI interrupt handler is:

    /**
    * @brief TWI events handler.
    */
    void twi_handler(nrf_drv_twi_evt_t const *p_event, void *p_context)
    {
            twi_xfer_state = p_event->type;
    }//end twi_handler()

    I now have created a twi_wait() routine that is called prior to any TWI tx or rx calls to ensure that any previous TWI transfer is completed. The standard twi_handler() routine used to only set twi_xfer_done=true if p_event->type=NRF_DRV_TWI_EVT_DONE. If NRF_DRV_TWI_EVT_NACK was returned, the system would hang indefinitely.

    Now I can check for this in the twi_wait() routine and handle this situation more gracefully and I don't hang-up the system waiting for an event that will never occur.

    Regards,

    Jeff.

    Here is my twi_wait() routine:

    /**
    * @brief TWI wait handler.
    */
    LEP_RESULT twi_wait (void)
    {
            while (twi_xfer_state==NRF_DRV_TWI_EVT_BUSY) {
                    if (NRF_LOG_PROCESS() == false)
                    {
                            nrf_pwr_mgmt_run();
                    }
            };
            LEP_RESULT result = (twi_xfer_state==NRF_DRV_TWI_EVT_DONE)?LEP_OK:LEP_ERROR_I2C_NACK_RECEIVED;
            twi_xfer_state = NRF_DRV_TWI_EVT_BUSY;
            return (result);
    }//end twi_wait()

Reply
  • I am using the TWI master to communicate to several slave devices.

    My TWI interrupt handler is:

    /**
    * @brief TWI events handler.
    */
    void twi_handler(nrf_drv_twi_evt_t const *p_event, void *p_context)
    {
            twi_xfer_state = p_event->type;
    }//end twi_handler()

    I now have created a twi_wait() routine that is called prior to any TWI tx or rx calls to ensure that any previous TWI transfer is completed. The standard twi_handler() routine used to only set twi_xfer_done=true if p_event->type=NRF_DRV_TWI_EVT_DONE. If NRF_DRV_TWI_EVT_NACK was returned, the system would hang indefinitely.

    Now I can check for this in the twi_wait() routine and handle this situation more gracefully and I don't hang-up the system waiting for an event that will never occur.

    Regards,

    Jeff.

    Here is my twi_wait() routine:

    /**
    * @brief TWI wait handler.
    */
    LEP_RESULT twi_wait (void)
    {
            while (twi_xfer_state==NRF_DRV_TWI_EVT_BUSY) {
                    if (NRF_LOG_PROCESS() == false)
                    {
                            nrf_pwr_mgmt_run();
                    }
            };
            LEP_RESULT result = (twi_xfer_state==NRF_DRV_TWI_EVT_DONE)?LEP_OK:LEP_ERROR_I2C_NACK_RECEIVED;
            twi_xfer_state = NRF_DRV_TWI_EVT_BUSY;
            return (result);
    }//end twi_wait()

Children
No Data
Related