include/system_timer.h: Timer API cleanup

Rename timer driver API functions to be consistent.  ADD DOCS TO THE
HEADER so implementations understand what the requirements are.
Remove some unused functions that don't need declarations here.

Also removes the per-platform #if's around the power control callback
in favor of a weak-linked noop function in the driver initialization
(adds a few bytes of code to default platforms -- we'll live, I
think).

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2018-09-21 09:33:36 -07:00 committed by Anas Nashif
commit 1a1a9539ea
16 changed files with 109 additions and 82 deletions

View file

@ -41,7 +41,7 @@ static void timer_irq_handler(void *unused)
#endif
}
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
ARG_UNUSED(device);

View file

@ -15,7 +15,7 @@
* be programmed to wake the system in N >= TICKLESS_IDLE_THRESH ticks. The
* kernel invokes _timer_idle_enter() to program the up counter to trigger an
* interrupt in N ticks. When the timer expires (or when another interrupt is
* detected), the kernel's interrupt stub invokes _timer_idle_exit() to leave
* detected), the kernel's interrupt stub invokes z_clock_idle_exit() to leave
* the tickless idle state.
*
* @internal
@ -28,13 +28,13 @@
*
* 2. The act of entering tickless idle may potentially straddle a tick
* boundary. This can be detected in _timer_idle_enter() after Timer0 is
* programmed with the new limit and acted upon in _timer_idle_exit().
* programmed with the new limit and acted upon in z_clock_idle_exit().
*
* 3. Tickless idle may be prematurely aborted due to a straddled tick. See
* previous factor.
*
* 4. Tickless idle may end naturally. This is detected and handled in
* _timer_idle_exit().
* z_clock_idle_exit().
*
* 5. Tickless idle may be prematurely aborted due to a non-timer interrupt.
* If this occurs, Timer0 is reprogrammed to trigger at the next tick.
@ -198,7 +198,7 @@ void _timer_int_handler(void *unused)
#ifdef CONFIG_TICKLESS_KERNEL
if (!programmed_ticks) {
if (_sys_clock_always_on) {
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
program_max_cycles();
}
return;
@ -218,7 +218,7 @@ void _timer_int_handler(void *unused)
/* z_clock_announce(_sys_idle_elapsed_ticks) could cause new programming */
if (!programmed_ticks && _sys_clock_always_on) {
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
program_max_cycles();
}
#else
@ -283,7 +283,7 @@ void _set_time(u32_t time)
programmed_ticks = time > max_system_ticks ? max_system_ticks : time;
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
timer0_limit_register_set(programmed_ticks * cycles_per_tick);
timer0_count_register_set(0);
@ -314,7 +314,7 @@ static inline u64_t get_elapsed_count(void)
return elapsed;
}
u64_t _get_elapsed_clock_time(void)
u64_t z_clock_uptime(void)
{
return get_elapsed_count() / cycles_per_tick;
}
@ -401,7 +401,7 @@ void _timer_idle_enter(s32_t ticks)
* RETURNS: N/A
*/
void _timer_idle_exit(void)
void z_clock_idle_exit(void)
{
#ifdef CONFIG_TICKLESS_KERNEL
if (!programmed_ticks && _sys_clock_always_on) {
@ -482,7 +482,7 @@ static void tickless_idle_init(void) {}
*
* @return 0
*/
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
ARG_UNUSED(device);
@ -547,7 +547,7 @@ static int sys_clock_resume(struct device *dev)
* Implements the driver control management functionality
* the *context may include IN data or/and OUT data
*/
int sys_clock_device_ctrl(struct device *port, u32_t ctrl_command,
int z_clock_device_ctrl(struct device *port, u32_t ctrl_command,
void *context)
{
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {

View file

@ -242,7 +242,7 @@ void _timer_int_handler(void *unused)
#if defined(CONFIG_TICKLESS_KERNEL)
if (!idle_original_ticks) {
if (_sys_clock_always_on) {
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
/* clear overflow tracking flag as it is accounted */
timer_overflow = 0;
sysTickStop();
@ -272,7 +272,7 @@ void _timer_int_handler(void *unused)
/* z_clock_announce(_sys_idle_elapsed_ticks) could cause new programming */
if (!idle_original_ticks && _sys_clock_always_on) {
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
/* clear overflow tracking flag as it is accounted */
timer_overflow = 0;
sysTickStop();
@ -283,7 +283,7 @@ void _timer_int_handler(void *unused)
#else
/*
* If this a wakeup from a completed tickless idle or after
* _timer_idle_exit has processed a partial idle, return
* z_clock_idle_exit has processed a partial idle, return
* to the normal tick cycle.
*/
if (timer_mode == TIMER_MODE_ONE_SHOT) {
@ -327,7 +327,7 @@ void _timer_int_handler(void *unused)
/*
* Complete idle processing.
* Note that for tickless idle, nothing will be done in
* _timer_idle_exit.
* z_clock_idle_exit.
*/
_sys_power_save_idle_exit(numIdleTicks);
}
@ -390,7 +390,7 @@ void _set_time(u32_t time)
idle_original_ticks = time > max_system_ticks ? max_system_ticks : time;
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
/* clear overflow tracking flag as it is accounted */
timer_overflow = 0;
@ -428,7 +428,7 @@ static inline u64_t get_elapsed_count(void)
return elapsed;
}
u64_t _get_elapsed_clock_time(void)
u64_t z_clock_uptime(void)
{
return get_elapsed_count() / default_load_value;
}
@ -599,13 +599,13 @@ void _timer_idle_enter(s32_t ticks /* system ticks */
*
* @return N/A
*/
void _timer_idle_exit(void)
void z_clock_idle_exit(void)
{
#ifdef CONFIG_TICKLESS_KERNEL
if (idle_mode == IDLE_TICKLESS) {
idle_mode = IDLE_NOT_TICKLESS;
if (!idle_original_ticks && _sys_clock_always_on) {
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
timer_overflow = 0;
sysTickReloadSet(max_load_value);
sysTickStart();
@ -697,7 +697,7 @@ void _timer_idle_exit(void)
*
* @return 0
*/
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
/* enable counter, interrupt and set clock src to system clock */
u32_t ctrl = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk |
@ -756,7 +756,7 @@ return (u32_t) get_elapsed_count();
#ifdef CONFIG_TICKLESS_IDLE
/* When we leave a tickless period the reload value of the timer
* can be set to a remaining value to wait until end of tick.
* (see _timer_idle_exit). The remaining value is always smaller
* (see z_clock_idle_exit). The remaining value is always smaller
* than default_load_value. In this case the time elapsed until
* the timer restart was not yet added to
* clock_accumulated_count. To retrieve a correct cycle count

View file

@ -274,7 +274,7 @@ void _timer_int_handler(void *unused)
/* If timer not programmed or already consumed exit */
if (!programmed_ticks) {
if (_sys_clock_always_on) {
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
program_max_cycles();
}
return;
@ -303,7 +303,7 @@ void _timer_int_handler(void *unused)
/* z_clock_announce(_sys_idle_elapsed_ticks) could cause new programming */
if (!programmed_ticks && _sys_clock_always_on) {
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
program_max_cycles();
}
#else
@ -357,7 +357,7 @@ void _set_time(u32_t time)
programmed_ticks = time;
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
stale_irq_check = 1;
@ -374,7 +374,7 @@ void _enable_sys_clock(void)
}
}
u64_t _get_elapsed_clock_time(void)
u64_t z_clock_uptime(void)
{
u64_t elapsed;
@ -456,7 +456,7 @@ void _timer_idle_enter(s32_t ticks /* system ticks */
*
*/
void _timer_idle_exit(void)
void z_clock_idle_exit(void)
{
#ifdef CONFIG_TICKLESS_KERNEL
if (!programmed_ticks && _sys_clock_always_on) {
@ -560,7 +560,7 @@ void _timer_idle_exit(void)
* @return 0
*/
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
u64_t hpetClockPeriod;
u64_t tickFempto;

View file

@ -15,7 +15,7 @@ void _set_time(u32_t time);
#ifdef CONFIG_TICKLESS_IDLE
void _timer_idle_enter(s32_t ticks);
void _timer_idle_exit(void);
void z_clock_idle_exit(void);
#endif
extern void z_clock_set_timeout(s32_t ticks, bool idle)

View file

@ -26,7 +26,7 @@
* kernel invokes _timer_idle_enter() to program the down counter in one-shot
* mode to trigger an interrupt in N ticks. When the timer expires or when
* another interrupt is detected, the kernel's interrupt stub invokes
* _timer_idle_exit() to leave the tickless idle state.
* z_clock_idle_exit() to leave the tickless idle state.
*
* @internal
* Factors that increase the driver's complexity:
@ -296,7 +296,7 @@ void _timer_int_handler(void *unused /* parameter is not used */
#if defined(CONFIG_TICKLESS_KERNEL)
if (!programmed_full_ticks) {
if (_sys_clock_always_on) {
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
program_max_cycles();
}
return;
@ -322,7 +322,7 @@ void _timer_int_handler(void *unused /* parameter is not used */
/* z_clock_announce(_sys_idle_elapsed_ticks) could cause new programming */
if (!programmed_full_ticks && _sys_clock_always_on) {
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
program_max_cycles();
}
#else
@ -335,7 +335,7 @@ void _timer_int_handler(void *unused /* parameter is not used */
* The timer fired unexpectedly. This is due to one of two cases:
* 1. Entering tickless idle straddled a tick.
* 2. Leaving tickless idle straddled the final tick.
* Due to the timer reprogramming in _timer_idle_exit(), case #2
* Due to the timer reprogramming in z_clock_idle_exit(), case #2
* can be handled as a fall-through.
*
* NOTE: Although the cycle count is supposed to stop decrementing
@ -411,7 +411,7 @@ void _set_time(u32_t time)
programmed_full_ticks =
time > max_system_ticks ? max_system_ticks : time;
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
programmed_cycles = programmed_full_ticks * cycles_per_tick;
initial_count_register_set(programmed_cycles);
@ -424,7 +424,7 @@ void _enable_sys_clock(void)
}
}
u64_t _get_elapsed_clock_time(void)
u64_t z_clock_uptime(void)
{
u64_t elapsed;
@ -542,7 +542,7 @@ void _timer_idle_enter(s32_t ticks /* system ticks */
*
* @return N/A
*/
void _timer_idle_exit(void)
void z_clock_idle_exit(void)
{
#ifdef CONFIG_TICKLESS_KERNEL
if (!programmed_full_ticks && _sys_clock_always_on) {
@ -643,7 +643,7 @@ void _timer_idle_exit(void)
*
* @return 0
*/
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
ARG_UNUSED(device);
@ -733,7 +733,7 @@ static int sys_clock_resume(struct device *dev)
* Implements the driver control management functionality
* the *context may include IN data or/and OUT data
*/
int sys_clock_device_ctrl(struct device *port, u32_t ctrl_command,
int z_clock_device_ctrl(struct device *port, u32_t ctrl_command,
void *context)
{
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {

View file

@ -51,7 +51,7 @@ void _timer_idle_enter(s32_t sys_ticks)
posix_print_warning("native timer: Re-entering idle mode with "
"%i ticks pending\n",
silent_ticks);
_timer_idle_exit();
z_clock_idle_exit();
/* LCOV_EXCL_STOP */
}
if (sys_ticks < 0) {
@ -75,7 +75,7 @@ void _timer_idle_enter(s32_t sys_ticks)
* Note that we do not assume this function is called before the interrupt is
* raised (the interrupt can handle it announcing all ticks)
*/
void _timer_idle_exit(void)
void z_clock_idle_exit(void)
{
silent_ticks -= hwtimer_get_pending_silent_ticks();
if (silent_ticks > 0) {
@ -102,7 +102,7 @@ static void sp_timer_isr(void *arg)
/*
* Enable the hw timer, setting its tick period, and setup its interrupt
*/
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
ARG_UNUSED(device);

View file

@ -93,10 +93,10 @@ static void rtc_compare_set(u32_t rtc_ticks)
*
* This function is not reentrant. It is called from:
*
* * _timer_idle_exit(), which in turn is called with interrupts disabled when
* * z_clock_idle_exit(), which in turn is called with interrupts disabled when
* an interrupt fires.
* * rtc1_nrf5_isr(), which runs with interrupts enabled but at that time the
* device cannot be idle and hence _timer_idle_exit() cannot be called.
* device cannot be idle and hence z_clock_idle_exit() cannot be called.
*
* Since this function can be preempted, we need to take some provisions to
* announce all expected sys ticks that have passed.
@ -223,7 +223,7 @@ static inline void program_max_cycles(void)
{
u32_t max_cycles = _get_max_clock_time();
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
/* Update rtc_past to track rtc timer count*/
rtc_past = (z_tick_get() *
sys_clock_hw_cycles_per_tick()) & RTC_MASK;
@ -309,7 +309,7 @@ void _set_time(u32_t time)
/* Update expected_sys_ticls to time to programe*/
expected_sys_ticks = time;
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
/* Update rtc_past to track rtc timer count*/
rtc_past = (z_tick_get() * sys_clock_hw_cycles_per_tick()) & RTC_MASK;
@ -367,7 +367,7 @@ void _enable_sys_clock(void)
* returns : total number of sys ticks passed since device bootup.
*/
u64_t _get_elapsed_clock_time(void)
u64_t z_clock_uptime(void)
{
u64_t elapsed;
u32_t rtc_elapsed, rtc_past_copy;
@ -418,7 +418,7 @@ u64_t _get_elapsed_clock_time(void)
* b) Schedule next sys tick at 400.
*
*/
void _timer_idle_exit(void)
void z_clock_idle_exit(void)
{
#ifdef CONFIG_TICKLESS_KERNEL
if (!expected_sys_ticks && _sys_clock_always_on) {
@ -509,7 +509,7 @@ void rtc1_nrf5_isr(void *arg)
}
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
struct device *clock;

View file

@ -40,7 +40,7 @@ static void pulpino_timer_irq_handler(void *unused)
#error "Tickless idle not yet implemented for pulpino timer"
#endif
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
ARG_UNUSED(device);
IRQ_CONNECT(PULP_TIMER_A_CMP_IRQ, 0,

View file

@ -86,7 +86,7 @@ static void riscv_machine_timer_irq_handler(void *unused)
#error "Tickless idle not yet implemented for riscv-machine timer"
#endif
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
ARG_UNUSED(device);

View file

@ -16,5 +16,16 @@
#include <init.h>
#include <drivers/system_timer.h>
SYS_DEVICE_DEFINE("sys_clock", _sys_clock_driver_init, sys_clock_device_ctrl,
SYS_DEVICE_DEFINE("sys_clock", z_clock_driver_init, z_clock_device_ctrl,
PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
int __weak z_clock_driver_init(struct device *device)
{
return 0;
}
int __weak z_clock_device_ctrl(struct device *device,
u32_t ctrl_command, void *context)
{
return 0;
}

View file

@ -167,7 +167,7 @@ static inline void _set_max_clock_time(void)
unsigned int key;
key = irq_lock();
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
last_timer_value = GET_TIMER_CURRENT_TIME();
irq_unlock(key);
SET_TIMER_FIRE_TIME(MAX_TIMER_CYCLES); /* Program timer to max value */
@ -191,7 +191,7 @@ void _set_time(u32_t time)
}
key = irq_lock();
/* Update System Level Ticks Time Keeping */
z_tick_set(_get_elapsed_clock_time());
z_tick_set(z_clock_uptime());
C = GET_TIMER_CURRENT_TIME();
last_timer_value = C;
irq_unlock(key);
@ -224,7 +224,7 @@ void _enable_sys_clock(void)
}
/* Total number of ticks passed since device bootup. */
u64_t _get_elapsed_clock_time(void)
u64_t z_clock_uptime(void)
{
u32_t C;
unsigned int key;
@ -329,7 +329,7 @@ void _timer_idle_enter(s32_t ticks)
*
* @return N/A
*/
void _timer_idle_exit(void)
void z_clock_idle_exit(void)
{
#ifdef CONFIG_TICKLESS_KERNEL
if (!idle_original_ticks) {
@ -558,7 +558,7 @@ void _timer_int_handler(void *params)
*
* @return 0
*/
int _sys_clock_driver_init(struct device *device)
int z_clock_driver_init(struct device *device)
{
IRQ_CONNECT(TIMER_IRQ, 0, _timer_int_handler, 0, 0);

View file

@ -23,9 +23,25 @@ extern "C" {
#include <device.h>
#include <stdbool.h>
extern int _sys_clock_driver_init(struct device *device);
/**
* @brief Initialize system clock driver
*
* The system clock is a Zephyr device created globally. This is its
* initialization callback. It is a weak symbol that will be
* implemented as a noop if undefined in the clock driver.
*/
extern int z_clock_driver_init(struct device *device);
extern void _timer_int_handler(void *arg);
/**
* @brief Initialize system clock driver
*
* The system clock is a Zephyr device created globally. This is its
* device control callback, used in a few devices for power
* management. It is a weak symbol that will be implemented as a noop
* if undefined in the clock driver.
*/
extern int z_clock_device_ctrl(struct device *device,
u32_t ctrl_command, void *context);
/**
* @brief Set system clock timeout
@ -60,15 +76,19 @@ extern void _timer_int_handler(void *arg);
*/
extern void z_clock_set_timeout(s32_t ticks, bool idle);
#ifdef CONFIG_SYSTEM_CLOCK_DISABLE
extern void sys_clock_disable(void);
#endif
#ifdef CONFIG_TICKLESS_IDLE
extern void _timer_idle_exit(void);
#else
#define _timer_idle_exit() do { } while (false)
#endif /* CONFIG_TICKLESS_IDLE */
/**
* @brief Timer idle exit notification
*
* This notifies the timer driver that the system is exiting the idle
* and allows it to do whatever bookeeping is needed to restore timer
* operation and compute elapsed ticks.
*
* @note Legacy timer drivers also use this opportunity to call back
* into z_clock_announce() to notify the kernel of expired ticks.
* This is allowed for compatibility, but not recommended. The kernel
* will figure that out on its own.
*/
extern void z_clock_idle_exit(void);
/**
* @brief Announce time progress to the kernel
@ -81,23 +101,18 @@ extern void _timer_idle_exit(void);
*/
extern void z_clock_announce(s32_t ticks);
/**
* @brief System uptime in ticks
*
* Queries the clock driver for the current time elapsed since system
* bootup in ticks.
*/
extern u64_t z_clock_uptime(void);
#ifdef CONFIG_TICKLESS_KERNEL
extern u32_t _get_program_time(void);
extern u32_t _get_remaining_program_time(void);
extern u32_t _get_elapsed_program_time(void);
extern u64_t _get_elapsed_clock_time(void);
#endif
extern int sys_clock_device_ctrl(struct device *device,
u32_t ctrl_command, void *context);
/*
* Currently regarding timers, only loapic timer and arcv2_timer0 implements
* device pm functionality. For other timers, use default handler in case
* the app enables CONFIG_DEVICE_POWER_MANAGEMENT.
*/
#if !defined(CONFIG_LOAPIC_TIMER) && !defined(CONFIG_ARCV2_TIMER)
#define sys_clock_device_ctrl device_pm_control_nop
#endif
#ifdef __cplusplus

View file

@ -145,7 +145,7 @@ void _sys_power_save_idle_exit(s32_t ticks)
if (_must_enter_tickless_idle(ticks)) {
/* Resume normal periodic system timer interrupts */
_timer_idle_exit();
z_clock_idle_exit();
}
}

View file

@ -51,7 +51,7 @@ static u32_t next_ts;
u32_t z_tick_get_32(void)
{
#ifdef CONFIG_TICKLESS_KERNEL
return (u32_t)_get_elapsed_clock_time();
return (u32_t)z_clock_uptime();
#else
return (u32_t)tick_count;
#endif
@ -79,7 +79,7 @@ Z_SYSCALL_HANDLER(k_uptime_get_32)
s64_t z_tick_get(void)
{
#ifdef CONFIG_TICKLESS_KERNEL
return _get_elapsed_clock_time();
return z_clock_uptime();
#else
unsigned int key = irq_lock();
s64_t ret = tick_count;

View file

@ -16,6 +16,7 @@
#include <misc/reboot.h>
extern void sys_arch_reboot(int type);
extern void sys_clock_disable(void);
void sys_reboot(int type)
{