1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/sam0*: Switch EIC clock to slow speed on STANDBY mode

This commit is contained in:
Juergen Fitschen 2020-02-21 16:25:45 +01:00
parent 1265efc785
commit 43ff72ad56
2 changed files with 92 additions and 3 deletions

View File

@ -352,6 +352,20 @@ typedef struct {
*/
void gpio_init_mux(gpio_t pin, gpio_mux_t mux);
/**
* @brief Called before the power management enters a power mode
*
* @param[in] deep
*/
void gpio_pm_cb_enter(int deep);
/**
* @brief Called after the power management left a power mode
*
* @param[in] deep
*/
void gpio_pm_cb_leave(int deep);
/**
* @brief Wrapper for cortexm_sleep calling power management callbacks
*
@ -359,7 +373,15 @@ void gpio_init_mux(gpio_t pin, gpio_mux_t mux);
*/
static inline void sam0_cortexm_sleep(int deep)
{
#ifdef MODULE_PERIPH_GPIO
gpio_pm_cb_enter(deep);
#endif
cortexm_sleep(deep);
#ifdef MODULE_PERIPH_GPIO
gpio_pm_cb_leave(deep);
#endif
}
/**

View File

@ -56,6 +56,14 @@
#define _EIC EIC
#endif
/**
* @brief Clock source for the External Interrupt Controller
*/
typedef enum {
_EIC_CLOCK_FAST,
_EIC_CLOCK_SLOW
} gpio_eic_clock_t;
static gpio_isr_ctx_t gpio_config[NUMOF_IRQS];
#endif /* MODULE_PERIPH_GPIO_IRQ */
@ -155,6 +163,13 @@ void gpio_write(gpio_t pin, int value)
}
#ifdef MODULE_PERIPH_GPIO_IRQ
#ifdef CPU_FAM_SAMD21
#define EIC_SYNC() while (_EIC->STATUS.bit.SYNCBUSY)
#else
#define EIC_SYNC() while (_EIC->SYNCBUSY.bit.ENABLE)
#endif
static int _exti(gpio_t pin)
{
unsigned port_num = ((pin >> 7) & 0x03);
@ -196,7 +211,7 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(SAM0_GCLK_MAIN);
/* disable the EIC module*/
_EIC->CTRLA.reg = 0;
while (_EIC->SYNCBUSY.reg & EIC_SYNCBUSY_ENABLE) {}
EIC_SYNC();
#endif
/* configure the active flank */
_EIC->CONFIG[exti >> 3].reg &= ~(0xf << ((exti & 0x7) * 4));
@ -217,15 +232,55 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
_EIC->WAKEUP.reg |= (1 << exti);
/* enable the EIC module*/
_EIC->CTRL.reg = EIC_CTRL_ENABLE;
while (_EIC->STATUS.reg & EIC_STATUS_SYNCBUSY) {}
EIC_SYNC();
#else /* CPU_FAM_SAML21 */
/* enable the EIC module*/
_EIC->CTRLA.reg = EIC_CTRLA_ENABLE;
while (_EIC->SYNCBUSY.reg & EIC_SYNCBUSY_ENABLE) {}
EIC_SYNC();
#endif
return 0;
}
inline static void reenable_eic(gpio_eic_clock_t clock) {
#if !defined(CPU_SAMD21)
uint32_t ctrla_reg = EIC_CTRLA_ENABLE;
EIC->CTRLA.reg = 0;
EIC_SYNC();
if (clock == _EIC_CLOCK_SLOW) {
ctrla_reg |= EIC_CTRLA_CKSEL;
}
EIC->CTRLA.reg = ctrla_reg;
EIC_SYNC();
#endif
}
void gpio_pm_cb_enter(int deep)
{
#if defined(PM_SLEEPCFG_SLEEPMODE_STANDBY)
(void) deep;
if (PM->SLEEPCFG.bit.SLEEPMODE == PM_SLEEPCFG_SLEEPMODE_STANDBY) {
DEBUG_PUTS("gpio: switching EIC to slow clock");
reenable_eic(_EIC_CLOCK_SLOW);
}
#endif
}
void gpio_pm_cb_leave(int deep)
{
#if defined(PM_SLEEPCFG_SLEEPMODE_STANDBY)
(void) deep;
if (PM->SLEEPCFG.bit.SLEEPMODE == PM_SLEEPCFG_SLEEPMODE_STANDBY) {
DEBUG_PUTS("gpio: switching EIC to fast clock");
reenable_eic(_EIC_CLOCK_FAST);
}
#endif
}
void gpio_irq_enable(gpio_t pin)
{
int exti = _exti(pin);
@ -285,4 +340,16 @@ ISR_EICn(_other)
#endif /* CPU_SAML1X */
#endif /* CPU_SAML1X || CPU_SAMD5X */
#else /* MODULE_PERIPH_GPIO_IRQ */
void gpio_pm_cb_enter(int deep)
{
(void) deep;
}
void gpio_pm_cb_leave(int deep)
{
(void) deep;
}
#endif /* MODULE_PERIPH_GPIO_IRQ */