From 5ba404bf9ebfdb4f0884475c17ab13b84f69389f Mon Sep 17 00:00:00 2001 From: William Takahashi Date: Mon, 17 Oct 2022 17:25:33 -0300 Subject: [PATCH 1/6] Initial configs for pm_layered --- cpu/nrf52/Makefile.features | 8 ++++++++ cpu/nrf52/include/periph_cpu.h | 15 +++++++++++++++ cpu/nrf52/nrf52.config | 1 + cpu/nrf52/periph/pm.c | 19 +++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 cpu/nrf52/nrf52.config create mode 100644 cpu/nrf52/periph/pm.c diff --git a/cpu/nrf52/Makefile.features b/cpu/nrf52/Makefile.features index 8edd5e4c5e92..71062deb3e3a 100644 --- a/cpu/nrf52/Makefile.features +++ b/cpu/nrf52/Makefile.features @@ -5,6 +5,8 @@ CPU_CORE = cortex-m4 endif CPU_FAM = nrf52 +USEMODULE += pm_layered + # The 802.15.4 radio is not available on all SoCs ifneq (,$(filter nrf52811xxaa nrf52820xxaa nrf52833xxaa nrf52840xxaa,$(CPU_MODEL))) FEATURES_PROVIDED += radio_nrf802154 @@ -34,3 +36,9 @@ ifneq (,$(filter nrf52811% nrf52820% nrf52833% nrf52840%,$(CPU_MODEL))) endif include $(RIOTCPU)/nrf5x_common/Makefile.features + +# This configuration enables modules that are only available when using Kconfig +# module modelling +ifeq (1, $(TEST_KCONFIG)) + KCONFIG_ADD_CONFIG += $(RIOTCPU)/nrf52/nrf52.config +endif \ No newline at end of file diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h index 7f3bef6051aa..2db397ce3256 100644 --- a/cpu/nrf52/include/periph_cpu.h +++ b/cpu/nrf52/include/periph_cpu.h @@ -27,6 +27,15 @@ extern "C" { #endif +/** + * @name Power management configuration + * @{ + */ +#define PROVIDES_PM_SET_LOWEST +#define PROVIDES_PM_RESTART +#define PROVIDES_PM_OFF +#define PROVIDES_PM_LAYERED_OFF + /** * @brief Enable the workaround for the SPI single byte transmit errata (No. * 58 on the nrf52832) @@ -269,6 +278,12 @@ void spi_twi_irq_register_i2c(NRF_TWIM_Type *bus, */ #define USBDEV_CPU_DMA_ALIGNMENT (4) +/** + * @brief Number of usable low power modes + FIXME: not sure what is the actual number of modes (see datasheet) + */ +#define PM_NUM_MODES (2U) + /** * @brief USBDEV buffer instantiation requirement */ diff --git a/cpu/nrf52/nrf52.config b/cpu/nrf52/nrf52.config new file mode 100644 index 000000000000..2e5ab372b17f --- /dev/null +++ b/cpu/nrf52/nrf52.config @@ -0,0 +1 @@ +CONFIG_MODULE_PM_LAYERED=y \ No newline at end of file diff --git a/cpu/nrf52/periph/pm.c b/cpu/nrf52/periph/pm.c new file mode 100644 index 000000000000..1f5f0fbacad7 --- /dev/null +++ b/cpu/nrf52/periph/pm.c @@ -0,0 +1,19 @@ +#include "periph/pm.h" +#include "periph_cpu.h" +#include "pm_layered.h" + + + +void pm_set(unsigned mode) +{ + switch (mode) { + case 0: + //Implementar o power mode 0 + break; + case 1: + //Implementar o power mode 1 + break; + } +} + +void pm_off(void); \ No newline at end of file From c6ae478dbb26f18b625748bb186127318c22e309 Mon Sep 17 00:00:00 2001 From: William Takahashi Date: Tue, 25 Oct 2022 20:05:12 -0300 Subject: [PATCH 2/6] Implementacoes de pm_set e pm_off --- cpu/nrf52/include/periph_cpu.h | 2 +- cpu/nrf52/periph/pm.c | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h index 2db397ce3256..5f155c2ef527 100644 --- a/cpu/nrf52/include/periph_cpu.h +++ b/cpu/nrf52/include/periph_cpu.h @@ -282,7 +282,7 @@ void spi_twi_irq_register_i2c(NRF_TWIM_Type *bus, * @brief Number of usable low power modes FIXME: not sure what is the actual number of modes (see datasheet) */ -#define PM_NUM_MODES (2U) +#define PM_NUM_MODES (3U) /** * @brief USBDEV buffer instantiation requirement diff --git a/cpu/nrf52/periph/pm.c b/cpu/nrf52/periph/pm.c index 1f5f0fbacad7..29be4633ddc4 100644 --- a/cpu/nrf52/periph/pm.c +++ b/cpu/nrf52/periph/pm.c @@ -1,19 +1,27 @@ #include "periph/pm.h" #include "periph_cpu.h" #include "pm_layered.h" - +#include "cpu_conf.h" void pm_set(unsigned mode) { switch (mode) { case 0: - //Implementar o power mode 0 + //Implementar o light sleep + cortexm_sleep(0); break; case 1: - //Implementar o power mode 1 + //Implementar o deep sleep + cortexm_sleep(1); + break; + case 2: + //Implementar o Wait fo event sleep + nrf52_sleep(); break; } } -void pm_off(void); \ No newline at end of file +void pm_off(void); + +void pm_set_lowest(void); \ No newline at end of file From 849c40b529fb9e6bda75f2781822d0d9b37a8fb7 Mon Sep 17 00:00:00 2001 From: William Takahashi Date: Fri, 18 Nov 2022 08:56:51 -0300 Subject: [PATCH 3/6] Implementacoes dos power modes --- cpu/nrf52/periph/pm.c | 15 +++++++++++---- cpu/nrf5x_common/periph/pm.c | 4 +--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cpu/nrf52/periph/pm.c b/cpu/nrf52/periph/pm.c index 29be4633ddc4..9eb1e5b84dbc 100644 --- a/cpu/nrf52/periph/pm.c +++ b/cpu/nrf52/periph/pm.c @@ -1,7 +1,6 @@ -#include "periph/pm.h" #include "periph_cpu.h" -#include "pm_layered.h" -#include "cpu_conf.h" +#include "cpu.h" + void pm_set(unsigned mode) @@ -17,7 +16,15 @@ void pm_set(unsigned mode) break; case 2: //Implementar o Wait fo event sleep - nrf52_sleep(); + NRF_POWER->TASKS_CONSTLAT = 0; + NRF_POWER->TASKS_LOWPWR = 1; + __DSB(); + /* Clear Event Register */ + __SEV(); + /* Wait for event */ + __WFE(); + /* Wait for event */ + __WFE(); break; } } diff --git a/cpu/nrf5x_common/periph/pm.c b/cpu/nrf5x_common/periph/pm.c index 690afcc6a5e4..6b998530b761 100644 --- a/cpu/nrf5x_common/periph/pm.c +++ b/cpu/nrf5x_common/periph/pm.c @@ -30,7 +30,7 @@ /* TODO: implement proper pm_off for nRF9160 */ void pm_off(void) { -#ifndef CPU_FAM_NRF9160 + #ifdef CPU_FAM_NRF51 NRF_POWER->RAMON = 0; #else @@ -40,6 +40,4 @@ void pm_off(void) } #endif NRF_POWER->SYSTEMOFF = 1; - while (1) {} -#endif /* ndef CPU_FAM_NRF9160 */ } From 0573176302e4da8172706703c51d42d9f0d9198b Mon Sep 17 00:00:00 2001 From: Geovane Fedrecheski Date: Wed, 23 Nov 2022 09:52:54 -0300 Subject: [PATCH 4/6] feat[examples]: add a example focused on low-power testing for the pulga --- examples/pulga-low-power-demo/Makefile | 23 +++++++++++ examples/pulga-low-power-demo/README.md | 3 ++ examples/pulga-low-power-demo/main.c | 52 +++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 examples/pulga-low-power-demo/Makefile create mode 100644 examples/pulga-low-power-demo/README.md create mode 100644 examples/pulga-low-power-demo/main.c diff --git a/examples/pulga-low-power-demo/Makefile b/examples/pulga-low-power-demo/Makefile new file mode 100644 index 000000000000..d3710a809273 --- /dev/null +++ b/examples/pulga-low-power-demo/Makefile @@ -0,0 +1,23 @@ +# name of your application +APPLICATION = pulga-low-power-demo + +# If no BOARD is found in the environment, use this default: +BOARD ?= native + +FEATURES_OPTIONAL += periph_gpio_irq + +USEMODULE += shell +USEMODULE += shell_commands +USEMODULE += ztimer +USEMODULE += ztimer_msec + +# avoid running Kconfig by default +SHOULD_RUN_KCONFIG ?= + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/pulga-low-power-demo/README.md b/examples/pulga-low-power-demo/README.md new file mode 100644 index 000000000000..6cf8fa938255 --- /dev/null +++ b/examples/pulga-low-power-demo/README.md @@ -0,0 +1,3 @@ +examples/pulga-low-power-demo +================ +See the documentation here: https://docs.google.com/document/d/12KXZuZcm3ZspvcS1gNZgoWsj-F7LGb05mXYUR6eE8TM/edit diff --git a/examples/pulga-low-power-demo/main.c b/examples/pulga-low-power-demo/main.c new file mode 100644 index 000000000000..0b9aa2aba78c --- /dev/null +++ b/examples/pulga-low-power-demo/main.c @@ -0,0 +1,52 @@ +#include +#include + +#include "periph/pm.h" +#ifdef MODULE_PERIPH_GPIO +#include "board.h" +#include "periph/gpio.h" +#endif +#ifdef MODULE_PM_LAYERED +#include "pm_layered.h" +#endif + +extern int _pm_handler(int argc, char **argv); + +#include "shell.h" +#include "ztimer.h" + +#ifndef BTN0_INT_FLANK +#define BTN0_INT_FLANK GPIO_RISING +#endif + +#if defined(MODULE_PERIPH_GPIO_IRQ) && defined(BTN0_PIN) +static void btn_cb(void *ctx) +{ + (void) ctx; + puts("BTN0 pressed!"); +} +#endif /* MODULE_PERIPH_GPIO_IRQ */ + +int main(void) +{ + puts("Pulga Low Power!"); + + printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD); + printf("This board features a(n) %s MCU.\n", RIOT_MCU); + + printf("This application allows you to test the CPU power management.\n" + "The available power modes are 0 - %d. Lower-numbered power modes\n" + "save more power, but may require an event/interrupt to wake up\n" + "the CPU. Reset the CPU if needed.\n\n\n", + PM_NUM_MODES - 1); + +#if defined(MODULE_PERIPH_GPIO_IRQ) && defined(BTN0_PIN) + puts("using BTN0 as wake-up source"); + gpio_init_int(BTN0_PIN, BTN0_MODE, BTN0_INT_FLANK, btn_cb, NULL); +#endif + + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + + return 0; +} From ad0e2fce3e9649bc2da2fc34bd3bf457f73db377 Mon Sep 17 00:00:00 2001 From: William Takahashi Date: Sun, 11 Dec 2022 23:49:33 -0300 Subject: [PATCH 5/6] RTC sleep --- cpu/nrf52/periph/pm.c | 47 ++++++++++++++++++-------- examples/pulga-low-power-demo/Makefile | 3 ++ examples/pulga-low-power-demo/main.c | 7 ++-- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/cpu/nrf52/periph/pm.c b/cpu/nrf52/periph/pm.c index 9eb1e5b84dbc..ccd5e16e0ecf 100644 --- a/cpu/nrf52/periph/pm.c +++ b/cpu/nrf52/periph/pm.c @@ -1,30 +1,49 @@ #include "periph_cpu.h" #include "cpu.h" +#include "pm_layered.h" +#include "clk.h" +#include "board.h" +#include "periph_conf.h" +#include "timex.h" +#include "ztimer.h" +#include "nrf_clock.h" +#include "ztimer/periph_rtc.h" +void nrf52_sys_on(void) { + /* Clear Event Register */ + __SEV(); + /* Wait for event */ + __WFE(); + /* Wait for event */ + __WFE(); + +} void pm_set(unsigned mode) { switch (mode) { case 0: - //Implementar o light sleep - cortexm_sleep(0); + //RTC wake up source sleep + + puts("Entering sleep"); + nrf52_sys_on(); + + pm_set(1); break; case 1: - //Implementar o deep sleep - cortexm_sleep(1); + //Ztimer active mode + + puts("Entering active"); + __WFE(); + ztimer_sleep(ZTIMER_SEC, 10); + + pm_set(0); + break; case 2: - //Implementar o Wait fo event sleep - NRF_POWER->TASKS_CONSTLAT = 0; - NRF_POWER->TASKS_LOWPWR = 1; - __DSB(); - /* Clear Event Register */ - __SEV(); - /* Wait for event */ - __WFE(); - /* Wait for event */ - __WFE(); + //No sleep + break; } } diff --git a/examples/pulga-low-power-demo/Makefile b/examples/pulga-low-power-demo/Makefile index d3710a809273..d9099ab60fb3 100644 --- a/examples/pulga-low-power-demo/Makefile +++ b/examples/pulga-low-power-demo/Makefile @@ -5,11 +5,14 @@ APPLICATION = pulga-low-power-demo BOARD ?= native FEATURES_OPTIONAL += periph_gpio_irq +FEATURES_OPTIONAL += periph_rtc USEMODULE += shell USEMODULE += shell_commands USEMODULE += ztimer USEMODULE += ztimer_msec +USEMODULE += ztimer_usec +USEMODULE += ztimer_sec # avoid running Kconfig by default SHOULD_RUN_KCONFIG ?= diff --git a/examples/pulga-low-power-demo/main.c b/examples/pulga-low-power-demo/main.c index 0b9aa2aba78c..6808490a7f7f 100644 --- a/examples/pulga-low-power-demo/main.c +++ b/examples/pulga-low-power-demo/main.c @@ -25,12 +25,15 @@ static void btn_cb(void *ctx) (void) ctx; puts("BTN0 pressed!"); } -#endif /* MODULE_PERIPH_GPIO_IRQ */ +#endif int main(void) { - puts("Pulga Low Power!"); + puts("Pulga Low Power!"); + #ifdef MODULE_ZTIMER + puts("ZTIMER definido!"); + #endif printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD); printf("This board features a(n) %s MCU.\n", RIOT_MCU); From 72ee579926ef65849da911b9c5a59c2f869c2659 Mon Sep 17 00:00:00 2001 From: William Takahashi Date: Sat, 17 Dec 2022 01:03:58 -0300 Subject: [PATCH 6/6] feature nrf52840 rtc sleep --- cpu/nrf52/periph/pm.c | 48 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/cpu/nrf52/periph/pm.c b/cpu/nrf52/periph/pm.c index ccd5e16e0ecf..c39a9eec22db 100644 --- a/cpu/nrf52/periph/pm.c +++ b/cpu/nrf52/periph/pm.c @@ -10,6 +10,9 @@ #include "nrf_clock.h" #include "ztimer/periph_rtc.h" +#define RTC_FREQ 32768 +#define RTC_INTERVAL 10 + void nrf52_sys_on(void) { /* Clear Event Register */ __SEV(); @@ -17,26 +20,61 @@ void nrf52_sys_on(void) { __WFE(); /* Wait for event */ __WFE(); +} + +void RTC1_IRQHandler(void) +{ + if(NRF_RTC1->EVENTS_COMPARE[0] == 1) { + NRF_RTC1->EVENTS_COMPARE[0] = 0; + } +} + +// Set the RTC to trigger a wake-up interrupt every 10 second +void clock_config(void) { + // Configure the RTC to use the low-frequency crystal + NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos); + NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; + NRF_CLOCK->TASKS_LFCLKSTART = 1; + + // Wait for the low-frequency crystal to start + while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0); + +} +void rtc_config(void) +{ + + NRF_RTC1->PRESCALER = 0; + NRF_RTC1->CC[0] = RTC_INTERVAL * RTC_FREQ; + + NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk; // Enable interrupt on compare event 0 + NRF_RTC1->TASKS_CLEAR = 1; + NRF_RTC1->TASKS_START = 1; } + void pm_set(unsigned mode) { + clock_config(); switch (mode) { case 0: //RTC wake up source sleep - + // Initialize the RTC + + rtc_config(); puts("Entering sleep"); nrf52_sys_on(); - + RTC1_IRQHandler(); + + puts("Exiting sleep"); pm_set(1); + break; case 1: //Ztimer active mode - puts("Entering active"); - __WFE(); - ztimer_sleep(ZTIMER_SEC, 10); + + ztimer_sleep(ZTIMER_MSEC, 10 * MS_PER_SEC); pm_set(0);