File indexing completed on 2025-05-11 08:24:54
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 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040
0041 #include "tx-support.h"
0042
0043 #include <rtems/sysinit.h>
0044 #include <rtems/timecounter.h>
0045 #include <rtems/score/atomic.h>
0046 #include <rtems/score/percpu.h>
0047 #include <rtems/score/smpimpl.h>
0048 #include <rtems/score/threaddispatch.h>
0049
0050 typedef struct {
0051 struct timecounter base;
0052 GetTimecountHandler handler;
0053 Atomic_Ulong counter;
0054 } TimecounterControl;
0055
0056 static TimecounterControl TimecounterInstance;
0057
0058 GetTimecountHandler SetGetTimecountHandler( GetTimecountHandler handler )
0059 {
0060 GetTimecountHandler previous;
0061
0062 previous = TimecounterInstance.handler;
0063 TimecounterInstance.handler = handler;
0064 return previous;
0065 }
0066
0067 uint32_t GetTimecountCounter( void )
0068 {
0069 return (uint32_t) _Atomic_Load_ulong(
0070 &TimecounterInstance.counter,
0071 ATOMIC_ORDER_RELAXED
0072 );
0073 }
0074
0075 uint32_t SetTimecountCounter( uint32_t counter )
0076 {
0077 return (uint32_t) _Atomic_Exchange_ulong(
0078 &TimecounterInstance.counter,
0079 counter,
0080 ATOMIC_ORDER_RELAXED
0081 );
0082 }
0083
0084 static uint32_t GetTimecountSoftware( void )
0085 {
0086 return (uint32_t) _Atomic_Fetch_add_ulong(
0087 &TimecounterInstance.counter,
0088 1,
0089 ATOMIC_ORDER_RELAXED
0090 );
0091 }
0092
0093 static uint32_t GetTimecountWrapper( struct timecounter *tc )
0094 {
0095 TimecounterControl *self;
0096
0097 self = (TimecounterControl *) tc;
0098 return ( *self->handler )();
0099 }
0100
0101 static void InstallTimecounter( void )
0102 {
0103 TimecounterControl *self;
0104
0105 self = &TimecounterInstance;
0106 self->handler = GetTimecountSoftware;
0107 self->base.tc_get_timecount = GetTimecountWrapper;
0108 self->base.tc_counter_mask = 0xffffffff;
0109 self->base.tc_frequency = SOFTWARE_TIMECOUNTER_FREQUENCY;
0110 self->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER + 1;
0111 rtems_timecounter_install( &self->base );
0112 }
0113
0114 RTEMS_SYSINIT_ITEM(
0115 InstallTimecounter,
0116 RTEMS_SYSINIT_DEVICE_DRIVERS,
0117 RTEMS_SYSINIT_ORDER_LAST
0118 );
0119
0120 static void DoTimecounterTick( void *arg )
0121 {
0122 (void) arg;
0123 _Timecounter_Tick();
0124 }
0125
0126 void TimecounterTick( void )
0127 {
0128 unsigned long counter_ticks_per_clock_tick;
0129 Per_CPU_Control *cpu_self;
0130 bool success;
0131
0132 counter_ticks_per_clock_tick =
0133 SOFTWARE_TIMECOUNTER_FREQUENCY / rtems_clock_get_ticks_per_second();
0134 cpu_self = _Thread_Dispatch_disable();
0135
0136 do {
0137 unsigned long old_counter;
0138 unsigned long new_counter;
0139
0140 old_counter = _Atomic_Load_ulong(
0141 &TimecounterInstance.counter,
0142 ATOMIC_ORDER_RELAXED
0143 );
0144 new_counter = old_counter + counter_ticks_per_clock_tick -
0145 ( old_counter % counter_ticks_per_clock_tick );
0146 success = _Atomic_Compare_exchange_ulong(
0147 &TimecounterInstance.counter,
0148 &old_counter,
0149 new_counter,
0150 ATOMIC_ORDER_RELAXED,
0151 ATOMIC_ORDER_RELAXED
0152 );
0153 } while ( !success );
0154
0155 DoTimecounterTick( NULL );
0156 #if defined( RTEMS_SMP )
0157 _SMP_Othercast_action( DoTimecounterTick, NULL );
0158 #endif
0159 _Thread_Dispatch_enable( cpu_self );
0160 }