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

Last change on this file since 30be024a was 30be024a, checked in by Sebastian Huber <sebastian.huber@…>, on Aug 3, 2017 at 12:48:04 PM

Optional Clock_driver_support_shutdown_hardware()

Make Clock_driver_support_shutdown_hardware() optional. This avoids
the atexit() support on memory constrained targets.

  • Property mode set to 100644
File size: 5.6 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_Get_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
105#ifdef Clock_driver_support_shutdown_hardware
106void Clock_exit( void );
107#endif
108
109/**
110 *  @brief Clock_isr
111 *
112 *  This is the clock tick interrupt handler.
113 *
114 *  @param vector Vector number.
115 */
116#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
117    (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
118void Clock_isr(void *arg);
119void Clock_isr(void *arg)
120{
121#else
122rtems_isr Clock_isr(rtems_vector_number vector);
123rtems_isr Clock_isr(
124  rtems_vector_number vector
125)
126{
127#endif
128  /*
129   *  Accurate count of ISRs
130   */
131  Clock_driver_ticks += 1;
132
133  #if CLOCK_DRIVER_USE_FAST_IDLE
134    {
135      struct timecounter *tc = _Timecounter;
136      uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
137      uint32_t interval = (uint32_t)
138        ((tc->tc_frequency * us_per_tick) / 1000000);
139
140      Clock_driver_timecounter_tick();
141
142      if (!rtems_configuration_is_smp_enabled()) {
143        while (
144          _Thread_Heir == _Thread_Executing && _Thread_Executing->is_idle
145        ) {
146          ISR_lock_Context lock_context;
147
148          _Timecounter_Acquire(&lock_context);
149          _Timecounter_Tick_simple(
150            interval,
151            (*tc->tc_get_timecount)(tc),
152            &lock_context
153          );
154        }
155      }
156
157      Clock_driver_support_at_tick();
158    }
159  #else
160    /*
161     *  Do the hardware specific per-tick action.
162     *
163     *  The counter/timer may or may not be set to automatically reload.
164     */
165    Clock_driver_support_at_tick();
166
167    #if CLOCK_DRIVER_ISRS_PER_TICK
168      /*
169       *  The driver is multiple ISRs per clock tick.
170       */
171      if ( !Clock_driver_isrs ) {
172        Clock_driver_timecounter_tick();
173
174        Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK;
175      }
176      Clock_driver_isrs--;
177    #else
178      /*
179       *  The driver is one ISR per clock tick.
180       */
181      Clock_driver_timecounter_tick();
182    #endif
183  #endif
184}
185
186#ifdef Clock_driver_support_shutdown_hardware
187/**
188 *  @brief Clock_exit
189 *
190 *  This routine allows the clock driver to exit by masking the interrupt and
191 *  disabling the clock's counter.
192 */
193void Clock_exit( void )
194{
195  Clock_driver_support_shutdown_hardware();
196
197  /* do not restore old vector */
198}
199#endif
200
201/**
202 * @brief Clock_initialize
203 *
204 * This routine initializes the clock driver.
205 *
206 * @param[in] major Clock device major number.
207 * @param[in] minor Clock device minor number.
208 * @param[in] parg  Pointer to optional device driver arguments
209 *
210 * @retval rtems_device_driver status code
211 */
212rtems_device_driver Clock_initialize(
213  rtems_device_major_number major,
214  rtems_device_minor_number minor,
215  void *pargp
216)
217{
218  rtems_isr_entry  Old_ticker;
219
220  Clock_driver_ticks = 0;
221
222  /*
223   *  Find timer -- some BSPs search buses for hardware timer
224   */
225  Clock_driver_support_find_timer();
226
227  /*
228   *  Install vector
229   */
230  (void) Old_ticker;
231  Clock_driver_support_install_isr( Clock_isr, Old_ticker );
232
233  #ifdef RTEMS_SMP
234    Clock_driver_support_set_interrupt_affinity(
235      _SMP_Get_online_processors()
236    );
237  #endif
238
239  /*
240   *  Now initialize the hardware that is the source of the tick ISR.
241   */
242  Clock_driver_support_initialize_hardware();
243
244#ifdef Clock_driver_support_shutdown_hardware
245  atexit( Clock_exit );
246#endif
247
248  /*
249   *  If we are counting ISRs per tick, then initialize the counter.
250   */
251  #if CLOCK_DRIVER_ISRS_PER_TICK
252    Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
253  #endif
254
255  return RTEMS_SUCCESSFUL;
256}
Note: See TracBrowser for help on using the repository browser.