mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
nrf51: Fix a race condition in hwtimer.c
The check for overflow was originally in __hw_clock_source_read() If it got interrupted, it would frequently see an overflow, because "prev_read" would be less than "now". 1 - Use the comparator to check for overflow. 2 - Only check for overflow in the interrupt handler. BUG=chrome-os-partner:35312 BRANCH=none TEST=make buildall -j use the keyboard code to type use a console command "forcetime", to force the system time to overflow soon. Signed-off-by: Myles Watson <mylesgw@chromium.org> Change-Id: I7005724222289ba967e89af0ce8b9ef8f90a4ae4 Reviewed-on: https://chromium-review.googlesource.com/239967 Reviewed-by: Alec Berg <alecaberg@chromium.org> Tested-by: Myles Watson <mylesgw@chromium.org> Commit-Queue: Myles Watson <mylesgw@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
4ee50837a0
commit
16eaf5cfde
@@ -56,8 +56,6 @@ static uint32_t last_deadline; /* cache of event set */
|
||||
*
|
||||
*/
|
||||
static uint32_t shift;
|
||||
static uint32_t overflow;
|
||||
static uint32_t prev_read;
|
||||
|
||||
void __hw_clock_event_set(uint32_t deadline)
|
||||
{
|
||||
@@ -81,50 +79,44 @@ void __hw_clock_event_clear(void)
|
||||
|
||||
uint32_t __hw_clock_source_read(void)
|
||||
{
|
||||
uint32_t now;
|
||||
|
||||
/* to capture the current value */
|
||||
NRF51_TIMER0_CAPTURE1 = 1;
|
||||
now = NRF51_TIMER0_CC1 + shift;
|
||||
|
||||
/* detect if a wrap happened */
|
||||
if (now < prev_read)
|
||||
overflow++;
|
||||
prev_read = now;
|
||||
|
||||
return now;
|
||||
return NRF51_TIMER0_CC1 + shift;
|
||||
}
|
||||
|
||||
void __hw_clock_source_set(uint32_t ts)
|
||||
{
|
||||
shift = prev_read = ts;
|
||||
shift = ts;
|
||||
|
||||
/* reset counter to zero */
|
||||
NRF51_TIMER0_STOP = 1;
|
||||
NRF51_TIMER0_CLEAR = 1;
|
||||
NRF51_TIMER0_START = 1;
|
||||
|
||||
/* So that no interrupt until next __hw_clock_event_set() */
|
||||
NRF51_TIMER0_CC0 = ts - 1;
|
||||
|
||||
/* Update the overflow point */
|
||||
NRF51_TIMER0_CC2 = 0 - shift;
|
||||
|
||||
/* Start the timer again */
|
||||
NRF51_TIMER0_START = 1;
|
||||
}
|
||||
|
||||
|
||||
/* Interrupt handler for timer */
|
||||
void timer_irq(void)
|
||||
{
|
||||
int overflow = 0;
|
||||
|
||||
/* clear status */
|
||||
NRF51_TIMER0_COMPARE0 = 0;
|
||||
|
||||
if (NRF51_TIMER0_COMPARE2) {
|
||||
/* Invoke a read to update overflow variable */
|
||||
__hw_clock_source_read();
|
||||
NRF51_TIMER0_COMPARE2 = 0;
|
||||
overflow = 1;
|
||||
}
|
||||
|
||||
process_timers(overflow);
|
||||
overflow = 0;
|
||||
}
|
||||
DECLARE_IRQ(NRF51_PERID_TIMER0, timer_irq, 1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user