Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #4

Open
wants to merge 8 commits into
base: pulga_x_v1.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cpu/nrf52/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
15 changes: 15 additions & 0 deletions cpu/nrf52/include/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 (3U)

/**
* @brief USBDEV buffer instantiation requirement
*/
Expand Down
1 change: 1 addition & 0 deletions cpu/nrf52/nrf52.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_MODULE_PM_LAYERED=y
91 changes: 91 additions & 0 deletions cpu/nrf52/periph/pm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#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"

#define RTC_FREQ 32768
#define RTC_INTERVAL 10

void nrf52_sys_on(void) {
/* Clear Event Register */
__SEV();
/* Wait for event */
__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");

ztimer_sleep(ZTIMER_MSEC, 10 * MS_PER_SEC);

pm_set(0);

break;
case 2:
//No sleep

break;
}
}

void pm_off(void);

void pm_set_lowest(void);
4 changes: 1 addition & 3 deletions cpu/nrf5x_common/periph/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -40,6 +40,4 @@ void pm_off(void)
}
#endif
NRF_POWER->SYSTEMOFF = 1;
while (1) {}
#endif /* ndef CPU_FAM_NRF9160 */
}
26 changes: 26 additions & 0 deletions examples/pulga-low-power-demo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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
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 ?=

# 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
3 changes: 3 additions & 0 deletions examples/pulga-low-power-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
examples/pulga-low-power-demo
================
See the documentation here: https://docs.google.com/document/d/12KXZuZcm3ZspvcS1gNZgoWsj-F7LGb05mXYUR6eE8TM/edit
55 changes: 55 additions & 0 deletions examples/pulga-low-power-demo/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <stdio.h>
#include <stdlib.h>

#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

int main(void)
{

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);

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;
}