diff options
Diffstat (limited to 'drivers/delay_timer/delay_timer.c')
-rw-r--r-- | drivers/delay_timer/delay_timer.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/delay_timer/delay_timer.c b/drivers/delay_timer/delay_timer.c index 0bee876f..ed7ed52e 100644 --- a/drivers/delay_timer/delay_timer.c +++ b/drivers/delay_timer/delay_timer.c @@ -48,19 +48,22 @@ void udelay(uint32_t usec) (ops->clk_div != 0) && (ops->get_timer_value != 0)); - uint32_t start, cnt, delta, delta_us; + uint32_t start, delta, total_delta; + + assert(usec < UINT32_MAX / ops->clk_div); - /* counter is decreasing */ start = ops->get_timer_value(); + + total_delta = (usec * ops->clk_div) / ops->clk_mult; + do { - cnt = ops->get_timer_value(); - if (cnt > start) { - delta = UINT32_MAX - cnt; - delta += start; - } else - delta = start - cnt; - delta_us = (delta * ops->clk_mult) / ops->clk_div; - } while (delta_us < usec); + /* + * If the timer value wraps around, the subtraction will + * overflow and it will still give the correct result. + */ + delta = start - ops->get_timer_value(); /* Decreasing counter */ + + } while (delta < total_delta); } /*********************************************************** |