RTEMS 6.3
Loading...
Searching...
No Matches
clockimpl.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
13
14/*
15 * COPYRIGHT (c) 1989-2014.
16 * On-Line Applications Research Corporation (OAR).
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40#include <stdlib.h>
41
42#include <bsp.h>
43#include <rtems/clockdrv.h>
44#include <rtems/score/percpu.h>
46#include <rtems/score/smpimpl.h>
48#include <rtems/score/thread.h>
50
58
59#ifdef Clock_driver_nanoseconds_since_last_tick
60#error "Update driver to use the timecounter instead of nanoseconds extension"
61#endif
62
63#if CLOCK_DRIVER_USE_FAST_IDLE && CLOCK_DRIVER_ISRS_PER_TICK
64#error "Fast Idle PLUS n ISRs per tick is not supported"
65#endif
66
67#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
68 (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
69typedef void * Clock_isr_argument;
70#else
71typedef rtems_vector_number Clock_isr_argument;
72#endif
73
77#ifndef Clock_driver_support_install_isr
78 #define Clock_driver_support_install_isr(isr)
79#endif
80
84#ifndef Clock_driver_support_find_timer
85 #define Clock_driver_support_find_timer()
86#endif
87
91#ifndef Clock_driver_support_at_tick
92 #define Clock_driver_support_at_tick( arg ) do { (void) arg; } while (0)
93#endif
94
98#ifndef Clock_driver_support_set_interrupt_affinity
99 #define Clock_driver_support_set_interrupt_affinity(online_processors)
100#endif
101
102/*
103 * A specialized clock driver may use for example rtems_timecounter_tick_simple()
104 * instead of the default.
105 */
106#ifndef Clock_driver_timecounter_tick
107static void Clock_driver_timecounter_tick( Clock_isr_argument arg )
108{
109 (void) arg;
110#if defined(CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER)
112#elif defined(RTEMS_SMP) && defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
113 uint32_t cpu_max;
114 uint32_t cpu_index;
115
116 cpu_max = _SMP_Get_processor_maximum();
117
118 for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
119 Per_CPU_Control *cpu;
120
121 cpu = _Per_CPU_Get_by_index( cpu_index );
122
123 if ( _Per_CPU_Is_boot_processor( cpu ) ) {
124 rtems_timecounter_tick();
125 } else if ( _Processor_mask_Is_set( _SMP_Get_online_processors(), cpu_index ) ) {
126 _Watchdog_Tick( cpu );
127 }
128 }
129#else
130 rtems_timecounter_tick();
131#endif
132}
133#endif
134
138#if CLOCK_DRIVER_ISRS_PER_TICK
139 volatile uint32_t Clock_driver_isrs;
140#endif
141
145volatile uint32_t Clock_driver_ticks;
146
147#ifdef Clock_driver_support_shutdown_hardware
148#error "Clock_driver_support_shutdown_hardware() is no longer supported"
149#endif
150
151#if CLOCK_DRIVER_USE_FAST_IDLE
152static bool _Clock_Has_watchdogs(const Per_CPU_Control *cpu)
153{
154 size_t i;
155
156 for (i = 0; i < RTEMS_ARRAY_SIZE(cpu->Watchdog.Header); ++i) {
157 if (_Watchdog_Header_first(&cpu->Watchdog.Header[i]) != NULL) {
158 return true;
159 }
160 }
161
162 return false;
163}
164#endif
165
173void Clock_isr( Clock_isr_argument arg );
174void Clock_isr( Clock_isr_argument arg )
175{
176 /*
177 * Accurate count of ISRs
178 */
179 Clock_driver_ticks += 1;
180
181 #if CLOCK_DRIVER_USE_FAST_IDLE
182 {
183 Clock_driver_timecounter_tick( arg );
184
185 if (_SMP_Get_processor_maximum() == 1) {
186 struct timecounter *tc;
187 uint64_t us_per_tick;
188 uint32_t interval;
189 Per_CPU_Control *cpu_self;
190
191 cpu_self = _Per_CPU_Get();
192 tc = _Timecounter;
194 interval = (uint32_t) ((tc->tc_frequency * us_per_tick) / 1000000);
195
196 while (
197 cpu_self->thread_dispatch_disable_level == cpu_self->isr_nest_level
198 && cpu_self->heir == cpu_self->executing
199 && cpu_self->executing->is_idle
200 && _Clock_Has_watchdogs(cpu_self)
201 ) {
202 ISR_lock_Context lock_context;
203
204 _Timecounter_Acquire(&lock_context);
206 interval,
207 (*tc->tc_get_timecount)(tc),
208 &lock_context
209 );
210 }
211 }
212
213 Clock_driver_support_at_tick( arg );
214 }
215 #else
216 /*
217 * Do the hardware specific per-tick action.
218 *
219 * The counter/timer may or may not be set to automatically reload.
220 */
221 Clock_driver_support_at_tick( arg );
222
223 #if CLOCK_DRIVER_ISRS_PER_TICK
224 /*
225 * The driver is multiple ISRs per clock tick.
226 */
227 if ( !Clock_driver_isrs ) {
228 Clock_driver_timecounter_tick( arg );
229
230 Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
231 }
232 Clock_driver_isrs--;
233 #else
234 /*
235 * The driver is one ISR per clock tick.
236 */
237 Clock_driver_timecounter_tick( arg );
238 #endif
239 #endif
240}
241
243{
244 Clock_driver_ticks = 0;
245
246 /*
247 * Find timer -- some BSPs search buses for hardware timer
248 */
249 Clock_driver_support_find_timer();
250
251 /*
252 * Install vector
253 */
254 Clock_driver_support_install_isr( Clock_isr );
255
256 #ifdef RTEMS_SMP
257 Clock_driver_support_set_interrupt_affinity(
258 _SMP_Get_online_processors()
259 );
260 #endif
261
262 /*
263 * Now initialize the hardware that is the source of the tick ISR.
264 */
265 Clock_driver_support_initialize_hardware();
266
267 /*
268 * If we are counting ISRs per tick, then initialize the counter.
269 */
270 #if CLOCK_DRIVER_ISRS_PER_TICK
271 Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
272 #endif
273}
This header file defines the Clock Driver API.
rtems_status_code rtems_clock_tick(void)
Announces a clock tick.
Definition clocktick.c:46
#define RTEMS_ARRAY_SIZE(_array)
Gets the element count of the array.
Definition basedefs.h:244
ISR_Vector_number rtems_vector_number
This integer type represents interrupt vector numbers.
Definition intr.h:102
#define rtems_configuration_get_microseconds_per_tick()
Gets the number of microseconds per clock tick configured for this application.
Definition config.h:527
void _Clock_Initialize(void)
Initialize the clock driver.
Definition clock.c:56
void _Timecounter_Tick_simple(uint32_t delta, uint32_t offset, ISR_lock_Context *lock_context)
Performs a simple timecounter tick.
#define _Timecounter_Acquire(lock_context)
Acquires the timecounter lock.
Definition timecounter.h:217
struct timecounter * _Timecounter
The current timecounter.
void _Watchdog_Tick(struct Per_CPU_Control *cpu)
Performs a watchdog tick.
Definition watchdogtick.c:76
This header file provides the interfaces of the Processor Mask.
This header file provides the interfaces of the Per-CPU Information.
This header file provides interfaces of the Thread Handler which are used by the implementation and t...
This header file provides interfaces of the Timecounter Handler which are used by the implementation ...
This header file provides interfaces of the SMP Support which are only used by the implementation.
Local ISR lock context for acquire and release pairs.
Definition isrlock.h:94
Per CPU Core Structure.
Definition percpu.h:384
struct _Thread_Control * heir
This is the heir thread for this processor.
Definition percpu.h:473
volatile uint32_t thread_dispatch_disable_level
The thread dispatch critical section nesting counter which is used to prevent context switches at ino...
Definition percpu.h:422
struct _Thread_Control * executing
This is the thread executing on this processor.
Definition percpu.h:457
uint32_t isr_nest_level
Definition percpu.h:406
bool is_idle
Definition thread.h:908
Definition timetc.h:58
This header file provides interfaces of the Watchdog Handler which are only used by the implementatio...