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

cpu/stm32f4: Add LPM implementation #2246

Merged
merged 1 commit into from Feb 11, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
77 changes: 61 additions & 16 deletions cpu/stm32f4/lpm_arch.c
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2015 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
Expand All @@ -13,41 +13,86 @@
* @file
* @brief Implementation of the kernels power management interface
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Fabian Nack <nack@inf.fu-berlin.de>
*
* @}
*/

#include "cpu.h"
#include "arch/lpm_arch.h"

static enum lpm_mode current_mode = LPM_UNKNOWN;

void lpm_arch_init(void)
{
/* TODO */
current_mode = LPM_ON;
}

enum lpm_mode lpm_arch_set(enum lpm_mode target)
{
/* TODO */
return 0;
enum lpm_mode last_mode = current_mode;

switch (target) {
case LPM_ON: /* STM Run mode */
current_mode = LPM_ON;
break;
case LPM_IDLE: /* STM Sleep mode */
current_mode = LPM_IDLE;
/* Reset SLEEPDEEP bit of system control block */
SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
/* Enter sleep mode */
__WFI();
break;
case LPM_SLEEP: /* STM Stop mode */
current_mode = LPM_SLEEP;
/* Clear PDDS and LPDS bits to enter stop mode on */
/* deepsleep with voltage regulator on */
PWR->CR &= ~(PWR_CR_PDDS | PWR_CR_LPDS);
/* Set SLEEPDEEP bit of system control block */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
/* Enter stop mode */
__WFI();
break;
case LPM_POWERDOWN: /* STM Standby mode */
/* Fall-through */
case LPM_OFF: /* STM Standby mode */
current_mode = LPM_POWERDOWN;
/* Set PDDS to enter standby mode on deepsleep and clear flags */
PWR->CR |= (PWR_CR_PDDS | PWR_CR_CWUF | PWR_CR_CSBF);
/* Enable WKUP pin to use for wakeup from standby mode */
PWR->CSR |= PWR_CSR_EWUP;
/* Set SLEEPDEEP bit of system control block */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
#if defined ( __CC_ARM )
/* Ensure that store operations are completed */
__force_stores();
#endif
/* Enter standby mode */
__WFI();
break;
default:
break;
}

return last_mode;
}

enum lpm_mode lpm_arch_get(void)
{
/* TODO */
return 0;
return current_mode;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is current_mode initialized with a value before any other function is called? Otherwise would it make sense to do so with LPM_UNKNOWN ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're probably right. Grepping through RIOT's code, lpm_init (which is defined as lpm_arch_init) is currently not called initially. I'll initialize it with LPM_UNKNOWN.

}

void lpm_arch_awake(void)
{
/* TODO */
if (current_mode == LPM_SLEEP) {
/* After stop mode, the clock system needs to be reconfigured */
cpu_init();
}
current_mode = LPM_ON;
}

void lpm_arch_begin_awake(void)
{
/* TODO */
}
/** Not provided */
inline void lpm_arch_begin_awake(void) { }

void lpm_arch_end_awake(void)
{
/* TODO */
}
/** Not provided */
inline void lpm_arch_end_awake(void) { }