Use of a Virtual Timer to set MCU asleep
Posted: Thu Jan 30, 2014 12:03 pm
Hey everyone,
I want to lay my STM32F031 asleep (stop mode) after a period of time where nothing happens. So I used a virtual timer for this task, which works quite well (timer and setting asleep). But I can't wake up from EXTI source anymore (active high button at PA=). My assumtption is, that this is due to the callback of the timer where the EXTI channel should be enabled, but doesn't. I get the wake up done, when I call the callback directly (without invloving a VT) and just wait some time using chThdSleepSeconds(2); prior to calling the callback.
So I use the following code:
Thanks for the quick help. I appreceate it.
Stefan
I want to lay my STM32F031 asleep (stop mode) after a period of time where nothing happens. So I used a virtual timer for this task, which works quite well (timer and setting asleep). But I can't wake up from EXTI source anymore (active high button at PA=). My assumtption is, that this is due to the callback of the timer where the EXTI channel should be enabled, but doesn't. I get the wake up done, when I call the callback directly (without invloving a VT) and just wait some time using chThdSleepSeconds(2); prior to calling the callback.
So I use the following code:
Code: Select all
VirtualTimer vtGoToSleep;
void goToSleep(){
chSysLockFromIsr();
// Enable wake up interrupt.
extChannelEnableI(&EXTD1, 0);
// Look deep into my eyes, you are tired now ...
PWR->CR |= (PWR_CR_LPSDSR | PWR_CR_CSBF | PWR_CR_CWUF); // stop mode
PWR->CR &= ~PWR_CR_PDDS;
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__WFI();
chSysUnlockFromIsr();
}
static void wakeUpIRQ(EXTDriver *extp, expchannel_t channel) {
(void)extp;
(void)channel;
chSysLockFromIsr();
// We must reinit clocks after waking up ESPECIALLY if use HSE or HSI+PLL.
stm32_clock_init();
// Since we are awake now, no need to let the wakeUp interrupt be enabled.
extChannelDisableI(&EXTD1, 0);
chSysUnlockFromIsr();
}
static const EXTConfig extcfg = {
{
/* Pin 0 */ {EXT_CH_MODE_RISING_EDGE | EXT_MODE_GPIOA, wakeUpIRQ},
/* Pin 1 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 2 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 3 */ {EXT_CH_MODE_FALLING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOA, buttonIRQ},
/* Pin 4 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 5 */ {EXT_CH_MODE_FALLING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOA, buttonIRQ},
/* Pin 6 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 7 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 8 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 9 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 10 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 11 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 12 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 13 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 14 */ {EXT_CH_MODE_DISABLED, NULL},
/* Pin 15 */ {EXT_CH_MODE_DISABLED, NULL}
}
};
int main(int argc, char **argv) {
chVTSet(&vtGoToSleep, S2ST(2), goToSleep, NULL);
while(TRUE){
chThdSleepMilliseconds(1000);
palTogglePad(LED_PORT, LED_PIN)
}
}
Thanks for the quick help. I appreceate it.
Stefan