nRF9160: LIS2DW12 high current consumption

Hi,

OS: Windows 10
Editor: SEGGER Embedded Studio for ARM (Nordic Edition) V5.68 (64-bit)
nrfjprog version: 10.15.3 external
JLinkARM.dll version: 7.58b
nRF Connect SDK version: 1.9.0
nRF9160 modem firmware version: 1.2.7


We have STMicroelectonics LIS2DW12 accelerometer on our custom board which has nRF9160 SiP and we are using the nRF Connect SDK.

The configuration of the LIS2DW12:
Interrupt pin: INT2
Accel range / full scale: 2G
ODR: 1.6Hz
Power mode: Low Power Mode 1
Low noise: Disabled
Stationary/motion: Enabled
VDD & VDD_IO: 3.0V
Bus: I2C

We have faced a high power consumption problem with LIS2DW12 (interrupt pin) earlier with SDK v1.5.0 and we created a ticket to DevZone (private ticket, Case ID: 269107) and got help and a solution to that problem. Now we faced this same problem again with the nRF Connect SDK v1.9.0. Our problem is that our board is consuming a lot of power when we are using the LIS2DW12. If we fully disable LIS2DW12 or just don't enable its trigger, the consumption is about 20µA and when it's enabled the consumption is around 200uA.

I thought it would be easier to discuss about it in that private ticket since we have already provided the schematics and other information there. But unfortunately, we didn't get any response there and this is a pretty urgent case for us so I thought I have to ask here too.

So, from SDK v1.6.0 we have used CONFIG_GPIO_NRF_INT_EDGE_USING_SENSE and the power consumption has been low with this config.
But now with SDK v1.9.0 and after this commit this config has been removed and it's replaced with sense-edge-mask definition in dts.

I modified our custom board dts like this:

&gpio0 {
	status = "okay";

	...

	/* The LIS2DW12 interrupt pin needs to use
	 * SENSE mechanism to keep the power consumption low.
	 * Use the same pin number as in LIS2DW12 irg-gpios section. */
    sense-edge-mask = <29>;
};

&i2c2 {
	compatible = "nordic,nrf-twim";
	status = "okay";
	sda-pin = <26>;
	scl-pin = <27>;
	/* It is recommended to use the same value
	 * for the zephyr,flash-buf-max-size and for the zephyr,concat-buf-size,
	 * as both these buffering mechanisms can utilize the same space in RAM. */
	zephyr,concat-buf-size = <512>;
	zephyr,flash-buf-max-size = <512>;
	clock-frequency = <I2C_BITRATE_STANDARD>;

	lis2dw12@19 {
		compatible = "st,lis2dw12";
		label = "LIS2DW12";
		reg = <0x19>;
		irq-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
		int-pin = <2>;
		range = <2>;
		power-mode = <0>;
	};
};

I found there might be a bug in Zephyr's gpio_nrfx driver:

In zephyr/drivers/gpio/gpio_nrfx.c - gpio_nrfx_pin_interrupt_configure(), it was earlier like this:

	/* Use GPIOTE IN event (if enabled) for edge on input pin. */
	if (IS_ENABLED(CONFIG_GPIO_NRF_INT_EDGE_USING_GPIOTE) &&

And it was changed to the below. I guess it shouldn't go inside the if-statement if the sense is configured for the specific pin. But now it goes inside and calls the nrfx_gpiote_channel_get() function because there is the !-mark at the beginning of if-statement.

	/* If edge mode is to be used and pin is not configured to use sense for
	 * edge use IN event.
	 */
	if (!(BIT(pin) & get_port_cfg(port)->edge_sense) &&

I added some prints inside the gpio_nrfx_pin_interrupt_configure() function and got responses like these:

 GPIO PORT: 0 -> PIN: 29 -> ABS PIN: 29 -> INT MODE: 81920 -> INT TRIG: 262144 -> EDGE SENSE: 29 
 BIT(pin): 536870912 
 get_port_cfg(port)->edge_sense: 29 
 !(BIT(pin) & get_port_cfg(port)->edge_sense): 1 
 nrfx_gpiote_channel_get() 
 nrfx_gpiote_input_configure() 
 nrfx_gpiote_trigger_enable() 

With the below changes to the if-statement, and the power consumption dropped from about 200uA to about 20uA.

    // 1: !-mark removed
	if ((BIT(pin) & get_port_cfg(port)->edge_sense) &&

    // 2: don't use BIT()
	if (!(pin & get_port_cfg(port)->edge_sense) &&

    // 3: don't use BIT(), use abs_pin
	if (!(abs_pin & get_port_cfg(port)->edge_sense) &&

So, have I defined the sense-edge-mask correctly or am I missing something else?
Or could this be a bug in Zephyr's gpio_nrfx driver?

BR,
Tero

Parents
  • Hi, the sense-edge-mask property should contain the bitmask of the pins you want to configure with the SENSE event. So the following configuration would set pin 29 to not use GPIOTE IN event:

    &gpio0 {
        ....
        sense-edge-mask = <(1 << 29)>;
    };

    This way you can add several pins to the same field:

        sense-edge-mask = <((1 << 29) | (1 << 30))>;

    Or you can use hex values if that's easier for you. This is the mask for pin 29:

        sense-edge-mask = <0x20000000>;

    Your workarounds are working in this specific case, but you are "fixing" the wrong part of the if statement.

    Best regards,
    Stian

Reply
  • Hi, the sense-edge-mask property should contain the bitmask of the pins you want to configure with the SENSE event. So the following configuration would set pin 29 to not use GPIOTE IN event:

    &gpio0 {
        ....
        sense-edge-mask = <(1 << 29)>;
    };

    This way you can add several pins to the same field:

        sense-edge-mask = <((1 << 29) | (1 << 30))>;

    Or you can use hex values if that's easier for you. This is the mask for pin 29:

        sense-edge-mask = <0x20000000>;

    Your workarounds are working in this specific case, but you are "fixing" the wrong part of the if statement.

    Best regards,
    Stian

Children
Related