File indexing completed on 2025-05-11 08:24:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #include <stdlib.h>
0041
0042 #include <bsp.h>
0043 #include <rtems/clockdrv.h>
0044 #include <rtems/score/percpu.h>
0045 #include <rtems/score/processormaskimpl.h>
0046 #include <rtems/score/smpimpl.h>
0047 #include <rtems/score/timecounter.h>
0048 #include <rtems/score/thread.h>
0049 #include <rtems/score/watchdogimpl.h>
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 #ifdef Clock_driver_nanoseconds_since_last_tick
0060 #error "Update driver to use the timecounter instead of nanoseconds extension"
0061 #endif
0062
0063 #if CLOCK_DRIVER_USE_FAST_IDLE && CLOCK_DRIVER_ISRS_PER_TICK
0064 #error "Fast Idle PLUS n ISRs per tick is not supported"
0065 #endif
0066
0067 #if defined(BSP_FEATURE_IRQ_EXTENSION) || \
0068 (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
0069 typedef void * Clock_isr_argument;
0070 #else
0071 typedef rtems_vector_number Clock_isr_argument;
0072 #endif
0073
0074
0075
0076
0077 #ifndef Clock_driver_support_install_isr
0078 #define Clock_driver_support_install_isr(isr)
0079 #endif
0080
0081
0082
0083
0084 #ifndef Clock_driver_support_find_timer
0085 #define Clock_driver_support_find_timer()
0086 #endif
0087
0088
0089
0090
0091 #ifndef Clock_driver_support_at_tick
0092 #define Clock_driver_support_at_tick( arg ) do { (void) arg; } while (0)
0093 #endif
0094
0095
0096
0097
0098 #ifndef Clock_driver_support_set_interrupt_affinity
0099 #define Clock_driver_support_set_interrupt_affinity(online_processors)
0100 #endif
0101
0102
0103
0104
0105
0106 #ifndef Clock_driver_timecounter_tick
0107 static void Clock_driver_timecounter_tick( Clock_isr_argument arg )
0108 {
0109 (void) arg;
0110 #if defined(CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER)
0111 rtems_clock_tick();
0112 #elif defined(RTEMS_SMP) && defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
0113 uint32_t cpu_max;
0114 uint32_t cpu_index;
0115
0116 cpu_max = _SMP_Get_processor_maximum();
0117
0118 for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
0119 Per_CPU_Control *cpu;
0120
0121 cpu = _Per_CPU_Get_by_index( cpu_index );
0122
0123 if ( _Per_CPU_Is_boot_processor( cpu ) ) {
0124 rtems_timecounter_tick();
0125 } else if ( _Processor_mask_Is_set( _SMP_Get_online_processors(), cpu_index ) ) {
0126 _Watchdog_Tick( cpu );
0127 }
0128 }
0129 #else
0130 rtems_timecounter_tick();
0131 #endif
0132 }
0133 #endif
0134
0135
0136
0137
0138 #if CLOCK_DRIVER_ISRS_PER_TICK
0139 volatile uint32_t Clock_driver_isrs;
0140 #endif
0141
0142
0143
0144
0145 volatile uint32_t Clock_driver_ticks;
0146
0147 #ifdef Clock_driver_support_shutdown_hardware
0148 #error "Clock_driver_support_shutdown_hardware() is no longer supported"
0149 #endif
0150
0151 #if CLOCK_DRIVER_USE_FAST_IDLE
0152 static bool _Clock_Has_watchdogs(const Per_CPU_Control *cpu)
0153 {
0154 size_t i;
0155
0156 for (i = 0; i < RTEMS_ARRAY_SIZE(cpu->Watchdog.Header); ++i) {
0157 if (_Watchdog_Header_first(&cpu->Watchdog.Header[i]) != NULL) {
0158 return true;
0159 }
0160 }
0161
0162 return false;
0163 }
0164 #endif
0165
0166
0167
0168
0169
0170
0171
0172
0173 void Clock_isr( Clock_isr_argument arg );
0174 void Clock_isr( Clock_isr_argument arg )
0175 {
0176
0177
0178
0179 Clock_driver_ticks += 1;
0180
0181 #if CLOCK_DRIVER_USE_FAST_IDLE
0182 {
0183 Clock_driver_timecounter_tick( arg );
0184
0185 if (_SMP_Get_processor_maximum() == 1) {
0186 struct timecounter *tc;
0187 uint64_t us_per_tick;
0188 uint32_t interval;
0189 Per_CPU_Control *cpu_self;
0190
0191 cpu_self = _Per_CPU_Get();
0192 tc = _Timecounter;
0193 us_per_tick = rtems_configuration_get_microseconds_per_tick();
0194 interval = (uint32_t) ((tc->tc_frequency * us_per_tick) / 1000000);
0195
0196 while (
0197 cpu_self->thread_dispatch_disable_level == cpu_self->isr_nest_level
0198 && cpu_self->heir == cpu_self->executing
0199 && cpu_self->executing->is_idle
0200 && _Clock_Has_watchdogs(cpu_self)
0201 ) {
0202 ISR_lock_Context lock_context;
0203
0204 _Timecounter_Acquire(&lock_context);
0205 _Timecounter_Tick_simple(
0206 interval,
0207 (*tc->tc_get_timecount)(tc),
0208 &lock_context
0209 );
0210 }
0211 }
0212
0213 Clock_driver_support_at_tick( arg );
0214 }
0215 #else
0216
0217
0218
0219
0220
0221 Clock_driver_support_at_tick( arg );
0222
0223 #if CLOCK_DRIVER_ISRS_PER_TICK
0224
0225
0226
0227 if ( !Clock_driver_isrs ) {
0228 Clock_driver_timecounter_tick( arg );
0229
0230 Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
0231 }
0232 Clock_driver_isrs--;
0233 #else
0234
0235
0236
0237 Clock_driver_timecounter_tick( arg );
0238 #endif
0239 #endif
0240 }
0241
0242 void _Clock_Initialize( void )
0243 {
0244 Clock_driver_ticks = 0;
0245
0246
0247
0248
0249 Clock_driver_support_find_timer();
0250
0251
0252
0253
0254 Clock_driver_support_install_isr( Clock_isr );
0255
0256 #ifdef RTEMS_SMP
0257 Clock_driver_support_set_interrupt_affinity(
0258 _SMP_Get_online_processors()
0259 );
0260 #endif
0261
0262
0263
0264
0265 Clock_driver_support_initialize_hardware();
0266
0267
0268
0269
0270 #if CLOCK_DRIVER_ISRS_PER_TICK
0271 Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
0272 #endif
0273 }