Skip to main content
Visitor II
May 22, 2022
Solved

LIS2DTW12 control registers do not persist changes

  • May 22, 2022
  • 2 replies
  • 1711 views

We are trying to integrate the LIS2DTW12 into our project but aren't able to get basic functionality to work correctly. We see the correct value from `WHO_AM_I`, but then all registers are read only - i.e., when we write to the control registers then read them back, we still see only the default values on the registers. We can recreate this problem on all of our units.

Here is our startup sequence, taken from AN5038 (which is for the LIS2DW12, but seems as though it should apply):

  1. Read `WHO_AM_I` (`0x0F`) and receive `0x44`
  2. Read `CTRL2` (`0x21`) and receive `0x04`
  3. Write `0x44` to `CTRL2` for `SOFT_RESET`
  4. Wait 100us
  5. Write `0x84` to `CTRL2` for `BOOT`
  6. Wait 25ms
  7. Read `CTRL2` (`0x21`) and receive `0x04`
  8. Write `0x08` to `CTRL2` to enable `BDU` and disable `IF_ADD_INC`
  9. Read `CTRL2` (`0x21`) and receive `0x04`
  10. While `BDU` from `CTRL2` is set to `0`, go to step 8 above

Using this procedure, we never leave the loop and the register is never set. This is true if we attempt to write to any register. We see the same behavior without attempting to write to `BOOT` as well, and we aren't even sure that the `SOFT_RESET` or `BOOT` are even doing anything at all since it seems likely that they are not being set. We have no access to the `INT1` or `INT2` pins. Are we missing something about the setup for the LIS2DTW12?

EDIT Just wanted to mention that R/W and ACK bits are as expected, so it doesn't looks like it's an I2C problem.

    This topic has been closed for replies.
    Best answer by jw56

    Actually, I found the issue. It turns out that the ST MEMS Zephyr module has a bug, at least for the LIS2DTW12 and the LIS2DW12. The following is from the LIS2DTW12. In the datasheet we see the following I2C sequence for register writes:

    0693W00000NqxZfQAJ.pngHowever, in the Zephyr module, the sequence is

    0693W00000NqxaEQAR.pngNotice the repeated START condition. This is verified by examining the code:

    static inline int i2c_burst_write(const struct device *dev,
    				 uint16_t dev_addr,
    				 uint8_t start_addr,
    				 const uint8_t *buf,
    				 uint32_t num_bytes)
    {
    	struct i2c_msg msg[2];
     
    	msg[0].buf = &start_addr;
    	msg[0].len = 1U;
    	msg[0].flags = I2C_MSG_WRITE;
     
    	msg[1].buf = (uint8_t *)buf;
    	msg[1].len = num_bytes;
    	msg[1].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
     
    	return i2c_transfer(dev, msg, 2, dev_addr);
    }

    You see that there are two separate transfers. It is finally also verified by scope screens:

    0693W00000NqxaTQAR.bmp0693W00000NqxbgQAB.bmp0693W00000Nqxc5QAB.bmp0693W00000NqxaOQAR.bmp 

    2 replies

    jw56Author
    Visitor II
    May 25, 2022

    Hoping to bump this since it has been a few days.

    ST Employee
    May 27, 2022

    Hi @jw56​ ,

    this sound a bit strange... Ja, I would have checked the R/W bit as first step, but you say it is well configured. Is the VddIO set together with the Vdd? Which pull-up resistors are you using?

    It could be useful if you can share the oscilloscope screen of the I2C lines.

    -Eleon

    jw56AuthorAnswer
    Visitor II
    May 31, 2022

    Actually, I found the issue. It turns out that the ST MEMS Zephyr module has a bug, at least for the LIS2DTW12 and the LIS2DW12. The following is from the LIS2DTW12. In the datasheet we see the following I2C sequence for register writes:

    0693W00000NqxZfQAJ.pngHowever, in the Zephyr module, the sequence is

    0693W00000NqxaEQAR.pngNotice the repeated START condition. This is verified by examining the code:

    static inline int i2c_burst_write(const struct device *dev,
    				 uint16_t dev_addr,
    				 uint8_t start_addr,
    				 const uint8_t *buf,
    				 uint32_t num_bytes)
    {
    	struct i2c_msg msg[2];
     
    	msg[0].buf = &start_addr;
    	msg[0].len = 1U;
    	msg[0].flags = I2C_MSG_WRITE;
     
    	msg[1].buf = (uint8_t *)buf;
    	msg[1].len = num_bytes;
    	msg[1].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
     
    	return i2c_transfer(dev, msg, 2, dev_addr);
    }

    You see that there are two separate transfers. It is finally also verified by scope screens:

    0693W00000NqxaTQAR.bmp0693W00000NqxbgQAB.bmp0693W00000Nqxc5QAB.bmp0693W00000NqxaOQAR.bmp 

    ST Employee
    June 3, 2022

    Hi @jw56​ ,

    Great! Glad you solved the issue and you reported here on ST Community! :)

    -Eleon