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

5
Last change on this file since 90d8567 was 90d8567, checked in by Sebastian Huber <sebastian.huber@…>, on 02/18/16 at 07:36:16

score: Distribute clock tick to all online CPUs

Update #2554.

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