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

5
Last change on this file since b61d5cac was b61d5cac, checked in by Sebastian Huber <sebastian.huber@…>, on 06/14/16 at 08:56:09

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
RevLine 
[0c0181d]1/**
[98eb7e78]2 * @file
[b7f2060]3 *
[98eb7e78]4 * @ingroup bsp_clock
5 *
6 * @brief Clock Tick Device Driver Shell
[0c0181d]7 */
8
9/*
[3532ff91]10 *  COPYRIGHT (c) 1989-2014.
[b94554f]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
[c499856]15 *  http://www.rtems.org/license/LICENSE.
[b94554f]16 */
17
18#include <stdlib.h>
19
20#include <bsp.h>
[3532ff91]21#include <rtems/clockdrv.h>
[48fed9a]22#include <rtems/score/percpu.h>
[90d8567]23#include <rtems/score/smpimpl.h>
[b61d5cac]24#include <rtems/score/watchdogimpl.h>
[b94554f]25
[75acd9e]26#ifdef Clock_driver_nanoseconds_since_last_tick
27#error "Update driver to use the timecounter instead of nanoseconds extension"
28#endif
29
[98eb7e78]30/**
31 * @defgroup bsp_clock Clock Support
32 *
[296c74e6]33 * @ingroup bsp_shared
[98eb7e78]34 *
35 * @brief Clock support
36 *
37 */
[b7f2060]38#if CLOCK_DRIVER_USE_FAST_IDLE && CLOCK_DRIVER_ISRS_PER_TICK
[79fee34]39#error "clockdrv_shell.h: Fast Idle PLUS n ISRs per tick is not supported"
[b94554f]40#endif
41
[98eb7e78]42/**
43 * @brief This method is rarely used so default it.
[b94554f]44 */
45#ifndef Clock_driver_support_find_timer
[f1e8903]46  #define Clock_driver_support_find_timer()
[b94554f]47#endif
48
[76ac1ee3]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
[90d8567]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
[75acd9e]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
[b61d5cac]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}
[75acd9e]91#endif
92
[98eb7e78]93/**
94 * @brief ISRs until next clock tick
[b94554f]95 */
[d473dc0]96#if CLOCK_DRIVER_ISRS_PER_TICK
[f1e8903]97  volatile uint32_t  Clock_driver_isrs;
[b94554f]98#endif
99
[98eb7e78]100/**
101 * @brief Clock ticks since initialization
[b94554f]102 */
[6083017]103volatile uint32_t    Clock_driver_ticks;
[b94554f]104
105void Clock_exit( void );
106
[98eb7e78]107/**
108 *  @brief Clock_isr
[b94554f]109 *
110 *  This is the clock tick interrupt handler.
111 *
[98eb7e78]112 *  @param vector Vector number.
[b94554f]113 */
[314fab55]114#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
115    (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
[56c6888]116void Clock_isr(void *arg);
[37f938d7]117void Clock_isr(void *arg)
[0c0181d]118{
[b7f2060]119#else
[0c0181d]120rtems_isr Clock_isr(rtems_vector_number vector);
[b94554f]121rtems_isr Clock_isr(
122  rtems_vector_number vector
123)
124{
[0c0181d]125#endif
[b94554f]126  /*
127   *  Accurate count of ISRs
128   */
129  Clock_driver_ticks += 1;
130
[b7f2060]131  #if CLOCK_DRIVER_USE_FAST_IDLE
[75acd9e]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
[ccd5434]142          && _Thread_Executing->Start.Entry.Kinds.Idle.entry
143            == rtems_configuration_get_idle_task()
[75acd9e]144      ) {
[76ac1ee3]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        );
[75acd9e]153      }
[f1e8903]154
[75acd9e]155      Clock_driver_support_at_tick();
156    }
[f1e8903]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
[b7f2060]165    #if CLOCK_DRIVER_ISRS_PER_TICK
[f1e8903]166      /*
167       *  The driver is multiple ISRs per clock tick.
168       */
169      if ( !Clock_driver_isrs ) {
[75acd9e]170        Clock_driver_timecounter_tick();
[f1e8903]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       */
[75acd9e]179      Clock_driver_timecounter_tick();
[f1e8903]180    #endif
181  #endif
[b94554f]182}
183
[98eb7e78]184/**
185 *  @brief Clock_exit
[b94554f]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
[98eb7e78]197/**
198 * @brief Clock_initialize
[b94554f]199 *
[98eb7e78]200 * This routine initializes the clock driver.
[b94554f]201 *
[98eb7e78]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
[b94554f]205 *
[98eb7e78]206 * @retval rtems_device_driver status code
[b94554f]207 */
208rtems_device_driver Clock_initialize(
209  rtems_device_major_number major,
210  rtems_device_minor_number minor,
211  void *pargp
212)
213{
[6083017]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   */
[ab49921]226  (void) Old_ticker;
[6083017]227  Clock_driver_support_install_isr( Clock_isr, Old_ticker );
228
[90d8567]229  #ifdef RTEMS_SMP
230    Clock_driver_support_set_interrupt_affinity( _SMP_Online_processors );
231  #endif
232
[6083017]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 );
[b94554f]239
240  /*
241   *  If we are counting ISRs per tick, then initialize the counter.
242   */
[b7f2060]243  #if CLOCK_DRIVER_ISRS_PER_TICK
[3109857c]244    Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
[f1e8903]245  #endif
[b94554f]246
247  return RTEMS_SUCCESSFUL;
248}
Note: See TracBrowser for help on using the repository browser.