RTEMS 6.1-rc7
Loading...
Searching...
No Matches
clockimpl.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
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
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 */
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
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 */
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{
245
246 /*
247 * Find timer -- some BSPs search buses for hardware timer
248 */
250
251 /*
252 * Install vector
253 */
255
256 #ifdef RTEMS_SMP
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}
#define Clock_driver_support_find_timer()
This method is rarely used so default it.
Definition: clockimpl.h:85
#define Clock_driver_support_set_interrupt_affinity(online_processors)
Do nothing by default.
Definition: clockimpl.h:99
#define Clock_driver_support_at_tick(arg)
Do nothing by default.
Definition: clockimpl.h:92
#define Clock_driver_support_install_isr(isr)
Do nothing by default.
Definition: clockimpl.h:78
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
volatile uint32_t Clock_driver_ticks
ISRs until next clock tick.
Definition: clockimpl.h:145
void _Clock_Initialize(void)
Initialize the clock driver.
Definition: clockimpl.h:242
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
Watchdog_Header Header[PER_CPU_WATCHDOG_COUNT]
Header for watchdogs.
Definition: percpu.h:513
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
struct Per_CPU_Control::@4403 Watchdog
Watchdog state for this processor.
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...