Branch data Line data Source code
1 : : /* 2 : : * Copyright (c) 2017-2019 Oticon A/S 3 : : * 4 : : * SPDX-License-Identifier: Apache-2.0 5 : : */ 6 : : 7 : : /** 8 : : * Driver for the timer model of the POSIX native_sim/posix board 9 : : * It provides the interfaces required by the kernel and the sanity testcases 10 : : * It also provides a custom k_busy_wait() which can be used with the 11 : : * POSIX arch and InfClock SOC 12 : : */ 13 : : #include <zephyr/types.h> 14 : : #include <zephyr/irq.h> 15 : : #include <zephyr/init.h> 16 : : #include <zephyr/drivers/timer/system_timer.h> 17 : : #include <zephyr/sys_clock.h> 18 : : #include "timer_model.h" 19 : : #include "soc.h" 20 : : #include <zephyr/arch/posix/posix_trace.h> 21 : : 22 : : static uint64_t tick_period; /* System tick period in microseconds */ 23 : : /* Time (microseconds since boot) of the last timer tick interrupt */ 24 : : static uint64_t last_tick_time; 25 : : 26 : : /** 27 : : * Return the current HW cycle counter 28 : : * (number of microseconds since boot in 32bits) 29 : : */ 30 : 261 : uint32_t sys_clock_cycle_get_32(void) 31 : : { 32 : 261 : return hwm_get_time(); 33 : : } 34 : : 35 : 0 : uint64_t sys_clock_cycle_get_64(void) 36 : : { 37 : 0 : return hwm_get_time(); 38 : : } 39 : : 40 : : /** 41 : : * Interrupt handler for the timer interrupt 42 : : * Announce to the kernel that a number of ticks have passed 43 : : */ 44 : 0 : static void np_timer_isr(const void *arg) 45 : : { 46 : 0 : ARG_UNUSED(arg); 47 : : 48 : 0 : uint64_t now = hwm_get_time(); 49 : 0 : int32_t elapsed_ticks = (now - last_tick_time)/tick_period; 50 : : 51 : 0 : last_tick_time += elapsed_ticks*tick_period; 52 : 0 : sys_clock_announce(elapsed_ticks); 53 : 0 : } 54 : : 55 : : /** 56 : : * This function exists only to enable tests to call into the timer ISR 57 : : */ 58 : 0 : void np_timer_isr_test_hook(const void *arg) 59 : : { 60 : 0 : np_timer_isr(NULL); 61 : 0 : } 62 : : 63 : : /** 64 : : * @brief Set system clock timeout 65 : : * 66 : : * Informs the system clock driver that the next needed call to 67 : : * sys_clock_announce() will not be until the specified number of ticks 68 : : * from the current time have elapsed. 69 : : * 70 : : * See system_timer.h for more information 71 : : * 72 : : * @param ticks Timeout in tick units 73 : : * @param idle Hint to the driver that the system is about to enter 74 : : * the idle state immediately after setting the timeout 75 : : */ 76 : 0 : void sys_clock_set_timeout(int32_t ticks, bool idle) 77 : : { 78 : 0 : ARG_UNUSED(idle); 79 : : 80 : : #if defined(CONFIG_TICKLESS_KERNEL) 81 : 0 : uint64_t silent_ticks; 82 : : 83 : : /* Note that we treat INT_MAX literally as anyhow the maximum amount of 84 : : * ticks we can report with sys_clock_announce() is INT_MAX 85 : : */ 86 [ # # ]: 0 : if (ticks == K_TICKS_FOREVER) { 87 : : silent_ticks = INT64_MAX; 88 [ # # ]: 0 : } else if (ticks > 0) { 89 : 0 : silent_ticks = ticks - 1; 90 : : } else { 91 : : silent_ticks = 0; 92 : : } 93 : 0 : hwtimer_set_silent_ticks(silent_ticks); 94 : : #endif 95 : 0 : } 96 : : 97 : : /** 98 : : * @brief Ticks elapsed since last sys_clock_announce() call 99 : : * 100 : : * Queries the clock driver for the current time elapsed since the 101 : : * last call to sys_clock_announce() was made. The kernel will call 102 : : * this with appropriate locking, the driver needs only provide an 103 : : * instantaneous answer. 104 : : */ 105 : 0 : uint32_t sys_clock_elapsed(void) 106 : : { 107 : 0 : return (hwm_get_time() - last_tick_time)/tick_period; 108 : : } 109 : : 110 : : /** 111 : : * @brief Stop announcing sys ticks into the kernel 112 : : * 113 : : * Disable the system ticks generation 114 : : */ 115 : 0 : void sys_clock_disable(void) 116 : : { 117 : 0 : irq_disable(TIMER_TICK_IRQ); 118 : 0 : hwtimer_set_silent_ticks(INT64_MAX); 119 : 0 : } 120 : : 121 : : /** 122 : : * @brief Initialize system timer driver 123 : : * 124 : : * Enable the hw timer, setting its tick period, and setup its interrupt 125 : : */ 126 : 1 : static int sys_clock_driver_init(void) 127 : : { 128 : : 129 : 1 : tick_period = 1000000ul / CONFIG_SYS_CLOCK_TICKS_PER_SEC; 130 : : 131 : 1 : last_tick_time = hwm_get_time(); 132 : 1 : hwtimer_enable(tick_period); 133 : : 134 : 1 : IRQ_CONNECT(TIMER_TICK_IRQ, 1, np_timer_isr, 0, 0); 135 : 1 : irq_enable(TIMER_TICK_IRQ); 136 : : 137 : 1 : return 0; 138 : : } 139 : : 140 : : SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, 141 : : CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);