Community
cancel
Showing results for 
Search instead for 
Did you mean: 
PPati4
Novice
970 Views

Intel Quark D2000: Delay function not working after wake up

Hello, I want to know if we have to separately restore the system clock after microcontroller wake up from sleep? If yes, the How?

clk_sys_udelay(DELAY) function not providing delay after system wake- up.

0 Kudos
4 Replies
Pedro_M_Intel
Employee
56 Views

Hello Pratik__PP,

Could you please provide us a simple example/code of when this behavior is happening? We would like to see what is going on the board at the time and to replicate the behavior.

Peter.

PPati4
Novice
56 Views

Hello Peter, kindly refer the code below. Here the system will come out of sleep after 30sec. Kindly observe the delay provided for LED blinking after wake-up.

# include "qm_common.h"

# include "qm_power.h"

# include "qm_rtc.h"

# include "qm_interrupt.h"

# include "qm_soc_regs.h"

# include "qm_gpio.h"

# include "qm_scss.h"

# define LED_BIT 24 /*LED*/

# define PIN_INTR 2 /*Switch on D2000 Dev Board*/

# define DELAY 300000UL

static void rtc_example_callback();

static void gpio_example_callback();

static qm_gpio_port_config_t cfg1;

volatile unsigned char flag = 0;

int main(void)

{

qm_rtc_config_t rtc_cfg;

cfg1.direction = BIT(LED_BIT);

qm_gpio_set_config(QM_GPIO_0, &cfg1);

clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);

/* Initialize RTC configuration. */

rtc_cfg.init_val = 0;

rtc_cfg.alarm_en = 1;

rtc_cfg.alarm_val = QM_RTC_ALARM_MINUTE/2;

rtc_cfg.callback = rtc_example_callback;

qm_gpio_set_pin(QM_GPIO_0, LED_BIT);

clk_sys_udelay(DELAY);

clk_sys_udelay(DELAY);

clk_sys_udelay(DELAY);

qm_gpio_clear_pin(QM_GPIO_0, LED_BIT);

clk_sys_udelay(DELAY);

clk_sys_udelay(DELAY);

clk_sys_udelay(DELAY);

/* Set alarm for 30sec from now. */

qm_rtc_set_alarm(QM_RTC_0,QM_RTC_ALARM_MINUTE/2);

qm_gpio_set_pin(QM_GPIO_0, LED_BIT);

qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0);

qm_rtc_set_config(QM_RTC_0, &rtc_cfg);

soc_sleep();

while(1)

{

qm_gpio_clear_pin(QM_GPIO_0, LED_BIT);

clk_sys_udelay(DELAY);

clk_sys_udelay(DELAY);

clk_sys_udelay(DELAY);

qm_gpio_set_pin(QM_GPIO_0, LED_BIT);

clk_sys_udelay(DELAY);

clk_sys_udelay(DELAY);

clk_sys_udelay(DELAY);

}

return 0;

}

void rtc_example_callback()

{

}

Pedro_M_Intel
Employee
56 Views

Hello Pratik_PP,

I have successfully replicated the behavior you described. I am currently debugging the code to see if I can find out the reason why this is happening. I will post any updates I have as soon as I can.

Peter.

PPati4
Novice
56 Views

Hey Peter, I think the problem lies in the soc_sleep() function and the solution is found.

Before sleep the system clock is set to 512KHz the same clock frequency is restored after system wake-up in the recovery section of sleep function after halt. It should actually be set back to 32MHz.

Kindly check out this edited soc_sleep() wherein I restore the system clock to 32MHz. The code provides correct delay after wake- up.

void soc_sleep(void)

{

/* Variables to save register values. */

qm_ac_config_t ac_cfg;

uint32_t ac_power_save;

uint32_t clk_gate_save = QM_SCSS_CCU->ccu_periph_clk_gate_ctl;

uint32_t sys_clk_ctl_save = QM_SCSS_CCU->ccu_sys_clk_ctl;

uint32_t osc0_cfg_save = QM_SCSS_CCU->osc0_cfg1;

uint32_t adc_mode_save = QM_ADC->adc_op_mode;

/* Clear any pending interrupts. */

clear_all_pending_interrupts();

qm_adc_set_mode(QM_ADC_0, QM_ADC_MODE_PWR_DOWN);

/* Turn off high power comparators. */

qm_ac_get_config(&ac_cfg);

ac_power_save = ac_cfg.power;

ac_cfg.power &= QM_AC_HP_COMPARATORS_MASK;

qm_ac_set_config(&ac_cfg);

/*

* Program WAKE_MASK.WAKE_MASK[31:0],

* CCU_LP_CLK_CTL.WAKE_PROBE_MODE_MASK registers identical to Interrupt

* Mask registers.

*/

QM_SCSS_CCU->ccu_lp_clk_ctl &= ~QM_WAKE_PROBE_MODE_MASK;

/*

* Ensure that powering down of oscillators is delayed by hardware until

* core executes HALT instruction.

*/

/* HYB_OSC_PD_LATCH_EN = 0, RTC_OSC_PD_LATCH_EN=0 */

QM_SCSS_CCU->ccu_lp_clk_ctl &=

~(QM_HYB_OSC_PD_LATCH_EN | QM_RTC_OSC_PD_LATCH_EN);

/* Ensure that at exit, hardware will switch system clock to Hybrid

* oscillator clock so as to minimize exit latency by running at higher

* frequency than RTC clock.

*/

/* CCU_LP_CLK_CTL.CCU_EXIT_TO_HYBOSC */

QM_SCSS_CCU->ccu_lp_clk_ctl |= QM_CCU_EXIT_TO_HYBOSC;

/* Power down hybrid oscillator after HALT instruction is executed. */

QM_SCSS_CCU->osc0_cfg1 |= QM_OSC0_PD;

/*

* Only the following peripherals can be used as a wakeup source:

* - GPIO Interrupts

* - AON timers

* - RTC

* - low power comparators

*/

clk_periph_disable(

CLK_PERIPH_I2C_M0 | CLK_PERIPH_SPI_S | CLK_PERIPH_SPI_M0 |CLK_PERIPH_WDT_REGISTER |CLK_PERIPH_PWM_REGISTER |

CLK_PERIPH_SPI_M0_REGISTER | CLK_PERIPH_SPI_S_REGISTER |CLK_PERIPH_UARTA_REGISTER | CLK_PERIPH_UARTB_REGISTER |CLK_PERIPH_I2C_M0_REGISTER);

/* Set system clock source to hyb osc, 4 MHz, scaled to 512 kHz. */

clk_sys_set_mode(CLK_SYS_HYB_OSC_4MHZ, CLK_SYS_DIV_8);

/* Set the RAR to retention mode. */

rar_set_mode(RAR_RETENTION);

/*

* If wake source is any of AON Timer, RTC, GPIO interrupt, program

* CCU_SYS_CLK_CTL.CCU_SYS_CLK_SEL to RTC Oscillator.

*/

/* Enter SoC sleep mode. */

cpu_halt();

/* From here on, restore the SoC to an active state. */

/* Set the RAR to normal mode. */

rar_set_mode(RAR_NORMAL);

/* Restore all previous values. */

QM_SCSS_CCU->ccu_sys_clk_ctl = sys_clk_ctl_save;

/* Re-apply clock divider values. DIV_EN must go 0 -> 1. */

QM_SCSS_CCU->ccu_sys_clk_ctl &=

~(QM_CCU_SYS_CLK_DIV_EN | QM_CCU_RTC_CLK_DIV_EN);

QM_SCSS_CCU->ccu_sys_clk_ctl |=

QM_CCU_SYS_CLK_DIV_EN | QM_CCU_RTC_CLK_DIV_EN;

/* Wait for the XTAL or SI oscillator to stabilise. */

while (!(QM_SCSS_CCU->osc0_stat1 &

(QM_OSC0_LOCK_SI | QM_OSC0_LOCK_XTAL))) {

};

/* Restore original clocking, ADC, analog comparator states. */

QM_SCSS_CCU->osc0_cfg1 = osc0_cfg_save;

QM_SCSS_CCU->ccu_periph_clk_gate_ctl = clk_gate_save;

ac_cfg.power = ac_power_save;

qm_ac_set_config(&ac_cfg);

QM_ADC->adc_op_mode = adc_mode_save;

clk_sys_set_mode(CLK_SYS_HYB_OSC_32MHZ, CLK_SYS_DIV_1);

}