source: rtems/bsps/shared/dev/clock/clockimpl.h @ d6ebf40

Last change on this file since d6ebf40 was d6ebf40, checked in by Joel Sherrill <joel@…>, on 06/14/22 at 17:15:38

bsps/shared/*: Change license to BSD-2

Updates #3053.

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup bsp_clock
7 *
8 * @brief Clock Tick Device Driver Shell
9 */
10
11/*
12 *  COPYRIGHT (c) 1989-2014.
13 *  On-Line Applications Research Corporation (OAR).
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <stdlib.h>
38
39#include <bsp.h>
40#include <rtems/clockdrv.h>
41#include <rtems/score/percpu.h>
42#include <rtems/score/smpimpl.h>
43#include <rtems/score/timecounter.h>
44#include <rtems/score/thread.h>
45#include <rtems/score/watchdogimpl.h>
46
47#ifdef Clock_driver_nanoseconds_since_last_tick
48#error "Update driver to use the timecounter instead of nanoseconds extension"
49#endif
50
51/**
52 * @defgroup bsp_clock Clock Support
53 *
54 * @ingroup RTEMSBSPsShared
55 *
56 * @brief Clock support
57 *
58 */
59#if CLOCK_DRIVER_USE_FAST_IDLE && CLOCK_DRIVER_ISRS_PER_TICK
60#error "Fast Idle PLUS n ISRs per tick is not supported"
61#endif
62
63/**
64 * @brief Do nothing by default.
65 */
66#ifndef Clock_driver_support_install_isr
67  #define Clock_driver_support_install_isr(isr)
68#endif
69
70/**
71 * @brief This method is rarely used so default it.
72 */
73#ifndef Clock_driver_support_find_timer
74  #define Clock_driver_support_find_timer()
75#endif
76
77/**
78 * @brief Do nothing by default.
79 */
80#ifndef Clock_driver_support_at_tick
81  #define Clock_driver_support_at_tick()
82#endif
83
84/**
85 * @brief Do nothing by default.
86 */
87#ifndef Clock_driver_support_set_interrupt_affinity
88  #define Clock_driver_support_set_interrupt_affinity(online_processors)
89#endif
90
91/*
92 * A specialized clock driver may use for example rtems_timecounter_tick_simple()
93 * instead of the default.
94 */
95#ifndef Clock_driver_timecounter_tick
96static void Clock_driver_timecounter_tick( void )
97{
98#if defined(CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER)
99  rtems_clock_tick();
100#elif defined(RTEMS_SMP) && defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
101  uint32_t cpu_max;
102  uint32_t cpu_index;
103
104  cpu_max = _SMP_Get_processor_maximum();
105
106  for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
107    Per_CPU_Control *cpu;
108
109    cpu = _Per_CPU_Get_by_index( cpu_index );
110
111    if ( _Per_CPU_Is_boot_processor( cpu ) ) {
112      rtems_timecounter_tick();
113    } else if ( _Processor_mask_Is_set( _SMP_Get_online_processors(), cpu_index ) ) {
114      _Watchdog_Tick( cpu );
115    }
116  }
117#else
118  rtems_timecounter_tick();
119#endif
120}
121#endif
122
123/**
124 * @brief ISRs until next clock tick
125 */
126#if CLOCK_DRIVER_ISRS_PER_TICK
127  volatile uint32_t  Clock_driver_isrs;
128#endif
129
130/**
131 * @brief Clock ticks since initialization
132 */
133volatile uint32_t    Clock_driver_ticks;
134
135#ifdef Clock_driver_support_shutdown_hardware
136#error "Clock_driver_support_shutdown_hardware() is no longer supported"
137#endif
138
139/**
140 *  @brief Clock_isr
141 *
142 *  This is the clock tick interrupt handler.
143 *
144 *  @param vector Vector number.
145 */
146#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
147    (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
148void Clock_isr(void *arg);
149void Clock_isr(void *arg)
150{
151#else
152rtems_isr Clock_isr(rtems_vector_number vector);
153rtems_isr Clock_isr(
154  rtems_vector_number vector
155)
156{
157#endif
158  /*
159   *  Accurate count of ISRs
160   */
161  Clock_driver_ticks += 1;
162
163  #if CLOCK_DRIVER_USE_FAST_IDLE
164    {
165      Clock_driver_timecounter_tick();
166
167      if (_SMP_Get_processor_maximum() == 1) {
168        struct timecounter *tc;
169        uint64_t            us_per_tick;
170        uint32_t            interval;
171        Per_CPU_Control    *cpu_self;
172
173        cpu_self = _Per_CPU_Get();
174        tc = _Timecounter;
175        us_per_tick = rtems_configuration_get_microseconds_per_tick();
176        interval = (uint32_t) ((tc->tc_frequency * us_per_tick) / 1000000);
177
178        while (
179          cpu_self->thread_dispatch_disable_level == cpu_self->isr_nest_level
180            && cpu_self->heir == cpu_self->executing
181            && cpu_self->executing->is_idle
182        ) {
183          ISR_lock_Context lock_context;
184
185          _Timecounter_Acquire(&lock_context);
186          _Timecounter_Tick_simple(
187            interval,
188            (*tc->tc_get_timecount)(tc),
189            &lock_context
190          );
191        }
192      }
193
194      Clock_driver_support_at_tick();
195    }
196  #else
197    /*
198     *  Do the hardware specific per-tick action.
199     *
200     *  The counter/timer may or may not be set to automatically reload.
201     */
202    Clock_driver_support_at_tick();
203
204    #if CLOCK_DRIVER_ISRS_PER_TICK
205      /*
206       *  The driver is multiple ISRs per clock tick.
207       */
208      if ( !Clock_driver_isrs ) {
209        Clock_driver_timecounter_tick();
210
211        Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
212      }
213      Clock_driver_isrs--;
214    #else
215      /*
216       *  The driver is one ISR per clock tick.
217       */
218      Clock_driver_timecounter_tick();
219    #endif
220  #endif
221}
222
223void _Clock_Initialize( void )
224{
225  Clock_driver_ticks = 0;
226
227  /*
228   *  Find timer -- some BSPs search buses for hardware timer
229   */
230  Clock_driver_support_find_timer();
231
232  /*
233   *  Install vector
234   */
235  Clock_driver_support_install_isr( Clock_isr );
236
237  #ifdef RTEMS_SMP
238    Clock_driver_support_set_interrupt_affinity(
239      _SMP_Get_online_processors()
240    );
241  #endif
242
243  /*
244   *  Now initialize the hardware that is the source of the tick ISR.
245   */
246  Clock_driver_support_initialize_hardware();
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}
Note: See TracBrowser for help on using the repository browser.