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