timing: do not repeatedly do init()/start()/stop()

We should not be initializing/starting/stoping timing functions
multiple times. So this changes how the timing functions are
structured to allow only one initialization, only start when
stopped, and only stop when started.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2020-10-14 11:15:40 -07:00 committed by Anas Nashif
parent e9ef078a11
commit 9be37553ee
13 changed files with 353 additions and 88 deletions

View file

@ -121,48 +121,48 @@ static inline uint64_t z_arm_dwt_freq_get(void)
#endif /* CONFIG_SOC_FAMILY_NRF */
}
void timing_init(void)
void arch_timing_init(void)
{
z_arm_dwt_init(NULL);
}
void timing_start(void)
void arch_timing_start(void)
{
z_arm_dwt_cycle_count_start();
}
void timing_stop(void)
void arch_timing_stop(void)
{
DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk;
}
timing_t timing_counter_get(void)
timing_t arch_timing_counter_get(void)
{
return (timing_t)z_arm_dwt_get_cycles();
}
uint64_t timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
uint64_t arch_timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
{
return (*end - *start);
}
uint64_t timing_freq_get(void)
uint64_t arch_timing_freq_get(void)
{
return z_arm_dwt_freq_get();
}
uint64_t timing_cycles_to_ns(uint64_t cycles)
uint64_t arch_timing_cycles_to_ns(uint64_t cycles)
{
return (cycles) * (NSEC_PER_USEC) / timing_freq_get_mhz();
return (cycles) * (NSEC_PER_USEC) / arch_timing_freq_get_mhz();
}
uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
uint64_t arch_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
{
return timing_cycles_to_ns(cycles) / count;
return arch_timing_cycles_to_ns(cycles) / count;
}
uint32_t timing_freq_get_mhz(void)
uint32_t arch_timing_freq_get_mhz(void)
{
return (uint32_t)(timing_freq_get() / 1000000);
return (uint32_t)(arch_timing_freq_get() / 1000000);
}

View file

@ -8,46 +8,46 @@
#include <sys_clock.h>
#include <timing/timing.h>
void timing_init(void)
void arch_timing_init(void)
{
}
void timing_start(void)
void arch_timing_start(void)
{
}
void timing_stop(void)
void arch_timing_stop(void)
{
}
timing_t timing_counter_get(void)
timing_t arch_timing_counter_get(void)
{
return k_cycle_get_32();
}
uint64_t timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
uint64_t arch_timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
{
return (*end - *start);
}
uint64_t timing_freq_get(void)
uint64_t arch_timing_freq_get(void)
{
return sys_clock_hw_cycles_per_sec();
}
uint64_t timing_cycles_to_ns(uint64_t cycles)
uint64_t arch_timing_cycles_to_ns(uint64_t cycles)
{
return k_cyc_to_ns_floor64(cycles);
}
uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
uint64_t arch_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
{
return timing_cycles_to_ns(cycles) / count;
return arch_timing_cycles_to_ns(cycles) / count;
}
uint32_t timing_freq_get_mhz(void)
uint32_t arch_timing_freq_get_mhz(void)
{
return (uint32_t)(timing_freq_get() / 1000000);
return (uint32_t)(arch_timing_freq_get() / 1000000);
}

View file

@ -20,46 +20,46 @@
<< 16) | \
((uint32_t)IORD_ALTERA_AVALON_TIMER_SNAPL(TIMER_0_BASE))))
void timing_init(void)
void arch_timing_init(void)
{
}
void timing_start(void)
void arch_timing_start(void)
{
}
void timing_stop(void)
void arch_timing_stop(void)
{
}
timing_t timing_counter_get(void)
timing_t arch_timing_counter_get(void)
{
IOWR_ALTERA_AVALON_TIMER_SNAPL(TIMER_0_BASE, 10);
return TIMING_INFO_OS_GET_TIME();
}
uint64_t timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
uint64_t arch_timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
{
return (*end - *start);
}
uint64_t timing_freq_get(void)
uint64_t arch_timing_freq_get(void)
{
return sys_clock_hw_cycles_per_sec();
}
uint64_t timing_cycles_to_ns(uint64_t cycles)
uint64_t arch_timing_cycles_to_ns(uint64_t cycles)
{
return k_cyc_to_ns_floor64(cycles);
}
uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
uint64_t arch_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
{
return timing_cycles_to_ns(cycles) / count;
return arch_timing_cycles_to_ns(cycles) / count;
}
uint32_t timing_freq_get_mhz(void)
uint32_t arch_timing_freq_get_mhz(void)
{
return (uint32_t)(timing_freq_get() / 1000000);
return (uint32_t)(arch_timing_freq_get() / 1000000);
}

View file

@ -11,7 +11,7 @@
static uint64_t tsc_freq;
void timing_x86_init(void)
void arch_timing_x86_init(void)
{
uint32_t cyc_start = k_cycle_get_32();
uint64_t tsc_start = z_tsc_read();
@ -35,51 +35,52 @@ void timing_x86_init(void)
tsc_freq = (cyc_freq * dtsc) / dcyc;
}
uint64_t timing_x86_freq_get(void)
uint64_t arch_timing_x86_freq_get(void)
{
return tsc_freq;
}
void timing_init(void)
void arch_timing_init(void)
{
timing_x86_init();
arch_timing_x86_init();
}
void timing_start(void)
void arch_timing_start(void)
{
}
void timing_stop(void)
void arch_timing_stop(void)
{
}
timing_t timing_counter_get(void)
timing_t arch_timing_counter_get(void)
{
return k_cycle_get_32();
}
uint64_t timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
uint64_t arch_timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
{
return (*end - *start);
}
uint64_t timing_freq_get(void)
uint64_t arch_timing_freq_get(void)
{
return timing_x86_freq_get();
return arch_timing_x86_freq_get();
}
uint64_t timing_cycles_to_ns(uint64_t cycles)
uint64_t arch_timing_cycles_to_ns(uint64_t cycles)
{
return k_cyc_to_ns_floor64(cycles);
}
uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
uint64_t arch_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
{
return timing_cycles_to_ns(cycles) / count;
return arch_timing_cycles_to_ns(cycles) / count;
}
uint32_t timing_freq_get_mhz(void)
uint32_t arch_timing_freq_get_mhz(void)
{
return (uint32_t)(timing_freq_get() / 1000000);
return (uint32_t)(arch_timing_freq_get() / 1000000);
}

View file

@ -845,6 +845,109 @@ size_t arch_cache_line_size_get(void);
#endif
/** @} */
#ifdef CONFIG_TIMING_FUNCTIONS
#include <timing/types.h>
/**
* @ingroup arch-interface timing_api
*/
/**
* @brief Initialize the timing subsystem.
*
* Perform the necessary steps to initialize the timing subsystem.
*
* @see timing_init()
*/
void arch_timing_init(void);
/**
* @brief Signal the start of the timing information gathering.
*
* Signal to the timing subsystem that timing information
* will be gathered from this point forward.
*
* @see timing_start()
*/
void arch_timing_start(void);
/**
* @brief Signal the end of the timing information gathering.
*
* Signal to the timing subsystem that timing information
* is no longer being gathered from this point forward.
*
* @see timing_stop()
*/
void arch_timing_stop(void);
/**
* @brief Return timing counter.
*
* @return Timing counter.
*
* @see timing_counter_get()
*/
timing_t arch_timing_counter_get(void);
/**
* @brief Get number of cycles between @p start and @p end.
*
* For some architectures or SoCs, the raw numbers from counter
* need to be scaled to obtain actual number of cycles.
*
* @param start Pointer to counter at start of a measured execution.
* @param end Pointer to counter at stop of a measured execution.
* @return Number of cycles between start and end.
*
* @see timing_cycles_get()
*/
uint64_t arch_timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end);
/**
* @brief Get frequency of counter used (in Hz).
*
* @return Frequency of counter used for timing in Hz.
*
* @see timing_freq_get()
*/
uint64_t arch_timing_freq_get(void);
/**
* @brief Convert number of @p cycles into nanoseconds.
*
* @param cycles Number of cycles
* @return Converted time value
*
* @see timing_cycles_to_ns()
*/
uint64_t arch_timing_cycles_to_ns(uint64_t cycles);
/**
* @brief Convert number of @p cycles into nanoseconds with averaging.
*
* @param cycles Number of cycles
* @param count Times of accumulated cycles to average over
* @return Converted time value
*
* @see timing_cycles_to_ns_avg()
*/
uint64_t arch_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count);
/**
* @brief Get frequency of counter used (in MHz).
*
* @return Frequency of counter used for timing in MHz.
*
* @see timing_freq_get_mhz()
*/
uint32_t arch_timing_freq_get_mhz(void);
/* @} */
#endif /* CONFIG_TIMING_FUNCTIONS */
#ifdef __cplusplus
}
#endif /* __cplusplus */

View file

@ -7,7 +7,30 @@
#ifndef ZEPHYR_INCLUDE_TIMING_TIMING_H_
#define ZEPHYR_INCLUDE_TIMING_TIMING_H_
#include <kernel.h>
#include <sys/arch_interface.h>
#include <timing/types.h>
void soc_timing_init(void);
void soc_timing_start(void);
void soc_timing_stop(void);
timing_t soc_timing_counter_get(void);
uint64_t soc_timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end);
uint64_t soc_timing_freq_get(void);
uint64_t soc_timing_cycles_to_ns(uint64_t cycles);
uint64_t soc_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count);
uint32_t soc_timing_freq_get_mhz(void);
void board_timing_init(void);
void board_timing_start(void);
void board_timing_stop(void);
timing_t board_timing_counter_get(void);
uint64_t board_timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end);
uint64_t board_timing_freq_get(void);
uint64_t board_timing_cycles_to_ns(uint64_t cycles);
uint64_t board_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count);
uint32_t board_timing_freq_get_mhz(void);
/**
@ -17,8 +40,6 @@
*/
typedef uint64_t timing_t;
/**
* @brief Initialize the timing subsystem.
*
@ -47,7 +68,16 @@ void timing_stop(void);
*
* @return Timing counter.
*/
timing_t timing_counter_get(void);
static inline timing_t timing_counter_get(void)
{
#if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
return board_timing_counter_get();
#elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
return soc_timing_counter_get();
#else
return arch_timing_counter_get();
#endif
}
/**
* @brief Get number of cycles between @p start and @p end.
@ -59,15 +89,33 @@ timing_t timing_counter_get(void);
* @param end Pointer to counter at stop of a measured execution.
* @return Number of cycles between start and end.
*/
uint64_t timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end);
static inline uint64_t timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
{
#if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
return board_timing_cycles_get(start, end);
#elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
return soc_timing_cycles_get(start, end);
#else
return arch_timing_cycles_get(start, end);
#endif
}
/**
* @brief Get frequency of counter used (in Hz).
*
* @return Frequency of counter used for timing in Hz.
*/
uint64_t timing_freq_get(void);
static inline uint64_t timing_freq_get(void)
{
#if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
return board_timing_freq_get();
#elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
return soc_timing_freq_get();
#else
return arch_timing_freq_get();
#endif
}
/**
* @brief Convert number of @p cycles into nanoseconds.
@ -75,16 +123,50 @@ uint64_t timing_freq_get(void);
* @param cycles Number of cycles
* @return Converted time value
*/
uint64_t timing_cycles_to_ns(uint64_t cycles);
static inline uint64_t timing_cycles_to_ns(uint64_t cycles)
{
#if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
return board_timing_cycles_to_ns(cycles);
#elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
return soc_timing_cycles_to_ns(cycles);
#else
return arch_timing_cycles_to_ns(cycles);
#endif
}
uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count);
/**
* @brief Convert number of @p cycles into nanoseconds with averaging.
*
* @param cycles Number of cycles
* @param count Times of accumulated cycles to average over
* @return Converted time value
*/
static inline uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
{
#if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
return board_timing_cycles_to_ns_avg(cycles, count);
#elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
return soc_timing_cycles_to_ns_avg(cycles, count);
#else
return arch_timing_cycles_to_ns_avg(cycles, count);
#endif
}
/**
* @brief Get frequency of counter used (in MHz).
*
* @return Frequency of counter used for timing in MHz.
*/
uint32_t timing_freq_get_mhz(void);
static inline uint32_t timing_freq_get_mhz(void)
{
#if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
return board_timing_freq_get_mhz();
#elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
return soc_timing_freq_get_mhz();
#else
return arch_timing_freq_get_mhz();
#endif
}
/**
* @}

12
include/timing/types.h Normal file
View file

@ -0,0 +1,12 @@
/*
* Copyright (c) 2020 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_TIMING_TYPES_H_
#define ZEPHYR_INCLUDE_TIMING_TYPES_H_
typedef uint64_t timing_t;
#endif /* ZEPHYR_INCLUDE_TIMING_TYPES_H_ */

View file

@ -10,7 +10,7 @@
#include <timing/timing.h>
#include <soc.h>
void timing_init(void)
void soc_timing_init(void)
{
/* Setup counter */
B32TMR1_REGS->CTRL = MCHP_BTMR_CTRL_ENABLE |
@ -24,43 +24,43 @@ void timing_init(void)
B32TMR1_REGS->STS = 1; /* Clear interrupt */
}
void timing_start(void)
void soc_timing_start(void)
{
B32TMR1_REGS->CTRL |= MCHP_BTMR_CTRL_START;
}
void timing_stop(void)
void soc_timing_stop(void)
{
B32TMR1_REGS->CTRL &= ~MCHP_BTMR_CTRL_START;
}
timing_t timing_counter_get(void)
timing_t soc_timing_counter_get(void)
{
return B32TMR1_REGS->CNT;
}
uint64_t timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
uint64_t soc_timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
{
return (*end - *start);
}
uint64_t timing_freq_get(void)
uint64_t soc_timing_freq_get(void)
{
return CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
}
uint64_t timing_cycles_to_ns(uint64_t cycles)
uint64_t soc_timing_cycles_to_ns(uint64_t cycles)
{
return (cycles) * (NSEC_PER_SEC) / (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
}
uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
uint64_t soc_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
{
return (uint32_t)timing_cycles_to_ns(cycles) / count;
return (uint32_t)soc_timing_cycles_to_ns(cycles) / count;
}
uint32_t timing_freq_get_mhz(void)
uint32_t soc_timing_freq_get_mhz(void)
{
return (uint32_t)(timing_freq_get() / 1000000);
return (uint32_t)(soc_timing_freq_get() / 1000000);
}

View file

@ -33,7 +33,7 @@ config SYS_POWER_MANAGEMENT
config BUILD_OUTPUT_HEX
default y
if !CORTEX_M_DWT
if !CORTEX_M_DWT && NRF_RTC_TIMER
config SOC_HAS_TIMING_FUNCTIONS
default y
endif

View file

@ -14,7 +14,7 @@
#define CYCLES_PER_SEC (16000000 / (1 << NRF_TIMER2->PRESCALER))
void timing_init(void)
void soc_timing_init(void)
{
NRF_TIMER2->TASKS_CLEAR = 1; /* Clear Timer */
NRF_TIMER2->MODE = 0; /* Timer Mode */
@ -26,24 +26,24 @@ void timing_init(void)
#endif
}
void timing_start(void)
void soc_timing_start(void)
{
NRF_TIMER2->TASKS_START = 1;
}
void timing_stop(void)
void soc_timing_stop(void)
{
NRF_TIMER2->TASKS_STOP = 1; /* Stop Timer */
}
timing_t timing_counter_get(void)
timing_t soc_timing_counter_get(void)
{
NRF_TIMER2->TASKS_CAPTURE[0] = 1;
return NRF_TIMER2->CC[0] * ((SystemCoreClock) / CYCLES_PER_SEC);
}
uint64_t timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
uint64_t soc_timing_cycles_get(volatile timing_t *const start,
volatile timing_t *const end)
{
#if defined(CONFIG_SOC_SERIES_NRF51X)
#define COUNTER_SPAN BIT(16)
@ -57,24 +57,24 @@ uint64_t timing_cycles_get(volatile timing_t *const start,
#endif
}
uint64_t timing_freq_get(void)
uint64_t soc_timing_freq_get(void)
{
return SystemCoreClock;
}
uint64_t timing_cycles_to_ns(uint64_t cycles)
uint64_t soc_timing_cycles_to_ns(uint64_t cycles)
{
return (cycles) * (NSEC_PER_SEC) / (SystemCoreClock);
}
uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
uint64_t soc_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
{
return timing_cycles_to_ns(cycles) / count;
return soc_timing_cycles_to_ns(cycles) / count;
}
uint32_t timing_freq_get_mhz(void)
uint32_t soc_timing_freq_get_mhz(void)
{
return (uint32_t)(timing_freq_get() / 1000000);
return (uint32_t)(soc_timing_freq_get() / 1000000);
}
#endif

View file

@ -24,3 +24,4 @@ add_subdirectory(testsuite)
add_subdirectory(tracing)
add_subdirectory_ifdef(CONFIG_JWT jwt)
add_subdirectory(canbus)
add_subdirectory_ifdef(CONFIG_TIMING_FUNCTIONS timing)

View file

@ -0,0 +1,6 @@
# Copyright (c) 2020 Intel Corporation.
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_sources(timing.c)

60
subsys/timing/timing.c Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2020 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <kernel.h>
#include <sys/atomic.h>
#include <timing/timing.h>
static bool has_inited;
static atomic_val_t started_ref;
void timing_init(void)
{
if (has_inited) {
return;
}
#if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
board_timing_init();
#elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
soc_timing_init();
#else
arch_timing_init();
#endif
has_inited = true;
}
void timing_start(void)
{
if (atomic_inc(&started_ref) != 0) {
return;
}
#if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
board_timing_start();
#elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
soc_timing_start();
#else
arch_timing_start();
#endif
}
void timing_stop(void)
{
if (atomic_dec(&started_ref) > 1) {
return;
}
#if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
board_timing_stop();
#elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
soc_timing_stop();
#else
arch_timing_stop();
#endif
}