RTEMS  5.0.0
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_count = _SMP_Get_processor_count();
83  uint32_t cpu_index;
84 
85  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
86  Per_CPU_Control *cpu;
87 
88  cpu = _Per_CPU_Get_by_index( cpu_index );
89 
90  if ( _Per_CPU_Is_boot_processor( cpu ) ) {
92  } else if ( _Processor_mask_Is_set( _SMP_Get_online_processors(), cpu_index ) ) {
93  _Watchdog_Tick( cpu );
94  }
95  }
96 #else
98 #endif
99 }
100 #endif
101 
105 #if CLOCK_DRIVER_ISRS_PER_TICK
106  volatile uint32_t Clock_driver_isrs;
107 #endif
108 
112 volatile uint32_t Clock_driver_ticks;
113 
114 #ifdef Clock_driver_support_shutdown_hardware
115 #error "Clock_driver_support_shutdown_hardware() is no longer supported"
116 #endif
117 
125 #if defined(BSP_FEATURE_IRQ_EXTENSION) || \
126  (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
127 void Clock_isr(void *arg);
128 void Clock_isr(void *arg)
129 {
130 #else
133  rtems_vector_number vector
134 )
135 {
136 #endif
137  /*
138  * Accurate count of ISRs
139  */
140  Clock_driver_ticks += 1;
141 
142  #if CLOCK_DRIVER_USE_FAST_IDLE
143  {
144  struct timecounter *tc = _Timecounter;
145  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
146  uint32_t interval = (uint32_t)
147  ((tc->tc_frequency * us_per_tick) / 1000000);
148 
149  Clock_driver_timecounter_tick();
150 
152  while (
153  _Thread_Heir == _Thread_Executing && _Thread_Executing->is_idle
154  ) {
155  ISR_lock_Context lock_context;
156 
157  _Timecounter_Acquire(&lock_context);
159  interval,
160  (*tc->tc_get_timecount)(tc),
161  &lock_context
162  );
163  }
164  }
165 
167  }
168  #else
169  /*
170  * Do the hardware specific per-tick action.
171  *
172  * The counter/timer may or may not be set to automatically reload.
173  */
175 
176  #if CLOCK_DRIVER_ISRS_PER_TICK
177  /*
178  * The driver is multiple ISRs per clock tick.
179  */
180  if ( !Clock_driver_isrs ) {
181  Clock_driver_timecounter_tick();
182 
183  Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK;
184  }
185  Clock_driver_isrs--;
186  #else
187  /*
188  * The driver is one ISR per clock tick.
189  */
190  Clock_driver_timecounter_tick();
191  #endif
192  #endif
193 }
194 
207  rtems_device_major_number major,
208  rtems_device_minor_number minor,
209  void *pargp
210 )
211 {
212  Clock_driver_ticks = 0;
213 
214  /*
215  * Find timer -- some BSPs search buses for hardware timer
216  */
218 
219  /*
220  * Install vector
221  */
223 
224  #ifdef RTEMS_SMP
226  _SMP_Get_online_processors()
227  );
228  #endif
229 
230  /*
231  * Now initialize the hardware that is the source of the tick ISR.
232  */
233  Clock_driver_support_initialize_hardware();
234 
235  /*
236  * If we are counting ISRs per tick, then initialize the counter.
237  */
238  #if CLOCK_DRIVER_ISRS_PER_TICK
239  Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
240  #endif
241 
242  return RTEMS_SUCCESSFUL;
243 }
Definition: status.h:47
#define Clock_driver_support_install_isr(isr)
Do nothing by default.
Definition: clockimpl.h:48
#define rtems_configuration_is_smp_enabled()
Returns true if the SMP mode of operation is enabled, and false otherwise.
Definition: config.h:332
void _Watchdog_Tick(struct Per_CPU_Control *cpu)
Performs a watchdog tick.
Definition: watchdogtick.c:54
rtems_device_driver Clock_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *pargp)
Clock_initialize.
Definition: clockimpl.h:206
#define Clock_driver_support_find_timer()
This method is rarely used so default it.
Definition: clockimpl.h:55
Inlined Routines in the Watchdog Handler.
#define _Timecounter_Acquire(lock_context)
Lock to protect the timecounter mechanic.
Definition: timecounter.h:199
struct timecounter * _Timecounter
The current timecounter.
ISR_Vector_number rtems_vector_number
Control block type used to manage the vectors.
Definition: intr.h:47
RTEMS_INLINE_ROUTINE void rtems_timecounter_tick(void)
Performs a timecounter tick.
Definition: timecounter.h:81
rtems_status_code rtems_clock_tick(void)
Announce a Clock Tick.
Definition: clocktick.c:25
ISR_Handler rtems_isr
Return type for interrupt handler.
Definition: intr.h:52
rtems_status_code
Classic API Status.
Definition: status.h:43
Definition: timetc.h:46
Per CPU Core Structure.
Definition: percpu.h:290
#define Clock_driver_support_set_interrupt_affinity(online_processors)
Do nothing by default.
Definition: clockimpl.h:69
volatile uint32_t Clock_driver_ticks
ISRs until next clock tick.
Definition: clockimpl.h:112
Clock Driver for all Boards.
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
void _Timecounter_Tick_simple(uint32_t delta, uint32_t offset, ISR_lock_Context *lock_context)
Performs a simple timecounter tick.
Constants and Structures Related with the Thread Control Block.
rtems_isr Clock_isr(rtems_vector_number vector)
Clock_isr.
Definition: clockimpl.h:132
Timecounter API.
#define Clock_driver_support_at_tick()
Do nothing by default.
Definition: clockimpl.h:62
SuperCore SMP Implementation.