Esempio n. 1
0
/*!
 * @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
    }
}
Esempio n. 2
0
/*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(&notifyStruct, 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(&notifyStruct, 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(&notifyStruct, 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);
}