From 43f0726985e77ae63aafffc3f40da3a2eadef027 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Tue, 27 Apr 2021 10:19:42 -0700 Subject: [PATCH] arm: aarch32: timing: fix potential divide by zero if DWT There is a possibility that the DWT frequency calculation is divided by zero. So this fixes the issue by repeatedly trying to get the delta clock cycles and delta DWT cycles until they both are not zero. Signed-off-by: Daniel Leung --- arch/arm/core/aarch32/cortex_m/timing.c | 34 ++++++++++++++----------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/arch/arm/core/aarch32/cortex_m/timing.c b/arch/arm/core/aarch32/cortex_m/timing.c index 2356e51bd5a..7a480c01183 100644 --- a/arch/arm/core/aarch32/cortex_m/timing.c +++ b/arch/arm/core/aarch32/cortex_m/timing.c @@ -43,31 +43,35 @@ static inline uint64_t z_arm_dwt_freq_get(void) return CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; #else static uint64_t dwt_frequency; + uint32_t cyc_start, cyc_end; + uint64_t dwt_start, dwt_end; + uint64_t cyc_freq = sys_clock_hw_cycles_per_sec(); + uint64_t dcyc, ddwt; if (!dwt_frequency) { z_arm_dwt_init(); - uint32_t cyc_start = k_cycle_get_32(); - uint64_t dwt_start = z_arm_dwt_get_cycles(); + do { + cyc_start = k_cycle_get_32(); + dwt_start = z_arm_dwt_get_cycles(); - k_busy_wait(10 * USEC_PER_MSEC); + k_busy_wait(10 * USEC_PER_MSEC); - uint32_t cyc_end = k_cycle_get_32(); - uint64_t dwt_end = z_arm_dwt_get_cycles(); + cyc_end = k_cycle_get_32(); + dwt_end = z_arm_dwt_get_cycles(); - uint64_t cyc_freq = sys_clock_hw_cycles_per_sec(); + /* + * cycles are in 32-bit, and delta must be + * calculated in 32-bit percision. Or it would + * wrapping around in 64-bit. + */ + dcyc = (uint32_t)cyc_end - (uint32_t)cyc_start; - /* - * cycles are in 32-bit, and delta must be - * calculated in 32-bit percision. Or it would - * wrapping around in 64-bit. - */ - uint64_t dcyc = (uint32_t)cyc_end - (uint32_t)cyc_start; + ddwt = dwt_end - dwt_start; + } while ((dcyc == 0) || (ddwt == 0)); - uint64_t dtsc = dwt_end - dwt_start; - - dwt_frequency = (cyc_freq * dtsc) / dcyc; + dwt_frequency = (cyc_freq * ddwt) / dcyc; } return dwt_frequency;