Devicetree re-initialization after waking up from deep sleep

Hey, I have an nrf52840, with lis2dh sensor.

I configured the sensor using the devicetree using the following code

&i2c0 {
    status = "okay";

    lis2dh12: lis2dh12@18 {
        compatible = "st,lis2dh12";
        reg = <0x18>;
        int1-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; /* P0.11 connected to INT1 */
    };
};

and I change the sensetivity and some other register in the runtime, and the microcontroller goes to deep sleep every while, wakes up, and start from the main.

The question is: Does the sensor got reconfigured every time it wakes up ?. Do I have to reconfigure the sensor on every wake up ?.

And most importantly, If an interrupt happened and waked up the microcontroller, and the sensor library reads the register that indicates that there is an interrupt. will that interrupt goes away ?

If yes, is there a way to prevent the devicetree initialization and still use the library ?.

It shows those lines on every wake up

00> [00:00:00.007,202] <inf> lis2dh: lis2dh12@19: int2 on [email protected]
00> [00:00:00.008,819] <inf> lis2dh: fs=2, odr=0x4 lp_en=0x0 scale=9576

Thanks in advanced

Parents
  • Sorry for raising the question,

    The answer is YES, it do initialize every time, and to stop it we need to raise a flag in the device tree

    		zephyr,deferred-init;
    

    But every time the microcontroller wakes up, the return of the function device_init(sensor) is false.
    Do I have to manually initialize it every time after waking up ?. Because it sound like it should only be initialized once and just sense in the rest of the runtime.

    And does it got it's initialization arguments from the device tree properties ?

  • Hi Abdulrahman,

    No need to apologize about the initial question.

    abdulrahman yasser said:
    But every time the microcontroller wakes up, the return of the function device_init(sensor) is false.
    Do I have to manually initialize it every time after waking up ?. Because it sound like it should only be initialized once and just sense in the rest of the runtime.

    device_init() doesn't return a boolean value, but an integer value. What value are you getting from it?

    By deep sleep, I assume you are putting the device into System OFF state. Waking up from System OFF state is essentially a reset; and generally, you need to initialize drivers again after a reset, because a lot of drivers are stateful.
    If the driver you are working with is stateless, then you might be fine with not calling device_init().

    I tried to give the lis2dh driver a quick read, but it's complex enough that I don't dare claim either way after a quick glance.

    To err on the safer side, I recommend having the driver initialized gain anyway, in which case, you can skip the deferred-init property altogether.

    That being said, is there a reason you want to skip the initialization?

    And most importantly, If an interrupt happened and waked up the microcontroller, and the sensor library reads the register that indicates that there is an interrupt. will that interrupt goes away ?

    During System OFF, the entire system is powered down, so there is no I2C interrupt that can wake the SoC up.

Reply
  • Hi Abdulrahman,

    No need to apologize about the initial question.

    abdulrahman yasser said:
    But every time the microcontroller wakes up, the return of the function device_init(sensor) is false.
    Do I have to manually initialize it every time after waking up ?. Because it sound like it should only be initialized once and just sense in the rest of the runtime.

    device_init() doesn't return a boolean value, but an integer value. What value are you getting from it?

    By deep sleep, I assume you are putting the device into System OFF state. Waking up from System OFF state is essentially a reset; and generally, you need to initialize drivers again after a reset, because a lot of drivers are stateful.
    If the driver you are working with is stateless, then you might be fine with not calling device_init().

    I tried to give the lis2dh driver a quick read, but it's complex enough that I don't dare claim either way after a quick glance.

    To err on the safer side, I recommend having the driver initialized gain anyway, in which case, you can skip the deferred-init property altogether.

    That being said, is there a reason you want to skip the initialization?

    And most importantly, If an interrupt happened and waked up the microcontroller, and the sensor library reads the register that indicates that there is an interrupt. will that interrupt goes away ?

    During System OFF, the entire system is powered down, so there is no I2C interrupt that can wake the SoC up.

Children
  • Thanks for your reply,

    My mistake, device_init() doesn't return false.

    It wakes up the microcontroller through interrupt connection between the sensor and the microcontroller.

    My problem is that the microcontroller and the sensor work together perfectly fine on the initialization and till the device goes to sleep, 

    After going to sleep, waking up, re-initialize the sensor, the sensor trigger doesn't work.

    The sensor works perfectly on every function, i can read it's values, suspend, resume, and everything.

    But I can't set the trigger function after the first wake up.
    I read the INT pin that connected to the microcontroller, and it goes high once the sensor is moved, but the sensor doesn't call the handler function that I set.

    void enable_sensor_interrupt(void) {
      device_init(sensor);
      k_msleep(500);
      if(sensor == NULL){
          printf("No device found\n");
        //   return;
      }
      if (!device_is_ready(sensor)) {
          printf("LIS2DH not ready!\n");
        //   return;
      }
      pm_device_action_run(sensor, PM_DEVICE_ACTION_RESUME);
      struct sensor_trigger trig;
      int rc;
      trig.type = SENSOR_TRIG_DELTA;
      trig.chan = SENSOR_CHAN_ACCEL_XYZ;
      struct sensor_value odr = {.val1 = Tilt_Senstivity};
      rc = sensor_attr_set(sensor, trig.chan, SENSOR_ATTR_SLOPE_TH, &odr);
      if (rc != 0) {
        printf("Failed to set odr: %d\n", rc);
        // return 0;
      }
    
      printf("The function address is %p\r\n", trigger_handler_isr);
      rc = sensor_trigger_set(sensor, &trig, trigger_handler_isr);
      if (rc != 0) {
        printf("Failed to set trigger: %d\n", rc);
      }
    }
    

    The prev code works perfectly fine on the first initialization, the sensor sense move, interrupt happens, it calls the handler function. But it goes sleep and the handler function isn't connected with the sensor interrupt again!.

    So the sensor works, I can read from it, and it set the pin to high once I move it.

    In the code I can resume the sensor and read from the sensor using sensor_sample_fetch function.

    But the mapping between the handler function and the sensor doesn't work after waking up.

  • I see, it could be that after waking the device from System OFF, the GPIO LATCH register wasn't reset. Could you please add a handling that clear the LATCH register if the reset reason is waking up from System OFF?

    If that doesn't help, here are a few things to check:

    If you are going to use deferred-init and device_init(), then you should check that the device pointer isn't NULL before calling it as well.

    I see that you are not checking the return value of a lot of function calls. Are you sure they all ran correctly?

    Could you please add checking of the return value and logging it out?

    I also find the pm_device_action_run() call a little strange. Is there a reason you need it here?

    Could you please also add CONFIG_SENSOR_LOG_LEVEL_DBG to your project and give me the full log?

Related