[ac7d5ef0] | 1 | /* |
---|
| 2 | * Time of Day (TOD) Handler |
---|
| 3 | * |
---|
| 4 | * |
---|
| 5 | * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. |
---|
| 6 | * On-Line Applications Research Corporation (OAR). |
---|
| 7 | * All rights assigned to U.S. Government, 1994. |
---|
| 8 | * |
---|
| 9 | * This material may be reproduced by or for the U.S. Government pursuant |
---|
| 10 | * to the copyright license under the clause at DFARS 252.227-7013. This |
---|
| 11 | * notice must appear in all copies of this file and its derivatives. |
---|
| 12 | * |
---|
| 13 | * $Id$ |
---|
| 14 | */ |
---|
| 15 | |
---|
| 16 | #include <rtems/system.h> |
---|
[5e9b32b] | 17 | #include <rtems/score/object.h> |
---|
| 18 | #include <rtems/score/thread.h> |
---|
| 19 | #include <rtems/score/tod.h> |
---|
| 20 | #include <rtems/score/watchdog.h> |
---|
[ac7d5ef0] | 21 | |
---|
| 22 | /*PAGE |
---|
| 23 | * |
---|
| 24 | * _TOD_Handler_initialization |
---|
| 25 | * |
---|
| 26 | * This routine initializes the time of day handler. |
---|
| 27 | * |
---|
| 28 | * Input parameters: |
---|
| 29 | * microseconds_per_tick - microseconds between clock ticks |
---|
| 30 | * |
---|
| 31 | * Output parameters: NONE |
---|
| 32 | */ |
---|
| 33 | |
---|
| 34 | void _TOD_Handler_initialization( |
---|
| 35 | unsigned32 microseconds_per_tick |
---|
| 36 | ) |
---|
| 37 | { |
---|
| 38 | _TOD_Microseconds_per_tick = microseconds_per_tick; |
---|
| 39 | |
---|
| 40 | _TOD_Seconds_since_epoch = 0; |
---|
| 41 | |
---|
| 42 | _TOD_Current.year = TOD_BASE_YEAR; |
---|
| 43 | _TOD_Current.month = 1; |
---|
| 44 | _TOD_Current.day = 1; |
---|
| 45 | _TOD_Current.hour = 0; |
---|
| 46 | _TOD_Current.minute = 0; |
---|
| 47 | _TOD_Current.second = 0; |
---|
| 48 | _TOD_Current.ticks = 0; |
---|
| 49 | |
---|
| 50 | if ( microseconds_per_tick == 0 ) |
---|
| 51 | _TOD_Ticks_per_second = 0; |
---|
| 52 | else |
---|
| 53 | _TOD_Ticks_per_second = |
---|
| 54 | TOD_MICROSECONDS_PER_SECOND / microseconds_per_tick; |
---|
| 55 | |
---|
| 56 | _Watchdog_Initialize( &_TOD_Seconds_watchdog, _TOD_Tickle, 0, NULL ); |
---|
[7fea679b] | 57 | |
---|
| 58 | _TOD_Is_set = FALSE; |
---|
| 59 | _TOD_Activate( _TOD_Ticks_per_second ); |
---|
[ac7d5ef0] | 60 | } |
---|
| 61 | |
---|
| 62 | /*PAGE |
---|
| 63 | * |
---|
| 64 | * _TOD_Set |
---|
| 65 | * |
---|
| 66 | * This rountine sets the current date and time with the specified |
---|
| 67 | * new date and time structure. |
---|
| 68 | * |
---|
| 69 | * Input parameters: |
---|
| 70 | * the_tod - pointer to the time and date structure |
---|
| 71 | * seconds_since_epoch - seconds since system epoch |
---|
| 72 | * |
---|
| 73 | * Output parameters: NONE |
---|
| 74 | */ |
---|
| 75 | |
---|
| 76 | void _TOD_Set( |
---|
[3a4ae6c] | 77 | TOD_Control *the_tod, |
---|
| 78 | Watchdog_Interval seconds_since_epoch |
---|
[ac7d5ef0] | 79 | ) |
---|
| 80 | { |
---|
[3a4ae6c] | 81 | Watchdog_Interval ticks_until_next_second; |
---|
[ac7d5ef0] | 82 | |
---|
| 83 | _Thread_Disable_dispatch(); |
---|
| 84 | _TOD_Deactivate(); |
---|
| 85 | |
---|
| 86 | if ( seconds_since_epoch < _TOD_Seconds_since_epoch ) |
---|
| 87 | _Watchdog_Adjust_seconds( WATCHDOG_BACKWARD, |
---|
| 88 | _TOD_Seconds_since_epoch - seconds_since_epoch ); |
---|
| 89 | else |
---|
| 90 | _Watchdog_Adjust_seconds( WATCHDOG_FORWARD, |
---|
| 91 | seconds_since_epoch - _TOD_Seconds_since_epoch ); |
---|
| 92 | |
---|
| 93 | ticks_until_next_second = _TOD_Ticks_per_second; |
---|
| 94 | if ( ticks_until_next_second > _TOD_Current.ticks ) |
---|
| 95 | ticks_until_next_second -= _TOD_Current.ticks; |
---|
| 96 | |
---|
| 97 | _TOD_Current = *the_tod; |
---|
| 98 | _TOD_Seconds_since_epoch = seconds_since_epoch; |
---|
[7fea679b] | 99 | _TOD_Is_set = TRUE; |
---|
[ac7d5ef0] | 100 | _TOD_Activate( ticks_until_next_second ); |
---|
| 101 | |
---|
| 102 | _Thread_Enable_dispatch(); |
---|
| 103 | } |
---|
| 104 | |
---|
| 105 | /*PAGE |
---|
| 106 | * |
---|
| 107 | * _TOD_Validate |
---|
| 108 | * |
---|
| 109 | * This kernel routine checks the validity of a date and time structure. |
---|
| 110 | * |
---|
| 111 | * Input parameters: |
---|
| 112 | * the_tod - pointer to a time and date structure |
---|
| 113 | * |
---|
| 114 | * Output parameters: |
---|
[3a4ae6c] | 115 | * TRUE - if the date, time, and tick are valid |
---|
| 116 | * FALSE - if the the_tod is invalid |
---|
[ac7d5ef0] | 117 | * |
---|
| 118 | * NOTE: This routine only works for leap-years through 2099. |
---|
| 119 | */ |
---|
| 120 | |
---|
[3a4ae6c] | 121 | boolean _TOD_Validate( |
---|
| 122 | TOD_Control *the_tod |
---|
[ac7d5ef0] | 123 | ) |
---|
| 124 | { |
---|
| 125 | unsigned32 days_in_month; |
---|
| 126 | |
---|
| 127 | if ((the_tod->ticks >= _TOD_Ticks_per_second) || |
---|
| 128 | (the_tod->second >= TOD_SECONDS_PER_MINUTE) || |
---|
| 129 | (the_tod->minute >= TOD_MINUTES_PER_HOUR) || |
---|
| 130 | (the_tod->hour >= TOD_HOURS_PER_DAY) || |
---|
| 131 | (the_tod->month == 0) || |
---|
| 132 | (the_tod->month > TOD_MONTHS_PER_YEAR) || |
---|
| 133 | (the_tod->year < TOD_BASE_YEAR) || |
---|
| 134 | (the_tod->day == 0) ) |
---|
[3a4ae6c] | 135 | return FALSE; |
---|
[ac7d5ef0] | 136 | |
---|
| 137 | if ( (the_tod->year % 4) == 0 ) |
---|
| 138 | days_in_month = _TOD_Days_per_month[ 1 ][ the_tod->month ]; |
---|
| 139 | else |
---|
| 140 | days_in_month = _TOD_Days_per_month[ 0 ][ the_tod->month ]; |
---|
| 141 | |
---|
| 142 | if ( the_tod->day > days_in_month ) |
---|
[3a4ae6c] | 143 | return FALSE; |
---|
[ac7d5ef0] | 144 | |
---|
[3a4ae6c] | 145 | return TRUE; |
---|
[ac7d5ef0] | 146 | } |
---|
| 147 | |
---|
| 148 | /*PAGE |
---|
| 149 | * |
---|
| 150 | * _TOD_To_seconds |
---|
| 151 | * |
---|
| 152 | * This routine returns the seconds from the epoch until the |
---|
| 153 | * current date and time. |
---|
| 154 | * |
---|
| 155 | * Input parameters: |
---|
| 156 | * the_tod - pointer to the time and date structure |
---|
| 157 | * |
---|
| 158 | * Output parameters: |
---|
| 159 | * returns - seconds since epoch until the_tod |
---|
| 160 | */ |
---|
| 161 | |
---|
| 162 | unsigned32 _TOD_To_seconds( |
---|
[3a4ae6c] | 163 | TOD_Control *the_tod |
---|
[ac7d5ef0] | 164 | ) |
---|
| 165 | { |
---|
| 166 | unsigned32 time; |
---|
| 167 | unsigned32 year_mod_4; |
---|
| 168 | |
---|
| 169 | time = the_tod->day - 1; |
---|
| 170 | year_mod_4 = the_tod->year & 3; |
---|
| 171 | |
---|
| 172 | if ( year_mod_4 == 0 ) |
---|
| 173 | time += _TOD_Days_to_date[ 1 ][ the_tod->month ]; |
---|
| 174 | else |
---|
| 175 | time += _TOD_Days_to_date[ 0 ][ the_tod->month ]; |
---|
| 176 | |
---|
| 177 | time += ( (the_tod->year - TOD_BASE_YEAR) / 4 ) * |
---|
| 178 | ( (TOD_DAYS_PER_YEAR * 4) + 1); |
---|
| 179 | |
---|
| 180 | time += _TOD_Days_since_last_leap_year[ year_mod_4 ]; |
---|
| 181 | |
---|
| 182 | time *= TOD_SECONDS_PER_DAY; |
---|
| 183 | |
---|
| 184 | time += ((the_tod->hour * TOD_MINUTES_PER_HOUR) + the_tod->minute) |
---|
| 185 | * TOD_SECONDS_PER_MINUTE; |
---|
| 186 | |
---|
| 187 | time += the_tod->second; |
---|
| 188 | |
---|
| 189 | return( time ); |
---|
| 190 | } |
---|
| 191 | |
---|
| 192 | /*PAGE |
---|
| 193 | * |
---|
| 194 | * _TOD_Tickle |
---|
| 195 | * |
---|
| 196 | * This routine updates the calendar time and tickles the |
---|
| 197 | * per second watchdog timer chain. |
---|
| 198 | * |
---|
| 199 | * Input parameters: |
---|
| 200 | * ignored - this parameter is ignored |
---|
| 201 | * |
---|
| 202 | * Output parameters: NONE |
---|
| 203 | * |
---|
| 204 | * NOTE: This routine only works for leap-years through 2099. |
---|
| 205 | */ |
---|
| 206 | |
---|
| 207 | void _TOD_Tickle( |
---|
| 208 | Objects_Id id, |
---|
| 209 | void *ignored |
---|
| 210 | ) |
---|
| 211 | { |
---|
| 212 | unsigned32 leap; |
---|
| 213 | |
---|
| 214 | _TOD_Current.ticks = 0; |
---|
| 215 | ++_TOD_Seconds_since_epoch; |
---|
| 216 | if ( ++_TOD_Current.second >= TOD_SECONDS_PER_MINUTE ) { |
---|
| 217 | _TOD_Current.second = 0; |
---|
| 218 | if ( ++_TOD_Current.minute >= TOD_MINUTES_PER_HOUR ) { |
---|
| 219 | _TOD_Current.minute = 0; |
---|
| 220 | if ( ++_TOD_Current.hour >= TOD_HOURS_PER_DAY ) { |
---|
| 221 | _TOD_Current.hour = 0; |
---|
| 222 | if ( _TOD_Current.year & 0x3 ) leap = 0; |
---|
| 223 | else leap = 1; |
---|
| 224 | if ( ++_TOD_Current.day > |
---|
| 225 | _TOD_Days_per_month[ leap ][ _TOD_Current.month ]) { |
---|
| 226 | _TOD_Current.day = 1; |
---|
| 227 | if ( ++_TOD_Current.month > TOD_MONTHS_PER_YEAR ) { |
---|
| 228 | _TOD_Current.month = 1; |
---|
| 229 | _TOD_Current.year++; |
---|
| 230 | } |
---|
| 231 | } |
---|
| 232 | } |
---|
| 233 | } |
---|
| 234 | } |
---|
| 235 | |
---|
| 236 | _Watchdog_Tickle_seconds(); |
---|
[8d0b7d96] | 237 | _Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, _TOD_Ticks_per_second ); |
---|
[ac7d5ef0] | 238 | } |
---|