- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
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()
{
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
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);
}

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page