File indexing completed on 2025-05-11 08:24:22
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 #ifdef HAVE_CONFIG_H
0041 #include "config.h"
0042 #endif
0043
0044 #include <rtems/rtems/timerimpl.h>
0045 #include <rtems/rtems/clockimpl.h>
0046 #include <rtems/rtems/status.h>
0047 #include <rtems/rtems/support.h>
0048 #include <rtems/score/assert.h>
0049 #include <rtems/score/chainimpl.h>
0050 #include <rtems/score/thread.h>
0051 #include <rtems/score/todimpl.h>
0052 #include <rtems/score/watchdogimpl.h>
0053 #include <rtems/sysinit.h>
0054
0055 RTEMS_STATIC_ASSERT(
0056 PER_CPU_WATCHDOG_REALTIME == TIMER_CLASS_BIT_TIME_OF_DAY,
0057 TIMER_CLASS_BIT_TIME_OF_DAY
0058 );
0059
0060 Timer_server_Control *volatile _Timer_server;
0061
0062 void _Timer_Routine_adaptor( Watchdog_Control *the_watchdog )
0063 {
0064 Timer_Control *the_timer;
0065 Per_CPU_Control *cpu;
0066
0067 the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker );
0068 cpu = _Watchdog_Get_CPU( &the_timer->Ticker );
0069 the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
0070
0071 ( *the_timer->routine )( the_timer->Object.id, the_timer->user_data );
0072 }
0073
0074 rtems_status_code _Timer_Fire(
0075 rtems_id id,
0076 rtems_interval interval,
0077 rtems_timer_service_routine_entry routine,
0078 void *user_data,
0079 Timer_Classes the_class,
0080 Watchdog_Service_routine_entry adaptor
0081 )
0082 {
0083 Timer_Control *the_timer;
0084 ISR_lock_Context lock_context;
0085
0086 the_timer = _Timer_Get( id, &lock_context );
0087 if ( the_timer != NULL ) {
0088 Per_CPU_Control *cpu;
0089
0090 cpu = _Timer_Acquire_critical( the_timer, &lock_context );
0091 _Timer_Cancel( cpu, the_timer );
0092 _Watchdog_Initialize( &the_timer->Ticker, adaptor );
0093 the_timer->the_class = the_class;
0094 the_timer->routine = routine;
0095 the_timer->user_data = user_data;
0096 the_timer->initial = interval;
0097 the_timer->start_time = _Timer_Get_CPU_ticks( cpu );
0098
0099 if ( _Timer_Is_interval_class( the_class ) ) {
0100 _Watchdog_Insert(
0101 &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ],
0102 &the_timer->Ticker,
0103 cpu->Watchdog.ticks + interval
0104 );
0105 } else {
0106 _Watchdog_Insert(
0107 &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ],
0108 &the_timer->Ticker,
0109 _Watchdog_Ticks_from_seconds( interval )
0110 );
0111 }
0112
0113 _Timer_Release( cpu, &lock_context );
0114 return RTEMS_SUCCESSFUL;
0115 }
0116
0117 return RTEMS_INVALID_ID;
0118 }
0119
0120 rtems_status_code _Timer_Fire_after(
0121 rtems_id id,
0122 rtems_interval ticks,
0123 rtems_timer_service_routine_entry routine,
0124 void *user_data,
0125 Timer_Classes the_class,
0126 Watchdog_Service_routine_entry adaptor
0127 )
0128 {
0129 if ( ticks == 0 )
0130 return RTEMS_INVALID_NUMBER;
0131
0132 if ( !routine )
0133 return RTEMS_INVALID_ADDRESS;
0134
0135 return _Timer_Fire(
0136 id,
0137 ticks,
0138 routine,
0139 user_data,
0140 the_class,
0141 adaptor
0142 );
0143 }
0144
0145 rtems_status_code _Timer_Fire_when(
0146 rtems_id id,
0147 const rtems_time_of_day *wall_time,
0148 rtems_timer_service_routine_entry routine,
0149 void *user_data,
0150 Timer_Classes the_class,
0151 Watchdog_Service_routine_entry adaptor
0152 )
0153 {
0154 rtems_status_code status;
0155 rtems_interval seconds;
0156
0157 if ( !_TOD_Is_set() )
0158 return RTEMS_NOT_DEFINED;
0159
0160 if ( !routine )
0161 return RTEMS_INVALID_ADDRESS;
0162
0163 status = _TOD_Validate( wall_time, TOD_ENABLE_TICKS_VALIDATION );
0164
0165 if ( status != RTEMS_SUCCESSFUL ) {
0166 return status;
0167 }
0168
0169 seconds = _TOD_To_seconds( wall_time );
0170 if ( seconds <= _TOD_Seconds_since_epoch() )
0171 return RTEMS_INVALID_CLOCK;
0172
0173 return _Timer_Fire(
0174 id,
0175 seconds,
0176 routine,
0177 user_data,
0178 the_class,
0179 adaptor
0180 );
0181 }
0182
0183 void _Timer_Cancel( Per_CPU_Control *cpu, Timer_Control *the_timer )
0184 {
0185 Timer_Classes the_class;
0186
0187 the_class = the_timer->the_class;
0188
0189 if ( _Watchdog_Is_scheduled( &the_timer->Ticker ) ) {
0190 the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
0191 _Watchdog_Remove(
0192 &cpu->Watchdog.Header[ _Timer_Watchdog_header_index( the_class ) ],
0193 &the_timer->Ticker
0194 );
0195 } else if ( _Timer_Is_on_task_class( the_class ) ) {
0196 Timer_server_Control *timer_server;
0197 ISR_lock_Context lock_context;
0198
0199 timer_server = _Timer_server;
0200 _Assert( timer_server != NULL );
0201 _Timer_server_Acquire_critical( timer_server, &lock_context );
0202
0203 if ( _Watchdog_Get_state( &the_timer->Ticker ) == WATCHDOG_PENDING ) {
0204 _Watchdog_Set_state( &the_timer->Ticker, WATCHDOG_INACTIVE );
0205 _Chain_Extract_unprotected( &the_timer->Ticker.Node.Chain );
0206 }
0207
0208 _Timer_server_Release_critical( timer_server, &lock_context );
0209 }
0210 }
0211
0212 rtems_status_code rtems_timer_create(
0213 rtems_name name,
0214 rtems_id *id
0215 )
0216 {
0217 Timer_Control *the_timer;
0218
0219 if ( !rtems_is_name_valid( name ) )
0220 return RTEMS_INVALID_NAME;
0221
0222 if ( !id )
0223 return RTEMS_INVALID_ADDRESS;
0224
0225 the_timer = _Timer_Allocate();
0226
0227 if ( !the_timer ) {
0228 _Objects_Allocator_unlock();
0229 return RTEMS_TOO_MANY;
0230 }
0231
0232 the_timer->the_class = TIMER_DORMANT;
0233 _Watchdog_Preinitialize( &the_timer->Ticker, _Per_CPU_Get_snapshot() );
0234
0235 *id = _Objects_Open_u32(
0236 &_Timer_Information,
0237 &the_timer->Object,
0238 name
0239 );
0240 _Objects_Allocator_unlock();
0241 return RTEMS_SUCCESSFUL;
0242 }
0243
0244 static void _Timer_Manager_initialization( void )
0245 {
0246 _Objects_Initialize_information( &_Timer_Information );
0247 }
0248
0249 RTEMS_SYSINIT_ITEM(
0250 _Timer_Manager_initialization,
0251 RTEMS_SYSINIT_CLASSIC_TIMER,
0252 RTEMS_SYSINIT_ORDER_MIDDLE
0253 );