source: rtems/c/src/lib/libbsp/shared/clockdrv_shell.h @ b61d5cac

Last change on this file since b61d5cac was b61d5cac, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 14, 2016 at 8:56:09 AM

bsps: Add CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR

Add CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR clock driver option. If
defined, then do the clock tick processing on the boot processor on
behalf of all other processors. Currently, this is intended as a
workaround for a Qemu shortcoming on ARM.

Update #2737.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup bsp_clock
5 *
6 * @brief Clock Tick Device Driver Shell
7 */
8
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>
24#include <rtems/score/watchdogimpl.h>
25
26#ifdef Clock_driver_nanoseconds_since_last_tick
27#error "Update driver to use the timecounter instead of nanoseconds extension"
28#endif
29
30/**
31 * @defgroup bsp_clock Clock Support
32 *
33 * @ingroup bsp_shared
34 *
35 * @brief Clock support
36 *
37 */
38#if CLOCK_DRIVER_USE_FAST_IDLE && CLOCK_DRIVER_ISRS_PER_TICK
39#error "clockdrv_shell.h: Fast Idle PLUS n ISRs per tick is not supported"
40#endif
41
42/**
43 * @brief This method is rarely used so default it.
44 */
45#ifndef Clock_driver_support_find_timer
46  #define Clock_driver_support_find_timer()
47#endif
48
49/**
50 * @brief Do nothing by default.
51 */
52#ifndef Clock_driver_support_at_tick
53  #define Clock_driver_support_at_tick()
54#endif
55
56/**
57 * @brief Do nothing by default.
58 */
59#ifndef Clock_driver_support_set_interrupt_affinity
60  #define Clock_driver_support_set_interrupt_affinity(online_processors)
61#endif
62
63/*
64 * A specialized clock driver may use for example rtems_timecounter_tick_simple()
65 * instead of the default.
66 */
67#ifndef Clock_driver_timecounter_tick
68static void Clock_driver_timecounter_tick( void )
69{
70#if defined(CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER)
71  rtems_clock_tick();
72#elif defined(RTEMS_SMP) && defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
73  uint32_t cpu_count = _SMP_Get_processor_count();
74  uint32_t cpu_index;
75
76  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
77    Per_CPU_Control *cpu;
78
79    cpu = _Per_CPU_Get_by_index( cpu_index );
80
81    if ( _Per_CPU_Is_boot_processor( cpu ) ) {
82      rtems_timecounter_tick();
83    } else if ( _Processor_mask_Is_set( _SMP_Online_processors, cpu_index ) ) {
84      _Watchdog_Tick( cpu );
85    }
86  }
87#else
88  rtems_timecounter_tick();
89#endif
90}
91#endif
92
93/**
94 * @brief ISRs until next clock tick
95 */
96#if CLOCK_DRIVER_ISRS_PER_TICK
97  volatile uint32_t  Clock_driver_isrs;
98#endif
99
100/**
101 * @brief Clock ticks since initialization
102 */
103volatile uint32_t    Clock_driver_ticks;
104
105void Clock_exit( void );
106
107/**
108 *  @brief Clock_isr
109 *
110 *  This is the clock tick interrupt handler.
111 *
112 *  @param vector Vector number.
113 */
114#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
115    (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
116void Clock_isr(void *arg);
117void Clock_isr(void *arg)
118{
119#else
120rtems_isr Clock_isr(rtems_vector_number vector);
121rtems_isr Clock_isr(
122  rtems_vector_number vector
123)
124{
125#endif
126  /*
127   *  Accurate count of ISRs
128   */
129  Clock_driver_ticks += 1;
130
131  #if CLOCK_DRIVER_USE_FAST_IDLE
132    {
133      struct timecounter *tc = _Timecounter;
134      uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
135      uint32_t interval = (uint32_t)
136        ((tc->tc_frequency * us_per_tick) / 1000000);
137
138      Clock_driver_timecounter_tick();
139
140      while (
141        _Thread_Heir == _Thread_Executing
142          && _Thread_Executing->Start.Entry.Kinds.Idle.entry
143            == rtems_configuration_get_idle_task()
144      ) {
145        ISR_lock_Context lock_context;
146
147        _Timecounter_Acquire(&lock_context);
148        _Timecounter_Tick_simple(
149          interval,
150          (*tc->tc_get_timecount)(tc),
151          &lock_context
152        );
153      }
154
155      Clock_driver_support_at_tick();
156    }
157  #else
158    /*
159     *  Do the hardware specific per-tick action.
160     *
161     *  The counter/timer may or may not be set to automatically reload.
162     */
163    Clock_driver_support_at_tick();
164
165    #if CLOCK_DRIVER_ISRS_PER_TICK
166      /*
167       *  The driver is multiple ISRs per clock tick.
168       */
169      if ( !Clock_driver_isrs ) {
170        Clock_driver_timecounter_tick();
171
172        Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK;
173      }
174      Clock_driver_isrs--;
175    #else
176      /*
177       *  The driver is one ISR per clock tick.
178       */
179      Clock_driver_timecounter_tick();
180    #endif
181  #endif
182}
183
184/**
185 *  @brief Clock_exit
186 *
187 *  This routine allows the clock driver to exit by masking the interrupt and
188 *  disabling the clock's counter.
189 */
190void Clock_exit( void )
191{
192  Clock_driver_support_shutdown_hardware();
193
194  /* do not restore old vector */
195}
196
197/**
198 * @brief Clock_initialize
199 *
200 * This routine initializes the clock driver.
201 *
202 * @param[in] major Clock device major number.
203 * @param[in] minor Clock device minor number.
204 * @param[in] parg  Pointer to optional device driver arguments
205 *
206 * @retval rtems_device_driver status code
207 */
208rtems_device_driver Clock_initialize(
209  rtems_device_major_number major,
210  rtems_device_minor_number minor,
211  void *pargp
212)
213{
214  rtems_isr_entry  Old_ticker;
215
216  Clock_driver_ticks = 0;
217
218  /*
219   *  Find timer -- some BSPs search buses for hardware timer
220   */
221  Clock_driver_support_find_timer();
222
223  /*
224   *  Install vector
225   */
226  (void) Old_ticker;
227  Clock_driver_support_install_isr( Clock_isr, Old_ticker );
228
229  #ifdef RTEMS_SMP
230    Clock_driver_support_set_interrupt_affinity( _SMP_Online_processors );
231  #endif
232
233  /*
234   *  Now initialize the hardware that is the source of the tick ISR.
235   */
236  Clock_driver_support_initialize_hardware();
237
238  atexit( Clock_exit );
239
240  /*
241   *  If we are counting ISRs per tick, then initialize the counter.
242   */
243  #if CLOCK_DRIVER_ISRS_PER_TICK
244    Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
245  #endif
246
247  return RTEMS_SUCCESSFUL;
248}
Note: See TracBrowser for help on using the repository browser.