/*FUNCTION********************************************************************** * * Function Name : POWER_SYS_ClearWakeupPinFlag * Description : This function allows to clear wake up pin flag in low leakage wake up unit (LLWU). * *END**************************************************************************/ void POWER_SYS_ClearWakeupPinFlag(power_wakeup_pin_t pin) { llwu_wakeup_pin_t llwuPin = POWER_EXTRACT_LLWU_PIN(pin); assert( (uint32_t)llwuPin < FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN); LLWU_HAL_ClearExternalPinWakeupFlag(LLWU, llwuPin); }
/*! * @brief LLWU ISR function */ void llwu_isr(void) { uint8_t pinEn; NVIC_ClearPendingIRQ(LLW_IRQn); /* Print LLWU acknowledgement only if UART is enabled */ for(pinEn = 0; pinEn < FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN; pinEn++) { if (LLWU_HAL_GetExternalPinWakeupFlag(LLWU_BASE, (llwu_wakeup_pin_t)pinEn)) { LLWU_HAL_ClearExternalPinWakeupFlag(LLWU_BASE, (llwu_wakeup_pin_t)pinEn); /* write one to clear the flag */ } } /* * Note: This ISR does not write to the LLWU_F3 register because these * are peripheral module wakeups. The flags contained in the LLWU_F3 * register should be cleared through the associated module interrupt * and not through the LLWU_F3 per the Kinetis L Family Reference * Manual (LLWU Chapter) */ if (LLWU_HAL_GetInternalModuleWakeupFlag(LLWU_BASE, kLlwuWakeupModule0)) { CLOCK_SYS_EnableLptimerClock(0); LPTMR_HAL_ClearIntFlag(LPTMR0_BASE); /* write 1 to TCF to clear the LPT timer compare flag */ LPTMR_HAL_IsEnabled(LPTMR0_BASE); LPTMR_HAL_SetIntCmd(LPTMR0_BASE, 1); LPTMR_HAL_IsIntPending(LPTMR0_BASE); } if(LLWU_HAL_GetFilterDetectFlag(LLWU_BASE, 0)){ LLWU_HAL_ClearFilterDetectFlag(LLWU_BASE, 0); } if(LLWU_HAL_GetFilterDetectFlag(LLWU_BASE, 1)){ LLWU_HAL_ClearFilterDetectFlag(LLWU_BASE, 1); } }
/*! * @brief Set up the LLWU for wakeup the MCU from LLS and VLLSx modes * from the selected pin or module. * * @param * pin_en - unsigned integer, bit position indicates the pin is enabled. * More than one bit can be set to enable more than one pin at a time. * @param * rise_fall - 0x00 = External input disabled as wakeup * 0x01 - External input enabled as rising edge detection * 0x02 - External input enabled as falling edge detection * 0x03 - External input enablge as any edge detection * @param * module_en - unsigned char, bit position indicates the module is enabled. * More than one bit can be set to enabled more than one module * * for example: if bit 0 and 1 need to be enabled as rising edge detect call this routine with * pin_en = 0x0003 and rise_fall = 0x02 * Note: to set up one set of pins for rising and another for falling, 2 calls to this * function are required, 1st for rising then the second for falling. */ void llwu_configure(llwu_wakeup_pin_t pinEn, llwu_external_pin_modes_t riseFall, llwu_wakeup_module_t moduleEn ) { /**************************************************************** * LLWU pin initialization * * First, clear the associated flag just to be sure the device * doesn't immediately enter the LLWU interrupt service routine * (ISR). Then enable the interrupt ****************************************************************/ LLWU_HAL_ClearExternalPinWakeupFlag(LLWU_BASE, pinEn); LLWU_HAL_SetExternalInputPinMode(LLWU_BASE, riseFall, pinEn); /****************************************************************** * LLWU module initialization * * Now enable an internal peripheral module as an LLWU source if * desired ****************************************************************/ if (moduleEn < NULL_LLWU_SRC_VAL) { LLWU_HAL_SetInternalModuleCmd(LLWU_BASE, moduleEn, true); } } /* End LLWU Configuration */
void gpioEnableWakeUp(void) { // enables falling edge interrupt for switch SWx PORT_HAL_SetPinIntMode(BOARD_SW_LLWU_BASE, BOARD_SW_LLWU_PIN, kPortIntFallingEdge); INT_SYS_EnableIRQ(BOARD_SW_LLWU_IRQ_NUM); LLWU_HAL_ClearExternalPinWakeupFlag(LLWU_BASE_PTR, (llwu_wakeup_pin_t)BOARD_SW_LLWU_EXT_PIN); LLWU_HAL_SetExternalInputPinMode(LLWU_BASE_PTR,kLlwuExternalPinFallingEdge, (llwu_wakeup_pin_t)BOARD_SW_LLWU_EXT_PIN); }
void gpioDisableWakeUp(void) { // disables interrupt PORT_HAL_SetPinIntMode(BOARD_SW_LLWU_BASE, BOARD_SW_LLWU_PIN, kPortIntDisabled); INT_SYS_DisableIRQ(BOARD_SW_LLWU_IRQ_NUM); LLWU_HAL_ClearExternalPinWakeupFlag(LLWU_BASE_PTR, (llwu_wakeup_pin_t)BOARD_SW_LLWU_EXT_PIN); LLWU_HAL_SetExternalInputPinMode(LLWU_BASE_PTR,kLlwuExternalPinDisabled, (llwu_wakeup_pin_t)BOARD_SW_LLWU_EXT_PIN); }
void LLWU_IRQHandler(void) { if (RTC_HAL_HasAlarmOccured(RTC)) { RTC_HAL_SetAlarmIntCmd(RTC_BASE_PTR, false); } LLWU_HAL_ClearExternalPinWakeupFlag(LLWU_BASE_PTR, (llwu_wakeup_pin_t)BOARD_SW_LLWU_EXT_PIN); }
/* LLW_IRQHandler that would cover the same name's APIs in startup code */ void LLWU_IRQHandler(void) { // The LLWU wakeup interrup is LPTMR source if (LLWU_HAL_GetInternalModuleWakeupFlag(LLWU_BASE_PTR, PM_RTOS_DEMO_LPTMR_LLWU_WAKEUP_MODULE)) { LPTMR_HAL_ClearIntFlag(g_lptmrBase[PM_RTOS_DEMO_LPTMR_FUNC_INSTANCE]); } // The LLWU wakeup interrup is RTC source if (LLWU_HAL_GetInternalModuleWakeupFlag(LLWU_BASE_PTR, PM_RTOS_DEMO_RTC_LLWU_WAKEUP_MODULE)) { RTC_DRV_SetAlarmIntCmd(PM_RTOS_DEMO_RTC_FUNC_INSTANCE, false); } // The LLWU wakeup interrup is Switch/Button source if (LLWU_HAL_GetExternalPinWakeupFlag(LLWU_BASE_PTR,(llwu_wakeup_pin_t)BOARD_SW_LLWU_EXT_PIN)) { LLWU_HAL_ClearExternalPinWakeupFlag(LLWU_BASE_PTR, (llwu_wakeup_pin_t)BOARD_SW_LLWU_EXT_PIN); } }
//****************************************************************************** //* Interrupt handlers used to wake the device from the various low power modes. //****************************************************************************** void LLWU_IRQHandler(void) { // Clear the interrupt flag. LLWU_HAL_ClearExternalPinWakeupFlag(LLWU, BOARD_SW_LLWU_EXT_PIN); }
/******************************************************************************* * Main function for application. ******************************************************************************/ void lab2_power(void) { demo_power_modes_t testVal = kDemoRun; volatile uint8_t powerMode; uint8_t clockManagerMode = CLOCK_RUN; uint32_t freq = 0; //******************************************************* //* Step 1: Initialize the Clock Manager configurations. //******************************************************* // Create list of supported clock configurations. These are taken from the // board.c file and will be passed into CLOCK_SYS_Init(). clock_manager_user_config_t const *clockConfigs[] = { NULL, &g_defaultClockConfigVlpr, &g_defaultClockConfigRun, &g_defaultClockConfigHsrun, }; //***************************************************** //* Step 2: Configure Clock Manager callback function. //***************************************************** // Clock Manager callback function. clock_manager_callback_user_config_t clockManagerCallbackCfg = { .callback = clockManagerCallback, .callbackType = kClockManagerCallbackBeforeAfter, .callbackData = NULL }; clock_manager_callback_user_config_t *clockCallbacks[] = { &clockManagerCallbackCfg }; //***************************************************** //* Step 3: Initialize the Clock Manager. //***************************************************** // Pass in configuration and callback data to Clock Manager. CLOCK_SYS_Init(clockConfigs, CLOCK_NUMBER_OF_CONFIGURATIONS, clockCallbacks, ARRAY_SIZE(clockCallbacks)); // Set to RUN mode. CLOCK_SYS_UpdateConfiguration(CLOCK_RUN, kClockManagerPolicyForcible); //***************************************************** //* Step 4: Set up supported power mode structures. //***************************************************** const power_manager_user_config_t runConfig = { .mode = kPowerManagerRun, .sleepOnExitValue = false, }; power_manager_user_config_t hsrunConfig = runConfig; hsrunConfig.mode = kPowerManagerHsrun; power_manager_user_config_t waitConfig = runConfig; waitConfig.mode = kPowerManagerWait; power_manager_user_config_t stopConfig = runConfig; stopConfig.mode = kPowerManagerStop; power_manager_user_config_t vlprConfig = runConfig; vlprConfig.mode = kPowerManagerVlpr; power_manager_user_config_t vlpwConfig = runConfig; vlpwConfig.mode = kPowerManagerVlpw; power_manager_user_config_t vlpsConfig = runConfig; vlpsConfig.mode = kPowerManagerVlps; power_manager_user_config_t lls3Config = runConfig; lls3Config.mode = kPowerManagerLls3; power_manager_user_config_t vlls0Config = runConfig; vlls0Config.mode = kPowerManagerVlls0; //*********************************************************** //* Step 5: Configure managed power configurations structure. //*********************************************************** // Create the list of supported modes to pass into the Power Manager. power_manager_user_config_t const *powerConfigs[] = { &runConfig, &hsrunConfig, &waitConfig, &stopConfig, &vlprConfig, &vlpwConfig, &vlpsConfig, &lls3Config, &vlls0Config }; //***************************************************** //* Step 6: Configure Power Manager callback function. //***************************************************** // Initializes callback configuration structure for the Power Manager. power_manager_callback_user_config_t powerManagerCallbackCfg = { .callback = powerManagerCallback, .callbackType = kPowerManagerCallbackBeforeAfter, .callbackData = NULL }; // Initializes array of pointers to power manager callbacks. power_manager_callback_user_config_t *powerCallbacks[] = { &powerManagerCallbackCfg }; //***************************************************** //* Step 7: Initialize the Power Manager. //***************************************************** // Pass power configurations and callback info to Power Manager. POWER_SYS_Init(powerConfigs, sizeof(powerConfigs) / sizeof(power_manager_user_config_t *), powerCallbacks, ARRAY_SIZE(powerCallbacks)); // Initialize system to RUN mode. powerMode = kDemoRun - kDemoMin - 1; POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); //************************************************************** //* Step 8: Configure the rest of the chip for this application. //************************************************************** // Configure pin mux for UART functionality. configure_uart_pins(BOARD_DEBUG_UART_INSTANCE); // Initializes GPIO driver for LEDs and buttons GPIO_DRV_Init(switchPins, ledPins); // Initialize the debug UART console. DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_LOW_POWER_UART_BAUD, kDebugConsoleUART); // Enable PORTC clock for GPIO/LLWU interrupt. CLOCK_SYS_EnablePortClock(2); // Enables falling edge interrupt for switch SW2. PORT_HAL_SetMuxMode(BOARD_SW_LLWU_BASE, BOARD_SW_LLWU_PIN, kPortMuxAsGpio); PORT_HAL_SetPinIntMode(BOARD_SW_LLWU_BASE, BOARD_SW_LLWU_PIN, kPortIntFallingEdge); // Enable GPIO interrupt. INT_SYS_EnableIRQ(PORTC_IRQn); // Configure the LLWU. LLWU_HAL_ClearExternalPinWakeupFlag(LLWU, BOARD_SW_LLWU_EXT_PIN); LLWU_HAL_SetExternalInputPinMode(LLWU, kLlwuExternalPinFallingEdge, BOARD_SW_LLWU_EXT_PIN); // Enable LLWU interrupt. INT_SYS_EnableIRQ(LLWU_IRQn); // Main loop. while (1) { // Get the system clock frequency and current clock configuration to print out. CLOCK_SYS_GetFreq(kCoreClock, &freq); clockManagerMode = CLOCK_SYS_GetCurrentConfiguration(); PRINTF("\n\r#################### Power Manager Demo ####################\n\n\r"); PRINTF(" Core Clock = %d MHz \n\r", freq / 1000000); PRINTF(" Current Mode = "); switch(clockManagerMode) { case CLOCK_RUN: PRINTF("RUN\n\r"); break; case CLOCK_VLPR: PRINTF("VLPR\n\r"); break; case CLOCK_HSRUN: PRINTF("HSRUN\n\r"); break; } PRINTF("\n\rSelect the desired operation \n\n\r"); PRINTF("Press %c for enter: RUN - Normal RUN mode\n\r", kDemoRun); PRINTF("Press %c for enter: HSRUN - High Speed RUN mode\n\r", kDemoHsRun); PRINTF("Press %c for enter: Wait - Wait mode\n\r", kDemoWait); PRINTF("Press %c for enter: Stop - Stop mode\n\r", kDemoStop); PRINTF("Press %c for enter: VLPR - Very Low Power Run mode\n\r", kDemoVlpr); PRINTF("Press %c for enter: VLPW - Very Low Power Wait mode\n\r", kDemoVlpw); PRINTF("Press %c for enter: VLPS - Very Low Power Stop mode\n\r", kDemoVlps); PRINTF("Press %c for enter: LLS3 - Low Leakage Stop mode\n\r", kDemoLls3); PRINTF("Press %c for enter: VLLS0 - Very Low Leakage Stop mode 0\n\r", kDemoVlls0); //PRINTF("Press %c for enter: VLLS3 - Very Low Leakage Stop mode 3\n\r", kDemoVlls3); PRINTF("\n\rWaiting for key press...\n\r\n\r"); // Wait for user input. testVal = (demo_power_modes_t)GETCHAR(); if ((testVal >= 'a') && (testVal <= 'z')) { testVal -= 'a' - 'A'; } if (testVal > kDemoMin && testVal < kDemoMax) { // Obtain Power Manager readable version of the value passed in. powerMode = testVal - kDemoMin - 1; // Switch to selected mode. switch (testVal) { case kDemoRun: if (POWER_SYS_GetCurrentMode() == kPowerManagerRun) { PRINTF("Run mode already active.\n\r"); break; } // Update the power configuration. POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); // Update the clock configuration. CLOCK_SYS_UpdateConfiguration(CLOCK_RUN, kClockManagerPolicyAgreement); break; case kDemoHsRun: if (POWER_SYS_GetCurrentMode() == kPowerManagerHsrun) { PRINTF("High Speed Run mode already active.\n\r"); break; } // Update the power configuration. POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); // Update the clock configuration. CLOCK_SYS_UpdateConfiguration(CLOCK_HSRUN, kClockManagerPolicyAgreement); break; case kDemoWait: if (POWER_SYS_GetCurrentMode() == kPowerManagerVlpr) { PRINTF("Cannot go from VLPR to WAIT directly...\n\r"); break; } if (POWER_SYS_GetCurrentMode() == kPowerManagerHsrun) { PRINTF("Cannot go from HSRUN to WAIT directly...\n\r"); break; } PRINTF("Entering WAIT mode. Press SW2 to wake...\n\r"); // Update the power configuration. POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); break; case kDemoStop: if (POWER_SYS_GetCurrentMode() == kPowerManagerVlpr) { PRINTF("Cannot go from VLPR to STOP directly...\n\r"); break; } if (POWER_SYS_GetCurrentMode() == kPowerManagerHsrun) { PRINTF("Cannot go from HSRUN to STOP directly...\n\r"); break; } PRINTF("Entering STOP mode. Press SW2 to wake...\n\r"); // Update the power configuration. POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); // Update the clock configuration. CLOCK_SYS_UpdateConfiguration(clockManagerMode, kClockManagerPolicyAgreement); break; case kDemoVlpr: if (POWER_SYS_GetCurrentMode() == kPowerManagerHsrun) { PRINTF("Cannot go from HSRUN to VLPR directly...\n\r"); break; } if(POWER_SYS_GetCurrentMode() != kPowerManagerVlpr) { // Update the clock configuration PRIOR to entering VLPR. CLOCK_SYS_UpdateConfiguration(CLOCK_VLPR, kClockManagerPolicyAgreement); // Update the power configuration. POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); } else { PRINTF("Very Low Power Run mode already active.\n\r"); } break; case kDemoVlpw: if (POWER_SYS_GetCurrentMode() == kPowerManagerRun) { PRINTF("Cannot go from RUN to VLPW directly...\n\r"); break; } if (POWER_SYS_GetCurrentMode() == kPowerManagerHsrun) { PRINTF("Cannot go from HSRUN to VLPW directly...\n\r"); break; } PRINTF("Entering VLPW mode. Press SW2 to wake...\n\r"); // Update the power configuration. POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); break; case kDemoVlps: if (POWER_SYS_GetCurrentMode() == kPowerManagerHsrun) { PRINTF("Cannot go from HSRUN to VLPS directly...\n\r"); break; } PRINTF("Entering VLPS mode. Press SW2 to wake...\n\r"); // Update the power configuration. POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); // If we entered via RUN mode, restore clock settings. if (POWER_SYS_GetCurrentMode() == kPowerManagerRun) { CLOCK_SYS_UpdateConfiguration(clockManagerMode, kClockManagerPolicyAgreement); } break; case kDemoLls3: if (POWER_SYS_GetCurrentMode() == kPowerManagerHsrun) { PRINTF("Cannot go from HSRUN to LLSx directly...\n\r"); break; } PRINTF("Entering LLS3 mode. Press SW2 to wake...\n\r"); // Update the power configuration. POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); // Check the mode active mode prior to LLS3 entry. if(POWER_SYS_GetCurrentMode() != kPowerManagerVlpr) { CLOCK_SYS_UpdateConfiguration(clockManagerMode, kClockManagerPolicyAgreement); } break; case kDemoVlls0: if (POWER_SYS_GetCurrentMode() == kPowerManagerHsrun) { PRINTF("Cannot go from HSRUN to VLLSx directly...\n\r"); break; } PRINTF("Press SW2 to wake. VLLSx wake goes through RESET sequence.\n\r"); // Update the power configuration. POWER_SYS_SetMode(powerMode, kPowerManagerPolicyAgreement); break; default: PRINTF("Bad value."); break; } PRINTF("\n\rNext loop\n\r"); } } }