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

5
Last change on this file since ca4602e was 76ac1ee3, checked in by Sebastian Huber <sebastian.huber@…>, on 12/23/15 at 06:29:47

score: Fix simple timecounter support

Update #2502.

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