cancel
Showing results for 
Search instead for 
Did you mean: 

[LSM6DSR] Correct flow to get XL and gyro data by data-ready interrupt mode?

E-John
Associate III

I tried to get XL and gyro data by data-ready interrupt mode,

1. Configuartion registers sequence and values are as follows

Use Bypass mode, XL data-ready rounted to INT1; gyro data-ready rounted to INT2

2. In ISR1 reads the STATUS_REG, if XLDA bit is set, read XL data

3. In ISR2 reads the STATUS_REG, if GDA bit is set, read gyro data

is that correct to get XL and gyro by data-ready interrupt mode?

My questions are

  1. If read STATUS_REG on ISR, the INTx will keep on high, only do a XL read or gyro read from LSM6DSR, the INTx pin change to low?
  2. If I put the read XL and read gyro on background while(1), it is likely to cause the INTx pin high and system hangs
  3. Only read XL and gyro inside ISR can keep system stable​

setup sequence​

read back reg = 0x12, val = 0x 4

read back reg = 0x14, val = 0x60

read back reg = 0x16, val = 0x 0

read back reg = 0x a, val = 0x 0

read back reg = 0x 9, val = 0x 0

read back reg = 0x5e, val = 0x 0

read back reg = 0x56, val = 0x41

read back reg = 0x17, val = 0x 0

read back reg = 0x18, val = 0x 2

read back reg = 0x d, val = 0x 1

read back reg = 0x e, val = 0x 2

read back reg = 0x11, val = 0x4c

read back reg = 0x10, val = 0x40

const unsigned char gsensorInterrupTestTable[13][2] =
{
	//Keep to update g and gyro data. H_LACTIVE:0,PP_OD:0,
	{ (LSM6DSR_CTRL3_C_REG), (LSM6DSR_BLOCK_DATA_UPDATE_DISABLE + LSM6DSR_REGISTER_ADDRESS_AUTO_INCREMENTED) },
	//Rounding read
	{ (LSM6DSR_CTRL5_C_REG), (LSM6DSR_GYROSCOPE_AND_ACCELEROMETER) },
	//Set high perform
	{ (LSM6DSR_CTRL7_G_REG), (LSM6DSR_G_HM_MODE_ENABLE) },
	//Disable FIFO fucntion
	{ (LSM6DSR_FIFO_CTRL4_REG), (LSM6DSR_FIFO_MODE_BYPASS) },
	
	{ (LSM6DSR_FIFO_CTRL3_REG), (LSM6DSR_FIFO_BDR_GY_NOT_IN_FIFO + LSM6DSR_FIFO_BDR_XL_DISABLE) },
	//Disable interrupt for specific event. 
	{ (LSM6DSR_MD1_CFG), (LSM6DSR_INT1_6D_DISABLE) },
	//Set interrupt property
	{ (LSM6DSR_TAP_CFG0), (LSM6DSR_TAP_CFG_LATCHED + LSM6DSR_TAP_CFG_INT_CLR_ON_READ) },
	//Filter configuration
	{ (LSM6DSR_CTRL8_XL_REG), (0) },
	//Disable I3C
	{ (LSM6DSR_CTRL9_XL_REG), (LSM6DSR_CTRL_DEVICE_CONF) },
	//Set INT1 source
	{ (LSM6DSR_INT1_CTRL_REG), (0x01) },
	//Set INT2 source
	{ (LSM6DSR_INT2_CTRL_REG), (0x02) },
	//Set gyro scale and ODR
	{ (LSM6DSR_CTRL2_G_REG), (LSM6DSR_G_ODR_104HZ + LSM6DSR_G_FS_2000DPS) },
	//Set g sensor scale and ODR
	{ (LSM6DSR_CTRL1_XL_REG), (LSM6DSR_XL_RANGE_2G + LSM6DSR_XL_ODR_104HZ) },
};

 ========================================

INT1 and INT2 works fine if read XL, read gyro inside ISR

char LSM6DSR_InterruptTest(void)
{
	unsigned char pucData[3];
	unsigned char ucI2CCh = I2C_CH_LSM6DSR;
	unsigned char ucCount = 0;
	unsigned char ucRet = 0;
	int rval = 0;
	unsigned char i = 0;
	uint32_t t0, t1 = 0;
	// software reset
        pucData[0] = LSM6DSR_CTRL3_C_REG;
        pucData[1] = LSM6DSR_SOFT_RESET;
 
	rval = I2CWrite(I2C_ADDR_LSM6DSR, pucData, 2, ucI2CCh);
	// timeout to check software rest bit status
	// software reset bit is automatically cleared
	i = 0;
	do {
              I2CRead(I2C_ADDR_LSM6DSR, LSM6DSR_CTRL3_C_REG, &pucData[0], 1, ucI2CCh);
               vTaskDelay(10 / portTICK_RATE_MS);
               i++;
	} while(((pucData[0] & LSM6DSR_SOFT_RESET) == 0) && i <= 10);
 
	LSM6DSR_WriteRegisters(&gsensorInterrupTestTable[0][0],
  REG_TABLE_ROW_NUM(gsensorInterrupTestTable));
 
	while (ucCount < 50) {
            vTaskDelay(10/portTICK_RATE_MS);
           ucCount++;
	}
 
	DEBUGMSG("g-sensor int count = %d\r\n", g_gs_int_count);
	DEBUGMSG("gyro int count = %d\r\n", g_gyro_int_count);
 
	return ucRet;
}
 
void LSM6DSR_ISR1(void)
{
	// INT1
	unsigned char pucData[3];
	unsigned char ucI2CCh = I2C_CH_LSM6DSR;
 
	I2CRead(I2C_ADDR_LSM6DSR, LSM6DSR_STATUS_REG, &pucData[0], 1, ucI2CCh);
​	if (pucData[0] & LSM6DSR_STATUS_XLDA)	{
            g_gs_int_count++;
            GSensorRead(READ_CURRENT_XL);
        }
}
 
void LSM6DSR_ISR2(void)
{
	// INT2
	unsigned char pucData[3];
	unsigned char ucI2CCh = I2C_CH_LSM6DSR;
 
	I2CRead(I2C_ADDR_LSM6DSR, LSM6DSR_STATUS_REG, &pucData[0], 1, ucI2CCh);
	if (pucData[0] & LSM6DSR_STATUS_GDA)	{
            g_gyro_int_count++;
            GyroRead(READ_CURRENT_GYRO);
        }
}
 

 ===========================================================

INT1 and INT2 goes high after read XL(system hangs), read gyro inside background while(1) during timeout 500ms

char LSM6DSR_InterruptTest(void)
{
    unsigned char pucData[3];
    unsigned char ucI2CCh = I2C_CH_LSM6DSR;
    unsigned char ucCount = 0;
    unsigned char ucRet = 0;
    int rval = 0;
    unsigned char i = 0;
    uint32_t t0, t1 = 0;
    
    // software reset
    pucData[0] = LSM6DSR_CTRL3_C_REG;
    pucData[1] = LSM6DSR_SOFT_RESET;
    rval = I2CWrite(I2C_ADDR_LSM6DSR, pucData, 2, ucI2CCh);
    // timeout to check software rest bit status
    // software reset bit is automatically cleared
    i = 0;
    do {
        I2CRead(I2C_ADDR_LSM6DSR, LSM6DSR_CTRL3_C_REG, &pucData[0], 1, ucI2CCh);
        vTaskDelay(10 / portTICK_RATE_MS);
        i++;
    } while(((pucData[0] & LSM6DSR_SOFT_RESET) == 0) && i <= 10);
 
    LSM6DSR_WriteRegisters(&gsensorInterrupTestTable[0][0],  REG_TABLE_ROW_NUM(gsensorInterrupTestTable));
 
    while (ucCount < 50) {
        I2CRead(I2C_ADDR_LSM6DSR, LSM6DSR_STATUS_REG, &pucData[0], 1, ucI2CCh);
        if(pucData[0] & LSM6DSR_STATUS_XLDA) {
            GSensorRead(READ_CURRENT_XL, true);
        }
        if (pucData[0] & LSM6DSR_STATUS_GDA) {
            GyroRead(READ_CURRENT_GYRO, true);
        }
        vTaskDelay(10/portTICK_RATE_MS);
        ucCount++;
    }
    DEBUGMSG("g-sensor int count = %d\r\n", g_gs_int_count);
    DEBUGMSG("gyro int count = %d\r\n", g_gyro_int_count);
 
    return ucRet;
}
 
void LSM6DSR_ISR1(void)
{
    // INT1
    unsigned char pucData[3];
    unsigned char ucI2CCh = I2C_CH_LSM6DSR;
 
    I2CRead(I2C_ADDR_LSM6DSR, LSM6DSR_STATUS_REG, &pucData[0], 1, ucI2CCh);
​    if (pucData[0] & LSM6DSR_STATUS_XLDA) {
        g_gs_int_count++;
    }
}
​
void LSM6DSR_ISR2(void)
{
   // INT2
    unsigned char pucData[3];
    unsigned char ucI2CCh = I2C_CH_LSM6DSR;
 
    I2CRead(I2C_ADDR_LSM6DSR, LSM6DSR_STATUS_REG, &pucData[0], 1, ucI2CCh);
    if (pucData[0] & LSM6DSR_STATUS_GDA) {
         g_gyro_int_count++;
    }
}

5 REPLIES 5
Federica Bossi
ST Employee

Hi @E-John​ ,

  • is that correct to get XL and gyro by data-ready interrupt mode? Yes it is
  • If read STATUS_REG on ISR, the INTx will keep on high, only do a XL read or gyro read from LSM6DSR, the INTx pin change to low? yes, it's correct

For any other questions I suggest you look at our PID on github.

If my reply answered your question, please click on Select as Best at the bottom of this post. This will help other users with the same issue to find the answer faster!

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
E-John
Associate III

Hi @Federica Bossi​ ​

I have referred to the code on github, it does not enable the ISR1 and ISR2 on LSM6DSR IC.

My question is when I enable XL and Gyro Interrupt on LSM6DSR

If read the XL and gyro data on while(1) loop, system is hanged, it is OK when read XL and gyro on ISR1 and ISR2

If XL and gyro interrupt is enable on LSM6DSR, to read data on while(1) or read data on ISR is correct?

Thanks.

Federica Bossi
ST Employee

Hi @E-John​ ,

Look at the function lsm6dsrx_main_interrupt on Github to enable the ISR1 and ISR2 on LSM6DSR IC.

In particular this part:

void lsm6dsrx_main_interrupt(void) {
stmdev_ctx_t dev_ctx;
 /* Uncomment to configure INT 1 */ 
//lsm6dsrx_pin_int1_route_t int1_route; 
/* Uncomment to configure INT 2 */
//lsm6dsrx_pin_int2_route_t int2_route;
 /* Initialize mems driver interface. */

Let me know if this solves your problem

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
E-John
Associate III

Hi Federica,

I have enable the interrupt on my system. it read the g-sensor and gyro data on while(1) loop, the system hanges on my side, is there any missing for this flow?

Thanks.

Federica Bossi
ST Employee

Ciao @E-John​ ,

Let's try to enable the dataready_pulsed bit (reg 0Bh) and see if the system still hangs.

Also please check interrupt priority in your system.

If my reply answered your question, please click on Select as Best at the bottom of this post. This will help other users with the same issue to find the answer faster!

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.