int main(void) { qm_rtc_config_t rtc_cfg; unsigned int count = 0; /* loop_max : Maximum number of iterations. * A value of 50 will run the application for roughly 30s. */ const unsigned int loop_max = 50; gpio_init(); pin_mux_setup(); gpio_set_out(BOARD_LED_PIN, 0); /* Configure the onboard LED pin. */ /* Clear Screen. */ QM_PUTS("Starting: Power Profiler"); QM_PUTS("Low power mode example."); QM_PRINTF("Increment = %d\n", QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1)); clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK); /* Initialise RTC configuration: Run, but don't interrupt. */ rtc_cfg.init_val = 0; rtc_cfg.alarm_en = 0; rtc_cfg.alarm_val = QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1); rtc_cfg.callback = rtc_example_callback; rtc_cfg.prescaler = CLK_RTC_DIV_1; qm_rtc_set_config(QM_RTC_0, &rtc_cfg); QM_IR_UNMASK_INT(QM_IRQ_RTC_0_INT); QM_IRQ_REQUEST(QM_IRQ_RTC_0_INT, qm_rtc_0_isr); #if (!QM_SENSOR) test_clock_rates(); #endif /* Enable the RTC Interrupt. */ rtc_cfg.alarm_en = 1; qm_rtc_set_config(QM_RTC_0, &rtc_cfg); count = 0; while (++count < loop_max) { QM_PRINTF("\nC:%d R:%d => ", count, rtc_tick); slow_mode_test(); halt_test(); core_sleep_test(); /* TODO : Enable soc_sleep test for c1000. */ soc_sleep_test(); /* TODO : Enable soc_deep_sleep test for d2000 and c1000. */ soc_deep_sleep_test(); } SOC_WATCH_TRIGGER_FLUSH(); QM_PUTS("Finished: Power Profiler"); return 0; }
void start_rtc() { uint32_t aonc_start; qm_rtc_config_t cfg; /* Make sure RTC is enabled during sleep. */ QM_SCSS_PMU->slp_cfg &= ~QM_SCSS_SLP_CFG_RTC_DIS; cfg.init_val = 0; cfg.alarm_en = true; cfg.alarm_val = RTC_ALARM_SECONDS(2); cfg.prescaler = RTC_PRESCALER; cfg.callback = NULL; cfg.callback_data = NULL; QM_IR_UNMASK_INT(QM_IRQ_RTC_0_INT); QM_IRQ_REQUEST(QM_IRQ_RTC_0_INT, qm_rtc_0_isr); qm_rtc_set_config(QM_RTC_0, &cfg); /* * The RTC clock resides in a different clock domain * to the system clock. * It takes 3-4 RTC ticks for a system clock write to propagate * to the RTC domain. * If an entry to sleep is initiated without waiting for the * transaction to complete the SOC will not wake from sleep. */ aonc_start = QM_AONC[0]->aonc_cnt; while (QM_AONC[0]->aonc_cnt - aonc_start < RTC_SYNC_CLK_COUNT) { } }
int main(void) { qm_rtc_config_t rtc_cfg; unsigned int count = 0; /* Maximum number of 3-second iterations. */ const unsigned int loop_max = 5; gpio_init(); gpio_set_out(BOARD_LED_PIN, 0); /* Configure the onboard LED pin. */ /* Clear Screen. */ QM_PUTS("Starting: Power Profiler"); QM_PUTS("Low power mode example."); QM_PRINTF("Increment = %d\n", QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1)); clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK); /* Initialise RTC configuration: Run, but don't interrupt. */ rtc_cfg.init_val = 0; rtc_cfg.alarm_en = 0; rtc_cfg.alarm_val = QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1); rtc_cfg.callback = rtc_example_callback; rtc_cfg.prescaler = CLK_RTC_DIV_1; qm_rtc_set_config(QM_RTC_0, &rtc_cfg); qm_irq_request(QM_IRQ_RTC_0_INT, qm_rtc_0_isr); test_clock_rates(); /* Enable the RTC Interrupt. */ rtc_cfg.alarm_en = 1; qm_rtc_set_config(QM_RTC_0, &rtc_cfg); count = 0; while (++count < loop_max) { QM_PRINTF("\nC:%d R:%d => ", count, rtc_tick); slow_mode_test(); halt_test(); sleep_test(); #if DEEP_SLEEP deep_sleep_test(); #endif } QM_PUTS("Finished: Power Profiler"); return 0; }
/* Receive one byte */ int xmodem_io_getc(uint8_t *ch) { enum rx_state retv; /* Set up timeout timer */ rtc_cfg.alarm_en = true; qm_rtc_set_config(QM_RTC_0, &rtc_cfg); /* Reseting the state and read byte */ xmodem_io_rx_state = STATE_WAITING; qm_uart_irq_read(DM_CONFIG_UART, &uart_transfer); /* Wait for UART interruption or RTC timeout callback */ while (retv = xmodem_io_rx_state, retv == STATE_WAITING) { ; /* Busy wait until one of the callbacks is called */ } switch (retv) { case STATE_TIMEOUT: qm_uart_irq_read_terminate(DM_CONFIG_UART); break; case STATE_UART_RX_DONE: /* Got byte */ *ch = in_byte; break; default: /** * Handle STATE_UART_ERROR case which can happen on UART read * error, and STATE_WAITING which is an impossible case */ break; } /* Disable timer alarm */ rtc_cfg.alarm_en = false; qm_rtc_set_config(QM_RTC_0, &rtc_cfg); return retv; }
static int rtc_qmsi_set_alarm(struct device *dev, u8_t chan_id, const struct counter_alarm_cfg *alarm_cfg) { qm_rtc_config_t qm_cfg; int result = 0; qm_cfg.init_val = 0; qm_cfg.alarm_en = 1; qm_cfg.alarm_val = alarm_cfg->ticks; user_cb = alarm_cfg->callback; /* Casting callback type due different input parameter from QMSI * compared aganst the Zephyr callback from void cb(struct device *dev) * to void cb(void *) */ qm_cfg.callback = rtc_callback; qm_cfg.callback_data = (void *)alarm_cfg; /* Set prescaler value. Ideally, the divider should come from struct * rtc_config instead. It's safe to use RTC_DIVIDER here for now since * values defined by clk_rtc_div and by QMSI's clk_rtc_div_t match for * both D2000 and SE. */ qm_cfg.prescaler = (clk_rtc_div_t)CONFIG_RTC_PRESCALER - 1; if (IS_ENABLED(CONFIG_RTC_QMSI_API_REENTRANCY)) { k_sem_take(RP_GET(dev), K_FOREVER); } if (qm_rtc_set_config(QM_RTC_0, &qm_cfg)) { result = -EIO; } if (IS_ENABLED(CONFIG_RTC_QMSI_API_REENTRANCY)) { k_sem_give(RP_GET(dev)); } k_busy_wait(60); qm_rtc_set_alarm(QM_RTC_0, alarm_cfg->ticks); return result; }
/*-------------------------------------------------------------------------*/ void xmodem_io_uart_init() { /* Pinmux for UART_x */ qm_pmux_select(DM_COMM_UART_PIN_TX_ID, DM_COMM_UART_PIN_TX_FN); qm_pmux_select(DM_COMM_UART_PIN_RX_ID, DM_COMM_UART_PIN_RX_FN); qm_pmux_input_en(DM_COMM_UART_PIN_RX_ID, true); /* Enable UART and RTC clocks */ clk_periph_enable(DM_COMM_UART_CLK | CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK); /* Setup UART */ qm_uart_set_config(DM_CONFIG_UART, &uart_config); /* Request IRQ for UART */ dm_comm_irq_request(); /* Set up timeout timer (RTC) */ qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0); qm_rtc_set_config(QM_RTC_0, &rtc_cfg); }
int main(void) { qm_rtc_config_t rtc; QM_PUTS("Accelerometer example app\n"); rtc.init_val = 0; rtc.alarm_en = true; rtc.alarm_val = ALARM; rtc.callback = print_accel_callback; qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0); clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK); bmc150_init(BMC150_J14_POS_0); bmc150_set_accel_mode(BMC150_MODE_2G); bmc150_set_bandwidth(BMC150_BANDWIDTH_64MS); qm_rtc_set_config(QM_RTC_0, &rtc); return 0; }
/* Low power app example */ int main(void) { /* Setup the RTC to get out of sleep mode. deep sleep will require an */ /* analog comparator interrupt to wake up the system. */ /* Variables */ uint32_t pmux_sel_save[2], pmux_in_en_save, pmux_pullup_save; qm_ac_config_t ac_cfg; qm_rtc_config_t rtc_cfg; QM_PUTS("Low power mode example."); clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK); /* Initialise RTC configuration. */ rtc_cfg.init_val = 0; rtc_cfg.alarm_en = 1; rtc_cfg.alarm_val = QM_RTC_ALARM_SECOND; rtc_cfg.callback = rtc_example_callback; qm_rtc_set_config(QM_RTC_0, &rtc_cfg); qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0); QM_PUTS("CPU Halt."); /* Halt the CPU, RTC alarm will wake me up. */ cpu_halt(); QM_PUTS("CPU Halt wakeup."); /* Set another alarm one minute from now. */ qm_rtc_set_alarm(QM_RTC_0, QM_RTC[QM_RTC_0].rtc_ccvr + QM_RTC_ALARM_SECOND); QM_PUTS("Go to sleep."); /* Go to sleep, RTC will wake me up. */ soc_sleep(); QM_PUTS("Wake up from sleep."); /* Physical step at this stage to raise the V on the comparator pin. */ /* Go to deep sleep, a comparator should wake me up. */ QM_PUTS("Go to deep sleep."); ac_cfg.reference = BIT(WAKEUP_COMPARATOR_PIN); /* Ref internal voltage */ ac_cfg.polarity = 0x0; /* Fire if greater than ref (high level) */ ac_cfg.power = BIT(WAKEUP_COMPARATOR_PIN); /* Normal operation mode */ ac_cfg.int_en = BIT(WAKEUP_COMPARATOR_PIN); /* Enable comparator */ ac_cfg.callback = ac_example_callback; qm_ac_set_config(&ac_cfg); qm_irq_request(QM_IRQ_AC, qm_ac_isr); /* * Comparator pin will fire an interrupt when the input voltage is * greater than the reference voltage (0.95V). */ /* * In order to minimise power, pmux_sel must be set to 0, input enable * must be cleared for any pins not expecting to be used to wake the * SoC from deep sleep mode, in this example we are using AC 6. */ pmux_sel_save[0] = QM_SCSS_PMUX->pmux_sel[0]; pmux_sel_save[1] = QM_SCSS_PMUX->pmux_sel[1]; pmux_in_en_save = QM_SCSS_PMUX->pmux_in_en[0]; pmux_pullup_save = QM_SCSS_PMUX->pmux_pullup[0]; QM_SCSS_PMUX->pmux_sel[0] = QM_SCSS_PMUX->pmux_sel[1] = 0; QM_SCSS_PMUX->pmux_in_en[0] = BIT(WAKEUP_COMPARATOR_PIN); QM_SCSS_PMUX->pmux_pullup[0] = 0; /* Mux out comparator */ qm_pmux_select(QM_PIN_ID_6, QM_PMUX_FN_1); qm_pmux_input_en(QM_PIN_ID_6, true); soc_deep_sleep(); /* Restore previous pinmuxing settings. */ QM_SCSS_PMUX->pmux_sel[0] = pmux_sel_save[0]; QM_SCSS_PMUX->pmux_sel[1] = pmux_sel_save[1]; QM_SCSS_PMUX->pmux_in_en[0] = pmux_in_en_save; QM_SCSS_PMUX->pmux_pullup[0] = pmux_pullup_save; QM_PUTS("Wake up from deep sleep."); return 0; }
int main(void) { qm_rtc_config_t rtc_cfg; uint32_t aonc_start; uint32_t rtc_trigger; /* Initialise RTC configuration. */ rtc_cfg.init_val = 0; /* Set initial value to 0. */ rtc_cfg.alarm_en = 1; /* Enable alarm. */ rtc_cfg.alarm_val = QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1); /* 1s alarm. */ rtc_cfg.callback = NULL; rtc_cfg.callback_data = NULL; rtc_cfg.prescaler = CLK_RTC_DIV_1; qm_rtc_set_config(QM_RTC_0, &rtc_cfg); /* * The RTC clock resides in a different clock domain * to the system clock. * It takes 3-4 RTC ticks for a system clock write to propagate * to the RTC domain. * If an entry to sleep is initiated without waiting for the * transaction to complete the SOC will not wake from sleep. */ aonc_start = QM_AONC[QM_AONC_0]->aonc_cnt; while (QM_AONC[QM_AONC_0]->aonc_cnt - aonc_start < RTC_SYNC_CLK_COUNT) { } QM_IR_UNMASK_INT(QM_IRQ_RTC_0_INT); QM_IRQ_REQUEST(QM_IRQ_RTC_0_INT, qm_rtc_0_isr); /* * Enable LPSS by the Sensor Subsystem. * This will clock gate sensor peripherals. */ qm_ss_power_soc_lpss_enable(); /* * Signal to the x86 core that the Sensor Subsystem * is ready to enter LPSS mode. */ QM_SCSS_GP->gps2 |= QM_SCSS_GP_SENSOR_READY; rtc_trigger = switch_rtc_to_level(); /* Go to LPSS, RTC will wake the Sensor Subsystem up. */ qm_ss_power_cpu_ss2(); /* Log the interrupt event in soc_watch. */ SOC_WATCH_LOG_EVENT(SOCW_EVENT_INTERRUPT, QM_IRQ_RTC_0_INT_VECTOR); restore_rtc_trigger(rtc_trigger); /* Clear the SENSOR_READY flag in General Purpose Sticky Register 2. */ QM_SCSS_GP->gps2 &= ~QM_SCSS_GP_SENSOR_READY; /* * Disable LPSS. * This will restore clock gating of sensor peripherals. */ qm_ss_power_soc_lpss_disable(); /* Core still in C2 mode. */ qm_gpio_clear_pin(QM_GPIO_0, PIN_OUT); clk_sys_udelay(GPIO_TOGGLE_DELAY); qm_gpio_set_pin(QM_GPIO_0, PIN_OUT); clk_sys_udelay(GPIO_TOGGLE_DELAY); qm_gpio_clear_pin(QM_GPIO_0, PIN_OUT); /* Set another alarm 1 second from now. */ qm_rtc_set_alarm(QM_RTC_0, QM_RTC[QM_RTC_0]->rtc_ccvr + (QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1))); /* * The RTC clock resides in a different clock domain * to the system clock. * It takes 3-4 RTC ticks for a system clock write to propagate * to the RTC domain. * If an entry to sleep is initiated without waiting for the * transaction to complete the SOC will not wake from sleep. */ aonc_start = QM_AONC[QM_AONC_0]->aonc_cnt; while (QM_AONC[QM_AONC_0]->aonc_cnt - aonc_start < RTC_SYNC_CLK_COUNT) { } /* * Enable LPSS by the Sensor Subsystem. * This will clock gate sensor peripherals. */ qm_ss_power_soc_lpss_enable(); /* * Signal to the x86 core that the Sensor Subsystem * is ready to enter LPSS mode. */ QM_SCSS_GP->gps2 |= QM_SCSS_GP_SENSOR_READY; rtc_trigger = switch_rtc_to_level(); /* Go to LPSS, RTC will wake the Sensor Subsystem up. */ qm_ss_power_cpu_ss2(); /* Log the interrupt event in soc_watch. */ SOC_WATCH_LOG_EVENT(SOCW_EVENT_INTERRUPT, QM_IRQ_RTC_0_INT_VECTOR); restore_rtc_trigger(rtc_trigger); /* Clear the SENSOR_READY flag in General Purpose Sticky Register 2. */ QM_SCSS_GP->gps2 &= ~QM_SCSS_GP_SENSOR_READY; /* * Disable LPSS. * This will restore clock gating of sensor peripherals. */ qm_ss_power_soc_lpss_disable(); /* Core still in C2LP mode. */ qm_gpio_clear_pin(QM_GPIO_0, PIN_OUT); clk_sys_udelay(GPIO_TOGGLE_DELAY); qm_gpio_set_pin(QM_GPIO_0, PIN_OUT); clk_sys_udelay(GPIO_TOGGLE_DELAY); qm_gpio_clear_pin(QM_GPIO_0, PIN_OUT); /* Trigger soc_watch flush. */ SOC_WATCH_TRIGGER_FLUSH(); return 0; }