[LSM6DSR] Correct flow to get XL and gyro data by data-ready interrupt mode?
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
- 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?
- 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
- 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++;
}
}