1 /*
2  * Copyright (c) 2019 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "retained.h"
8 
9 #include <inttypes.h>
10 #include <stdio.h>
11 
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/drivers/comparator.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/pm/device.h>
17 #include <zephyr/sys/poweroff.h>
18 #include <zephyr/sys/util.h>
19 
20 #if defined(CONFIG_GRTC_WAKEUP_ENABLE)
21 #include <zephyr/drivers/timer/nrf_grtc_timer.h>
22 #define DEEP_SLEEP_TIME_S 2
23 #endif
24 #if defined(CONFIG_GPIO_WAKEUP_ENABLE)
25 static const struct gpio_dt_spec sw0 = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
26 #endif
27 #if defined(CONFIG_LPCOMP_WAKEUP_ENABLE)
28 static const struct device *comp_dev = DEVICE_DT_GET(DT_NODELABEL(comp));
29 #endif
30 
main(void)31 int main(void)
32 {
33 	int rc;
34 	const struct device *const cons = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
35 
36 	if (!device_is_ready(cons)) {
37 		printf("%s: device not ready.\n", cons->name);
38 		return 0;
39 	}
40 
41 	printf("\n%s system off demo\n", CONFIG_BOARD);
42 
43 	if (IS_ENABLED(CONFIG_APP_USE_RETAINED_MEM)) {
44 		bool retained_ok = retained_validate();
45 
46 		/* Increment for this boot attempt and update. */
47 		retained.boots += 1;
48 		retained_update();
49 
50 		printf("Retained data: %s\n", retained_ok ? "valid" : "INVALID");
51 		printf("Boot count: %u\n", retained.boots);
52 		printf("Off count: %u\n", retained.off_count);
53 		printf("Active Ticks: %" PRIu64 "\n", retained.uptime_sum);
54 	} else {
55 		printf("Retained data not supported\n");
56 	}
57 
58 #if defined(CONFIG_GRTC_WAKEUP_ENABLE)
59 	int err = z_nrf_grtc_wakeup_prepare(DEEP_SLEEP_TIME_S * USEC_PER_SEC);
60 
61 	if (err < 0) {
62 		printk("Unable to prepare GRTC as a wake up source (err = %d).\n", err);
63 	} else {
64 		printk("Entering system off; wait %u seconds to restart\n", DEEP_SLEEP_TIME_S);
65 	}
66 #endif
67 #if defined(CONFIG_GPIO_WAKEUP_ENABLE)
68 	/* configure sw0 as input, interrupt as level active to allow wake-up */
69 	rc = gpio_pin_configure_dt(&sw0, GPIO_INPUT);
70 	if (rc < 0) {
71 		printf("Could not configure sw0 GPIO (%d)\n", rc);
72 		return 0;
73 	}
74 
75 	rc = gpio_pin_interrupt_configure_dt(&sw0, GPIO_INT_LEVEL_ACTIVE);
76 	if (rc < 0) {
77 		printf("Could not configure sw0 GPIO interrupt (%d)\n", rc);
78 		return 0;
79 	}
80 
81 	printf("Entering system off; press sw0 to restart\n");
82 #endif
83 #if defined(CONFIG_LPCOMP_WAKEUP_ENABLE)
84 	comparator_set_trigger(comp_dev, COMPARATOR_TRIGGER_BOTH_EDGES);
85 	comparator_trigger_is_pending(comp_dev);
86 	printf("Entering system off; change signal level at comparator input to restart\n");
87 #endif
88 
89 	rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
90 	if (rc < 0) {
91 		printf("Could not suspend console (%d)\n", rc);
92 		return 0;
93 	}
94 
95 	if (IS_ENABLED(CONFIG_APP_USE_RETAINED_MEM)) {
96 		/* Update the retained state */
97 		retained.off_count += 1;
98 		retained_update();
99 	}
100 
101 	sys_poweroff();
102 
103 	return 0;
104 }
105