Fix corner case that could cause the top of minute alarm to stop firing
This commit is contained in:
@@ -49,6 +49,8 @@ typedef struct {
|
||||
volatile bool enabled;
|
||||
} comp_cb_t;
|
||||
|
||||
volatile uint32_t scheduled_comp_counter;
|
||||
|
||||
watch_cb_t tick_callbacks[8];
|
||||
comp_cb_t comp_callbacks[WATCH_RTC_N_COMP_CB];
|
||||
watch_cb_t alarm_callback;
|
||||
@@ -76,6 +78,8 @@ void _watch_rtc_init(void) {
|
||||
comp_callbacks[index].enabled = false;
|
||||
}
|
||||
|
||||
scheduled_comp_counter = 0;
|
||||
|
||||
NVIC_ClearPendingIRQ(RTC_IRQn);
|
||||
NVIC_EnableIRQ(RTC_IRQn);
|
||||
}
|
||||
@@ -195,10 +199,15 @@ void watch_rtc_disable_all_periodic_callbacks(void) {
|
||||
}
|
||||
|
||||
static void _watch_rtc_schedule_next_comp(void) {
|
||||
rtc_disable_compare_interrupt();
|
||||
rtc_counter_t curr_counter = watch_rtc_get_counter();
|
||||
// If there is already a pending comp interrupt for this very tick, let it fire
|
||||
// And this function will be called again as soon as the interrupt fires.
|
||||
if (curr_counter == scheduled_comp_counter) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The soonest we can schedule is the next tick
|
||||
rtc_counter_t curr_counter = watch_rtc_get_counter() + 1;
|
||||
// Because of the hardware, the soonest we can schedule is the next tick
|
||||
curr_counter +=1;
|
||||
|
||||
bool schedule_any = false;
|
||||
rtc_counter_t comp_counter;
|
||||
@@ -216,8 +225,15 @@ static void _watch_rtc_schedule_next_comp(void) {
|
||||
}
|
||||
|
||||
if (schedule_any) {
|
||||
// If we are changing the comp counter at the front of the line
|
||||
if (comp_counter != scheduled_comp_counter) {
|
||||
scheduled_comp_counter = comp_counter;
|
||||
rtc_enable_compare_interrupt(comp_counter);
|
||||
}
|
||||
} else {
|
||||
scheduled_comp_counter = curr_counter - 2;
|
||||
rtc_disable_compare_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
void watch_rtc_register_comp_callback(watch_cb_t callback, rtc_counter_t counter, uint8_t index) {
|
||||
@@ -225,8 +241,6 @@ void watch_rtc_register_comp_callback(watch_cb_t callback, rtc_counter_t counter
|
||||
return;
|
||||
}
|
||||
|
||||
rtc_disable_compare_interrupt();
|
||||
|
||||
comp_callbacks[index].counter = counter;
|
||||
comp_callbacks[index].callback = callback;
|
||||
comp_callbacks[index].enabled = true;
|
||||
@@ -239,8 +253,6 @@ void watch_rtc_disable_comp_callback(uint8_t index) {
|
||||
return;
|
||||
}
|
||||
|
||||
rtc_disable_compare_interrupt();
|
||||
|
||||
comp_callbacks[index].enabled = false;
|
||||
|
||||
_watch_rtc_schedule_next_comp();
|
||||
|
||||
@@ -286,10 +286,15 @@ void watch_rtc_disable_comp_callback(uint8_t index) {
|
||||
}
|
||||
|
||||
static void _watch_rtc_schedule_next_comp(void) {
|
||||
scheduled_comp_counter = 0;
|
||||
rtc_counter_t curr_counter = watch_rtc_get_counter();
|
||||
// If there is already a pending comp interrupt for this very tick, let it fire
|
||||
// And this function will be called again as soon as the interrupt fires.
|
||||
if (curr_counter == scheduled_comp_counter) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The soonest we can schedule is the next tick
|
||||
rtc_counter_t curr_counter = watch_rtc_get_counter() + 1;
|
||||
curr_counter +=1;
|
||||
|
||||
bool schedule_any = false;
|
||||
rtc_counter_t comp_counter;
|
||||
@@ -309,6 +314,8 @@ static void _watch_rtc_schedule_next_comp(void) {
|
||||
|
||||
if (schedule_any) {
|
||||
scheduled_comp_counter = comp_counter;
|
||||
} else {
|
||||
scheduled_comp_counter = curr_counter - 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user