LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
app_pmc_states.c
Go to the documentation of this file.
1 /*
2  * @brief Power Management Controller example
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
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 <stdlib.h>
33 #include <string.h>
34 #include "board.h"
35 #include "chip.h"
36 
76 /*****************************************************************************
77  * Private types/enumerations/variables
78  ****************************************************************************/
79 
80  #define RTC_ALARM_TIME 5
82 /* Structure for initial base clock states */
83 struct CLK_BASE_STATES {
84  CHIP_CGU_BASE_CLK_T clk; /* Base clock */
85  CHIP_CGU_CLKIN_T clkin; /* Base clock source, see UM for allowable souorces per base clock */
86  bool autoblock_enab;/* Set to true to enable autoblocking on frequency change */
87  bool powerdn; /* Set to true if the base clock is initially powered down */
88 };
89 
90 static char menu[] =
91  "\r\n==========================================================================\r\n"
92  "NXP Semiconductors LPC18xx/43xx MCU Power Management Controller example \r\n"
93  "=============================================================================\r\n"
94  "Select the power state test to be executed \r\n"
95  " - Sleep state & Wake up test : Press '1' to select \r\n"
96  " - Deep Sleep state & Wake up test : Press '2' to select \r\n"
97  " - Power down state & Wake up test : Press '3' to select \r\n"
98  " - Deep power down state & Wake up test : Press '4' to select \r\n"
99  " - Exit the demo : Press 'X' or 'x' to select \r\n"
100  "=============================================================================\r\n";
101 static char menu1[] = "\r\nSelect the Wake up signal \r\n"
102  " - WAKEUP0 pin : Press 'W' or 'w' to select \r\n"
103  " - RTC Alarm : Press 'R' or 'r' to select \r\n";
104 
105 static char menu2[] = "PMC demo example terimnated \r\n";
106 static char menu3[] = "\r\nPress 'C' or 'c' to start demo...\r\n";
107 
108 /* Initial base clock states are mostly on */
109 static struct CLK_BASE_STATES InitClkStates[] = {
110  {CLK_BASE_SAFE, CLKIN_IRC, true, false},
111  {CLK_BASE_APB1, CLKIN_MAINPLL, true, false},
112  {CLK_BASE_APB3, CLKIN_MAINPLL, true, false},
113  {CLK_BASE_USB0, CLKIN_USBPLL, true, true},
114 #if defined(CHIP_LPC43XX)
115  {CLK_BASE_PERIPH, CLKIN_MAINPLL, true, false},
116  {CLK_BASE_SPI, CLKIN_MAINPLL, true, false},
117  {CLK_BASE_VADC, CLKIN_MAINPLL, true, true},
118 #endif
119  {CLK_BASE_PHY_TX, CLKIN_ENET_TX, true, false},
120 #if defined(USE_RMII)
121  {CLK_BASE_PHY_RX, CLKIN_ENET_TX, true, false},
122 #else
123  {CLK_BASE_PHY_RX, CLKIN_ENET_RX, true, false},
124 #endif
125  {CLK_BASE_SDIO, CLKIN_MAINPLL, true, false},
126  {CLK_BASE_SSP0, CLKIN_MAINPLL, true, false},
127  {CLK_BASE_SSP1, CLKIN_MAINPLL, true, false},
128  {CLK_BASE_UART0, CLKIN_MAINPLL, true, false},
129  {CLK_BASE_UART1, CLKIN_MAINPLL, true, false},
130  {CLK_BASE_UART2, CLKIN_MAINPLL, true, false},
131  {CLK_BASE_UART3, CLKIN_MAINPLL, true, false},
132  // {CLK_BASE_OUT, CLKINPUT_PD, true, false},
133  // {CLK_BASE_APLL, CLKINPUT_PD, true, false},
134  // {CLK_BASE_CGU_OUT0, CLKINPUT_PD, true, false},
135  // {CLK_BASE_CGU_OUT1, CLKINPUT_PD, true, false},
136  {CLK_BASE_LCD, CLKIN_IDIVC, true, false},
137  {CLK_BASE_USB1, CLKIN_IDIVD, true, true},
138 };
139 
140 /*****************************************************************************
141  * Public types/enumerations/variables
142  ****************************************************************************/
143 
144 /*****************************************************************************
145  * Private functions
146  ****************************************************************************/
147 static void PMC_Get_Wakeup_option(uint8_t *Wakeup_rtc)
148 {
149  FlagStatus exitflag;
150  uint8_t buffer = 0xFF;
151 
152  DEBUGOUT(menu1);
153 
154  exitflag = RESET;
155  while (exitflag == RESET) {
156 
157  /* Get user input */
158  buffer = DEBUGIN();
159 
160  if ((buffer == 'W') || (buffer == 'w')) {
161  DEBUGOUT("WAKEUP0 pin selected \r\n");
162  *Wakeup_rtc = 0;
163  exitflag = SET;
164  }
165 
166  if ((buffer == 'R') || (buffer == 'r')) {
167  DEBUGOUT("RTC Alarm selected \r\n");
168  *Wakeup_rtc = 1;
169  exitflag = SET;
170  }
171  }
172 }
173 
178 static void PMC_Pre_SleepPowerDown(void)
179 {
180  int i;
181 
182 #ifndef BOARD_NGX_XPLORER_18304330
183  /* SDRAM in self refresh mode only for Keil & Hitex boards */
184  LPC_EMC->DYNAMICCONTROL |= (1 << 2);
185  while (!(LPC_EMC->STATUS & (1 << 2))) {}
186 #endif
187 
188  /* Shutdown perpheral clocks with wake up enabled */
190 
191  /* Get state of individual base clocks & store them for restoring.
192  * Sets up the IRC as base clock source
193  */
194  for (i = 0; i < (sizeof(InitClkStates) / sizeof(InitClkStates[0])); i++) {
195  /* Get the Base clock settings */
196  Chip_Clock_GetBaseClockOpts(InitClkStates[i].clk, &InitClkStates[i].clkin,
197  &InitClkStates[i].autoblock_enab, &InitClkStates[i].powerdn);
198 
199  /* Set IRC as clock input for all the base clocks */
200  Chip_Clock_SetBaseClock(InitClkStates[i].clk, CLKIN_IRC, InitClkStates[i].autoblock_enab,
201  InitClkStates[i].powerdn);
202  }
203 
204  /* Set IRC as clock source for SPIFI */
206 
207  /* Set IRC as source clock for Core */
209 
210 #ifdef BOARD_KEIL_MCB_18574357
211  /* Set Flash acceleration */
213 #endif
214 
215  /* Power down the main PLL */
219 }
220 
224 static void PMC_Post_Wakeup(uint8_t buffer)
225 {
226  int i;
227 
228 #ifdef BOARD_KEIL_MCB_18574357
229  /* Setup FLASH acceleration to target clock rate prior to clock switch */
231 #endif
232 
233  /* Reinitialise Clocks */
235 
236  /* Setup PLL for 100MHz and switch main system clocking */
237  Chip_Clock_SetupMainPLLHz(CLKIN_CRYSTAL, CRYSTAL_MAIN_FREQ_IN, 100 * 1000000, 100 * 1000000);
239 
240  /* Setup PLL for maximum clock */
242 
243  /* Restore the base clock states */
244  for (i = 0; i < (sizeof(InitClkStates) / sizeof(InitClkStates[0])); i++) {
245  Chip_Clock_SetBaseClock(InitClkStates[i].clk, InitClkStates[i].clkin,
246  InitClkStates[i].autoblock_enab, InitClkStates[i].powerdn);
247  }
248 
249  /* Reset and enable 32Khz oscillator */
250  LPC_CREG->CREG0 &= ~((1 << 3) | (1 << 2));
251  LPC_CREG->CREG0 |= (1 << 1) | (1 << 0);
252 
253  /* Setup a divider E for main PLL clock switch SPIFI clock to that divider.
254  Divide rate is based on CPU speed and speed of SPI FLASH part. */
255 #if (MAX_CLOCK_FREQ > 180000000)
257 #else
259 #endif
261 
262  /* Attach main PLL clock to divider C with a divider of 2 */
264 
265  /* Re-Initialize debug UART
266  * � 115200bps
267  * � 8 data bit
268  * � No parity
269  * � 1 stop bit
270  * � No flow control
271  */
272  DEBUGINIT();
273 
274 #ifndef BOARD_NGX_XPLORER_18304330
275  /* SDRAM in NORMAL mode, only for Keil & Hitex boards */
276  LPC_EMC->DYNAMICCONTROL &= ~(1 << 2);
277  while (LPC_EMC->STATUS & (1 << 2)) {}
278 #endif
279 }
280 
284 static void PMC_Evrt_Configure(CHIP_EVRT_SRC_T Evrt_Src)
285 {
286  /* Configure Interrupt signal from Evrt_Src pin to EVRT */
288 
289  /* Enable interrupt signal from Evrt_Src pin to EVRT */
290  Chip_EVRT_SetUpIntSrc(Evrt_Src, ENABLE);
291 
292  /* Clear any pending interrupt */
293  Chip_EVRT_ClrPendIntSrc(Evrt_Src);
294 
295  /* Disable EVRT interrupt in NVIC */
296  NVIC_DisableIRQ(EVENTROUTER_IRQn);
297 
298  /* preemption = 1, sub-priority = 1 */
299  NVIC_SetPriority(EVENTROUTER_IRQn, ((0x01 << 3) | 0x01));
300 
301  /* Enable Event Router interrupt in NVIC */
302  NVIC_EnableIRQ(EVENTROUTER_IRQn);
303 }
304 
308 static void PMC_PwrState_Handler(uint8_t buffer, uint8_t Wake_RTC)
309 {
310  CHIP_EVRT_SRC_T Evrt_Src;
311  CHIP_PMC_PWR_STATE_T Pwr_state;
312  uint8_t confirm = 0xFF;
313 
314  if (Wake_RTC) {
315  /* Configure EVRT_SRC_RTC as wake up signal */
316  Evrt_Src = EVRT_SRC_RTC;
317 
318  /* Disable interrupt signal from Evrt_Src pin to EVRT */
319  Chip_EVRT_SetUpIntSrc(Evrt_Src, DISABLE);
320 
321  /* Initialize and configure RTC */
325 
326  /* Set alarm time = RTC_ALARM_TIME seconds.
327  * So after each RTC_ALARM_TIME seconds, RTC will generate and wake-up system
328  */
331 
332  /* Set the AMR for RTC_ALARM_TIME match alarm interrupt */
335  }
336  else {
337  Evrt_Src = EVRT_SRC_WAKEUP0;
338  }
339 
340  /* Configure wake up signal */
341  PMC_Evrt_Configure(Evrt_Src);
342 
343  /* Get confirmation from user to continue
344  * Print wake up signal information to user
345  */
346  DEBUGOUT(menu3);
347  while ( (confirm != 'C') && (confirm != 'c')) {
348  confirm = DEBUGIN();
349  }
350 
351  switch (buffer) {
352  case '1':
353  DEBUGOUT("Entering 'Sleep' state ...\r\n");
354  if (Wake_RTC) {
355  DEBUGOUT("Wait for %d seconds, RTC alarm will wake up from 'Sleep' mode \r\n", RTC_ALARM_TIME);
357  }
358  else {
359  DEBUGOUT("Press WAKEUP0 button/Connect WAKEUP0 pin to 3.3V to exit 'Sleep' mode \r\n");
360  }
361  Chip_PMC_Sleep();
363  DEBUGOUT("Woken up \r\n");
364  break;
365 
366  case '2':
367  DEBUGOUT("Entering 'Deep Sleep' state ...\r\n");
368  if (Wake_RTC) {
369  DEBUGOUT("Wait for %d seconds, RTC alarm will wake up from 'Deep Sleep' mode \r\n", RTC_ALARM_TIME);
371  }
372  else {
373  DEBUGOUT("Press WAKEUP0 button/Connect WAKEUP0 pin to 3.3V to exit 'Deep Sleep' mode \r\n");
374  }
375  Pwr_state = PMC_DeepSleep;
376 
377  /* Call Pre SleepPowerDown function */
379 
380  /* Goto Deep Sleep mode */
381  Chip_PMC_Set_PwrState(Pwr_state);
382 
383  /* Call Post Wake up Initialisation function */
384  PMC_Post_Wakeup(buffer);
385  DEBUGOUT("\r\nWoken up \r\n");
386  break;
387 
388  case '3':
389  DEBUGOUT("Entering 'Power Down' state ...\r\n");
390  if (Wake_RTC) {
391  DEBUGOUT("Wait for %d seconds, RTC alarm will wake up from 'Power Down' mode \r\n", RTC_ALARM_TIME);
393  }
394  else {
395  DEBUGOUT("Press WAKEUP0 button/Connect WAKEUP0 pin to 3.3V to exit 'Power Down' mode \r\n");
396  }
397  Pwr_state = PMC_PowerDown;
398 
399  /* Call Pre SleepPowerDown function */
401 
402  /* Goto Deep Sleep mode */
403  Chip_PMC_Set_PwrState(Pwr_state);
404 
405  /* Call Post Wake up Initialisation function */
406  PMC_Post_Wakeup(buffer);
407 
408  DEBUGOUT("\r\nWoken up \r\n");
409  break;
410 
411  case '4':
412  DEBUGOUT("Entering 'Deep Power Down' state ...\r\n");
413  if (Wake_RTC) {
414  DEBUGOUT("Wait for %d seconds, RTC alarm will wake up from 'Deep Power Down' mode \r\n", RTC_ALARM_TIME);
416  }
417  else {
418  DEBUGOUT("Press WAKEUP0 button/Connect WAKEUP0 pin to 3.3V to exit 'Deep Power Down' mode \r\n");
419  }
420  Pwr_state = PMC_DeepPowerDown;
421 
422  /* Call Pre SleepPowerDown function */
424 
425  /* Goto Deep Sleep mode */
426  Chip_PMC_Set_PwrState(Pwr_state);
427 
428  /* Wake up from Deep power down state is as good as RESET */
429  while (1) {}
430  break;
431 
432  default:
433  break;
434  }
435 }
436 
437 /*****************************************************************************
438  * Public functions
439  ****************************************************************************/
440 
445 void EVRT_IRQHandler(void)
446 {
449  NVIC_DisableIRQ(EVENTROUTER_IRQn);
450  }
451 
457  NVIC_DisableIRQ(EVENTROUTER_IRQn);
458  }
459  }
460 }
461 
466 int main(void)
467 {
468  FlagStatus exitflag;
469  uint8_t buffer = 0xFF;
470  uint8_t Wake_RTC = 0;
471 
472  Board_Init();
473 
474  /* Initialize the Event Router */
475  Chip_EVRT_Init();
476 
477  /* Print user menu on UART console */
478  DEBUGOUT(menu);
479 
480  exitflag = RESET;
481  /* Read user option from UART prompt */
482  while (exitflag == RESET) {
483 
484  /* Get user input */
485  buffer = DEBUGIN();
486 
487  switch (buffer) {
488  case '1': /* Sleep/Wake up Mode */
489  DEBUGOUT("'Sleep' state test selected \r\n");
490  PMC_Get_Wakeup_option(&Wake_RTC);
491  PMC_PwrState_Handler(buffer, Wake_RTC);
492  DEBUGOUT(menu);
493  break;
494 
495  case '2': /* Deep sleep/Wakeup Mode */
496  DEBUGOUT("'Deep Sleep' state test selected \r\n");
497  PMC_Get_Wakeup_option(&Wake_RTC);
498  PMC_PwrState_Handler(buffer, Wake_RTC);
499  DEBUGOUT(menu);
500  break;
501 
502  case '3': /* Power Down/Wakeup Mode */
503  DEBUGOUT("'Power Down' state test selected \r\n");
504  PMC_Get_Wakeup_option(&Wake_RTC);
505  PMC_PwrState_Handler(buffer, Wake_RTC);
506  DEBUGOUT(menu);
507  break;
508 
509  case '4': /* Deep Power Down/Wakeup Mode */
510  DEBUGOUT("'Deep Power Down' state test selected \r\n");
511  PMC_Get_Wakeup_option(&Wake_RTC);
512  PMC_PwrState_Handler(buffer, Wake_RTC);
513  DEBUGOUT(menu);
514  break;
515 
516  case 'X':
517  DEBUGOUT(menu2);
518  exitflag = SET;
519  break;
520 
521  case 'x':
522  DEBUGOUT(menu2);
523  exitflag = SET;
524  break;
525  }
526  }
527 
528  while (1) {}
529 }
530