コード例 #1
0
ファイル: sleep.c プロジェクト: haby77/BLE-passthrough
/**
 ****************************************************************************************
 * @brief  Restore from low power mode
 * @param[in]    callback       callback before XTAL clock ready
 * @description
 *  This function is used to set MCU restoring from low power mode, switch system clock to XTAL.
 *****************************************************************************************
 */
void restore_from_low_power_mode(void (*callback)(void))
{
    syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_PD_STATE|SYSCON_MASK_DVDD12_PMU_SET, MASK_DISABLE);
    if (callback != NULL) {
        callback();
    }
    
    // 16MHz/32MHz XTAL is ready
    while (!(syscon_GetBLESR(QN_SYSCON) & SYSCON_MASK_CLK_RDY))
    {
        // XTAL shall be ready before BLE wakeup
        if (check_ble_wakeup())
        {
            // In this case XTAL wakeup duration is larger than setting.
            // The parameter 'Oscillator wake-up time' in the NVDS should be revised.
#if (QN_DBG_INFO)
            set_dbg_info(QN_DBG_INFO_XTAL_WAKEUP_DURATION);
#endif
        }
    }
    //syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_CLK_MUX, CLK_XTAL<<SYSCON_POS_CLK_MUX);
    syscon_set_sysclk_src(CLK_XTAL, __XTAL);
    syscon_set_ahb_clk(__AHB_CLK);
    syscon_set_apb_clk(__APB_CLK);
}
コード例 #2
0
void sleep_timer_set(uint32_t time)
{
    // TBC
    
    // ble interrupt mask
    *(volatile uint32_t *)(0x2f00000c) |= 0x4;
    
    // correction sleep time
    *(volatile uint32_t *)(0x2f000030) = (*(volatile uint32_t *)(0x2f000030) & (~0x8)) | 0x8;

    // sleep time
    *(volatile uint32_t *)(0x2f000034) =  time;
    
    // enable sleep
    *(volatile uint32_t *)(0x2f000030) = (*(volatile uint32_t *)(0x2f000030) & (~0x4)) | 0x4;

    // OSC SLEEP EN
    *(volatile uint32_t *)(0x2f000030) = (*(volatile uint32_t *)(0x2f000030) & (~0x3)) | 0x1;

    //delay(5000);
    while (syscon_GetBLESR(QN_SYSCON) & SYSCON_MASK_OSC_EN);
}
コード例 #3
0
ファイル: sleep.c プロジェクト: haby77/BLE-passthrough
/**
 ****************************************************************************************
 * @brief  Enable sleep mode
 * @param[in]    mode           sleep mode
 * @param[in]    iconfig        wakeup interrupt config
 * @param[in]    callback       callback after wakeup
 * @description
 *  This function is used to set MCU into sleep mode, before enter sleep, wakeup source should be set.
 *****************************************************************************************
 */
void enter_sleep(enum SLEEP_MODE mode, uint32_t iconfig, void (*callback)(void))
{
    if (mode == SLEEP_CPU_CLK_OFF) {
        // --------------------------------------------
        // cpu clock disable
        // --------------------------------------------

        // Ensure we use deep SLEEP - SLEEPDEEP should be set
        // SCR[2] = SLEEPDEEP
        SCB->SCR |= (1UL << 2);
        // set pd state to deep gating
        syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_PD_STATE|SYSCON_MASK_PMUENABLE, MASK_DISABLE);

        GLOBAL_INT_DISABLE();
#if SLEEP_CONFIG_EN == TRUE
        NVIC->ISER[0] = iconfig;
#endif
        // Wait For Interrupt
        __WFI();  // Enter sleep mode

        // Wakeup when interrupt is triggered
        GLOBAL_INT_RESTORE();

        // TODO
    }
    else if ((mode == SLEEP_NORMAL) || (mode == SLEEP_DEEP)) {
        
#if QN_LOW_POWER_MODE_EN==TRUE
        enter_low_power_mode(0);

        // --------------------------------------------
        // cpu clock disable
        // --------------------------------------------

        // Ensure we use deep SLEEP - SLEEPDEEP should be set
        // SCR[2] = SLEEPDEEP
        SCB->SCR |= (1UL << 2);

#else
        
        // --------------------------------------------
        // sleep or deep sleep
        // --------------------------------------------
#ifdef BLE_PRJ
        // Save configuration before power down
        save_ble_setting();
#endif

#if (defined(QN_9020_B1) && QN_PMU_VOLTAGE)
        // Switch off REF PLL power
        syscon_SetPGCR1WithMask(QN_SYSCON, SYSCON_MASK_DIS_REF_PLL, MASK_ENABLE);
#endif
        
        // switch to internal 20MHz
        syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_CLK_MUX, CLK_INT_20M<<SYSCON_POS_CLK_MUX);

        if(mode == SLEEP_NORMAL)
        {
#if (QN_DEEP_SLEEP_EN)
            sleep_env.deep_sleep = false;
#endif
            // power down all module in sleep except 32K and retention memory
            syscon_SetPGCR0WithMask(QN_SYSCON, sleep_env.retention_modules|0x00000001, 0x00000001);
        }
        else
        {
#if (QN_DEEP_SLEEP_EN)
            sleep_env.deep_sleep = true;
#endif
            // power down all module in deep sleep except retention memory
#if (defined(QN_9020_B2) || defined(QN_9020_B1))
            syscon_SetPGCR0WithMask(QN_SYSCON, 0xF7FFFCFF, 0xFFFFFC01|~sleep_env.retention_modules);
#elif defined(QN_9020_B0)
            syscon_SetPGCR0WithMask(QN_SYSCON, 0xFFFFFCFF, 0xFFFFFC01|~sleep_env.retention_modules);
#endif
        }

#if (defined(QN_9020_B0) && QN_PMU_VOLTAGE)
        syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_AHB_DIV_BYPASS|SYSCON_MASK_AHB_DIVIDER, 
                                              (0xf<<SYSCON_POS_AHB_DIVIDER));
#endif

        // Ensure we use deep SLEEP - SLEEPDEEP should be set
        // SCR[2] = SLEEPDEEP
        SCB->SCR |= (1UL << 2);
        // set pd state to sleep
#if !QN_PMU_VOLTAGE
        syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_PD_STATE|SYSCON_MASK_DVDD12_PMU_SET|SYSCON_MASK_PMUENABLE, MASK_ENABLE);
#else
        syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_PD_STATE|SYSCON_MASK_PMUENABLE, MASK_ENABLE);
#endif

        syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_VREG12_A|SYSCON_MASK_VREG12_D|SYSCON_MASK_DVDD12_SW_EN, 
                                              (0x0 << SYSCON_POS_VREG12_A)|(0x0 << SYSCON_POS_VREG12_D));

#endif // QN_LOW_POWER_MODE_EN==TRUE

#if SLEEP_CONFIG_EN == TRUE
        NVIC->ICPR[0] = 0x00000020;  // clear OSC_EN pending flag
        NVIC->ISER[0] = iconfig;
#endif
        // Wait For Interrupt
        __WFI();  // Enter sleep mode
        // Wakeup when sleep timer, comparator or gpio is triggered

        // Disable interrupt in the wakeup procedure.
        NVIC->ICER[0] = iconfig;

#if QN_LOW_POWER_MODE_EN==TRUE
#ifdef BLE_PRJ
        restore_from_low_power_mode(NULL);
#else
        restore_from_low_power_mode(callback);
#endif
#else

        // 1.2V
        syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_VREG12_A|SYSCON_MASK_VREG12_D|SYSCON_MASK_DVDD12_SW_EN, 
                                              (0x1 << SYSCON_POS_VREG12_A)|(0x0 << SYSCON_POS_VREG12_D)|SYSCON_MASK_DVDD12_SW_EN);

#if (defined(QN_9020_B0) && QN_PMU_VOLTAGE)
        syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_AHB_DIV_BYPASS, MASK_ENABLE);
#endif
        syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_PD_STATE|SYSCON_MASK_DVDD12_PMU_SET, MASK_DISABLE);

#if SLEEP_CALLBACK_EN == TRUE
        if (callback != NULL) {
            callback();
        }
#endif

#if (defined(QN_9020_B0) && QN_PMU_VOLTAGE)
        syscon_set_ahb_clk(__AHB_CLK);
#endif

        // 16MHz/32MHz XTAL is ready
        while (!(syscon_GetBLESR(QN_SYSCON) & SYSCON_MASK_CLK_RDY))
        {
            // XTAL shall be ready before BLE wakeup
            if(check_ble_wakeup())
            {
                // In this case XTAL wakeup duration is larger than setting.
                // The parameter 'Oscillator wake-up time' in the NVDS should be revised.
#if (QN_DBG_INFO)
                set_dbg_info(QN_DBG_INFO_XTAL_WAKEUP_DURATION);
#endif
            }
        }
        syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_CLK_MUX, CLK_XTAL<<SYSCON_POS_CLK_MUX);

#endif // QN_LOW_POWER_MODE_EN==TRUE

#if ((defined(QN_9020_B2) || defined(QN_9020_B1)) && defined(BLE_PRJ))
        sleep_post_process();
#endif
    }
}