Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Restart after system off if the sensor driver is not suspended (Zephyr OS)

Hello, 

I'm working with LIS3DH sensor and I want to wakeup nRF52832 from system off by an interrupt from the sensor (not added the interrupt configuration yet). I'm using Zephyr OS v3.1.99 on a nRF52 DK, and I've merged two examples : nRF5x System Off demo and LIS2DH: Motion Sensor Monitor. The problem is, whenever I put the chip in system off mode, It will reset immediately, but if I suspend the sensor driver using pm_device_action_run(), it won't reset anymore. I don't know what's going on, can someone explain the reason?

This is the main.c :

/*
 * Copyright (c) 2019 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <zephyr/zephyr.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/pm/pm.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/policy.h>
#include <hal/nrf_gpio.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/init.h>

static void fetch_and_display(const struct device *sensor)
{
	static unsigned int count;
	struct sensor_value accel[3];
	struct sensor_value temperature;
	const char *overrun = "";
	int rc = sensor_sample_fetch(sensor);

	++count;
	if (rc == -EBADMSG) {
		/* Sample overrun.  Ignore in polled mode. */
		if (IS_ENABLED(CONFIG_LIS2DH_TRIGGER)) {
			overrun = "[OVERRUN] ";
		}
		rc = 0;
	}
	if (rc == 0) {
		rc = sensor_channel_get(sensor,
					SENSOR_CHAN_ACCEL_XYZ,
					accel);
	}
	if (rc < 0) {
		printf("ERROR: Update failed: %d\n", rc);
	} else {
		printf("#%u @ %u ms: %sx %f , y %f , z %f",
		       count, k_uptime_get_32(), overrun,
		       sensor_value_to_double(&accel[0]),
		       sensor_value_to_double(&accel[1]),
		       sensor_value_to_double(&accel[2]));
	}

	if (IS_ENABLED(CONFIG_LIS2DH_MEASURE_TEMPERATURE)) {
		if (rc == 0) {
			rc = sensor_channel_get(sensor, SENSOR_CHAN_DIE_TEMP, &temperature);
			if (rc < 0) {
				printf("\nERROR: Unable to read temperature:%d\n", rc);
			} else {
				printf(", t %f\n", sensor_value_to_double(&temperature));
			}
		}

	} else {
		printf("\n");
	}
}

#ifdef CONFIG_LIS2DH_TRIGGER
static void trigger_handler(const struct device *dev,
			    const struct sensor_trigger *trig)
{
	fetch_and_display(dev);
}
#endif


void main(void)
{
	const struct device *sensor = DEVICE_DT_GET_ANY(st_lis2dh);

	if (sensor == NULL) {
		printf("No device found\n");
		return;
	}
	if (!device_is_ready(sensor)) {
		printf("Device %s is not ready\n", sensor->name);
		return;
	}


#if CONFIG_LIS2DH_TRIGGER
	{
		struct sensor_trigger trig;
		int rc;

		trig.type = SENSOR_TRIG_DATA_READY;
		trig.chan = SENSOR_CHAN_ACCEL_XYZ;

		if (IS_ENABLED(CONFIG_LIS2DH_ODR_RUNTIME)) {
			struct sensor_value odr = {
				.val1 = 1,
			};

			rc = sensor_attr_set(sensor, trig.chan,
					     SENSOR_ATTR_SAMPLING_FREQUENCY,
					     &odr);
			if (rc != 0) {
				printf("Failed to set odr: %d\n", rc);
				return;
			}
			printf("Sampling at %u Hz\n", odr.val1);
		}

		rc = sensor_trigger_set(sensor, &trig, trigger_handler);
		if (rc != 0) {
			printf("Failed to set trigger: %d\n", rc);
			return;
		}

		printf("Waiting for triggers\n");
		while (true) {
			k_sleep(K_MSEC(2000));
		}
	}
#else /* CONFIG_LIS2DH_TRIGGER */
	printf("Polling at 0.5 Hz\n");

	fetch_and_display(sensor);

	pm_device_action_run(sensor, PM_DEVICE_ACTION_SUSPEND);

	printf("Going to sleep after 3 sec...\n");
	k_sleep(K_MSEC(3000));
	printf("Deep Sleep Starts now\n");

	pm_state_force(0u, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0});
	k_sleep(K_SECONDS(2U));

	while (true) {

	}
#endif /* CONFIG_LIS2DH_TRIGGER */
}

prj.conf :

CONFIG_STDOUT_CONSOLE=y
CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_CBPRINTF_FP_SUPPORT=y
CONFIG_LIS2DH=y
CONFIG_LIS2DH_ACCEL_RANGE_2G=y
CONFIG_LIS2DH_OPER_MODE_LOW_POWER=y
CONFIG_LIS2DH_ODR_1=y
# CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD=y
CONFIG_PM=y
CONFIG_PM_DEVICE=y
CONFIG_GPIO=y

dts.overlay :

&i2c0 {
    lis3dh: lis3dh@19 {
        status = "okay";
        compatible = "st,lis2dh";
        reg = <0x19 >;
    };
};

Parents Reply Children
  • Hi,

    None of the pins appear to be configured with sense enabled, which makes me think the wake-up is caused by something else. Please read the  RESETREAS after the device failed to stay in system off to see if the 'OFF' bit is set. You can do this with the "$ nrfjprog --memrd 0x40000400 " command (Note that the chip can't enter system OFF when it's in debug interface mode). 

  • Hi Vidar, 

    While my code was running, I ran the command you said in the terminal and I read : 0x40000400: 00000001. How do you interpret that ?

  • Hi, 

    The RESETPIN bit is set, indicating that the last reset was a pinreset. But did you make sure to read the register after this happened:

    The problem is, whenever I put the chip in system off mode, It will reset immediately

    ?

  • I turned on the log and I'm getting these errors :

    *** Booting Zephyr OS build v3.1.99-ncs1 ***
    Polling at 0.5 Hz
    #1 @ 266 ms: x -0.153216 , y -0.153216 , z 9.805824
    Going to sleep after 3 sec...
    [00:00:00.259,124] <inf> lis2dh: fs=2, odr=0x1 lp_en=0x8 scale=9576
    Deep Sleep Starts now
    [00:00:03.275,512] <err> os: ***** MPU FAULT *****
    [00:00:03.275,543] <err> os: Stacking error (context area might be not valid)
    [00:00:03.275,543] <err> os: Data Access Violation
    [00:00:03.275,573] <err> os: MMFAR Address: 0x200015f8
    [00:00:03.275,573] <err> os: r0/a1: 0x34f155bf r1/a2: 0x00c52802 r2/a3: 0x7d679934
    [00:00:03.275,604] <err> os: r3/a4: 0xc0ebe905 r12/ip: 0x5c1b1937 r14/lr: 0x0a8008e8
    [00:00:03.275,604] <err> os: xpsr: 0x2406de00
    [00:00:03.275,634] <err> os: Faulting instruction address (r15/pc): 0x8bc6d297
    [00:00:03.275,634] <err> os: >>> ZEPHYR FATAL ERROR 2: Stack overflow on CPU 0
    [00:00:03.275,665] <err> os: Current thread: 0x20000628 (unknown)
    [00:00:04.461,730] <err> fatal_error: Resetting system
    *** Booting Zephyr OS build v3.1.99-ncs1 ***
    Polling at 0.5 Hz
    #1 @ 266 ms: x -0.153216 , y -0.306432 , z 9.959040
    Going to sleep after 3 sec...




  • The crashlog indicates that you had a stack overflow in one of your threads. Please add CONFIG_DEBUG_THREAD_INFO=y to your prj.conf to get the name of the thread.

Related