Contiki 3.x
power-modes.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Eistec AB.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * This file is part of the Mulle platform port of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Power mode switching functions for the K60 CPU.
36  *
37  * This file is based on sample code from Freescale.
38  *
39  * \author
40  * Joakim Gebart <joakim.gebart@eistec.se>
41  */
42 
43 #include "power-modes.h"
44 #include "config-board.h"
45 #include "K60.h"
46 
47 #if K60_CPU_REV == 1
48 #define PMCTRL MC->PMCTRL
49 #define SET_PMCTRL(x) (PMCTRL = MC_PMCTRL_LPLLSM(x) | MC_PMCTRL_LPWUI_MASK)
50 #elif K60_CPU_REV == 2
51 #define PMCTRL SMC->PMCTRL
52 #define SET_PMCTRL(x) (PMCTRL = SMC_PMCTRL_STOPM(x) | SMC_PMCTRL_LPWUI_MASK)
53 #else
54 #error Unknown K60 CPU revision!
55 #endif
56 
57 #define POWER_MODE_NORMAL (0b000)
58 #define POWER_MODE_VLPS (0b010)
59 #define POWER_MODE_LLS (0b011)
60 
61 void
63 {
64  /* Clear LLS protection */
65  /* Clear VLPS, VLPW, VLPR protection */
66  /* Note: This register can only be written once after each reset, so we must
67  * enable all power modes that we wish to use. */
68 #if K60_CPU_REV == 1
69  MC->PMPROT |= MC_PMPROT_ALLS_MASK | MC_PMPROT_AVLP_MASK;
70 #else /* K60_CPU_REV == 1 */
71  SMC->PMPROT |= SMC_PMPROT_ALLS_MASK | SMC_PMPROT_AVLP_MASK;
72 #endif /* K60_CPU_REV == 1 */
73 }
74 
75 static inline void
76 wait(void)
77 {
78  /* Clear the SLEEPDEEP bit to make sure we go into WAIT (sleep) mode instead
79  * of deep sleep.
80  */
81  SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
82 
83  /* WFI instruction will start entry into WAIT mode */
84  __WFI();
85 }
86 
87 static inline void
88 stop(void)
89 {
90  /* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */
91  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
92 
93  /* WFI instruction will start entry into STOP mode */
94  __WFI();
95 }
96 
97 void
98 power_mode_wait(void)
99 {
100  wait();
101 }
102 void
103 power_mode_stop(void)
104 {
105  uint8_t dummy;
106  SET_PMCTRL(POWER_MODE_NORMAL);
107  /* Wait for the write to complete before stopping core */
108  dummy = PMCTRL;
109  (void)dummy; /* Avoid warnings about set but not used variable [-Wunused-but-set-variable] */
110  stop();
111 }
112 void
113 power_mode_vlps(void)
114 {
115  uint8_t dummy;
116  SET_PMCTRL(POWER_MODE_VLPS);
117  /* Wait for the write to complete before stopping core */
118  dummy = PMCTRL;
119  (void)dummy; /* Avoid warnings about set but not used variable [-Wunused-but-set-variable] */
120  stop();
121 }
122 void
123 power_mode_lls(void)
124 {
125  uint8_t dummy;
126  SET_PMCTRL(POWER_MODE_LLS);
127  /* Wait for the write to complete before stopping core */
128  dummy = PMCTRL;
129  (void)dummy; /* Avoid warnings about set but not used variable [-Wunused-but-set-variable] */
130  stop();
131 }
#define SCB
Definition: core_cm0.h:494
#define SCB_SCR_SLEEPDEEP_Msk
Definition: core_cm0.h:403
#define MC
Peripheral MC base pointer.
Definition: MK60DZ10.h:5471
Board configuration defines for Mulle platform.
K60 hardware register header wrapper.
void power_modes_init(void)
Definition: power-modes.c:62
Power mode switching functions for the K60 CPU.
#define SMC
Peripheral SMC base pointer.
Definition: MK60D10.h:7723