cpu/sam0_common: GPIO: use tamper detection to wake from Deep Sleep
On samd5x only the RTC can wake the CPU from Deep Sleep (pm modes 0 & 1). The external interrupt controller is disabled, but we can use the tamper detection of the RTC. If an gpio interrupt is configured on one of the five tamper detect pins, those can be used to wake the CPU from Deep Sleep / Hibernate.
This commit is contained in:
parent
0499d016ad
commit
310eb4970c
@ -16,6 +16,15 @@
|
|||||||
* @file gpio.c
|
* @file gpio.c
|
||||||
* @brief Low-level GPIO driver implementation
|
* @brief Low-level GPIO driver implementation
|
||||||
*
|
*
|
||||||
|
* On processors that support Deep Sleep the External Interrupt Controller
|
||||||
|
* will be off during Deep Sleep.
|
||||||
|
* To wake the CPU up from Deep Sleep the RTC Tamper Detection will be
|
||||||
|
* used instead.
|
||||||
|
* Only a few pins (@ref rtc_tamper_pins) can be used for that purpose.
|
||||||
|
*
|
||||||
|
* Note that when configuring those pins as interrupt, the RTC/RTT will be
|
||||||
|
* stopped briefly as the RTC configuration is enable protected.
|
||||||
|
*
|
||||||
* @author Troels Hoffmeyer <troels.d.hoffmeyer@gmail.com>
|
* @author Troels Hoffmeyer <troels.d.hoffmeyer@gmail.com>
|
||||||
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
|
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
|
||||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||||
@ -240,11 +249,41 @@ static int _exti(gpio_t pin)
|
|||||||
return exti_config[port_num][_pin_pos(pin)];
|
return exti_config[port_num][_pin_pos(pin)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if an RTC tamper pin was configured as interrupt */
|
||||||
|
__attribute__ ((unused))
|
||||||
|
static bool _rtc_irq_enabled(void)
|
||||||
|
{
|
||||||
|
#if MODULE_PERIPH_GPIO_TAMPER_WAKE
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(rtc_tamper_pins); ++i) {
|
||||||
|
int exti = _exti(rtc_tamper_pins[i]);
|
||||||
|
|
||||||
|
if (exti == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_EIC->INTENSET.reg & (1 << exti)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _init_rtc_pin(gpio_t pin, gpio_flank_t flank)
|
||||||
|
{
|
||||||
|
if (IS_ACTIVE(MODULE_PERIPH_GPIO_TAMPER_WAKE)) {
|
||||||
|
rtc_tamper_register(pin, flank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
||||||
gpio_cb_t cb, void *arg)
|
gpio_cb_t cb, void *arg)
|
||||||
{
|
{
|
||||||
int exti = _exti(pin);
|
int exti = _exti(pin);
|
||||||
|
|
||||||
|
/* if it's a tamper pin configure wake from Deep Sleep */
|
||||||
|
_init_rtc_pin(pin, flank);
|
||||||
|
|
||||||
/* make sure EIC channel is valid */
|
/* make sure EIC channel is valid */
|
||||||
if (exti == -1) {
|
if (exti == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -330,11 +369,17 @@ void gpio_pm_cb_enter(int deep)
|
|||||||
{
|
{
|
||||||
#if defined(PM_SLEEPCFG_SLEEPMODE_STANDBY)
|
#if defined(PM_SLEEPCFG_SLEEPMODE_STANDBY)
|
||||||
(void) deep;
|
(void) deep;
|
||||||
|
unsigned mode = PM->SLEEPCFG.bit.SLEEPMODE;
|
||||||
|
|
||||||
if (PM->SLEEPCFG.bit.SLEEPMODE == PM_SLEEPCFG_SLEEPMODE_STANDBY) {
|
if (mode == PM_SLEEPCFG_SLEEPMODE_STANDBY) {
|
||||||
DEBUG_PUTS("gpio: switching EIC to slow clock");
|
DEBUG_PUTS("gpio: switching EIC to slow clock");
|
||||||
reenable_eic(_EIC_CLOCK_SLOW);
|
reenable_eic(_EIC_CLOCK_SLOW);
|
||||||
}
|
}
|
||||||
|
else if (IS_ACTIVE(MODULE_PERIPH_GPIO_TAMPER_WAKE)
|
||||||
|
&& mode > PM_SLEEPCFG_SLEEPMODE_STANDBY
|
||||||
|
&& _rtc_irq_enabled()) {
|
||||||
|
rtc_tamper_enable();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (deep) {
|
if (deep) {
|
||||||
DEBUG_PUTS("gpio: switching EIC to slow clock");
|
DEBUG_PUTS("gpio: switching EIC to slow clock");
|
||||||
|
|||||||
@ -12,6 +12,7 @@ config CPU_COMMON_SAMD5X
|
|||||||
select HAS_BACKUP_RAM
|
select HAS_BACKUP_RAM
|
||||||
select HAS_CORTEXM_MPU
|
select HAS_CORTEXM_MPU
|
||||||
select HAS_CPU_SAMD5X
|
select HAS_CPU_SAMD5X
|
||||||
|
select HAS_PERIPH_GPIO_TAMPER_WAKE
|
||||||
select HAS_PERIPH_HWRNG
|
select HAS_PERIPH_HWRNG
|
||||||
|
|
||||||
config CPU_FAM_SAMD51
|
config CPU_FAM_SAMD51
|
||||||
|
|||||||
@ -1 +1,5 @@
|
|||||||
|
ifneq (,$(filter periph_gpio_tamper_wake,$(USEMODULE)))
|
||||||
|
USEMODULE += periph_rtc_rtt
|
||||||
|
endif
|
||||||
|
|
||||||
include $(RIOTCPU)/sam0_common/Makefile.dep
|
include $(RIOTCPU)/sam0_common/Makefile.dep
|
||||||
|
|||||||
@ -3,5 +3,6 @@ CPU_CORE = cortex-m4f
|
|||||||
FEATURES_PROVIDED += periph_hwrng
|
FEATURES_PROVIDED += periph_hwrng
|
||||||
FEATURES_PROVIDED += backup_ram
|
FEATURES_PROVIDED += backup_ram
|
||||||
FEATURES_PROVIDED += cortexm_mpu
|
FEATURES_PROVIDED += cortexm_mpu
|
||||||
|
FEATURES_PROVIDED += periph_gpio_tamper_wake
|
||||||
|
|
||||||
include $(RIOTCPU)/sam0_common/Makefile.features
|
include $(RIOTCPU)/sam0_common/Makefile.features
|
||||||
|
|||||||
@ -116,6 +116,15 @@ typedef enum {
|
|||||||
#define RTT_MAX_FREQUENCY (RTT_CLOCK_FREQUENCY) /* in Hz */
|
#define RTT_MAX_FREQUENCY (RTT_CLOCK_FREQUENCY) /* in Hz */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RTC input pins that can be used for tamper detection and
|
||||||
|
* wake from Deep Sleep
|
||||||
|
*/
|
||||||
|
static const gpio_t rtc_tamper_pins[RTC_NUM_OF_TAMPERS] = {
|
||||||
|
GPIO_PIN(PB, 0), GPIO_PIN(PB, 2), GPIO_PIN(PA, 2),
|
||||||
|
GPIO_PIN(PC, 0), GPIO_PIN(PC, 1)
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -82,6 +82,15 @@ typedef enum {
|
|||||||
#define RTT_MAX_FREQUENCY (RTT_CLOCK_FREQUENCY) /* in Hz */
|
#define RTT_MAX_FREQUENCY (RTT_CLOCK_FREQUENCY) /* in Hz */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RTC input pins that can be used for tamper detection and
|
||||||
|
* wake from Deep Sleep
|
||||||
|
*/
|
||||||
|
static const gpio_t rtc_tamper_pins[RTC_NUM_OF_TAMPERS] = {
|
||||||
|
GPIO_PIN(PA, 8), GPIO_PIN(PA, 9), GPIO_PIN(PA, 16),
|
||||||
|
GPIO_PIN(PA, 17)
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#define USB_H_USER_IS_RIOT_INTERNAL
|
#define USB_H_USER_IS_RIOT_INTERNAL
|
||||||
|
|
||||||
|
#include "periph_cpu.h"
|
||||||
|
|
||||||
#ifdef MODULE_PERIPH_INIT
|
#ifdef MODULE_PERIPH_INIT
|
||||||
#ifdef MODULE_PERIPH_INIT_I2C
|
#ifdef MODULE_PERIPH_INIT_I2C
|
||||||
#include "periph/i2c.h"
|
#include "periph/i2c.h"
|
||||||
@ -73,6 +75,11 @@ void periph_init(void)
|
|||||||
rtc_init();
|
rtc_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Initialize Tamper Detection */
|
||||||
|
#ifdef MODULE_PERIPH_INIT_GPIO_TAMPER_WAKE
|
||||||
|
rtc_tamper_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE_PERIPH_INIT_HWRNG
|
#ifdef MODULE_PERIPH_INIT_HWRNG
|
||||||
hwrng_init();
|
hwrng_init();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -150,6 +150,12 @@ config HAS_PERIPH_GPIO_FAST_READ
|
|||||||
operations are faster, usually with a tradeoff against a different
|
operations are faster, usually with a tradeoff against a different
|
||||||
property.
|
property.
|
||||||
|
|
||||||
|
config HAS_PERIPH_GPIO_TAMPER_WAKE
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Indicates that Tamper Detection can be used to wake the CPU from
|
||||||
|
Deep Sleep.
|
||||||
|
|
||||||
config HAS_PERIPH_HWRNG
|
config HAS_PERIPH_HWRNG
|
||||||
bool
|
bool
|
||||||
help
|
help
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user