I am using the low power function of RT595_EVK to try UTICK timing wake up after the MCU goes into DeepSleep mode.The current phenomenon is that UTICK can wake up the MCU from Sleep mode, but not from DeepSleep mode.
The example I used is power_manager of SDK_2.10.0. This example uses the Key(SW2) to wake up, and everything works fine. Based on this example, I added the UTICK part of the code, and then the above phenomenon occurs (UTICK can wake up the MCU from Sleep mode, but not from DeepSleep mode, UTICK does not enter interrupt handel functions when the MCU is in DeepSleep mode ).
The specific code is as follows, could you please help to see if there is any other configuration needed? Deep gratitude!
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_common.h"
#include "fsl_power.h"
#include "fsl_inputmux.h"
#include "fsl_pint.h"
#include "fsl_usart.h"
#include "fsl_utick.h" //增加,20210915
#include "pmic_support.h"
#include "fsl_pca9420.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*
* The option is used for measurement of the deep sleep wake-up latency. When the application calls
* POWER_EnterDeepSleep(), the power library will control the PLL power depending on the
* exclude_from_pd parameter and the PLL running status. If the PLL is not in the exclude_from_pd list
* and is running, it will be powered off before WFI and restored after WFI by the power library. Otherwise,
* the PLL control will not be changed in POWER_EnterDeepSleep().
* As the PLL initialization costs time to stabilize the clock, user will see the duration of
* POWER_EnterDeepSleep() is longer than expectation.
* To get rid of the PLL clock initialization time from deep sleep wake-up latency measurement, we can set
* POWER_DOWN_PLL_BEFORE_DEEP_SLEEP to 1, then the demo itself will disable the PLL before
* calling POWER_EnterDeepSleep(), and restore PLL after that. Thus we get the real duration of system
* deep sleep wake-up time.
*/
#define POWER_DOWN_PLL_BEFORE_DEEP_SLEEP \
0 /* By default, we keep the application as simple as possible to make good OOBE. */
#define APP_USART_RX_ERROR kUSART_RxError
#define APP_USER_WAKEUP_KEY_NAME "SW2"
#define APP_USER_WAKEUP_KEY_GPIO GPIO
#define APP_USER_WAKEUP_KEY_PORT 0
#define APP_USER_WAKEUP_KEY_PIN 10
#define APP_USER_WAKEUP_KEY_INPUTMUX_SEL kINPUTMUX_GpioPort0Pin10ToPintsel
/*!< Power down all unnecessary blocks and enable RBB during deep sleep. */
#define APP_DEEPSLEEP_RUNCFG0 (SYSCTL0_PDRUNCFG0_RBBSRAM_PD_MASK | SYSCTL0_PDRUNCFG0_RBB_PD_MASK)
#define APP_DEEPSLEEP_RAM_APD 0x00FFF000U /* 0x80000 - 0x2FFFFF keep powered */
#define APP_DEEPSLEEP_RAM_PPD 0x0U
#define APP_EXCLUDE_FROM_DEEPSLEEP \
(((const uint32_t[]){APP_DEEPSLEEP_RUNCFG0, \
(SYSCTL0_PDSLEEPCFG1_FLEXSPI0_SRAM_APD_MASK | SYSCTL0_PDSLEEPCFG1_SRAM_SLEEP_MASK), \
APP_DEEPSLEEP_RAM_APD, APP_DEEPSLEEP_RAM_PPD}))
#define APP_EXCLUDE_FROM_DEEP_POWERDOWN (((const uint32_t[]){0, 0, 0, 0}))
#define APP_EXCLUDE_FROM_FULL_DEEP_POWERDOWN (((const uint32_t[]){0, 0, 0, 0}))
const char *gWakeupInfoStr[] = {"Sleep [Press the user key to wakeup]", "Deep Sleep [Press the user key to wakeup]",
#if (defined(FSL_FEATURE_SYSCON_HAS_POWERDOWN_MODE) && FSL_FEATURE_SYSCON_HAS_POWERDOWN_MODE)
"Powerdown [Reset to wakeup]", "Deep Powerdown [Reset to wakeup]"};
#else
"Deep Powerdown [Reset to wakeup]", "Full Deep Powerdown [Reset to wakeup]"};
#endif
uint32_t gCurrentPowerMode;
volatile bool pintFlag = false;
static volatile bool utickExpired; //增加,20210915
/*******************************************************************************
* Prototypes
******************************************************************************/
void BOARD_ConfigPMICModes(pca9420_modecfg_t *cfg, uint32_t num);
#if POWER_DOWN_PLL_BEFORE_DEEP_SLEEP
void BOARD_DisablePll();
void BOARD_RestorePll();
#endif
static uint32_t APP_GetUserSelection(void);
static void APP_InitWakeupPin(void);
static void pint_intr_callback(pint_pin_int_t pintr, uint32_t pmatch_status);
static void APP_InitWakeupUTick(void); //增加,20210915
static void UTickCallback(void); //增加,20210915
static void UTickSet(uint32_t usec); //增加,20210915
/*******************************************************************************
* Code
******************************************************************************/
/*PLL status*/
extern const clock_sys_pll_config_t g_sysPllConfig_BOARD_BootClockRUN;
extern const clock_audio_pll_config_t g_audioPllConfig_BOARD_BootClockRUN;
AT_QUICKACCESS_SECTION_CODE(void BOARD_SetFlexspiClock(FLEXSPI_Type *base, uint32_t src, uint32_t divider));
void BOARD_ConfigPMICModes(pca9420_modecfg_t *cfg, uint32_t num)
{
assert(cfg);
/* Configuration PMIC mode to align with power lib like below:
* 0b00 run mode, no special.
* 0b01 deep sleep mode, vddcore 0.6V.
* 0b10 deep powerdown mode, vddcore off.
* 0b11 full deep powerdown mode vdd1v8 and vddcore off. */
/* Mode 1: VDDCORE 0.6V. */
cfg[1].sw1OutVolt = kPCA9420_Sw1OutVolt0V600;
/* Mode 2: VDDCORE off. */
cfg[2].enableSw1Out = false;
/* Mode 3: VDDCORE, VDD1V8 and VDDIO off. */
cfg[3].enableSw1Out = false;
cfg[3].enableSw2Out = false;
cfg[3].enableLdo2Out = false;
}
#if POWER_DOWN_PLL_BEFORE_DEEP_SLEEP
void BOARD_DisablePll(void)
{
/* Let FlexSPI run on FRO. */
BOARD_SetFlexspiClock(FLEXSPI0, 3U, 2U);
/* Let CPU run on FRO div 2 (96MHz) before power down SYS PLL. */
CLOCK_AttachClk(kFRO_DIV1_to_MAIN_CLK);
/* Disable the PFD clock output first. */
CLOCK_DeinitSysPfd(kCLOCK_Pfd0);
CLOCK_DeinitSysPfd(kCLOCK_Pfd2);
CLOCK_DeinitAudioPfd(kCLOCK_Pfd0);
/* Disable PLL. */
CLOCK_DeinitSysPll();
CLOCK_DeinitAudioPll();
/* Power down SysOsc */
POWER_EnablePD(kPDRUNCFG_PD_SYSXTAL);
}
void BOARD_RestorePll(void)
{
/* Power on SysOsc */
POWER_DisablePD(kPDRUNCFG_PD_SYSXTAL);
CLOCK_EnableSysOscClk(true, true, BOARD_SYSOSC_SETTLING_US);
/*Restore PLL*/
CLOCK_InitSysPll(&g_sysPllConfig_BOARD_BootClockRUN);
CLOCK_InitAudioPll(&g_audioPllConfig_BOARD_BootClockRUN);
/*Restore PFD*/
CLOCK_InitSysPfd(kCLOCK_Pfd0, 24); /* Enable main PLL clock 396MHz. */
CLOCK_InitSysPfd(kCLOCK_Pfd2, 24); /* Enable aux0 PLL clock 396MHz for SDIO */
CLOCK_InitAudioPfd(kCLOCK_Pfd0, 26); /* Configure audio_pll_clk to 368.64MHz */
/* Let CPU run on SYS PLL PFD0 with divider 2 (250Mhz). */
CLOCK_AttachClk(kMAIN_PLL_to_MAIN_CLK);
/* Move FlexSPI clock source from FRO clock to Main clock. */
BOARD_SetFlexspiClock(FLEXSPI0, 0U, 2U);
}
#endif /* POWER_DOWN_PLL_BEFORE_DEEP_SLEEP */
/*!
* @brief Main function
*/
int main(void)
{
/* Define the init structure for the output LED pin*/
gpio_pin_config_t led_config = { //增加,20210915
kGPIO_DigitalOutput,
0,
};
/* Init board hardware. */
pca9420_modecfg_t pca9420ModeCfg[4];
uint32_t i;
/* BE CAUTIOUS TO SET CORRECT VOLTAGE RANGE ACCORDING TO YOUR BOARD/APPLICATION. PAD SUPPLY BEYOND THE RANGE DO
HARM TO THE SILICON. */
power_pad_vrange_t vrange = {.Vdde0Range = kPadVol_171_198,
.Vdde1Range = kPadVol_171_198,
.Vdde2Range = kPadVol_171_198,
.Vdde3Range = kPadVol_300_360,
.Vdde4Range = kPadVol_171_198};
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
//----------------------------------- LED -----------------------------------
GPIO_PortInit(GPIO, 3U);
GPIO_PinInit(GPIO, 3U, 17U, &led_config); //增加,20210915
GPIO_PinWrite(GPIO, 3U, 17U, 1);
/* PMIC PCA9420 */
BOARD_InitPmic();
for (i = 0; i < ARRAY_SIZE(pca9420ModeCfg); i++)
{
PCA9420_GetDefaultModeConfig(&pca9420ModeCfg[i]);
}
BOARD_ConfigPMICModes(pca9420ModeCfg, ARRAY_SIZE(pca9420ModeCfg));
PCA9420_WriteModeConfigs(&pca9420Handle, kPCA9420_Mode0, &pca9420ModeCfg[0], ARRAY_SIZE(pca9420ModeCfg));
/* Configure PMIC Vddcore value according to CM33 clock. DSP not used in this demo. */
BOARD_SetPmicVoltageForFreq(CLOCK_GetFreq(kCLOCK_CoreSysClk), 0U);
/* Indicate to power library that PMIC is used. */
POWER_UpdatePmicRecoveryTime(1);
POWER_SetPadVolRange(&vrange);
/* Determine the power mode before bring up. */
if ((POWER_GetEventFlags() & PMC_FLAGS_DEEPPDF_MASK) != 0)
{
PRINTF("Board wake up from deep or full deep power down mode.\r\n");
POWER_ClearEventFlags(PMC_FLAGS_DEEPPDF_MASK);
}
APP_InitWakeupPin();
//----------------------------------- UTick -----------------------------------
APP_InitWakeupUTick(); //增加,20210915
PRINTF("Power Manager Demo.\r\n");
PRINTF("The \"user key\" is: %s\r\n\r\n", APP_USER_WAKEUP_KEY_NAME);
gCurrentPowerMode = APP_GetUserSelection(); //测试
PRINTF("Entering %s ...\r\n", gWakeupInfoStr[gCurrentPowerMode]);
while (1)
{
// gCurrentPowerMode = APP_GetUserSelection(); //测试 //屏蔽,20210915
// PRINTF("Entering %s ...\r\n", gWakeupInfoStr[gCurrentPowerMode]);
// pintFlag = false;
/* Enter the low power mode. */
switch (gCurrentPowerMode)
{
case kPmu_Sleep: /* Enter sleep mode. */
{
PRINTF("Entering Sleep...\r\n");
PRINTF("UTick = 2000ms.\r\n");
UTickSet(2000000); //2000ms //增加,20210915
POWER_EnterSleep();
break;
}
case kPmu_Deep_Sleep: /* Enter deep sleep mode. */
{
PRINTF("Entering Deep Sleep...\r\n");
PRINTF("UTick = 2000ms.\r\n");
UTickSet(2000000); //2000ms //增加,20210915
BOARD_SetPmicVoltageBeforeDeepSleep();
#if POWER_DOWN_PLL_BEFORE_DEEP_SLEEP
/* Disable Pll before enter deep sleep mode */
BOARD_DisablePll();
#endif
POWER_EnterDeepSleep(APP_EXCLUDE_FROM_DEEPSLEEP);
#if POWER_DOWN_PLL_BEFORE_DEEP_SLEEP
/* Restore Pll before enter deep sleep mode */
BOARD_RestorePll();
#endif
BOARD_RestorePmicVoltageAfterDeepSleep();
break;
}
case kPmu_Deep_PowerDown: /* Enter deep power down mode. */
{
PRINTF(
"Press any key to confirm to enter the deep power down mode and wakeup the device by "
"reset.\r\n\r\n");
GETCHAR();
BOARD_SetPmicVoltageBeforeDeepPowerDown();
POWER_EnterDeepPowerDown(APP_EXCLUDE_FROM_DEEP_POWERDOWN);
/* After deep power down wakeup, the code will restart and cannot reach here. */
break;
}
case kPmu_Full_Deep_PowerDown: /* Enter full deep power down mode. */
{
PRINTF(
"Press any key to confirm to enter the full deep power down mode and wakeup the device by "
"reset.\r\n\r\n");
GETCHAR();
BOARD_SetPmicVoltageBeforeDeepPowerDown();
POWER_EnterFullDeepPowerDown(APP_EXCLUDE_FROM_FULL_DEEP_POWERDOWN);
/* After full deep power down wakeup, the code will restart and cannot reach here. */
break;
}
default:
break;
}
if (pintFlag)
{
PRINTF("Pin event occurs\r\n");
pintFlag = false; //增加,20210915
PRINTF("UTick = 0.\r\n"); //增加,20210915
UTickSet(0); //0ms
PRINTF("Wakeup.\r\n");
gCurrentPowerMode = 4; //测试 //增加,20210915
}
if (utickExpired) //增加,20210915
{
PRINTF("Utick event occurs\r\n");
utickExpired = false; //增加,20210915
PRINTF("UTick = 0.\r\n");
UTickSet(0); //0ms
PRINTF("Wakeup.\r\n");
gCurrentPowerMode = 4; //测试 //增加,20210915
}
//----------------------------------- LED -----------------------------------
GPIO_PortToggle(GPIO, 3U, 1u << 17U); //增加,20210915
for(int32_t i = 10000*1000; i>0; --i)
{
}
}
}
/*
* Setup a GPIO input pin as wakeup source.
*/
static void APP_InitWakeupPin(void)
{
gpio_pin_config_t gpioPinConfigStruct;
/* Set SW pin as GPIO input. */
gpioPinConfigStruct.pinDirection = kGPIO_DigitalInput;
GPIO_PinInit(APP_USER_WAKEUP_KEY_GPIO, APP_USER_WAKEUP_KEY_PORT, APP_USER_WAKEUP_KEY_PIN, &gpioPinConfigStruct);
/* Configure the Input Mux block and connect the trigger source to PinInt channle. */
INPUTMUX_Init(INPUTMUX);
INPUTMUX_AttachSignal(INPUTMUX, kPINT_PinInt0, APP_USER_WAKEUP_KEY_INPUTMUX_SEL); /* Using channel 0. */
INPUTMUX_Deinit(INPUTMUX); /* Turnoff clock to inputmux to save power. Clock is only needed to make changes */
/* Configure the interrupt for SW pin. */
PINT_Init(PINT);
PINT_PinInterruptConfig(PINT, kPINT_PinInt0, kPINT_PinIntEnableFallEdge, pint_intr_callback);
PINT_EnableCallback(PINT); /* Enable callbacks for PINT */
EnableDeepSleepIRQ(PIN_INT0_IRQn);
}
static void APP_InitWakeupUTick(void) //增加,20210915
{
/* Init board hardware. */
CLOCK_AttachClk(kLPOSC_to_UTICK_CLK);
/* Intiialize UTICK */
UTICK_Init(UTICK0);
EnableDeepSleepIRQ(UTICK0_IRQn);
}
static void UTickSet(uint32_t usec) //增加,20210915
{
/* Set the UTICK timer to wake up the device from reduced power mode */
UTICK_SetTick(UTICK0, kUTICK_Repeat, usec - 1, UTickCallback); //kUTICK_Onetime
utickExpired = false;
}
static void UTickCallback(void) //增加,20210915
{
PRINTF("UTickCallback\r\n");
utickExpired = true;
}
/*
* Callback function when wakeup key is pressed.
*/
static void pint_intr_callback(pint_pin_int_t pintr, uint32_t pmatch_status)
{
pintFlag = true;
}
/*
* Get user selection from UART.
*/
static uint32_t APP_GetUserSelection(void)
{
uint32_t ch = 0;
/* Clear rx overflow error once it happens during low power mode. */
if (APP_USART_RX_ERROR == (APP_USART_RX_ERROR & USART_GetStatusFlags((USART_Type *)BOARD_DEBUG_UART_BASEADDR)))
{
USART_ClearStatusFlags((USART_Type *)BOARD_DEBUG_UART_BASEADDR, APP_USART_RX_ERROR);
}
PRINTF(
"Select an option\r\n"
"\t1. Sleep mode\r\n"
"\t2. Deep Sleep mode\r\n"
"\t3. Deep power down mode\r\n"
"\t4. Full deep power down mode\r\n");
while (1)
{
ch = GETCHAR();
if ((ch < '1') || (ch > '4')) /* Only '1', '2', '3' , '4'. */
{
continue;
}
else
{
ch = ch - '1'; /* Only 0, 1, 2 , 3 . */
break;
}
}
switch (ch)
{
case 0:
ch = kPmu_Sleep;
break;
case 1:
ch = kPmu_Deep_Sleep;
break;
case 2:
ch = kPmu_Deep_PowerDown;
break;
case 3:
ch = kPmu_Full_Deep_PowerDown;
break;
default:
break;
}
return ch;
}
Thank you very much for your reply, I have found the reason, LPOSC clock source is not turned on when entering deep sleep mode (the default is turned off), it needs to turn on clock source in the entry parameter of function " POWER_EnterDeepSleep(APP_EXCLUDE_FROM_DEEPSLEEP) "
The following content is modified to work normally :
#define APP_EXCLUDE_FROM_DEEPSLEEP \
(((const uint32_t[]){(APP_DEEPSLEEP_RUNCFG0 | SYSCTL0_PDSLEEPCFG0_LPOSC_PD_MASK), \
(SYSCTL0_PDSLEEPCFG1_FLEXSPI0_SRAM_APD_MASK | SYSCTL0_PDSLEEPCFG1_SRAM_SLEEP_MASK), \
APP_DEEPSLEEP_RAM_APD, APP_DEEPSLEEP_RAM_PPD}))
Thank you for your help!
Hello
Hope you are well.
To allow interrupts to wake up the device from deep-sleep mode, enable this in the SYSCTL0_STARTEN0.
You might use the routine EnableDeepSleepIRQ from the power control API.
Let me know if this is helpful, if you have more questions do not hesitate to ask me.
Best regards,
Omar