00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <config.h>
00039
00040 #ifdef CONF_TIME
00041
00042 #include <sys/time.h>
00043 #include <sys/h8.h>
00044 #include <sys/irq.h>
00045 #include <sys/dmotor.h>
00046 #include <sys/dsound.h>
00047 #include <sys/battery.h>
00048 #include <sys/critsec.h>
00049 #ifdef CONF_AUTOSHUTOFF
00050 #include <sys/timeout.h>
00051 #endif
00052
00054
00055
00056
00058
00060
00063 volatile time_t sys_time;
00064
00066
00067
00068
00070
00071 #ifdef CONF_TM
00072 volatile unsigned char tm_timeslice;
00073 volatile unsigned char tm_current_slice;
00074
00075 void* tm_switcher_vector;
00076 #endif
00077
00078
00080
00081
00082
00084
00086
00088 extern void clock_handler(void);
00089 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00090 __asm__("\n\
00091 .text\n\
00092 .align 1\n\
00093 .global _clock_handler\n\
00094 _clock_handler:\n\
00095 mov.w #0x5a07,r6 ; reset wd timer to 6\n\
00096 mov.w r6,@0xffa8\n\
00097 \n\
00098 mov.w @_sys_time+2,r6 ; lower 8 bits\n\
00099 add.b #0x1,r6l ; inc lower 4 bits\n\
00100 addx #0x0,r6h ; add carry to top 4 bits\n\
00101 mov.w r6,@_sys_time+2\n\
00102 bcc sys_nohigh ; if carry, inc upper 8 bits\n\
00103 mov.w @_sys_time,r6 ; \n\
00104 add.b #0x1,r6l ; inc lower 4 bits\n\
00105 addx #0x0,r6h ; add carry to top 4 bits\n\
00106 mov.w r6,@_sys_time\n\
00107 sys_nohigh: \n\
00108 rts\n\
00109 ");
00110 #endif // DOXYGEN_SHOULD_SKIP_THIS
00111
00113
00117 extern void subsystem_handler(void);
00118
00120
00122 extern void task_switch_handler(void);
00123 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00124 __asm__("\n\
00125 .text\n\
00126 .align 1\n\
00127 .global _subsystem_handler\n\
00128 .global _task_switch_handler\n\
00129 .global _systime_tm_return\n\
00130 _subsystem_handler:\n\
00131 ; r6 saved by ROM\n\
00132 \n\
00133 push r0 ; both motors & task\n\
00134 ; switcher need this reg.\n\
00135 "
00136
00137 #ifdef CONF_DSOUND
00138 "\n\
00139 jsr _dsound_handler ; call sound handler\n\
00140 "
00141 #endif
00142
00143 #ifdef CONF_LNP
00144 "\n\
00145 mov.w @_lnp_timeout_counter,r6 ; check LNP timeout counter\n\
00146 subs #0x1,r6\n\
00147 mov.w r6,r6 ; subs doesn't change flags!\n\
00148 bne sys_noreset\n\
00149 \n\
00150 jsr _lnp_integrity_reset\n\
00151 mov.w @_lnp_timeout,r6 ; reset timeout\n\
00152 \n\
00153 sys_noreset:\n\
00154 mov.w r6,@_lnp_timeout_counter\n\
00155 "
00156 #endif
00157
00158 #ifdef CONF_DKEY
00159 "\n\
00160 jsr _dkey_handler\n\
00161 "
00162 #endif
00163
00164 #ifndef CONF_TM
00165 #ifdef CONF_BATTERY_INDICATOR
00166 "\n\
00167 mov.w @_battery_refresh_counter,r6\n\
00168 subs #0x1,r6\n\
00169 bne batt_norefresh\n\
00170 \n\
00171 jsr _battery_refresh\n\
00172 mov.w @_battery_refresh_period,r6\n\
00173 \n\
00174 batt_norefresh:\n\
00175 mov.w r6,@_battery_refresh_counter\n\
00176 "
00177 #endif
00178 #endif
00179
00180 #ifdef CONF_AUTOSHUTOFF
00181 "\n\
00182 mov.w @_auto_shutoff_counter,r6\n\
00183 subs #0x1,r6\n\
00184 bne auto_notshutoff\n\
00185 \n\
00186 jsr _autoshutoff_check\n\
00187 mov.w @_auto_shutoff_period,r6\n\
00188 \n\
00189 auto_notshutoff:\n\
00190 mov.w r6,@_auto_shutoff_counter\n\
00191 "
00192 #endif
00193
00194 #ifdef CONF_VIS
00195 "\n\
00196 mov.b @_vis_refresh_counter,r6l\n\
00197 dec r6l\n\
00198 bne vis_norefresh\n\
00199 \n\
00200 jsr _vis_handler\n\
00201 mov.b @_vis_refresh_period,r6l\n\
00202 \n\
00203 vis_norefresh:\n\
00204 mov.b r6l,@_vis_refresh_counter\n\
00205 "
00206 #endif
00207
00208 #ifdef CONF_LCD_REFRESH
00209 "\n\
00210 mov.b @_lcd_refresh_counter,r6l\n\
00211 dec r6l\n\
00212 bne lcd_norefresh\n\
00213 \n\
00214 jsr _lcd_refresh_next_byte\n\
00215 mov.b @_lcd_refresh_period,r6l\n\
00216 \n\
00217 lcd_norefresh:\n\
00218 mov.b r6l,@_lcd_refresh_counter\n\
00219 "
00220 #endif
00221 "\n\
00222 bclr #2,@0x91:8 ; reset compare B IRQ flag\n\
00223 "
00224 #ifdef CONF_TM
00225 "\n\
00226 pop r0 ; if fallthrough, pop r0\n\
00227 _task_switch_handler:\n\
00228 push r0 ; save r0\n\
00229 \n\
00230 mov.b @_tm_current_slice,r6l\n\
00231 dec r6l\n\
00232 bne sys_noswitch ; timeslice elapsed?\n\
00233 \n\
00234 mov.w @_kernel_critsec_count,r6 ; check critical section\n\
00235 beq sys_switch ; ok to switch\n\
00236 mov.b #1,r6l ; wait another tick\n\
00237 jmp sys_noswitch ; don't switch\n\
00238 \n\
00239 sys_switch:\n\
00240 mov.w @_tm_switcher_vector,r6\n\
00241 jsr @r6 ; call task switcher\n\
00242 \n\
00243 _systime_tm_return:\n\
00244 mov.b @_tm_timeslice,r6l ; new timeslice\n\
00245 \n\
00246 sys_noswitch:\n\
00247 mov.b r6l,@_tm_current_slice\n\
00248 "
00249 #endif
00250
00251 #ifdef CONF_DMOTOR
00252 "\n\
00253 jsr _dm_handler ; call motor driver\n\
00254 "
00255 #endif
00256
00257 "\n\
00258 pop r0\n\
00259 bclr #3,@0x91:8 ; reset compare A IRQ flag\n\
00260 rts\n\
00261 "
00262 );
00263 #endif // DOXYGEN_SHOULD_SKIP_THIS
00264
00265
00267
00270 void systime_init(void) {
00271 systime_shutdown();
00272
00273 sys_time=0l;
00274
00275 #ifdef CONF_TM
00276 tm_current_slice=tm_timeslice=TM_DEFAULT_SLICE;
00277 tm_switcher_vector=&rom_dummy_handler;
00278 #endif
00279
00280 #ifdef CONF_DMOTOR
00281 dm_shutdown();
00282 #endif
00283
00284
00285
00286
00287
00288
00289 T_CSR = TCSR_RESET_ON_A;
00290 T_CR = TCR_CLOCK_32;
00291 T_OCR &= ~TOCR_OCRB;
00292 T_OCRA = 1000;
00293 T_OCR &= ~TOCR_OCRA;
00294 T_OCR |= TOCR_OCRB;
00295 T_OCRB = 500;
00296
00297 #if defined(CONF_TM)
00298 ocia_vector = &task_switch_handler;
00299 #else // CONF_TM
00300 ocia_vector = &subsystem_handler;
00301 #endif // CONF_TM
00302 ocib_vector = &subsystem_handler;
00303 T_IER |= (TIER_ENABLE_OCB | TIER_ENABLE_OCA);
00304
00305 nmi_vector = &clock_handler;
00306 WDT_CSR = WDT_CNT_PASSWORD | WDT_CNT_MSEC_64;
00307 WDT_CSR = WDT_CSR_PASSWORD
00308 | WDT_CSR_CLOCK_64
00309 | WDT_CSR_WATCHDOG_NMI
00310 | WDT_CSR_ENABLE
00311 | WDT_CSR_MODE_WATCHDOG;
00312 }
00313
00315
00317 void systime_shutdown(void) {
00318 T_IER &= ~(TIER_ENABLE_OCA | TIER_ENABLE_OCB);
00319 WDT_CSR &= ~WDT_CSR_ENABLE;
00320 }
00321
00322 #ifdef CONF_TM
00323
00324
00326 void systime_set_switcher(void* switcher) {
00327 tm_switcher_vector=switcher;
00328 }
00329
00331
00333 void systime_set_timeslice(unsigned char slice) {
00334 if(slice>5) {
00335 tm_timeslice=slice;
00336 if(tm_current_slice>tm_timeslice)
00337 tm_current_slice=tm_timeslice;
00338 }
00339 }
00340
00341 #endif
00342
00344
00351 extern time_t get_system_up_time(void);
00352 __asm__("\n\
00353 .text\n\
00354 .align 1\n\
00355 .global _get_system_up_time\n\
00356 _get_system_up_time:\n\
00357 push r2\n\
00358 try_again:\n\
00359 mov.w @_sys_time+2, r1\n\
00360 mov.w @_sys_time, r0\n\
00361 mov.w @_sys_time+2, r2\n\
00362 cmp r2, r1\n\
00363 bne try_again\n\
00364 pop r2\n\
00365 rts\n\
00366 ");
00367
00368 #endif // CONF_TIME