RTEMS
clockimpl.h
Go to the documentation of this file.
1 
9 /*
10  * COPYRIGHT (c) 1989-2014.
11  * On-Line Applications Research Corporation (OAR).
12  *
13  * The license and distribution terms for this file may be
14  * found in the file LICENSE in this distribution or at
15  * http://www.rtems.org/license/LICENSE.
16  */
17 
18 #include <stdlib.h>
19 
20 #include <bsp.h>
21 #include <rtems/clockdrv.h>
22 #include <rtems/score/percpu.h>
23 #include <rtems/score/smpimpl.h>
25 #include <rtems/score/thread.h>
27 
28 #ifdef Clock_driver_nanoseconds_since_last_tick
29 #error "Update driver to use the timecounter instead of nanoseconds extension"
30 #endif
31 
40 #if CLOCK_DRIVER_USE_FAST_IDLE && CLOCK_DRIVER_ISRS_PER_TICK
41 #error "Fast Idle PLUS n ISRs per tick is not supported"
42 #endif
43 
47 #ifndef Clock_driver_support_install_isr
48  #define Clock_driver_support_install_isr(isr)
49 #endif
50 
54 #ifndef Clock_driver_support_find_timer
55  #define Clock_driver_support_find_timer()
56 #endif
57 
61 #ifndef Clock_driver_support_at_tick
62  #define Clock_driver_support_at_tick()
63 #endif
64 
68 #ifndef Clock_driver_support_set_interrupt_affinity
69  #define Clock_driver_support_set_interrupt_affinity(online_processors)
70 #endif
71 
72 /*
73  * A specialized clock driver may use for example rtems_timecounter_tick_simple()
74  * instead of the default.
75  */
76 #ifndef Clock_driver_timecounter_tick
77 static void Clock_driver_timecounter_tick( void )
78 {
79 #if defined(CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER)
81 #elif defined(RTEMS_SMP) && defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
82  uint32_t cpu_max;
83  uint32_t cpu_index;
84 
85  cpu_max = _SMP_Get_processor_maximum();
86 
87  for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
88  Per_CPU_Control *cpu;
89 
90  cpu = _Per_CPU_Get_by_index( cpu_index );
91 
92  if ( _Per_CPU_Is_boot_processor( cpu ) ) {
94  } else if ( _Processor_mask_Is_set( _SMP_Get_online_processors(), cpu_index ) ) {
95  _Watchdog_Tick( cpu );
96  }
97  }
98 #else
100 #endif
101 }
102 #endif
103 
107 #if CLOCK_DRIVER_ISRS_PER_TICK
108  volatile uint32_t Clock_driver_isrs;
109 #endif
110 
114 volatile uint32_t Clock_driver_ticks;
115 
116 #ifdef Clock_driver_support_shutdown_hardware
117 #error "Clock_driver_support_shutdown_hardware() is no longer supported"
118 #endif
119 
127 #if defined(BSP_FEATURE_IRQ_EXTENSION) || \
128  (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
129 void Clock_isr(void *arg);
130 void Clock_isr(void *arg)
131 {
132 #else
135  rtems_vector_number vector
136 )
137 {
138 #endif
139  /*
140  * Accurate count of ISRs
141  */
142  Clock_driver_ticks += 1;
143 
144  #if CLOCK_DRIVER_USE_FAST_IDLE
145  {
146  Clock_driver_timecounter_tick();
147 
148  if (_SMP_Get_processor_maximum() == 1) {
149  struct timecounter *tc;
150  uint64_t us_per_tick;
151  uint32_t interval;
152  Per_CPU_Control *cpu_self;
153 
154  cpu_self = _Per_CPU_Get();
155  tc = _Timecounter;
157  interval = (uint32_t) ((tc->tc_frequency * us_per_tick) / 1000000);
158 
159  while (
160  cpu_self->thread_dispatch_disable_level == cpu_self->isr_nest_level
161  && cpu_self->heir == cpu_self->executing
162  && cpu_self->executing->is_idle
163  ) {
164  ISR_lock_Context lock_context;
165 
166  _Timecounter_Acquire(&lock_context);
168  interval,
169  (*tc->tc_get_timecount)(tc),
170  &lock_context
171  );
172  }
173  }
174 
176  }
177  #else
178  /*
179  * Do the hardware specific per-tick action.
180  *
181  * The counter/timer may or may not be set to automatically reload.
182  */
184 
185  #if CLOCK_DRIVER_ISRS_PER_TICK
186  /*
187  * The driver is multiple ISRs per clock tick.
188  */
189  if ( !Clock_driver_isrs ) {
190  Clock_driver_timecounter_tick();
191 
192  Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
193  }
194  Clock_driver_isrs--;
195  #else
196  /*
197  * The driver is one ISR per clock tick.
198  */
199  Clock_driver_timecounter_tick();
200  #endif
201  #endif
202 }
203 
204 void _Clock_Initialize( void )
205 {
206  Clock_driver_ticks = 0;
207 
208  /*
209  * Find timer -- some BSPs search buses for hardware timer
210  */
212 
213  /*
214  * Install vector
215  */
217 
218  #ifdef RTEMS_SMP
221  );
222  #endif
223 
224  /*
225  * Now initialize the hardware that is the source of the tick ISR.
226  */
227  Clock_driver_support_initialize_hardware();
228 
229  /*
230  * If we are counting ISRs per tick, then initialize the counter.
231  */
232  #if CLOCK_DRIVER_ISRS_PER_TICK
233  Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
234  #endif
235 }
#define Clock_driver_support_install_isr(isr)
Do nothing by default.
Definition: clockimpl.h:48
volatile uint32_t Clock_driver_ticks
ISRs until next clock tick.
Definition: clockimpl.h:114
#define Clock_driver_support_find_timer()
This method is rarely used so default it.
Definition: clockimpl.h:55
void _Timecounter_Tick_simple(uint32_t delta, uint32_t offset, ISR_lock_Context *lock_context)
Performs a simple timecounter tick.
Definition: kern_tc.c:2142
struct _Thread_Control * executing
This is the thread executing on this processor.
Definition: percpu.h:420
struct timecounter * _Timecounter
The current timecounter.
Inlined Routines in the Watchdog Handler.
static __inline__ const Processor_mask * _SMP_Get_online_processors(void)
Gets all online processors.
Definition: smpimpl.h:318
#define _Timecounter_Acquire(lock_context)
Lock to protect the timecounter mechanic.
Definition: timecounter.h:201
RTEMS_INLINE_ROUTINE bool _Processor_mask_Is_set(const Processor_mask *mask, uint32_t index)
Checks if the specified index bit of the mask is set.
Per CPU Core Structure.
Definition: percpu.h:347
#define Clock_driver_support_set_interrupt_affinity(online_processors)
Do nothing by default.
Definition: clockimpl.h:69
uint32_t isr_nest_level
Definition: percpu.h:369
void Clock_isr(void *arg)
Clock_isr.
Definition: clockimpl.h:130
#define rtems_configuration_get_microseconds_per_tick()
Returns the number of microseconds per clock tick configured for this application.
Definition: config.h:205
struct _Thread_Control * heir
This is the heir thread for this processor.
Definition: percpu.h:436
void _Clock_Initialize(void)
Initialize the clock driver.
Definition: clockimpl.h:204
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:385
static __inline__ void rtems_timecounter_tick(void)
Performs a timecounter tick.
Definition: timecounter.h:83
Clock Driver API.
ISR_Handler rtems_isr
%
Definition: intr.h:202
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
ISR_Vector_number rtems_vector_number
%
Definition: intr.h:90
Constants and Structures Related with the Thread Control Block.
Timecounter API.
#define Clock_driver_support_at_tick()
Do nothing by default.
Definition: clockimpl.h:62
SuperCore SMP Implementation.
rtems_status_code rtems_clock_tick(void)
%
void _Watchdog_Tick(struct Per_CPU_Control *cpu)
Performs a watchdog tick.
Definition: watchdogtick.c:54
bool is_idle
Definition: thread.h:789