Improve CC13xx/CC26xx LPM logic
This commit applies a number of improvements to the logic used when trying to drop to a CC13xx/CC26xx low-power mode: * We identify whether there are any pending etimers by using `etimer_pending()` instead of `etimer_next_expiration_time()`. This subsequently allows us to also identify whether an etimer is set to fire at time 0. * We run a larger portion of the code with the global interrupt disabled. This prevents a number of messy conditions that can occur if an interrupt fires after we have started the low-power sequence. * We check whether there are pending events earlier in the sequence. * We make sure to schedule a next wakeup event even when an LPM module prohibits deep sleep and forces sleep instead. This fixes some of the issues discussed in #1236
This commit is contained in:
parent
08fddb6598
commit
571cf9364a
|
@ -244,8 +244,18 @@ lpm_drop()
|
||||||
|
|
||||||
uint32_t domains = LOCKABLE_DOMAINS;
|
uint32_t domains = LOCKABLE_DOMAINS;
|
||||||
|
|
||||||
|
/* Critical. Don't get interrupted! */
|
||||||
|
ti_lib_int_master_disable();
|
||||||
|
|
||||||
|
/* Check if any events fired before we turned interrupts off. If so, abort */
|
||||||
|
if(process_nevents()) {
|
||||||
|
ti_lib_int_master_enable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(RTIMER_CLOCK_LT(soc_rtc_get_next_trigger(),
|
if(RTIMER_CLOCK_LT(soc_rtc_get_next_trigger(),
|
||||||
RTIMER_NOW() + STANDBY_MIN_DURATION)) {
|
RTIMER_NOW() + STANDBY_MIN_DURATION)) {
|
||||||
|
ti_lib_int_master_enable();
|
||||||
lpm_sleep();
|
lpm_sleep();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -261,30 +271,20 @@ lpm_drop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if any events fired during this process. Last chance to abort */
|
/* Reschedule AON RTC CH1 to fire just in time for the next etimer event */
|
||||||
if(process_nevents()) {
|
next_event = etimer_next_expiration_time();
|
||||||
return;
|
|
||||||
|
if(etimer_pending()) {
|
||||||
|
next_event = next_event - clock_time();
|
||||||
|
soc_rtc_schedule_one_shot(AON_RTC_CH1, soc_rtc_last_isr_time() +
|
||||||
|
(next_event * (RTIMER_SECOND / CLOCK_SECOND)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Drop */
|
/* Drop */
|
||||||
if(max_pm == LPM_MODE_SLEEP) {
|
if(max_pm == LPM_MODE_SLEEP) {
|
||||||
|
ti_lib_int_master_enable();
|
||||||
lpm_sleep();
|
lpm_sleep();
|
||||||
} else {
|
} else {
|
||||||
/* Critical. Don't get interrupted! */
|
|
||||||
ti_lib_int_master_disable();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reschedule AON RTC CH1 to fire an event N ticks before the next etimer
|
|
||||||
* event
|
|
||||||
*/
|
|
||||||
next_event = etimer_next_expiration_time();
|
|
||||||
|
|
||||||
if(next_event) {
|
|
||||||
next_event = next_event - clock_time();
|
|
||||||
soc_rtc_schedule_one_shot(AON_RTC_CH1, soc_rtc_last_isr_time() +
|
|
||||||
(next_event * (RTIMER_SECOND / CLOCK_SECOND)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notify all registered modules that we are dropping to mode X. We do not
|
* Notify all registered modules that we are dropping to mode X. We do not
|
||||||
* need to do this for simple sleep.
|
* need to do this for simple sleep.
|
||||||
|
|
Loading…
Reference in a new issue