Exemple #1
0
static int app_32k_xtal_wakeup_timer(ke_msg_id_t const msgid, void const *param,
                               ke_task_id_t const dest_id, ke_task_id_t const src_id)
{
    // disable schmitt trigger in 32.768KHz buffer
    syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_X32SMT_EN, MASK_DISABLE);
    syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_X32ICTRL, 16);
    
    // switch 32k RCO to 32k XTAL
    syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_SEL_CLK_32K, MASK_DISABLE);
    syscon_SetPGCR1WithMask(QN_SYSCON, SYSCON_MASK_DIS_RCO, MASK_ENABLE);

    // allow ble sleep
    enable_ble_sleep(true);

    return (KE_MSG_CONSUMED);
}
Exemple #2
0
/**
 ****************************************************************************************
 * @brief  Wakeup 32k XTAL
 * @description
 *  This function will be called after waking up from deep sleep mode.
 *****************************************************************************************
 */
void wakeup_32k_xtal_switch_clk(void)
{
    if(sleep_env.deep_sleep)
    {
        // prevent ble sleep
        enable_ble_sleep(false);

        // ensable schmitt trigger in 32.768KHz buffer
        syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_X32SMT_EN, MASK_ENABLE);
        // Set 32.768KHz xtal higher current, that can let the 32k xtal stable fastly (decrease stable time).
        syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_X32ICTRL, 32);
        
        // switch to 32k RCO
        syscon_SetPGCR1WithMask(QN_SYSCON, SYSCON_MASK_DIS_RCO, MASK_DISABLE);
#if (QN_PMU_VOLTAGE)
        delay(10);
#else
        delay(300);
#endif
        syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_SEL_CLK_32K, MASK_ENABLE);
    }
}
Exemple #3
0
/**
 ****************************************************************************************
 * @brief  Setup the microcontroller system.
 *
 *  Initialize the system clock and pins.
 *****************************************************************************************
 */
void SystemInit(void)
{
    /*
     **************************
     * Sub module clock setting
     **************************
     */
    syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_DVDD12_SW_EN, MASK_ENABLE);
    syscon_set_sysclk_src(CLK_XTAL, __XTAL);
    
#if __XTAL == XTAL_32MHz
    calibration_init(XTAL_32M);
#else
    calibration_init(XTAL_16M);
#endif
    ref_pll_calibration();

    clk32k_enable(__32K_TYPE);
#if QN_32K_RCO
    rco_calibration();
#endif

    // Reset SPI1 module(since the default register value was changed in bootloader)
    syscon_SetCRSS(QN_SYSCON, SYSCON_MASK_USART1_RST);
    syscon_SetCRSC(QN_SYSCON, SYSCON_MASK_USART1_RST);
    
    /*
        Disable all peripheral clock, will be enabled in the driver initilization.
        The next function performs the equivalent effect of a collection of these functions.
    
        timer_clock_off(QN_TIMER0);
        timer_clock_off(QN_TIMER1);
        timer_clock_off(QN_TIMER2);
        timer_clock_off(QN_TIMER3);
        uart_clock_off(QN_UART0);
        uart_clock_off(QN_UART1);
        spi_clock_off(QN_SPI0);
        spi_clock_off(QN_SPI1);
        flash_clock_off();
        gpio_clock_off();
        adc_clock_off();
        dma_clock_off();
        pwm_clock_off();
    */
    syscon_SetCRSS(QN_SYSCON, SYSCON_MASK_GATING_TIMER0
                            | SYSCON_MASK_GATING_TIMER1
                            | SYSCON_MASK_GATING_TIMER2
                            | SYSCON_MASK_GATING_TIMER3
                            | SYSCON_MASK_GATING_UART0
                            | SYSCON_MASK_GATING_UART1
                            | SYSCON_MASK_GATING_SPI0
                            | SYSCON_MASK_GATING_SPI1
                            | SYSCON_MASK_GATING_SPI_AHB
                            | SYSCON_MASK_GATING_GPIO
                            | SYSCON_MASK_GATING_ADC
                            | SYSCON_MASK_GATING_DMA
                            | SYSCON_MASK_GATING_PWM);
    
    // calibration changed system clock setting
    // Configure sytem clock.  
    syscon_set_sysclk_src(CLK_XTAL, __XTAL);
    syscon_set_ahb_clk(__AHB_CLK);
    syscon_set_apb_clk(__APB_CLK);
    syscon_set_ble_clk(__BLE_CLK);
    syscon_set_timer_clk(__TIMER_CLK);
    syscon_set_usart_clk((uint32_t)QN_UART0, __USART_CLK);
    syscon_set_usart_clk((uint32_t)QN_UART1, __USART_CLK);  
    

    /*
     **************************
     * IO configuration
     **************************
     */

    SystemIOCfg();

    /*
     **************************
     * Peripheral setting
     **************************
     */

}
Exemple #4
0
/**
 ****************************************************************************************
 * @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
    }
}
Exemple #5
0
/**
 ****************************************************************************************
 * @brief  Setup the microcontroller system.
 *
 *  Initialize the system clock and pins.
 *****************************************************************************************
 */
void SystemInit(void)
{
    /*
     **************************
     * Sub module clock setting
     **************************
     */
    syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_DVDD12_SW_EN, MASK_ENABLE);
    syscon_set_sysclk_src(CLK_XTAL, __XTAL);
    
#if __XTAL == XTAL_32MHz
    calibration_init(XTAL_32M);
#else
    calibration_init(XTAL_16M);
#endif
    ref_pll_calibration();

    clk32k_enable(__32K_TYPE);
#if QN_32K_RCO
    rco_calibration();
#endif

    // Disable all peripheral clock, will be enabled in the driver initilization.
    timer_clock_off(QN_TIMER0);
    timer_clock_off(QN_TIMER1);
    timer_clock_off(QN_TIMER2);
    timer_clock_off(QN_TIMER3);
    uart_clock_off(QN_UART0);
    uart_clock_off(QN_UART1);
    spi_clock_off(QN_SPI0);
    usart_reset((uint32_t) QN_SPI1);
    spi_clock_off(QN_SPI1);
    flash_clock_off();
    gpio_clock_off();
    adc_clock_off();
    dma_clock_off();
    pwm_clock_off();
    
    // calibration will change system clock setting
    // Configure sytem clock.  
    syscon_set_sysclk_src(CLK_XTAL, __XTAL);
    syscon_set_ahb_clk(__AHB_CLK);
    syscon_set_apb_clk(__APB_CLK);
    syscon_set_ble_clk(__BLE_CLK);
    syscon_set_timer_clk(__TIMER_CLK);
    syscon_set_usart_clk((uint32_t)QN_UART0, __USART_CLK);
    syscon_set_usart_clk((uint32_t)QN_UART1, __USART_CLK);  


    /*
     **************************
     * IO configuration
     **************************
     */

    SystemIOCfg();

    /*
     **************************
     * Peripheral setting
     **************************
     */

}
int main (void) 
{
    
    SystemInit();
    
#if 0
    if (0x00000004 & inp32(0x40000038)) {
        outp32(0x40000038, 0x80000000);
    }
    else {
        Led_flash();
        while(1);
    }
#endif
    
    /* Initialize GPIO */
    gpio_init(cb_gpio);
    
#if TEST_SLEEP_NORMAL == TRUE
    // --------------------------------------------
    // sleep wakeup
    // --------------------------------------------
    
    //set all pin to gpio
    syscon_SetPMCR0(QN_SYSCON, 0x00000000);
    syscon_SetPMCR1(QN_SYSCON, 0x00000000);
    //set all gpio input
    gpio_set_direction_field(GPIO_PIN_ALL, GPIO_INPUT); 
    gpio_write_pin_field(GPIO_PIN_ALL, (uint32_t)GPIO_HIGH);    
    // pin pull ( 00 : High-Z,  01 : Pull-down,  10 : Pull-up,  11 : Reserved )
    syscon_SetPPCR0(QN_SYSCON, 0xAAAA5AAA); // SWD pull-down save 20uA
    syscon_SetPPCR1(QN_SYSCON, 0x2AAAAAAA);  
    
    // power down BUCK needed
    syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_BUCK_BYPASS|SYSCON_MASK_BUCK_DPD, MASK_ENABLE);    
    // power down Flash
    syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_FLASH_VCC_EN, MASK_DISABLE);
    // enable dbg power down
    syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_DBGPMUENABLE, MASK_ENABLE);
    // dis sar adc buffer
    syscon_SetPGCR1WithMask(QN_SYSCON, SYSCON_MASK_DIS_SAR_BUF, MASK_ENABLE);
    Led_flash();

    do {
        delay(10);
    } while (gpio_read_pin(GPIO_P14) == GPIO_HIGH);
    
    sleep_init();
    wakeup_by_sleep_timer(__32K_TYPE);
    wakeup_by_gpio(GPIO_P15, GPIO_WKUP_BY_LOW);
    
    do {
        gpio_set_direction(GPIO_P01, GPIO_INPUT);
        //enter_sleep(SLEEP_NORMAL, WAKEUP_BY_GPIO, Led_flash);
        if (wakeup_from_sleeptimer) {
            sleep_timer_set(32000);
            wakeup_from_sleeptimer = 0;
#if QN_32K_RCO == TRUE
            clock_32k_correction_enable(clock_32k_correction_cb);
#endif
        }

#if QN_32K_RCO == TRUE
        if (gpio_sleep_allowed() && !dev_get_bf())
#else
        if (gpio_sleep_allowed())
#endif
        enter_sleep(SLEEP_NORMAL, WAKEUP_BY_OSC_EN|WAKEUP_BY_GPIO, Led_flash);

    } while(1);
#endif
    
#if TEST_SLEEP_DEEP == TRUE
    // --------------------------------------------
    // deep sleep wakeup
    // --------------------------------------------
    
    //set all pin to gpio
    syscon_SetPMCR0(QN_SYSCON, 0x00000000);
    syscon_SetPMCR1(QN_SYSCON, 0x00000000);
    //set all gpio input
    gpio_set_direction_field(GPIO_PIN_ALL, (uint32_t)GPIO_INPUT); 
    gpio_write_pin_field(GPIO_PIN_ALL, (uint32_t)GPIO_HIGH);
    // pin pull ( 00 : High-Z,  01 : Pull-down,  10 : Pull-up,  11 : Reserved )
    syscon_SetPPCR0(QN_SYSCON, 0xAAAA5AAA); // SWD pull-down save 20uA
    syscon_SetPPCR1(QN_SYSCON, 0x2AAAAAAA);        
    
    // power down BUCK needed
    syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_BUCK_BYPASS|SYSCON_MASK_BUCK_DPD, MASK_ENABLE);
    // power down Flash
    syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_FLASH_VCC_EN, MASK_DISABLE);
    // enable dbg power down
    syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_DBGPMUENABLE, MASK_ENABLE);
    // dis sar adc buffer
    syscon_SetPGCR1WithMask(QN_SYSCON, SYSCON_MASK_DIS_SAR_BUF, MASK_ENABLE);
    Led_flash();
    
    do {
        delay(10);
    } while (gpio_read_pin(GPIO_P14) == GPIO_HIGH);
    
    sleep_init();
    
    do {
        gpio_set_direction(GPIO_P01, GPIO_INPUT);
        wakeup_by_gpio(GPIO_P15, GPIO_WKUP_BY_CHANGE);
        enter_sleep(SLEEP_DEEP, WAKEUP_BY_GPIO, Led_flash);
                
    } while(1);
#endif

#if TEST_SLEEP_CPU_CLK_OFF == TRUE
    // --------------------------------------------
    // clock gating 
    // --------------------------------------------
    // Set timer 0 wakeup
    timer_init(QN_TIMER0, NULL);
    timer_config(QN_TIMER0, TIMER_PSCAL_DIV, TIMER_COUNT_MS(1000, TIMER_PSCAL_DIV));
    timer_enable(QN_TIMER0, MASK_ENABLE);  

    sleep_init();
    
    do {

        enter_sleep(SLEEP_CPU_CLK_OFF, WAKEUP_BY_TIMER0, NULL);
        Led_flash();
    
    }
    while(1);
#endif
    
    
}