LSM6DS032 programming finite state machine
Hi all,
I'm trying to move Finite State Machine config from devkit using Unico GUI to final application. I've prepared movement wakeup example from FSM datasheet in Unico, which is working totally fine on devkit, it could even detect knocking in desk.

static const uint8_t lsm6dso32_prg_wakeup[] = {
0x50, 0x40, 0x12, 0x20, 0x0C, 0x0D,
0x00, 0x38, // threshold (1.00)
0xAE, 0x23, // hyst (0.03)
0x02, //mask A
0x02, //temp mask A
0x41,
0x75,
0x10,
0x10,
0x22,
0x00
};I've tried to replicate example from here: https://community.st.com/t5/mems-sensors/dear-st-community-i-am-currently-trying-to-setup-a-finite-state/td-p/77183
Overall, it doesn't seem to be working, code below gives me infinite interrupts on INT1. So far I discovered on devkit, it happens when fsm is correctly enabled but there is issue in fsm program. It also happens when I comment lsm6dso32_ln_pg_write.
ImuError imuInit(void)
{
uint8_t id;
HAL_StatusTypeDef err = HAL_OK;
// Set the IMU's reset bit and wait for it to clear after a reset
uint8_t resetValue = 1;
lsm6dso32_reset_set(&lsm6Context, resetValue);
do
{
lsm6dso32_reset_get(&lsm6Context, &resetValue);
} while (resetValue);
if (lsm6dso_device_id_get(&lsm6Context, &id) != HAL_OK)
{
return imuInitError;
}
if (id != LSM6DSO32_ID)
{
return imuUnknownID;
}
err = lsm6dso32_i3c_disable_set(&lsm6Context, LSM6DSO32_I3C_DISABLE);
if (err != HAL_OK)
{
return imuInitError;
}
err = lsm6dso32_auto_increment_set(&lsm6Context, PROPERTY_ENABLE);
if (err != HAL_OK)
{
return imuInitError;
}
err = lsm6dso32_block_data_update_set(&lsm6Context, PROPERTY_ENABLE);
if (err != HAL_OK)
{
return imuInitError;
}
err = lsm6dso32_fifo_mode_set(&lsm6Context, LSM6DSO32_BYPASS_MODE);
if (err != HAL_OK)
{
return imuInitError;
}
err = lsm6dso32_xl_full_scale_set(&lsm6Context, LSM6DSO32_8g);
if (err != HAL_OK)
{
return imuInitError;
}
err = lsm6dso32_gy_full_scale_set(&lsm6Context, LSM6DSO32_1000dps);
if (err != HAL_OK)
{
return imuInitError;
}
err = lsm6dso32_xl_data_rate_set(&lsm6Context,
LSM6DSO32_XL_ODR_26Hz_LOW_PW);
if (err != HAL_OK)
{
return imuError;
}
err = lsm6dso32_gy_data_rate_set(&lsm6Context,
LSM6DSO32_GY_ODR_26Hz_LOW_PW);
if (err != HAL_OK)
{
return imuError;
}
sGyroRange = gyro1000dps;
volatile uint32_t ret = 0;
lsm6dso32_pin_int1_route_t int1_route = { 0 };
int1_route.fsm_int1_a.int1_fsm1 = 1;
ret = lsm6dso32_pin_int1_route_set(&lsm6Context, &int1_route);
ret = lsm6dso32_long_cnt_int_value_set(&lsm6Context, 0x0000U);
ret = lsm6dso32_fsm_start_address_set(&lsm6Context, 0x0400U);
ret = lsm6dso32_fsm_number_of_programs_set(&lsm6Context, 1);
lsm6dso32_emb_fsm_enable_t fsm_enable = { 0 };
fsm_enable.fsm_enable_a.fsm1_en = 1;
ret = lsm6dso32_fsm_enable_set(&lsm6Context, &fsm_enable);
ret = lsm6dso32_fsm_data_rate_set(&lsm6Context, LSM6DSO32_ODR_FSM_26Hz);
ret = lsm6dso32_ln_pg_write(&lsm6Context, 0x0400, (uint8_t *)lsm6dso32_prg_wakeup, sizeof(lsm6dso32_prg_wakeup));
ret = lsm6dso32_fsm_init_set(&lsm6Context, 1);
ret = lsm6dso32_emb_fsm_en_set(&lsm6Context, 1);
lsm6dso32_pin_int2_route_t int2_route = { 0 };
int2_route.int2_ctrl.int2_drdy_g = 1;
lsm6dso32_pin_int2_route_set(&lsm6Context, &int2_route);
return imuOk;
}On MCU side interrupt is setted correctly, I've successfully ran dedicated wkup function like below, however it's not enough senstive for my application.
lsm6dso32_pin_int1_route_t int1_route = { 0 };
int1_route.md1_cfg.int1_wu = 1;
lsm6dso32_pin_int1_route_set(&lsm6Context, &int1_route);
lsm6dso32_wkup_threshold_set(&lsm6Context, 0b00000001);
lsm6dso32_wkup_dur_set(&lsm6Context, 0b00000000);Instead of lsm6dso32_ln_pg_write, I've tried to save FSM program byte by byte.
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x50);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x40);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x12);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x20);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x0C);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x0D);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x00); //thr
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x38); //thr
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0xAE); //hyst
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x23); //hyst
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x02);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x02);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x41);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x75);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x10);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x10);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x22);
ret = lsm6dso32_ln_pg_write_byte(&lsm6Context, 0x0400, 0x00);And it seems that it was programmed correctly, however it doesn't bring me any interrupts. When I try to break it, for example commenting last 2 bytes, I get the same infinite interrupts behavior as I mentioned in the beginning.
What other cause could there be for the fsm not working properly?
