Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

kernel/systime.c

Go to the documentation of this file.
00001 
00006 /*
00007  *  The contents of this file are subject to the Mozilla Public License
00008  *  Version 1.0 (the "License"); you may not use this file except in
00009  *  compliance with the License. You may obtain a copy of the License at
00010  *  http://www.mozilla.org/MPL/
00011  *
00012  *  Software distributed under the License is distributed on an "AS IS"
00013  *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
00014  *  License for the specific language governing rights and limitations
00015  *  under the License.
00016  *
00017  *  The Original Code is legOS code, released October 17, 1999.
00018  *
00019  *  The Initial Developer of the Original Code is Markus L. Noga.
00020  *  Portions created by Markus L. Noga are Copyright (C) 1999
00021  *  Markus L. Noga. All Rights Reserved.
00022  *
00023  *  Contributor(s): Markus L. Noga <markus@noga.de>
00024  *                  David Van Wagner <davevw@alumni.cse.ucsc.edu>
00025  */
00026 
00027 /*
00028  *  2000.05.01 - Paolo Masetti <paolo.masetti@itlug.org>
00029  *
00030  * - Added battery indicator handler
00031  *
00032  *  2000.08.12 - Rossz Vámos-Wentworth <rossw@jps.net>
00033  *
00034  * - Added idle shutdown handler
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 // Global Variables
00056 //
00058 
00060 
00063 volatile time_t sys_time;
00064 
00066 //
00067 // Internal Variables
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 // Functions
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 // CONF_DSOUND
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 // CONF_LNP
00157 
00158 #ifdef CONF_DKEY
00159         "\n\
00160                 jsr _dkey_handler\n\
00161         "
00162 #endif // CONF_DKEY
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 // CONF_BATTERY_INDICATOR
00178 #endif // CONF_TM
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 // CONF_AUTOSHUTOFF
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 // CONF_VIS
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 // CONF_LCD_REFRESH
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 // CONF_TM
00250 
00251 #ifdef CONF_DMOTOR
00252         "\n\
00253                 jsr _dm_handler                 ; call motor driver\n\
00254         "
00255 #endif // CONF_DMOTOR
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();                           // shutdown hardware
00272 
00273   sys_time=0l;                                  // init timer
00274 
00275 #ifdef CONF_TM
00276   tm_current_slice=tm_timeslice=TM_DEFAULT_SLICE;
00277   tm_switcher_vector=&rom_dummy_handler;        // empty handler
00278 #endif
00279 
00280 #ifdef CONF_DMOTOR
00281   dm_shutdown();
00282 #endif
00283 
00284   // configure 16-bit timer
00285   // compare B IRQ will fire after one msec
00286   // compare A IRQ will fire after another msec
00287   // counter is then reset
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;   // trigger every msec 
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);  // unhook compare A/B IRQs
00319   WDT_CSR &= ~WDT_CSR_ENABLE;                     // disable wd timer
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) {                    // some minimum value
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

brickOS is released under the Mozilla Public License.
Original code copyright 1998-2002 by the authors.

Generated on Mon Feb 16 21:02:10 2004 for brickOS Kernel Developer by doxygen 1.3.5