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 LPC_PWRD_API->power_mode_configure(PMU_SLEEP, (PMU_PD_WDOSC | PMU_PD_BOD | PMU_PD_ACMP0 | PMU_PD_ACMP1 | PMU_PD_ACMP2 |PMU_PD_ACMP3 | PMU_PD_IREF | PMU_PD_TS));
104 __WFI();
105
106 break;
107
108 case PMU_MCU_DEEP_SLEEP:
109 DEBUGSTR("-----------------------------------------------------------------\r\n");
110 DEBUGSTR(" Entering DEEP SLEEP power setting\r\n");
111 DEBUGOUT(" (System will exit DEEP SLEEP in %d seconds)\r\n", POWER_CYCLE_SEC_DELAY);
112 DEBUGSTR("-----------------------------------------------------------------\r\n\r\n");
113
114 /* Wait for all serial characters to be output */
115 DelayForSerialOutput();
116
117 /* We should call Chip_SYSCTL_SetWakeup() to setup any peripherals we want
118 to power back up on wakeup. For this example, we'll power back up the IRC,
119 FLASH, the system oscillator, and the PLL */
120 Chip_SYSCTL_SetWakeup(~(SYSCTL_SLPWAKE_IRCOUT_PD | SYSCTL_SLPWAKE_IRC_PD |
121 SYSCTL_SLPWAKE_FLASH_PD | SYSCTL_SLPWAKE_SYSOSC_PD | SYSCTL_SLPWAKE_SYSPLL_PD));
122 Chip_SYSCTL_EnableERP1PeriphWakeup(SYSCTL_ERP1_WAKEUP_RTCALARMINT);
123
124 /* Enter MCU Deep Sleep mode */
125 LPC_PWRD_API->power_mode_configure(PMU_DEEP_SLEEP, (PMU_PD_WDOSC | PMU_PD_BOD | PMU_PD_ACMP0 | PMU_PD_ACMP1 | PMU_PD_ACMP2 |PMU_PD_ACMP3 | PMU_PD_IREF | PMU_PD_TS));
126 __WFI();
127
128 break;
129
130 case PMU_MCU_POWER_DOWN:
131 DEBUGSTR("-----------------------------------------------------------------\r\n");
132 DEBUGSTR(" Entering POWER DOWN power setting\r\n");
133 DEBUGOUT(" (System will exit POWER DOWN in %d seconds)\r\n", POWER_CYCLE_SEC_DELAY);
134 DEBUGSTR("-----------------------------------------------------------------\r\n\r\n");
135
136 /* Wait for all serial characters to be output */
137 DelayForSerialOutput();
138
139 /* We should call Chip_SYSCTL_SetWakeup() to setup any peripherals we want
140 to power back up on wakeup. For this example, we'll power back up the IRC,
141 FLASH, the system oscillator, and the PLL */
142 Chip_SYSCTL_SetWakeup(~(SYSCTL_SLPWAKE_IRCOUT_PD | SYSCTL_SLPWAKE_IRC_PD |
143 SYSCTL_SLPWAKE_FLASH_PD | SYSCTL_SLPWAKE_SYSOSC_PD | SYSCTL_SLPWAKE_SYSPLL_PD));
144 Chip_SYSCTL_EnableERP1PeriphWakeup(SYSCTL_ERP1_WAKEUP_RTCALARMINT);
145
146 /* Enter MCU Power down mode */
147 LPC_PWRD_API->power_mode_configure(PMU_POWERDOWN, (PMU_PD_WDOSC | PMU_PD_BOD | PMU_PD_ACMP0 | PMU_PD_ACMP1 | PMU_PD_ACMP2 |PMU_PD_ACMP3 | PMU_PD_IREF | PMU_PD_TS));
148 __WFI();
149
150 break;
151
152 case PMU_MCU_DEEP_PWRDOWN:
153 DEBUGSTR("-----------------------------------------------------------------\r\n");
154 DEBUGSTR(" Entering DEEP POWER DOWN power setting\r\n");
155 DEBUGOUT(" (System will exit DEEP POWER DOWN in %d seconds)\r\n", POWER_CYCLE_SEC_DELAY);
156 DEBUGSTR("-----------------------------------------------------------------\r\n\r\n");
157
158 /* Wait for all serial characters to be output */
159 DelayForSerialOutput();
160 /* Enable wakeup from deep power down mode due to RTC Alarm Match */
161 Chip_RTC_EnableWakeup(LPC_RTC, RTC_CTRL_ALARMDPD_EN);
162 /* Enter MCU Deep Power down mode */
163 LPC_PWRD_API->power_mode_configure(PMU_DEEP_POWERDOWN, (PMU_PD_WDOSC | PMU_PD_BOD | PMU_PD_ACMP0 | PMU_PD_ACMP1 | PMU_PD_ACMP2 |PMU_PD_ACMP3 | PMU_PD_IREF | PMU_PD_TS));
164 __WFI();
165
166 break;
167 }
168 }
169
170 /*****************************************************************************
171 * Public functions
172 ****************************************************************************/
173
174 /**
175 * @brief RealTimeClock (RTC) Alarm Interrupt Handler
176 * @return None
177 */
RTC_ALARM_IRQHandler(void)178 void RTC_ALARM_IRQHandler(void)
179 {
180 uint32_t rtcStatus;
181
182 /* Get RTC status register */
183 rtcStatus = Chip_RTC_GetStatus(LPC_RTC);
184
185 /* Clear only latched RTC status */
186 Chip_RTC_EnableOptions(LPC_RTC,
187 (rtcStatus & (RTC_CTRL_WAKE1KHZ | RTC_CTRL_ALARM1HZ)));
188 }
189
190 /**
191 * @brief Main program body
192 * @return int
193 */
main(void)194 int main(void)
195 {
196 CHIP_PMU_MCUPOWER_T crntPowerSetting;
197
198 /* Setup SystemCoreClock and any needed board code */
199 SystemCoreClockUpdate();
200 Board_Init();
201 Board_LED_Set(0, true);
202
203 /* Clear any previously set deep power down and sleep flags */
204 Chip_PMU_ClearSleepFlags(LPC_PMU, PMU_PCON_SLEEPFLAG | PMU_PCON_DPDFLAG);
205 /* Enable the RTC oscillator, oscillator rate can be determined by
206 calling Chip_Clock_GetRTCOscRate() */
207 Chip_Clock_EnableRTCOsc();
208
209 /* Initialize RTC driver (enables RTC clocking) */
210 Chip_RTC_Init(LPC_RTC);
211
212 /* RTC reset */
213 Chip_RTC_Reset(LPC_RTC);
214
215 /* Start RTC at a count of 0 when RTC is disabled. If the RTC is enabled, you
216 need to disable it before setting the initial RTC count. */
217 Chip_RTC_Disable(LPC_RTC);
218 Chip_RTC_SetCount(LPC_RTC, 0);
219
220 /* Set a long alarm time so the interrupt won't trigger */
221 Chip_RTC_SetAlarm(LPC_RTC, 1000);
222
223 /* Enable RTC */
224 Chip_RTC_Enable(LPC_RTC);
225
226 /* Clear latched RTC interrupt statuses */
227 Chip_RTC_ClearStatus(LPC_RTC, (RTC_CTRL_OFD | RTC_CTRL_ALARM1HZ | RTC_CTRL_WAKE1KHZ));
228
229 /* Enable RTC interrupt */
230 NVIC_EnableIRQ(RTC_ALARM_IRQn);
231
232 /* Enable RTC alarm interrupt */
233 Chip_RTC_EnableWakeup(LPC_RTC, RTC_CTRL_ALARMDPD_EN);
234
235 /* Output example's activity banner */
236 DEBUGSTR("\r\n");
237 DEBUGSTR("-----------------------------------------------------------------\r\n");
238 #ifdef RESET_POWER_CYCLE_COUNT
239 ProcessCycleCounter();
240 DEBUGOUT("Power Control Example\r\n");
241 #else
242 DEBUGOUT("Power Control Example Cycle Count: %d\r\n", ProcessCycleCounter());
243 #endif
244 DEBUGSTR(" System will cycle through SLEEP, DEEP SLEEP, POWER\r\n");
245 DEBUGSTR(" DOWN, and DEEP POWER DOWN power states\r\n");
246 DEBUGSTR("-----------------------------------------------------------------\r\n\r\n");
247
248 /* Setup alarm, process next power state then wait for alarm to wake-up system */
249 crntPowerSetting = PMU_MCU_SLEEP;
250 while (1) {
251 /* Set alarm to wakeup in POWER_CYCLE_SEC_DELAY seconds */
252 Chip_RTC_SetAlarm(LPC_RTC, Chip_RTC_GetCount(LPC_RTC) + POWER_CYCLE_SEC_DELAY);
253
254 /* Enter first (or next) power state */
255 ProcessPowerState(crntPowerSetting);
256
257 /* Inc current power setting and test for overflow */
258 if (crntPowerSetting == PMU_MCU_DEEP_PWRDOWN) {
259 /* Reset to lowest power setting */
260 crntPowerSetting = PMU_MCU_SLEEP;
261 }
262 else {
263 crntPowerSetting++;
264 }
265 }
266
267 return 0;
268 }
269