sys_clock: Make sys_clock_hw_cycles_per_tick() a proper API

This was another "global variable" API.  Give it function syntax too.
Also add a warning, because on nRF devices (at least) the cycle clock
runs in kHz and is too slow to give a precise answer here.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2018-09-19 11:33:07 -07:00 committed by Anas Nashif
commit b2e4283555
15 changed files with 59 additions and 66 deletions

View file

@ -16,7 +16,7 @@
#include <kernel_structs.h>
extern volatile u64_t _sys_clock_tick_count;
extern int sys_clock_hw_cycles_per_tick;
extern int sys_clock_hw_cycles_per_tick();
/*
* @brief Read 64-bit timestamp value
@ -36,7 +36,7 @@ u64_t _tsc_read(void)
t = (u64_t)_sys_clock_tick_count;
count = _arc_v2_aux_reg_read(_ARC_V2_TMR0_COUNT);
irq_unlock(key);
t *= (u64_t)sys_clock_hw_cycles_per_tick;
t *= (u64_t)sys_clock_hw_cycles_per_tick();
t += (u64_t)count;
return t;
}

View file

@ -24,7 +24,7 @@ static void timer_irq_handler(void *unused)
read_timer_start_of_tick_handler();
#endif
accumulated_cycle_count += sys_clock_hw_cycles_per_tick;
accumulated_cycle_count += sys_clock_hw_cycles_per_tick();
/* Clear the interrupt */
alt_handle_irq((void *)TIMER_0_BASE, TIMER_0_IRQ);
@ -42,15 +42,15 @@ int _sys_clock_driver_init(struct device *device)
ARG_UNUSED(device);
IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE,
sys_clock_hw_cycles_per_tick & 0xFFFF);
sys_clock_hw_cycles_per_tick() & 0xFFFF);
IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE,
(sys_clock_hw_cycles_per_tick >> 16) & 0xFFFF);
(sys_clock_hw_cycles_per_tick() >> 16) & 0xFFFF);
IRQ_CONNECT(TIMER_0_IRQ, 0, timer_irq_handler, NULL, 0);
irq_enable(TIMER_0_IRQ);
alt_avalon_timer_sc_init((void *)TIMER_0_BASE, 0,
TIMER_0_IRQ, sys_clock_hw_cycles_per_tick);
TIMER_0_IRQ, sys_clock_hw_cycles_per_tick());
return 0;
}

View file

@ -487,7 +487,7 @@ int _sys_clock_driver_init(struct device *device)
timer0_control_register_set(0);
timer0_count_register_set(0);
cycles_per_tick = sys_clock_hw_cycles_per_tick;
cycles_per_tick = sys_clock_hw_cycles_per_tick();
IRQ_CONNECT(IRQ_TIMER0, CONFIG_ARCV2_TIMER_IRQ_PRIORITY,
_timer_int_handler, NULL, 0);

View file

@ -313,7 +313,7 @@ void _timer_int_handler(void *unused)
* No tickless idle:
* Update the total tick count and announce this tick to the kernel.
*/
clock_accumulated_count += sys_clock_hw_cycles_per_tick;
clock_accumulated_count += sys_clock_hw_cycles_per_tick();
_sys_clock_tick_announce();
#endif /* CONFIG_TICKLESS_IDLE */
@ -336,7 +336,7 @@ void _timer_int_handler(void *unused)
#else /* !CONFIG_SYS_POWER_MANAGEMENT */
/* accumulate total counter value */
clock_accumulated_count += sys_clock_hw_cycles_per_tick;
clock_accumulated_count += sys_clock_hw_cycles_per_tick();
/*
* one more tick has occurred -- don't need to do anything special since
@ -709,9 +709,9 @@ int _sys_clock_driver_init(struct device *device)
*/
/* systick supports 24-bit H/W counter */
__ASSERT(sys_clock_hw_cycles_per_tick <= (1 << 24),
"sys_clock_hw_cycles_per_tick too large");
sysTickReloadSet(sys_clock_hw_cycles_per_tick - 1);
__ASSERT(sys_clock_hw_cycles_per_tick() <= (1 << 24),
"sys_clock_hw_cycles_per_tick() too large");
sysTickReloadSet(sys_clock_hw_cycles_per_tick() - 1);
#ifdef CONFIG_TICKLESS_IDLE

View file

@ -589,7 +589,7 @@ int _sys_clock_driver_init(struct device *device)
/*
* This driver shall read the COUNTER_CLK_PERIOD value from the general
* capabilities register rather than rely on a board.h provide macro
* (or the global variable 'sys_clock_hw_cycles_per_tick')
* (or the global variable 'sys_clock_hw_cycles_per_tick()')
* to determine the frequency of clock applied to the HPET device.
*/
@ -611,10 +611,9 @@ int _sys_clock_driver_init(struct device *device)
DBG("HPET: timer0: available interrupts mask 0x%x\n",
(u32_t)(*_HPET_TIMER0_CONFIG_CAPS >> 32));
/* Initialize sys_clock_hw_cycles_per_tick/sec */
/* Initialize sys_clock_hw_cycles_per_sec */
sys_clock_hw_cycles_per_tick = counter_load_value;
z_clock_hw_cycles_per_sec = sys_clock_hw_cycles_per_tick *
z_clock_hw_cycles_per_sec = counter_load_value *
CONFIG_SYS_CLOCK_TICKS_PER_SEC;

View file

@ -648,7 +648,7 @@ int _sys_clock_driver_init(struct device *device)
/* determine the timer counter value (in timer clock cycles/system tick)
*/
cycles_per_tick = sys_clock_hw_cycles_per_tick;
cycles_per_tick = sys_clock_hw_cycles_per_tick();
tickless_idle_init();

View file

@ -38,7 +38,7 @@
/*
* rtc_past holds the value of RTC_COUNTER at the time the last sys tick was
* announced, in RTC ticks. It is therefore always a multiple of
* sys_clock_hw_cycles_per_tick.
* sys_clock_hw_cycles_per_tick().
*/
static u32_t rtc_past;
@ -114,12 +114,12 @@ static void rtc_announce_set_next(void)
/* If no sys ticks have elapsed, there is no point in incrementing the
* counters or announcing it.
*/
if (rtc_elapsed >= sys_clock_hw_cycles_per_tick) {
if (rtc_elapsed >= sys_clock_hw_cycles_per_tick()) {
#ifdef CONFIG_TICKLESS_IDLE
/* Calculate how many sys ticks elapsed since the last sys tick
* and notify the kernel if necessary.
*/
sys_elapsed = rtc_elapsed / sys_clock_hw_cycles_per_tick;
sys_elapsed = rtc_elapsed / sys_clock_hw_cycles_per_tick();
if (sys_elapsed > expected_sys_ticks) {
/* Never announce more sys ticks than the kernel asked
@ -141,7 +141,7 @@ static void rtc_announce_set_next(void)
* has passed.
*/
rtc_past = (rtc_past +
(sys_elapsed * sys_clock_hw_cycles_per_tick)
(sys_elapsed * sys_clock_hw_cycles_per_tick())
) & RTC_MASK;
_sys_idle_elapsed_ticks = sys_elapsed;
@ -149,7 +149,7 @@ static void rtc_announce_set_next(void)
}
/* Set the RTC to the next sys tick */
rtc_compare_set(rtc_past + sys_clock_hw_cycles_per_tick);
rtc_compare_set(rtc_past + sys_clock_hw_cycles_per_tick());
}
#endif
@ -196,8 +196,8 @@ void _timer_idle_enter(s32_t sys_ticks)
#else
/* Restrict ticks to max supported by RTC without risking overflow*/
if ((sys_ticks < 0) ||
(sys_ticks > (RTC_HALF / sys_clock_hw_cycles_per_tick))) {
sys_ticks = RTC_HALF / sys_clock_hw_cycles_per_tick;
(sys_ticks > (RTC_HALF / sys_clock_hw_cycles_per_tick()))) {
sys_ticks = RTC_HALF / sys_clock_hw_cycles_per_tick();
}
expected_sys_ticks = sys_ticks;
@ -205,7 +205,7 @@ void _timer_idle_enter(s32_t sys_ticks)
/* If ticks is 0, the RTC interrupt handler will be set pending
* immediately, meaning that we will not go to sleep.
*/
rtc_compare_set(rtc_past + (sys_ticks * sys_clock_hw_cycles_per_tick));
rtc_compare_set(rtc_past + (sys_ticks * sys_clock_hw_cycles_per_tick()));
#endif
}
@ -222,11 +222,11 @@ static inline void program_max_cycles(void)
_sys_clock_tick_count = _get_elapsed_clock_time();
/* Update rtc_past to track rtc timer count*/
rtc_past = (_sys_clock_tick_count *
sys_clock_hw_cycles_per_tick) & RTC_MASK;
sys_clock_hw_cycles_per_tick()) & RTC_MASK;
/* Programe RTC compare register to generate interrupt*/
rtc_compare_set(rtc_past +
(max_cycles * sys_clock_hw_cycles_per_tick));
(max_cycles * sys_clock_hw_cycles_per_tick()));
}
@ -283,7 +283,7 @@ u32_t _get_elapsed_program_time(void)
rtc_elapsed = (RTC_COUNTER - rtc_past_copy) & RTC_MASK;
/* Convert number of Machine cycles to SYS_TICKS */
return (rtc_elapsed / sys_clock_hw_cycles_per_tick);
return (rtc_elapsed / sys_clock_hw_cycles_per_tick());
}
@ -307,14 +307,14 @@ void _set_time(u32_t time)
expected_sys_ticks = time;
_sys_clock_tick_count = _get_elapsed_clock_time();
/* Update rtc_past to track rtc timer count*/
rtc_past = (_sys_clock_tick_count * sys_clock_hw_cycles_per_tick) & RTC_MASK;
rtc_past = (_sys_clock_tick_count * sys_clock_hw_cycles_per_tick()) & RTC_MASK;
expected_sys_ticks = expected_sys_ticks > _get_max_clock_time() ?
_get_max_clock_time() : expected_sys_ticks;
/* Programe RTC compare register to generate interrupt*/
rtc_compare_set(rtc_past +
(expected_sys_ticks * sys_clock_hw_cycles_per_tick));
(expected_sys_ticks * sys_clock_hw_cycles_per_tick()));
}
@ -336,8 +336,8 @@ s32_t _get_max_clock_time(void)
rtc_away = rtc_away > RTC_HALF ? RTC_HALF : rtc_away;
/* Convert RTC Ticks to SYS TICKS*/
if (rtc_away >= sys_clock_hw_cycles_per_tick) {
sys_away = rtc_away / sys_clock_hw_cycles_per_tick;
if (rtc_away >= sys_clock_hw_cycles_per_tick()) {
sys_away = rtc_away / sys_clock_hw_cycles_per_tick();
}
return sys_away;
@ -378,9 +378,9 @@ u64_t _get_elapsed_clock_time(void)
compiler_barrier();
rtc_elapsed = (RTC_COUNTER - rtc_past_copy) & RTC_MASK;
if (rtc_elapsed >= sys_clock_hw_cycles_per_tick) {
if (rtc_elapsed >= sys_clock_hw_cycles_per_tick()) {
/* Update total number of SYS_TICKS passed */
elapsed += (rtc_elapsed / sys_clock_hw_cycles_per_tick);
elapsed += (rtc_elapsed / sys_clock_hw_cycles_per_tick());
}
return elapsed;
@ -526,7 +526,7 @@ int _sys_clock_driver_init(struct device *device)
/* TODO: replace with counter driver to access RTC */
SYS_CLOCK_RTC->PRESCALER = 0;
nrf_rtc_cc_set(SYS_CLOCK_RTC, RTC_CC_IDX, sys_clock_hw_cycles_per_tick);
nrf_rtc_cc_set(SYS_CLOCK_RTC, RTC_CC_IDX, sys_clock_hw_cycles_per_tick());
nrf_rtc_event_enable(SYS_CLOCK_RTC, RTC_EVTENSET_COMPARE0_Msk);
nrf_rtc_int_enable(SYS_CLOCK_RTC, RTC_INTENSET_COMPARE0_Msk);
@ -549,7 +549,7 @@ u32_t _timer_cycle_get_32(void)
u32_t elapsed_cycles;
/* Number of timer cycles announced as ticks so far. */
ticked_cycles = _sys_clock_tick_count * sys_clock_hw_cycles_per_tick;
ticked_cycles = _sys_clock_tick_count * sys_clock_hw_cycles_per_tick();
/* Make sure that compiler will not reverse access to RTC and
* _sys_clock_tick_count.

View file

@ -31,7 +31,7 @@ static void pulpino_timer_irq_handler(void *unused)
/* Reset counter */
timer->val = 0;
accumulated_cycle_count += sys_clock_hw_cycles_per_tick;
accumulated_cycle_count += sys_clock_hw_cycles_per_tick();
_sys_clock_tick_announce();
}
@ -50,10 +50,10 @@ int _sys_clock_driver_init(struct device *device)
/*
* Initialize timer.
* Reset counter and set timer to generate interrupt
* every sys_clock_hw_cycles_per_tick
* every sys_clock_hw_cycles_per_tick()
*/
timer->val = 0;
timer->cmp = sys_clock_hw_cycles_per_tick;
timer->cmp = sys_clock_hw_cycles_per_tick();
timer->ctrl = TIMER_CTRL_EN;
return 0;

View file

@ -51,9 +51,9 @@ static ALWAYS_INLINE void riscv_machine_rearm_timer(void)
/*
* Rearm timer to generate an interrupt after
* sys_clock_hw_cycles_per_tick
* sys_clock_hw_cycles_per_tick()
*/
rtc += sys_clock_hw_cycles_per_tick;
rtc += sys_clock_hw_cycles_per_tick();
mtimecmp->val_low = (u32_t)(rtc & 0xffffffff);
mtimecmp->val_high = (u32_t)((rtc >> 32) & 0xffffffff);

View file

@ -242,7 +242,7 @@ u64_t _get_elapsed_clock_time(void)
static ALWAYS_INLINE void tickless_idle_init(void)
{
cycles_per_tick = sys_clock_hw_cycles_per_tick;
cycles_per_tick = sys_clock_hw_cycles_per_tick();
/* calculate the max number of ticks with this 32-bit H/W counter */
max_system_ticks = MAX_TIMER_CYCLES / cycles_per_tick;
max_load_value = max_system_ticks * cycles_per_tick;

View file

@ -42,6 +42,20 @@ static inline int sys_clock_hw_cycles_per_sec(void)
#endif
}
/* Note that some systems with comparatively slow cycle counters
* experience precision loss when doing math like this. In the
* general case it is not correct that "cycles" are much faster than
* "ticks".
*/
static inline int sys_clock_hw_cycles_per_tick(void)
{
#ifdef CONFIG_SYS_CLOCK_EXISTS
return sys_clock_hw_cycles_per_sec() / CONFIG_SYS_CLOCK_TICKS_PER_SEC;
#else
return 1; /* Just to avoid a division by zero */
#endif
}
#if defined(CONFIG_SYS_CLOCK_EXISTS) && \
(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0)
#error "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!"
@ -138,22 +152,6 @@ static inline s64_t __ticks_to_ms(s64_t ticks)
#define _TICK_ALIGN 1
#endif
/*
* sys_clock_us_per_tick global variable represents a number
* of microseconds in one OS timer tick
*
* Note: This variable is deprecated and will be removed soon!
*/
__deprecated extern int sys_clock_us_per_tick;
/*
* sys_clock_hw_cycles_per_tick global variable represents a number
* of platform clock ticks in one OS timer tick.
* sys_clock_hw_cycles_per_tick often represents a value of divider
* of the board clock frequency
*/
extern int sys_clock_hw_cycles_per_tick;
/* SYS_CLOCK_HW_CYCLES_TO_NS64 converts CPU clock cycles to nanoseconds */
#define SYS_CLOCK_HW_CYCLES_TO_NS64(X) \
(((u64_t)(X) * NSEC_PER_SEC) / sys_clock_hw_cycles_per_sec())

View file

@ -21,14 +21,10 @@
#endif
#ifdef CONFIG_SYS_CLOCK_EXISTS
int sys_clock_hw_cycles_per_tick =
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC;
#if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)
int z_clock_hw_cycles_per_sec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
#endif
#else
/* don't initialize to avoid division-by-zero error */
int sys_clock_hw_cycles_per_tick;
#if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)
int z_clock_hw_cycles_per_sec;
#endif

View file

@ -101,7 +101,7 @@ void test_clock_cycle(void)
c32 = k_cycle_get_32();
/*break if cycle counter wrap around*/
while (k_cycle_get_32() > c32 &&
k_cycle_get_32() < (c32 + sys_clock_hw_cycles_per_tick))
k_cycle_get_32() < (c32 + sys_clock_hw_cycles_per_tick()))
#if defined(CONFIG_ARCH_POSIX)
posix_halt_cpu();
#else

View file

@ -61,7 +61,7 @@ static int ticks_to_sleep(int ticks)
k_sleep(__ticks_to_ms(ticks));
stop_time = k_cycle_get_32();
return (stop_time - start_time) / sys_clock_hw_cycles_per_tick;
return (stop_time - start_time) / sys_clock_hw_cycles_per_tick();
}

View file

@ -54,8 +54,8 @@ void test_timer(void)
errors = 0;
TC_PRINT("sys_clock_hw_cycles_per_tick = %d\n",
sys_clock_hw_cycles_per_tick);
TC_PRINT("sys_clock_hw_cycles_per_tick() = %d\n",
sys_clock_hw_cycles_per_tick());
TC_PRINT("sys_clock_hw_cycles_per_sec() = %d\n",
sys_clock_hw_cycles_per_sec());