This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

NCS system off fast

Hello,

NCS1.9.1, VSCode ,nRF21540DK,

i want to system off fast,   but 

after clicking the button1 many times, it cannot be restarted/awaken.


#include <stdio.h>
#include <zephyr.h>
#include <device.h>
#include <init.h>
#include <pm/pm.h>
#include <pm/device.h>
#include "pm.h"
// #include "retained.h"
#include <hal/nrf_gpio.h>

#define CONSOLE_LABEL DT_LABEL(DT_CHOSEN(zephyr_console))

#define BUSY_WAIT_S 1U
#define SLEEP_S 2U

/* Prevent deep sleep (system off) from being entered on long timeouts
 * or `K_FOREVER` due to the default residency policy.
 *
 * This has to be done before anything tries to sleep, which means
 * before the threading system starts up between PRE_KERNEL_2 and
 * POST_KERNEL.  Do it at the start of PRE_KERNEL_2.
 */
static int disable_ds_1(const struct device *dev)
{
	ARG_UNUSED(dev);
	pm_constraint_set(PM_STATE_SOFT_OFF);
	return 0;
}
SYS_INIT(disable_ds_1, PRE_KERNEL_2, 0);

void go_system_off(void)
{
	const struct device *cons = device_get_binding(CONSOLE_LABEL);

	printk("%s system off doing\n", CONFIG_BOARD);

	/*if (IS_ENABLED(CONFIG_APP_RETENTION)) {
		bool retained_ok = retained_validate();

		// Increment for this boot attempt and update.
		retained.boots += 1;
		retained_update();

		printk("Retained data: %s\n", retained_ok ? "valid" : "INVALID");
		printk("Boot count: %u\n", retained.boots);
		printk("Off count: %u\n", retained.off_count);
		printk("Active Ticks: %" PRIu64 "\n", retained.uptime_sum);
	} else {
		printk("Retained data not supported\n");
	}*/

	// Configure to generate PORT event (wakeup) on button 1 press.
	nrf_gpio_cfg_input(DT_GPIO_PIN(DT_NODELABEL(button0), gpios),NRF_GPIO_PIN_PULLUP);
	nrf_gpio_cfg_sense_set(DT_GPIO_PIN(DT_NODELABEL(button0), gpios),NRF_GPIO_PIN_SENSE_LOW);

	printk("Busy-wait %u s\n", BUSY_WAIT_S);
	k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);

	printk("Busy-wait %u s with UART off\n", BUSY_WAIT_S);
	int rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
	k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);
	rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME);

	// printk("Sleep %u s\n", SLEEP_S);
	// k_sleep(K_SECONDS(SLEEP_S));

	// printk("Sleep %u s with UART off\n", SLEEP_S);
	// rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
	// k_sleep(K_SECONDS(SLEEP_S));
	// rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME);

	printk("Entering system off; press BUTTON1 to restart\n");

	/*if (IS_ENABLED(CONFIG_APP_RETENTION)) {
		// Update the retained state
		retained.off_count += 1;
		retained_update();
	}*/

	/* Above we disabled entry to deep sleep based on duration of
	 * controlled delay.  Here we need to override that, then
	 * force entry to deep sleep on any delay.
	 */
	pm_power_state_force(0u, (struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0});

	/* Now we need to go sleep. This will let the idle thread runs and
	 * the pm subsystem will use the forced state. To confirm that the
	 * forced state is used, lets set the same timeout used previously.
	 */
	k_sleep(K_SECONDS(SLEEP_S));

	// printk("ERROR: System off failed\n");
	// while (true) {
	// 	// spin to avoid fall-off behavior
	// }
}

periodic_sync_off.rar

  

Best regards

Parents
  • Hi

    Ah, I see. Yes, this is possible, as it's not necessary to have these busy wait and extra sleep calls before going to system OFF. You can just disable the peripherals you're using, and then go directly to system OFF if you'd like. The following snippet can be commented out entirely as long as you disable the UART at some point I think.

    	printk("Busy-wait %u s\n", BUSY_WAIT_S);
    	k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);
    
    	printk("Busy-wait %u s with UART off\n", BUSY_WAIT_S);
    	int rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
    	k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);
    	rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME);

    Best regards,

    Simon

  • Hi,Simon,

    in main() ,when button pressed,will break while,

    and call   go_system_off();

      
    I tried system off five times and couldn't wake up again.
        press button to go_sysytem_off
           press button  to wake up ok
        press button to go_sysytem_off
           press button  to wake up ok
        press button to go_sysytem_off
           press button  to wake up ok
        press button to go_sysytem_off
           press button can't wake up
        press button to go_sysytem_off
           press button can't wake up
        press button to go_sysytem_off
           press button can't wake up

    when i change to as follow:

        k_timer_stop(&my_timer);
        bt_le_scan_cb_unregister(&scan_callbacks);
        bt_le_per_adv_sync_delete(sync);
        bt_le_scan_stop();
        go_system_off();
    problem solved.
        
    one more question:
    how to add codes to control LED twinkle or ADCreadBattery_NTC_temperature  in system off mode?
         

    Best regards,

  • Hi

    Glad to hear you were able to turn the device off correctly.

    In system OFF mode, the CPU is turned OFF (which is why the power consumption is so low), and thus you won't be able to use it for anything until you turn it back on. 

    Best regards,

    Simon

Reply
  • Hi

    Glad to hear you were able to turn the device off correctly.

    In system OFF mode, the CPU is turned OFF (which is why the power consumption is so low), and thus you won't be able to use it for anything until you turn it back on. 

    Best regards,

    Simon

Children
Related