1 /*
2 * @brief PMU example
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2014
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #include "board.h"
33
34 /*****************************************************************************
35 * Private types/enumerations/variables
36 ****************************************************************************/
37
38 /* Change this value to increase/decrease the time between power state changes */
39 #define POWER_CYCLE_SEC_DELAY 10
40
41 /* Comment out this #define if you want a power-cycle count */
42 /* #define RESET_POWER_CYCLE_COUNT */
43
44 /* Index of PMU GP registers */
45 #define PWR_CYCLE_COUNT_REG_INDEX 0
46
47 /*****************************************************************************
48 * Public types/enumerations/variables
49 ****************************************************************************/
50
51 /*****************************************************************************
52 * Private functions
53 ****************************************************************************/
54
55 /* Read or reset the power-cycle counter */
ProcessCycleCounter(void)56 static uint32_t ProcessCycleCounter(void)
57 {
58 uint32_t returnVal = 0xFFFFFFFF;
59
60 #ifndef RESET_POWER_CYCLE_COUNT
61 /* Read current power-cycle count register */
62 returnVal = Chip_PMU_ReadGPREG(LPC_PMU, PWR_CYCLE_COUNT_REG_INDEX);
63 #endif
64
65 /* Write power-cycle count register */
66 Chip_PMU_WriteGPREG(LPC_PMU, PWR_CYCLE_COUNT_REG_INDEX, returnVal + 1);
67
68 /* Return current value of cycle-count */
69 return returnVal;
70 }
71
72 /* Delay to allow all serial output to be processed before power state change */
DelayForSerialOutput(void)73 static void DelayForSerialOutput(void)
74 {
75 volatile uint32_t tempTimeout;
76
77 /* Delay until all serial processing complete */
78 tempTimeout = Chip_RTC_GetCount(LPC_RTC) + 1;
79 while (Chip_RTC_GetCount(LPC_RTC) < tempTimeout) {}
80 }
81
82 /* Handle interrupt from GPIO pin or GPIO pin mapped to PININT */
ProcessPowerState(CHIP_PMU_MCUPOWER_T crntPowerSetting)83 static void ProcessPowerState(CHIP_PMU_MCUPOWER_T crntPowerSetting)
84 {
85 volatile uint32_t tempTimeout;
86
87 /* Output power status message, add separating space */
88 DEBUGSTR("\r\n");
89
90 /* Switch on current selected power setting */
91 switch (crntPowerSetting) {
92 case PMU_MCU_SLEEP:
93 default:
94 DEBUGSTR("-----------------------------------------------------------------\r\n");
95 DEBUGSTR(" Entering SLEEP power setting\r\n");
96 DEBUGOUT(" (System will exit SLEEP in %d seconds)\r\n", POWER_CYCLE_SEC_DELAY);
97 DEBUGSTR("-----------------------------------------------------------------\r\n\r\n");
98
99 /* Wait for all serial characters to be output */
100 DelayForSerialOutput();
101
102 /* Enter MCU Sleep mode */
103 Chip_PMU_SleepState(LPC_PMU);
104
105 break;
106
107 case PMU_MCU_DEEP_SLEEP:
108 DEBUGSTR("-----------------------------------------------------------------\r\n");
109 DEBUGSTR(" Entering DEEP SLEEP power setting\r\n");
110 DEBUGOUT(" (System will exit DEEP SLEEP in %d seconds)\r\n", POWER_CYCLE_SEC_DELAY);
111 DEBUGSTR("-----------------------------------------------------------------\r\n\r\n");
112
113 /* Wait for all serial characters to be output */
114 DelayForSerialOutput();
115
116 /* We should call Chip_SYSCTL_SetWakeup() to setup any peripherals we want
117 to power back up on wakeup. For this example, we'll power back up the IRC,
118 FLASH, the system oscillator, and the PLL */
119 Chip_SYSCTL_SetWakeup(~(SYSCTL_SLPWAKE_IRCOUT_PD | SYSCTL_SLPWAKE_IRC_PD |
120 SYSCTL_SLPWAKE_FLASH_PD | SYSCTL_SLPWAKE_SYSOSC_PD | SYSCTL_SLPWAKE_SYSPLL_PD));
121 Chip_SYSCTL_EnableERP1PeriphWakeup(SYSCTL_ERP1_WAKEUP_RTCALARMINT);
122
123 /* Enter MCU Deep Sleep mode */
124 Chip_PMU_DeepSleepState(LPC_PMU);
125
126 break;
127
128 case PMU_MCU_POWER_DOWN:
129 DEBUGSTR("-----------------------------------------------------------------\r\n");
130 DEBUGSTR(" Entering POWER DOWN power setting\r\n");
131 DEBUGOUT(" (System will exit POWER DOWN in %d seconds)\r\n", POWER_CYCLE_SEC_DELAY);
132 DEBUGSTR("-----------------------------------------------------------------\r\n\r\n");
133
134 /* Wait for all serial characters to be output */
135 DelayForSerialOutput();
136
137 /* We should call Chip_SYSCTL_SetWakeup() to setup any peripherals we want
138 to power back up on wakeup. For this example, we'll power back up the IRC,
139 FLASH, the system oscillator, and the PLL */
140 Chip_SYSCTL_SetWakeup(~(SYSCTL_SLPWAKE_IRCOUT_PD | SYSCTL_SLPWAKE_IRC_PD |
141 SYSCTL_SLPWAKE_FLASH_PD | SYSCTL_SLPWAKE_SYSOSC_PD | SYSCTL_SLPWAKE_SYSPLL_PD));
142 Chip_SYSCTL_EnableERP1PeriphWakeup(SYSCTL_ERP1_WAKEUP_RTCALARMINT);
143
144 /* Enter MCU Power down mode */
145 Chip_PMU_PowerDownState(LPC_PMU);
146
147 break;
148
149 case PMU_MCU_DEEP_PWRDOWN:
150 DEBUGSTR("-----------------------------------------------------------------\r\n");
151 DEBUGSTR(" Entering DEEP POWER DOWN power setting\r\n");
152 DEBUGOUT(" (System will exit DEEP POWER DOWN in %d seconds)\r\n", POWER_CYCLE_SEC_DELAY);
153 DEBUGSTR("-----------------------------------------------------------------\r\n\r\n");
154
155 /* Wait for all serial characters to be output */
156 DelayForSerialOutput();
157 /* Enable wakeup from deep power down mode due to RTC Alarm Match */
158 Chip_RTC_EnableWakeup(LPC_RTC, RTC_CTRL_ALARMDPD_EN);
159 /* Enter MCU Deep Power down mode */
160 Chip_PMU_DeepPowerDownState(LPC_PMU);
161
162 break;
163 }
164 }
165
166 /*****************************************************************************
167 * Public functions
168 ****************************************************************************/
169
170 /**
171 * @brief RealTimeClock (RTC) Alarm Interrupt Handler
172 * @return None
173 */
RTC_ALARM_IRQHandler(void)174 void RTC_ALARM_IRQHandler(void)
175 {
176 uint32_t rtcStatus;
177
178 /* Get RTC status register */
179 rtcStatus = Chip_RTC_GetStatus(LPC_RTC);
180
181 /* Clear only latched RTC status */
182 Chip_RTC_EnableOptions(LPC_RTC,
183 (rtcStatus & (RTC_CTRL_WAKE1KHZ | RTC_CTRL_ALARM1HZ)));
184 }
185
186 /**
187 * @brief Main program body
188 * @return int
189 */
main(void)190 int main(void)
191 {
192 CHIP_PMU_MCUPOWER_T crntPowerSetting;
193
194 /* Setup SystemCoreClock and any needed board code */
195 SystemCoreClockUpdate();
196 Board_Init();
197 Board_LED_Set(0, true);
198
199 /* Clear any previously set deep power down and sleep flags */
200 Chip_PMU_ClearSleepFlags(LPC_PMU, PMU_PCON_SLEEPFLAG | PMU_PCON_DPDFLAG);
201 /* Enable the RTC oscillator, oscillator rate can be determined by
202 calling Chip_Clock_GetRTCOscRate() */
203 Chip_Clock_EnableRTCOsc();
204
205 /* Initialize RTC driver (enables RTC clocking) */
206 Chip_RTC_Init(LPC_RTC);
207
208 /* RTC reset */
209 Chip_RTC_Reset(LPC_RTC);
210
211 /* Start RTC at a count of 0 when RTC is disabled. If the RTC is enabled, you
212 need to disable it before setting the initial RTC count. */
213 Chip_RTC_Disable(LPC_RTC);
214 Chip_RTC_SetCount(LPC_RTC, 0);
215
216 /* Set a long alarm time so the interrupt won't trigger */
217 Chip_RTC_SetAlarm(LPC_RTC, 1000);
218
219 /* Enable RTC */
220 Chip_RTC_Enable(LPC_RTC);
221
222 /* Clear latched RTC interrupt statuses */
223 Chip_RTC_ClearStatus(LPC_RTC, (RTC_CTRL_OFD | RTC_CTRL_ALARM1HZ | RTC_CTRL_WAKE1KHZ));
224
225 /* Enable RTC interrupt */
226 NVIC_EnableIRQ(RTC_ALARM_IRQn);
227
228 /* Enable RTC alarm interrupt */
229 Chip_RTC_EnableWakeup(LPC_RTC, RTC_CTRL_ALARMDPD_EN);
230
231 /* Output example's activity banner */
232 DEBUGSTR("\r\n");
233 DEBUGSTR("-----------------------------------------------------------------\r\n");
234 #ifdef RESET_POWER_CYCLE_COUNT
235 ProcessCycleCounter();
236 DEBUGOUT("Power Control Example\r\n");
237 #else
238 DEBUGOUT("Power Control Example Cycle Count: %d\r\n", ProcessCycleCounter());
239 #endif
240 DEBUGSTR(" System will cycle through SLEEP, DEEP SLEEP, POWER\r\n");
241 DEBUGSTR(" DOWN, and DEEP POWER DOWN power states\r\n");
242 DEBUGSTR("-----------------------------------------------------------------\r\n\r\n");
243
244 /* Setup alarm, process next power state then wait for alarm to wake-up system */
245 crntPowerSetting = PMU_MCU_SLEEP;
246 while (1) {
247 /* Set alarm to wakeup in POWER_CYCLE_SEC_DELAY seconds */
248 Chip_RTC_SetAlarm(LPC_RTC, Chip_RTC_GetCount(LPC_RTC) + POWER_CYCLE_SEC_DELAY);
249
250 /* Enter first (or next) power state */
251 ProcessPowerState(crntPowerSetting);
252
253 /* Inc current power setting and test for overflow */
254 if (crntPowerSetting == PMU_MCU_DEEP_PWRDOWN) {
255 /* Reset to lowest power setting */
256 crntPowerSetting = PMU_MCU_SLEEP;
257 }
258 else {
259 crntPowerSetting++;
260 }
261 }
262
263 return 0;
264 }
265