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/samd21: implement low power modes #2309

Merged
merged 1 commit into from
Oct 17, 2016
Merged
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
103 changes: 88 additions & 15 deletions cpu/samd21/lpm_arch.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2015 Saurabh Singh
*
* 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
Expand All @@ -14,40 +15,112 @@
* @brief Implementation of the kernels power management interface
*
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Saurabh Singh <saurabh@cezy.co>
*
* @}
*/

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

enum system_sleepmode {
/**
* Idle 0 mode.
* Potential Wake Up sources: Synchronous(APB, AHB), asynchronous.
*/
SYSTEM_SLEEPMODE_IDLE_0,
/**
* Idle 1 mode.
* Potential Wake Up sources: Synchronous (APB), asynchronous
*/
SYSTEM_SLEEPMODE_IDLE_1,
/**
* Idle 2 mode.
* Potential Wake Up sources: Asynchronous
*/
SYSTEM_SLEEPMODE_IDLE_2,
/**
* Standby mode.
* Potential Wake Up sources: Asynchronous
*/
SYSTEM_SLEEPMODE_STANDBY,
};

static enum lpm_mode current_mode;

static void start_lpm(void);


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;

enum lpm_mode lpm_arch_get(void)
{
// TODO
return 0;
switch (target) {
case LPM_ON: /* Run mode */
current_mode = LPM_ON;
break;
case LPM_IDLE: /* Sleep mode Idle 0 */
current_mode = LPM_IDLE;
/* Idle Mode 0 */
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
PM->SLEEP.reg = SYSTEM_SLEEPMODE_IDLE_0;
start_lpm();
break;
case LPM_SLEEP: /* Sleep mode Idle 1 */
current_mode = LPM_SLEEP;
/* Idle Mode 1 */
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
PM->SLEEP.reg = SYSTEM_SLEEPMODE_IDLE_1;
start_lpm();
break;
case LPM_POWERDOWN: /* Sleep mode Idle 2 */
/* Idle Mode 2 */

Choose a reason for hiding this comment

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

My mistake sorry! Missing line

current_mode = LPM_POWERDOWN;

Copy link
Member Author

Choose a reason for hiding this comment

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

did

current_mode = LPM_POWERDOWN;
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
PM->SLEEP.reg = SYSTEM_SLEEPMODE_IDLE_2;
start_lpm();
break;
case LPM_OFF: /* Standby Mode - Potential Wake Up sources: Asynchronous */
current_mode = LPM_OFF;
/* Standby Mode */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
start_lpm();
break;
default:
break;
}

return last_mode;
}

void lpm_arch_awake(void)
static void start_lpm(void)
{
// TODO
/* Executes a device DSB (Data Synchronization Barrier) */
__DSB();
/* Enter standby mode */
__WFI();
}

void lpm_arch_begin_awake(void)
enum lpm_mode lpm_arch_get(void)
{
// TODO
return current_mode;
}

void lpm_arch_end_awake(void)
void lpm_arch_awake(void)
{
// TODO
if (current_mode == LPM_SLEEP) {

Choose a reason for hiding this comment

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

Not quite sure which modes will require a cpu_init(); need to test this!

/* Re-init */
cpu_init();
}
current_mode = LPM_ON;
}

/** Not needed */
void lpm_arch_begin_awake(void){ }

/** Not needed */
void lpm_arch_end_awake(void){ }