/*! * @brief Main function */ int main (void) { /* enable clock for PORTs */ CLOCK_SYS_EnablePortClock(PORTA_IDX); //CLOCK_SYS_EnablePortClock(PORTB_IDX); CLOCK_SYS_EnablePortClock(PORTC_IDX); CLOCK_SYS_EnablePortClock(PORTD_IDX); CLOCK_SYS_EnablePortClock(PORTE_IDX); /* Set allowed power mode, allow all. */ SMC_HAL_SetProtection(SMC, kAllowPowerModeAll); /* Set system clock configuration. */ CLOCK_SYS_SetConfiguration(&g_defaultClockConfigVlpr); /* Initialize LPTMR */ lptmr_state_t lptmrState; LPTMR_DRV_Init(LPTMR0_IDX, &lptmrState, &g_lptmrConfig); LPTMR_DRV_SetTimerPeriodUs(LPTMR0_IDX, 100000); LPTMR_DRV_InstallCallback(LPTMR0_IDX, lptmr_call_back); /* Initialize DMA */ dma_state_t dma_state; DMA_DRV_Init(&dma_state); /* Initialize PIT */ PIT_DRV_Init(0, false); PIT_DRV_InitChannel(0, 0, &g_pitChan0); /* Initialize CMP */ CMP_DRV_Init(0, &g_cmpState, &g_cmpConf); CMP_DRV_ConfigDacChn(0, &g_cmpDacConf); PORT_HAL_SetMuxMode(g_portBase[GPIOC_IDX], 0, kPortMuxAlt5); CMP_DRV_Start(0); /* Buttons */ GPIO_DRV_InputPinInit(&g_switch1); GPIO_DRV_InputPinInit(&g_switch2); GPIO_DRV_InputPinInit(&g_switchUp); GPIO_DRV_InputPinInit(&g_switchDown); GPIO_DRV_InputPinInit(&g_switchLeft); GPIO_DRV_InputPinInit(&g_switchRight); GPIO_DRV_InputPinInit(&g_switchSelect); /* Start LPTMR */ LPTMR_DRV_Start(LPTMR0_IDX); /* Setup LPUART1 */ LPUART_DRV_Init(1, &g_lpuartState, &g_lpuartConfig); LPUART_DRV_InstallRxCallback(1, lpuartRxCallback, rxBuff, NULL, true); LPUART_DRV_InstallTxCallback(1, lpuartTxCallback, NULL, NULL); LPUART_BWR_CTRL_TXINV(g_lpuartBase[1], 1); PORT_HAL_SetMuxMode(g_portBase[GPIOE_IDX], 0, kPortMuxAlt3); PORT_HAL_SetMuxMode(g_portBase[GPIOE_IDX], 1, kPortMuxAlt3); /* Setup FlexIO for the WS2812B */ FLEXIO_Type *fiobase = g_flexioBase[0]; CLOCK_SYS_SetFlexioSrc(0, kClockFlexioSrcMcgIrClk); FLEXIO_DRV_Init(0, &g_flexioConfig); FLEXIO_HAL_ConfigureTimer(fiobase, 0, &g_timerConfig); FLEXIO_HAL_ConfigureShifter(fiobase, 0, &g_shifterConfig); PORT_HAL_SetMuxMode(g_portBase[GPIOE_IDX], 20, kPortMuxAlt6); FLEXIO_DRV_Start(0); FLEXIO_HAL_SetShifterStatusDmaCmd(fiobase, 1, true); DMA_DRV_RequestChannel(kDmaAnyChannel, kDmaRequestMux0FlexIOChannel0, &g_fioChan); DMA_DRV_RegisterCallback(&g_fioChan, fioDmaCallback, NULL); /* Connect buzzer to TPM0_CH3 */ PORT_HAL_SetMuxMode(g_portBase[GPIOE_IDX], 30, kPortMuxAlt3); tpm_general_config_t tmpConfig = { .isDBGMode = false, .isGlobalTimeBase = false, .isTriggerMode = false, .isStopCountOnOveflow = false, .isCountReloadOnTrig = false, .triggerSource = kTpmTrigSel0, }; TPM_DRV_Init(0, &tmpConfig); TPM_DRV_SetClock(0, kTpmClockSourceModuleMCGIRCLK, kTpmDividedBy1); /* Blank LED just in case, saves power */ led(0x00, 0x00, 0x00); /* Init e-paper display */ EPD_Init(); /* Throw up first image */ int ret = EPD_Draw(NULL, images[current_image]); if (-1 == ret) { led(0xff, 0x00, 0x00); } else if (-2 == ret) { led(0xff, 0xff, 0x00); } else if (-3 == ret) { led(0x00, 0x00, 0xff); } else { led(0x00, 0xff, 0x00); } blank_led = 30; /* Deinit so we can mess around on the bus pirate */ //EPD_Deinit(); /* We're done, everything else is triggered through interrupts */ for(;;) { if (cue_next_image) { int old_image = current_image; current_image = (current_image + 1) % image_count; EPD_Draw(images[old_image], images[current_image]); cue_next_image = 0; } #ifndef DEBUG SMC_HAL_SetMode(SMC, &g_idlePowerMode); #endif } }
/*FUNCTION********************************************************************** * * Function Name : POWER_SYS_SetMode * Description : Configures the power mode. * * This function switches to one of the defined power modes. Requested mode number is passed * as an input parameter. This function notifies all registered callback functions before * the mode change (using kPowerManagerCallbackBefore set as callback type parameter), * sets specific power options defined in the power mode configuration and enters the specified * mode. In case of run modes (for example, Run, Very low power run, or High speed run), this function * also invokes all registered callbacks after the mode change (using kPowerManagerCallbackAfter). * In case of sleep or deep sleep modes, if the requested mode is not exited through * a reset, these notifications are sent after the core wakes up. * Callbacks are invoked in the following order: All registered callbacks are notified * ordered by index in the callbacks array (see callbacksPtr parameter of POWER_SYS_Init()). * The same order is used for before and after switch notifications. * The notifications before the power mode switch can be used to obtain confirmation about * the change from registered callbacks. If any registered callback denies the power * mode change, further execution of this function depends on mode change policy: the mode * change is either forced (kPowerManagerPolicyForcible) or exited (kPowerManagerPolicyAgreement). * When mode change is forced, the result of the before switch notifications are ignored. If * agreement is required, if any callback returns an error code then further notifications * before switch notifications are cancelled and all already notified callbacks are re-invoked * with kPowerManagerCallbackAfter set as callback type parameter. The index of the callback * which returned error code during pre-switch notifications is stored (any error codes during * callbacks re-invocation are ignored) and POWER_SYS_GetErrorCallback() can be used to get it. * Regardless of the policies, if any callback returned an error code, an error code denoting in which phase * the error occurred is returned when POWER_SYS_SetMode() exits. * It is possible to enter any mode supported by the processor. Refer to the chip reference manual * for list of available power modes. If it is necessary to switch into intermediate power mode prior to * entering requested mode (for example, when switching from Run into Very low power wait through Very low * power run mode), then the intermediate mode is entered without invoking the callback mechanism. * *END**************************************************************************/ power_manager_error_code_t POWER_SYS_SetMode(uint8_t powerModeIndex, power_manager_policy_t policy) { power_manager_user_config_t const * configPtr; /* Local pointer to the requested user-defined power mode configuration */ power_manager_modes_t mode; /* Local variable with requested power mode */ smc_power_mode_config_t halModeConfig; /* SMC HAL layer configuration structure */ uint8_t currentStaticCallback = 0U; /* Index to array of statically registered call-backs */ power_manager_error_code_t returnCode = kPowerManagerSuccess; /* Function return */ power_manager_error_code_t clockCheckRetCode; /* Return code from clock checks */ power_manager_notify_struct_t notifyStruct; /* Callback notification structure */ power_manager_callback_user_config_t * callbackConfig; /* Pointer to callback configuration */ /* Default value of handle of last call-back that returned error */ gPowerManagerState.errorCallbackIndex = gPowerManagerState.staticCallbacksNumber; POWER_SYS_LOCK(); /* Requested power mode configuration availability check */ if (powerModeIndex >= gPowerManagerState.configsNumber) { POWER_SYS_UNLOCK(); return kPowerManagerErrorOutOfRange; } /* Initialization of local variables from the Power manager state structure */ configPtr = gPowerManagerState.configs[powerModeIndex]; mode = configPtr->mode; notifyStruct.policy = policy; notifyStruct.targetPowerConfigIndex = powerModeIndex; notifyStruct.targetPowerConfigPtr = configPtr; /* Check that requested power mode is not protected */ if ((mode == kPowerManagerVlpr) || (mode == kPowerManagerVlpw) || (mode == kPowerManagerVlps)) { if (!SMC_HAL_GetProtection(SMC, kAllowPowerModeVlp)) { POWER_SYS_UNLOCK(); return kPowerManagerError; } } #if FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE #if FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 else if ((mode >= kPowerManagerLls) && (mode < kPowerManagerVlls0)) #else else if ((mode >= kPowerManagerLls) && (mode < kPowerManagerVlls1)) #endif { if (!SMC_HAL_GetProtection(SMC, kAllowPowerModeLls)) { POWER_SYS_UNLOCK(); return kPowerManagerError; } } #endif #if FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 else if (mode >= kPowerManagerVlls0) #else else if (mode >= kPowerManagerVlls1) #endif { if (!SMC_HAL_GetProtection(SMC, kAllowPowerModeVlls)) { POWER_SYS_UNLOCK(); return kPowerManagerError; } } notifyStruct.notifyType = kPowerManagerNotifyBefore; /* From all statically registered call-backs... */ for (currentStaticCallback = 0U; currentStaticCallback < gPowerManagerState.staticCallbacksNumber; currentStaticCallback++) { callbackConfig = (gPowerManagerState.staticCallbacks[currentStaticCallback]); /* Check pointer to static callback configuration */ if ( callbackConfig != NULL ){ /* ...notify only those which asked to be called before the power mode change */ if (((uint32_t)callbackConfig->callbackType) & kPowerManagerCallbackBefore) { /* In case that call-back returned error code mark it, store the call-back handle and eventually cancel the mode switch */ if (callbackConfig->callback(¬ifyStruct, callbackConfig->callbackData) != kPowerManagerSuccess) { returnCode = kPowerManagerErrorNotificationBefore; gPowerManagerState.errorCallbackIndex = currentStaticCallback; /* If not forcing power mode switch, call all already notified call-backs to revert their state as the mode change is canceled */ if (policy != kPowerManagerPolicyForcible) { break; } } } } } POWER_SYS_UNLOCK(); /* Clocks should be in desired range. Some registered callback can change the clock so checks clock after callbacks */ clockCheckRetCode = POWER_SYS_CheckClocks(mode); /* Power mode switch */ /* In case that any call-back returned error code and policy doesn't force the mode switch go to after switch call-backs */ if ( ((policy == kPowerManagerPolicyForcible) || (returnCode == kPowerManagerSuccess)) && (clockCheckRetCode == kPowerManagerSuccess)) { #if FSL_FEATURE_SMC_HAS_LPWUI halModeConfig.lpwuiOptionValue = configPtr->lowPowerWakeUpOnInterruptValue; #endif /* Configure the HAL layer */ switch (mode) { #if FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE /* High speed run mode */ case kPowerManagerHsrun: halModeConfig.powerModeName = kPowerModeHsrun; break; #endif /* Run mode */ case kPowerManagerRun: halModeConfig.powerModeName = kPowerModeRun; break; /* Very low power run mode */ case kPowerManagerVlpr: halModeConfig.powerModeName = kPowerModeVlpr; break; /* Wait mode */ case kPowerManagerWait: halModeConfig.powerModeName = kPowerModeWait; break; /* Very low power wait mode */ case kPowerManagerVlpw: halModeConfig.powerModeName = kPowerModeVlpw; break; #if FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE /* Low leakage stop modes */ case kPowerManagerLls: halModeConfig.powerModeName = kPowerModeLls; break; #if FSL_FEATURE_SMC_HAS_LLS_SUBMODE case kPowerManagerLls2: halModeConfig.powerModeName = kPowerModeLls; halModeConfig.stopSubMode = kSmcStopSub2; break; case kPowerManagerLls3: halModeConfig.powerModeName = kPowerModeLls; halModeConfig.stopSubMode = kSmcStopSub3; break; #endif #endif /* Very low leakage stop modes */ #if FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 case kPowerManagerVlls0: halModeConfig.powerModeName = kPowerModeVlls; halModeConfig.stopSubMode = kSmcStopSub0; #if FSL_FEATURE_SMC_HAS_PORPO /* Optionally setup the power-on-reset detect circuit in VLLS0 */ halModeConfig.porOptionValue = configPtr->powerOnResetDetectionValue; #endif break; #endif case kPowerManagerVlls1: halModeConfig.powerModeName = kPowerModeVlls; halModeConfig.stopSubMode = kSmcStopSub1; break; #if FSL_FEATURE_SMC_HAS_STOP_SUBMODE2 case kPowerManagerVlls2: halModeConfig.powerModeName = kPowerModeVlls; halModeConfig.stopSubMode = kSmcStopSub2; #if FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION /* Optionally setup the RAM2 partition retention in VLLS2 */ halModeConfig.ram2OptionValue = configPtr->RAM2PartitionValue; #endif break; #endif case kPowerManagerVlls3: halModeConfig.powerModeName = kPowerModeVlls; halModeConfig.stopSubMode = kSmcStopSub3; break; #if FSL_FEATURE_SMC_HAS_PSTOPO /* Partial stop modes */ case kPowerManagerPstop1: halModeConfig.powerModeName = kPowerModeStop; halModeConfig.pstopOptionValue = kSmcPstopStop1; break; case kPowerManagerPstop2: halModeConfig.powerModeName = kPowerModeStop; halModeConfig.pstopOptionValue = kSmcPstopStop2; break; #endif /* Stop mode */ case kPowerManagerStop: halModeConfig.powerModeName = kPowerModeStop; #if FSL_FEATURE_SMC_HAS_PSTOPO halModeConfig.pstopOptionValue = kSmcPstopStop; #endif break; /* Very low power stop mode */ case kPowerManagerVlps: halModeConfig.powerModeName = kPowerModeVlps; break; default: return kPowerManagerErrorSwitch; } #if FSL_FEATURE_SMC_HAS_LPOPO #if FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE if ((mode >= kPowerManagerLls) && (mode <= kPowerManagerVlls3)) #else #if FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 if ((mode >= kPowerManagerVlls0) && (mode <= kPowerManagerVlls3)) #else if ((mode >= kPowerManagerVlls1) && (mode <= kPowerManagerVlls3)) #endif #endif { /* Optionally setup the LPO operation in LLSx/VLLSx */ halModeConfig.lpoOptionValue = configPtr->lowPowerOscillatorValue; } #endif /* Configure ARM core what to do after interrupt invoked in (deep) sleep state */ if (mode >= kPowerManagerWait) { if (configPtr->sleepOnExitValue) { /* Go back to (deep) sleep state on ISR exit */ SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; } else { /* Do not re-enter (deep) sleep state on ISR exit */ SCB->SCR &= ~(SCB_SCR_SLEEPONEXIT_Msk); } } /* Switch the mode */ if (SMC_HAL_SetMode(SMC, &halModeConfig) != kSmcHalSuccess) { returnCode = kPowerManagerErrorSwitch; } /* Wait until new run mode is entered */ if (mode == kPowerManagerRun) { returnCode = POWER_SYS_WaitForRunStatus(); if(returnCode != kPowerManagerSuccess) { return returnCode; } } else if (mode == kPowerManagerVlpr) { returnCode = POWER_SYS_WaitForVlprStatus(); if(returnCode != kPowerManagerSuccess) { return returnCode; } } /* End of successful switch */ POWER_SYS_LOCK(); /* Update current configuration index */ gPowerManagerState.currentConfig = powerModeIndex; notifyStruct.notifyType = kPowerManagerNotifyAfter; /* From all statically registered call-backs... */ for (currentStaticCallback = 0U; currentStaticCallback < gPowerManagerState.staticCallbacksNumber; currentStaticCallback++) { callbackConfig = (gPowerManagerState.staticCallbacks[currentStaticCallback]); /* Check pointer to static callback configuration */ if ( callbackConfig != NULL ){ /* ...notify only those which asked to be called after the power mode change */ if (((uint32_t)callbackConfig->callbackType) & kPowerManagerCallbackAfter) { /* In case that call-back returned error code mark it and store the call-back handle */ if (callbackConfig->callback(¬ifyStruct, callbackConfig->callbackData) != kPowerManagerSuccess) { returnCode = kPowerManagerErrorNotificationAfter; gPowerManagerState.errorCallbackIndex = currentStaticCallback; } } } } POWER_SYS_UNLOCK(); } else { /* End of unsuccessful switch */ /* Checks if we can't switch due to clock */ if((policy == kPowerManagerPolicyForcible) || (returnCode == kPowerManagerSuccess)) { returnCode = clockCheckRetCode; } POWER_SYS_LOCK(); notifyStruct.notifyType = kPowerManagerNotifyRecover; while(currentStaticCallback--) { callbackConfig = (gPowerManagerState.staticCallbacks[currentStaticCallback]); /* Check pointer to static callback configuration */ if ( callbackConfig != NULL ){ if (((uint32_t)callbackConfig->callbackType) & kPowerManagerCallbackBefore) { callbackConfig->callback(¬ifyStruct, callbackConfig->callbackData); } } } POWER_SYS_UNLOCK(); } return returnCode; }
/*! * @brief main function */ int main(void) { i2c_slave_state_t slave; i2cData_t i2cData = { .subAddress = Invalid_Subaddress_Index, .data = 0, .state = CMD_MODE }; i2c_slave_user_config_t userConfig = { .address = 0x3A, .slaveListening = true, .slaveCallback = i2c_slave_event_callback_passive, .callbackParam = &i2cData, #if FSL_FEATURE_I2C_HAS_START_STOP_DETECT .startStopDetect = false, #endif #if FSL_FEATURE_I2C_HAS_STOP_DETECT .stopDetect = false, #endif }; // Low Power Configuration smc_power_mode_config_t smcConfig; // Init struct memset(&smcConfig, 0, sizeof(smcConfig)); hardware_init(); OSA_Init(); GPIO_DRV_Init(0, ledPins); // Initiate I2C instance module I2C_DRV_SlaveInit(BOARD_I2C_INSTANCE, &userConfig, &slave); PRINTF("\r\n====== I2C Slave ======\r\n\r\n"); // turn LED_slave on to indicate I2C slave status is waiting for date receiving LED_turnon_slave(); LED_turnoff_master(); OSA_TimeDelay(50); PRINTF("\r\n I2C slave enters low power mode...\r\n"); // set to allow entering specific modes SMC_HAL_SetProtection(SMC, kAllowPowerModeVlp); // set power mode to specific Run mode #if FSL_FEATURE_SMC_HAS_LPWUI smcConfig.lpwuiOptionValue = kSmcLpwuiEnabled; #endif #if FSL_FEATURE_SMC_HAS_PORPO smcConfig.porOptionValue = kSmcPorEnabled; #endif #if FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE smcConfig.powerModeName = kPowerModeRun; // If current status is HSRUN mode, change to RUN mode first. if (kStatHsrun == SMC_HAL_GetStat(SMC_BASE_PTR)) { SMC_HAL_SetMode(SMC_BASE_PTR, &smcConfig); } #endif smcConfig.powerModeName = kPowerModeWait; // Entry to Low Power Mode SMC_HAL_SetMode(SMC_BASE_PTR, &smcConfig); // LED_slave is still on during low power mode until I2C master send data to slave. // Turn off LED_slave to indicate MCU wake up by I2C address matching interrupt LED_turnoff_slave(); PRINTF("\r\n I2C slave wakes up from low power mode by I2C address matching.\r\n"); while(1); }