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

TWI driver strange behavior

Hi, I wrote a simple program to communicate with ICM20948 IMU . 

The IMU correctly acknowledges its address.

But, when I try to read its WHO_AM_I  ID, the program halts inside the read_byte function I wrote,

at the transfer complete check ( while(m_xfer_done == false) )  under the nrf_drv_twi_tx( ... ) function.

So the code cannot continue and read the ID of the slave...( I have also verified that with logic analyzer) .

uint8_t ICM_RD_byte(uint8_t  ICMregister)
{
  uint8_t receivedByte;
  
  uint8_t pinax[] = {ICMregister};

  //m_xfer_done = false;
  err_code = nrf_drv_twi_tx(&m_twi, ICM20948_ADDRESS, pinax, sizeof(pinax), true); 
    //nrf_delay_ms(1000);
  APP_ERROR_CHECK(err_code);
  while(m_xfer_done == false);                                                   // wait for Tx + no_stop event to occur
  m_xfer_done = false;                                                            // reset the done flag for next event
  err_code = nrf_drv_twi_rx(&m_twi, ICM20948_ADDRESS, &receivedByte, 1);          // Fetch temperature data from MAX30102_DIE Register and save it to pinax[2]
  APP_ERROR_CHECK(err_code); 
  while (m_xfer_done == false); 

  return receivedByte;
}

m_xfer_done is a boolean variable that  I have defined in my global_variables header file

#ifndef GLOBAL_VARIABLES_H
#define GLOBAL_VARIABLES_H

#ifdef __cplusplus
extern "C" {
#endif

#include "nrf_drv_twi.h"
#include "app_error.h"
#include "ICM20948.h"      

#define TWI_INSTANCE_ID     0
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);

static volatile bool m_xfer_done = false;
static volatile ret_code_t err_code;
static volatile bool flag = false;


#ifdef __cplusplus
}
#endif

#endif // GLOBAL_VARIABLES_H

I use this variable as a flag  that is updated in the TWI event handler function  in main.c file

so that I know when an event occurred. The process is almost the same with the TWI_sensor example.

void twi_event_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:            
            
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
            {
                NRF_LOG_INFO("NRF_DRV_TWI_XFER_RX event occured");
                  
            }
            else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX)
            {
               NRF_LOG_INFO("NRF_DRV_TWI_XFER_TX event occured");
               
             
            }
            else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX)
            {
                NRF_LOG_INFO("NRF_DRV_TWI_XFER_TXRX event occured");
               //data_handler(m_sample);
            }

            m_xfer_done = true;
            break;

        default:
            break;
    }
}

Strangely, even when m_xfer_done variable becomes true in the handler function after the TX event (verified that it becomes true with debugger in segger) the program halts 

at while(m_xfer_done == false)  . How is this possible? I can see the m_xfer_done to become true and the while check cannot see it...

To verify that the communication works ok  I placed a delay of 1sec after the nrf_drv_twi_tx( ... ) function and removed the  while(m_xfer_done == false)

I did the same thing to the nrf_drv_twi_rx( ...) function.

and the program responds as expected and I receive the ID of the slave device correctly.

So, it must be something with this while() check

What am I doing wrong here?

Thank you for your time

Parents Reply Children
Related