From d7bc024a6a9bb77f9709202d7105e38c45dc75f0 Mon Sep 17 00:00:00 2001 From: Masao Hamanaka Date: Thu, 26 Feb 2015 16:36:30 +0900 Subject: [PATCH] Fix a bug that Ticker driver has the potential to loop infinitely. Ticker driver has the potential to loop infinitely. Because, running "us_ticker_irq_handler()" from "us_ticker_set_interrupt()" before "obj->next = p;" of "us_ticker_insert_event()" is executed. --- .../TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c | 88 +++++++++---------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c index c7eed18125..46ff8cefb0 100644 --- a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c @@ -30,6 +30,7 @@ int us_ticker_inited = 0; static double count_clock = 0; static uint32_t last_read = 0; static uint32_t wrap_arround = 0; +static uint64_t ticker_us_last64 = 0; void us_ticker_interrupt(void) { us_ticker_irq_handler(); @@ -61,69 +62,67 @@ void us_ticker_init(void) { GIC_EnableIRQ(US_TICKER_TIMER_IRQn); } -uint64_t us_ticker_read64() { - uint32_t val; - volatile uint64_t val64; - int check_irq_masked; - - check_irq_masked = __disable_irq(); +static uint64_t ticker_read_counter64(void) { + uint32_t cnt_val; + uint64_t cnt_val64; if (!us_ticker_inited) us_ticker_init(); /* read counter */ - val = OSTM1CNT; - if ( last_read > val ) { + cnt_val = OSTM1CNT; + if (last_read > cnt_val) { wrap_arround++; } - last_read = val; - val64 = ((uint64_t)wrap_arround << 32) + val; + last_read = cnt_val; + cnt_val64 = ((uint64_t)wrap_arround << 32) + cnt_val; - /* clock to us */ - val64 = val64 / count_clock; + return cnt_val64; +} + +uint32_t us_ticker_read() { + uint64_t cnt_val64; + uint64_t us_val64; + int check_irq_masked; + + check_irq_masked = __disable_irq(); + + cnt_val64 = ticker_read_counter64(); + us_val64 = (cnt_val64 / count_clock); + ticker_us_last64 = us_val64; if (!check_irq_masked) { __enable_irq(); } - return val64; -} - -uint32_t us_ticker_read() { - return (uint32_t)us_ticker_read64(); + /* clock to us */ + return (uint32_t)us_val64; } void us_ticker_set_interrupt(timestamp_t timestamp) { // set match value - volatile uint64_t set_cmp_val = 0; - uint64_t timestamp_tmp; - int64_t timestamp_req; - int64_t timestamp_comp; - uint64_t timestamp_now = us_ticker_read64(); - + uint64_t timestamp64; + uint64_t set_cmp_val64; + volatile uint32_t set_cmp_val; + uint64_t count_val_64; + /* calc compare mach timestamp */ - set_cmp_val = (timestamp_now & 0xFFFFFFFF00000000) + timestamp; - - timestamp_tmp = (uint64_t)timestamp; - timestamp_req = (int64_t)timestamp_tmp; - - timestamp_tmp = (uint64_t)(timestamp_now & 0x00000000FFFFFFFF); - timestamp_comp = (int64_t)timestamp_tmp; - - if (timestamp_req <= timestamp_comp + 1) { - if (((timestamp_req - timestamp_comp) <= 1) && ((timestamp_req - timestamp_comp) >= -10)) { - /* This event was in the past */ - us_ticker_irq_handler(); - return; - } else { - /* This event is wrap arround */ - set_cmp_val += 0x100000000; - } + timestamp64 = (ticker_us_last64 & 0xFFFFFFFF00000000) + timestamp; + if (timestamp < (ticker_us_last64 & 0x00000000FFFFFFFF)) { + /* This event is wrap arround */ + timestamp64 += 0x100000000; } - + /* calc compare mach timestamp */ - set_cmp_val = set_cmp_val * count_clock; - OSTM1CMP = (uint32_t)(set_cmp_val & 0xffffffff); + set_cmp_val64 = timestamp64 * count_clock; + set_cmp_val = (uint32_t)(set_cmp_val64 & 0x00000000FFFFFFFF); + count_val_64 = ticker_read_counter64(); + if (set_cmp_val64 <= (count_val_64 + 500)) { + GIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); + GIC_EnableIRQ(US_TICKER_TIMER_IRQn); + return; + } + OSTM1CMP = set_cmp_val; GIC_EnableIRQ(US_TICKER_TIMER_IRQn); } @@ -132,6 +131,5 @@ void us_ticker_disable_interrupt(void) { } void us_ticker_clear_interrupt(void) { - /* There are no Flags of OSTM1 to clear here */ - /* Do Nothing */ + GIC_ClearPendingIRQ(US_TICKER_TIMER_IRQn); }